@out r: Eina.Rectangle; [[bounding box to be returned.]]
}
}
+ interpolate {
+ return: bool;
+ params {
+ @in from: const(Efl.VG.Base)*;
+ @in to: const(Efl.VG.Base)*;
+ @in pos_map: double;
+ }
+ }
}
implements {
Eo.Base.parent.set;
Eo.Base.constructor;
Eo.Base.destructor;
Efl.VG.Base.bounds_get;
+ Efl.VG.Base.interpolate;
}
}
Efl.Gfx.Gradient.Base.stop.get;
Efl.Gfx.Gradient.Base.spread.set;
Efl.Gfx.Gradient.Base.spread.get;
+ Efl.VG.Base.interpolate;
}
}
Efl.Gfx.Gradient.Linear.end.set;
Efl.Gfx.Gradient.Linear.end.get;
Efl.VG.Base.bounds_get;
+ Efl.VG.Base.interpolate;
Eo.Base.constructor;
Eo.Base.destructor;
}
Efl.Gfx.Gradient.Radial.focal.set;
Efl.Gfx.Gradient.Radial.focal.get;
Efl.VG.Base.bounds_get;
+ Efl.VG.Base.interpolate;
Eo.Base.constructor;
Eo.Base.destructor;
}
Efl.Gfx.Base.color_part.set;
Efl.Gfx.Base.color_part.get;
Efl.VG.Base.bounds_get;
+ Efl.VG.Base.interpolate;
Eo.Base.constructor;
Eo.Base.destructor;
}
return eina_list_iterator_new(pd->children);
}
+static Eina_Bool
+_efl_vg_container_efl_vg_base_interpolate(Eo *obj,
+ Efl_VG_Container_Data *pd,
+ const Efl_VG_Base *from, const Efl_VG_Base *to,
+ double pos_map)
+{
+ Efl_VG_Container_Data *fd;
+ Efl_VG_Container_Data *td;
+ Eina_Iterator *it;
+ Eina_Hash_Tuple *tuple;
+ Eina_Bool r;
+
+ eo_do_super(obj, EFL_VG_CONTAINER_CLASS, r = efl_vg_interpolate(from, to, pos_map));
+
+ if (!r) return EINA_FALSE;
+
+ fd = eo_data_scope_get(from, EFL_VG_CONTAINER_CLASS);
+ td = eo_data_scope_get(to, EFL_VG_CONTAINER_CLASS);
+
+ it = eina_hash_iterator_tuple_new(pd->names);
+ EINA_ITERATOR_FOREACH(it, tuple)
+ {
+ Eo *fromc, *toc;
+ Eo *cc = tuple->data;
+
+ fromc = eina_hash_find(fd->names, tuple->key);
+ toc = eina_hash_find(td->names, tuple->key);
+
+ if (!toc || !fromc) continue ;
+ if (eo_class_get(toc) != eo_class_get(fromc)) continue ;
+
+ eo_do(cc, r &= efl_vg_interpolate(fromc, toc, pos_map));
+ }
+ eina_iterator_free(it);
+
+ return r;
+}
+
EAPI Efl_VG*
evas_vg_container_add(Efl_VG *parent)
{
return pd->s;
}
+static Eina_Bool
+_efl_vg_gradient_efl_vg_base_interpolate(Eo *obj,
+ Efl_VG_Gradient_Data *pd,
+ const Efl_VG_Base *from, const Efl_VG_Base *to,
+ double pos_map)
+{
+ Efl_VG_Gradient_Data *fromd, *tod;
+ Efl_Gfx_Gradient_Stop *colors;
+ unsigned int i;
+ double from_map;
+ Eina_Bool r;
+
+ eo_do_super(obj, EFL_VG_GRADIENT_CLASS, r = efl_vg_interpolate(from, to, pos_map));
+
+ fromd = eo_data_scope_get(from, EFL_VG_GRADIENT_CLASS);
+ tod = eo_data_scope_get(to, EFL_VG_GRADIENT_CLASS);
+ from_map = 1.0 - pos_map;
+
+ if (!r) return EINA_FALSE;
+ if (fromd->colors_count != tod->colors_count) return EINA_FALSE;
+
+ colors = realloc(pd->colors, sizeof (Efl_Gfx_Gradient_Stop) * tod->colors_count);
+ if (!colors) return EINA_FALSE;
+
+ pd->colors = colors;
+
+#define INTP(Pd, From, To, I, Member, From_Map, Pos_Map) \
+ Pd->colors[I].Member = From->colors[I].Member * From_Map + To->colors[I].Member * Pos_Map
+
+ for (i = 0; i < fromd->colors_count; i++)
+ {
+ INTP(pd, fromd, tod, i, offset, from_map, pos_map);
+ INTP(pd, fromd, tod, i, r, from_map, pos_map);
+ INTP(pd, fromd, tod, i, g, from_map, pos_map);
+ INTP(pd, fromd, tod, i, b, from_map, pos_map);
+ INTP(pd, fromd, tod, i, a, from_map, pos_map);
+ }
+
+#undef INTP
+
+ return EINA_TRUE;
+}
+
EAPI void
evas_vg_gradient_stop_set(Eo *obj, const Efl_Gfx_Gradient_Stop *colors, unsigned int length)
{
pd->end.x - pd->start.x, pd->end.y - pd->start.x);
}
+static Eina_Bool
+_efl_vg_gradient_linear_efl_vg_base_interpolate(Eo *obj,
+ Efl_VG_Gradient_Linear_Data *pd,
+ const Efl_VG_Base *from, const Efl_VG_Base *to,
+ double pos_map)
+{
+ Efl_VG_Gradient_Linear_Data *fromd, *tod;
+ double from_map;
+ Eina_Bool r;
+
+ eo_do_super(obj, EFL_VG_GRADIENT_LINEAR_CLASS, r = efl_vg_interpolate(from, to, pos_map));
+
+ if (!r) return EINA_FALSE;
+
+ fromd = eo_data_scope_get(from, EFL_VG_GRADIENT_LINEAR_CLASS);
+ tod = eo_data_scope_get(to, EFL_VG_GRADIENT_LINEAR_CLASS);
+ from_map = 1.0 - pos_map;
+
+#define INTP(Pd, From, To, Member, From_Map, Pos_Map) \
+ Pd->Member = From->Member * From_Map + To->Member * Pos_Map
+
+ INTP(pd, fromd, tod, start.x, from_map, pos_map);
+ INTP(pd, fromd, tod, start.y, from_map, pos_map);
+ INTP(pd, fromd, tod, end.x, from_map, pos_map);
+ INTP(pd, fromd, tod, end.y, from_map, pos_map);
+
+#undef INTP
+
+ return EINA_TRUE;
+}
+
EAPI void
evas_vg_gradient_linear_start_set(Eo *obj, double x, double y)
{
pd->radius * 2, pd->radius * 2);
}
+static Eina_Bool
+_efl_vg_gradient_radial_efl_vg_base_interpolate(Eo *obj,
+ Efl_VG_Gradient_Radial_Data *pd,
+ const Efl_VG_Base *from, const Efl_VG_Base *to,
+ double pos_map)
+{
+ Efl_VG_Gradient_Radial_Data *fromd, *tod;
+ double from_map;
+ Eina_Bool r;
+
+ eo_do_super(obj, EFL_VG_GRADIENT_RADIAL_CLASS, r = efl_vg_interpolate(from, to, pos_map));
+
+ if (!r) return EINA_FALSE;
+
+ fromd = eo_data_scope_get(from, EFL_VG_GRADIENT_RADIAL_CLASS);
+ tod = eo_data_scope_get(to, EFL_VG_GRADIENT_RADIAL_CLASS);
+ from_map = 1.0 - pos_map;
+
+#define INTP(Pd, From, To, Member, From_Map, Pos_Map) \
+ Pd->Member = From->Member * From_Map + To->Member * Pos_Map
+
+ INTP(pd, fromd, tod, focal.x, from_map, pos_map);
+ INTP(pd, fromd, tod, focal.y, from_map, pos_map);
+ INTP(pd, fromd, tod, center.x, from_map, pos_map);
+ INTP(pd, fromd, tod, center.y, from_map, pos_map);
+ INTP(pd, fromd, tod, radius, from_map, pos_map);
+
+#undef INTP
+
+ return EINA_TRUE;
+}
+
EAPI void
evas_vg_gradient_radial_center_set(Eo *obj, double x, double y)
{
#define MY_CLASS EFL_VG_BASE_CLASS
+static const Efl_VG_Interpolation interpolation_identity = {
+ { 0, 0, 0, 1 },
+ { 0, 0, 0, 1 },
+ { 0, 0, 0 },
+ { 1, 1, 1 },
+ { 0, 0, 0 }
+};
+
static Eina_Bool
_efl_vg_base_property_changed(void *data, Eo *obj, const Eo_Event_Description *desc, void *event_info)
{
Efl_VG_Base_Data *pd,
const Eina_Matrix3 *m)
{
+ if (pd->intp)
+ {
+ free(pd->intp);
+ pd->intp = NULL;
+ }
+
if (m)
{
if (!pd->m)
eo_del(pd->renderer);
pd->renderer = NULL;
}
+ if (pd->intp)
+ {
+ free(pd->intp);
+ pd->intp = NULL;
+ }
eo_do_super(obj, MY_CLASS, eo_destructor());
}
return above;
}
+static Efl_VG_Interpolation *
+_efl_vg_interpolation_get(Efl_VG_Base_Data *pd)
+{
+ Eina_Matrix4 m;
+
+ if (!pd->m) return NULL;
+ if (pd->intp) return pd->intp;
+
+ pd->intp = calloc(1, sizeof (Efl_VG_Interpolation));
+ if (!pd->intp) return NULL;
+
+ eina_matrix3_matrix4_to(&m, pd->m);
+
+ if (eina_matrix4_quaternion_to(&pd->intp->rotation,
+ &pd->intp->perspective,
+ &pd->intp->translation,
+ &pd->intp->scale,
+ &pd->intp->skew,
+ &m))
+ return pd->intp;
+
+ free(pd->intp);
+ pd->intp = NULL;
+
+ return NULL;
+}
+
+static inline void
+_efl_vg_interpolate_point(Eina_Point_3D *d,
+ const Eina_Point_3D *a, const Eina_Point_3D *b,
+ double pos_map, double from_map)
+{
+ d->x = a->x * from_map + b->x * pos_map;
+ d->y = a->y * from_map + b->y * pos_map;
+ d->z = a->z * from_map + b->z * pos_map;
+}
+
+static Eina_Bool
+_efl_vg_base_interpolate(Eo *obj,
+ Efl_VG_Base_Data *pd, const Efl_VG_Base *from, const Efl_VG_Base *to,
+ double pos_map)
+{
+ Efl_VG_Base_Data *fromd, *tod;
+ double from_map;
+ Eina_Bool r = EINA_TRUE;
+
+ fromd = eo_data_scope_get(from, EFL_VG_BASE_CLASS);
+ tod = eo_data_scope_get(to, EFL_VG_BASE_CLASS);
+ from_map = 1.0 - pos_map;
+
+ eo_del(pd->renderer);
+ pd->renderer = NULL;
+
+ if (fromd->m || tod->m)
+ {
+ if (!pd->m) pd->m = malloc(sizeof (Eina_Matrix3));
+ if (pd->m)
+ {
+ const Efl_VG_Interpolation *fi, *ti;
+ Efl_VG_Interpolation result;
+ Eina_Matrix4 m;
+
+ fi = _efl_vg_interpolation_get(fromd);
+ if (!fi) fi = &interpolation_identity;
+ ti = _efl_vg_interpolation_get(tod);
+ if (!ti) ti = &interpolation_identity;
+
+ eina_quaternion_slerp(&result.rotation,
+ &fi->rotation, &ti->rotation,
+ pos_map);
+ _efl_vg_interpolate_point(&result.translation,
+ &fi->translation, &ti->translation,
+ pos_map, from_map);
+ _efl_vg_interpolate_point(&result.scale,
+ &fi->scale, &ti->scale,
+ pos_map, from_map);
+ _efl_vg_interpolate_point(&result.skew,
+ &fi->skew, &ti->skew,
+ pos_map, from_map);
+
+ result.perspective.x = fi->perspective.x * from_map + ti->perspective.x * pos_map;
+ result.perspective.y = fi->perspective.y * from_map + ti->perspective.y * pos_map;
+ result.perspective.z = fi->perspective.z * from_map + ti->perspective.z * pos_map;
+ result.perspective.w = fi->perspective.w * from_map + ti->perspective.w * pos_map;
+
+ eina_quaternion_matrix4_to(&m,
+ &result.rotation,
+ &result.perspective,
+ &result.translation,
+ &result.scale,
+ &result.skew);
+ eina_matrix4_matrix3_to(pd->m, &m);
+ }
+ }
+
+ pd->x = fromd->x * from_map + tod->x * pos_map;
+ pd->y = fromd->y * from_map + tod->y * pos_map;
+
+ pd->r = fromd->r * from_map + tod->r * pos_map;
+ pd->g = fromd->g * from_map + tod->g * pos_map;
+ pd->b = fromd->b * from_map + tod->b * pos_map;
+ pd->a = fromd->a * from_map + tod->a * pos_map;
+
+ pd->visibility = pos_map >= 0.5 ? tod->visibility : fromd->visibility;
+
+ if (fromd->mask && tod->mask && pd->mask)
+ {
+ eo_do(pd->mask,
+ r &= efl_vg_interpolate(fromd->mask, tod->mask, pos_map));
+ }
+
+ _efl_vg_base_changed(obj);
+
+ return r;
+}
+
+static void
+_efl_vg_base_dup(Eo *obj, Efl_VG_Base_Data *pd, const Efl_VG_Base *from)
+{
+ Efl_VG_Container_Data *cd = NULL;
+ Efl_VG_Base_Data *fromd;
+ Eo *parent = NULL;
+
+ fromd = eo_data_scope_get(from, EFL_VG_BASE_CLASS);
+ pd->name = eina_stringshare_ref(fromd->name);
+
+ _efl_vg_base_parent_checked_get(obj, &parent, &cd);
+ if (cd) _efl_vg_base_name_insert(obj, pd, cd);
+
+ if (pd->intp)
+ {
+ free(pd->intp);
+ pd->intp = NULL;
+ }
+
+ if (fromd->m)
+ {
+ pd->m = pd->m ? pd->m : malloc(sizeof (Eina_Matrix3)) ;
+ if (pd->m) memcpy(pd->m, fromd->m, sizeof (Eina_Matrix3));
+ }
+ else
+ {
+ free(pd->m);
+ }
+
+ // We may come from an already duped/initialized node, clean it first
+ _efl_vg_clean_object(&pd->mask);
+ if (fromd->mask)
+ {
+ pd->mask = eo_add(eo_class_get(fromd->mask),
+ obj,
+ efl_vg_dup(pd->mask));
+ }
+
+ pd->x = fromd->x;
+ pd->y = fromd->y;
+ pd->r = fromd->r;
+ pd->g = fromd->g;
+ pd->b = fromd->b;
+ pd->a = fromd->a;
+ pd->visibility = fromd->visibility;
+
+ _efl_vg_base_changed(obj);
+}
+
EAPI Eina_Bool
evas_vg_node_visible_get(Eo *obj)
{
typedef struct _Efl_VG_Base_Data Efl_VG_Base_Data;
typedef struct _Efl_VG_Container_Data Efl_VG_Container_Data;
typedef struct _Efl_VG_Gradient_Data Efl_VG_Gradient_Data;
+typedef struct _Efl_VG_Interpolation Efl_VG_Interpolation;
struct _Efl_VG_Base_Data
{
const char *name;
Eina_Matrix3 *m;
+ Efl_VG_Interpolation *intp;
+
Efl_VG *mask;
Ector_Renderer *renderer;
Efl_Gfx_Gradient_Spread s;
};
+struct _Efl_VG_Interpolation
+{
+ Eina_Quaternion rotation;
+ Eina_Quaternion perspective;
+ Eina_Point_3D translation;
+ Eina_Point_3D scale;
+ Eina_Point_3D skew;
+};
+
static inline Efl_VG_Base_Data *
_evas_vg_render_pre(Efl_VG *child, Ector_Surface *s, Eina_Matrix3 *m)
{
eo_do_super(obj, MY_CLASS, eo_destructor());
}
+static Eina_Bool
+_efl_vg_shape_efl_vg_base_interpolate(Eo *obj,
+ Efl_VG_Shape_Data *pd,
+ const Efl_VG_Base *from, const Efl_VG_Base *to,
+ double pos_map)
+{
+ Efl_VG_Shape_Data *fromd, *tod;
+ Eina_Bool r;
+
+ fromd = eo_data_scope_get(from, EFL_VG_SHAPE_CLASS);
+ tod = eo_data_scope_get(to, EFL_VG_SHAPE_CLASS);
+
+ eo_do_super(obj, MY_CLASS, r = efl_vg_interpolate(from, to, pos_map));
+
+ eo_do(obj, r &= efl_gfx_shape_interpolate(from, to, pos_map));
+
+ if (fromd->fill && tod->fill && pd->fill)
+ {
+ eo_do(pd->fill, r &= efl_vg_interpolate(fromd->fill, tod->fill, pos_map));
+ }
+ if (fromd->stroke.fill && tod->stroke.fill && pd->stroke.fill)
+ {
+ eo_do(pd->stroke.fill,
+ r &= efl_vg_interpolate(fromd->stroke.fill, tod->stroke.fill, pos_map));
+ }
+ if (fromd->stroke.marker && tod->stroke.marker && pd->stroke.marker)
+ {
+ eo_do(pd->stroke.marker,
+ r &= efl_vg_interpolate(fromd->stroke.marker, tod->stroke.marker, pos_map));
+ }
+
+ return r;
+}
+
EAPI double
evas_vg_shape_stroke_scale_get(Eo *obj)
{