forked from len0rd/rockbox
Player graphics library extended and converted to new api. Please note that the player gfx bitmap format chas changed.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6956 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
05c3cc2978
commit
93867305d5
5 changed files with 370 additions and 127 deletions
|
@ -24,21 +24,20 @@
|
|||
#ifdef HAVE_LCD_CHARCELLS /* Player only :) */
|
||||
#include "playergfx.h"
|
||||
|
||||
/* Global variables */
|
||||
/*** globals ***/
|
||||
|
||||
static struct plugin_api *pgfx_rb = NULL; /* global api struct pointer */
|
||||
static int char_width;
|
||||
static int char_height;
|
||||
static unsigned pixel_height;
|
||||
static unsigned pixel_width;
|
||||
static int pixel_height;
|
||||
static int pixel_width;
|
||||
static unsigned char gfx_chars[8];
|
||||
static unsigned char gfx_buffer[56];
|
||||
static int drawmode = DRMODE_SOLID;
|
||||
|
||||
/* Private function declarations */
|
||||
static void linefunc(int x1, int y1, int x2, int y2,
|
||||
void (*pixelfunc)(int x, int y));
|
||||
|
||||
/* Implementation */
|
||||
/*** Special functions ***/
|
||||
|
||||
/* library init */
|
||||
bool pgfx_init(struct plugin_api* newrb, int cwidth, int cheight)
|
||||
{
|
||||
int i;
|
||||
|
@ -64,6 +63,7 @@ bool pgfx_init(struct plugin_api* newrb, int cwidth, int cheight)
|
|||
return true;
|
||||
}
|
||||
|
||||
/* library deinit */
|
||||
void pgfx_release(void)
|
||||
{
|
||||
int i;
|
||||
|
@ -73,6 +73,7 @@ void pgfx_release(void)
|
|||
pgfx_rb->lcd_unlock_pattern(gfx_chars[i]);
|
||||
}
|
||||
|
||||
/* place the display */
|
||||
void pgfx_display(int cx, int cy)
|
||||
{
|
||||
int i, j;
|
||||
|
@ -84,6 +85,8 @@ void pgfx_display(int cx, int cy)
|
|||
pgfx_rb->lcd_putc(cx + i, cy + j, gfx_chars[char_height * i + j]);
|
||||
}
|
||||
|
||||
/*** Update functions ***/
|
||||
|
||||
void pgfx_update(void)
|
||||
{
|
||||
int i;
|
||||
|
@ -92,28 +95,111 @@ void pgfx_update(void)
|
|||
pgfx_rb->lcd_define_pattern(gfx_chars[i], gfx_buffer + 7 * i);
|
||||
}
|
||||
|
||||
void pgfx_clear_display(void)
|
||||
/*** Parameter handling ***/
|
||||
|
||||
void pgfx_set_drawmode(int mode)
|
||||
{
|
||||
pgfx_rb->memset(gfx_buffer, 0, char_width * pixel_height);
|
||||
drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID);
|
||||
}
|
||||
|
||||
void pgfx_drawpixel(int x, int y)
|
||||
int pgfx_get_drawmode(void)
|
||||
{
|
||||
return drawmode;
|
||||
}
|
||||
|
||||
/*** Low-level drawing functions ***/
|
||||
|
||||
static void setpixel(int x, int y)
|
||||
{
|
||||
gfx_buffer[pixel_height * (x/5) + y] |= 0x10 >> (x%5);
|
||||
}
|
||||
|
||||
void pgfx_clearpixel(int x, int y)
|
||||
static void clearpixel(int x, int y)
|
||||
{
|
||||
gfx_buffer[pixel_height * (x/5) + y] &= ~(0x10 >> (x%5));
|
||||
}
|
||||
|
||||
void pgfx_invertpixel(int x, int y)
|
||||
static void flippixel(int x, int y)
|
||||
{
|
||||
gfx_buffer[pixel_height * (x/5) + y] ^= 0x10 >> (x%5);
|
||||
}
|
||||
|
||||
static void linefunc(int x1, int y1, int x2, int y2,
|
||||
void (*pixelfunc)(int x, int y))
|
||||
static void nopixel(int x, int y)
|
||||
{
|
||||
(void)x;
|
||||
(void)y;
|
||||
}
|
||||
|
||||
lcd_pixelfunc_type* pgfx_pixelfuncs[8] = {
|
||||
flippixel, nopixel, setpixel, setpixel,
|
||||
nopixel, clearpixel, nopixel, clearpixel
|
||||
};
|
||||
|
||||
static void flipblock(unsigned char *address, unsigned mask, unsigned bits)
|
||||
{
|
||||
*address ^= (bits & mask);
|
||||
}
|
||||
|
||||
static void bgblock(unsigned char *address, unsigned mask, unsigned bits)
|
||||
{
|
||||
*address &= (bits | ~mask);
|
||||
}
|
||||
|
||||
static void fgblock(unsigned char *address, unsigned mask, unsigned bits)
|
||||
{
|
||||
*address |= (bits & mask);
|
||||
}
|
||||
|
||||
static void solidblock(unsigned char *address, unsigned mask, unsigned bits)
|
||||
{
|
||||
*address = (*address & ~mask) | (bits & mask);
|
||||
}
|
||||
|
||||
static void flipinvblock(unsigned char *address, unsigned mask, unsigned bits)
|
||||
{
|
||||
*address ^= (~bits & mask);
|
||||
}
|
||||
|
||||
static void bginvblock(unsigned char *address, unsigned mask, unsigned bits)
|
||||
{
|
||||
*address &= ~(bits & mask);
|
||||
}
|
||||
|
||||
static void fginvblock(unsigned char *address, unsigned mask, unsigned bits)
|
||||
{
|
||||
*address |= (~bits & mask);
|
||||
}
|
||||
|
||||
static void solidinvblock(unsigned char *address, unsigned mask, unsigned bits)
|
||||
{
|
||||
*address = (*address & ~mask) | (~bits & mask);
|
||||
}
|
||||
|
||||
lcd_blockfunc_type* pgfx_blockfuncs[8] = {
|
||||
flipblock, bgblock, fgblock, solidblock,
|
||||
flipinvblock, bginvblock, fginvblock, solidinvblock
|
||||
};
|
||||
|
||||
/*** Drawing functions ***/
|
||||
|
||||
/* Clear the whole display */
|
||||
void pgfx_clear_display(void)
|
||||
{
|
||||
unsigned bits = (drawmode & DRMODE_INVERSEVID) ? 0x1F : 0;
|
||||
|
||||
pgfx_rb->memset(gfx_buffer, bits, char_width * pixel_height);
|
||||
}
|
||||
|
||||
/* Set a single pixel */
|
||||
void pgfx_drawpixel(int x, int y)
|
||||
{
|
||||
if (((unsigned)x < (unsigned)pixel_width)
|
||||
&& ((unsigned)y < (unsigned)pixel_height))
|
||||
pgfx_pixelfuncs[drawmode](x, y);
|
||||
}
|
||||
|
||||
/* Draw a line */
|
||||
void pgfx_drawline(int x1, int y1, int x2, int y2)
|
||||
{
|
||||
int numpixels;
|
||||
int i;
|
||||
|
@ -121,6 +207,7 @@ static void linefunc(int x1, int y1, int x2, int y2,
|
|||
int d, dinc1, dinc2;
|
||||
int x, xinc1, xinc2;
|
||||
int y, yinc1, yinc2;
|
||||
lcd_pixelfunc_type *pfunc = pgfx_pixelfuncs[drawmode];
|
||||
|
||||
deltax = abs(x2 - x1);
|
||||
deltay = abs(y2 - y1);
|
||||
|
@ -147,13 +234,13 @@ static void linefunc(int x1, int y1, int x2, int y2,
|
|||
}
|
||||
numpixels++; /* include endpoints */
|
||||
|
||||
if(x1 > x2)
|
||||
if (x1 > x2)
|
||||
{
|
||||
xinc1 = -xinc1;
|
||||
xinc2 = -xinc2;
|
||||
}
|
||||
|
||||
if(y1 > y2)
|
||||
if (y1 > y2)
|
||||
{
|
||||
yinc1 = -yinc1;
|
||||
yinc2 = -yinc2;
|
||||
|
@ -164,7 +251,9 @@ static void linefunc(int x1, int y1, int x2, int y2,
|
|||
|
||||
for (i = 0; i < numpixels; i++)
|
||||
{
|
||||
pixelfunc(x, y);
|
||||
if (((unsigned)x < (unsigned)pixel_width)
|
||||
&& ((unsigned)y < (unsigned)pixel_height))
|
||||
pfunc(x, y);
|
||||
|
||||
if (d < 0)
|
||||
{
|
||||
|
@ -181,69 +270,237 @@ static void linefunc(int x1, int y1, int x2, int y2,
|
|||
}
|
||||
}
|
||||
|
||||
void pgfx_drawline(int x1, int y1, int x2, int y2)
|
||||
/* Draw a horizontal line (optimised) */
|
||||
void pgfx_hline(int x1, int x2, int y)
|
||||
{
|
||||
linefunc(x1, y1, x2, y2, pgfx_drawpixel);
|
||||
}
|
||||
int nx;
|
||||
unsigned char *dst;
|
||||
unsigned mask, mask_right;
|
||||
lcd_blockfunc_type *bfunc;
|
||||
|
||||
void pgfx_clearline(int x1, int y1, int x2, int y2)
|
||||
{
|
||||
linefunc(x1, y1, x2, y2, pgfx_clearpixel);
|
||||
}
|
||||
|
||||
void pgfx_invertline(int x1, int y1, int x2, int y2)
|
||||
{
|
||||
linefunc(x1, y1, x2, y2, pgfx_invertpixel);
|
||||
}
|
||||
|
||||
void pgfx_invertrect (int x, int y, int nx, int ny)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (((unsigned) x >= pixel_width) || ((unsigned) y >= pixel_height))
|
||||
return;
|
||||
|
||||
if ((unsigned)(x + nx) > pixel_width)
|
||||
nx = pixel_width - x;
|
||||
if ((unsigned)(y + ny) > pixel_height)
|
||||
ny = pixel_height - y;
|
||||
|
||||
for (i = 0; i < nx; i++)
|
||||
for (j = 0; j < ny; j++)
|
||||
pgfx_invertpixel(x + i, y + j);
|
||||
}
|
||||
|
||||
void pgfx_bitmap (const unsigned char *src, int x, int y, int nx, int ny,
|
||||
bool clear)
|
||||
{
|
||||
int stride, i, j;
|
||||
unsigned data;
|
||||
|
||||
if (((unsigned) x >= pixel_width) || ((unsigned) y >= pixel_height))
|
||||
return;
|
||||
|
||||
stride = nx; /* otherwise right-clipping will destroy the image */
|
||||
|
||||
if (((unsigned)(x + nx)) >= pixel_width)
|
||||
nx = pixel_width - x;
|
||||
if (((unsigned)(y + ny)) >= pixel_height)
|
||||
ny = pixel_height - y;
|
||||
|
||||
for (i = 0; i < nx; i++, src++)
|
||||
/* direction flip */
|
||||
if (x2 < x1)
|
||||
{
|
||||
data = src[0];
|
||||
if (ny > 8) /* ny is max. 14 */
|
||||
data |= src[stride] << 8;
|
||||
for (j = 0; j < ny; j++)
|
||||
nx = x1;
|
||||
x1 = x2;
|
||||
x2 = nx;
|
||||
}
|
||||
|
||||
/* nothing to draw? */
|
||||
if (((unsigned)y >= (unsigned)pixel_height) || (x1 >= pixel_width)
|
||||
|| (x2 < 0))
|
||||
return;
|
||||
|
||||
/* clipping */
|
||||
if (x1 < 0)
|
||||
x1 = 0;
|
||||
if (x2 >= pixel_width)
|
||||
x2 = pixel_width - 1;
|
||||
|
||||
bfunc = pgfx_blockfuncs[drawmode];
|
||||
dst = &gfx_buffer[pixel_height * (x1/5) + y];
|
||||
nx = x2 - (x1 - (x1 % 5));
|
||||
mask = 0x1F >> (x1 % 5);
|
||||
mask_right = 0x1F0 >> (nx % 5);
|
||||
|
||||
for (; nx >= 5; nx -= 5)
|
||||
{
|
||||
bfunc(dst, mask, 0xFFu);
|
||||
dst += pixel_height;
|
||||
mask = 0x1F;
|
||||
}
|
||||
mask &= mask_right;
|
||||
bfunc(dst, mask, 0x1F);
|
||||
}
|
||||
|
||||
/* Draw a vertical line (optimised) */
|
||||
void pgfx_vline(int x, int y1, int y2)
|
||||
{
|
||||
int y;
|
||||
unsigned char *dst;
|
||||
unsigned mask;
|
||||
lcd_blockfunc_type *bfunc;
|
||||
|
||||
/* direction flip */
|
||||
if (y2 < y1)
|
||||
{
|
||||
y = y1;
|
||||
y1 = y2;
|
||||
y2 = y;
|
||||
}
|
||||
|
||||
/* nothing to draw? */
|
||||
if (((unsigned)x >= (unsigned)pixel_width) || (y1 >= pixel_height)
|
||||
|| (y2 < 0))
|
||||
return;
|
||||
|
||||
/* clipping */
|
||||
if (y1 < 0)
|
||||
y1 = 0;
|
||||
if (y2 >= pixel_height)
|
||||
y2 = pixel_height - 1;
|
||||
|
||||
bfunc = pgfx_blockfuncs[drawmode];
|
||||
dst = &gfx_buffer[pixel_height * (x/5) + y1];
|
||||
mask = 0x10 >> (x % 5);
|
||||
|
||||
for (y = y1; y <= y2; y++)
|
||||
bfunc(dst++, mask, 0x1F);
|
||||
}
|
||||
|
||||
/* Draw a rectangular box */
|
||||
void pgfx_drawrect(int x, int y, int width, int height)
|
||||
{
|
||||
if ((width <= 0) || (height <= 0))
|
||||
return;
|
||||
|
||||
int x2 = x + width - 1;
|
||||
int y2 = y + height - 1;
|
||||
|
||||
pgfx_vline(x, y, y2);
|
||||
pgfx_vline(x2, y, y2);
|
||||
pgfx_hline(x, x2, y);
|
||||
pgfx_hline(x, x2, y2);
|
||||
}
|
||||
|
||||
/* Fill a rectangular area */
|
||||
void pgfx_fillrect(int x, int y, int width, int height)
|
||||
{
|
||||
int nx, i;
|
||||
unsigned char *dst;
|
||||
unsigned mask, mask_right;
|
||||
lcd_blockfunc_type *bfunc;
|
||||
|
||||
/* nothing to draw? */
|
||||
if ((width <= 0) || (height <= 0) || (x >= pixel_width)
|
||||
|| (y >= pixel_height) || (x + width <= 0) || (y + height <= 0))
|
||||
return;
|
||||
|
||||
/* clipping */
|
||||
if (x < 0)
|
||||
{
|
||||
width += x;
|
||||
x = 0;
|
||||
}
|
||||
if (y < 0)
|
||||
{
|
||||
height += y;
|
||||
y = 0;
|
||||
}
|
||||
if (x + width > pixel_width)
|
||||
width = pixel_width - x;
|
||||
if (y + height > pixel_height)
|
||||
height = pixel_height - y;
|
||||
|
||||
bfunc = pgfx_blockfuncs[drawmode];
|
||||
dst = &gfx_buffer[pixel_height * (x/5) + y];
|
||||
nx = width - 1 + (x % 5);
|
||||
mask = 0x1F >> (x % 5);
|
||||
mask_right = 0x1F0 >> (nx % 5);
|
||||
|
||||
for (; nx >= 5; nx -= 5)
|
||||
{
|
||||
unsigned char *dst_col = dst;
|
||||
|
||||
for (i = height; i > 0; i--)
|
||||
bfunc(dst_col++, mask, 0x1F);
|
||||
|
||||
dst += pixel_height;
|
||||
mask = 0x1F;
|
||||
}
|
||||
mask &= mask_right;
|
||||
|
||||
for (i = height; i > 0; i--)
|
||||
bfunc(dst++, mask, 0x1F);
|
||||
}
|
||||
|
||||
/* About PlayerGFX internal bitmap format:
|
||||
*
|
||||
* A bitmap contains one bit for every pixel that defines if that pixel is
|
||||
* black (1) or white (0). Bits within a byte are arranged horizontally,
|
||||
* MSB at the left.
|
||||
* The bytes are stored in row-major order, with byte 0 being top left,
|
||||
* byte 1 2nd from left etc. Each row of bytes defines one pixel row.
|
||||
*
|
||||
* This approximates the (even more strange) internal hardware format. */
|
||||
|
||||
/* Draw a partial bitmap. Note that stride is given in bytes */
|
||||
void pgfx_bitmap_part(const unsigned char *src, int src_x, int src_y,
|
||||
int stride, int x, int y, int width, int height)
|
||||
{
|
||||
int nx, shift;
|
||||
unsigned char *dst;
|
||||
unsigned mask, mask_right;
|
||||
lcd_blockfunc_type *bfunc;
|
||||
|
||||
/* nothing to draw? */
|
||||
if ((width <= 0) || (height <= 0) || (x >= pixel_width)
|
||||
|| (y >= pixel_height) || (x + width <= 0) || (y + height <= 0))
|
||||
return;
|
||||
|
||||
/* clipping */
|
||||
if (x < 0)
|
||||
{
|
||||
width += x;
|
||||
src_x -= x;
|
||||
x = 0;
|
||||
}
|
||||
if (y < 0)
|
||||
{
|
||||
height += y;
|
||||
src_y -= y;
|
||||
y = 0;
|
||||
}
|
||||
if (x + width > pixel_width)
|
||||
width = pixel_width - x;
|
||||
if (y + height > pixel_height)
|
||||
height = pixel_height - y;
|
||||
|
||||
src += stride * src_y + (src_x >> 3); /* move starting point */
|
||||
dst = &gfx_buffer[pixel_height * (x/5) + y];
|
||||
shift = 3 + (x % 5) - (src_x & 7);
|
||||
nx = width - 1 + (x % 5);
|
||||
|
||||
bfunc = pgfx_blockfuncs[drawmode];
|
||||
mask = 0x1F >> (x % 5);
|
||||
mask_right = 0x1F0 >> (nx % 5);
|
||||
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
const unsigned char *src_row = src;
|
||||
unsigned char *dst_row = dst;
|
||||
unsigned mask_row = mask;
|
||||
unsigned data = *src_row++;
|
||||
int extrabits = shift;
|
||||
|
||||
for (x = nx; x >= 5; x -= 5)
|
||||
{
|
||||
if (data & 1)
|
||||
pgfx_drawpixel(x + i, y + j);
|
||||
else
|
||||
if (clear)
|
||||
pgfx_clearpixel(x + i, y + j);
|
||||
data >>= 1;
|
||||
if (extrabits < 0)
|
||||
{
|
||||
data = (data << 8) | *src_row++;
|
||||
extrabits += 8;
|
||||
}
|
||||
bfunc(dst_row, mask_row, data >> extrabits);
|
||||
extrabits -= 5;
|
||||
dst_row += pixel_height;
|
||||
mask_row = 0x1F;
|
||||
}
|
||||
if (extrabits < 0)
|
||||
{
|
||||
data = (data << 8) | *src_row;
|
||||
extrabits += 8;
|
||||
}
|
||||
bfunc(dst_row, mask_row & mask_right, data >> extrabits);
|
||||
|
||||
src += stride;
|
||||
dst++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Draw a full bitmap */
|
||||
void pgfx_bitmap(const unsigned char *src, int x, int y, int width, int height)
|
||||
{
|
||||
pgfx_bitmap_part(src, 0, 0, (width + 7) >> 3, x, y, width, height);
|
||||
}
|
||||
|
||||
#endif /* HAVE_LCD_CHARCELLS */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue