raster pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=972cd7f62bbfaa03d3b25ea1e8ba643de24cf7b9

commit 972cd7f62bbfaa03d3b25ea1e8ba643de24cf7b9
Author: Ali Alzyod <[email protected]>
Date:   Mon Jul 6 12:43:40 2020 +0100

    evas_text: lazy loading color glyph images in RAM
    
    Summary:
    Lazy loading for glyph images into RAM, instead of caching at layout level 
we will cache only when rendering.
    
    This may affect speed a bit since color glyphs will be loaded twice before 
caching (with FT_Load_Glyph)
    
    Try to run test application, and hit `scale font`
    
    ** RAM consumption (Accelerated Rendering) **
    
    | Before | After |
    |-------:|-------|
    |  111.9 | 21.8  |
    |  204.8 | 24.4  |
    |  298.0 | 26.3  |
    |  391.5 | 28.4  |
    |  484.8 | 29.9  |
    |  578.1 | 31.4  |
    |  671.4 | 32.5  |
    
    ** RAM consumption (SW Rendering) **
    
    | Before | After |
    |-------:|-------|
    |  104   | 14.6  |
    |  197   | 17    |
    |  290   | 19.1  |
    |  384   | 21.2  |
    |  477   | 22.8  |
    |  571   | 24.3  |
    |  664   | 25.6  |
    
    Test Plan:
    ```
    #include <Elementary.h>
    
    typedef struct _APP
    {
      Evas_Object *tb1;
      Evas_Object *btnLoad;
    } APP;
    
    char *text = "<align=center><color=#4DE0FFFF underline=on 
underline_color=#4DE0FFFF><a 
href='tel:1234567890'>1234567890</a></color>๐Ÿ˜€๐Ÿ˜๐Ÿ˜‚๐Ÿคฃ๐Ÿ˜ƒ๐Ÿ˜„๐Ÿ˜…๐Ÿ˜†๐Ÿ˜‰๐Ÿ˜Š๐Ÿ˜‹๐Ÿ˜Ž๐Ÿ˜๐Ÿ˜˜๐Ÿ˜—๐Ÿ˜™๐Ÿ˜šโ˜บ๐Ÿ™‚๐Ÿค—๐Ÿค”๐Ÿ˜๐Ÿ˜‘๐Ÿ˜ถ๐Ÿ™„๐Ÿ˜๐Ÿ˜ฃ๐Ÿ˜ฅ๐Ÿ˜ฎ๐Ÿค๐Ÿ˜ฏ๐Ÿ˜ช๐Ÿ˜ซ๐Ÿ˜ด๐Ÿ˜Œ๐Ÿค“๐Ÿ˜›๐Ÿ˜œ๐Ÿ˜๐Ÿคค๐Ÿ˜’๐Ÿ˜“๐Ÿ˜”๐Ÿ˜•๐Ÿ™ƒ๐Ÿค‘๐Ÿ˜ฒโ˜น๐Ÿ™๐Ÿ˜–๐Ÿ˜ž๐Ÿ˜Ÿ๐Ÿ˜ค๐Ÿ˜ข๐Ÿ˜ญ๐Ÿ˜ฆ๐Ÿ˜ง๐Ÿ˜จ๐Ÿ˜ฉ๐Ÿ˜ฌ๐Ÿ˜ฐ๐Ÿ˜ฑ๐Ÿ˜ณ๐Ÿ˜ต๐Ÿ˜ก๐Ÿ˜ ๐Ÿ˜‡๐Ÿค ๐Ÿคก๐Ÿคฅ๐Ÿ˜ท๐Ÿค’๐Ÿค•๐Ÿคข๐Ÿคงโ˜ป๐Ÿ˜ˆ๐Ÿ‘ฟ๐Ÿ‘น๐Ÿ‘บ๐Ÿ’€โ˜ ๐Ÿ‘ป๐Ÿ‘ฝ๐Ÿ‘พ๐Ÿค–๐Ÿ’ฉ๐Ÿ˜บ๐Ÿ˜ธ๐Ÿ˜น๐Ÿ˜ป๐Ÿ˜ผ๐Ÿ˜ฝ๐Ÿ™€๐Ÿ˜ฟ๐Ÿ˜พ๐Ÿ™ˆ๐Ÿ™‰๐Ÿ™Š๐Ÿ‘ฆ๐Ÿ‘ง๐Ÿ‘จ๐Ÿ‘ฉ๐Ÿ‘ต๐Ÿ‘ถ๐Ÿ‘ผ๐Ÿ‘จโ€โš•๏ธ๐Ÿ‘ฉโ€โš•๏ธ๐Ÿ‘จโ€๐ŸŽ“๐Ÿ‘ฉโ€๐ŸŽ“๐Ÿ‘จโ€๐Ÿซ๐Ÿ‘ฉโ€๐Ÿซ๐Ÿ‘จโ€โš–๐Ÿ‘ฉโ€โš–๐Ÿ‘จโ€๐ŸŒพ๐Ÿ‘ฉโ€๐ŸŒพ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘ฉโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿ”ง๐Ÿ‘ฉโ€๐Ÿ”ง๐Ÿ‘จโ€๐Ÿญ๐Ÿ‘ฉโ€๐Ÿญ๐Ÿ‘จโ€๐Ÿ’ผ๐Ÿ‘ฉโ€๐Ÿ’ผ๐Ÿ‘จโ€๐Ÿ”ฌ๐Ÿ‘ฉโ€๐Ÿ”ฌ๐Ÿ‘จโ€๐Ÿ’ป๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐ŸŽค๐Ÿ‘ฉโ€๐ŸŽค๐Ÿ‘จโ€๐ŸŽจ๐Ÿ‘ฉโ€๐ŸŽจ๐Ÿ‘จโ€โœˆ๏ธ๐Ÿ‘ฉโ€โœˆ๏ธ๐Ÿ‘จโ€๐Ÿš€๐Ÿ‘ฉโ€๐Ÿš€๐Ÿ‘จโ€๐Ÿš’๐Ÿ‘ฉโ€๐Ÿš’๐Ÿ‘ฎโ€โ™‚๏ธ๐Ÿ‘ฎโ€โ™€๏ธ๐Ÿ•ต๏ธโ€โ™‚๏ธ๐Ÿ•ต๏ธโ€โ™€๏ธ๐Ÿ’‚โ€โ™‚๏ธ๐Ÿ’‚โ€โ™€๏ธ๐Ÿ‘ทโ€โ™‚๏ธ๐Ÿ‘ทโ€โ™€๏ธ๐Ÿ‘ณโ€โ™‚๏ธ๐Ÿ‘ณโ€โ™€๏ธ๐Ÿ‘ฑโ€โ™‚๏ธ๐Ÿ‘ฑโ€โ™€๏ธ๐ŸŽ…๐Ÿคถ๐Ÿ‘ธ๐Ÿคด๐Ÿ‘ฐ๐Ÿคต๐Ÿคฐ๐Ÿ‘ฒ๐Ÿ™โ€โ™‚๏ธ๐Ÿ™โ€โ™€๏ธ๐Ÿ™Žโ€โ™‚๏ธ๐Ÿ™Žโ€โ™€๏ธ๐Ÿ™…โ€โ™‚๏ธ๐Ÿ™…โ€โ™€๏ธ๐Ÿ™†โ€โ™‚๏ธ๐Ÿ™†โ€โ™€๏ธ๐Ÿ’โ€โ™‚๏ธ๐Ÿ’โ€โ™€๏ธ๐Ÿ™‹โ€โ™‚๏ธ๐Ÿ™‹โ€โ™€๏ธ๐Ÿ™‡โ€โ™‚๏ธ๐Ÿ™‡โ€โ™€๏ธ๐Ÿคฆโ€โ™‚๏ธ๐Ÿคฆโ€โ™€๏ธ๐Ÿคทโ€โ™‚๏ธ๐Ÿคทโ€โ™€๏ธ๐Ÿ’†โ€โ™‚๏ธ๐Ÿ’†โ€โ™€๏ธ๐Ÿ’‡โ€โ™‚๏ธ๐Ÿ’‡โ€โ™€๏ธ๐Ÿšถโ€โ™‚๏ธ๐Ÿšถโ€
 [...]
    int font_size = 50;
    
    int counter = 0;
    void _button_clicked(void *data, Evas_Object *obj, void *event_info)
    {
       APP *app = data;
    
      font_size += 10;
      Evas_Textblock_Style *style = evas_textblock_style_new();
      char buffer[100] = {0};
      sprintf(buffer, "DEFAULT='font=NotoColorEmoji font_size=%i color=red 
ellipsis=-1.0 wrap=mixed'", font_size);
      evas_textblock_style_set(style, buffer);
      evas_object_textblock_style_set(app->tb1, style);
      evas_textblock_style_free(style);
      style = NULL;
    }
    
    EAPI_MAIN int
    elm_main(int argc EINA_UNUSED, char **argv EINA_UNUSED)
    {
      APP *app = calloc(1, sizeof(APP));
      Evas_Object *win, *scroller1, *scroller2, *box;
    
      elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
    
      win = elm_win_util_standard_add("", "");
      elm_win_autodel_set(win, EINA_TRUE);
    
      box = elm_box_add(win);
      evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
      evas_object_size_hint_align_set(box, EVAS_HINT_FILL, EVAS_HINT_FILL);
      scroller1 = elm_scroller_add(win);
      evas_object_size_hint_weight_set(scroller1, EVAS_HINT_EXPAND, 
EVAS_HINT_EXPAND);
      evas_object_size_hint_align_set(scroller1, EVAS_HINT_FILL, 
EVAS_HINT_FILL);
    
      app->tb1 = evas_object_textblock_add(win);
      Evas_Textblock_Style *style = evas_textblock_style_new();
      char buffer[100] = {0};
      sprintf(buffer, "DEFAULT='font=NotoColorEmoji font_size=%i color=red 
ellipsis=-1.0 wrap=mixed'", font_size);
      evas_textblock_style_set(style, buffer);
      evas_object_textblock_style_set(app->tb1, style);
      evas_textblock_style_free(style);
      style = NULL;
    
      evas_font_cache_set(evas_object_evas_get(app->tb1), 0);
    
      int w,h;
      evas_object_textblock_text_markup_set(app->tb1, "");
      evas_object_size_hint_min_set(app->tb1, 400, 400);
      elm_object_content_set(scroller1, app->tb1);
      elm_box_pack_end(box, scroller1);
      elm_object_content_set(win, box);
    
      app->btnLoad = elm_button_add(win);
      elm_object_text_set(app->btnLoad, "Scale Font");
      evas_object_smart_callback_add(app->btnLoad, "clicked", _button_clicked, 
app);
      evas_object_show(app->btnLoad);
      evas_object_move(app->btnLoad, 0, 20);
      evas_object_resize(app->btnLoad, 150, 20);
    
      evas_object_textblock_text_markup_set(app->tb1, text);
      evas_object_textblock_size_formatted_get(app->tb1, &w, &h);
      evas_object_size_hint_min_set(app->tb1, 400, w/400 + h + 150);
    
      evas_object_resize(win, 400, 400);
      evas_object_show(box);
      evas_object_show(scroller1);
      evas_object_show(scroller2);
      evas_object_show(win);
      elm_run();
    
      return 0;
    }
    ELM_MAIN()
    
    ```
    
    Reviewers: raster, woohyun, bowonryu, bu5hm4n, zmike, segfaultxavi
    
    Subscribers: cedric, #reviewers, #committers
    
    Tags: #efl
    
    Maniphest Tasks: T8727
    
    Differential Revision: https://phab.enlightenment.org/D11861
---
 src/lib/evas/common/evas_font.h       |   1 +
 src/lib/evas/common/evas_font_main.c  | 102 +++++++++++++++++++++++++---------
 src/lib/evas/common/evas_font_ot.c    |   2 +-
 src/lib/evas/common/evas_text_utils.c |   4 +-
 4 files changed, 81 insertions(+), 28 deletions(-)

diff --git a/src/lib/evas/common/evas_font.h b/src/lib/evas/common/evas_font.h
index 8b97c19399..fbed8e64bf 100644
--- a/src/lib/evas/common/evas_font.h
+++ b/src/lib/evas/common/evas_font.h
@@ -362,6 +362,7 @@ struct _RGBA_Font_Glyph
    Evas_Coord      x_bear;
    Evas_Coord      y_bear;
    FT_Glyph        glyph;
+   FT_Vector       advance;
    RGBA_Font_Glyph_Out *glyph_out;
    void           *col_dat;
    /* this is a problem - only 1 engine at a time can extend such a font... 
grrr */
diff --git a/src/lib/evas/common/evas_font_main.c 
b/src/lib/evas/common/evas_font_main.c
index 548ce4d01c..3a5b280437 100644
--- a/src/lib/evas/common/evas_font_main.c
+++ b/src/lib/evas/common/evas_font_main.c
@@ -711,6 +711,46 @@ _fash_gl_add(Fash_Glyph *fash, int item, RGBA_Font_Glyph 
*glyph)
    fash->bucket[grp]->bucket[maj]->item[min] = glyph;
 }
 
+static void evas_font_glyph_load(RGBA_Font_Glyph *fg)
+{
+   if(fg->glyph) return;
+
+   RGBA_Font_Int *fi = fg->fi;
+   FT_UInt idx = fg->index;
+   FT_Error error;
+
+   const FT_Int32 hintflags[3] =
+     { FT_LOAD_NO_HINTING, FT_LOAD_FORCE_AUTOHINT, FT_LOAD_NO_AUTOHINT };
+   static FT_Matrix transform = {0x10000, _EVAS_FONT_SLANT_TAN * 0x10000,
+        0x00000, 0x10000};
+
+   evas_common_font_int_reload(fi);
+   FTLOCK();
+   error = FT_Load_Glyph(fi->src->ft.face, idx,
+                         (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)
+     {
+        return;
+     }
+
+   /* Transform the outline of Glyph according to runtime_rend. */
+   if (fi->runtime_rend & FONT_REND_SLANT)
+     FT_Outline_Transform(&fi->src->ft.face->glyph->outline, &transform);
+   /* Embolden the outline of Glyph according to rundtime_rend. */
+   if (fi->runtime_rend & FONT_REND_WEIGHT)
+     FT_GlyphSlot_Embolden(fi->src->ft.face->glyph);
+
+   FTLOCK();
+   error = FT_Get_Glyph(fi->src->ft.face->glyph, &(fg->glyph));
+   FTUNLOCK();
+
+   return;
+}
+
 EAPI RGBA_Font_Glyph *
 evas_common_font_int_cache_glyph_get(RGBA_Font_Int *fi, FT_UInt idx)
 {
@@ -749,48 +789,60 @@ evas_common_font_int_cache_glyph_get(RGBA_Font_Int *fi, 
FT_UInt idx)
 
    /* Transform the outline of Glyph according to runtime_rend. */
    if (fi->runtime_rend & FONT_REND_SLANT)
-      FT_Outline_Transform(&fi->src->ft.face->glyph->outline, &transform);
+     FT_Outline_Transform(&fi->src->ft.face->glyph->outline, &transform);
    /* Embolden the outline of Glyph according to rundtime_rend. */
    if (fi->runtime_rend & FONT_REND_WEIGHT)
-      FT_GlyphSlot_Embolden(fi->src->ft.face->glyph);
+     FT_GlyphSlot_Embolden(fi->src->ft.face->glyph);
 
    fg = calloc(1, sizeof(RGBA_Font_Glyph));
    if (!fg) return NULL;
 
-   FTLOCK();
-   error = FT_Get_Glyph(fi->src->ft.face->glyph, &(fg->glyph));
-   FTUNLOCK();
-   if (error)
+   if (FT_HAS_COLOR(fi->src->ft.face))
      {
-        free(fg);
-        if (!fi->fash) fi->fash = _fash_gl_new();
-        if (fi->fash) _fash_gl_add(fi->fash, idx, (void *)(-1));
-        return NULL;
-     }
+        fg->advance.x = fi->src->ft.face->glyph->advance.x * 1024;
+        fg->advance.y = fi->src->ft.face->glyph->advance.y * 1024;
 
-     {
-        FT_BBox outbox;
-        FT_Glyph_Get_CBox(fg->glyph,
-              ((fi->hinting == 0) ? FT_GLYPH_BBOX_UNSCALED :
-               FT_GLYPH_BBOX_GRIDFIT),
-              &outbox);
-        fg->width = EVAS_FONT_ROUND_26_6_TO_INT(outbox.xMax - outbox.xMin);
-        fg->x_bear = EVAS_FONT_ROUND_26_6_TO_INT(outbox.xMin);
-        fg->y_bear = EVAS_FONT_ROUND_26_6_TO_INT(outbox.yMax);
+        FT_GlyphSlot slot = fi->src->ft.face->glyph;
+        fg->width = EVAS_FONT_ROUND_26_6_TO_INT(slot->metrics.width);
+        fg->x_bear = EVAS_FONT_ROUND_26_6_TO_INT(slot->metrics.horiBearingX);
+        fg->y_bear = EVAS_FONT_ROUND_26_6_TO_INT(slot->metrics.horiBearingY);
 
         if (FT_HAS_FIXED_SIZES(fi->src->ft.face))
           {
-             if (FT_HAS_COLOR(fi->src->ft.face) &&
-                 fi->bitmap_scalable & EFL_TEXT_FONT_BITMAP_SCALABLE_COLOR)
+             if (fi->bitmap_scalable & EFL_TEXT_FONT_BITMAP_SCALABLE_COLOR)
                {
-                  fg->glyph->advance.x *= fi->scale_factor;
-                  fg->glyph->advance.y *= fi->scale_factor;
+                  fg->advance.x *= fi->scale_factor;
+                  fg->advance.y *= fi->scale_factor;
                   fg->width *= fi->scale_factor;
                   fg->x_bear *= fi->scale_factor;
                   fg->y_bear *= fi->scale_factor;
                }
           }
      }
+   else
+     {
+        FTLOCK();
+        error = FT_Get_Glyph(fi->src->ft.face->glyph, &(fg->glyph));
+        FTUNLOCK();
+        if (error)
+          {
+             free(fg);
+             if (!fi->fash) fi->fash = _fash_gl_new();
+             if (fi->fash) _fash_gl_add(fi->fash, idx, (void *)(-1));
+             return NULL;
+          }
+        fg->advance.x = fg->glyph->advance.x;
+        fg->advance.y = fg->glyph->advance.y;
+
+        FT_BBox outbox;
+        FT_Glyph_Get_CBox(fg->glyph,
+              ((fi->hinting == 0) ? FT_GLYPH_BBOX_UNSCALED :
+              FT_GLYPH_BBOX_GRIDFIT),
+              &outbox);
+        fg->width = EVAS_FONT_ROUND_26_6_TO_INT(outbox.xMax - outbox.xMin);
+        fg->x_bear = EVAS_FONT_ROUND_26_6_TO_INT(outbox.xMin);
+        fg->y_bear = EVAS_FONT_ROUND_26_6_TO_INT(outbox.yMax);
+     }
 
    fg->index = idx;
    fg->fi = fi;
@@ -813,7 +865,7 @@ evas_common_font_int_cache_glyph_render(RGBA_Font_Glyph *fg)
    /* no cserve2 case */
    if (fg->glyph_out)
      return EINA_TRUE;
-
+   evas_font_glyph_load(fg);
    FTLOCK();
    error = FT_Glyph_To_Bitmap(&(fg->glyph), FT_RENDER_MODE_NORMAL, 0, 1);
    if (error)
diff --git a/src/lib/evas/common/evas_font_ot.c 
b/src/lib/evas/common/evas_font_ot.c
index 47c624c99a..275727d8be 100644
--- a/src/lib/evas/common/evas_font_ot.c
+++ b/src/lib/evas/common/evas_font_ot.c
@@ -188,7 +188,7 @@ _evas_common_font_ot_hb_get_glyph_advance(hb_font_t *font,
    fg = evas_common_font_int_cache_glyph_get(fi, glyph);
    if (fg)
      {
-        return fg->glyph->advance.x >> 10;
+        return fg->advance.x >> 10;
      }
    return 0;
 }
diff --git a/src/lib/evas/common/evas_text_utils.c 
b/src/lib/evas/common/evas_text_utils.c
index fc291a9536..b109e9b98a 100644
--- a/src/lib/evas/common/evas_text_utils.c
+++ b/src/lib/evas/common/evas_text_utils.c
@@ -1104,7 +1104,7 @@ _content_create_ot(RGBA_Font_Int *fi, const Eina_Unicode 
*text,
              if (is_replacement)
                {
                   /* Update the advance accordingly */
-                  adjust_x += (pen_x + (fg->glyph->advance.x >> 16)) -
+                  adjust_x += (pen_x + (fg->advance.x >> 16)) -
                      gl_itr->pen_after;
                }
              pen_x = gl_itr->pen_after;
@@ -1198,7 +1198,7 @@ _content_create_regular(RGBA_Font_Int *fi, const 
Eina_Unicode *text,
         gl_itr->index = idx;
         gl_itr->x_bear = fg->x_bear;
         gl_itr->y_bear = fg->y_bear;
-        adv = fg->glyph->advance.x >> 10;
+        adv = fg->advance.x >> 10;
         gl_itr->width = fg->width;
 
         if (EVAS_FONT_CHARACTER_IS_INVISIBLE(_gl))

-- 


Reply via email to