summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsubhransu mohanty <sub.mohanty@samsung.com>2017-10-27 09:11:02 +0900
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>2017-10-30 15:52:43 +0900
commiteb37ca333eb139acbd57b69444cc7118bde77796 (patch)
tree54cd777a49443514cefbb48d402c747b15fbea6e
parentca369f55d90def54ad62df9a993798c163be33a3 (diff)
downloadefl-eb37ca333eb139acbd57b69444cc7118bde77796.tar.gz
evas/vg: Added vg tree caching support
-rw-r--r--src/Makefile_Evas.am5
-rw-r--r--src/lib/evas/canvas/evas_main.c2
-rw-r--r--src/lib/evas/canvas/evas_vg_private.h43
-rw-r--r--src/lib/evas/vg/evas_vg_cache.c328
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--;
+}
+