#ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #define MY_CLASS EFL_GFX_SHAPE_MIXIN typedef struct _Efl_Gfx_Shape_Data { Efl_Gfx_Shape_Public public; Efl_Gfx_Fill_Rule fill_rule; } Efl_Gfx_Shape_Data; static inline double interpolate(double from, double to, double pos_map) { return (from * (1.0 - pos_map)) + (to * pos_map); } static inline int interpolatei(int from, int to, double pos_map) { return (from * (1.0 - pos_map)) + (to * pos_map); } typedef struct _Efl_Gfx_Property Efl_Gfx_Property; struct _Efl_Gfx_Property { double scale; double w; double centered; Efl_Gfx_Cap c; Efl_Gfx_Join j; const Efl_Gfx_Dash *dash; unsigned int dash_length; int r, g, b, a; }; static inline void _efl_gfx_property_get(const Eo *obj, Efl_Gfx_Property *property) { property->scale = efl_gfx_shape_stroke_scale_get(obj); efl_gfx_shape_stroke_color_get(obj, &property->r, &property->g, &property->b, &property->a); property->w = efl_gfx_shape_stroke_width_get(obj); property->centered = efl_gfx_shape_stroke_location_get(obj); efl_gfx_shape_stroke_dash_get(obj, &property->dash, &property->dash_length); property->c = efl_gfx_shape_stroke_cap_get(obj); property->j = efl_gfx_shape_stroke_join_get(obj); } EOLIAN static Eina_Bool _efl_gfx_shape_efl_gfx_path_interpolate(Eo *obj, Efl_Gfx_Shape_Data *pd, const Eo *from, const Eo *to, double pos_map) { Efl_Gfx_Shape_Data *from_pd, *to_pd; Efl_Gfx_Property property_from, property_to; Efl_Gfx_Dash *dash = NULL; double interv; //interpolated value unsigned int i; if (!efl_isa(from, EFL_GFX_SHAPE_MIXIN) || !efl_isa(to, EFL_GFX_SHAPE_MIXIN)) return EINA_FALSE; from_pd = efl_data_scope_get(from, EFL_GFX_SHAPE_MIXIN); to_pd = efl_data_scope_get(to, EFL_GFX_SHAPE_MIXIN); if ((pd == from_pd) || (pd == to_pd)) return EINA_FALSE; _efl_gfx_property_get(from, &property_from); _efl_gfx_property_get(to, &property_to); //Can be interpolated! if (property_from.dash_length != property_to.dash_length) return EINA_FALSE; if (property_to.dash_length) { dash = malloc(sizeof (Efl_Gfx_Dash) * property_to.dash_length); if (!dash) return EINA_FALSE; for (i = 0; i < property_to.dash_length; i++) { dash[i].length = interpolate(property_from.dash[i].length, property_to.dash[i].length, pos_map); dash[i].gap = interpolate(property_from.dash[i].gap, property_to.dash[i].gap, pos_map); } } interv = interpolate(property_from.scale, property_to.scale, pos_map); efl_gfx_shape_stroke_scale_set(obj, interv); efl_gfx_shape_stroke_color_set(obj, interpolatei(property_from.r, property_to.r, pos_map), interpolatei(property_from.g, property_to.g, pos_map), interpolatei(property_from.b, property_to.b, pos_map), interpolatei(property_from.a, property_to.a, pos_map)); interv = interpolate(property_from.w, property_to.w, pos_map); efl_gfx_shape_stroke_width_set(obj, interv); interv = interpolate(property_from.centered, property_to.centered, pos_map); efl_gfx_shape_stroke_location_set(obj, interv); efl_gfx_shape_stroke_dash_set(obj, dash, property_to.dash_length); efl_gfx_shape_stroke_cap_set(obj, (pos_map < 0.5) ? property_from.c : property_to.c); efl_gfx_shape_stroke_join_set(obj, (pos_map < 0.5) ? property_from.j : property_to.j); return efl_gfx_path_interpolate(efl_cast(obj, EFL_GFX_PATH_MIXIN), from, to, pos_map); } EOLIAN static void _efl_gfx_shape_stroke_scale_set(Eo *obj EINA_UNUSED, Efl_Gfx_Shape_Data *pd, double s) { pd->public.stroke.scale = s; } EOLIAN static double _efl_gfx_shape_stroke_scale_get(const Eo *obj EINA_UNUSED, Efl_Gfx_Shape_Data *pd) { return pd->public.stroke.scale; } EOLIAN static void _efl_gfx_shape_stroke_color_set(Eo *obj EINA_UNUSED, Efl_Gfx_Shape_Data *pd, int r, int g, int b, int a) { pd->public.stroke.color.r = r; pd->public.stroke.color.g = g; pd->public.stroke.color.b = b; pd->public.stroke.color.a = a; } EOLIAN static void _efl_gfx_shape_stroke_color_get(const Eo *obj EINA_UNUSED, Efl_Gfx_Shape_Data *pd, int *r, int *g, int *b, int *a) { if (r) *r = pd->public.stroke.color.r; if (g) *g = pd->public.stroke.color.g; if (b) *b = pd->public.stroke.color.b; if (a) *a = pd->public.stroke.color.a; } EOLIAN static void _efl_gfx_shape_stroke_width_set(Eo *obj, Efl_Gfx_Shape_Data *pd, double w) { pd->public.stroke.width = w; } EOLIAN static double _efl_gfx_shape_stroke_width_get(const Eo *obj EINA_UNUSED, Efl_Gfx_Shape_Data *pd) { return pd->public.stroke.width; } EOLIAN static void _efl_gfx_shape_stroke_location_set(Eo *obj EINA_UNUSED, Efl_Gfx_Shape_Data *pd, double centered) { pd->public.stroke.centered = centered; } EOLIAN static double _efl_gfx_shape_stroke_location_get(const Eo *obj EINA_UNUSED, Efl_Gfx_Shape_Data *pd) { return pd->public.stroke.centered; } EOLIAN static void _efl_gfx_shape_stroke_dash_set(Eo *obj EINA_UNUSED, Efl_Gfx_Shape_Data *pd, const Efl_Gfx_Dash *dash, unsigned int length) { Efl_Gfx_Dash *tmp; if (!dash) { free(pd->public.stroke.dash); pd->public.stroke.dash = NULL; pd->public.stroke.dash_length = 0; return; } tmp = realloc(pd->public.stroke.dash, length * sizeof (Efl_Gfx_Dash)); if (!tmp && length) return; memcpy(tmp, dash, length * sizeof (Efl_Gfx_Dash)); pd->public.stroke.dash = tmp; pd->public.stroke.dash_length = length; } EOLIAN static void _efl_gfx_shape_stroke_dash_get(const Eo *obj EINA_UNUSED, Efl_Gfx_Shape_Data *pd, const Efl_Gfx_Dash **dash, unsigned int *length) { if (dash) *dash = pd->public.stroke.dash; if (length) *length = pd->public.stroke.dash_length; } EOLIAN static void _efl_gfx_shape_stroke_cap_set(Eo *obj EINA_UNUSED, Efl_Gfx_Shape_Data *pd, Efl_Gfx_Cap c) { pd->public.stroke.cap = c; } EOLIAN static Efl_Gfx_Cap _efl_gfx_shape_stroke_cap_get(const Eo *obj EINA_UNUSED, Efl_Gfx_Shape_Data *pd) { return pd->public.stroke.cap; } EOLIAN static void _efl_gfx_shape_stroke_join_set(Eo *obj EINA_UNUSED, Efl_Gfx_Shape_Data *pd, Efl_Gfx_Join j) { pd->public.stroke.join = j; } EOLIAN static Efl_Gfx_Join _efl_gfx_shape_stroke_join_get(const Eo *obj EINA_UNUSED, Efl_Gfx_Shape_Data *pd) { return pd->public.stroke.join; } EOLIAN static void _efl_gfx_shape_fill_rule_set(Eo *obj EINA_UNUSED, Efl_Gfx_Shape_Data *pd, Efl_Gfx_Fill_Rule fill_rule) { pd->fill_rule = fill_rule; } EOLIAN static Efl_Gfx_Fill_Rule _efl_gfx_shape_fill_rule_get(const Eo *obj EINA_UNUSED, Efl_Gfx_Shape_Data *pd) { return pd->fill_rule; } EOLIAN static void _efl_gfx_shape_efl_gfx_path_copy_from(Eo *obj, Efl_Gfx_Shape_Data *pd, const Eo *dup_from) { Efl_Gfx_Shape_Data *from; if (obj == dup_from) return; from = efl_data_scope_get(dup_from, MY_CLASS); if (!from) return; pd->public.stroke.scale = from->public.stroke.scale; pd->public.stroke.width = from->public.stroke.width; pd->public.stroke.centered = from->public.stroke.centered; pd->public.stroke.cap = from->public.stroke.cap; pd->public.stroke.join = from->public.stroke.join; pd->public.stroke.color.r = from->public.stroke.color.r; pd->public.stroke.color.g = from->public.stroke.color.g; pd->public.stroke.color.b = from->public.stroke.color.b; pd->public.stroke.color.a = from->public.stroke.color.a; pd->fill_rule = from->fill_rule; _efl_gfx_shape_stroke_dash_set(obj, pd, from->public.stroke.dash, from->public.stroke.dash_length); efl_gfx_path_copy_from(efl_super(obj, MY_CLASS), dup_from); } #include "interfaces/efl_gfx_shape.eo.c"