raster pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=54850ccd2f630b1397a4268088ba53b3305ffcb7

commit 54850ccd2f630b1397a4268088ba53b3305ffcb7
Author: Ali Alzyod <ali198...@gmail.com>
Date:   Fri Jul 24 10:36:27 2020 +0100

    evas: font glyphs texture garbage collector
    
    Summary:
    Introduce two public APIS
    ```
    #define EVAS_FONT_DATA_CACHE_TEXTURE 0x01
    
    /**
     * Set the limit in bytes for memory allocated by font glyphs in evas.
     * @param[in] bytes cache size in bytes, pass negative value to ignore the 
limit.
     * @param[in] options for caching, pass 0x1 to set the texture cache (in 
case of accelerated rendering).
     *
     * @since 1.24
     */
    EAPI void                    evas_font_data_cache_set(signed long long int 
byte, int options);
    
    /**
     * @}
     */
    
    /**
     * Get the limit in bytes for memory allocated by font glyphs in evas.
     * @param[in] options for caching, pass 0x1 to get the texture cache (in 
case of accelerated rendering).
     * @return Returns font allocated memory cache limit, if value is negative 
this means no limit.
     * @since 1.24
     */
    EAPI signed long long int    evas_font_data_cache_get(int options);
    ```
    
    Test Plan:
    elementary_test => Text Memory
    You need a tool to observe Video memory allocation.
    1- If you have detected Graphics card then use **radiontop** or  
**nvidia-smi** ).
    2- If you have Integrated Graphics card, then you can detect memory 
allocation on RAM use.
    
    ----------------------------------------------
    
    this example allows only 50 MByte Video memory texture allocated by font 
glyphs
    ```
    #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 = 200;
    
    int counter = 0;
    void _button_clicked(void *data, Evas_Object *obj, void *event_info)
    {
       APP *app = data;
    
      font_size -= 5;
      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);
    
      evas_font_data_cache_set(50 * 1024* 1024, EVAS_FONT_DATA_CACHE_TEXTURE );
    
      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, zmike, cedric, bu5hm4n, Hermet
    
    Subscribers: cedric, #reviewers, #committers
    
    Tags: #efl
    
    Maniphest Tasks: T8737
    
    Differential Revision: https://phab.enlightenment.org/D11943
---
 src/bin/elementary/test.c                          |   2 +
 src/bin/elementary/test_label.c                    | 118 +++++++++++++++++++++
 src/lib/evas/Evas_Common.h                         |  33 ++++++
 src/lib/evas/canvas/evas_render.c                  |   5 +
 src/lib/evas/common/evas_font_main.c               |  22 +++-
 src/lib/evas/include/evas_common_private.h         |   1 +
 src/lib/evas/include/evas_private.h                |   2 +
 .../evas/engines/gl_common/evas_gl_common.h        |   3 +
 src/modules/evas/engines/gl_common/evas_gl_font.c  |  26 ++++-
 .../evas/engines/gl_common/evas_gl_texture.c       |   5 +
 src/modules/evas/engines/gl_generic/evas_engine.c  |  37 +++++++
 .../evas/engines/software_generic/evas_engine.c    |   7 ++
 12 files changed, 259 insertions(+), 2 deletions(-)

diff --git a/src/bin/elementary/test.c b/src/bin/elementary/test.c
index 1acf333dcf..d0d374ece4 100644
--- a/src/bin/elementary/test.c
+++ b/src/bin/elementary/test.c
@@ -241,6 +241,7 @@ void test_label(void *data, Evas_Object *obj, void 
*event_info);
 void test_label_slide(void *data, Evas_Object *obj, void *event_info);
 void test_label_wrap(void *data, Evas_Object *obj, void *event_info);
 void test_textblock_fit(void *data, Evas_Object *obj, void *event_info);
+void test_text_memory(void *data, Evas_Object *obj, void *event_info);
 void test_label_ellipsis(void *data, Evas_Object *obj, void *event_info);
 void test_label_colors(void *data, Evas_Object *obj, void *event_info);
 void test_label_emoji(void *data, Evas_Object *obj, void *event_info);
@@ -1220,6 +1221,7 @@ add_tests:
    ADD_TEST(NULL, "Text", "Label Slide", test_label_slide);
    ADD_TEST(NULL, "Text", "Label Wrap", test_label_wrap);
    ADD_TEST(NULL, "Text", "Textblock Fit", test_textblock_fit);
+   ADD_TEST(NULL, "Text", "Text Memory", test_text_memory);
    ADD_TEST(NULL, "Text", "Label Ellipsis", test_label_ellipsis);
    ADD_TEST(NULL, "Text", "Label Colors", test_label_colors);
    ADD_TEST(NULL, "Text", "Label Emoji", test_label_emoji);
diff --git a/src/bin/elementary/test_label.c b/src/bin/elementary/test_label.c
index 414058d9ad..d8d1a80698 100644
--- a/src/bin/elementary/test_label.c
+++ b/src/bin/elementary/test_label.c
@@ -543,6 +543,124 @@ test_textblock_fit(void *data EINA_UNUSED, Evas_Object 
*obj EINA_UNUSED, void *e
    evas_object_show(app->win);
 }
 
+/*** Text Memory Configuration 
**************************************************************/
+enum BUTTON_MEM{
+   BUTTON_MEM_SET_TEXT         = 0,
+   BUTTON_MEM_APPLY_MEM        = 1,
+   BUTTON_MEM_APPLY_FONT_SIZE  = 2,
+   BUTTON_MEM_ALL              = BUTTON_MEM_APPLY_FONT_SIZE+1,
+};
+
+char* BUTTON_MEM_STR[BUTTON_MEM_ALL] ={
+   "Load Emojis Text",
+   "Memory Limit(MB)",
+   "Font Size"
+};
+
+char *content = 
"<align=center>๐Ÿ˜€๐Ÿ˜๐Ÿ˜‚๐Ÿคฃ๐Ÿ˜ƒ๐Ÿ˜„๐Ÿ˜…๐Ÿ˜†๐Ÿ˜‰๐Ÿ˜Š๐Ÿ˜‹๐Ÿ˜Ž๐Ÿ˜๐Ÿ˜˜๐Ÿ˜—๐Ÿ˜™๐Ÿ˜šโ˜บ๐Ÿ™‚๐Ÿค—๐Ÿค”๐Ÿ˜๐Ÿ˜‘๐Ÿ˜ถ๐Ÿ™„๐Ÿ˜๐Ÿ˜ฃ๐Ÿ˜ฅ๐Ÿ˜ฎ๐Ÿค๐Ÿ˜ฏ๐Ÿ˜ช๐Ÿ˜ซ๐Ÿ˜ด๐Ÿ˜Œ๐Ÿค“๐Ÿ˜›๐Ÿ˜œ๐Ÿ˜๐Ÿคค๐Ÿ˜’๐Ÿ˜“๐Ÿ˜”๐Ÿ˜•๐Ÿ™ƒ๐Ÿค‘๐Ÿ˜ฒโ˜น๐Ÿ™๐Ÿ˜–๐Ÿ˜ž๐Ÿ˜Ÿ๐Ÿ˜ค๐Ÿ˜ข๐Ÿ˜ญ๐Ÿ˜ฆ๐Ÿ˜ง๐Ÿ˜จ๐Ÿ˜ฉ๐Ÿ˜ฌ๐Ÿ˜ฐ๐Ÿ˜ฑ๐Ÿ˜ณ๐Ÿ˜ต๐Ÿ˜ก๐Ÿ˜ ๐Ÿ˜‡๐Ÿค ๐Ÿคก๐Ÿคฅ๐Ÿ˜ท๐Ÿค’๐Ÿค•๐Ÿคข๐Ÿคงโ˜ป๐Ÿ˜ˆ๐Ÿ‘ฟ๐Ÿ‘น๐Ÿ‘บ๐Ÿ’€โ˜ ๐Ÿ‘ป๐Ÿ‘ฝ๐Ÿ‘พ๐Ÿค–๐Ÿ’ฉ๐Ÿ˜บ๐Ÿ˜ธ๐Ÿ˜น๐Ÿ˜ป๐Ÿ˜ผ๐Ÿ˜ฝ๐Ÿ™€๐Ÿ˜ฟ๐Ÿ˜พ๐Ÿ™ˆ๐Ÿ™‰๐Ÿ™Š๐Ÿ‘ฆ๐Ÿ‘ง๐Ÿ‘จ๐Ÿ‘ฉ๐Ÿ‘ต๐Ÿ‘ถ๐Ÿ‘ผ๐Ÿ‘จโ€โš•๏ธ๐Ÿ‘ฉโ€โš•๏ธ๐Ÿ‘จโ€๐ŸŽ“๐Ÿ‘ฉโ€๐ŸŽ“๐Ÿ‘จโ€๐Ÿซ๐Ÿ‘ฉโ€๐Ÿซ๐Ÿ‘จโ€โš–๐Ÿ‘ฉโ€โš–๐Ÿ‘จโ€๐ŸŒพ๐Ÿ‘ฉโ€๐ŸŒพ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘ฉโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿ”ง๐Ÿ‘ฉโ€๐Ÿ”ง๐Ÿ‘จโ€๐Ÿญ๐Ÿ‘ฉโ€๐Ÿญ๐Ÿ‘จโ€๐Ÿ’ผ๐Ÿ‘ฉโ€๐Ÿ’ผ๐Ÿ‘จโ€๐Ÿ”ฌ๐Ÿ‘ฉโ€๐Ÿ”ฌ๐Ÿ‘จโ€๐Ÿ’ป๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐ŸŽค๐Ÿ‘ฉโ€๐ŸŽค๐Ÿ‘จโ€๐ŸŽจ๐Ÿ‘ฉโ€๐ŸŽจ๐Ÿ‘จโ€โœˆ๏ธ๐Ÿ‘ฉโ€โœˆ๏ธ๐Ÿ‘จโ€๐Ÿš€๐Ÿ‘ฉโ€๐Ÿš€๐Ÿ‘จโ€๐Ÿš’๐Ÿ‘ฉโ€๐Ÿš’๐Ÿ‘ฎโ€โ™‚๏ธ๐Ÿ‘ฎโ€โ™€๏ธ๐Ÿ•ต๏ธโ€โ™‚๏ธ๐Ÿ•ต๏ธโ€โ™€๏ธ๐Ÿ’‚โ€โ™‚๏ธ๐Ÿ’‚โ€โ™€๏ธ๐Ÿ‘ทโ€โ™‚๏ธ๐Ÿ‘ทโ€โ™€๏ธ๐Ÿ‘ณโ€โ™‚๏ธ๐Ÿ‘ณโ€โ™€๏ธ๐Ÿ‘ฑโ€โ™‚๏ธ๐Ÿ‘ฑโ€โ™€๏ธ๐ŸŽ…๐Ÿคถ๐Ÿ‘ธ๐Ÿคด๐Ÿ‘ฐ๐Ÿคต๐Ÿคฐ๐Ÿ‘ฒ๐Ÿ™โ€โ™‚๏ธ๐Ÿ™โ€โ™€๏ธ๐Ÿ™Žโ€โ™‚๏ธ๐Ÿ™Žโ€โ™€๏ธ๐Ÿ™…โ€โ™‚๏ธ๐Ÿ™…โ€โ™€๏ธ๐Ÿ™†โ€โ™‚๏ธ๐Ÿ™†โ€โ™€๏ธ๐Ÿ’โ€โ™‚๏ธ๐Ÿ’โ€โ™€๏ธ๐Ÿ™‹โ€โ™‚๏ธ๐Ÿ™‹โ€โ™€๏ธ๐Ÿ™‡โ€โ™‚๏ธ๐Ÿ™‡โ€โ™€๏ธ๐Ÿคฆโ€โ™‚๏ธ๐Ÿคฆโ€โ™€๏ธ๐Ÿคทโ€โ™‚๏ธ๐Ÿคทโ€โ™€๏ธ๐Ÿ’†โ€โ™‚๏ธ๐Ÿ’†โ€โ™€๏ธ๐Ÿ’‡โ€โ™‚๏ธ๐Ÿ’‡โ€โ™€๏ธ๐Ÿšถโ€โ™‚๏ธ๐Ÿšถโ€โ™€๏ธ๐Ÿƒโ€โ™‚๏ธ๐Ÿƒโ€โ™€๏ธ๐Ÿ’ƒ๐Ÿ•บ๐Ÿ‘ฏโ€โ™‚๏ธ๐Ÿ‘ฏโ€โ™€๏ธ๐Ÿ•ด๐Ÿ—ฃ๐Ÿ‘ค๐Ÿ‘ฅ๐Ÿ‘ซ๐Ÿ‘ฌ๐Ÿ‘ญ๐Ÿ’๐Ÿ’‘๐Ÿ‘ช๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ง๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ง๐Ÿ‘จโ€๐Ÿ‘ฆ๐Ÿ‘จโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ๐Ÿ‘จโ€๐Ÿ‘ง๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ฆ๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ง๐Ÿ‘ฉโ€๐Ÿ‘ฆ๐Ÿ‘ฉโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ๐Ÿ‘ฉโ€๐Ÿ‘ง๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ง๐Ÿ’ช๐Ÿคณ๐Ÿ‘ˆ๐Ÿ‘‰โ˜
 [...]
+
+typedef struct _APP_MEM
+{
+   Evas_Object *win, *box, *main_entry;
+   Eo *btn[BUTTON_MEM_ALL];
+   Eo *entry[BUTTON_MEM_ALL];
+} APP_MEM;
+APP_MEM *app_mem;
+
+static void _btn_clicked_mem(void *data EINA_UNUSED, Eo *obj, void *eventInfo 
EINA_UNUSED){
+   if (obj == app_mem->btn[BUTTON_MEM_SET_TEXT])
+     {
+        elm_object_text_set(app_mem->main_entry, content);
+     }
+   else if (obj == app_mem->btn[BUTTON_MEM_APPLY_MEM])
+     {
+        int size = 
atoi(elm_object_text_get(app_mem->entry[BUTTON_MEM_APPLY_MEM]));
+        if (size > 0 && size < 4000)
+          {
+            evas_font_data_cache_set(EVAS_FONT_DATA_CACHE_TEXTURE, size * 1024 
* 1024);
+          }
+        else
+          {
+             elm_object_text_set(app_mem->entry[BUTTON_MEM_APPLY_MEM], "NAN");
+          }
+     }
+   else if (obj == app_mem->btn[BUTTON_MEM_APPLY_FONT_SIZE])
+     {
+        int font_size = 
atoi(elm_object_text_get(app_mem->entry[BUTTON_MEM_APPLY_FONT_SIZE]));
+        if (font_size > 0 && font_size < 1000)
+          {
+            char sfont_size[256] = {0};
+            sprintf(sfont_size,"DEFAULT='font_size=%i'", font_size);
+            elm_entry_text_style_user_push(app_mem->main_entry, sfont_size);
+          }
+        else
+          {
+             elm_object_text_set(app_mem->entry[BUTTON_MEM_APPLY_FONT_SIZE], 
"NAN");
+          }
+     }
+}
+
+void
+test_text_memory(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void 
*event_info EINA_UNUSED)
+{
+  app_mem = calloc(sizeof(APP), 1);
+
+   elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
+
+   app_mem->win = elm_win_util_standard_add("Main", "App");
+   elm_win_autodel_set(app_mem->win, EINA_TRUE);
+
+   app_mem->box = elm_box_add(app_mem->win);
+   app_mem->main_entry = elm_entry_add(app_mem->box);
+
+   evas_object_size_hint_weight_set(app_mem->box, EVAS_HINT_EXPAND, 
EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(app_mem->box, EVAS_HINT_FILL, 
EVAS_HINT_FILL);
+
+   app_mem->btn[BUTTON_MEM_SET_TEXT] = elm_button_add(app_mem->box);
+   evas_object_smart_callback_add(app_mem->btn[BUTTON_MEM_SET_TEXT], 
"clicked", _btn_clicked_mem, NULL);
+   elm_object_text_set(app_mem->btn[BUTTON_MEM_SET_TEXT], 
BUTTON_MEM_STR[BUTTON_MEM_SET_TEXT]);
+   evas_object_size_hint_align_set(app_mem->btn[BUTTON_MEM_SET_TEXT], 
EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(app_mem->box, app_mem->btn[BUTTON_MEM_SET_TEXT]);
+   evas_object_show(app_mem->btn[BUTTON_MEM_SET_TEXT]);
+
+   elm_entry_scrollable_set(app_mem->main_entry, EINA_TRUE);
+   evas_object_show(app_mem->main_entry);
+   evas_object_show(app_mem->box);
+
+   elm_box_pack_end(app_mem->box, app_mem->main_entry);
+   evas_object_smart_callback_add(app_mem->btn[BUTTON_MEM_SET_TEXT], 
"clicked", _btn_clicked_mem, NULL);
+   evas_object_show(app_mem->btn[BUTTON_MEM_SET_TEXT]);
+
+   elm_win_resize_object_add(app_mem->win, app_mem->box);
+   evas_object_resize(app_mem->win, 320, 320);
+
+   elm_entry_text_style_user_push(app_mem->main_entry, 
"DEFAULT='font_size=20'");
+
+   for(int i = BUTTON_MEM_APPLY_MEM ; i < BUTTON_MEM_ALL ; i++)
+     {
+        app_mem->btn[i] = elm_button_add(app_mem->box);
+        app_mem->entry[i] = elm_entry_add(app_mem->box);
+        evas_object_smart_callback_add(app_mem->btn[i], "clicked", 
_btn_clicked_mem, NULL);
+        elm_object_text_set(app_mem->btn[i], BUTTON_MEM_STR[i]);
+        elm_box_pack_end(app_mem->box, app_mem->btn[i]);
+        elm_box_pack_end(app_mem->box, app_mem->entry[i]);
+
+        evas_object_size_hint_align_set(app_mem->btn[i], EVAS_HINT_FILL, 
EVAS_HINT_FILL);
+        evas_object_size_hint_align_set(app_mem->entry[i], EVAS_HINT_FILL, 
EVAS_HINT_FILL);
+
+        evas_object_show(app_mem->btn[i]);
+        evas_object_show(app_mem->entry[i]);
+     }
+
+   elm_object_text_set(app_mem->entry[BUTTON_MEM_APPLY_MEM],"Texture limit in 
MB");
+   elm_object_text_set(app_mem->entry[BUTTON_MEM_APPLY_FONT_SIZE],"20");
+
+   evas_object_size_hint_weight_set(app_mem->main_entry, 
EVAS_HINT_EXPAND,EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(app_mem->main_entry, EVAS_HINT_FILL, 
EVAS_HINT_FILL);
+
+   evas_object_show(app_mem->win);
+}
+
 /*** Label Wrap **************************************************************/
 void
 test_label_wrap(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void 
*event_info EINA_UNUSED)
diff --git a/src/lib/evas/Evas_Common.h b/src/lib/evas/Evas_Common.h
index 97a5e1adb4..e365eb9f0d 100644
--- a/src/lib/evas/Evas_Common.h
+++ b/src/lib/evas/Evas_Common.h
@@ -385,6 +385,12 @@ typedef Efl_Text_Bidirectional_Type Evas_BiDi_Direction;
 #define EVAS_BIDI_DIRECTION_RTL     EFL_TEXT_BIDIRECTIONAL_TYPE_RTL
 #define EVAS_BIDI_DIRECTION_INHERIT EFL_TEXT_BIDIRECTIONAL_TYPE_INHERIT
 
+typedef enum _Evas_Font_Data_Cache
+{
+   EVAS_FONT_DATA_CACHE_TEXTURE = 0x01,/**< Texture caching (in case of 
accelerated rendering) */
+} Evas_Font_Data_Cache; /**< font caching options, used for 
evas_font_data_cache_set()/evas_font_data_cache_get()*/
+
+
 /**
  * How the mouse pointer should be handled by Evas.
  *
@@ -3370,6 +3376,33 @@ EAPI const Eina_List        
*evas_font_path_global_list(void) EINA_WARN_UNUSED_R
  */
 EAPI void                    evas_font_reinit(void);
 
+/**
+ * @}
+ */
+
+#define EVAS_FONT_DATA_CACHE_TEXTURE 0x01
+
+/**
+ * Set the limit in bytes for memory allocated by font glyphs in evas.
+ * @param[in] options for caching.
+ * @param[in] bytes cache size in bytes, pass negative value to ignore the 
limit.
+ *
+ * @since 1.24
+ */
+EAPI void                    evas_font_data_cache_set(Evas_Font_Data_Cache 
options, int byte);
+
+/**
+ * @}
+ */
+
+/**
+ * Get the limit in bytes for memory allocated by font glyphs in evas.
+ * @param[in] options for caching.
+ * @return Returns font allocated memory cache limit, if value is negative 
this means no limit.
+ * @since 1.24
+ */
+EAPI int    evas_font_data_cache_get(Evas_Font_Data_Cache options);
+
 /**
  * @}
  */
diff --git a/src/lib/evas/canvas/evas_render.c 
b/src/lib/evas/canvas/evas_render.c
index c33f69a22d..cac56d1757 100644
--- a/src/lib/evas/canvas/evas_render.c
+++ b/src/lib/evas/canvas/evas_render.c
@@ -3713,6 +3713,11 @@ evas_render_updates_internal(Evas *eo_e,
      }
    eina_evlog("-render_phase8", eo_e, 0.0, NULL);
 
+   if (evas_font_data_cache_get(EVAS_FONT_DATA_CACHE_TEXTURE) == 0)
+      ENFN->font_glyphs_gc_collect(ENC, 1.0f, NULL, NULL, EINA_TRUE);
+   else
+      ENFN->font_glyphs_gc_collect(ENC, 0.33f, NULL, NULL, EINA_TRUE);
+
    eina_evlog("+render_clear", eo_e, 0.0, NULL);
    if (!do_async && rendering)
      {
diff --git a/src/lib/evas/common/evas_font_main.c 
b/src/lib/evas/common/evas_font_main.c
index 3a5b280437..50de0819bc 100644
--- a/src/lib/evas/common/evas_font_main.c
+++ b/src/lib/evas/common/evas_font_main.c
@@ -13,7 +13,8 @@ LK(lock_font_draw); // for freetype2 API calls
 LK(lock_bidi); // for evas bidi internal usage.
 LK(lock_ot); // for evas bidi internal usage.
 
-int _evas_font_log_dom_global = -1;
+int             _evas_font_log_dom_global = -1;
+int             _evas_font_texture_cache = -1;
 
 EAPI void
 evas_common_font_init(void)
@@ -854,6 +855,25 @@ evas_common_font_int_cache_glyph_get(RGBA_Font_Int *fi, 
FT_UInt idx)
    return fg;
 }
 
+EAPI void
+evas_font_data_cache_set(Evas_Font_Data_Cache options, int bytes)
+{
+   if ((options & EVAS_FONT_DATA_CACHE_TEXTURE) == 
EVAS_FONT_DATA_CACHE_TEXTURE)
+     {
+        _evas_font_texture_cache = bytes;
+        //FIXME No direct free happend until next render call
+     }
+}
+
+EAPI int
+evas_font_data_cache_get(Evas_Font_Data_Cache options)
+{
+   if ((options & EVAS_FONT_DATA_CACHE_TEXTURE) == 
EVAS_FONT_DATA_CACHE_TEXTURE)
+     return _evas_font_texture_cache;
+   else
+     return -1;
+}
+
 EAPI Eina_Bool
 evas_common_font_int_cache_glyph_render(RGBA_Font_Glyph *fg)
 {
diff --git a/src/lib/evas/include/evas_common_private.h 
b/src/lib/evas/include/evas_common_private.h
index 509f7c93a8..e4a5168bdb 100644
--- a/src/lib/evas/include/evas_common_private.h
+++ b/src/lib/evas/include/evas_common_private.h
@@ -691,6 +691,7 @@ struct _RGBA_Draw_Context
          void *(*gl_image_new) (void *gc, RGBA_Font_Glyph *fg, int alpha, 
Evas_Colorspace cspace);
          void  (*gl_image_free) (void *image);
          void  (*gl_image_draw) (void *gc, void *im, int dx, int dy, int dw, 
int dh, int smooth);
+         void  (*gl_garbage_collector) (void *gc, float ratio, int 
*texture_size, int *atlas_size);
       } func;
       void *data;
    } font_ext;
diff --git a/src/lib/evas/include/evas_private.h 
b/src/lib/evas/include/evas_private.h
index 147e2ae0d1..d270b2be65 100644
--- a/src/lib/evas/include/evas_private.h
+++ b/src/lib/evas/include/evas_private.h
@@ -1103,6 +1103,8 @@ struct _Evas_Func
    Evas_Filter_Support (*gfx_filter_supports) (void *engine, 
Evas_Filter_Command *cmd);
    Eina_Bool (*gfx_filter_process)       (void *engine, Evas_Filter_Command 
*cmd);
 
+   void (*font_glyphs_gc_collect)   (void *engine, float ratio, int 
*texture_size, int *atlas_size, Eina_Bool only_when_requested);
+
    unsigned int info_size;
 };
 
diff --git a/src/modules/evas/engines/gl_common/evas_gl_common.h 
b/src/modules/evas/engines/gl_common/evas_gl_common.h
index 5873b93fb6..c7b4d22150 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_common.h
+++ b/src/modules/evas/engines/gl_common/evas_gl_common.h
@@ -368,6 +368,9 @@ struct _Evas_Engine_GL_Context
    Eina_List     *font_glyph_images;
    Evas_GL_Image *def_surface;
    RGBA_Image    *font_surface;
+   int            font_glyph_textures_size;
+   int            font_glyph_atlas_size;
+   Eina_Bool      font_glyph_gc_requested    :1;
 
 #ifdef GL_GLES
    // FIXME: hack. expose egl display to gl core for egl image sec extn.
diff --git a/src/modules/evas/engines/gl_common/evas_gl_font.c 
b/src/modules/evas/engines/gl_common/evas_gl_font.c
index 53260d971d..4a5f428487 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_font.c
+++ b/src/modules/evas/engines/gl_common/evas_gl_font.c
@@ -218,13 +218,37 @@ void
 evas_gl_font_image_draw(void *gc, void *gl_image, int dx, int dy, int dw, int 
dh, int smooth)
 {
    Evas_GL_Image *im = (Evas_GL_Image *)gl_image;
+   Evas_Engine_GL_Context *gl_context = gc;
+   Eina_Bool is_cached = EINA_FALSE;
+   Eina_Bool is_new_atlas = EINA_FALSE;
 
    if (!im || !im->fglyph) return;
 
-   evas_gl_common_image_draw((Evas_Engine_GL_Context *)gc,
+   is_cached = (im->tex != NULL) && (im->tex->pt != NULL);
+
+   evas_gl_common_image_draw(gl_context,
                              im, 0, 0,
                              (unsigned int)im->fglyph->glyph_out->bitmap.width,
                              (unsigned int)im->fglyph->glyph_out->bitmap.rows,
                              dx, dy, dw, dh,
                              smooth);
+
+   // Move latest used glyph image to the back, because GC will start freeing 
from the beginning
+   gl_context->font_glyph_images = 
eina_list_remove(gl_context->font_glyph_images, im);
+   gl_context->font_glyph_images = 
eina_list_append(gl_context->font_glyph_images, im);
+
+   if (!is_cached)
+     {
+        gl_context->font_glyph_textures_size += im->w * im->h * 4;
+     }
+
+   is_new_atlas = (!is_cached) && (im->tex != NULL) && (im->tex->pt) && 
(im->tex->pt->references == 1);
+   if (is_new_atlas)
+     {
+        int size = (im->tex->pt->w * im->tex->pt->h * 4);
+        gl_context->font_glyph_atlas_size += size;
+        if ((evas_font_data_cache_get(EVAS_FONT_DATA_CACHE_TEXTURE) >= 0) &&
+            (evas_font_data_cache_get(EVAS_FONT_DATA_CACHE_TEXTURE) * 0.95 < 
gl_context->font_glyph_atlas_size))
+          gl_context->font_glyph_gc_requested = EINA_TRUE;
+     }
 }
diff --git a/src/modules/evas/engines/gl_common/evas_gl_texture.c 
b/src/modules/evas/engines/gl_common/evas_gl_texture.c
index 1aa9d3ccb0..47dd8305a8 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_texture.c
+++ b/src/modules/evas/engines/gl_common/evas_gl_texture.c
@@ -1565,6 +1565,7 @@ evas_gl_common_texture_free(Evas_GL_Texture *tex, 
Eina_Bool force)
    if (tex->references != 0) return;
    if (tex->fglyph)
      {
+        tex->gc->font_glyph_textures_size -= tex->w * tex->h * 4;
         tex->gc->font_glyph_textures = 
eina_list_remove(tex->gc->font_glyph_textures, tex);
         tex->fglyph->ext_dat = NULL;
         tex->fglyph->ext_dat_free = NULL;
@@ -1575,6 +1576,10 @@ evas_gl_common_texture_free(Evas_GL_Texture *tex, 
Eina_Bool force)
         tex->pt->allocations = eina_list_remove(tex->pt->allocations, 
tex->apt);
         if (tex->apt) eina_rectangle_pool_release(tex->apt);
         tex->apt = NULL;
+        if (tex->fglyph && (tex->pt->references == 1))
+          {
+            tex->gc->font_glyph_atlas_size -= tex->pt->w * tex->pt->h * 4;
+          }
         pt_unref(tex->pt);
         tex->pt = NULL;
      }
diff --git a/src/modules/evas/engines/gl_generic/evas_engine.c 
b/src/modules/evas/engines/gl_generic/evas_engine.c
index 0fc241643d..a051f00242 100644
--- a/src/modules/evas/engines/gl_generic/evas_engine.c
+++ b/src/modules/evas/engines/gl_generic/evas_engine.c
@@ -3023,6 +3023,42 @@ eng_gfx_filter_process(void *engine, Evas_Filter_Command 
*cmd)
      return pfunc.gfx_filter_process(&re->software, cmd);
 }
 
+static void
+eng_font_glyphs_gc_collect(void *data EINA_UNUSED, float ratio EINA_UNUSED, 
int *texture_size EINA_UNUSED, int *atlas_size EINA_UNUSED, Eina_Bool 
only_when_requested EINA_UNUSED)
+{
+   Evas_Engine_GL_Context *gl_context;
+   gl_context = gl_generic_context_find(data, 1);
+
+   if ((only_when_requested && gl_context->font_glyph_gc_requested) || 
(!only_when_requested))
+     {
+        if (ratio > 0.0)
+          {
+             int requested_size = ratio * gl_context->font_glyph_textures_size;
+
+             Eina_List *l;
+             Eina_List *ll;
+             Evas_GL_Image *im;
+             EINA_LIST_FOREACH_SAFE(gl_context->font_glyph_images, l, ll, im)
+               {
+                  int size = im->w * im->h * 4;
+                  gl_context->font_glyph_textures_size -= size;
+                  requested_size -= size;
+                  if ((im->tex != NULL) && (im->tex->pt) && 
(im->tex->pt->references == 1))
+                    {
+                       gl_context->font_glyph_atlas_size -= im->tex->pt->w * 
im->tex->pt->h * 4;
+                    }
+                  evas_gl_common_image_free(im);
+                  if (requested_size <= 0)
+                    break;
+               }
+          }
+
+         gl_context->font_glyph_gc_requested = EINA_FALSE;
+     }
+   if (texture_size) *texture_size = gl_context->font_glyph_textures_size;
+   if (atlas_size) *atlas_size = gl_context->font_glyph_atlas_size;
+}
+
 //------------------------------------------------//
 
 static int
@@ -3178,6 +3214,7 @@ module_open(Evas_Module *em)
    ORD(ector_surface_cache_drop);
    ORD(gfx_filter_supports);
    ORD(gfx_filter_process);
+   ORD(font_glyphs_gc_collect);
 
    /* now advertise out own api */
    em->functions = (void *)(&func);
diff --git a/src/modules/evas/engines/software_generic/evas_engine.c 
b/src/modules/evas/engines/software_generic/evas_engine.c
index a942a96f02..aca24c4936 100644
--- a/src/modules/evas/engines/software_generic/evas_engine.c
+++ b/src/modules/evas/engines/software_generic/evas_engine.c
@@ -4645,6 +4645,12 @@ eng_gfx_filter_supports(void *data EINA_UNUSED, 
Evas_Filter_Command *cmd)
    return EVAS_FILTER_SUPPORT_CPU;
 }
 
+static void
+eng_font_glyphs_gc_collect(void *data EINA_UNUSED, float ratio EINA_UNUSED, 
int *texture_size EINA_UNUSED, int *atlas_size EINA_UNUSED, Eina_Bool 
only_when_requested EINA_UNUSED)
+{
+   return;
+}
+
 static Eina_Bool
 eng_gfx_filter_process(void *data EINA_UNUSED, Evas_Filter_Command *cmd)
 {
@@ -4851,6 +4857,7 @@ static Evas_Func func =
      eng_gfx_filter_supports,
      eng_gfx_filter_process,
    /* FUTURE software generic calls go here */
+     eng_font_glyphs_gc_collect,
      0 // sizeof (Info)
 };
 

-- 


Reply via email to