evas_vg refactoring: efl will use thorvg's SVG loader 83/257083/3
authorMichal Maciola <m.maciola@samsung.com>
Mon, 19 Apr 2021 08:17:51 +0000 (10:17 +0200)
committerChun <jykeon@samsung.com>
Tue, 27 Apr 2021 00:59:41 +0000 (00:59 +0000)
If file extension meets .svg, file will be loaded with thorvg.

Change-Id: I1eb25f912bd079a22f127587e614b3583a66986f

src/lib/evas/canvas/efl_canvas_vg_image.c
src/lib/evas/canvas/efl_canvas_vg_image.eo
src/lib/evas/include/evas_private.h
src/lib/evas/vg/evas_vg_cache.c

index e6c235a..ab005de 100644 (file)
@@ -86,24 +86,12 @@ _efl_canvas_vg_image_render_pre_tvg(EINA_UNUSED Evas_Object_Protected_Data *vg_p
    Tvg_Matrix trans_mat = { 0 };
 
    if (!nd || !nd->data) return;
-
    Efl_Canvas_Vg_Image_Data *pd = nd->data;
 
    if (nd->flags != EFL_GFX_CHANGE_FLAG_NONE)
      {
         nd->flags = EFL_GFX_CHANGE_FLAG_NONE;
 
-        if (!pd->picture && pd->image)
-          {
-             pd->picture = tvg_picture_new();
-             if (tvg_picture_load_raw(pd->picture, pd->image, pd->w, pd->h, true) != TVG_RESULT_SUCCESS)
-                {
-                   printf("Error loading image buffer \n");
-                   return;
-                }
-          }
-        if (!pd->picture) return;
-
         EFL_CANVAS_VG_COMPUTE_MATRIX(cTransform, pTransform, nd);
         tvg_paint_translate(pd->picture, nd->x, nd->y);
         if (cTransform)
@@ -139,6 +127,7 @@ _efl_canvas_vg_image_efl_object_constructor(Eo *obj, Efl_Canvas_Vg_Image_Data *p
    nd->render_pre = _efl_canvas_vg_image_render_pre;
 #else
    nd->render_pre_tvg = _efl_canvas_vg_image_render_pre_tvg;
+   pd->picture = tvg_picture_new();
 #endif
 
    efl_gfx_color_set(obj , 255, 255, 255, 255);
@@ -172,6 +161,15 @@ _efl_canvas_vg_image_data_set(Eo *obj EINA_UNUSED, Efl_Canvas_Vg_Image_Data *pd,
         efl_unref(pd->buffer);
         pd->buffer= NULL;
      }
+#else
+   if (pd->image != data || pd->w != size.w || pd->h != size.h)
+     {
+      if (!pd->picture || tvg_picture_load_raw(pd->picture, data, size.w, size.h, true) != TVG_RESULT_SUCCESS)
+        {
+           printf("Error loading image buffer \n");
+           return;
+        }
+     }
 #endif
 
    pd->image = data;
@@ -179,4 +177,57 @@ _efl_canvas_vg_image_data_set(Eo *obj EINA_UNUSED, Efl_Canvas_Vg_Image_Data *pd,
    pd->h = size.h;
 }
 
+// This function is HAVE_THORVG only
+static void
+_efl_canvas_vg_image_filepath_set(Eo *obj EINA_UNUSED, Efl_Canvas_Vg_Image_Data *pd, const char *path)
+{
+#ifdef HAVE_THORVG
+   if (!pd->picture || tvg_picture_load(pd->picture, path) != TVG_RESULT_SUCCESS)
+     {
+        printf("Error loading image from path \'%s\' \n", path);
+        return;
+     }
+#endif
+}
+
+// This function is HAVE_THORVG only
+static Eina_Rect
+_efl_canvas_vg_image_viewbox_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Vg_Image_Data *pd)
+{
+#ifdef HAVE_THORVG
+   float x, y, w, h;
+
+   if (!pd->picture || tvg_picture_get_viewbox(pd->picture, &x, &y, &w, &h) != TVG_RESULT_SUCCESS)
+      return EINA_RECT(0, 0, 0, 0);
+
+   return EINA_RECT(x, y, w, h);
+#endif
+}
+
+// This function is HAVE_THORVG only
+// Duplication is used on _root_update() for static_viewbox image
+EOLIAN static Efl_Canvas_Vg_Node *
+_efl_canvas_vg_image_efl_duplicate_duplicate(const Eo *obj, Efl_Canvas_Vg_Image_Data *pd)
+{
+#ifdef HAVE_THORVG
+   Efl_Canvas_Vg_Node *node = NULL;
+   Efl_Canvas_Vg_Image_Data *sd = NULL;
+
+   node = efl_duplicate(efl_super(obj, MY_CLASS));
+   sd = efl_data_scope_get(node, MY_CLASS);
+
+   if (pd->picture)
+      {
+         if (sd->picture) tvg_paint_del(sd->picture);
+         sd->picture = tvg_paint_duplicate(pd->picture);
+      }
+
+   sd->image = pd->image; // note: no memcpy here
+   sd->w = pd->w;
+   sd->h = pd->h;
+
+   return node;
+#endif
+}
+
 #include "efl_canvas_vg_image.eo.c"
index 05ea4b9..c9f43ba 100644 (file)
@@ -11,8 +11,25 @@ class @beta Efl.Canvas.Vg.Image extends Efl.Canvas.Vg.Node implements Efl.Gfx.Im
             size: Eina.Size2D; [[The size in pixels.]]
          }
       }
+      @property filepath {
+         [[Set path for file to be loaded]]
+         set {
+         }
+         values {
+            path: string; [[Path for image to be loaded]]
+         }
+      }
+      @property viewbox {
+         [[Get viewbox for loaded]]
+         get {
+         }
+         values {
+            r: Eina.Rect; [[The function returns viewbox coordinates and size for given paint: x y w h]]
+         }
+      }
    }
    implements {
+      Efl.Duplicate.duplicate;
       Efl.Object.constructor;
       Efl.Object.destructor;
    }
index ed4cbfa..6be9956 100755 (executable)
@@ -1160,6 +1160,10 @@ struct _Vg_File_Data
    Eina_Bool       preserve_aspect : 1;    //Used in SVG
 
    Eina_Bool       shareable: 1;
+
+#ifdef HAVE_THORVG
+   Eina_Bool       thorvg_loader: 1;
+#endif
 };
 
 struct _Evas_Vg_Load_Func
index 8ec385b..cff1f5a 100644 (file)
@@ -45,6 +45,44 @@ static const struct ext_saver_s savers[] =
    MATCHING(".svg", "svg")
 };
 
+#ifdef HAVE_THORVG
+struct ext_loader_thorvg_s
+{
+   unsigned int length;
+   const char *extension;
+};
+
+#define EXTENSION(Ext) { sizeof(Ext)-1, Ext }
+
+static const struct ext_loader_thorvg_s thorvg_extensions[] =
+{
+      EXTENSION(".svg")
+};
+
+static Eina_Bool
+_thorvg_loader_applicable(const char *file)
+{
+   if (!file) return EINA_FALSE;
+
+   const int len = strlen(file);
+   const char *end = file + len;
+   unsigned int i;
+   int len2;
+
+   for (i = 0; i < (sizeof (thorvg_extensions) / sizeof(struct ext_loader_thorvg_s)); i++)
+        {
+           len2 = thorvg_extensions[i].length;
+           if (len2 > len) continue;
+           if (!strcasecmp(end - len2, thorvg_extensions[i].extension))
+             {
+                return EINA_TRUE;
+             }
+        }
+   return EINA_FALSE;
+}
+#endif
+
+
 static Evas_Module *
 _find_loader_module(const char *file)
 {
@@ -79,6 +117,30 @@ _vg_load_from_file(const Eina_File *file, const char *key)
    unsigned int i;
 
    const char *file_name = eina_file_filename_get(file);
+
+#ifdef HAVE_THORVG
+   if (_thorvg_loader_applicable(file_name))
+     {
+        vfd = calloc(1, sizeof(Vg_File_Data));
+        EINA_SAFETY_ON_NULL_RETURN_VAL(vfd, NULL);
+
+        Efl_Canvas_Vg_Image *image = efl_add_ref(EFL_CANVAS_VG_IMAGE_CLASS, NULL);
+        efl_canvas_vg_image_filepath_set(image, file_name);
+        vfd->root = image;
+
+        Eina_Rect r = efl_canvas_vg_image_viewbox_get(image);
+        vfd->view_box.x = r.x;
+        vfd->view_box.y = r.y;
+        vfd->view_box.w = r.w;
+        vfd->view_box.h = r.h;
+
+        vfd->preserve_aspect = EINA_TRUE;
+        vfd->static_viewbox = EINA_TRUE;
+        vfd->thorvg_loader = EINA_TRUE;
+        return vfd;
+     }
+#endif
+
    em = _find_loader_module(file_name);
    if (em)
      {
@@ -139,7 +201,7 @@ static void
 _evas_cache_vg_data_free_cb(void *data)
 {
    Vg_File_Data *vfd = data;
-   vfd->loader->file_close(vfd);
+   if (vfd->loader) vfd->loader->file_close(vfd);
 }
 
 static void
@@ -166,7 +228,8 @@ _evas_cache_vg_entry_free_cb(void *data)
                }
              else
                {
-                  vg_entry->vfd->loader->file_close(vg_entry->vfd);
+                  if (vg_entry->vfd->loader)
+                     vg_entry->vfd->loader->file_close(vg_entry->vfd);
                }
           }
      }
@@ -541,7 +604,7 @@ evas_cache_vg_tree_get(Vg_Cache_Entry *vg_entry, unsigned int frame_num)
 
    if (vfd->anim_data) vfd->anim_data->frame_num = frame_num;
 
-   if (!vfd->loader->file_data(vfd)) return NULL;
+   if (vfd->loader && !vfd->loader->file_data(vfd)) return NULL;
 
    _root_update(vg_entry);