summaryrefslogtreecommitdiffstats
path: root/apps/plugins/mpegplayer/mpegplayer.c
diff options
context:
space:
mode:
authorThomas Martitz <kugel@rockbox.org>2011-03-05 18:36:51 +0000
committerThomas Martitz <kugel@rockbox.org>2011-03-05 18:36:51 +0000
commit9edd6d4ee912273690b2600e8c52183dfa058eb9 (patch)
treecf6b0723f42c090022b94b38b3c4d856e9378d40 /apps/plugins/mpegplayer/mpegplayer.c
parent396ddd9fd79e458d1107f4065ce072eef99b6bce (diff)
downloadrockbox-9edd6d4ee912273690b2600e8c52183dfa058eb9.tar.gz
rockbox-9edd6d4ee912273690b2600e8c52183dfa058eb9.tar.bz2
rockbox-9edd6d4ee912273690b2600e8c52183dfa058eb9.zip
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
Diffstat (limited to 'apps/plugins/mpegplayer/mpegplayer.c')
-rw-r--r--apps/plugins/mpegplayer/mpegplayer.c174
1 files changed, 172 insertions, 2 deletions
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;