From 9edd6d4ee912273690b2600e8c52183dfa058eb9 Mon Sep 17 00:00:00 2001 From: Thomas Martitz Date: Sat, 5 Mar 2011 18:36:51 +0000 Subject: Anti-Aliased Fonts support. This enables Rockbox to render anti-aliased fonts using an alpha blending method. The input font bitmaps are 4bit, i.e. 4x larger, but the metadata size stays the same. A tool, convttf, for converting ttf fonts directly to the Rockbox fnt format is provided. It has a useful help output, but the parameter that works best is -c1 or -c2 (2 for larger font sizes). Flyspray: FS#8961 Author: Initial work by Jonas Hurrelmann, further work by Fred Bauer, Andrew Mahone, Teruaki Kawashima and myself. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29523 a1c6a512-1295-4272-9138-f99709370657 --- apps/plugins/mpegplayer/mpegplayer.c | 174 ++++++++++++++++++++++++++++++++++- 1 file changed, 172 insertions(+), 2 deletions(-) (limited to 'apps/plugins/mpegplayer/mpegplayer.c') diff --git a/apps/plugins/mpegplayer/mpegplayer.c b/apps/plugins/mpegplayer/mpegplayer.c index 2361ba0fbd..22136d8393 100644 --- a/apps/plugins/mpegplayer/mpegplayer.c +++ b/apps/plugins/mpegplayer/mpegplayer.c @@ -663,6 +663,172 @@ static void draw_oriented_mono_bitmap_part(const unsigned char *src, while (src < src_end); } +/* 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) +#define ALPHA_COLOR_PIXEL_PER_WORD (32 >> ALPHA_COLOR_FONT_DEPTH) +#ifdef CPU_ARM +#define BLEND_INIT do {} while (0) +#define BLEND_START(acc, color, alpha) \ + asm volatile("mul %0, %1, %2" : "=&r" (acc) : "r" (color), "r" (alpha)) +#define BLEND_CONT(acc, color, alpha) \ + asm volatile("mla %0, %1, %2, %0" : "+&r" (acc) : "r" (color), "r" (alpha)) +#define BLEND_OUT(acc) do {} while (0) +#elif defined(CPU_COLDFIRE) +#define ALPHA_BITMAP_READ_WORDS +#define BLEND_INIT coldfire_set_macsr(EMAC_UNSIGNED) +#define BLEND_START(acc, color, alpha) \ + asm volatile("mac.l %0, %1, %%acc0" :: "%d" (color), "d" (alpha)) +#define BLEND_CONT BLEND_START +#define BLEND_OUT(acc) asm volatile("movclr.l %%acc0, %0" : "=d" (acc)) +#else +#define BLEND_INIT do {} while (0) +#define BLEND_START(acc, color, alpha) ((acc) = (color) * (alpha)) +#define BLEND_CONT(acc, color, alpha) ((acc) += (color) * (alpha)) +#define BLEND_OUT(acc) do {} while (0) +#endif + +/* Blend the given two colors */ +static inline unsigned blend_two_colors(unsigned c1, unsigned c2, unsigned a) +{ + a += a >> (ALPHA_COLOR_LOOKUP_SHIFT - 1); +#if (LCD_PIXELFORMAT == RGB565SWAPPED) + c1 = swap16(c1); + c2 = swap16(c2); +#endif + unsigned c1l = (c1 | (c1 << 16)) & 0x07e0f81f; + unsigned c2l = (c2 | (c2 << 16)) & 0x07e0f81f; + unsigned p; + BLEND_START(p, c1l, a); + BLEND_CONT(p, c2l, ALPHA_COLOR_LOOKUP_SIZE + 1 - a); + BLEND_OUT(p); + p = (p >> ALPHA_COLOR_LOOKUP_SHIFT) & 0x07e0f81f; + p |= (p >> 16); +#if (LCD_PIXELFORMAT == RGB565SWAPPED) + return swap16(p); +#else + return p; +#endif +} + +static void draw_oriented_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, *dst_start; + unsigned fg_pattern, bg_pattern; + + if (x + width > SCREEN_WIDTH) + width = SCREEN_WIDTH - x; /* Clip right */ + if (x < 0) + width += x, x = 0; /* Clip left */ + if (width <= 0) + return; /* nothing left to do */ + + if (y + height > SCREEN_HEIGHT) + height = SCREEN_HEIGHT - y; /* Clip bottom */ + if (y < 0) + height += y, y = 0; /* Clip top */ + if (height <= 0) + return; /* nothing left to do */ + + /* initialize blending */ + BLEND_INIT; + + fg_pattern = rb->lcd_get_foreground(); + bg_pattern = rb->lcd_get_background(); + + dst_start = rb->lcd_framebuffer + (LCD_WIDTH - y - 1) + x*LCD_WIDTH; + int col, row = height; + unsigned data, pixels; + unsigned skip_end = (stride - width); + unsigned skip_start = src_y * stride + src_x; + +#ifdef ALPHA_BITMAP_READ_WORDS + uint32_t *src_w = (uint32_t *)((uintptr_t)src & ~3); + skip_start += ALPHA_COLOR_PIXEL_PER_BYTE * ((uintptr_t)src & 3); + src_w += skip_start / ALPHA_COLOR_PIXEL_PER_WORD; + data = letoh32(*src_w++); +#else + src += skip_start / ALPHA_COLOR_PIXEL_PER_BYTE; + data = *src; +#endif + pixels = skip_start % ALPHA_COLOR_PIXEL_PER_WORD; + data >>= pixels * ALPHA_COLOR_LOOKUP_SHIFT; +#ifdef ALPHA_BITMAP_READ_WORDS + pixels = 8 - pixels; +#endif + + do + { + col = width; + dst = dst_start--; +#ifdef ALPHA_BITMAP_READ_WORDS +#define UPDATE_SRC_ALPHA do { \ + if (--pixels) \ + data >>= ALPHA_COLOR_LOOKUP_SHIFT; \ + else \ + { \ + data = letoh32(*src_w++); \ + pixels = ALPHA_COLOR_PIXEL_PER_WORD; \ + } \ + } while (0) +#elif ALPHA_COLOR_PIXEL_PER_BYTE == 2 +#define UPDATE_SRC_ALPHA do { \ + if (pixels ^= 1) \ + data >>= ALPHA_COLOR_LOOKUP_SHIFT; \ + else \ + data = *(++src); \ + } while (0) +#else +#define UPDATE_SRC_ALPHA do { \ + if (pixels = (++pixels % ALPHA_COLOR_PIXEL_PER_BYTE)) \ + data >>= ALPHA_COLOR_LOOKUP_SHIFT; \ + else \ + data = *(++src); \ + } while (0) +#endif + do + { + *dst=blend_two_colors(*dst, fg_pattern, + data & ALPHA_COLOR_LOOKUP_SIZE ); + dst += LCD_WIDTH; + UPDATE_SRC_ALPHA; + } + while (--col); +#ifdef ALPHA_BITMAP_READ_WORDS + if (skip_end < pixels) + { + pixels -= skip_end; + data >>= skip_end * ALPHA_COLOR_LOOKUP_SHIFT; + } else { + pixels = skip_end - pixels; + src_w += pixels / ALPHA_COLOR_PIXEL_PER_WORD; + pixels %= ALPHA_COLOR_PIXEL_PER_WORD; + data = letoh32(*src_w++); + data >>= pixels * ALPHA_COLOR_LOOKUP_SHIFT; + pixels = 8 - pixels; + } +#else + if (skip_end) + { + pixels += skip_end; + if (pixels >= ALPHA_COLOR_PIXEL_PER_BYTE) + { + src += pixels / ALPHA_COLOR_PIXEL_PER_BYTE; + pixels %= ALPHA_COLOR_PIXEL_PER_BYTE; + data = *src; + data >>= pixels * ALPHA_COLOR_LOOKUP_SHIFT; + } else + data >>= skip_end * ALPHA_COLOR_LOOKUP_SHIFT; + } +#endif + } while (--row); +} + static void draw_putsxy_oriented(int x, int y, const char *str) { unsigned short ch; @@ -690,8 +856,12 @@ static void draw_putsxy_oriented(int x, int y, const char *str) bits = rb->font_get_bits(pf, ch); - draw_oriented_mono_bitmap_part(bits, ofs, 0, width, x, y, - width - ofs, pf->height); + if (pf->depth) + draw_oriented_alpha_bitmap_part(bits, ofs, 0, width, x, y, + width - ofs, pf->height); + else + draw_oriented_mono_bitmap_part(bits, ofs, 0, width, x, y, + width - ofs, pf->height); x += width - ofs; ofs = 0; -- cgit