#include "evas_map.h" // FIXME: cur vs. prev is not handled (may be an issue?) // FIXME: some render artifacts appear when this API is used (green pixels) #define EINA_INLIST_REMOVE(l,i) do { l = (__typeof__(l)) eina_inlist_remove(EINA_INLIST_GET(l), EINA_INLIST_GET(i)); } while (0) #define EINA_INLIST_APPEND(l,i) do { l = (__typeof__(l)) eina_inlist_append(EINA_INLIST_GET(l), EINA_INLIST_GET(i)); } while (0) #define EINA_INLIST_PREPEND(l,i) do { l = (__typeof__(l)) eina_inlist_prepend(EINA_INLIST_GET(l), EINA_INLIST_GET(i)); } while (0) #define EINA_INLIST_NEXT(l) (typeof(l)) EINA_INLIST_CONTAINER_GET(EINA_INLIST_GET(l)->next, typeof(*l)) #define MY_CLASS EFL_GFX_MAPPING_MIXIN typedef struct _Gfx_Map Gfx_Map; typedef struct _Gfx_Map_Op Gfx_Map_Op; typedef struct _Gfx_Map_Pivot Gfx_Map_Pivot; typedef struct _Efl_Gfx_Mapping_Data Efl_Gfx_Mapping_Data; typedef struct _Gfx_Map_Point Gfx_Map_Point; typedef enum _Gfx_Map_Op_Type Gfx_Map_Op_Type; enum _Gfx_Map_Op_Type { GFX_MAPPING_RAW_COORD, GFX_MAPPING_COLOR, GFX_MAPPING_ROTATE_2D, GFX_MAPPING_ROTATE_3D, GFX_MAPPING_ROTATE_QUAT, GFX_MAPPING_ZOOM, GFX_MAPPING_TRANSLATE, GFX_MAPPING_LIGHTING_3D, GFX_MAPPING_PERSPECTIVE_3D, }; struct _Gfx_Map_Op { EINA_INLIST; Gfx_Map_Op_Type op; union { struct { int idx; double x, y, z; } raw_coord; struct { int idx; uint8_t r, g, b, a; } color; struct { double degrees; } rotate_2d; struct { double dx, dy, dz; } rotate_3d; struct { double qx, qy, qz, qw; } rotate_quat; struct { double zx, zy; } zoom; struct { double dx, dy, dz; } translate; struct { uint8_t lr, lg, lb, ar, ag, ab; } lighting_3d; struct { double z0, foc; } perspective_3d; }; struct { Gfx_Map_Pivot *pivot; double cx, cy, cz; Eina_Bool is_absolute; Eina_Bool is_self; } pivot; }; struct _Gfx_Map_Pivot { EINA_INLIST; Evas_Object_Protected_Data *map_obj; Eo *eo_obj; // strong or weak ref? Eina_Rect geometry; Eina_Bool event_cbs; Eina_Bool is_evas; Eina_Bool is_canvas; Eina_Bool changed; }; struct _Gfx_Map_Point { double u, v; }; struct _Gfx_Map { Gfx_Map_Op *ops; Gfx_Map_Point *points; Gfx_Map_Pivot *pivots; Evas_Map *map; Gfx_Map_Op *last_calc_op; int imw, imh; int count; // FIXME: Those need a quality vs. performance setting instead Eina_Bool alpha; Eina_Bool smooth; Eina_Bool event_cbs; }; struct _Efl_Gfx_Mapping_Data { const Gfx_Map *cow; }; // ---------------------------------------------------------------------------- static Eo *gfx_mapping_absolute = NULL; static Eina_Cow *gfx_mapping_cow = NULL; static const Gfx_Map gfx_mapping_cow_default = { NULL, NULL, NULL, NULL, NULL, 0, 0, 4, EINA_TRUE, EINA_TRUE, EINA_FALSE }; #define MAPCOW_BEGIN(_pd) eina_cow_write(gfx_mapping_cow, (const Eina_Cow_Data**)&(_pd->cow)) #define MAPCOW_END(_mapcow, _pd) eina_cow_done(gfx_mapping_cow, (const Eina_Cow_Data**)&(_pd->cow), _mapcow, EINA_FALSE) #define MAPCOW_WRITE(pd, name, value) do { \ if (pd->cow->name != (value)) { \ Gfx_Map *_cow = MAPCOW_BEGIN(pd); \ _cow->name = (value); \ MAPCOW_END(_cow, pd); \ }} while (0) #define PIVOT_REF(_pivot) (_pivot ? efl_xref((Eo *) _pivot, eo_obj) : NULL) #define PIVOT_UNREF(_pivot) (_pivot ? efl_xunref(_pivot, eo_obj) : NULL) static inline void _map_clean(Eo *eo_obj, Efl_Gfx_Mapping_Data *pd); // ---------------------------------------------------------------------------- void _efl_gfx_mapping_init(void) { gfx_mapping_cow = eina_cow_add("Efl.Gfx.Mapping", sizeof(Gfx_Map), 8, &gfx_mapping_cow_default, EINA_FALSE); } void _efl_gfx_mapping_shutdown(void) { eina_cow_del(gfx_mapping_cow); gfx_mapping_cow = NULL; efl_unref(gfx_mapping_absolute); gfx_mapping_absolute = NULL; } // ---------------------------------------------------------------------------- EOLIAN static Efl_Object * _efl_gfx_mapping_efl_object_constructor(Eo *eo_obj, Efl_Gfx_Mapping_Data *pd) { eo_obj = efl_constructor(efl_super(eo_obj, MY_CLASS)); pd->cow = eina_cow_alloc(gfx_mapping_cow); return eo_obj; } EOLIAN static void _efl_gfx_mapping_efl_object_destructor(Eo *eo_obj, Efl_Gfx_Mapping_Data *pd) { if (pd->cow) { _map_clean(eo_obj, pd); eina_cow_free(gfx_mapping_cow, (const Eina_Cow_Data **) &pd->cow); } efl_destructor(efl_super(eo_obj, MY_CLASS)); } // ---------------------------------------------------------------------------- static void _geometry_changed_cb(void *data, const Efl_Event *ev EINA_UNUSED) { Evas_Object_Protected_Data *obj = data; Efl_Gfx_Mapping_Data *pd = efl_data_scope_get(obj->object, MY_CLASS); MAPCOW_WRITE(pd, last_calc_op, NULL); obj->gfx_mapping_update = EINA_TRUE; } EFL_CALLBACKS_ARRAY_DEFINE(_geometry_changes, { EFL_GFX_ENTITY_EVENT_POSITION_CHANGED, _geometry_changed_cb }, { EFL_GFX_ENTITY_EVENT_SIZE_CHANGED, _geometry_changed_cb }); static void _pivot_changed_cb(void *data, const Efl_Event *ev EINA_UNUSED) { Gfx_Map_Pivot *pivot = data; Evas_Object_Protected_Data *obj = pivot->map_obj; obj->gfx_mapping_update = EINA_TRUE; pivot->changed = EINA_TRUE; } EFL_CALLBACKS_ARRAY_DEFINE(_pivot_changes, { EFL_GFX_ENTITY_EVENT_POSITION_CHANGED, _pivot_changed_cb }, { EFL_GFX_ENTITY_EVENT_SIZE_CHANGED, _pivot_changed_cb }); static inline void _map_dirty(Eo *eo_obj, Efl_Gfx_Mapping_Data *pd, Eina_Bool reset) { Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj); Gfx_Map_Pivot *pivot; obj->gfx_mapping_has = EINA_TRUE; obj->gfx_mapping_update |= !reset; obj->changed_map = EINA_TRUE; evas_object_change(eo_obj, obj); if (reset) { _evas_map_reset(pd->cow->map); return; } // FIXME: Only add if there is a self-pivot (relative coordinates) if (!pd->cow->event_cbs) { MAPCOW_WRITE(pd, event_cbs, EINA_TRUE); efl_event_callback_array_add(eo_obj, _geometry_changes(), obj); } EINA_INLIST_FOREACH(pd->cow->pivots, pivot) { if (pivot->event_cbs) continue; pivot->event_cbs = EINA_TRUE; efl_event_callback_array_add(pivot->eo_obj, _pivot_changes(), pivot); } } static Evas_Map * _map_calc(const Eo *eo_obj, Evas_Object_Protected_Data *obj, Efl_Gfx_Mapping_Data *pd) { Gfx_Map_Op *op, *first_op = pd->cow->ops, *last_op; Gfx_Map_Pivot *pivot; Gfx_Map *mcow; Evas_Map *m; int imw, imh; int count; Eina_Bool map_alloc = EINA_FALSE; if (pd->cow == &gfx_mapping_cow_default) return NULL; m = pd->cow->map; if (!obj->gfx_mapping_update) return m; last_op = pd->cow->last_calc_op; count = pd->cow->count < 4 ? 4 : pd->cow->count; EINA_INLIST_FOREACH(pd->cow->pivots, pivot) { if (!pivot->changed) continue; last_op = NULL; pivot->changed = EINA_FALSE; if (!pivot->is_canvas) { pivot->geometry = efl_gfx_entity_geometry_get(pivot->eo_obj); } else { // Note: pivot can not be an Evas when using pure EO API if (pivot->is_evas) evas_output_size_get(pivot->eo_obj, &pivot->geometry.w, &pivot->geometry.h); else pivot->geometry.size = efl_gfx_entity_size_get(pivot->eo_obj); pivot->geometry.x = 0; pivot->geometry.y = 0; } } if (!pd->cow->points) { Gfx_Map_Point *ps = calloc(1, count * sizeof(Gfx_Map_Point)); if (!ps) return m; ps[0].u = 0.0; ps[0].v = 0.0; ps[1].u = 1.0; ps[1].v = 0.0; ps[2].u = 1.0; ps[2].v = 1.0; ps[3].u = 0.0; ps[3].v = 1.0; MAPCOW_WRITE(pd, points, ps); } if (m && last_op) { first_op = EINA_INLIST_NEXT(last_op); imw = pd->cow->imw; imh = pd->cow->imh; } else { if (!m) { m = evas_map_new(count); if (!m) return NULL; map_alloc = EINA_TRUE; } else _evas_map_reset(m); m->alpha = pd->cow->alpha; m->smooth = pd->cow->smooth; m->move_sync.enabled = EINA_FALSE; _evas_map_util_points_populate(m, obj->cur->geometry.x, obj->cur->geometry.y, obj->cur->geometry.w, obj->cur->geometry.h, 0); if (obj->is_image_object) { // Image is a special case in terms of geometry Eina_Size2D sz; sz = efl_gfx_view_size_get(eo_obj); imw = sz.w; imh = sz.h; } else { imw = obj->cur->geometry.w; imh = obj->cur->geometry.h; } last_op = NULL; first_op = pd->cow->ops; } for (int k = 0; k < count; k++) { Evas_Map_Point *p = &(m->points[k]); p->u = pd->cow->points[k].u * imw; p->v = pd->cow->points[k].v * imh; } EINA_INLIST_FOREACH(first_op, op) { int k, kmin = 0, kmax = count - 1; double cx, cy, cz; Evas_Map_Point *p; if (!op->pivot.is_absolute) { int px = 0, py = 0, pw = 1, ph = 1; if (op->pivot.is_self) { px = obj->cur->geometry.x; py = obj->cur->geometry.y; pw = obj->cur->geometry.w; ph = obj->cur->geometry.h; } else { if (!op->pivot.pivot) { EINA_SAFETY_ERROR("safety check failed: op->pivot.pivot == NULL"); if (map_alloc) evas_map_free(m); return NULL; } pivot = op->pivot.pivot; px = pivot->geometry.x; py = pivot->geometry.y; pw = pivot->geometry.w; ph = pivot->geometry.h; } cx = (double) px + (double) pw * op->pivot.cx; cy = (double) py + (double) ph * op->pivot.cy; cz = op->pivot.cz; } else { cx = op->pivot.cx; cy = op->pivot.cy; cz = op->pivot.cz; } switch (op->op) { case GFX_MAPPING_RAW_COORD: if (op->raw_coord.idx != -1) kmin = kmax = op->raw_coord.idx; for (k = kmin; k <= kmax; k++) { p = &(m->points[k]); p->px = p->x = op->raw_coord.x; p->py = p->y = op->raw_coord.y; p->z = op->raw_coord.z; } break; case GFX_MAPPING_COLOR: if (op->raw_coord.idx != -1) kmin = kmax = op->raw_coord.idx; for (k = kmin; k <= kmax; k++) { p = &(m->points[k]); p->r = op->color.r; p->g = op->color.g; p->b = op->color.b; p->a = op->color.a; } break; case GFX_MAPPING_ROTATE_2D: _map_util_rotate(m, op->rotate_2d.degrees, cx, cy); break; case GFX_MAPPING_ROTATE_3D: _map_util_3d_rotate(m, op->rotate_3d.dx, op->rotate_3d.dy, op->rotate_3d.dz, cx, cy, cz); break; case GFX_MAPPING_ROTATE_QUAT: _map_util_quat_rotate(m, op->rotate_quat.qx, op->rotate_quat.qy, op->rotate_quat.qz, op->rotate_quat.qw, cx, cy, cz); break; case GFX_MAPPING_ZOOM: _map_util_zoom(m, op->zoom.zx, op->zoom.zy, cx, cy); break; case GFX_MAPPING_TRANSLATE: _map_util_translate(m, op->translate.dx, op->translate.dy, op->translate.dz); break; case GFX_MAPPING_LIGHTING_3D: _map_util_3d_lighting(m, cx, cy, cz, op->lighting_3d.lr, op->lighting_3d.lg, op->lighting_3d.lb, op->lighting_3d.ar, op->lighting_3d.ag, op->lighting_3d.ab); break; case GFX_MAPPING_PERSPECTIVE_3D: _map_util_3d_perspective(m, cx, cy, op->perspective_3d.z0, op->perspective_3d.foc); break; } last_op = op; } mcow = MAPCOW_BEGIN(pd); mcow->map = m; mcow->last_calc_op = last_op; mcow->imw = imw; mcow->imh = imh; MAPCOW_END(mcow, pd); obj->gfx_mapping_update = EINA_FALSE; return m; } void _efl_gfx_mapping_update(Eo *eo_obj) { Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj); Efl_Gfx_Mapping_Data *pd = efl_data_scope_get(eo_obj, MY_CLASS); Evas_Map *m; m = _map_calc(eo_obj, obj, pd); evas_object_map_set(eo_obj, m); _evas_object_map_enable_set(eo_obj, obj, m != NULL); obj->gfx_mapping_has = (m != NULL); } static inline void _map_clean(Eo *eo_obj, Efl_Gfx_Mapping_Data *pd) { free(pd->cow->points); if (pd->cow->map) evas_map_free(pd->cow->map); if (pd->cow->ops) { Gfx_Map_Pivot *pivot; Gfx_Map_Op *op; Gfx_Map *mcow; mcow = MAPCOW_BEGIN(pd); EINA_INLIST_FREE(mcow->ops, op) { EINA_INLIST_REMOVE(mcow->ops, op); free(op); } EINA_INLIST_FREE(mcow->pivots, pivot) { EINA_INLIST_REMOVE(mcow->pivots, pivot); if (pivot->event_cbs) efl_event_callback_array_del(pivot->eo_obj, _pivot_changes(), pivot); PIVOT_UNREF(pivot->eo_obj); free(pivot); } MAPCOW_END(mcow, pd); } } EOLIAN Eina_Bool _efl_gfx_mapping_mapping_has(Eo *eo_obj EINA_UNUSED, Efl_Gfx_Mapping_Data *pd EINA_UNUSED) { if (pd->cow == &gfx_mapping_cow_default) return EINA_FALSE; if (pd->cow->ops) return EINA_TRUE; if (pd->cow->map) return EINA_TRUE; return EINA_FALSE; } EOLIAN static void _efl_gfx_mapping_mapping_reset(Eo *eo_obj, Efl_Gfx_Mapping_Data *pd) { Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj); Eina_Bool alpha, smooth; alpha = pd->cow->alpha; smooth = pd->cow->smooth; _map_clean(eo_obj, pd); if (pd->cow->event_cbs) efl_event_callback_array_del(eo_obj, _geometry_changes(), obj); eina_cow_memcpy(gfx_mapping_cow, (const Eina_Cow_Data * const *) &pd->cow, (const Eina_Cow_Data *) &gfx_mapping_cow_default); _map_dirty(eo_obj, pd, EINA_TRUE); MAPCOW_WRITE(pd, alpha, alpha); MAPCOW_WRITE(pd, smooth, smooth); } EOLIAN static int _efl_gfx_mapping_mapping_point_count_get(const Eo *eo_obj EINA_UNUSED, Efl_Gfx_Mapping_Data *pd) { return pd->cow->count; } EOLIAN static void _efl_gfx_mapping_mapping_point_count_set(Eo *eo_obj EINA_UNUSED, Efl_Gfx_Mapping_Data *pd, int count) { Gfx_Map *mcow; if ((count <= 0) || (count % 4 != 0)) { ERR("Map point count (%d) should be multiples of 4", count); return; } if (pd->cow->count == count) return; mcow = MAPCOW_BEGIN(pd); if (mcow->points == NULL) { mcow->points = calloc(1, count * sizeof(Gfx_Map_Point)); if (mcow->points) mcow->count = count; else ERR("Failed to allocate memory with calloc"); } else { Gfx_Map_Point *ps = realloc(mcow->points, count * sizeof(Gfx_Map_Point)); if (ps) { mcow->points = ps; mcow->count = count; memset(mcow->points, 0, count * sizeof(Gfx_Map_Point)); } else ERR("Failed to allocate memory with realloc"); } MAPCOW_END(mcow, pd); } EOLIAN static Eina_Bool _efl_gfx_mapping_mapping_clockwise_get(const Eo *eo_obj, Efl_Gfx_Mapping_Data *pd) { Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj, EINA_TRUE); Evas_Map *m; m = _map_calc(eo_obj, obj, pd); if (!m) return EINA_TRUE; return evas_map_util_clockwise_get(m); } EOLIAN static void _efl_gfx_mapping_mapping_smooth_set(Eo *eo_obj, Efl_Gfx_Mapping_Data *pd, Eina_Bool smooth) { if (pd->cow->smooth == smooth) return; MAPCOW_WRITE(pd, smooth, smooth); _map_dirty(eo_obj, pd, EINA_FALSE); } EOLIAN static Eina_Bool _efl_gfx_mapping_mapping_smooth_get(const Eo *eo_obj EINA_UNUSED, Efl_Gfx_Mapping_Data *pd) { return pd->cow->smooth; } EOLIAN static void _efl_gfx_mapping_mapping_alpha_set(Eo *eo_obj, Efl_Gfx_Mapping_Data *pd, Eina_Bool alpha) { if (pd->cow->alpha == alpha) return; MAPCOW_WRITE(pd, alpha, alpha); _map_dirty(eo_obj, pd, EINA_FALSE); } EOLIAN static Eina_Bool _efl_gfx_mapping_mapping_alpha_get(const Eo *eo_obj EINA_UNUSED, Efl_Gfx_Mapping_Data *pd) { return pd->cow->alpha; } EOLIAN static void _efl_gfx_mapping_mapping_coord_absolute_get(const Eo *eo_obj, Efl_Gfx_Mapping_Data *pd, int idx, double *x, double *y, double *z) { Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj); Evas_Map *m; EINA_SAFETY_ON_FALSE_RETURN((idx >= 0) && (idx < pd->cow->count)); m = _map_calc(eo_obj, obj, pd); if (!m) { int X, Y, W, H; X = obj->cur->geometry.x; Y = obj->cur->geometry.y; W = obj->cur->geometry.w; H = obj->cur->geometry.h; if (x) { if ((idx == 0) || (idx == 3)) *x = X; else *x = X + W; } if (y) { if ((idx == 0) || (idx == 1)) *y = Y; else *y = Y + H; } if (z) *z = 0; return; } _map_point_coord_get(m, idx, x, y, z); } EOLIAN static void _efl_gfx_mapping_mapping_uv_set(Eo *eo_obj, Efl_Gfx_Mapping_Data *pd, int idx, double u, double v) { Gfx_Map *mcow; EINA_SAFETY_ON_FALSE_RETURN((idx >= 0) && (idx < pd->cow->count)); if (!pd->cow->points) { Gfx_Map_Point *ps = calloc(1, pd->cow->count * sizeof(Gfx_Map_Point)); if (!ps) return; MAPCOW_WRITE(pd, points, ps); } if (EINA_DBL_EQ(pd->cow->points[idx].u, u) && EINA_DBL_EQ(pd->cow->points[idx].v, v)) return; mcow = MAPCOW_BEGIN(pd); mcow->points[idx].u = CLAMP(0.0, u, 1.0); mcow->points[idx].v = CLAMP(0.0, v, 1.0); MAPCOW_END(mcow, pd); _map_dirty(eo_obj, pd, EINA_FALSE); } EOLIAN static void _efl_gfx_mapping_mapping_uv_get(const Eo *eo_obj EINA_UNUSED, Efl_Gfx_Mapping_Data *pd, int idx, double *u, double *v) { EINA_SAFETY_ON_FALSE_RETURN((idx >= 0) && (idx < pd->cow->count) && (pd->cow->points)); if (u) *u = pd->cow->points[idx].u; if (v) *v = pd->cow->points[idx].v; } EOLIAN static void _efl_gfx_mapping_mapping_color_get(const Eo *eo_obj EINA_UNUSED, Efl_Gfx_Mapping_Data *pd, int idx, int *r, int *g, int *b, int *a) { Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj); Evas_Map_Point *p; Evas_Map *m; EINA_SAFETY_ON_FALSE_RETURN((idx >= 0) && (idx < pd->cow->count)); if (!r && !g && !b && !a) return; m = _map_calc(eo_obj, obj, pd); if (!m) { if (r) *r = 255; if (g) *g = 255; if (b) *b = 255; if (a) *a = 255; return; } p = &(m->points[idx]); if (r) *r = p->r; if (g) *g = p->g; if (b) *b = p->b; if (a) *a = p->a; } static Gfx_Map_Op * _gfx_mapping_op_add(Eo *eo_obj, Efl_Gfx_Mapping_Data *pd, Gfx_Map_Op_Type type, const Efl_Gfx_Entity *eo_pivot, double cx, double cy, double cz, Eina_Bool is_absolute) { Eina_Bool is_self = EINA_FALSE; Gfx_Map_Pivot *pivot = NULL; Gfx_Map_Op *op; Gfx_Map *mcow; op = calloc(1, sizeof(*op)); if (!op) return NULL; mcow = MAPCOW_BEGIN(pd); if (!is_absolute) { if ((eo_pivot == eo_obj) || !eo_pivot) { eo_pivot = NULL; is_self = EINA_TRUE; } else { Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, MY_CLASS); EINA_INLIST_FOREACH(mcow->pivots, pivot) if (pivot->eo_obj == eo_pivot) break; if (!pivot) { pivot = calloc(1, sizeof(*pivot)); pivot->eo_obj = PIVOT_REF(eo_pivot); pivot->changed = EINA_TRUE; if (efl_isa(eo_pivot, EVAS_CANVAS_CLASS)) { pivot->is_evas = EINA_TRUE; pivot->is_canvas = EINA_TRUE; } else if (efl_isa(eo_pivot, EFL_CANVAS_SCENE_INTERFACE)) pivot->is_canvas = EINA_TRUE; pivot->map_obj = obj; EINA_INLIST_APPEND(mcow->pivots, pivot); } } } op->op = type; op->pivot.is_absolute = is_absolute; op->pivot.is_self = is_self; op->pivot.pivot = pivot; op->pivot.cx = cx; op->pivot.cy = cy; op->pivot.cz = cz; EINA_INLIST_APPEND(mcow->ops, op); MAPCOW_END(mcow, pd); _map_dirty(eo_obj, pd, EINA_FALSE); return op; } EOLIAN static void _efl_gfx_mapping_mapping_coord_absolute_set(Eo *eo_obj, Efl_Gfx_Mapping_Data *pd, int idx, double x, double y, double z) { Gfx_Map_Op *op; EINA_SAFETY_ON_FALSE_RETURN((idx >= 0) && (idx < pd->cow->count)); op = _gfx_mapping_op_add(eo_obj, pd, GFX_MAPPING_RAW_COORD, NULL, 0, 0, 0, EINA_FALSE); if (!op) return; op->raw_coord.idx = idx; op->raw_coord.x = x; op->raw_coord.y = y; op->raw_coord.z = z; } EOLIAN static void _efl_gfx_mapping_mapping_color_set(Eo *eo_obj, Efl_Gfx_Mapping_Data *pd, int idx, int r, int g, int b, int a) { Gfx_Map_Op *op; EINA_SAFETY_ON_FALSE_RETURN((idx >= -1) && (idx < pd->cow->count)); op = _gfx_mapping_op_add(eo_obj, pd, GFX_MAPPING_COLOR, NULL, 0, 0, 0, EINA_FALSE); if (!op) return; op->color.idx = idx; op->color.r = r; op->color.g = g; op->color.b = b; op->color.a = a; } EOLIAN static void _efl_gfx_mapping_translate(Eo *eo_obj, Efl_Gfx_Mapping_Data *pd, double dx, double dy, double dz) { Gfx_Map_Op *op; op = _gfx_mapping_op_add(eo_obj, pd, GFX_MAPPING_TRANSLATE, NULL, 0, 0, 0, EINA_FALSE); if (!op) return; op->translate.dx = dx; op->translate.dy = dy; op->translate.dz = dz; } static inline void _map_rotate(Eo *eo_obj, Efl_Gfx_Mapping_Data *pd, double degrees, const Efl_Gfx_Entity *pivot, double cx, double cy, Eina_Bool absolute) { Gfx_Map_Op *op; op = _gfx_mapping_op_add(eo_obj, pd, GFX_MAPPING_ROTATE_2D, pivot, cx, cy, 0, absolute); if (!op) return; op->rotate_2d.degrees = degrees; } EOLIAN static void _efl_gfx_mapping_rotate(Eo *eo_obj, Efl_Gfx_Mapping_Data *pd, double degrees, const Efl_Gfx_Entity *pivot, double cx, double cy) { _map_rotate(eo_obj, pd, degrees, pivot, cx, cy, EINA_FALSE); } EOLIAN static void _efl_gfx_mapping_rotate_absolute(Eo *eo_obj, Efl_Gfx_Mapping_Data *pd, double degrees, double cx, double cy) { _map_rotate(eo_obj, pd, degrees, NULL, cx, cy, EINA_TRUE); } static inline void _map_rotate_3d(Eo *eo_obj, Efl_Gfx_Mapping_Data *pd, double dx, double dy, double dz, const Efl_Gfx_Entity *pivot, double cx, double cy, double cz, Eina_Bool absolute) { Gfx_Map_Op *op; op = _gfx_mapping_op_add(eo_obj, pd, GFX_MAPPING_ROTATE_3D, pivot, cx, cy, cz, absolute); if (!op) return; op->rotate_3d.dx = dx; op->rotate_3d.dy = dy; op->rotate_3d.dz = dz; } EOLIAN static void _efl_gfx_mapping_rotate_3d(Eo *eo_obj, Efl_Gfx_Mapping_Data *pd, double dx, double dy, double dz, const Efl_Gfx_Entity *pivot, double cx, double cy, double cz) { _map_rotate_3d(eo_obj, pd, dx, dy, dz, pivot, cx, cy, cz, EINA_FALSE); } EOLIAN static void _efl_gfx_mapping_rotate_3d_absolute(Eo *eo_obj, Efl_Gfx_Mapping_Data *pd, double dx, double dy, double dz, double cx, double cy, double cz) { _map_rotate_3d(eo_obj, pd, dx, dy, dz, NULL, cx, cy, cz, EINA_TRUE); } static inline void _map_rotate_quat(Eo *eo_obj, Efl_Gfx_Mapping_Data *pd, double qx, double qy, double qz, double qw, const Efl_Gfx_Entity *pivot, double cx, double cy, double cz, Eina_Bool absolute) { Gfx_Map_Op *op; op = _gfx_mapping_op_add(eo_obj, pd, GFX_MAPPING_ROTATE_QUAT, pivot, cx, cy, cz, absolute); if (!op) return; op->rotate_quat.qx = qx; op->rotate_quat.qy = qy; op->rotate_quat.qz = qz; op->rotate_quat.qw = qw; } EOLIAN static void _efl_gfx_mapping_rotate_quat(Eo *eo_obj, Efl_Gfx_Mapping_Data *pd, double qx, double qy, double qz, double qw, const Efl_Gfx_Entity *pivot, double cx, double cy, double cz) { _map_rotate_quat(eo_obj, pd, qx, qy, qz, qw, pivot, cx, cy, cz, EINA_FALSE); } EOLIAN static void _efl_gfx_mapping_rotate_quat_absolute(Eo *eo_obj, Efl_Gfx_Mapping_Data *pd, double qx, double qy, double qz, double qw, double cx, double cy, double cz) { _map_rotate_quat(eo_obj, pd, qx, qy, qz, qw, NULL, cx, cy, cz, EINA_TRUE); } static inline void _map_zoom(Eo *eo_obj, Efl_Gfx_Mapping_Data *pd, double zoomx, double zoomy, const Efl_Gfx_Entity *pivot, double cx, double cy, Eina_Bool absolute) { Gfx_Map_Op *op; op = _gfx_mapping_op_add(eo_obj, pd, GFX_MAPPING_ZOOM, pivot, cx, cy, 0, absolute); if (!op) return; op->zoom.zx = zoomx; op->zoom.zy = zoomy; } EOLIAN static void _efl_gfx_mapping_zoom(Eo *eo_obj, Efl_Gfx_Mapping_Data *pd, double zoomx, double zoomy, const Efl_Gfx_Entity *pivot, double cx, double cy) { _map_zoom(eo_obj, pd, zoomx, zoomy, pivot, cx, cy, EINA_FALSE); } EOLIAN static void _efl_gfx_mapping_zoom_absolute(Eo *eo_obj, Efl_Gfx_Mapping_Data *pd, double zoomx, double zoomy, double cx, double cy) { _map_zoom(eo_obj, pd, zoomx, zoomy, NULL, cx, cy, EINA_TRUE); } static inline void _map_lighting_3d(Eo *eo_obj, Efl_Gfx_Mapping_Data *pd, const Efl_Gfx_Entity *pivot, double lx, double ly, double lz, int lr, int lg, int lb, int ar, int ag, int ab, Eina_Bool absolute) { Gfx_Map_Op *op; op = _gfx_mapping_op_add(eo_obj, pd, GFX_MAPPING_LIGHTING_3D, pivot, lx, ly, lz, absolute); if (!op) return; op->lighting_3d.lr = lr; op->lighting_3d.lg = lg; op->lighting_3d.lb = lb; op->lighting_3d.ar = ar; op->lighting_3d.ag = ag; op->lighting_3d.ab = ab; } EOLIAN static void _efl_gfx_mapping_lighting_3d(Eo *eo_obj, Efl_Gfx_Mapping_Data *pd, const Efl_Gfx_Entity *pivot, double lx, double ly, double lz, int lr, int lg, int lb, int ar, int ag, int ab) { _map_lighting_3d(eo_obj, pd, pivot, lx, ly, lz, lr, lg, lb, ar, ag, ab, EINA_FALSE); } EOLIAN static void _efl_gfx_mapping_lighting_3d_absolute(Eo *eo_obj, Efl_Gfx_Mapping_Data *pd, double lx, double ly, double lz, int lr, int lg, int lb, int ar, int ag, int ab) { _map_lighting_3d(eo_obj, pd, NULL, lx, ly, lz, lr, lg, lb, ar, ag, ab, EINA_TRUE); } static inline void _map_perspective_3d(Eo *eo_obj, Efl_Gfx_Mapping_Data *pd, const Efl_Gfx_Entity *pivot, double px, double py, double z0, double foc, Eina_Bool absolute) { Gfx_Map_Op *op; if (foc <= 0.0) { ERR("Focal length must be greater than 0!"); return; } op = _gfx_mapping_op_add(eo_obj, pd, GFX_MAPPING_PERSPECTIVE_3D, pivot, px, py, 0, absolute); if (!op) return; op->perspective_3d.z0 = z0; op->perspective_3d.foc = foc; } EOLIAN static void _efl_gfx_mapping_perspective_3d(Eo *eo_obj, Efl_Gfx_Mapping_Data *pd, const Efl_Gfx_Entity *pivot, double px, double py, double z0, double foc) { _map_perspective_3d(eo_obj, pd, pivot, px, py, z0, foc, EINA_FALSE); } EOLIAN static void _efl_gfx_mapping_perspective_3d_absolute(Eo *eo_obj, Efl_Gfx_Mapping_Data *pd, double px, double py, double z0, double foc) { _map_perspective_3d(eo_obj, pd, NULL, px, py, z0, foc, EINA_TRUE); } #include "canvas/efl_gfx_mapping.eo.c"