forked from len0rd/rockbox
Document the internal alpha channel format better, and fixes for 32bit alpha bitmaps.
For images, rows need to be even (this is not true for anti-aliased font files). Fix stride and size calculation. This makes images that have odd pixel rows display properly and fixes buffer overflows. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30966 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
158e14a8c6
commit
312b2a2de7
3 changed files with 33 additions and 13 deletions
|
|
@ -438,7 +438,7 @@ void output_row_8_native(uint32_t row, void * row_in,
|
||||||
if (ctx->bm->alpha_offset > 0)
|
if (ctx->bm->alpha_offset > 0)
|
||||||
bm_alpha = ctx->bm->data + ctx->bm->alpha_offset;
|
bm_alpha = ctx->bm->data + ctx->bm->alpha_offset;
|
||||||
if (bm_alpha)
|
if (bm_alpha)
|
||||||
bm_alpha += ctx->bm->width*row/2;
|
bm_alpha += ALIGN_UP(ctx->bm->width, 2) * row/2;
|
||||||
|
|
||||||
for (col = 0; col < ctx->bm->width; col++) {
|
for (col = 0; col < ctx->bm->width; col++) {
|
||||||
if (ctx->dither)
|
if (ctx->dither)
|
||||||
|
|
@ -453,7 +453,7 @@ void output_row_8_native(uint32_t row, void * row_in,
|
||||||
dest += STRIDE_MAIN(1, ctx->bm->height);
|
dest += STRIDE_MAIN(1, ctx->bm->height);
|
||||||
if (bm_alpha) {
|
if (bm_alpha) {
|
||||||
/* pack alpha channel for 2 pixels into 1 byte */
|
/* pack alpha channel for 2 pixels into 1 byte */
|
||||||
unsigned alpha = 255-qp->alpha;
|
unsigned alpha = qp->alpha;
|
||||||
if (col%2)
|
if (col%2)
|
||||||
*bm_alpha++ |= alpha&0xf0;
|
*bm_alpha++ |= alpha&0xf0;
|
||||||
else
|
else
|
||||||
|
|
@ -612,6 +612,8 @@ int read_bmp_fd(int fd,
|
||||||
rset.rowstop = -1;
|
rset.rowstop = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* need even rows (see lcd-16bit-common.c for details) */
|
||||||
|
int alphasize = ALIGN_UP(bm->width, 2) * bm->height / 2;
|
||||||
if (cformat)
|
if (cformat)
|
||||||
totalsize = cformat->get_size(bm);
|
totalsize = cformat->get_size(bm);
|
||||||
else {
|
else {
|
||||||
|
|
@ -620,7 +622,7 @@ int read_bmp_fd(int fd,
|
||||||
if (!remote)
|
if (!remote)
|
||||||
#endif
|
#endif
|
||||||
if (depth == 32 && read_alpha) /* account for possible 4bit alpha per pixel */
|
if (depth == 32 && read_alpha) /* account for possible 4bit alpha per pixel */
|
||||||
totalsize += bm->width * bm->height / 2;
|
totalsize += alphasize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(return_size)
|
if(return_size)
|
||||||
|
|
@ -718,7 +720,7 @@ int read_bmp_fd(int fd,
|
||||||
|
|
||||||
#ifdef HAVE_LCD_COLOR
|
#ifdef HAVE_LCD_COLOR
|
||||||
if (read_alpha && depth == 32)
|
if (read_alpha && depth == 32)
|
||||||
bm->alpha_offset = totalsize - (bm->width * bm->height / 2);
|
bm->alpha_offset = totalsize - alphasize;
|
||||||
else
|
else
|
||||||
bm->alpha_offset = 0;
|
bm->alpha_offset = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -882,7 +884,7 @@ int read_bmp_fd(int fd,
|
||||||
{ /* if this has an alpha channel, totalsize accounts for it as well
|
{ /* if this has an alpha channel, totalsize accounts for it as well
|
||||||
* subtract if no actual alpha information was found */
|
* subtract if no actual alpha information was found */
|
||||||
if (bm->alpha_offset > 0)
|
if (bm->alpha_offset > 0)
|
||||||
totalsize -= bm->width*bm->height/2;
|
totalsize -= alphasize;
|
||||||
bm->alpha_offset = 0;
|
bm->alpha_offset = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -775,7 +775,7 @@ static void output_row_32_native(uint32_t row, void * row_in,
|
||||||
if (ctx->bm->alpha_offset > 0)
|
if (ctx->bm->alpha_offset > 0)
|
||||||
bm_alpha = ctx->bm->data + ctx->bm->alpha_offset;
|
bm_alpha = ctx->bm->data + ctx->bm->alpha_offset;
|
||||||
if (bm_alpha)
|
if (bm_alpha)
|
||||||
bm_alpha += ctx->bm->width*row/2;
|
bm_alpha += ALIGN_UP(ctx->bm->width, 2)*row/2;
|
||||||
|
|
||||||
for (col = 0; col < ctx->bm->width; col++) {
|
for (col = 0; col < ctx->bm->width; col++) {
|
||||||
if (ctx->dither)
|
if (ctx->dither)
|
||||||
|
|
@ -791,7 +791,7 @@ static void output_row_32_native(uint32_t row, void * row_in,
|
||||||
dest += STRIDE_MAIN(1, ctx->bm->height);
|
dest += STRIDE_MAIN(1, ctx->bm->height);
|
||||||
if (bm_alpha) {
|
if (bm_alpha) {
|
||||||
/* pack alpha channel for 2 pixels into 1 byte */
|
/* pack alpha channel for 2 pixels into 1 byte */
|
||||||
unsigned alpha = 255-SC_OUT(q0.a, ctx);
|
unsigned alpha = SC_OUT(q0.a, ctx);
|
||||||
if (col%2)
|
if (col%2)
|
||||||
*bm_alpha++ |= alpha&0xf0;
|
*bm_alpha++ |= alpha&0xf0;
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -229,6 +229,25 @@ void lcd_mono_bitmap(const unsigned char *src, int x, int y, int width, int heig
|
||||||
lcd_mono_bitmap_part(src, 0, 0, width, x, y, width, height);
|
lcd_mono_bitmap_part(src, 0, 0, width, x, y, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* About Rockbox' internal alpha channel format (for ALPHA_COLOR_FONT_DEPTH == 2)
|
||||||
|
*
|
||||||
|
* For each pixel, 4bit of alpha information is stored in a byte-stream,
|
||||||
|
* so two pixels are packed into one byte.
|
||||||
|
* The lower nibble is the first pixel, the upper one the second. The stride is
|
||||||
|
* horizontal. E.g row0: pixel0: byte0[0:3], pixel1: byte0[4:7], pixel2: byte1[0:3],...
|
||||||
|
* The format is independant of the internal display orientation, as to
|
||||||
|
* support the same font files on
|
||||||
|
* The values go linear from 0 (fully transparent) to 15 (fully opaque).
|
||||||
|
*
|
||||||
|
* This might suggest that rows need to have an even number of pixels.
|
||||||
|
* However this is generally not the case. lcd_alpha_bitmap_part_mix() can deal
|
||||||
|
* with uneven colums (i.e. two rows can share one byte). And font files do
|
||||||
|
* exploit this.
|
||||||
|
* However, this is difficult to do for image files, especially bottom-up bitmaps,
|
||||||
|
* so lcd_bmp() do expect even rows.
|
||||||
|
*/
|
||||||
|
|
||||||
#define ALPHA_COLOR_FONT_DEPTH 2
|
#define ALPHA_COLOR_FONT_DEPTH 2
|
||||||
#define ALPHA_COLOR_LOOKUP_SHIFT (1 << ALPHA_COLOR_FONT_DEPTH)
|
#define ALPHA_COLOR_LOOKUP_SHIFT (1 << ALPHA_COLOR_FONT_DEPTH)
|
||||||
#define ALPHA_COLOR_LOOKUP_SIZE ((1 << ALPHA_COLOR_LOOKUP_SHIFT) - 1)
|
#define ALPHA_COLOR_LOOKUP_SIZE ((1 << ALPHA_COLOR_LOOKUP_SHIFT) - 1)
|
||||||
|
|
@ -357,17 +376,16 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image,
|
||||||
dmask = 0xffffffff;
|
dmask = 0xffffffff;
|
||||||
drmode &= DRMODE_SOLID; /* mask out inversevid */
|
drmode &= DRMODE_SOLID; /* mask out inversevid */
|
||||||
}
|
}
|
||||||
if (drmode == DRMODE_BG)
|
|
||||||
{
|
|
||||||
dmask = ~dmask;
|
|
||||||
}
|
|
||||||
/* sourcing from an image ignore drawmode.
|
/* sourcing from an image ignore drawmode.
|
||||||
* Set to DRMODE_BG as we use its code path in the switch below */
|
* Set to DRMODE_BG as we use its code path in the switch below */
|
||||||
if (image != NULL)
|
if (image != NULL)
|
||||||
{
|
{
|
||||||
dmask = 0;
|
|
||||||
drmode = DRMODE_BG;
|
drmode = DRMODE_BG;
|
||||||
}
|
}
|
||||||
|
if (drmode == DRMODE_BG)
|
||||||
|
{
|
||||||
|
dmask = ~dmask;
|
||||||
|
}
|
||||||
|
|
||||||
dst_row = LCDADDR(x, y);
|
dst_row = LCDADDR(x, y);
|
||||||
|
|
||||||
|
|
@ -560,7 +578,7 @@ void ICODE_ATTR lcd_bmp_part(const struct bitmap* bm, int src_x, int src_y,
|
||||||
else if (bm->alpha_offset > 0)
|
else if (bm->alpha_offset > 0)
|
||||||
lcd_alpha_bitmap_part_mix((fb_data*)bm->data, bm->data+bm->alpha_offset,
|
lcd_alpha_bitmap_part_mix((fb_data*)bm->data, bm->data+bm->alpha_offset,
|
||||||
src_x, src_y, x, y, width, height,
|
src_x, src_y, x, y, width, height,
|
||||||
bitmap_stride, bm->width);
|
bitmap_stride, ALIGN_UP(bm->width, 2));
|
||||||
else
|
else
|
||||||
lcd_bitmap_transparent_part((fb_data*)bm->data,
|
lcd_bitmap_transparent_part((fb_data*)bm->data,
|
||||||
src_x, src_y, bitmap_stride, x, y, width, height);
|
src_x, src_y, bitmap_stride, x, y, width, height);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue