efl/src/lib/efl/interfaces/efl_gfx_shape.c

292 lines
8.8 KiB
C

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <math.h>
#include <float.h>
#include <ctype.h>
#include <Efl.h>
#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"