1 #include "evas_common_private.h"
2 #include "evas_private.h"
3 
4 #include "evas_vg_private.h"
5 
6 #include <string.h>
7 #include <math.h>
8 
9 #define MY_CLASS EFL_CANVAS_VG_NODE_CLASS
10 
11 static const Efl_Canvas_Vg_Interpolation interpolation_identity = {
12   { 0, 0, 0, 1 },
13   { 0, 0, 0, 1 },
14   { 0, 0, 0 },
15   { 1, 1, 1 },
16   { 0, 0, 0 }
17 };
18 
19 static void
_node_change(Efl_VG * obj,Efl_Canvas_Vg_Node_Data * nd)20 _node_change(Efl_VG *obj, Efl_Canvas_Vg_Node_Data *nd)
21 {
22    if (!nd) return;
23    if (nd->flags != EFL_GFX_CHANGE_FLAG_NONE)
24      {
25        if ((nd->vd && nd->vd->obj) &&
26            (!nd->vd->obj || !nd->vd->obj->changed))
27          efl_canvas_vg_object_change(nd->vd);
28 
29        return;
30      }
31    nd->flags = EFL_GFX_CHANGE_FLAG_ALL;
32 
33    Eo *p = obj;
34    while ((p = efl_parent_get(p)))
35      {
36         if (!efl_isa(p, MY_CLASS)) break;
37         Efl_Canvas_Vg_Node_Data *pnd = efl_data_scope_get(p, MY_CLASS);
38         if (pnd->flags != EFL_GFX_CHANGE_FLAG_NONE) break;
39         pnd->flags = EFL_GFX_CHANGE_FLAG_ALL;
40      }
41    if (!nd->vg_obj || efl_invalidated_get(nd->vg_obj)) return;
42    efl_canvas_vg_object_change(nd->vd);
43 }
44 
45 static void
_efl_canvas_vg_node_transformation_set(Eo * obj,Efl_Canvas_Vg_Node_Data * pd,const Eina_Matrix3 * m)46 _efl_canvas_vg_node_transformation_set(Eo *obj,
47                                        Efl_Canvas_Vg_Node_Data *pd,
48                                        const Eina_Matrix3 *m)
49 {
50    if (pd->intp)
51      {
52         free(pd->intp);
53         pd->intp = NULL;
54      }
55 
56    if (m)
57      {
58         if (!pd->m)
59           {
60              pd->m = malloc(sizeof (Eina_Matrix3));
61              if (!pd->m) return;
62           }
63         memcpy(pd->m, m, sizeof (Eina_Matrix3));
64      }
65    else
66      {
67         free(pd->m);
68         pd->m = NULL;
69      }
70 
71    /* NOTE: _node_change function is only executed
72             when pd->flags is EFL_GFX_CHANGE_FLAG_NONE to prevent duplicate calls.*/
73    _node_change(obj, pd);
74    pd->flags |= EFL_GFX_CHANGE_FLAG_MATRIX;
75 }
76 
77 const Eina_Matrix3 *
_efl_canvas_vg_node_transformation_get(const Eo * obj EINA_UNUSED,Efl_Canvas_Vg_Node_Data * pd)78 _efl_canvas_vg_node_transformation_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Vg_Node_Data *pd)
79 {
80    return pd->m;
81 }
82 
83 static void
_efl_canvas_vg_node_comp_method_set(Eo * obj EINA_UNUSED,Efl_Canvas_Vg_Node_Data * pd EINA_UNUSED,Efl_Canvas_Vg_Node * target EINA_UNUSED,Efl_Gfx_Vg_Composite_Method method EINA_UNUSED)84 _efl_canvas_vg_node_comp_method_set(Eo *obj EINA_UNUSED,
85                                     Efl_Canvas_Vg_Node_Data *pd EINA_UNUSED,
86                                     Efl_Canvas_Vg_Node *target EINA_UNUSED,
87                                     Efl_Gfx_Vg_Composite_Method method EINA_UNUSED)
88 {
89 }
90 
91 static void
_efl_canvas_vg_node_origin_set(Eo * obj,Efl_Canvas_Vg_Node_Data * pd,double x,double y)92 _efl_canvas_vg_node_origin_set(Eo *obj,
93                                Efl_Canvas_Vg_Node_Data *pd,
94                                double x, double y)
95 {
96    pd->x = x;
97    pd->y = y;
98 
99    _node_change(obj, pd);
100 }
101 
102 static void
_efl_canvas_vg_node_origin_get(const Eo * obj EINA_UNUSED,Efl_Canvas_Vg_Node_Data * pd,double * x,double * y)103 _efl_canvas_vg_node_origin_get(const Eo *obj EINA_UNUSED,
104                         Efl_Canvas_Vg_Node_Data *pd,
105                         double *x, double *y)
106 {
107    if (x) *x = pd->x;
108    if (y) *y = pd->y;
109 }
110 
111 static void
_efl_canvas_vg_node_efl_gfx_entity_position_set(Eo * obj,Efl_Canvas_Vg_Node_Data * pd,Eina_Position2D pos)112 _efl_canvas_vg_node_efl_gfx_entity_position_set(Eo *obj,
113                                                 Efl_Canvas_Vg_Node_Data *pd,
114                                                 Eina_Position2D pos)
115 {
116    pd->x = (double) pos.x;
117    pd->y = (double) pos.y;
118 
119    _node_change(obj, pd);
120 }
121 
122 static Eina_Position2D
_efl_canvas_vg_node_efl_gfx_entity_position_get(const Eo * obj EINA_UNUSED,Efl_Canvas_Vg_Node_Data * pd)123 _efl_canvas_vg_node_efl_gfx_entity_position_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Vg_Node_Data *pd)
124 {
125    // NOTE: This casts double to int!
126    return EINA_POSITION2D(pd->x, pd->y);
127 }
128 
129 static void
_efl_canvas_vg_node_efl_gfx_entity_visible_set(Eo * obj,Efl_Canvas_Vg_Node_Data * pd,Eina_Bool v)130 _efl_canvas_vg_node_efl_gfx_entity_visible_set(Eo *obj,
131                                                Efl_Canvas_Vg_Node_Data *pd,
132                                                Eina_Bool v)
133 {
134    pd->visibility = v;
135 
136    _node_change(obj, pd);
137 }
138 
139 
140 static Eina_Bool
_efl_canvas_vg_node_efl_gfx_entity_visible_get(const Eo * obj EINA_UNUSED,Efl_Canvas_Vg_Node_Data * pd)141 _efl_canvas_vg_node_efl_gfx_entity_visible_get(const Eo *obj EINA_UNUSED,
142                                       Efl_Canvas_Vg_Node_Data *pd)
143 {
144    return pd->visibility;
145 }
146 
147 static void
_efl_canvas_vg_node_efl_gfx_color_color_set(Eo * obj,Efl_Canvas_Vg_Node_Data * pd,int r,int g,int b,int a)148 _efl_canvas_vg_node_efl_gfx_color_color_set(Eo *obj,
149                                             Efl_Canvas_Vg_Node_Data *pd,
150                                             int r, int g, int b, int a)
151 {
152    Eina_Bool perr = EINA_FALSE;
153 
154    //Exception Handling.
155    if (r < 0) r = 0;
156    if (g < 0) g = 0;
157    if (b < 0) b = 0;
158    if (a > 255) a = 255;
159    else if (a < 0) a = 0;
160 
161    if (r > a)
162      {
163         r = a;
164         perr = EINA_TRUE;
165      }
166    if (g > a)
167      {
168         g = a;
169         perr = EINA_TRUE;
170      }
171    if (b > a)
172      {
173         b = a;
174         perr = EINA_TRUE;
175      }
176 
177    if (perr) ERR("Evas only handles pre-multiplied color!");
178 
179    pd->r = r;
180    pd->g = g;
181    pd->b = b;
182    pd->a = a;
183 
184    _node_change(obj, pd);
185 }
186 
187 static void
_efl_canvas_vg_node_efl_gfx_color_color_get(const Eo * obj EINA_UNUSED,Efl_Canvas_Vg_Node_Data * pd,int * r,int * g,int * b,int * a)188 _efl_canvas_vg_node_efl_gfx_color_color_get(const Eo *obj EINA_UNUSED,
189                                     Efl_Canvas_Vg_Node_Data *pd,
190                                     int *r, int *g, int *b, int *a)
191 {
192    if (r) *r = pd->r;
193    if (g) *g = pd->g;
194    if (b) *b = pd->b;
195    if (a) *a = pd->a;
196 }
197 
198 static Eina_Size2D
_efl_canvas_vg_node_efl_gfx_entity_size_get(const Eo * obj,Efl_Canvas_Vg_Node_Data * pd EINA_UNUSED)199 _efl_canvas_vg_node_efl_gfx_entity_size_get(const Eo *obj, Efl_Canvas_Vg_Node_Data *pd EINA_UNUSED)
200 {
201    Eina_Rect r;
202 
203    efl_gfx_path_bounds_get(obj, &r);
204    return r.size;
205 }
206 
207 EOLIAN static Eina_Rect
_efl_canvas_vg_node_efl_gfx_entity_geometry_get(const Eo * obj,Efl_Canvas_Vg_Node_Data * pd EINA_UNUSED)208 _efl_canvas_vg_node_efl_gfx_entity_geometry_get(const Eo *obj, Efl_Canvas_Vg_Node_Data *pd EINA_UNUSED)
209 {
210    Eina_Rect r;
211    r.pos = efl_gfx_entity_position_get(obj);
212    r.size = efl_gfx_entity_size_get(obj);
213    return r;
214 }
215 
216 // Parent should be a container otherwise dismissing the stacking operation
217 static Eina_Bool
_efl_canvas_vg_node_parent_checked_get(Eo * obj,Eo ** parent,Efl_Canvas_Vg_Container_Data ** cd)218 _efl_canvas_vg_node_parent_checked_get(Eo *obj,
219                                        Eo **parent,
220                                        Efl_Canvas_Vg_Container_Data **cd)
221 {
222    *cd = NULL;
223    *parent = efl_parent_get(obj);
224 
225    if (efl_isa(*parent, EFL_CANVAS_VG_CONTAINER_CLASS))
226      *cd = efl_data_scope_get(*parent, EFL_CANVAS_VG_CONTAINER_CLASS);
227    else if (efl_isa(*parent, EFL_CANVAS_VG_OBJECT_CLASS))
228      *parent = NULL;
229    else if (*parent)
230      {
231         ERR("Parent of unauthorized class '%s'.", efl_class_name_get(efl_class_get(*parent)));
232         *parent = NULL;
233         return EINA_FALSE;
234      }
235 
236    return EINA_TRUE;
237 }
238 
239 static Eo *
_efl_canvas_vg_node_efl_object_constructor(Eo * obj,Efl_Canvas_Vg_Node_Data * nd)240 _efl_canvas_vg_node_efl_object_constructor(Eo *obj,
241                                            Efl_Canvas_Vg_Node_Data *nd)
242 {
243    Efl_Canvas_Vg_Container_Data *cd;
244    Eo *parent;
245 
246    obj = efl_constructor(efl_super(obj, MY_CLASS));
247 
248    if (!_efl_canvas_vg_node_parent_checked_get(obj, &parent, &cd))
249      {
250         ERR("Failed");
251         return NULL;
252      }
253 
254    if (parent)
255      {
256         Efl_Canvas_Vg_Node_Data *parent_nd =
257            efl_data_scope_get(parent, MY_CLASS);
258         nd->vg_obj = parent_nd->vg_obj;
259         nd->vd = parent_nd->vd;
260      }
261 
262    nd->flags = EFL_GFX_CHANGE_FLAG_ALL;
263    nd->changed = EINA_TRUE;
264    nd->visibility = EINA_TRUE;
265 
266    return obj;
267 }
268 
269 static void
_efl_canvas_vg_node_efl_object_invalidate(Eo * obj,Efl_Canvas_Vg_Node_Data * pd)270 _efl_canvas_vg_node_efl_object_invalidate(Eo *obj, Efl_Canvas_Vg_Node_Data *pd)
271 {
272    if (pd->renderer)
273      {
274         efl_unref(pd->renderer);
275         pd->renderer = NULL;
276      }
277 
278    efl_invalidate(efl_super(obj, MY_CLASS));
279 }
280 
281 static void
_efl_canvas_vg_node_efl_object_destructor(Eo * obj,Efl_Canvas_Vg_Node_Data * pd)282 _efl_canvas_vg_node_efl_object_destructor(Eo *obj, Efl_Canvas_Vg_Node_Data *pd)
283 {
284    if (pd->m)
285      {
286         free(pd->m);
287         pd->m = NULL;
288      }
289    if (pd->intp)
290      {
291         free(pd->intp);
292         pd->intp = NULL;
293      }
294 
295    efl_destructor(efl_super(obj, MY_CLASS));
296 }
297 
298 static void
_efl_canvas_vg_node_name_insert(Eo * obj,Efl_Canvas_Vg_Container_Data * cd)299 _efl_canvas_vg_node_name_insert(Eo *obj, Efl_Canvas_Vg_Container_Data *cd)
300 {
301    Eo *set;
302    const char *name = efl_name_get(efl_super(obj, MY_CLASS));
303    if (!name) return;
304 
305    set = eina_hash_find(cd->names, name);
306    if (set == obj) return;
307 
308    if (set)
309      {
310         ERR("node name(%s) is already exist in container but child node(%p) is different...", name, obj);
311         efl_name_set(efl_super(obj, MY_CLASS), NULL);
312      }
313    else
314      {
315         eina_hash_direct_add(cd->names, name, obj);
316      }
317 }
318 
319 static void
_efl_canvas_vg_node_efl_object_name_set(Eo * obj,Efl_Canvas_Vg_Node_Data * pd EINA_UNUSED,const char * name)320 _efl_canvas_vg_node_efl_object_name_set(Eo *obj, Efl_Canvas_Vg_Node_Data *pd EINA_UNUSED, const char *name)
321 {
322    Efl_Canvas_Vg_Container_Data *cd;
323    Eo *parent;
324    const char *pname = efl_name_get(obj);
325 
326    if (_efl_canvas_vg_node_parent_checked_get(obj, &parent, &cd))
327      {
328         if (pname) eina_hash_del(cd->names, pname, obj);
329      }
330 
331    efl_name_set(efl_super(obj, MY_CLASS), name);
332 
333    if (cd) _efl_canvas_vg_node_name_insert(obj, cd);
334 }
335 
336 static void
_efl_canvas_vg_node_efl_object_parent_set(Eo * obj,Efl_Canvas_Vg_Node_Data * nd,Eo * parent)337 _efl_canvas_vg_node_efl_object_parent_set(Eo *obj,
338                                           Efl_Canvas_Vg_Node_Data *nd,
339                                           Eo *parent)
340 {
341    Efl_Canvas_Vg_Container_Data *cd = NULL;
342    Efl_Canvas_Vg_Container_Data *old_cd;
343    Efl_VG *old_parent;
344 
345    if (parent)
346      {
347         if (efl_isa(parent, EFL_CANVAS_VG_CONTAINER_CLASS))
348           cd = efl_data_scope_get(parent, EFL_CANVAS_VG_CONTAINER_CLASS);
349         else if (efl_isa(parent, EFL_CANVAS_VG_OBJECT_CLASS))
350           {
351              if (nd->vg_obj != parent)
352                {
353                   nd->vg_obj = parent;
354                   nd->vd = efl_data_scope_get(parent, EFL_CANVAS_VG_OBJECT_CLASS);
355                }
356           }
357         else
358           {
359              ERR("parent(%p, class = %s) is not allowed by vg node(%p).",
360                  parent, efl_class_name_get(efl_class_get(parent)), obj);
361              return;
362           }
363      }
364    else
365      {
366         nd->vg_obj = NULL;
367         nd->vd = NULL;
368      }
369 
370    if (!_efl_canvas_vg_node_parent_checked_get(obj, &old_parent, &old_cd))
371      return;
372 
373    // FIXME: this may become slow with to much object
374    if (old_cd)
375      {
376         old_cd->children = eina_list_remove(old_cd->children, obj);
377         eina_hash_del(old_cd->names, efl_name_get(efl_super(obj, MY_CLASS)), obj);
378         _node_change(old_parent, efl_data_scope_get(old_parent, MY_CLASS));
379      }
380 
381    efl_parent_set(efl_super(obj, MY_CLASS), parent);
382 
383    if (cd)
384      {
385         cd->children = eina_list_append(cd->children, obj);
386         _efl_canvas_vg_node_name_insert(obj, cd);
387 
388         Efl_Canvas_Vg_Node_Data *parent_nd = efl_data_scope_get(parent, MY_CLASS);
389         if (nd->vg_obj != parent_nd->vg_obj)
390           {
391              nd->vg_obj = parent_nd->vg_obj;
392              nd->vd = parent_nd->vd;
393           }
394      }
395 
396    if (parent) _node_change(obj, nd);
397 }
398 
399 static void
_efl_canvas_vg_node_efl_gfx_stack_raise_to_top(Eo * obj,Efl_Canvas_Vg_Node_Data * pd EINA_UNUSED)400 _efl_canvas_vg_node_efl_gfx_stack_raise_to_top(Eo *obj, Efl_Canvas_Vg_Node_Data *pd EINA_UNUSED)
401 {
402    Efl_Canvas_Vg_Node *parent = efl_parent_get(obj);
403    if (!efl_isa(parent, EFL_CANVAS_VG_CONTAINER_CLASS)) return;
404 
405    Efl_Canvas_Vg_Container_Data *cd = efl_data_scope_get(parent, EFL_CANVAS_VG_CONTAINER_CLASS);
406    if (!cd->children) return;
407    if (eina_list_data_get(eina_list_last(cd->children)) == obj) return;
408    cd->children = eina_list_remove(cd->children, obj);
409    cd->children = eina_list_append(cd->children, obj);
410    _node_change(parent, efl_data_scope_get(parent, MY_CLASS));
411 }
412 
413 static void
_efl_canvas_vg_node_efl_gfx_stack_stack_above(Eo * obj,Efl_Canvas_Vg_Node_Data * pd EINA_UNUSED,Efl_Gfx_Stack * above)414 _efl_canvas_vg_node_efl_gfx_stack_stack_above(Eo *obj,
415                                               Efl_Canvas_Vg_Node_Data *pd EINA_UNUSED,
416                                               Efl_Gfx_Stack *above)
417 {
418    Efl_Canvas_Vg_Container_Data *cd;
419    Eina_List *lookup, *ref;
420    Eo *parent;
421 
422    parent = efl_parent_get(obj);
423    if (!efl_isa(parent, EFL_CANVAS_VG_CONTAINER_CLASS)) goto on_error;
424    cd = efl_data_scope_get(parent, EFL_CANVAS_VG_CONTAINER_CLASS);
425 
426    // FIXME: this could become slow with to much object
427    lookup = eina_list_data_find_list(cd->children, obj);
428    if (!lookup) goto on_error;
429 
430    ref = eina_list_data_find_list(cd->children, above);
431    if (!ref) goto on_error;
432 
433    cd->children = eina_list_remove_list(cd->children, lookup);
434    cd->children = eina_list_append_relative_list(cd->children, obj, ref);
435 
436    _node_change(parent, efl_data_scope_get(parent, MY_CLASS));
437    return;
438 
439  on_error:
440    ERR("Err");
441 }
442 
443 static void
_efl_canvas_vg_node_efl_gfx_stack_stack_below(Eo * obj,Efl_Canvas_Vg_Node_Data * pd EINA_UNUSED,Efl_Gfx_Stack * below)444 _efl_canvas_vg_node_efl_gfx_stack_stack_below(Eo *obj,
445                                               Efl_Canvas_Vg_Node_Data *pd EINA_UNUSED,
446                                               Efl_Gfx_Stack *below)
447 {
448    Efl_Canvas_Vg_Container_Data *cd;
449    Eina_List *lookup, *ref;
450    Eo *parent;
451 
452    parent = efl_parent_get(obj);
453    if (!efl_isa(parent, EFL_CANVAS_VG_CONTAINER_CLASS)) goto on_error;
454    cd = efl_data_scope_get(parent, EFL_CANVAS_VG_CONTAINER_CLASS);
455 
456    // FIXME: this could become slow with to much object
457    lookup = eina_list_data_find_list(cd->children, obj);
458    if (!lookup) goto on_error;
459 
460    ref = eina_list_data_find_list(cd->children, below);
461    if (!ref) goto on_error;
462 
463    cd->children = eina_list_remove_list(cd->children, lookup);
464    cd->children = eina_list_prepend_relative_list(cd->children, obj, ref);
465 
466    _node_change(parent, efl_data_scope_get(parent, MY_CLASS));
467    return;
468 
469  on_error:
470    ERR("Err");
471 }
472 
473 static void
_efl_canvas_vg_node_efl_gfx_stack_lower_to_bottom(Eo * obj,Efl_Canvas_Vg_Node_Data * pd EINA_UNUSED)474 _efl_canvas_vg_node_efl_gfx_stack_lower_to_bottom(Eo *obj, Efl_Canvas_Vg_Node_Data *pd EINA_UNUSED)
475 {
476    Efl_Canvas_Vg_Node *parent = efl_parent_get(obj);
477    if (!efl_isa(parent, EFL_CANVAS_VG_CONTAINER_CLASS)) return;
478 
479    Efl_Canvas_Vg_Container_Data *cd = efl_data_scope_get(parent, EFL_CANVAS_VG_CONTAINER_CLASS);
480    if (!cd->children) return;
481    if (eina_list_data_get(cd->children) == obj) return;
482    cd->children = eina_list_remove(cd->children, obj);
483    cd->children = eina_list_prepend(cd->children, obj);
484    _node_change(parent, efl_data_scope_get(parent, MY_CLASS));
485 }
486 
487 static Efl_Gfx_Stack *
_efl_canvas_vg_node_efl_gfx_stack_below_get(const Eo * obj,Efl_Canvas_Vg_Node_Data * pd EINA_UNUSED)488 _efl_canvas_vg_node_efl_gfx_stack_below_get(const Eo *obj, Efl_Canvas_Vg_Node_Data *pd EINA_UNUSED)
489 {
490    Eo *parent, *below;
491    const Eina_List *list;
492 
493    parent = efl_parent_get(obj);
494    if (!efl_isa(parent, EFL_CANVAS_VG_CONTAINER_CLASS)) goto on_error;
495 
496    list = efl_canvas_vg_container_children_direct_get(parent);
497    if (list == NULL) goto on_error;
498 
499    list = eina_list_data_find_list(list, obj);
500    if (list == NULL) goto on_error;
501 
502    list = eina_list_prev(list);
503    if (list == NULL) goto on_error;
504 
505    below = list->data;
506 
507    return below;
508 
509  on_error:
510    return NULL;
511 }
512 
513 static Efl_Gfx_Stack *
_efl_canvas_vg_node_efl_gfx_stack_above_get(const Eo * obj,Efl_Canvas_Vg_Node_Data * pd EINA_UNUSED)514 _efl_canvas_vg_node_efl_gfx_stack_above_get(const Eo *obj, Efl_Canvas_Vg_Node_Data *pd EINA_UNUSED)
515 {
516    Eo *parent, *above;
517    const Eina_List *list;
518 
519    parent = efl_parent_get(obj);
520    if (!efl_isa(parent, EFL_CANVAS_VG_CONTAINER_CLASS)) goto on_error;
521 
522    list = efl_canvas_vg_container_children_direct_get(parent);
523    if (list == NULL) goto on_error;
524 
525    list = eina_list_data_find_list(list, obj);
526    if (list == NULL) goto on_error;
527 
528    list = eina_list_next(list);
529    if (list == NULL) goto on_error;
530 
531    above = list->data;
532 
533    return above;
534 
535  on_error:
536    return NULL;
537 }
538 
539 static Efl_Canvas_Vg_Interpolation *
_efl_canvas_vg_node_interpolation_get(Efl_Canvas_Vg_Node_Data * pd)540 _efl_canvas_vg_node_interpolation_get(Efl_Canvas_Vg_Node_Data *pd)
541 {
542    Eina_Matrix4 m;
543 
544    if (!pd->m) return NULL;
545    if (pd->intp) return pd->intp;
546 
547    pd->intp = calloc(1, sizeof (Efl_Canvas_Vg_Interpolation));
548    if (!pd->intp) return NULL;
549 
550    eina_matrix3_matrix4_to(&m, pd->m);
551 
552    if (eina_matrix4_quaternion_to(&pd->intp->rotation,
553                                   &pd->intp->perspective,
554                                   &pd->intp->translation,
555                                   &pd->intp->scale,
556                                   &pd->intp->skew,
557                                   &m))
558      return pd->intp;
559 
560    free(pd->intp);
561    pd->intp = NULL;
562 
563    return NULL;
564 }
565 
566 static inline void
_efl_canvas_vg_node_interpolate_point(Eina_Point_3D * d,const Eina_Point_3D * a,const Eina_Point_3D * b,double pos_map,double from_map)567 _efl_canvas_vg_node_interpolate_point(Eina_Point_3D *d,
568                                       const Eina_Point_3D *a, const Eina_Point_3D *b,
569                                       double pos_map, double from_map)
570 {
571    d->x = a->x * from_map + b->x * pos_map;
572    d->y = a->y * from_map + b->y * pos_map;
573    d->z = a->z * from_map + b->z * pos_map;
574 }
575 
576 /* Warning! Node itself doesn't have any path. Don't call super class(Path)'s */
577 static Eina_Bool
_efl_canvas_vg_node_efl_gfx_path_interpolate(Eo * obj,Efl_Canvas_Vg_Node_Data * pd,const Efl_VG * from,const Efl_VG * to,double pos_map)578 _efl_canvas_vg_node_efl_gfx_path_interpolate(Eo *obj,
579                                              Efl_Canvas_Vg_Node_Data *pd,
580                                              const Efl_VG *from,
581                                              const Efl_VG *to,
582                                              double pos_map)
583 {
584    Efl_Canvas_Vg_Node_Data *fromd, *tod;
585    double from_map;
586 
587    //Check if both objects have same type
588    if (!(efl_isa(from, MY_CLASS) && efl_isa(to, MY_CLASS)))
589      return EINA_FALSE;
590 
591    fromd = efl_data_scope_get(from, MY_CLASS);
592    tod = efl_data_scope_get(to, MY_CLASS);
593    from_map = 1.0 - pos_map;
594 
595    efl_unref(pd->renderer);
596    pd->renderer = NULL;
597 
598    //Interpolates Node Transform Matrix
599    if (fromd->m || tod->m)
600      {
601         if (!pd->m) pd->m = malloc(sizeof (Eina_Matrix3));
602         if (pd->m)
603           {
604              const Efl_Canvas_Vg_Interpolation *fi, *ti;
605              Efl_Canvas_Vg_Interpolation result;
606              Eina_Matrix4 m;
607 
608              fi = _efl_canvas_vg_node_interpolation_get(fromd);
609              if (!fi) fi = &interpolation_identity;
610 
611              ti = _efl_canvas_vg_node_interpolation_get(tod);
612              if (!ti) ti = &interpolation_identity;
613 
614              eina_quaternion_slerp(&result.rotation,
615                                    &fi->rotation, &ti->rotation,
616                                    pos_map);
617              _efl_canvas_vg_node_interpolate_point(&result.translation,
618                                        &fi->translation, &ti->translation,
619                                        pos_map, from_map);
620              _efl_canvas_vg_node_interpolate_point(&result.scale,
621                                        &fi->scale, &ti->scale,
622                                        pos_map, from_map);
623              _efl_canvas_vg_node_interpolate_point(&result.skew,
624                                        &fi->skew, &ti->skew,
625                                        pos_map, from_map);
626 
627              result.perspective.x =
628                 fi->perspective.x * from_map + ti->perspective.x * pos_map;
629              result.perspective.y =
630                 fi->perspective.y * from_map + ti->perspective.y * pos_map;
631              result.perspective.z =
632                 fi->perspective.z * from_map + ti->perspective.z * pos_map;
633              result.perspective.w =
634                 fi->perspective.w * from_map + ti->perspective.w * pos_map;
635 
636              eina_quaternion_matrix4_to(&m,
637                                         &result.rotation,
638                                         &result.perspective,
639                                         &result.translation,
640                                         &result.scale,
641                                         &result.skew);
642 
643              eina_matrix4_matrix3_to(pd->m, &m);
644           }
645      }
646 
647    //Position
648    pd->x = fromd->x * from_map + tod->x * pos_map;
649    pd->y = fromd->y * from_map + tod->y * pos_map;
650 
651    //Color
652    pd->r = fromd->r * from_map + tod->r * pos_map;
653    pd->g = fromd->g * from_map + tod->g * pos_map;
654    pd->b = fromd->b * from_map + tod->b * pos_map;
655    pd->a = fromd->a * from_map + tod->a * pos_map;
656 
657    pd->visibility = pos_map >= 0.5 ? tod->visibility : fromd->visibility;
658 
659    _node_change(obj, pd);
660 
661    return EINA_TRUE;
662 }
663 
664 void
efl_canvas_vg_node_vg_obj_set(Efl_VG * node,Efl_VG * vg_obj,Efl_Canvas_Vg_Object_Data * vd)665 efl_canvas_vg_node_vg_obj_set(Efl_VG *node, Efl_VG *vg_obj, Efl_Canvas_Vg_Object_Data *vd)
666 {
667    Efl_Canvas_Vg_Node_Data *nd = efl_data_scope_get(node, MY_CLASS);
668    if (nd->vg_obj == vg_obj) return;
669    nd->vg_obj = vg_obj;
670    nd->vd = vd;
671 
672    //root node is always container.
673    efl_canvas_vg_container_vg_obj_update(node, nd);
674 }
675 
676 void
efl_canvas_vg_node_change(Eo * obj)677 efl_canvas_vg_node_change(Eo *obj)
678 {
679    if (!obj) return;
680    _node_change(obj, efl_data_scope_get(obj, EFL_CANVAS_VG_NODE_CLASS));
681 }
682 
683 EOLIAN static Efl_VG *
_efl_canvas_vg_node_efl_duplicate_duplicate(const Eo * obj,Efl_Canvas_Vg_Node_Data * pd)684 _efl_canvas_vg_node_efl_duplicate_duplicate(const Eo *obj, Efl_Canvas_Vg_Node_Data *pd)
685 {
686    Efl_VG *node;
687    Efl_Canvas_Vg_Node_Data *nd;
688 
689    node = efl_add_ref(efl_class_get(obj), NULL);
690    nd = efl_data_scope_get(node, MY_CLASS);
691 
692    //Hmm...?
693    efl_name_set(efl_super(node, MY_CLASS), efl_name_get(efl_super(obj, MY_CLASS)));
694 
695    if (pd->m)
696      {
697         nd->m = malloc(sizeof(Eina_Matrix3));
698         if (nd->m) memcpy(nd->m, pd->m, sizeof(Eina_Matrix3));
699      }
700 
701    nd->x = pd->x;
702    nd->y = pd->y;
703    nd->r = pd->r;
704    nd->g = pd->g;
705    nd->b = pd->b;
706    nd->a = pd->a;
707    nd->visibility = pd->visibility;
708 
709    return node;
710 }
711 
712 EAPI Eina_Bool
evas_vg_node_visible_get(Evas_Vg_Node * obj)713 evas_vg_node_visible_get(Evas_Vg_Node *obj)
714 {
715    return efl_gfx_entity_visible_get(obj);
716 }
717 
718 EAPI void
evas_vg_node_visible_set(Evas_Vg_Node * obj,Eina_Bool v)719 evas_vg_node_visible_set(Evas_Vg_Node *obj, Eina_Bool v)
720 {
721    efl_gfx_entity_visible_set(obj, v);
722 }
723 
724 EAPI void
evas_vg_node_color_get(Evas_Vg_Node * obj,int * r,int * g,int * b,int * a)725 evas_vg_node_color_get(Evas_Vg_Node *obj, int *r, int *g, int *b, int *a)
726 {
727    efl_gfx_color_get(obj, r, g, b, a);
728 }
729 
730 EAPI void
evas_vg_node_color_set(Evas_Vg_Node * obj,int r,int g,int b,int a)731 evas_vg_node_color_set(Evas_Vg_Node *obj, int r, int g, int b, int a)
732 {
733    efl_gfx_color_set(obj, r, g, b, a);
734 }
735 
736 EAPI void
evas_vg_node_geometry_get(Evas_Vg_Node * obj,int * x,int * y,int * w,int * h)737 evas_vg_node_geometry_get(Evas_Vg_Node *obj, int *x, int *y, int *w, int *h)
738 {
739    Eina_Rect r;
740    r.pos = efl_gfx_entity_position_get(obj);
741    r.size = efl_gfx_entity_size_get(obj);
742    if (x) *x = r.x;
743    if (y) *y = r.y;
744    if (w) *w = r.w;
745    if (h) *h = r.h;
746 }
747 
748 /* deprecated */
749 EAPI void
evas_vg_node_geometry_set(Evas_Vg_Node * obj,int x,int y,int w,int h)750 evas_vg_node_geometry_set(Evas_Vg_Node *obj, int x, int y, int w, int h)
751 {
752    efl_gfx_entity_position_set(obj, EINA_POSITION2D(x, y));
753    efl_gfx_entity_size_set(obj, EINA_SIZE2D(w,  h));
754 }
755 
756 EAPI void
evas_vg_node_stack_below(Evas_Vg_Node * obj,Eo * below)757 evas_vg_node_stack_below(Evas_Vg_Node *obj, Eo *below)
758 {
759    efl_gfx_stack_below(obj, below);
760 }
761 
762 EAPI void
evas_vg_node_stack_above(Evas_Vg_Node * obj,Eo * above)763 evas_vg_node_stack_above(Evas_Vg_Node *obj, Eo *above)
764 {
765    efl_gfx_stack_above(obj, above);
766 }
767 
768 EAPI void
evas_vg_node_raise(Evas_Vg_Node * obj)769 evas_vg_node_raise(Evas_Vg_Node *obj)
770 {
771    efl_gfx_stack_raise_to_top(obj);
772 }
773 
774 EAPI void
evas_vg_node_lower(Evas_Vg_Node * obj)775 evas_vg_node_lower(Evas_Vg_Node *obj)
776 {
777    efl_gfx_stack_lower_to_bottom(obj);
778 }
779 
780 #include "efl_canvas_vg_node.eo.c"
781 #include "efl_canvas_vg_node_eo.legacy.c"
782