edje: cached the vg tree generation and fixed the interpolation betwwen two vg tree.
authorSubhransu Mohanty <sub.mohanty@samsung.com>
Thu, 9 Jun 2016 04:49:56 +0000 (13:49 +0900)
committerJean-Philippe Andre <jp.andre@samsung.com>
Thu, 9 Jun 2016 04:49:56 +0000 (13:49 +0900)
Reviewers: cedric, jpeg

Subscribers: cedric, jpeg

Differential Revision: https://phab.enlightenment.org/D4028

src/lib/edje/edje_calc.c
src/lib/edje/edje_load.c
src/lib/edje/edje_private.h

index 5b2f4ab..382e6d7 100644 (file)
@@ -3260,8 +3260,10 @@ _edje_svg_recalc_apply(Edje *ed, Edje_Real_Part *ep, Edje_Calc_Params *p3 EINA_U
 {
    int w, h;
    int new_svg = 0;
-   Efl_VG *vg_tree, *root_vg;
-   double sx, sy, vx, vy, vw, vh;
+   Efl_VG *root_vg;
+   double sx, sy;
+   Eina_Matrix3 matrix;
+   Edje_Vector_Data *start, *end;
 
    evas_object_geometry_get(ep->object, NULL, NULL, &w, &h);
 
@@ -3279,74 +3281,42 @@ _edje_svg_recalc_apply(Edje *ed, Edje_Real_Part *ep, Edje_Calc_Params *p3 EINA_U
      }
    if (new_svg) // animation with svg id change
      {
-        Efl_VG *container;
-        if (ep->typedata.vector->cache.svg_id != new_svg)
-          {
-             //create it
-             vg_tree = _edje_create_vg_tree(ed->file->ef, new_svg, w, h, &vx, &vy, &vw, &vh);
-             if (vg_tree)
-               {
-                  //1. clear the cache
-                  if (ep->typedata.vector->cache.vg)
-                    {
-                       eo_unref(ep->typedata.vector->cache.vg);
-                       ep->typedata.vector->cache.vg = NULL;
-                       ep->typedata.vector->cache.svg_id = 0;
-                    }
-                  //2. update current
-                  ep->typedata.vector->cache.svg_id = new_svg;
-                  ep->typedata.vector->cache.x = vx;
-                  ep->typedata.vector->cache.y = vy;
-                  ep->typedata.vector->cache.w = vw;
-                  ep->typedata.vector->cache.h = vh;
-                  ep->typedata.vector->cache.vg = vg_tree;
-               }
-          }
-        // just do the interpolation
-        if (eo_parent_get(ep->typedata.vector->cur.vg))
-          {
-             // remove it from the hirarchy
-             eo_ref(ep->typedata.vector->cur.vg);
-             eo_parent_set(ep->typedata.vector->cur.vg, NULL);
-          }
-        // create a container
-        container = evas_vg_container_add(NULL);
-        // reset the matrix.
-        Eina_Matrix3 matrix;
-        sx = w/ep->typedata.vector->cur.w;
-        sy = h/ep->typedata.vector->cur.h;
-        // for current vg
+        start = _edje_ref_vector_data(ed, chosen_desc->vg.id);
+        end = _edje_ref_vector_data(ed, new_svg);
+
+        // for start vector
+        sx = w/start->w;
+        sy = h/start->h;
         eina_matrix3_identity(&matrix);
-        eina_matrix3_translate(&matrix, -ep->typedata.vector->cur.x, -ep->typedata.vector->cur.y);
+        eina_matrix3_translate(&matrix, -start->x, -start->y);
         eina_matrix3_scale(&matrix, sx, sy);
-        evas_vg_node_transformation_set(ep->typedata.vector->cur.vg, &matrix);
-        // for next vg
-        sx = w/ep->typedata.vector->cache.w;
-        sy = h/ep->typedata.vector->cache.h;
+        evas_vg_node_transformation_set(start->vg, &matrix);
+
+        // for end vector
+        sx = w/end->w;
+        sy = h/end->h;
         eina_matrix3_identity(&matrix);
-        eina_matrix3_translate(&matrix, -ep->typedata.vector->cache.x, -ep->typedata.vector->cache.y);
+        eina_matrix3_translate(&matrix, -end->x, -end->y);
         eina_matrix3_scale(&matrix, sx, sy);
-        evas_vg_node_transformation_set(ep->typedata.vector->cache.vg, &matrix);
+        evas_vg_node_transformation_set(end->vg, &matrix);
+
         // do the interpolation
-        if (evas_vg_node_interpolate(container, ep->typedata.vector->cur.vg, ep->typedata.vector->cache.vg, pos))
-          {
-             // can interpolate between two svg file
-             eo_parent_set(container, root_vg);
-          }
-        else
+        if (!evas_vg_node_interpolate(ep->typedata.vector->cur.vg, start->vg, end->vg, pos))
           {
-             // can't interpolate between 2 shape
-             // keep the current vg tree
-             eo_parent_set(ep->typedata.vector->cur.vg, root_vg);
-             // delete the container
-             eo_unref(container);
+             ERR(" Can't interpolate check the svg file \n");
           }
+        // performance hack
+        // instead of duplicating the tree and applying the transformation
+        // i just updated the transformation matrix and reset it back to null.
+        // assumption is that the root vg will never have a transformation
+        eina_matrix3_identity(&matrix);
+        evas_vg_node_transformation_set(start->vg, &matrix);
+        evas_vg_node_transformation_set(end->vg, &matrix);
      }
    else 
      {
         if (ep->typedata.vector->cur.svg_id == chosen_desc->vg.id) // no svg file change
           {
-             Eina_Matrix3 matrix;
              sx = w/ep->typedata.vector->cur.w;
              sy = h/ep->typedata.vector->cur.h;
              eina_matrix3_identity(&matrix);
@@ -3357,88 +3327,12 @@ _edje_svg_recalc_apply(Edje *ed, Edje_Real_Part *ep, Edje_Calc_Params *p3 EINA_U
           }
         else
           {
-             Eina_Matrix3 matrix;
-             // check in cache if the vg tree already exists
-             if (ep->typedata.vector->cache.svg_id == chosen_desc->vg.id)
-               {
-                  int id = ep->typedata.vector->cache.svg_id;
-                  int vx = ep->typedata.vector->cache.x;
-                  int vy = ep->typedata.vector->cache.y;
-                  int vw = ep->typedata.vector->cache.w;
-                  int vh = ep->typedata.vector->cache.h;
-                  Efl_VG *vg = ep->typedata.vector->cache.vg;
-
-                  //1. update the cache from current.
-                  ep->typedata.vector->cache.svg_id = ep->typedata.vector->cur.svg_id;
-                  ep->typedata.vector->cache.vg = ep->typedata.vector->cur.vg;
-                  ep->typedata.vector->cache.x = ep->typedata.vector->cur.x;
-                  ep->typedata.vector->cache.y = ep->typedata.vector->cur.y;
-                  ep->typedata.vector->cache.w = ep->typedata.vector->cur.w;
-                  ep->typedata.vector->cache.h = ep->typedata.vector->cur.h;
-                  eo_ref(ep->typedata.vector->cache.vg);
-                  eo_parent_set(ep->typedata.vector->cache.vg, NULL);
-
-                  //2. update the root node
-                  sx = w/vw;
-                  sy = h/vh;
-                  eina_matrix3_identity(&matrix);
-                  eina_matrix3_translate(&matrix, -vx, -vy);
-                  eina_matrix3_scale(&matrix, sx, sy);
-                  evas_vg_node_transformation_set(vg, &matrix);
-                  // update parent and ref
-                  eo_parent_set(vg, root_vg);
-
-                  //3.update the cur 
-                  ep->typedata.vector->cur.svg_id = id;
-                  ep->typedata.vector->cur.x = vx;
-                  ep->typedata.vector->cur.y = vy;
-                  ep->typedata.vector->cur.w = vw;
-                  ep->typedata.vector->cur.h = vh;
-                  ep->typedata.vector->cur.vg = vg;
-               }
-             else
-               {
-                  //create it
-                  vg_tree = _edje_create_vg_tree(ed->file->ef, chosen_desc->vg.id, w, h, &vx, &vy, &vw, &vh);
-                  if (vg_tree)
-                    {
-                      //1. clear the cache
-                      if (ep->typedata.vector->cache.vg)
-                        {
-                           eo_unref(ep->typedata.vector->cache.vg);
-                           ep->typedata.vector->cache.vg = NULL;
-                           ep->typedata.vector->cache.svg_id = 0;
-                        }
-                      // 2. move the current tree to cache
-                      if (ep->typedata.vector->cur.vg)
-                       {
-                          eo_ref(ep->typedata.vector->cur.vg);
-                          eo_parent_set(ep->typedata.vector->cur.vg, NULL);
-                          // copy to the cache.
-                          ep->typedata.vector->cache.svg_id = ep->typedata.vector->cur.svg_id;
-                          ep->typedata.vector->cache.vg = ep->typedata.vector->cur.vg;
-                          ep->typedata.vector->cache.x = ep->typedata.vector->cur.x;
-                          ep->typedata.vector->cache.y = ep->typedata.vector->cur.y;
-                          ep->typedata.vector->cache.w = ep->typedata.vector->cur.w;
-                          ep->typedata.vector->cache.h = ep->typedata.vector->cur.h;
-                       }
-                      //3. update current
-                      ep->typedata.vector->cur.svg_id = chosen_desc->vg.id;
-                      ep->typedata.vector->cur.x = vx;
-                      ep->typedata.vector->cur.y = vy;
-                      ep->typedata.vector->cur.w = vw;
-                      ep->typedata.vector->cur.h = vh;
-                      ep->typedata.vector->cur.vg = vg_tree;
-                      eo_parent_set(vg_tree, root_vg);
-                    }
-                  else
-                    {
-                       //1. clear current
-                       ep->typedata.vector->cur.svg_id = 0;
-                       eo_parent_set(ep->typedata.vector->cur.vg, NULL);
-                       ep->typedata.vector->cur.vg = NULL;
-                    }
-               }
+             if (ep->typedata.vector->cur.vg)
+               eo_del(ep->typedata.vector->cur.vg);
+
+             _edje_dupe_vector_data(ed, chosen_desc->vg.id, w, h, &ep->typedata.vector->cur);
+
+             eo_parent_set(ep->typedata.vector->cur.vg, root_vg);
           }
      }
 }
index d1f6417..e26eb5e 100644 (file)
@@ -27,6 +27,7 @@ struct _Edje_Drag_Items
 };
 
 void _edje_file_add(Edje *ed, const Eina_File *f);
+static void _edje_vector_data_free(Edje *ed);
 
 /* START - Nested part support */
 #define _edje_smart_nested_type "Evas_Smart_Nested"
@@ -1556,7 +1557,7 @@ _edje_file_del(Edje *ed)
    _edje_message_del(ed);
    _edje_block_violate(ed);
    _edje_var_shutdown(ed);
-
+   _edje_vector_data_free(ed);
    if (!((ed->file) && (ed->collection)))
      {
         if (tev)
@@ -2380,43 +2381,97 @@ _create_vg_node(Svg_Node *node, Efl_VG *parent)
    _apply_vg_property(node, vg);
 }
 
-Efl_VG*
-_edje_create_vg_tree(Eet_File *ef, int svg_id, double width, double height,
-                     double *vx, double *vy, double *vw, double *vh)
+static void
+_edje_vector_data_free(Edje *ed)
+{
+   Edje_Vector_Data *vector;
+
+   EINA_LIST_FREE(ed->vector_cache, vector)
+     {
+        if (vector->vg) eo_del(vector->vg);
+        free(vector);
+     }
+}
+
+Edje_Vector_Data *
+_edje_ref_vector_data(Edje *ed, int svg_id)
 {
-   double sx=1.0, sy=1.0;
-   Eina_Matrix3 matrix;
-   Efl_VG *root = NULL;
-   Svg_Node *child;
    Eina_List *l;
-   Svg_Node *node;
+   Edje_Vector_Data *vector;
    char svg_key[20];
    Eet_Data_Descriptor *svg_node_eet;
+   Svg_Node *child;
+   Svg_Node *node;
+   Efl_VG *root = NULL;
+
+   // check in the cache
+   EINA_LIST_FOREACH(ed->vector_cache, l, vector)
+     {
+        if (vector->svg_id == svg_id)
+          return vector;
+     }
+
+   // create and put it in the cache.
+   vector = calloc(1, sizeof(Edje_Vector_Data));
+   vector->svg_id = svg_id;
 
    snprintf(svg_key, sizeof(svg_key), "edje/vectors/%i", svg_id);
    svg_node_eet = _edje_svg_node_eet();
-   node = eet_data_read(ef, svg_node_eet, svg_key);
+   node = eet_data_read(ed->file->ef, svg_node_eet, svg_key);
 
-   if (!node && (node->type != SVG_NODE_DOC)) return NULL;
-   if (node->node.doc.vw && node->node.doc.vh)
+   if (!node || (node->type != SVG_NODE_DOC))
+     {
+        root = NULL;
+     }
+   else
      {
-        sx = width/node->node.doc.vw;
-        sy = height/node->node.doc.vh;
         root = evas_vg_container_add(NULL);
+        EINA_LIST_FOREACH(node->child, l, child)
+          {
+             _create_vg_node(child, root);
+          }
+        vector->x = node->node.doc.vx;
+        vector->y = node->node.doc.vy;
+        vector->w = node->node.doc.vw;
+        vector->h = node->node.doc.vh;
+     }
+   vector->vg = root;
+   ed->vector_cache = eina_list_append(ed->vector_cache, vector);
+   return vector;
+}
+
+void
+_edje_dupe_vector_data(Edje *ed, int svg_id, double width, double height,
+                       Edje_Vector_Data *data)
+{
+   double sx=1.0, sy=1.0;
+   Edje_Vector_Data *vector;
+   Efl_VG *root;
+   Eina_Matrix3 matrix;
+
+   vector = _edje_ref_vector_data(ed, svg_id);
+   if (!vector->vg)
+     {
+        data->vg = NULL;
+     }
+
+   root = evas_vg_container_add(NULL);
+   efl_vg_dup(root, vector->vg);
+
+   if (vector->w && vector->h)
+     {
+        sx = width/vector->w;
+        sy = height/vector->h;
         eina_matrix3_identity(&matrix);
-        eina_matrix3_translate(&matrix, -node->node.doc.vx, -node->node.doc.vy);
+        eina_matrix3_translate(&matrix, -vector->x, -vector->y);
         eina_matrix3_scale(&matrix, sx, sy);
         evas_vg_node_transformation_set(root, &matrix);
      }
 
-   EINA_LIST_FOREACH(node->child, l, child)
-     {
-        _create_vg_node(child, root);
-     }
-   *vx = node->node.doc.vx;
-   *vy = node->node.doc.vy;
-   *vw = node->node.doc.vw;
-   *vh = node->node.doc.vh;
-   return root;
+   data->vg = root;
+   data->x = vector->x;
+   data->y = vector->y;
+   data->w = vector->w;
+   data->h = vector->h;
 }
 
index 7de6b58..fbfc633 100644 (file)
@@ -370,6 +370,7 @@ typedef struct _Edje_Part_Limit                      Edje_Part_Limit;
 typedef struct _Edje_Part_Description_Vector         Edje_Part_Description_Vector;
 typedef struct _Edje_Part_Description_Spec_Svg       Edje_Part_Description_Spec_Svg;
 typedef struct _Edje_Real_Part_Vector                Edje_Real_Part_Vector;
+typedef struct _Edje_Vector_Data                     Edje_Vector_Data;
 
 typedef struct _Edje Edje;
 typedef struct _Edje_Real_Part_Text Edje_Real_Part_Text;
@@ -1652,6 +1653,7 @@ struct _Edje
    Eina_List            *subobjs;
    Eina_List            *text_insert_filter_callbacks;
    Eina_List            *markup_filter_callbacks;
+   Eina_List            *vector_cache; /* list of Edje_Vector_Data */
 
    Eina_List            *groups;
 
@@ -1935,14 +1937,17 @@ struct _Edje_Real_Part_Swallow
    } swallow_params; // 28 // FIXME: only if type SWALLOW
 };
 
+struct _Edje_Vector_Data
+{
+   int svg_id;
+   double x, y, w, h;
+   Eina_Bool preserve_aspect;
+   Efl_VG *vg;
+};
+
 struct _Edje_Real_Part_Vector
 {
-   struct {
-     int svg_id;
-     double x, y, w, h;
-     Eina_Bool preserve_aspect;
-     Efl_VG *vg;
-   }cur, cache;
+   Edje_Vector_Data cur;
 };
 
 struct _Edje_Real_Part
@@ -3229,8 +3234,12 @@ enum _Svg_Style_Type
 
 EAPI Eet_Data_Descriptor * _edje_svg_node_eet(void);
 void _edje_svg_node_destroy_eet(void);
-Efl_VG* _edje_create_vg_tree(Eet_File *ef, int svg_id, double width, double height,
-                             double *vx, double *vy, double *vw, double *vh);
+
+void _edje_dupe_vector_data(Edje *ed, int svg_id, double width, double height,
+                            Edje_Vector_Data *data);
+
+Edje_Vector_Data * _edje_ref_vector_data(Edje *ed, int svg_id);
+
 
 #ifdef HAVE_LIBREMIX
 #include <remix/remix.h>