evas: Add scale feature for embedded bitmap fonts.
authorYoungbok Shin <youngb.shin@samsung.com>
Mon, 25 Sep 2017 09:34:22 +0000 (18:34 +0900)
committerJiyoun Park <jy0703.park@samsung.com>
Thu, 21 Dec 2017 12:47:43 +0000 (21:47 +0900)
Summary:
When evas selects a strike of embedded bitmap font,
calculate ratio and use it for scaling embedded bitmap.
@feature

Reviewers: jpeg, tasn, woohyun, raster, herdsman

Reviewed By: raster

Subscribers: charlesmilette, Francesco149, cedric

Differential Revision: https://phab.enlightenment.org/D2713

Change-Id: Ifcafac15f88cbc1914e005342af236b93b791dbf

src/lib/evas/canvas/evas_object_text.c
src/lib/evas/common/evas_font_compress.c

index 5d10cc9..4c7ae6a 100644 (file)
@@ -2562,6 +2562,7 @@ _evas_text_efl_text_font_font_bitmap_scalable_get(Eo *eo_obj EINA_UNUSED, Evas_T
 {
    return o->cur.bitmap_scalable;
 }
+
 /*********************************************************************************
  * TIZEN_ONLY(20171110): Import TIZEN_ONLY functions for
  *                       Edje textblock/text calculation/ellipsize feature.
index 6843c97..43628b2 100644 (file)
@@ -461,3 +461,149 @@ evas_common_font_glyph_uncompress(RGBA_Font_Glyph *fg, int *wret, int *hret)
                      fgo->bitmap.width, fgo->bitmap.rows);
    return buf;
 }
+
+// this draws a compressed font glyph and decompresses on the fly as it
+// draws, saving memory bandwidth and providing speedups
+EAPI void
+evas_common_font_glyph_draw(RGBA_Font_Glyph *fg, 
+                            RGBA_Draw_Context *dc,
+                            RGBA_Image *dst_image, int dst_pitch,
+                            int x, int y, int cx, int cy, int cw, int ch)
+{
+   RGBA_Font_Glyph_Out *fgo = fg->glyph_out;
+   int w, h, x1, x2, y1, y2, i, *iptr;
+   DATA32 *dst = dst_image->image.data;
+   DATA32 coltab[16], col;
+   DATA16 mtab[16], v;
+
+   w = fgo->bitmap.width; h = fgo->bitmap.rows;
+   // skip if totally clipped out
+   if ((y >= (cy + ch)) || ((y + h) <= cy) ||
+       (x >= (cx + cw)) || ((x + w) <= cx)) return;
+   // figure y1/y2 limit range
+   y1 = 0; y2 = h;
+   if ((y + y1) < cy) y1 = cy - y;
+   if ((y + y2) > (cy + ch)) y2 = cy + ch - y;
+   // figure x1/x2 limit range
+   x1 = 0; x2 = w;
+   if ((x + x1) < cx) x1 = cx - x;
+   if ((x + x2) > (cx + cw)) x2 = cx + cw - x;
+   col = dc->col.col;
+   if (dst_image->cache_entry.space == EVAS_COLORSPACE_GRY8)
+     {
+        // FIXME: Font draw not optimized for Alpha targets! SLOW!
+        // This is not pretty :)
+
+        DATA8 *src8, *dst8;
+        Draw_Func_Alpha func;
+        int row;
+
+        if (EINA_UNLIKELY(x < 0))
+          {
+             x1 += (-x);
+             x = 0;
+             if ((x2 - x1) <= 0) return;
+          }
+        if (EINA_UNLIKELY(y < 0))
+          {
+             y1 += (-y);
+             y = 0;
+             if ((y2 - y1) <= 0) return;
+          }
+
+        dst8 = dst_image->image.data8 + x + (y * dst_pitch);
+        func = efl_draw_alpha_func_get(dc->render_op, EINA_FALSE);
+        src8 = evas_common_font_glyph_uncompress(fg, NULL, NULL);
+        if (!src8) return;
+
+        for (row = y1; row < y2; row++)
+          {
+             DATA8 *d = dst8 + ((row - y1) * dst_pitch);
+             DATA8 *s = src8 + (row * w) + x1;
+             func(d, s, x2 - x1);
+          }
+        free(src8);
+     }
+   else if (dc->clip.mask)
+     {
+        RGBA_Gfx_Func func;
+        DATA8 *src8, *mask;
+        DATA32 *buf, *ptr, *buf_ptr;
+        RGBA_Image *im = dc->clip.mask;
+        int row;
+
+        buf = alloca(sizeof(DATA32) * w * h);
+
+        // Adjust clipping info
+        if (EINA_UNLIKELY((x + x1) < dc->clip.mask_x))
+          x1 = dc->clip.mask_x - x;
+        if (EINA_UNLIKELY((y + y1) < dc->clip.mask_y))
+          y1 = dc->clip.mask_y - y;
+        if (EINA_UNLIKELY((x + x2) > (int)(x + x1 + im->cache_entry.w)))
+          x2 = x1 + im->cache_entry.w;
+        if (EINA_UNLIKELY((y + y2) > (int)(y + y1 + im->cache_entry.h)))
+          y2 = y1 + im->cache_entry.h;
+
+        // Step 1: alpha glyph drawing
+        src8 = evas_common_font_glyph_uncompress(fg, NULL, NULL);
+        if (!src8) return;
+
+        // Step 2: color blending to buffer
+        func = evas_common_gfx_func_composite_mask_color_span_get(col, dst_image->cache_entry.flags.alpha, 1, EVAS_RENDER_COPY);
+        for (row = y1; row < y2; row++)
+          {
+             buf_ptr = buf + (row * w) + x1;
+             DATA8 *s = src8 + (row * w) + x1;
+             func(NULL, s, col, buf_ptr, x2 - x1);
+          }
+        free(src8);
+
+        // Step 3: masking to destination
+        func = evas_common_gfx_func_composite_pixel_mask_span_get(im->cache_entry.flags.alpha, im->cache_entry.flags.alpha_sparse, dst_image->cache_entry.flags.alpha, dst_pitch, dc->render_op);
+        for (row = y1; row < y2; row++)
+          {
+             mask = im->image.data8
+                + (y + row - dc->clip.mask_y) * im->cache_entry.w
+                + (x + x1 - dc->clip.mask_x);
+
+             ptr = dst + (x + x1) + ((y + row) * dst_pitch);
+             buf_ptr = buf + (row * w) + x1;
+             func(buf_ptr, mask, 0, ptr, x2 - x1);
+          }
+     }
+   else
+     {
+        // build fast multiply + mask color tables to avoid compute. this works
+        // because of our very limited 4bit range of alpha values
+        for (i = 0; i <= 0xf; i++)
+          {
+             v = (i << 4) | i;
+             coltab[i] = MUL_SYM(v, col);
+             mtab[i] = 256 - (coltab[i] >> 24);
+          }
+#ifdef BUILD_MMX
+        if (evas_common_cpu_has_feature(CPU_FEATURE_MMX))
+          {
+#define MMX 1
+#include "evas_font_compress_draw.c"
+#undef MMX
+          }
+        else
+#endif
+
+#ifdef BUILD_NEON
+        if (evas_common_cpu_has_feature(CPU_FEATURE_NEON))
+          {
+#define NEON 1
+#include "evas_font_compress_draw.c"
+#undef NEON
+          }
+        else
+#endif
+
+          // Plain C
+          {
+#include "evas_font_compress_draw.c"
+          }
+     }
+}