Index: tools/convbdf.c =================================================================== --- tools/convbdf.c (revision 22403) +++ tools/convbdf.c (working copy) @@ -1389,6 +1389,7 @@ " %d, /* ascent */\n" " %d, /* firstchar */\n" " %d, /* size */\n" + " 0, /* depth */\n" " _font_bits, /* bits */\n" " %s /* offset */\n" " %s\n" Index: firmware/export/font.h =================================================================== --- firmware/export/font.h (revision 22403) +++ firmware/export/font.h (working copy) @@ -79,7 +79,7 @@ * USHORT maxwidth 2 font max width in pixels * USHORT height 2 font height in pixels * USHORT ascent 2 font ascent (baseline) in pixels - * USHORT pad 2 unused, pad to 32-bit boundary + * USHORT depth 2 depth of the font, 0=1-bit and 1=4-bit * ULONG firstchar 4 first character code in font * ULONG defaultchar 4 default character code in font * ULONG size 4 # characters in font @@ -103,6 +103,7 @@ int ascent; /* ascent (baseline) height*/ int firstchar; /* first character in bitmap*/ int size; /* font size in glyphs*/ + int depth; /* depth of the font, 0=1-bit and 1=4-bit */ const unsigned char *bits; /* 8-bit column bitmap data*/ const unsigned short *offset; /* offsets into bitmap data*/ const unsigned char *width; /* character widths or NULL if fixed*/ Index: firmware/font.c =================================================================== --- firmware/font.c (revision 22403) +++ firmware/font.c (working copy) @@ -68,7 +68,7 @@ static int fnt_file = -1; /* >=0 if font is cached */ static uint32_t file_width_offset; /* offset to file width data */ static uint32_t file_offset_offset; /* offset to file offset data */ -static void cache_create(int maxwidth, int height); +static void cache_create(int maxwidth, int height, int depth); static int long_offset = 0; static int glyph_file; /* End Font cache structures */ @@ -139,7 +139,7 @@ pf->maxwidth = readshort(); pf->height = readshort(); pf->ascent = readshort(); - fileptr += 2; /* Skip padding */ + pf->depth = readshort(); pf->firstchar = readlong(); pf->defaultchar = readlong(); pf->size = readlong(); @@ -279,7 +279,7 @@ fileptr = oldfileptr; /* Create the cache */ - cache_create(pf->maxwidth, pf->height); + cache_create(pf->maxwidth, pf->height, pf->depth); return pf; } @@ -418,23 +418,23 @@ } else { - bitmap_offset = ((pf->height + 7) / 8) * p->width * char_code; + bitmap_offset = ((pf->height + 7) / 8) * p->width * char_code * (1 << pf->depth); } int32_t file_offset = FONT_HEADER_SIZE + bitmap_offset; lseek(fnt_file, file_offset, SEEK_SET); - int src_bytes = p->width * ((pf->height + 7) / 8); + int src_bytes = p->width * ((pf->height + 7) / 8) * (1 << pf->depth); read(fnt_file, p->bitmap, src_bytes); } /* * Converts cbuf into a font cache */ -static void cache_create(int maxwidth, int height) +static void cache_create(int maxwidth, int height, int depth) { /* maximum size of rotated bitmap */ - int bitmap_size = maxwidth * ((height + 7) / 8); + int bitmap_size = maxwidth * ((height + 7) / 8) * (1 << depth); /* Initialise cache */ font_cache_create(&font_cache_ui, mbuf, MAX_FONT_SIZE, bitmap_size); Index: firmware/drivers/lcd-bitmap-common.c =================================================================== --- firmware/drivers/lcd-bitmap-common.c (revision 22403) +++ firmware/drivers/lcd-bitmap-common.c (working copy) @@ -102,8 +102,14 @@ bits = font_get_bits(pf, ch); - LCDFN(mono_bitmap_part)(bits, ofs, 0, width, x, y, width - ofs, - pf->height); +#if defined(MAIN_LCD) && defined(HAVE_LCD_COLOR) + if (pf->depth) + lcd_alpha_bitmap_part(bits, ofs, 0, width, x, y, width - ofs, + pf->height); + else +#endif + LCDFN(mono_bitmap_part)(bits, ofs, 0, width, x, y, width - ofs, + pf->height); x += width - ofs; ofs = 0; Index: firmware/drivers/lcd-16bit.c =================================================================== --- firmware/drivers/lcd-16bit.c (revision 22403) +++ firmware/drivers/lcd-16bit.c (working copy) @@ -804,6 +804,224 @@ lcd_mono_bitmap_part(src, 0, 0, width, x, y, width, height); } +/* draw alpha bitmap for anti-alias font */ +#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) +#define ALPHA_COLOR_PIXEL_PER_BYTE (8 >> ALPHA_COLOR_FONT_DEPTH) +static unsigned int alpha_color_lookup[ALPHA_COLOR_LOOKUP_SIZE] = { 0xffffffff }; + +/* Blend the given two colors */ +static fb_data blend_two_colors(fb_data c1, fb_data c2, unsigned char a) +{ + /* no computation on full opaque/transparent */ + if ( a == ALPHA_COLOR_LOOKUP_SIZE ) return c1; + if ( a == 0 ) return c2; +#if (LCD_PIXELFORMAT == RGB565SWAPPED) + c1 = swap16(c1); + c2 = swap16(c2); +#endif + unsigned int p1 = ((c1|(c1<<16)) & 0x07e0f81f) * (a); + unsigned int p2 = ((c2|(c2<<16)) & 0x07e0f81f) * (ALPHA_COLOR_LOOKUP_SIZE+1-a); + p1 = ((p1 + p2) >> ALPHA_COLOR_LOOKUP_SHIFT) & 0x07e0f81f; +#if (LCD_PIXELFORMAT == RGB565SWAPPED) + return swap16((fb_data)(p1 | ( p1 >> 16 ))); +#else + return (fb_data)(p1 | ( p1 >> 16 )); +#endif +} + +/* Blend the given color with the value from the alpha_color_lookup table */ +static fb_data blend_color(fb_data c, unsigned char a) +{ + /* no computation on full opaque/transparent */ + if ( a == ALPHA_COLOR_LOOKUP_SIZE ) return c; + if ( a == 0 ) return current_vp->fg_pattern; +#if (LCD_PIXELFORMAT == RGB565SWAPPED) + c = swap16(c); +#endif + unsigned int p = ((c|(c<<16)) & 0x07e0f81f) * (a); + p = ((p + alpha_color_lookup[a]) >> ALPHA_COLOR_LOOKUP_SHIFT) & 0x07e0f81f; +#if (LCD_PIXELFORMAT == RGB565SWAPPED) + return swap16((fb_data)(p | ( p >> 16 ))); +#else + return (fb_data)(p | ( p >> 16 )); +#endif +} + +/* Update the alpha_color_lookup table */ +static void update_alpha_color_lookup(fb_data c) +{ + int i; + alpha_color_lookup[0] = c; + alpha_color_lookup[ALPHA_COLOR_LOOKUP_SIZE-1] = 0; +#if (LCD_PIXELFORMAT == RGB565SWAPPED) + c = swap16(c); +#endif + for(i = 1; i< ALPHA_COLOR_LOOKUP_SIZE-1; i++) + { + alpha_color_lookup[i] = ((c|(c<<16)) & 0x07e0f81f) * + (ALPHA_COLOR_LOOKUP_SIZE+1-i); + } +} + +void ICODE_ATTR lcd_alpha_bitmap_part(const unsigned char *src, int src_x, + int src_y, int stride, int x, int y, + int width, int height) +{ + fb_data *dst, *backdrop; + unsigned dmask = 0x00000000; + int drmode = current_vp->drawmode; + + /* nothing to draw? */ + if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || + (y >= current_vp->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 > current_vp->width) + width = current_vp->width - x; + if (y + height > current_vp->height) + height = current_vp->height - y; + + if (drmode & DRMODE_INVERSEVID) + { + dmask = 0xffffffff; + drmode &= DRMODE_SOLID; /* mask out inversevid */ + } + if (drmode == DRMODE_BG) + { + dmask = ~dmask; + } + + if((drmode & DRMODE_FG) && current_vp->fg_pattern != alpha_color_lookup[0]) + update_alpha_color_lookup(current_vp->fg_pattern); + + dst = LCDADDR(current_vp->x + x, current_vp->y + y); + + const char skip_start = src_y * stride + src_x; + const char skip_end = (stride - width); + int col, row = height; + unsigned char data, numbits = ALPHA_COLOR_PIXEL_PER_BYTE; + + numbits -= skip_start % ALPHA_COLOR_PIXEL_PER_BYTE; + src += skip_start / ALPHA_COLOR_PIXEL_PER_BYTE; + data = *src ^ dmask; + data >>= (ALPHA_COLOR_PIXEL_PER_BYTE - numbits) * ALPHA_COLOR_LOOKUP_SHIFT; + + do + { + col = width; +#define UPDATE_SRC_ALPHA do { \ + if (--numbits == 0) \ + { \ + data = *(++src) ^ dmask; \ + numbits = ALPHA_COLOR_PIXEL_PER_BYTE; \ + } \ + else \ + data >>= ALPHA_COLOR_LOOKUP_SHIFT; \ + } while (0) + + /* we don't want to have this in our inner + * loop and the codesize increase is minimal */ + switch (drmode) + { + case DRMODE_COMPLEMENT: + do + { + *dst=blend_two_colors(*dst, ~(*dst), + data & ALPHA_COLOR_LOOKUP_SIZE ); + dst++; + UPDATE_SRC_ALPHA; + } + while (--col); + break; + case DRMODE_BG: + if(lcd_backdrop) + { + backdrop = (fb_data *)((long)dst+lcd_backdrop_offset); + do + { + *dst=blend_two_colors(*dst, *(backdrop++), + data & ALPHA_COLOR_LOOKUP_SIZE ); + dst++; + UPDATE_SRC_ALPHA; + } + while (--col); + } + else + { + do + { + *dst=blend_two_colors(*dst, current_vp->bg_pattern, + data & ALPHA_COLOR_LOOKUP_SIZE ); + dst++; + UPDATE_SRC_ALPHA; + } + while (--col); + } + break; + case DRMODE_FG: + do + { + *dst=blend_color(*dst, data & ALPHA_COLOR_LOOKUP_SIZE ); + dst++; + UPDATE_SRC_ALPHA; + } + while (--col); + break; + case DRMODE_SOLID: + if(lcd_backdrop) + { + backdrop = (fb_data *)((long)dst+lcd_backdrop_offset); + do + { + *(dst++)=blend_color(*(backdrop++), + data & ALPHA_COLOR_LOOKUP_SIZE ); + UPDATE_SRC_ALPHA; + } + while (--col); + } + else + { + do + { + *(dst++)=blend_color(current_vp->bg_pattern, + data & ALPHA_COLOR_LOOKUP_SIZE ); + UPDATE_SRC_ALPHA; + } + while (--col); + } + break; + } + if ( skip_end ) + { + numbits -= skip_end % ALPHA_COLOR_PIXEL_PER_BYTE; + if ( numbits <= 0 ) + { + src++; + numbits += ALPHA_COLOR_PIXEL_PER_BYTE; + } + src += skip_end / ALPHA_COLOR_PIXEL_PER_BYTE; + data = *src ^ dmask; + data >>= ALPHA_COLOR_LOOKUP_SHIFT * (ALPHA_COLOR_PIXEL_PER_BYTE - numbits); + } + dst += LCD_WIDTH - width; + } while (--row); +} + /* Draw a partial native bitmap */ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, int stride, int x, int y, int width,