From 312b2a2de7a35f8c4b0dc355b7b291085a9a5ea4 Mon Sep 17 00:00:00 2001 From: Thomas Martitz Date: Fri, 11 Nov 2011 19:05:11 +0000 Subject: 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 --- firmware/drivers/lcd-16bit-common.c | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) (limited to 'firmware') diff --git a/firmware/drivers/lcd-16bit-common.c b/firmware/drivers/lcd-16bit-common.c index 7b37bf7c30..47f5968228 100644 --- a/firmware/drivers/lcd-16bit-common.c +++ b/firmware/drivers/lcd-16bit-common.c @@ -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); } + +/* 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_LOOKUP_SHIFT (1 << ALPHA_COLOR_FONT_DEPTH) #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; drmode &= DRMODE_SOLID; /* mask out inversevid */ } - if (drmode == DRMODE_BG) - { - dmask = ~dmask; - } /* sourcing from an image ignore drawmode. * Set to DRMODE_BG as we use its code path in the switch below */ if (image != NULL) { - dmask = 0; drmode = DRMODE_BG; } + if (drmode == DRMODE_BG) + { + dmask = ~dmask; + } 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) lcd_alpha_bitmap_part_mix((fb_data*)bm->data, bm->data+bm->alpha_offset, src_x, src_y, x, y, width, height, - bitmap_stride, bm->width); + bitmap_stride, ALIGN_UP(bm->width, 2)); else lcd_bitmap_transparent_part((fb_data*)bm->data, src_x, src_y, bitmap_stride, x, y, width, height); -- cgit v1.2.3