edje: cached the vg tree generation and fixed the interpolation betwwen two vg tree.

Reviewers: cedric, jpeg

Subscribers: cedric, jpeg

Differential Revision: https://phab.enlightenment.org/D4028
This commit is contained in:
Subhransu Mohanty 2016-06-09 13:49:56 +09:00 committed by Jean-Philippe Andre
parent ef84367fa9
commit e38cf1f85f
3 changed files with 128 additions and 170 deletions

View 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))
if (!evas_vg_node_interpolate(ep->typedata.vector->cur.vg, start->vg, end->vg, pos))
{
// can interpolate between two svg file
eo_parent_set(container, root_vg);
}
else
{
// 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;
if (ep->typedata.vector->cur.vg)
eo_del(ep->typedata.vector->cur.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);
_edje_dupe_vector_data(ed, chosen_desc->vg.id, w, h, &ep->typedata.vector->cur);
//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;
}
}
eo_parent_set(ep->typedata.vector->cur.vg, root_vg);
}
}
}

View 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;
}

View 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>