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