diff --git a/legacy/evas/src/modules/engines/software_16/Makefile.am b/legacy/evas/src/modules/engines/software_16/Makefile.am index 250f20e023..3f66123e94 100644 --- a/legacy/evas/src/modules/engines/software_16/Makefile.am +++ b/legacy/evas/src/modules/engines/software_16/Makefile.am @@ -12,7 +12,8 @@ pkg_LTLIBRARIES = module.la module_la_SOURCES = \ evas_engine.c \ evas_soft16.h \ -evas_soft16_main.c +evas_soft16_main.c \ +evas_soft16_font.c module_la_LIBADD = $(top_builddir)/src/lib/libevas.la module_la_LDFLAGS = -module -avoid-version -L$(top_builddir)/src/lib -L$(top_builddir)/src/lib/.libs @@ -23,4 +24,5 @@ endif EXTRA_DIST = \ evas_engine.c \ evas_soft16.h \ -evas_soft16_main.c +evas_soft16_main.c \ +evas_soft16_font.c diff --git a/legacy/evas/src/modules/engines/software_16/evas_engine.c b/legacy/evas/src/modules/engines/software_16/evas_engine.c index 2fa550d3e0..37b07f69a3 100644 --- a/legacy/evas/src/modules/engines/software_16/evas_engine.c +++ b/legacy/evas/src/modules/engines/software_16/evas_engine.c @@ -574,8 +574,28 @@ eng_font_char_at_coords_get(void *data, void *font, const char *text, int x, int static void eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow, int oh, const char *text) { -// evas_common_font_draw(surface, context, font, x, y, text); -// evas_common_cpu_end_opt(); + static RGBA_Image *im = NULL; + Soft16_Image *dst = surface; + + if (!im) + { + im = evas_common_image_new(); + im->image = evas_common_image_surface_new(im); + im->image->no_free = 1; + } + im->image->w = dst->w; + im->image->h = dst->h; + evas_common_draw_context_font_ext_set(context, + surface, + soft16_font_glyph_new, + soft16_font_glyph_free, + soft16_font_glyph_draw); + evas_common_font_draw(im, context, font, x, y, text); + evas_common_draw_context_font_ext_set(context, + NULL, + NULL, + NULL, + NULL); } static void diff --git a/legacy/evas/src/modules/engines/software_16/evas_soft16.h b/legacy/evas/src/modules/engines/software_16/evas_soft16.h index 77d0bc62e7..ea9eaf6411 100644 --- a/legacy/evas/src/modules/engines/software_16/evas_soft16.h +++ b/legacy/evas/src/modules/engines/software_16/evas_soft16.h @@ -5,6 +5,35 @@ #include "evas_private.h" #include "evas_common.h" +#define RGB_565_UNPACKED_MASK 0x07e0f81f +#define RGB_565_UNPACK(rgb) \ + (((rgb) | ((rgb) << 16)) & RGB_565_UNPACKED_MASK) +#define RGB_565_PACK(rgb) \ + ((((rgb) & RGB_565_UNPACKED_MASK) | \ + ((rgb) & RGB_565_UNPACKED_MASK) >> 16) & 0xffff) +#define RGB_565_UNPACKED_BLEND(a, b, alpha) \ + ((b) + ((((a) - (b)) * (alpha)) >> 5)) + +#define RGB_565_FROM_COMPONENTS(r, g, b) \ + (((((r) >> 3) & 0x1f) << 11) | \ + ((((g) >> 2) & 0x3f) << 5) | \ + (((b) >> 3) & 0x1f)) + +#define UNROLL2(op...) op op +#define UNROLL4(op...) UNROLL2(op) UNROLL2(op) +#define UNROLL8(op...) UNROLL4(op) UNROLL4(op) +#define UNROLL16(op...) UNROLL8(op) UNROLL8(op) + + +#if defined(__ARMEL__) +/* tested on ARMv6 (arm1136j-s), Nokia N800 CPU */ +#define pld(addr, off) \ + __asm__("pld [%[address], %[offset]]":: \ + [address] "r" (addr), [offset] "i" (off)) +#else +#define pld(addr, off) +#endif /* __ARMEL__ */ + typedef struct _Soft16_Image Soft16_Image; struct _Soft16_Image @@ -43,4 +72,10 @@ void soft16_image_draw(Soft16_Image *src, Soft16_Image *dst, void soft16_rectangle_draw(Soft16_Image *dst, RGBA_Draw_Context *dc, int x, int y, int w, int h); + + + +void *soft16_font_glyph_new(void *data, RGBA_Font_Glyph *fg); +void soft16_font_glyph_free(void *ext_dat); +void soft16_font_glyph_draw(Soft16_Image *dst, void *data, RGBA_Draw_Context *dc, RGBA_Font_Glyph *fg, int x, int y); #endif diff --git a/legacy/evas/src/modules/engines/software_16/evas_soft16_font.c b/legacy/evas/src/modules/engines/software_16/evas_soft16_font.c new file mode 100644 index 0000000000..7e37741052 --- /dev/null +++ b/legacy/evas/src/modules/engines/software_16/evas_soft16_font.c @@ -0,0 +1,298 @@ +#include "evas_common.h" +#include "evas_private.h" +#include "evas_soft16.h" + +static inline void +_glyph_pt_mask_solid_solid(DATA16 *dst, + const DATA16 rgb565, + const DATA32 rgb565_unpack, + const DATA8 *mask) +{ + DATA8 alpha = *mask; + + if (alpha == 255) *dst = rgb565; + else if (alpha > 8) + { + DATA32 d; + + d = RGB_565_UNPACK(*dst); + d = RGB_565_UNPACKED_BLEND(rgb565_unpack, d, alpha >> 3); + *dst = RGB_565_PACK(d); + } +} + +static inline void +_glyph_scanline_mask_solid_solid(DATA16 *dst, + int size, + const DATA16 rgb565, + const DATA32 rgb565_unpack, + const DATA8 *mask) +{ + DATA16 *start, *end; + + start = dst; + pld(start, 0); + pld(mask, 0); + end = start + (size & ~3); + + while (start < end) + { + pld(start, 16); + pld(mask, 4); + UNROLL4({ + _glyph_pt_mask_solid_solid(start, rgb565, rgb565_unpack, mask); + start++; + mask++; + }); + } + + end = start + (size & 3); + for (; start < end; start++, mask++) + _glyph_pt_mask_solid_solid(start, rgb565, rgb565_unpack, mask); +} + +static inline void +_glyph_pt_mask_transp_solid(DATA16 *dst, + const DATA32 rgb565_unpack, + const DATA8 rel_alpha, + const DATA8 *mask) +{ + DATA32 d; + DATA8 alpha; + + if (*mask == 255) alpha = rel_alpha >> 3; + else if (*mask == 0) return; + else + { + /* doing multiply to avoid too much error, it's acceptable to do: + * alpha - (max_alpha - rel_alpha) + * on images because error is not that important/noticeable, but + * on texts, with many edges, it's unacceptable. + */ + alpha = (*mask * rel_alpha) >> 11; + if (alpha == 0) return; + } + + d = RGB_565_UNPACK(*dst); + d = RGB_565_UNPACKED_BLEND(rgb565_unpack, d, alpha); + *dst = RGB_565_PACK(d); +} + +static inline void +_glyph_scanline_mask_transp_solid(DATA16 *dst, + int size, + const DATA32 rgb565_unpack, + const DATA8 rel_alpha, + const DATA8 *mask) +{ + DATA16 *start, *end; + + start = dst; + pld(start, 0); + pld(mask, 0); + end = start + (size & ~3); + + while (start < end) + { + pld(start, 16); + pld(mask, 4); + UNROLL4({ + _glyph_pt_mask_transp_solid(start, rgb565_unpack, rel_alpha, mask); + start++; + mask++; + }); + } + + end = start + (size & 3); + for (; start < end; start++, mask++) + _glyph_pt_mask_transp_solid(start, rgb565_unpack, rel_alpha, mask); +} + +static inline void +_calc_ext(const Soft16_Image *dst, const RGBA_Draw_Context *dc, + Evas_Rectangle *ext) +{ + ext->x = 0; + ext->y = 0; + ext->w = dst->w; + ext->h = dst->h; + + if (dc->clip.use) + { + int v; + + ext->x = dc->clip.x; + ext->y = dc->clip.y; + ext->w = dc->clip.w; + ext->h = dc->clip.h; + if (ext->x < 0) + { + ext->w += ext->x; + ext->x = 0; + } + if (ext->y < 0) + { + ext->h += ext->y; + ext->y = 0; + } + + v = dst->w - ext->x; + if (ext->w > v) ext->w = v; + + v = dst->h - ext->y; + if (ext->h > v) ext->h = v; + } +} + +static inline void +_glyph_scaline(Soft16_Image *dst, const DATA8 *p_mask, + const Evas_Rectangle ext, int dx, int dy, int max_x, int max_y, + int w, DATA8 alpha, const DATA16 rgb565, + const DATA32 rgb565_unpack) +{ + int size, in_x, in_w; + DATA16 *p_pixels; + + if ((dx >= max_x) || (dy < ext.y) || (dy >= max_y)) return; + + in_x = 0; + in_w = 0; + + if (dx + w > max_x) in_w += (dx + w) - max_x; + + if (dx < ext.x) + { + in_w += ext.x - dx; + in_x = ext.x - dx; + dx = ext.x; + } + + size = w - in_w; + p_pixels = dst->pixels + (dy * dst->stride) + dx; + p_mask += in_x; + + if (size > 1) + { + if (alpha == 255) + _glyph_scanline_mask_solid_solid + (p_pixels, size, rgb565, rgb565_unpack, p_mask); + else if (alpha != 0) + _glyph_scanline_mask_transp_solid + (p_pixels, size, rgb565_unpack, alpha, p_mask); + } + else if (size == 1) + { + if (alpha == 255) + _glyph_pt_mask_solid_solid(p_pixels, rgb565, rgb565_unpack, p_mask); + else if (alpha != 0) + _glyph_pt_mask_transp_solid(p_pixels, rgb565_unpack, alpha, p_mask); + } +} + +static inline void +_soft16_font_glyph_draw_grayscale(Soft16_Image *dst, + RGBA_Draw_Context *dc, RGBA_Font_Glyph *fg, + int x, int y, DATA8 alpha, DATA16 rgb565, + const Evas_Rectangle ext, int bw, int bh, + int bpitch, const DATA8 *bitmap) +{ + const DATA32 rgb565_unpack = RGB_565_UNPACK(rgb565); + int i, max_x, max_y; + + max_x = ext.x + ext.w; + max_y = ext.y + ext.h; + + for (i = 0; i < bh; i++, bitmap += bpitch) + _glyph_scaline(dst, bitmap, ext, x, y + i, max_x, max_y, bw, + alpha, rgb565, rgb565_unpack); +} + +static inline void +_glyph_create_mask_line(DATA8 *mask, const DATA8 *bitmap, int w) +{ + const DATA8 bitrepl[2] = {0x0, 0xff}; + int i; + + for (i = 0; i < w; i += 8, bitmap++) + { + int j, size; + DATA32 bits; + + if (i + 8 < w) size = 8; + else size = w - i; + + bits = *bitmap; + + for (j = size - 1; j >= 0; j--, mask++) + *mask = bitrepl[(bits >> j) & 0x1]; + } +} + +static inline void +_soft16_font_glyph_draw_mono(Soft16_Image *dst, + RGBA_Draw_Context *dc, RGBA_Font_Glyph *fg, + int x, int y, DATA8 alpha, DATA16 rgb565, + const Evas_Rectangle ext, int bw, int bh, + int bpitch, const DATA8 *bitmap) +{ + const DATA32 rgb565_unpack = RGB_565_UNPACK(rgb565); + DATA8 *mask; + int i, max_x, max_y; + + max_x = ext.x + ext.w; + max_y = ext.y + ext.h; + + mask = alloca(bpitch); + for (i = 0; i < bh; i++, bitmap += bpitch) + { + _glyph_create_mask_line(mask, bitmap, bw); + _glyph_scaline(dst, mask, ext, x, y + i, max_x, max_y, bw, + alpha, rgb565, rgb565_unpack); + } +} + +void +soft16_font_glyph_draw(Soft16_Image *dst, void *data, + RGBA_Draw_Context *dc, RGBA_Font_Glyph *fg, + int x, int y) +{ + const DATA8 *bitmap; + DATA8 alpha; + DATA16 rgb565; + Evas_Rectangle ext; + int bpitch, bw, bh; + + alpha = A_VAL(&dc->col.col); + if (alpha < 8) return; /* precision is 5 bits, 3 bits lost */ + + rgb565 = RGB_565_FROM_COMPONENTS(R_VAL(&dc->col.col), + G_VAL(&dc->col.col), + B_VAL(&dc->col.col)); + + bitmap = fg->glyph_out->bitmap.buffer; + bh = fg->glyph_out->bitmap.rows; + bw = fg->glyph_out->bitmap.width; + bpitch = fg->glyph_out->bitmap.pitch; + if (bpitch < bw) bpitch = bw; + + _calc_ext(dst, dc, &ext); + + if ((fg->glyph_out->bitmap.num_grays == 256) && + (fg->glyph_out->bitmap.pixel_mode == ft_pixel_mode_grays)) + _soft16_font_glyph_draw_grayscale(dst, dc, fg, x, y, alpha, rgb565, + ext, bw, bh, bpitch, bitmap); + else + _soft16_font_glyph_draw_mono(dst, dc, fg, x, y, alpha, rgb565, + ext, bw, bh, bpitch, bitmap); +} + +void * +soft16_font_glyph_new(void *data, RGBA_Font_Glyph *fg) +{ + return (void *)1; /* core requires != NULL to work */ +} + +void +soft16_font_glyph_free(void *ext_dat) +{ +} diff --git a/legacy/evas/src/modules/engines/software_16/evas_soft16_main.c b/legacy/evas/src/modules/engines/software_16/evas_soft16_main.c index 928f503717..ec0c429bb2 100644 --- a/legacy/evas/src/modules/engines/software_16/evas_soft16_main.c +++ b/legacy/evas/src/modules/engines/software_16/evas_soft16_main.c @@ -2,36 +2,6 @@ #include "evas_private.h" #include "evas_soft16.h" -#define RGB_565_UNPACKED_MASK 0x07e0f81f -#define RGB_565_UNPACK(rgb) \ - (((rgb) | ((rgb) << 16)) & RGB_565_UNPACKED_MASK) -#define RGB_565_PACK(rgb) \ - ((((rgb) & RGB_565_UNPACKED_MASK) | \ - ((rgb) & RGB_565_UNPACKED_MASK) >> 16) & 0xffff) -#define RGB_565_UNPACKED_BLEND(a, b, alpha) \ - ((b) + ((((a) - (b)) * (alpha)) >> 5)) - -#define RGB_565_FROM_COMPONENTS(r, g, b) \ - (((((r) >> 3) & 0x1f) << 11) | \ - ((((g) >> 2) & 0x3f) << 5) | \ - (((b) >> 3) & 0x1f)) - -#define UNROLL2(op...) op op -#define UNROLL4(op...) UNROLL2(op) UNROLL2(op) -#define UNROLL8(op...) UNROLL4(op) UNROLL4(op) -#define UNROLL16(op...) UNROLL8(op) UNROLL8(op) - - -#if defined(__ARMEL__) -/* tested on ARMv6 (arm1136j-s), Nokia N800 CPU */ -#define pld(addr, off) \ - __asm__("pld [%[address], %[offset]]":: \ - [address] "r" (addr), [offset] "i" (off)) -#else -#define pld(addr, off) -#endif /* __ARMEL__ */ - - #define IMG_BYTE_SIZE(stride, height, has_alpha) \ ((stride) * (height) * (!(has_alpha) ? 2 : 3))