jpeg pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=64231ae699858b34d65f6e27d665a1411ff1bcf0

commit 64231ae699858b34d65f6e27d665a1411ff1bcf0
Author: subhransu mohanty <sub.moha...@samsung.com>
Date:   Fri Oct 27 09:11:02 2017 +0900

    evas/vg: Added vg tree caching support
---
 src/Makefile_Evas.am                  |   5 +
 src/lib/evas/canvas/evas_main.c       |   2 +
 src/lib/evas/canvas/evas_vg_private.h |  43 ++++-
 src/lib/evas/vg/evas_vg_cache.c       | 328 ++++++++++++++++++++++++++++++++++
 4 files changed, 373 insertions(+), 5 deletions(-)

diff --git a/src/Makefile_Evas.am b/src/Makefile_Evas.am
index bc2c0abb1b..5657ed34b1 100644
--- a/src/Makefile_Evas.am
+++ b/src/Makefile_Evas.am
@@ -311,6 +311,11 @@ lib/evas/canvas/render2/evas_render2_th_main.c \
 lib/evas/canvas/render2/region.c \
 lib/evas/canvas/render2/region.h
 
+ # Vg
+ lib_evas_libevas_la_SOURCES += \
+ lib/evas/vg/evas_vg_cache.c
+
+
 # Cache
 lib_evas_libevas_la_SOURCES += \
 lib/evas/cache/evas_cache_image.c \
diff --git a/src/lib/evas/canvas/evas_main.c b/src/lib/evas/canvas/evas_main.c
index bcc2334ace..9efd0ca57d 100644
--- a/src/lib/evas/canvas/evas_main.c
+++ b/src/lib/evas/canvas/evas_main.c
@@ -84,6 +84,7 @@ evas_init(void)
 #endif
    _evas_preload_thread_init();
    evas_filter_init();
+   evas_cache_vg_init();
 
    if (!evas_thread_init())
      goto shutdown_filter;
@@ -146,6 +147,7 @@ evas_shutdown(void)
    if (evas_cserve2_use_get())
      evas_cserve2_shutdown();
 #endif
+   evas_cache_vg_shutdown();
 
    _efl_gfx_map_shutdown();
 
diff --git a/src/lib/evas/canvas/evas_vg_private.h 
b/src/lib/evas/canvas/evas_vg_private.h
index d3e151aba1..dda171bdad 100644
--- a/src/lib/evas/canvas/evas_vg_private.h
+++ b/src/lib/evas/canvas/evas_vg_private.h
@@ -3,18 +3,41 @@
 
 #include <Ector.h>
 
-typedef struct _Efl_VG_Data Efl_VG_Data;
-typedef struct _Efl_VG_Container_Data Efl_VG_Container_Data;
-typedef struct _Efl_VG_Gradient_Data Efl_VG_Gradient_Data;
-typedef struct _Efl_VG_Interpolation Efl_VG_Interpolation;
+typedef struct _Efl_VG_Data                  Efl_VG_Data;
+typedef struct _Efl_VG_Container_Data        Efl_VG_Container_Data;
+typedef struct _Efl_VG_Gradient_Data         Efl_VG_Gradient_Data;
+typedef struct _Efl_VG_Interpolation         Efl_VG_Interpolation;
 
-typedef struct _Efl_Canvas_Vg_Data      Efl_Canvas_Vg_Data;
+
+typedef struct _Efl_Canvas_Vg_Data           Efl_Canvas_Vg_Data;
+
+typedef struct _Evas_Cache_Vg_Entry          Evas_Cache_Vg_Entry;
+typedef struct _Evas_Cache_Vg                Evas_Cache_Vg;
+
+struct _Evas_Cache_Vg
+{
+   Eina_Hash             *vg_hash;
+   Eina_Hash             *active;
+   int                    ref;
+};
+
+struct _Evas_Cache_Vg_Entry
+{
+   char                 *hash_key;
+   Eina_Stringshare     *file;
+   Eina_Stringshare     *key;
+   int                   w;
+   int                   h;
+   Efl_VG               *root;
+   int                   ref;
+};
 
 struct _Efl_Canvas_Vg_Data
 {
    void                     *engine_data;
    Efl_VG                   *root;
    Efl_VG                   *vg_tree;
+   Evas_Cache_Vg_Entry      *vg_entry;
    Eina_Rect                 fill;
    Eina_Rect                 viewbox;
    unsigned int              width, height;
@@ -70,6 +93,16 @@ struct _Efl_VG_Interpolation
    Eina_Point_3D skew;
 };
 
+
+void                        evas_cache_vg_init(void);
+void                        evas_cache_vg_shutdown(void);
+Evas_Cache_Vg_Entry*        evas_cache_vg_entry_find(const char *file, const 
char *key, int w, int h);
+Efl_VG*                     evas_cache_vg_tree_get(Evas_Cache_Vg_Entry 
*svg_entry);
+void                        evas_cache_vg_entry_del(Evas_Cache_Vg_Entry 
*svg_entry);
+Vg_File_Data *              evas_cache_vg_file_info(const char *file, const 
char *key);
+
+Eina_Bool                   evas_vg_save_to_file(Vg_File_Data *evg_data, const 
char *file, const char *key, const char *flags);
+
 static inline Efl_VG_Data *
 _evas_vg_render_pre(Efl_VG *child, Ector_Surface *s, Eina_Matrix3 *m)
 {
diff --git a/src/lib/evas/vg/evas_vg_cache.c b/src/lib/evas/vg/evas_vg_cache.c
new file mode 100644
index 0000000000..dae36cc290
--- /dev/null
+++ b/src/lib/evas/vg/evas_vg_cache.c
@@ -0,0 +1,328 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "evas_common_private.h"
+#include "evas_private.h"
+#include "evas_vg_private.h"
+
+static Evas_Cache_Vg* vg_cache = NULL;
+
+struct ext_loader_s
+{
+   unsigned int length;
+   const char *extension;
+   const char *loader;
+};
+
+#define MATCHING(Ext, Module) { sizeof(Ext)-1, Ext, Module }
+
+static const struct ext_loader_s loaders[] =
+{ /* map extensions to loaders to use for good first-guess tries */
+   MATCHING(".eet", "eet"),
+   MATCHING(".edj", "eet"),
+   MATCHING(".svg", "svg"),
+   MATCHING(".svgz", "svg"),
+   MATCHING(".svg.gz", "svg")
+};
+
+static Evas_Module *
+_find_loader_module(const char *file)
+{
+   const char           *loader = NULL, *end;
+   Evas_Module          *em = NULL;
+   unsigned int          i;
+   int                   len, len2;
+   len = strlen(file);
+   end = file + len;
+   for (i = 0; i < (sizeof (loaders) / sizeof(struct ext_loader_s)); i++)
+     {
+        len2 = loaders[i].length;
+        if (len2 > len) continue;
+        if (!strcasecmp(end - len2, loaders[i].extension))
+          {
+             loader = loaders[i].loader;
+             break;
+          }
+     }
+   if (loader)
+     em = evas_module_find_type(EVAS_MODULE_TYPE_VG_LOADER, loader);
+   return em;
+}
+
+Vg_File_Data *
+_vg_load_from_file(const char *file, const char *key)
+{
+   Evas_Module       *em;
+   Evas_Vg_Load_Func *loader;
+   int                error = EVAS_LOAD_ERROR_GENERIC;
+   Vg_File_Data          *evg_data = NULL;
+
+   em = _find_loader_module(file);
+   if (em)
+     {
+        loader = em->functions;
+        evg_data = loader->file_data(file, key, &error);
+     }
+   return evg_data;
+}
+
+
+// evg file save
+struct ext_saver_s
+{
+   unsigned int length;
+   const char *extension;
+   const char *saver;
+};
+
+static const struct ext_saver_s savers[] =
+{ /* map extensions to savers to use for good first-guess tries */
+   MATCHING(".eet", "eet"),
+   MATCHING(".edj", "eet")
+};
+
+static Evas_Module *
+_find_saver_module(const char *file)
+{
+   const char           *saver = NULL, *end;
+   Evas_Module          *em = NULL;
+   unsigned int          i;
+   int                   len, len2;
+   len = strlen(file);
+   end = file + len;
+   for (i = 0; i < (sizeof (savers) / sizeof(struct ext_saver_s)); i++)
+     {
+        len2 = savers[i].length;
+        if (len2 > len) continue;
+        if (!strcasecmp(end - len2, savers[i].extension))
+          {
+             saver = savers[i].saver;
+             break;
+          }
+     }
+   if (saver)
+     em = evas_module_find_type(EVAS_MODULE_TYPE_VG_SAVER, saver);
+   return em;
+}
+
+Eina_Bool
+evas_vg_save_to_file(Vg_File_Data *evg_data, const char *file, const char 
*key, const char *flags)
+{
+   Evas_Module       *em;
+   Evas_Vg_Save_Func *saver;
+   int                error = EVAS_LOAD_ERROR_GENERIC;
+   int                compress = 9;
+
+   if (!file) return EINA_FALSE;
+
+   if (flags)
+     {
+        char *p, *pp;
+        char *tflags;
+
+        tflags = alloca(strlen(flags) + 1);
+        strcpy(tflags, flags);
+        p = tflags;
+        while (p)
+          {
+             pp = strchr(p, ' ');
+             if (pp) *pp = 0;
+             sscanf(p, "compress=%i", &compress);
+             if (pp) p = pp + 1;
+             else break;
+          }
+     }
+
+   em = _find_saver_module(file);
+   if (em)
+     {
+        saver = em->functions;
+        error = saver->vg_save(evg_data, file, key, compress);
+     }
+
+   if (error)
+     return EINA_FALSE;
+
+   return EINA_TRUE;
+}
+
+
+
+static void
+_evas_cache_vg_data_free_cb(void *data)
+{
+   Vg_File_Data *val = data;
+
+   efl_del(val->root);
+   free(val);
+}
+
+static void
+_evas_cache_svg_entry_free_cb(void *data)
+{
+   Evas_Cache_Vg_Entry *entry = data;
+
+   eina_stringshare_del(entry->file);
+   eina_stringshare_del(entry->key);
+   free(entry->hash_key);
+   efl_del(entry->root);
+   free(entry);
+}
+
+void
+evas_cache_vg_init(void)
+{
+   if (vg_cache)
+     {
+        vg_cache->ref++;
+        return;
+     }
+   vg_cache =  calloc(1, sizeof(Evas_Cache_Vg));
+   vg_cache->vg_hash = 
eina_hash_string_superfast_new(_evas_cache_vg_data_free_cb);
+   vg_cache->active = 
eina_hash_string_superfast_new(_evas_cache_svg_entry_free_cb);
+   vg_cache->ref++;
+}
+
+void
+evas_cache_vg_shutdown(void)
+{
+   if (!vg_cache) return;
+   vg_cache->ref--;
+   if (vg_cache->ref) return;
+   eina_hash_free(vg_cache->vg_hash);
+   eina_hash_free(vg_cache->active);
+   free(vg_cache);
+   vg_cache = NULL;
+}
+
+Vg_File_Data *
+evas_cache_vg_file_info(const char *file, const char *key)
+{
+   Vg_File_Data *vd;
+   Eina_Strbuf *hash_key;
+
+   hash_key = eina_strbuf_new();
+   eina_strbuf_append_printf(hash_key, "%s/%s", file, key);
+   vd = eina_hash_find(vg_cache->vg_hash, eina_strbuf_string_get(hash_key));
+   if (!vd)
+     {
+        vd = _vg_load_from_file(file, key);
+        eina_hash_add(vg_cache->vg_hash, eina_strbuf_string_get(hash_key), vd);
+     }
+   eina_strbuf_free(hash_key);
+   return vd;
+}
+
+static void
+_apply_transformation(Efl_VG *root, double w, double h, Vg_File_Data *vg_data)
+{
+   double sx = 0, sy= 0, scale;
+   Eina_Matrix3 m;
+
+   if (vg_data->view_box.w)
+     sx = w/vg_data->view_box.w;
+   if (vg_data->view_box.h)
+     sy = h/vg_data->view_box.h;
+   scale = sx < sy ? sx: sy;
+   eina_matrix3_identity(&m);
+   // allign hcenter and vcenter
+   if (vg_data->preserve_aspect)
+     {
+        eina_matrix3_translate(&m, (w - vg_data->view_box.w * scale)/2.0, (h - 
vg_data->view_box.h * scale)/2.0);
+        eina_matrix3_scale(&m, scale, scale);
+        eina_matrix3_translate(&m, -vg_data->view_box.x, -vg_data->view_box.y);
+     }
+   else
+     {
+        eina_matrix3_scale(&m, sx, sy);
+        eina_matrix3_translate(&m, -vg_data->view_box.x, -vg_data->view_box.y);
+     }
+   evas_vg_node_transformation_set(root, &m);
+}
+
+static Efl_VG *
+_evas_vg_dup_vg_tree(Vg_File_Data *fd, double w, double h)
+{
+
+   Efl_VG *root;
+
+   if (!fd) return NULL;
+   if ( !w || !h ) return NULL;
+
+   root = evas_vg_container_add(NULL);
+   evas_vg_node_dup(root, fd->root);
+   _apply_transformation(root, w, h, fd);
+
+   return root;
+}
+
+static void
+_evas_cache_svg_vg_tree_update(Evas_Cache_Vg_Entry *entry)
+{
+   Vg_File_Data *src_vg = NULL;
+   if(!entry) return;
+
+   if (!entry->file)
+     {
+        entry->root = NULL;
+        return;
+     }
+
+   src_vg = evas_cache_vg_file_info(entry->file, entry->key);
+
+   entry->root = _evas_vg_dup_vg_tree(src_vg, entry->w, entry->h);
+   eina_stringshare_del(entry->file);
+   eina_stringshare_del(entry->key);
+   entry->file = NULL;
+   entry->key = NULL;
+}
+
+Evas_Cache_Vg_Entry*
+evas_cache_vg_entry_find(const char *file, const char *key,
+                         int w, int h)
+{
+   Evas_Cache_Vg_Entry* se;
+   Eina_Strbuf *hash_key;
+
+   if (!vg_cache) return NULL;
+
+   hash_key = eina_strbuf_new();
+   eina_strbuf_append_printf(hash_key, "%s/%s/%d/%d",
+                             file, key, w, h);
+   se = eina_hash_find(vg_cache->active, eina_strbuf_string_get(hash_key));
+   if (!se)
+     {
+        se = calloc(1, sizeof(Evas_Cache_Vg_Entry));
+        se->file = eina_stringshare_add(file);
+        se->key = eina_stringshare_add(key);
+        se->w = w;
+        se->h = h;
+        se->hash_key = eina_strbuf_string_steal(hash_key);
+        eina_hash_direct_add(vg_cache->active, se->hash_key, se);
+     }
+   eina_strbuf_free(hash_key);
+   se->ref++;
+   return se;
+}
+
+Efl_VG*
+evas_cache_vg_tree_get(Evas_Cache_Vg_Entry *entry)
+{
+   if (entry->root) return entry->root;
+
+   if (entry->file)
+     {
+        _evas_cache_svg_vg_tree_update(entry);
+     }
+   return entry->root;
+}
+
+void
+evas_cache_vg_entry_del(Evas_Cache_Vg_Entry *svg_entry)
+{
+   if (!svg_entry) return;
+
+   svg_entry->ref--;
+}
+

-- 


Reply via email to