evas: Support bitmap embedded color font.
authorYoungbok Shin <youngb.shin@samsung.com>
Thu, 19 Mar 2015 10:02:02 +0000 (19:02 +0900)
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>
Thu, 19 Mar 2015 10:02:03 +0000 (19:02 +0900)
Summary:
Add the code for getting bitmap buffers from embedded color font,
And draw the bitmap buffers as images.
For drawing the bitmap buffers as images,
evas_common_draw_context_font_ext_set internal API is changed to
pass additional gl engine functions.
T2139
@feature

Test Plan:
1. Set a bitmap embedded color font to textblock.
2. Set a unicode emoticon text.
3. See the result.

Please check the sample unicode in the following link.
http://www.fileformat.info/info/unicode/char/1f3af/index.htm
http://www.fileformat.info/info/unicode/char/1f555/index.htm
http://www.fileformat.info/info/unicode/char/2600/index.htm
http://www.fileformat.info/info/unicode/char/263a/index.htm

Reviewers: tasn, woohyun, jpeg, raster

Reviewed By: raster

Subscribers: herdsman, cedric

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

12 files changed:
src/lib/evas/canvas/evas_object_text.c
src/lib/evas/canvas/evas_object_textblock.c
src/lib/evas/common/evas_draw.h
src/lib/evas/common/evas_draw_main.c
src/lib/evas/common/evas_font_draw.c
src/lib/evas/common/evas_font_load.c
src/lib/evas/common/evas_font_main.c
src/lib/evas/include/evas_common_private.h
src/modules/evas/engines/gl_common/evas_gl_common.h
src/modules/evas/engines/gl_common/evas_gl_image.c
src/modules/evas/engines/gl_generic/evas_engine.c
src/modules/evas/engines/software_generic/evas_engine.c

index f59bbd8..87c4d5a 100644 (file)
@@ -1978,6 +1978,7 @@ normal_render:
      }
    EINA_INLIST_FOREACH(EINA_INLIST_GET(o->items), it)
      {
+        ENFN->context_multiplier_set(output, context, 0, 0, 0, 0);
         /* Shadows */
         if (haveshad)
           {
@@ -2053,8 +2054,15 @@ normal_render:
           }
 
         /* normal text */
+        ENFN->context_multiplier_unset(output, context);
+        ENFN->context_multiplier_set(output, context,
+                                     obj->cur->clipper->cur->cache.clip.r,
+                                     obj->cur->clipper->cur->cache.clip.g,
+                                     obj->cur->clipper->cur->cache.clip.b,
+                                     obj->cur->clipper->cur->cache.clip.a);
         COLOR_ONLY_SET(obj, cur->cache, clip);
         DRAW_TEXT(0, 0);
+        ENFN->context_multiplier_unset(output, context);
      }
 }
 
index da4d41b..7b836b3 100644 (file)
@@ -11246,8 +11246,8 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
      };
 
    /* render object to surface with context, and offxet by x,y */
-   obj->layer->evas->engine.func->context_multiplier_unset(output,
-                                                          context);
+   ENFN->context_multiplier_unset(output, context);
+   ENFN->context_multiplier_set(output, context, 0, 0, 0, 0);
    ENFN->context_render_op_set(output, context, obj->cur->render_op);
    /* FIXME: This clipping is just until we fix inset handling correctly. */
    ENFN->context_clip_clip(output, context,
@@ -11668,6 +11668,12 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
            evas_common_font_instance_underline_thickness_get(NULL);
    int line_position =
            evas_common_font_instance_underline_position_get(NULL);
+   ENFN->context_multiplier_unset(output, context);
+   ENFN->context_multiplier_set(output, context,
+                                obj->cur->clipper->cur->cache.clip.r,
+                                obj->cur->clipper->cur->cache.clip.g,
+                                obj->cur->clipper->cur->cache.clip.b,
+                                obj->cur->clipper->cur->cache.clip.a);
    ITEM_WALK()
      {
         Evas_Object_Textblock_Text_Item *ti;
@@ -11701,6 +11707,7 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
               line_position, line_thickness);
      }
    ITEM_WALK_END();
+   ENFN->context_multiplier_unset(output, context);
 }
 
 static void
index 3f01a75..10cb26f 100644 (file)
@@ -10,7 +10,10 @@ EAPI void               evas_common_draw_context_font_ext_set            (RGBA_D
                                                                           void *data,
                                                                           void *(*gl_new)  (void *data, RGBA_Font_Glyph *fg),
                                                                           void  (*gl_free) (void *ext_dat),
-                                                                          void  (*gl_draw) (void *data, void *dest, void *context, RGBA_Font_Glyph *fg, int x, int y));
+                                                                          void  (*gl_draw) (void *data, void *dest, void *context, RGBA_Font_Glyph *fg, int x, int y),
+                                                                          void *(*gl_image_new_from_data) (void *gc, unsigned int w, unsigned int h, DATA32 *image_data, int alpha, Evas_Colorspace cspace),
+                                                                          void  (*gl_image_free) (void *image),
+                                                                          void  (*gl_image_draw) (void *gc, void *im, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, int smooth));
 EAPI void               evas_common_draw_context_clip_clip               (RGBA_Draw_Context *dc, int x, int y, int w, int h);
 EAPI void               evas_common_draw_context_set_clip                (RGBA_Draw_Context *dc, int x, int y, int w, int h);
 EAPI void               evas_common_draw_context_unset_clip              (RGBA_Draw_Context *dc);
index 27541bb..01ba20c 100644 (file)
@@ -108,15 +108,21 @@ evas_common_draw_context_clear_cutouts(RGBA_Draw_Context *dc)
 
 EAPI void
 evas_common_draw_context_font_ext_set(RGBA_Draw_Context *dc,
-                                     void *data,
-                                     void *(*gl_new)  (void *data, RGBA_Font_Glyph *fg),
-                                     void  (*gl_free) (void *ext_dat),
-                                     void  (*gl_draw) (void *data, void *dest, void *context, RGBA_Font_Glyph *fg, int x, int y))
+                                      void *data,
+                                      void *(*gl_new)  (void *data, RGBA_Font_Glyph *fg),
+                                      void  (*gl_free) (void *ext_dat),
+                                      void  (*gl_draw) (void *data, void *dest, void *context, RGBA_Font_Glyph *fg, int x, int y),
+                                      void *(*gl_image_new_from_data) (void *gc, unsigned int w, unsigned int h, DATA32 *image_data, int alpha, Evas_Colorspace cspace),
+                                      void  (*gl_image_free) (void *image),
+                                      void  (*gl_image_draw) (void *gc, void *im, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, int smooth))
 {
    dc->font_ext.data = data;
    dc->font_ext.func.gl_new = gl_new;
    dc->font_ext.func.gl_free = gl_free;
    dc->font_ext.func.gl_draw = gl_draw;
+   dc->font_ext.func.gl_image_new_from_data = gl_image_new_from_data;
+   dc->font_ext.func.gl_image_free = gl_image_free;
+   dc->font_ext.func.gl_image_draw = gl_image_draw;
 }
 
 EAPI void
index b243667..367b8cd 100644 (file)
@@ -23,6 +23,72 @@ evas_common_font_draw_init(void)
 {
 }
 
+static void *
+_software_generic_image_new_from_data(int w, int h, DATA32 *image_data, int alpha, Evas_Colorspace cspace)
+{
+#ifdef EVAS_CSERVE2
+   if (evas_cserve2_use_get())
+     {
+        Evas_Cache2 *cache = evas_common_image_cache2_get();
+        return evas_cache2_image_data(cache, w, h, image_data, alpha, cspace);
+     }
+#endif
+   return evas_cache_image_data(evas_common_image_cache_get(), w, h, image_data, alpha, cspace);
+}
+
+static void
+_software_generic_image_free(void *image)
+{
+#ifdef EVAS_CSERVE2
+   if (evas_cserve2_use_get() && evas_cache2_image_cached(image))
+     {
+        evas_cache2_image_close(image);
+        return;
+     }
+#endif
+   evas_cache_image_drop(image);
+}
+
+static void
+_software_generic_image_draw(void *context, void *surface, void *image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int dst_w, int dst_h, int smooth)
+{
+   RGBA_Image *im;
+
+   if (!image) return;
+   im = image;
+
+#ifdef BUILD_PIPE_RENDER
+   if ((eina_cpu_count() > 1))
+     {
+#ifdef EVAS_CSERVE2
+        if (evas_cserve2_use_get())
+          evas_cache2_image_load_data(&im->cache_entry);
+#endif
+        evas_common_rgba_image_scalecache_prepare((Image_Entry *)(im),
+                                                  surface, context, smooth,
+                                                  src_x, src_y, src_w, src_h,
+                                                  dst_x, dst_y, dst_w, dst_h);
+
+        evas_common_pipe_image_draw(im, surface, context, smooth,
+                                    src_x, src_y, src_w, src_h,
+                                    dst_x, dst_y, dst_w, dst_h);
+     }
+   else
+#endif
+     {
+        evas_common_rgba_image_scalecache_prepare
+          (&im->cache_entry, surface, context, smooth,
+           src_x, src_y, src_w, src_h,
+           dst_x, dst_y, dst_w, dst_h);
+        evas_common_rgba_image_scalecache_do
+          (&im->cache_entry, surface, context, smooth,
+           src_x, src_y, src_w, src_h,
+           dst_x, dst_y, dst_w, dst_h);
+
+        evas_common_cpu_end_opt();
+     }
+}
+
 /*
  * BiDi handling: We receive the shaped string + other props from text_props,
  * we need to reorder it so we'll have the visual string (the way we draw)
@@ -42,29 +108,80 @@ evas_common_font_rgba_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, int x, int y,
    EINA_INARRAY_FOREACH(glyphs->array, glyph)
      {
         RGBA_Font_Glyph *fg;
-        int chr_x, chr_y, w;
+        int chr_x, chr_y, w, h;
 
         fg = glyph->fg;
+        w = fg->glyph_out->bitmap.width;
+        h = fg->glyph_out->bitmap.rows;
+
         if ((!fg->ext_dat) && (dc->font_ext.func.gl_new))
           {
              /* extension calls */
              fg->ext_dat = dc->font_ext.func.gl_new(dc->font_ext.data, fg);
              fg->ext_dat_free = dc->font_ext.func.gl_free;
           }
-        w = fg->glyph_out->bitmap.width;
+
+        if ((!fg->ext_dat) && FT_HAS_COLOR(fg->fi->src->ft.face))
+          {
+             if (dc->font_ext.func.gl_image_new_from_data)
+               {
+                  /* extension calls */
+                  fg->ext_dat = dc->font_ext.func.gl_image_new_from_data(dc->font_ext.data,
+                                                                         (unsigned int)w, (unsigned int)h,
+                                                                         (DATA32 *)fg->glyph_out->bitmap.buffer,
+                                                                         EINA_TRUE,
+                                                                         EVAS_COLORSPACE_ARGB8888);
+                  fg->ext_dat_free = dc->font_ext.func.gl_image_free;
+               }
+             else
+               {
+                  fg->ext_dat = _software_generic_image_new_from_data(w, h,
+                                                                      (DATA32 *)fg->glyph_out->bitmap.buffer,
+                                                                      EINA_TRUE,
+                                                                      EVAS_COLORSPACE_ARGB8888);
+                  fg->ext_dat_free = _software_generic_image_free;
+               }
+          }
+
         chr_x = x + glyph->x;
         chr_y = y + glyph->y;
         if (chr_x < (ext_x + ext_w))
           {
              if ((w > 0) && ((chr_x + w) > ext_x))
                {
-                  if ((fg->ext_dat) && (dc->font_ext.func.gl_draw))
-                    dc->font_ext.func.gl_draw(dc->font_ext.data, (void *)dst,
-                                              dc, fg, chr_x, y - (chr_y - y));
-                  else if (fg->glyph_out->rle)
-                    evas_common_font_glyph_draw(fg, dc, dst, im_w,
-                                                chr_x, y - (chr_y - y),
-                                                ext_x, ext_y, ext_w, ext_h);
+                  if (fg->glyph_out->rle)
+                    {
+                       if ((fg->ext_dat) && (dc->font_ext.func.gl_draw))
+                         {
+                            dc->font_ext.func.gl_draw(dc->font_ext.data, (void *)dst,
+                                                      dc, fg, chr_x, y - (chr_y - y));
+                         }
+                       else
+                         {
+                            evas_common_font_glyph_draw(fg, dc, dst, im_w,
+                                                        chr_x, y - (chr_y - y),
+                                                        ext_x, ext_y, ext_w, ext_h);
+                         }
+                    }
+                  else if ((fg->ext_dat) && FT_HAS_COLOR(fg->fi->src->ft.face))
+                    {
+                       if (dc->font_ext.func.gl_image_draw)
+                         {
+                            dc->font_ext.func.gl_image_draw(dc->font_ext.data,
+                                                            fg->ext_dat,
+                                                            0, 0, w, h,
+                                                            chr_x, y - (chr_y - y), w, h,
+                                                            EINA_TRUE);
+                         }
+                       else
+                         {
+                            _software_generic_image_draw(dc, dst,
+                                                         fg->ext_dat,
+                                                         0, 0, w, h,
+                                                         chr_x, y - (chr_y - y), w, h,
+                                                         EINA_TRUE);
+                         }
+                    }
                }
           }
         else
index 92fdd24..041fe00 100644 (file)
@@ -446,6 +446,7 @@ evas_common_font_int_load_complete(RGBA_Font_Int *fi)
        int i, maxd = 0x7fffffff;
        int chosen_size = 0;
        int chosen_size2 = 0;
+        FT_Int strike_index = 0;
 
        for (i = 0; i < fi->src->ft.face->num_fixed_sizes; i++)
          {
@@ -459,12 +460,18 @@ evas_common_font_int_load_complete(RGBA_Font_Int *fi)
                   maxd = cd;
                  chosen_size = s;
                  chosen_size2 = fi->src->ft.face->available_sizes[i].y_ppem;
+                  strike_index = (FT_Int)i;
                   if (maxd == 0) break;
               }
          }
        fi->real_size = chosen_size;
         FTLOCK();
-       error = FT_Set_Pixel_Sizes(fi->src->ft.face, 0, fi->real_size);
+
+        if (FT_HAS_FIXED_SIZES(fi->src->ft.face))
+          error = FT_Select_Size(fi->src->ft.face, strike_index);
+        else
+          error = FT_Set_Pixel_Sizes(fi->src->ft.face, 0, fi->real_size);
+
         FTUNLOCK();
        if (error)
          {
index 97961d0..7562d28 100644 (file)
@@ -371,6 +371,12 @@ _glyph_free(RGBA_Font_Glyph *fg)
 
    if (fg->glyph_out)
      {
+        if ((!fg->glyph_out->rle) && (!fg->glyph_out->bitmap.rle_alloc))
+          {
+             FT_BitmapGlyph fbg = (FT_BitmapGlyph)fg->glyph;
+             FT_Bitmap_Done(evas_ft_lib, &(fbg->bitmap));
+          }
+
         if ((fg->glyph_out->rle) && (fg->glyph_out->bitmap.rle_alloc))
           free(fg->glyph_out->rle);
         fg->glyph_out->rle = NULL;
@@ -501,8 +507,10 @@ evas_common_font_int_cache_glyph_get(RGBA_Font_Int *fi, FT_UInt idx)
    evas_common_font_int_reload(fi);
    FTLOCK();
    error = FT_Load_Glyph(fi->src->ft.face, idx,
-                         FT_LOAD_DEFAULT | FT_LOAD_NO_BITMAP |
-                         hintflags[fi->hinting]);
+                         (FT_HAS_COLOR(fi->src->ft.face) ?
+                          (FT_LOAD_COLOR | hintflags[fi->hinting]) :
+                          (FT_LOAD_DEFAULT | FT_LOAD_NO_BITMAP | hintflags[fi->hinting])));
+
    FTUNLOCK();
    if (error)
      {
@@ -617,16 +625,25 @@ evas_common_font_int_cache_glyph_render(RGBA_Font_Glyph *fg)
    fi->usage += size;
    if (fi->inuse) evas_common_font_int_use_increase(size);
 
-   fg->glyph_out->rle = evas_common_font_glyph_compress
-   (fbg->bitmap.buffer, fbg->bitmap.num_grays, fbg->bitmap.pixel_mode,
-    fbg->bitmap.pitch, fbg->bitmap.width, fbg->bitmap.rows,
-    &(fg->glyph_out->rle_size));
+   if (!FT_HAS_COLOR(fi->src->ft.face))
+     {
+        fg->glyph_out->rle = evas_common_font_glyph_compress
+           (fbg->bitmap.buffer, fbg->bitmap.num_grays, fbg->bitmap.pixel_mode,
+            fbg->bitmap.pitch, fbg->bitmap.width, fbg->bitmap.rows,
+            &(fg->glyph_out->rle_size));
+        fg->glyph_out->bitmap.rle_alloc = EINA_TRUE;
 
-   fg->glyph_out->bitmap.buffer = NULL;
+        fg->glyph_out->bitmap.buffer = NULL;
 
-   // this may be technically incorrect as we go and free a bitmap buffer
-   // behind the ftglyph's back...
-   FT_Bitmap_Done(evas_ft_lib, &(fbg->bitmap));
+        // this may be technically incorrect as we go and free a bitmap buffer
+        // behind the ftglyph's back...
+        FT_Bitmap_Done(evas_ft_lib, &(fbg->bitmap));
+     }
+   else
+     {
+        fg->glyph_out->rle = NULL;
+        fg->glyph_out->bitmap.rle_alloc = EINA_FALSE;
+     }
    
    return EINA_TRUE;
 }
index aea5de4..da53e2e 100644 (file)
@@ -194,6 +194,10 @@ extern EAPI int _evas_log_dom_global;
 #include FT_SIZES_H
 #include FT_MODULE_H
 
+#ifndef FT_HAS_COLOR
+# define FT_HAS_COLOR(face) 0
+#endif
+
 #ifdef __GNUC__
 # if __GNUC__ >= 4
 // BROKEN in gcc 4 on amd64
@@ -708,9 +712,12 @@ struct _RGBA_Draw_Context
    Cutout_Rects cutout;
    struct {
       struct {
-        void *(*gl_new)  (void *data, RGBA_Font_Glyph *fg);
-        void  (*gl_free) (void *ext_dat);
-        void  (*gl_draw) (void *data, void *dest, void *context, RGBA_Font_Glyph *fg, int x, int y);
+         void *(*gl_new)  (void *data, RGBA_Font_Glyph *fg);
+         void  (*gl_free) (void *ext_dat);
+         void  (*gl_draw) (void *data, void *dest, void *context, RGBA_Font_Glyph *fg, int x, int y);
+         void *(*gl_image_new_from_data) (void *gc, unsigned int w, unsigned int h, DATA32 *image_data, int alpha, Evas_Colorspace cspace);
+         void  (*gl_image_free) (void *image);
+         void  (*gl_image_draw) (void *gc, void *im, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, int smooth);
       } func;
       void *data;
    } font_ext;
index 5cad385..112eb44 100644 (file)
@@ -827,6 +827,9 @@ void              evas_gl_common_image_draw(Evas_Engine_GL_Context *gc, Evas_GL_
 void             *evas_gl_font_texture_new(void *gc, RGBA_Font_Glyph *fg);
 void              evas_gl_font_texture_free(void *);
 void              evas_gl_font_texture_draw(void *gc, void *surface, void *dc, RGBA_Font_Glyph *fg, int x, int y);
+void             *evas_gl_image_new_from_data(void *gc, unsigned int w, unsigned int h, DATA32 *data, int alpha, Evas_Colorspace cspace);
+void              evas_gl_image_free(void *im);
+void              evas_gl_image_draw(void *gc, void *im, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, int smooth);
 
 Evas_GL_Polygon  *evas_gl_common_poly_point_add(Evas_GL_Polygon *poly, int x, int y);
 Evas_GL_Polygon  *evas_gl_common_poly_points_clear(Evas_GL_Polygon *poly);
index ec5eddb..b8076a0 100644 (file)
@@ -1265,3 +1265,29 @@ evas_gl_common_image_draw(Evas_Engine_GL_Context *gc, Evas_GL_Image *im, int sx,
    /* restore clip info */
    gc->dc->clip.use = c; gc->dc->clip.x = cx; gc->dc->clip.y = cy; gc->dc->clip.w = cw; gc->dc->clip.h = ch;
 }
+
+void *
+evas_gl_image_new_from_data(void *gc, unsigned int w, unsigned int h, DATA32 *data, int alpha, Evas_Colorspace cspace)
+{
+   return (void *)evas_gl_common_image_new_from_data((Evas_Engine_GL_Context *)gc,
+                                                     w, h,
+                                                     data,
+                                                     alpha,
+                                                     cspace);
+}
+
+void
+evas_gl_image_free(void *im)
+{
+   evas_gl_common_image_free((Evas_GL_Image *)im);
+}
+
+void
+evas_gl_image_draw(void *gc, void *im, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, int smooth)
+{
+   evas_gl_common_image_draw((Evas_Engine_GL_Context *)gc,
+                             (Evas_GL_Image *)im,
+                             sx, sy, sw, sh,
+                             dx, dy, dw, dh,
+                             smooth);
+}
index 236a4bc..2d0bff0 100644 (file)
@@ -1165,13 +1165,19 @@ eng_font_draw(void *data, void *context, void *surface, Evas_Font_Set *font EINA
                                               gl_context,
                                               evas_gl_font_texture_new,
                                               evas_gl_font_texture_free,
-                                              evas_gl_font_texture_draw);
+                                              evas_gl_font_texture_draw,
+                                              evas_gl_image_new_from_data,
+                                              evas_gl_image_free,
+                                              evas_gl_image_draw);
         evas_common_font_draw_prepare(intl_props);
         evas_common_font_draw(im, context, x, y, intl_props->glyphs);
         evas_common_draw_context_font_ext_set(context,
                                               NULL,
                                               NULL,
                                               NULL,
+                                              NULL,
+                                              NULL,
+                                              NULL,
                                               NULL);
      }
 
index 3fd180e..f053ace 100644 (file)
@@ -352,6 +352,7 @@ struct _Evas_Thread_Command_Font
    void *gl_draw;
    void *font_ext_data;
    DATA32 col;
+   DATA32 mul_col;
    Eina_Rectangle clip_rect, ext;
    int im_w, im_h;
    void *mask;
@@ -2608,6 +2609,8 @@ _draw_thread_font_draw(void *data)
    dc.font_ext.func.gl_free = font->gl_free;
    dc.font_ext.func.gl_draw = font->gl_draw;
    dc.col.col = font->col;
+   dc.mul.col = font->mul_col;
+   dc.mul.use = (font->mul_col == 0xffffffff) ? 0 : 1;
    dc.clip.use = font->clip_use;
    dc.clip.x = font->clip_rect.x;
    dc.clip.y = font->clip_rect.y;
@@ -2642,6 +2645,7 @@ _font_draw_thread_cmd(RGBA_Image *dst, RGBA_Draw_Context *dc, int x, int y, Evas
    cf->gl_draw = dc->font_ext.func.gl_draw;
    cf->font_ext_data = dc->font_ext.data;
    cf->col = dc->col.col;
+   cf->mul_col = dc->mul.use ? dc->mul.col : 0xffffffff;
    cf->clip_use = dc->clip.use;
    EINA_RECTANGLE_SET(&cf->clip_rect,
                       dc->clip.x, dc->clip.y, dc->clip.w, dc->clip.h);