diff --git a/src/bin/elementary/test_evas_mask.c b/src/bin/elementary/test_evas_mask.c index a107c017e5..1cfba27bb7 100644 --- a/src/bin/elementary/test_evas_mask.c +++ b/src/bin/elementary/test_evas_mask.c @@ -81,18 +81,12 @@ _toggle_map(void *data, const Efl_Event *ev EINA_UNUSED) { Eo *ly = data; - if (!efl_gfx_map_enable_get(ly)) + if (!efl_gfx_map_has(ly)) { - int x, y, w, h; - efl_gfx_map_reset(ly); - efl_gfx_geometry_get(ly, &x, &y, &w, &h); - efl_gfx_map_zoom(ly, 0.8, 0.8, x + w / 2, y + h / 2); - efl_gfx_map_enable_set(ly, 1); - } - else - { - efl_gfx_map_enable_set(ly, 0); + efl_gfx_map_zoom(ly, 0.8, 0.8, NULL, 0.5, 0.5); + efl_gfx_map_rotate(ly, 45, NULL, 0.5, 0.5); } + else efl_gfx_map_reset(ly); } static void diff --git a/src/bin/elementary/test_evas_snapshot.c b/src/bin/elementary/test_evas_snapshot.c index 2d5db2c602..20a872dbc7 100644 --- a/src/bin/elementary/test_evas_snapshot.c +++ b/src/bin/elementary/test_evas_snapshot.c @@ -25,24 +25,6 @@ static const char *filter = "print ('Evaluating filter: ' .. input.width .. 'x' .. input.height)" ; -static inline void -_efl_key_int_set(Eo *obj, const char *key, int val) -{ - Eina_Value *v = eina_value_new(EINA_VALUE_TYPE_INT); - eina_value_set(v, val); - efl_key_value_set(obj, key, v); -} - -static inline int -_efl_key_int_get(Eo *obj, const char *key) -{ - Eina_Value *v = efl_key_value_get(obj, key); - int val; - - if (!eina_value_get(v, &val)) return 0; - return val; -} - static inline Eo * _image_create(Eo *win, const char *path) { @@ -120,26 +102,6 @@ _close_do(void *data, const Efl_Event *ev EINA_UNUSED) efl_del(win); } -static void -_map_do(void *data, const Efl_Event *ev EINA_UNUSED) -{ - Eo *snap = data; - int x, y, w, h; - - // Prevent recursive infinite loop :( - static int here = 0; - if (here) return; - here = 1; - - efl_gfx_map_reset(snap); - efl_gfx_geometry_get(snap, &x, &y, &w, &h); - efl_gfx_map_zoom(snap, 0.8, 0.8, x + w/2., y + h/2.); - efl_gfx_map_rotate(snap, 45., x + w/2., y + h/2.); - efl_gfx_map_enable_set(snap, EINA_TRUE); - - here = 0; -} - static void _toggle_map(void *data, const Efl_Event *ev EINA_UNUSED) { @@ -147,20 +109,12 @@ _toggle_map(void *data, const Efl_Event *ev EINA_UNUSED) Eo *snap; snap = efl_key_wref_get(win, "snap"); - if (!_efl_key_int_get(snap, "map")) + if (!efl_gfx_map_has(snap)) { - _efl_key_int_set(snap, "map", 1); - _map_do(snap, NULL); - efl_event_callback_add(snap, EFL_GFX_EVENT_RESIZE, _map_do, snap); - efl_event_callback_add(snap, EFL_GFX_EVENT_MOVE, _map_do, snap); - } - else - { - _efl_key_int_set(snap, "map", 0); - efl_event_callback_del(snap, EFL_GFX_EVENT_RESIZE, _map_do, snap); - efl_event_callback_del(snap, EFL_GFX_EVENT_MOVE, _map_do, snap); - efl_gfx_map_enable_set(snap, EINA_FALSE); + efl_gfx_map_zoom(snap, 0.8, 0.8, NULL, 0.5, 0.5); + efl_gfx_map_rotate(snap, 20.0, NULL, 0.5, 0.5); } + else efl_gfx_map_reset(snap); } void @@ -272,6 +226,4 @@ test_evas_snapshot(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *e efl_key_wref_set(win, "grid", grid); efl_gfx_size_set(win, 400, 400); efl_gfx_visible_set(win, 1); - - } diff --git a/src/examples/evas/evas-map-aa-eo.c b/src/examples/evas/evas-map-aa-eo.c index 12bcdfe510..5b4c66fbb1 100644 --- a/src/examples/evas/evas-map-aa-eo.c +++ b/src/examples/evas/evas-map-aa-eo.c @@ -58,30 +58,17 @@ static struct exemple_data d = EINA_FALSE, EINA_FALSE, EINA_FALSE, EINA_FALSE, EINA_FALSE }; static void -update() +update(void) { - efl_gfx_map_populate(d.target1, 0); + efl_gfx_map_raw_coord_set(d.target1, 0, d.px1, d.py1, 0); + efl_gfx_map_raw_coord_set(d.target1, 1, d.px2, d.py2, 0); + efl_gfx_map_raw_coord_set(d.target1, 2, d.px3, d.py3, 0); + efl_gfx_map_raw_coord_set(d.target1, 3, d.px4, d.py4, 0); - efl_gfx_map_point_coord_set(d.target1, 0, d.px1, d.py1, 0); - efl_gfx_map_point_coord_set(d.target1, 1, d.px2, d.py2, 0); - efl_gfx_map_point_coord_set(d.target1, 2, d.px3, d.py3, 0); - efl_gfx_map_point_coord_set(d.target1, 3, d.px4, d.py4, 0); - - efl_gfx_map_point_image_uv_set(d.target1, 0, 0, 0); - efl_gfx_map_point_image_uv_set(d.target1, 1, IMAGE_SIZE_W, 0); - efl_gfx_map_point_image_uv_set(d.target1, 2, IMAGE_SIZE_W, IMAGE_SIZE_H); - efl_gfx_map_point_image_uv_set(d.target1, 3, 0, IMAGE_SIZE_H); - - efl_gfx_map_enable_set(d.target1, EINA_TRUE); - - efl_gfx_map_dup(d.target2, d.target1); - - efl_gfx_map_point_coord_set(d.target2, 0, d.px1 + 400, d.py1, 0); - efl_gfx_map_point_coord_set(d.target2, 1, d.px2 + 400, d.py2, 0); - efl_gfx_map_point_coord_set(d.target2, 2, d.px3 + 400, d.py3, 0); - efl_gfx_map_point_coord_set(d.target2, 3, d.px4 + 400, d.py4, 0); - - efl_gfx_map_enable_set(d.target2, EINA_TRUE); + efl_gfx_map_raw_coord_set(d.target2, 0, d.px1 + 400, d.py1, 0); + efl_gfx_map_raw_coord_set(d.target2, 1, d.px2 + 400, d.py2, 0); + efl_gfx_map_raw_coord_set(d.target2, 2, d.px3 + 400, d.py3, 0); + efl_gfx_map_raw_coord_set(d.target2, 3, d.px4 + 400, d.py4, 0); } static void diff --git a/src/examples/evas/evas-map-utils-eo.c b/src/examples/evas/evas-map-utils-eo.c index 329bd6c113..fdf000efd4 100644 --- a/src/examples/evas/evas-map-utils-eo.c +++ b/src/examples/evas/evas-map-utils-eo.c @@ -69,96 +69,81 @@ static Eina_Bool _anim_cb(void *data) { App_Data *ad = data; - Evas_Object *o, *ref; - int r, g, b, a; - int win_w, win_h, img_w, img_h; - Evas_Coord x, y, w, h; - - evas_output_size_get(ad->canvas, &win_w, &win_h); + Evas_Object *o; + int r, g, b, a, x, y, w, h, f; + int win_w, win_h, mx, my; + f = ad->frame; r = ad->colors[ad->colors_index].r; g = ad->colors[ad->colors_index].g; b = ad->colors[ad->colors_index].b; a = ad->colors[ad->colors_index].a; + evas_output_size_get(ad->canvas, &win_w, &win_h); o = evas_object_name_find(ad->canvas, "obj1"); - evas_object_geometry_get(o, &x, &y, &w, &h); - - efl_gfx_map_populate(o, 0); - efl_gfx_map_rotate(o, 3 * ad->frame, x + (w / 2), y + (h / 2)); + efl_gfx_map_reset(o); + efl_gfx_map_rotate(o, 3 * f, NULL, 0.5, 0.5); efl_gfx_map_smooth_set(o, ad->smooth); efl_gfx_map_alpha_set(o, ad->alpha); efl_gfx_map_color_set(o, -1, r, g, b, a); - efl_gfx_map_enable_set(o, EINA_TRUE); - ref = o; + o = evas_object_name_find(ad->canvas, "obj2"); - evas_object_geometry_get(o, &x, &y, &w, &h); - evas_object_image_size_get(o, &img_w, &img_h); - - efl_gfx_map_dup(o, ref); - efl_gfx_map_populate(o, 100); - efl_gfx_map_point_image_uv_set(o, 0, 0, 0); - efl_gfx_map_point_image_uv_set(o, 1, img_w, 0); - efl_gfx_map_point_image_uv_set(o, 2, img_w, img_h); - efl_gfx_map_point_image_uv_set(o, 3, 0, img_h); - efl_gfx_map_rotate_3d(o, ad->frame * 6, ad->frame * 6, ad->frame * 6, - x + (w / 3), y + 10, 0); + efl_gfx_size_get(o, NULL, &h); + efl_gfx_map_reset(o); + efl_gfx_map_smooth_set(o, ad->smooth); + efl_gfx_map_alpha_set(o, ad->alpha); + efl_gfx_map_color_set(o, -1, r, g, b, a); + efl_gfx_map_translate(o, 0, 0, 100); + efl_gfx_map_rotate_3d(o, f * 6, f * 6, f * 6, NULL, 1./3., 10. / h, 0); if (ad->apply_lighting) - efl_gfx_map_lightning_3d(o, win_w / 2, win_h / 2, -100, - 255, 255, 255, 0, 0, 0); - efl_gfx_map_enable_set(o, EINA_TRUE); + { + efl_gfx_map_lightning_3d(o, ad->canvas, 0.5, 0.5, -100., + 255, 255, 255, 0, 0, 0); + } + o = evas_object_name_find(ad->canvas, "obj3"); - evas_object_geometry_get(o, &x, &y, &w, &h); - evas_object_image_size_get(o, &img_w, &img_h); - - efl_gfx_map_dup(o, ref); - efl_gfx_map_populate_manual(o, x, y + (h / 2), w, h, -20); - efl_gfx_map_point_image_uv_set(o, 0, 0, 0); - efl_gfx_map_point_image_uv_set(o, 1, img_w, 0); - efl_gfx_map_point_image_uv_set(o, 2, img_w, img_h); - efl_gfx_map_point_image_uv_set(o, 3, 0, img_h); - efl_gfx_map_rotate_3d(o, 20, ad->frame * 6, 0, - x + (w / 2), y + (w / 2), w / 2); - + efl_gfx_size_get(o, &w, &h); + efl_gfx_map_reset(o); + efl_gfx_map_smooth_set(o, ad->smooth); + efl_gfx_map_alpha_set(o, ad->alpha); + efl_gfx_map_color_set(o, -1, r, g, b, a); + efl_gfx_map_translate(o, 0, h/2, -20); + efl_gfx_map_rotate_3d(o, 20, f * 6, 0, NULL, 0.5, 0.5, w / 2); if (ad->apply_perspective) - efl_gfx_map_perspective_3d(o, x + (w / 2), y + (h / 2), 0, 256); + efl_gfx_map_perspective_3d(o, NULL, 0.5, 0.5, 0, 256); if (ad->apply_lighting) { - Evas_Coord mx, my; evas_pointer_canvas_xy_get(ad->canvas, &mx, &my); - efl_gfx_map_lightning_3d(o, mx, my, -256, 255, 255, 255, 0, 0, 0); + efl_gfx_map_lightning_3d(o, ad->canvas, + (double) mx / win_w, (double) my / win_h, + -256, 255, 255, 255, 0, 0, 0); } if (ad->backface_culling) - { - if (efl_gfx_map_clockwise_get(o)) - evas_object_show(o); - else - evas_object_hide(o); - } + efl_gfx_visible_set(o, efl_gfx_map_clockwise_get(o)); else - evas_object_show(o); - efl_gfx_map_enable_set(o, EINA_TRUE); + efl_gfx_visible_set(o, 1); + o = evas_object_name_find(ad->canvas, "obj4"); efl_gfx_geometry_get(o, &x, &y, &w, &h); - efl_gfx_view_size_get(o, &img_w, &img_h); - - efl_gfx_map_dup(o, ref); - efl_gfx_map_point_coord_set(o, 0, x, y + h, 0); - efl_gfx_map_point_coord_set(o, 1, x + w, y + h, 0); - efl_gfx_map_point_coord_set(o, 2, win_w - 10, win_h - 30, 0); - efl_gfx_map_point_coord_set(o, 3, (win_w / 2) + 10, win_h - 30, 0); - efl_gfx_map_point_image_uv_set(o, 0, 0, img_h); - efl_gfx_map_point_image_uv_set(o, 1, img_w, img_h); - efl_gfx_map_point_image_uv_set(o, 2, img_w, 2 * (img_h / 3)); - efl_gfx_map_point_image_uv_set(o, 3, 0, 2 * (img_h / 3)); + efl_gfx_map_reset(o); + efl_gfx_map_smooth_set(o, ad->smooth); + efl_gfx_map_alpha_set(o, ad->alpha); + efl_gfx_map_raw_coord_set(o, 0, x, y + h, 0); + efl_gfx_map_raw_coord_set(o, 1, x + w, y + h, 0); + efl_gfx_map_raw_coord_set(o, 2, win_w - 10, win_h - 30, 0); + efl_gfx_map_raw_coord_set(o, 3, (win_w / 2) + 10, win_h - 30, 0); + efl_gfx_map_uv_set(o, 0, 0, 1); + efl_gfx_map_uv_set(o, 1, 1, 1); + efl_gfx_map_uv_set(o, 2, 1, 2. / 3.); + efl_gfx_map_uv_set(o, 3, 0, 2. / 3.); efl_gfx_map_color_set(o, 0, 200, 200, 200, 150); efl_gfx_map_color_set(o, 1, 200, 200, 200, 150); efl_gfx_map_color_set(o, 2, 0, 0, 0, 0); efl_gfx_map_color_set(o, 3, 0, 0, 0, 0); - efl_gfx_map_enable_set(o, EINA_TRUE); + ad->frame = (ad->frame + 1) % 60; diff --git a/src/lib/evas/Evas_Legacy.h b/src/lib/evas/Evas_Legacy.h index 673cbdc747..1af3be534b 100644 --- a/src/lib/evas/Evas_Legacy.h +++ b/src/lib/evas/Evas_Legacy.h @@ -6908,6 +6908,17 @@ EAPI const Evas_Map *evas_object_map_get(const Evas_Object *obj); */ EAPI void evas_object_map_enable_set(Evas_Object *obj, Eina_Bool enabled); +/** + * @brief Whether the map is enabled or not + * + * @param[in] obj The evas object + * + * @return The value of @c enabled as passed to evas_object_map_enable_set(). + * + * @see evas_object_map_enable_set + */ +EAPI Eina_Bool evas_object_map_enable_get(const Evas_Object *obj); + #include "canvas/efl_gfx_map.eo.legacy.h" /** diff --git a/src/lib/evas/canvas/efl_canvas_object.eo b/src/lib/evas/canvas/efl_canvas_object.eo index b2569ce26c..61ef44e542 100644 --- a/src/lib/evas/canvas/efl_canvas_object.eo +++ b/src/lib/evas/canvas/efl_canvas_object.eo @@ -667,7 +667,6 @@ abstract Efl.Canvas.Object (Efl.Object, Efl.Gfx, Efl.Gfx.Stack, Efl.Animator, Efl.Gfx.Size.Hint.hint_margin { get; set; } Efl.Gfx.Size.Hint.hint_request { get; set; } Efl.Gfx.Size.Hint.hint_weight { get; set; } - Efl.Gfx.Map.map_enable { get; set; } Efl.Input.Interface.seat_event_filter { get; set; } Efl.Loop_User.loop { get; } } diff --git a/src/lib/evas/canvas/efl_gfx_map.c b/src/lib/evas/canvas/efl_gfx_map.c index 5667a1c944..2bc0e7067e 100644 --- a/src/lib/evas/canvas/efl_gfx_map.c +++ b/src/lib/evas/canvas/efl_gfx_map.c @@ -1,325 +1,701 @@ #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 MY_CLASS EFL_GFX_MAP_MIXIN -/* Efl.Gfx.Map implementation - relies on legacy for now */ -// note: cur vs. prev is not handled +typedef struct _Gfx_Map Gfx_Map; +typedef struct _Gfx_Map_Op Gfx_Map_Op; +typedef struct _Efl_Gfx_Map_Data Efl_Gfx_Map_Data; +typedef enum _Gfx_Map_Op_Type Gfx_Map_Op_Type; -#define MAP_OBJ_CHANGE() do { \ - _evas_map_calc_map_geometry(eo_obj); \ - evas_object_change(eo_obj, obj); \ - obj->changed_map = EINA_TRUE; \ - } while (0) +enum _Gfx_Map_Op_Type { + GFX_MAP_ROTATE_2D, + GFX_MAP_ROTATE_3D, + GFX_MAP_ROTATE_QUAT, + GFX_MAP_ZOOM, + GFX_MAP_TRANSLATE, + GFX_MAP_LIGHTNING_3D, + GFX_MAP_PERSPECTIVE_3D, +}; -#define MAP_POPULATE_DEFAULT(m, z) \ - _evas_map_util_points_populate(m, obj->cur->geometry.x, obj->cur->geometry.y, \ - obj->cur->geometry.w, obj->cur->geometry.h, z) +struct _Gfx_Map_Op { + EINA_INLIST; -static Eina_Bool -_map_populate(Eo *eo_obj, int z) + Gfx_Map_Op_Type op; + union { + 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; + } lightning_3d; + struct { + double z0, foc; + } perspective_3d; + }; + struct { + Eo *eo_obj; // strong or weak ref? + double cx, cy, cz; + Eina_Bool event_cbs; + Eina_Bool is_canvas; + } pivot; +}; + +struct _Gfx_Map { + Gfx_Map_Op *ops; + + struct { + double u, v; + double x, y, z; + uint8_t r, g, b, a; + } point[4]; + + Eina_Bool alpha; + Eina_Bool smooth; + Eina_Bool absolute_xy; + Eina_Bool event_cbs; +}; + +struct _Efl_Gfx_Map_Data { + const Gfx_Map *cow; +}; + +// ---------------------------------------------------------------------------- + +static Eina_Cow *gfx_map_cow = NULL; +static const Gfx_Map gfx_map_cow_default = { + NULL, + { + { 0.0, 0.0, 0.0, 0.0, 0.0, 255, 255, 255, 255 }, + { 1.0, 0.0, 0.0, 0.0, 0.0, 255, 255, 255, 255 }, + { 1.0, 1.0, 0.0, 0.0, 0.0, 255, 255, 255, 255 }, + { 0.0, 1.0, 0.0, 0.0, 0.0, 255, 255, 255, 255 } + }, + EINA_TRUE, + EINA_TRUE, + EINA_FALSE, + EINA_FALSE +}; + +#define MAPCOW_BEGIN(_pd) eina_cow_write(gfx_map_cow, (const Eina_Cow_Data**)&(_pd->cow)) +#define MAPCOW_END(_mapcow, _pd) eina_cow_done(gfx_map_cow, (const Eina_Cow_Data**)&(_pd->cow), _mapcow, EINA_TRUE) +#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(_pivot, eo_obj) : NULL) +#define PIVOT_UNREF(_pivot) (_pivot ? efl_xunref(_pivot, eo_obj) : NULL) + +static inline void _map_ops_clean(Eo *eo_obj, Efl_Gfx_Map_Data *pd); + +// ---------------------------------------------------------------------------- + +void +_efl_gfx_map_init(void) { - Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj, EINA_FALSE); - Evas_Map *m; + gfx_map_cow = eina_cow_add("Efl.Gfx.Map", sizeof(Gfx_Map), 8, + &gfx_map_cow_default, EINA_TRUE); +} - if (!obj->map->cur.map) +void +_efl_gfx_map_shutdown(void) +{ + eina_cow_del(gfx_map_cow); + gfx_map_cow = NULL; +} + +// ---------------------------------------------------------------------------- + +EOLIAN static Efl_Object * +_efl_gfx_map_efl_object_constructor(Eo *eo_obj, Efl_Gfx_Map_Data *pd) +{ + eo_obj = efl_constructor(efl_super(eo_obj, MY_CLASS)); + pd->cow = eina_cow_alloc(gfx_map_cow); + return eo_obj; +} + +EOLIAN static void +_efl_gfx_map_efl_object_destructor(Eo *eo_obj, Efl_Gfx_Map_Data *pd) +{ + _map_ops_clean(eo_obj, pd); + eina_cow_free(gfx_map_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; + + obj->gfx_map_update = EINA_TRUE; +} + +static inline void +_map_dirty(Eo *eo_obj, Efl_Gfx_Map_Data *pd, Eina_Bool reset) +{ + Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj); + Gfx_Map_Op *op; + + obj->gfx_map_has = EINA_TRUE; + obj->gfx_map_update |= !reset; + _evas_object_map_enable_set(eo_obj, obj, !reset); + evas_object_change(eo_obj, obj); + + if (!reset && !pd->cow->absolute_xy) { - m = _evas_map_new(4, EINA_TRUE); - if (!m) return EINA_FALSE; - MAP_POPULATE_DEFAULT(m, z); - evas_object_map_set(eo_obj, m); - evas_map_free(m); + if (!pd->cow->event_cbs) + { + MAPCOW_WRITE(pd, event_cbs, EINA_TRUE); + efl_event_callback_add(eo_obj, EFL_GFX_EVENT_MOVE, _geometry_changed_cb, obj); + efl_event_callback_add(eo_obj, EFL_GFX_EVENT_RESIZE, _geometry_changed_cb, obj); + } + EINA_INLIST_FOREACH(pd->cow->ops, op) + { + if (op->pivot.eo_obj && !op->pivot.event_cbs) + { + op->pivot.event_cbs = EINA_TRUE; + if (!op->pivot.is_canvas) + efl_event_callback_add(op->pivot.eo_obj, EFL_GFX_EVENT_MOVE, _geometry_changed_cb, obj); + efl_event_callback_add(op->pivot.eo_obj, EFL_GFX_EVENT_RESIZE, _geometry_changed_cb, obj); + } + } + } +} + +static void +_map_update(Eo *eo_obj, Efl_Gfx_Map_Data *pd) +{ + Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj); + Evas_Map *m = NULL; + int imw, imh; + + if (!obj->gfx_map_update) return; + if (pd->cow == &gfx_map_cow_default) + goto end; + + m = evas_map_new(4); + m->alpha = pd->cow->alpha; + m->smooth = pd->cow->smooth; + m->move_sync.enabled = EINA_FALSE; + + if (pd->cow->absolute_xy) + { + for (int k = 0; k < 4; k++) + { + Evas_Map_Point *p = &(m->points[k]); + p->px = p->x = pd->cow->point[k].x; + p->py = p->y = pd->cow->point[k].y; + } } else { - m = (Evas_Map *) obj->map->cur.map; - MAP_POPULATE_DEFAULT(m, z); - MAP_OBJ_CHANGE(); + _evas_map_util_points_populate(m, obj->cur->geometry.x, obj->cur->geometry.y, + obj->cur->geometry.w, obj->cur->geometry.h, 0); } - return EINA_TRUE; + if (efl_isa(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS)) + efl_gfx_view_size_get(eo_obj, &imw, &imh); + else + efl_gfx_size_get(eo_obj, &imw, &imh); + + for (int k = 0; k < 4; k++) + { + Evas_Map_Point *p = &(m->points[k]); + p->u = pd->cow->point[k].u * imw; + p->v = pd->cow->point[k].v * imh; + p->z = pd->cow->point[k].z; + p->r = pd->cow->point[k].r; + p->g = pd->cow->point[k].g; + p->b = pd->cow->point[k].b; + p->a = pd->cow->point[k].a; + } + + if (!pd->cow->absolute_xy) + { + Gfx_Map_Op *op; + + EINA_INLIST_FOREACH(pd->cow->ops, op) + { + int px = 0, py = 0, pw = 1, ph = 1; + double cx, cy, cz; + Efl_Gfx *pivot; + + pivot = op->pivot.eo_obj ?: eo_obj; + if (!op->pivot.is_canvas) + { + efl_gfx_geometry_get(pivot, &px, &py, &pw, &ph); + } + else + { + // Note: pivot can not be an Evas when using pure EO API + if (efl_isa(pivot, EVAS_CANVAS_CLASS)) + evas_output_size_get(pivot, &pw, &ph); + else + efl_gfx_size_get(pivot, &pw, &ph); + } + cx = (double) px + (double) pw * op->pivot.cx; + cy = (double) py + (double) ph * op->pivot.cy; + cz = op->pivot.cz; + + switch (op->op) + { + case GFX_MAP_ROTATE_2D: + _map_util_rotate(m, op->rotate_2d.degrees, cx, cy); + break; + case GFX_MAP_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_MAP_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_MAP_ZOOM: + _map_util_zoom(m, op->zoom.zx, op->zoom.zy, cx, cy); + break; + case GFX_MAP_TRANSLATE: + _map_util_translate(m, op->translate.dx, op->translate.dy, + op->translate.dz); + break; + case GFX_MAP_LIGHTNING_3D: + _map_util_3d_lighting(m, cx, cy, cz, op->lightning_3d.lr, + op->lightning_3d.lg, op->lightning_3d.lb, + op->lightning_3d.ar, op->lightning_3d.ag, + op->lightning_3d.ab); + break; + case GFX_MAP_PERSPECTIVE_3D: + _map_util_3d_perspective(m, cx, cy, op->perspective_3d.z0, + op->perspective_3d.foc); + break; + } + } + } + else if (pd->cow->ops) + { + ERR("Map absolute coordinates override all high-level transformations, " + "such as rotate, perspective, etc..."); + } + +end: + evas_object_map_set(eo_obj, m); + if (m) evas_map_free(m); + obj->gfx_map_update = EINA_FALSE; +} + +void +_efl_gfx_map_update(Eo *eo_obj) +{ + Efl_Gfx_Map_Data *pd = efl_data_scope_get(eo_obj, MY_CLASS); + + _map_update(eo_obj, pd); +} + +static inline void +_map_ops_clean(Eo *eo_obj, Efl_Gfx_Map_Data *pd) +{ + if (pd->cow->ops) + { + Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj); + Gfx_Map_Op *op; + Gfx_Map *mcow; + + mcow = MAPCOW_BEGIN(pd); + EINA_INLIST_FREE(mcow->ops, op) + { + EINA_INLIST_REMOVE(mcow->ops, op); + if (op->pivot.event_cbs) + { + op->pivot.event_cbs = EINA_FALSE; + if (!op->pivot.is_canvas) + efl_event_callback_del(op->pivot.eo_obj, EFL_GFX_EVENT_MOVE, _geometry_changed_cb, obj); + efl_event_callback_del(op->pivot.eo_obj, EFL_GFX_EVENT_RESIZE, _geometry_changed_cb, obj); + } + PIVOT_UNREF(op->pivot.eo_obj); + } + MAPCOW_END(mcow, pd); + } +} + +EOLIAN Eina_Bool +_efl_gfx_map_map_has(Eo *eo_obj EINA_UNUSED, Efl_Gfx_Map_Data *pd EINA_UNUSED) +{ + Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj, EINA_FALSE); + + if (!obj->map->cur.usemap) return EINA_FALSE; + if (pd->cow == &gfx_map_cow_default) return EINA_FALSE; + if (pd->cow->ops) return EINA_TRUE; + if (memcmp(&pd->cow->point, &gfx_map_cow_default.point, sizeof(pd->cow->point))) + return EINA_TRUE; + if (pd->cow->absolute_xy) return EINA_TRUE; + return EINA_FALSE; } EOLIAN static void -_efl_gfx_map_map_reset(Eo *eo_obj, void *_pd EINA_UNUSED) -{ - evas_object_map_set(eo_obj, NULL); -} - -EOLIAN static Eina_Bool -_efl_gfx_map_map_clockwise_get(Eo *eo_obj, void *_pd EINA_UNUSED) -{ - return evas_map_util_clockwise_get((Evas_Map *) evas_object_map_get(eo_obj)); -} - -EOLIAN static void -_efl_gfx_map_map_smooth_set(Eo *eo_obj, void *_pd EINA_UNUSED, Eina_Bool smooth) +_efl_gfx_map_map_reset(Eo *eo_obj, Efl_Gfx_Map_Data *pd) { Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj); - Evas_Map *m; + Eina_Bool alpha, smooth; - if (!obj->map->cur.map) + alpha = pd->cow->alpha; + smooth = pd->cow->smooth; + _map_ops_clean(eo_obj, pd); + if (pd->cow->event_cbs) { - if (smooth) return; - if (!_map_populate(eo_obj, 0)) - return; + efl_event_callback_del(eo_obj, EFL_GFX_EVENT_MOVE, _geometry_changed_cb, obj); + efl_event_callback_del(eo_obj, EFL_GFX_EVENT_RESIZE, _geometry_changed_cb, obj); } - m = (Evas_Map *) obj->map->cur.map; - m->smooth = smooth; - MAP_OBJ_CHANGE(); + eina_cow_memcpy(gfx_map_cow, (const Eina_Cow_Data * const *) &pd->cow, + (const Eina_Cow_Data *) &gfx_map_cow_default); + _map_dirty(eo_obj, pd, EINA_TRUE); + MAPCOW_WRITE(pd, alpha, alpha); + MAPCOW_WRITE(pd, smooth, smooth); + obj->gfx_map_has = EINA_FALSE; } EOLIAN static Eina_Bool -_efl_gfx_map_map_smooth_get(Eo *eo_obj, void *_pd EINA_UNUSED) +_efl_gfx_map_map_clockwise_get(Eo *eo_obj, Efl_Gfx_Map_Data *pd) { - const Evas_Map *om = evas_object_map_get(eo_obj); - return om ? om->smooth : EINA_TRUE; + Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj, EINA_TRUE); + + _map_update(eo_obj, pd); + if (!obj->map->cur.map) return EINA_TRUE; + return evas_map_util_clockwise_get(obj->map->cur.map); } EOLIAN static void -_efl_gfx_map_map_alpha_set(Eo *eo_obj, void *_pd EINA_UNUSED, Eina_Bool alpha) +_efl_gfx_map_map_smooth_set(Eo *eo_obj, Efl_Gfx_Map_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_map_map_smooth_get(Eo *eo_obj EINA_UNUSED, Efl_Gfx_Map_Data *pd) +{ + return pd->cow->smooth; +} + +EOLIAN static void +_efl_gfx_map_map_alpha_set(Eo *eo_obj, Efl_Gfx_Map_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_map_map_alpha_get(Eo *eo_obj EINA_UNUSED, Efl_Gfx_Map_Data *pd) +{ + return pd->cow->alpha; +} + +EOLIAN static void +_efl_gfx_map_map_raw_coord_set(Eo *eo_obj, Efl_Gfx_Map_Data *pd, + int idx, double x, double y, double z) +{ + Gfx_Map *mcow; + + EINA_SAFETY_ON_FALSE_RETURN((idx >= 0) && (idx < 4)); + + if (EINA_DBL_EQ(pd->cow->point[idx].x, x) && + EINA_DBL_EQ(pd->cow->point[idx].y, y) && + EINA_DBL_EQ(pd->cow->point[idx].z, z) && + pd->cow->absolute_xy) + return; + + mcow = MAPCOW_BEGIN(pd); + mcow->point[idx].x = x; + mcow->point[idx].y = y; + mcow->point[idx].x = x; + mcow->absolute_xy = EINA_TRUE; + MAPCOW_END(mcow, pd); + + _map_dirty(eo_obj, pd, EINA_FALSE); +} + +EOLIAN static void +_efl_gfx_map_map_raw_coord_get(Eo *eo_obj, Efl_Gfx_Map_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; + const Evas_Map *m = obj->map->cur.map; - if (!obj->map->cur.map) + EINA_SAFETY_ON_FALSE_RETURN((idx >= 0) && (idx < 4)); + + if (pd->cow->absolute_xy) { - if (alpha) return; - if (!_map_populate(eo_obj, 0)) - return; + if (x) *x = pd->cow->point[idx].x; + if (y) *y = pd->cow->point[idx].y; + if (z) *z = pd->cow->point[idx].z; + return; } - m = (Evas_Map *) obj->map->cur.map; - m->alpha = alpha; - MAP_OBJ_CHANGE(); -} + if (!m) + { + int X, Y, W, H; -EOLIAN static Eina_Bool -_efl_gfx_map_map_alpha_get(Eo *eo_obj, void *_pd EINA_UNUSED) -{ - const Evas_Map *om = evas_object_map_get(eo_obj); - return om ? om->alpha : EINA_TRUE; + 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_map_map_point_coord_set(Eo *eo_obj, void *_pd EINA_UNUSED, int idx, double x, double y, double z) +_efl_gfx_map_map_uv_set(Eo *eo_obj, Efl_Gfx_Map_Data *pd, + int idx, double u, double v) +{ + Gfx_Map *mcow; + + EINA_SAFETY_ON_FALSE_RETURN((idx >= 0) && (idx < 4)); + + if (EINA_DBL_EQ(pd->cow->point[idx].u, u) && + EINA_DBL_EQ(pd->cow->point[idx].v, v)) + return; + + mcow = MAPCOW_BEGIN(pd); + mcow->point[idx].u = CLAMP(0.0, u, 1.0); + mcow->point[idx].v = CLAMP(0.0, v, 1.0); + MAPCOW_END(mcow, pd); + + _map_dirty(eo_obj, pd, EINA_FALSE); +} + +EOLIAN static void +_efl_gfx_map_map_uv_get(Eo *eo_obj EINA_UNUSED, Efl_Gfx_Map_Data *pd, + int idx, double *u, double *v) { EINA_SAFETY_ON_FALSE_RETURN((idx >= 0) && (idx < 4)); - Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj); - Evas_Map *m; - - if (!obj->map->cur.map && !_map_populate(eo_obj, 0)) - return; - - m = (Evas_Map *) obj->map->cur.map; - _map_point_coord_set(m, idx, x, y, z); - MAP_OBJ_CHANGE(); + if (u) *u = pd->cow->point[idx].u; + if (v) *v = pd->cow->point[idx].v; } EOLIAN static void -_efl_gfx_map_map_point_coord_get(Eo *eo_obj, void *_pd EINA_UNUSED, int idx, double *x, double *y, double *z) +_efl_gfx_map_map_color_set(Eo *eo_obj, Efl_Gfx_Map_Data *pd, + int idx, int r, int g, int b, int a) { - const Evas_Map *om = evas_object_map_get(eo_obj); - _map_point_coord_get(om, idx, x, y, z); -} + int kmin = 0, kmax = 3; + Gfx_Map *mcow; -EOLIAN static void -_efl_gfx_map_map_point_image_uv_set(Eo *eo_obj, void *_pd EINA_UNUSED, int idx, double u, double v) -{ - EINA_SAFETY_ON_FALSE_RETURN((idx >= 0) && (idx < 4)); - - Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj); - Evas_Map *m; - - if (!obj->map->cur.map && !_map_populate(eo_obj, 0)) - return; - - m = (Evas_Map *) obj->map->cur.map; - evas_map_point_image_uv_set(m, idx, u, v); - MAP_OBJ_CHANGE(); -} - -EOLIAN static void -_efl_gfx_map_map_point_image_uv_get(Eo *eo_obj, void *_pd EINA_UNUSED, int idx, double *u, double *v) -{ - const Evas_Map *om = evas_object_map_get(eo_obj); - - evas_map_point_image_uv_get(om, idx, u, v); -} - -EOLIAN static void -_efl_gfx_map_map_color_set(Eo *eo_obj, void *_pd EINA_UNUSED, int idx, int r, int g, int b, int a) -{ EINA_SAFETY_ON_FALSE_RETURN((idx >= -1) && (idx < 4)); - Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj); - Evas_Map *m; - - if (!obj->map->cur.map && !_map_populate(eo_obj, 0)) + if ((idx != -1) && + (pd->cow->point[idx].r == r) && (pd->cow->point[idx].g == g) && + (pd->cow->point[idx].b == b) && (pd->cow->point[idx].a == a)) return; - m = (Evas_Map *) obj->map->cur.map; - if (idx == -1) - evas_map_util_points_color_set(m, r, g, b, a); - else - evas_map_point_color_set(m, idx, r, g, b, a); - MAP_OBJ_CHANGE(); + if (idx >= 0) + kmin = kmax = idx; + + mcow = MAPCOW_BEGIN(pd); + for (int k = kmin; k <= kmax; k++) + { + mcow->point[k].r = r; + mcow->point[k].g = g; + mcow->point[k].b = b; + mcow->point[k].a = a; + } + MAPCOW_END(mcow, pd); + + _map_dirty(eo_obj, pd, EINA_FALSE); } EOLIAN static void -_efl_gfx_map_map_color_get(Eo *eo_obj, void *_pd EINA_UNUSED, int idx, int *r, int *g, int *b, int *a) +_efl_gfx_map_map_color_get(Eo *eo_obj EINA_UNUSED, Efl_Gfx_Map_Data *pd, + int idx, int *r, int *g, int *b, int *a) { - const Evas_Map *om = evas_object_map_get(eo_obj); + EINA_SAFETY_ON_FALSE_RETURN((idx >= 0) && (idx < 4)); - evas_map_point_color_get(om, idx, r, g, b, a); + if (r) *r = pd->cow->point[idx].r; + if (g) *g = pd->cow->point[idx].g; + if (b) *b = pd->cow->point[idx].b; + if (a) *a = pd->cow->point[idx].a; +} + +static Gfx_Map_Op * +_gfx_map_op_add(Eo *eo_obj, Efl_Gfx_Map_Data *pd, Gfx_Map_Op_Type type, + Efl_Gfx *pivot, double cx, double cy, double cz) +{ + Gfx_Map_Op *op; + Gfx_Map *mcow; + + op = calloc(1, sizeof(*op)); + if (!op) return NULL; + + if (pivot == eo_obj) + pivot = NULL; + + op->op = type; + op->pivot.eo_obj = PIVOT_REF(pivot); + op->pivot.cx = cx; + op->pivot.cy = cy; + op->pivot.cz = cz; + + if (pivot && efl_isa(pivot, EFL_CANVAS_INTERFACE)) + op->pivot.is_canvas = EINA_TRUE; + + mcow = MAPCOW_BEGIN(pd); + EINA_INLIST_APPEND(mcow->ops, op); + MAPCOW_END(mcow, pd); + + _map_dirty(eo_obj, pd, EINA_FALSE); + + return op; } EOLIAN static void -_efl_gfx_map_map_move_sync_set(Eo *eo_obj, void *_pd EINA_UNUSED, Eina_Bool enable) +_efl_gfx_map_rotate(Eo *eo_obj, Efl_Gfx_Map_Data *pd, + double degrees, Efl_Gfx *pivot, double cx, double cy) { - Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj); - Evas_Map *m; + Gfx_Map_Op *op; - if (!obj->map->cur.map) + op = _gfx_map_op_add(eo_obj, pd, GFX_MAP_ROTATE_2D, pivot, cx, cy, 0); + if (!op) return; + + op->rotate_2d.degrees = degrees; +} + +EOLIAN static void +_efl_gfx_map_rotate_3d(Eo *eo_obj, Efl_Gfx_Map_Data *pd, + double dx, double dy, double dz, + Efl_Gfx *pivot, double cx, double cy, double cz) +{ + Gfx_Map_Op *op; + + op = _gfx_map_op_add(eo_obj, pd, GFX_MAP_ROTATE_3D, pivot, cx, cy, cz); + if (!op) return; + + op->rotate_3d.dx = dx; + op->rotate_3d.dy = dy; + op->rotate_3d.dz = dz; +} + +EOLIAN static void +_efl_gfx_map_rotate_quat(Eo *eo_obj, Efl_Gfx_Map_Data *pd, + double qx, double qy, double qz, double qw, + Efl_Gfx *pivot, double cx, double cy, double cz) +{ + Gfx_Map_Op *op; + + op = _gfx_map_op_add(eo_obj, pd, GFX_MAP_ROTATE_QUAT, pivot, cx, cy, cz); + 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_map_zoom(Eo *eo_obj, Efl_Gfx_Map_Data *pd, + double zoomx, double zoomy, + Efl_Gfx *pivot, double cx, double cy) +{ + Gfx_Map_Op *op; + + op = _gfx_map_op_add(eo_obj, pd, GFX_MAP_ZOOM, pivot, cx, cy, 0); + if (!op) return; + + op->zoom.zx = zoomx; + op->zoom.zy = zoomy; +} + +EOLIAN static void +_efl_gfx_map_translate(Eo *eo_obj, Efl_Gfx_Map_Data *pd, + double dx, double dy, double dz) +{ + Gfx_Map_Op *op; + + op = _gfx_map_op_add(eo_obj, pd, GFX_MAP_TRANSLATE, NULL, 0, 0, 0); + if (!op) return; + + op->translate.dx = dx; + op->translate.dy = dy; + op->translate.dz = dz; +} + +EOLIAN static void +_efl_gfx_map_lightning_3d(Eo *eo_obj, Efl_Gfx_Map_Data *pd, + Efl_Gfx *pivot, double lx, double ly, double lz, + int lr, int lg, int lb, int ar, int ag, int ab) +{ + Gfx_Map_Op *op; + + op = _gfx_map_op_add(eo_obj, pd, GFX_MAP_LIGHTNING_3D, pivot, lx, ly, lz); + if (!op) return; + + op->lightning_3d.lr = lr; + op->lightning_3d.lg = lg; + op->lightning_3d.lb = lb; + op->lightning_3d.ar = ar; + op->lightning_3d.ag = ag; + op->lightning_3d.ab = ab; +} + +EOLIAN static void +_efl_gfx_map_perspective_3d(Eo *eo_obj, Efl_Gfx_Map_Data *pd, + Efl_Gfx *pivot, double px, double py, + double z0, double foc) +{ + Gfx_Map_Op *op; + + if (foc <= 0.0) { - if (enable) return; - if (!_map_populate(eo_obj, 0)) - return; + ERR("Focal length must be greater than 0!"); + return; } - m = (Evas_Map *) obj->map->cur.map; - m->move_sync.enabled = enable; - MAP_OBJ_CHANGE(); -} + op = _gfx_map_op_add(eo_obj, pd, GFX_MAP_PERSPECTIVE_3D, pivot, px, py, 0); + if (!op) return; -EOLIAN static Eina_Bool -_efl_gfx_map_map_move_sync_get(Eo *eo_obj, void *_pd EINA_UNUSED) -{ - const Evas_Map *om = evas_object_map_get(eo_obj); - - return om ? om->move_sync.enabled : EINA_TRUE; -} - -EOLIAN static Eina_Bool -_efl_gfx_map_map_rotate(Eo *eo_obj, void *_pd EINA_UNUSED, double degrees, double cx, double cy) -{ - Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj, EINA_FALSE); - Evas_Map *m; - - if (!obj->map->cur.map) - { - if (!_map_populate(eo_obj, 0)) - return EINA_FALSE; - } - - m = (Evas_Map *) obj->map->cur.map; - _map_util_rotate(m, degrees, cx, cy); - MAP_OBJ_CHANGE(); - - return EINA_TRUE; -} - -EOLIAN static Eina_Bool -_efl_gfx_map_map_zoom(Eo *eo_obj, void *_pd EINA_UNUSED, double zoomx, double zoomy, double cx, double cy) -{ - Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj, EINA_FALSE); - Evas_Map *m; - - if (!obj->map->cur.map) - { - if (!_map_populate(eo_obj, 0)) - return EINA_FALSE; - } - - m = (Evas_Map *) obj->map->cur.map; - _map_util_zoom(m, zoomx, zoomy, cx, cy); - MAP_OBJ_CHANGE(); - - return EINA_TRUE; -} - -EOLIAN static Eina_Bool -_efl_gfx_map_map_rotate_3d(Eo *eo_obj, void *_pd EINA_UNUSED, double dx, double dy, double dz, double cx, double cy, double cz) -{ - Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj, EINA_FALSE); - Evas_Map *m; - - if (!obj->map->cur.map) - { - if (!_map_populate(eo_obj, 0)) - return EINA_FALSE; - } - - m = (Evas_Map *) obj->map->cur.map; - _map_util_3d_rotate(m, dx, dy, dz, cx, cy, cz); - MAP_OBJ_CHANGE(); - - return EINA_TRUE; -} - -EOLIAN static Eina_Bool -_efl_gfx_map_map_quat_rotate(Eo *eo_obj, void *_pd EINA_UNUSED, double qx, double qy, double qz, double qw, double cx, double cy, double cz) -{ - Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj, EINA_FALSE); - Evas_Map *m; - - if (!obj->map->cur.map) - { - if (!_map_populate(eo_obj, 0)) - return EINA_FALSE; - } - - m = (Evas_Map *) obj->map->cur.map; - evas_map_util_quat_rotate(m, qx, qy, qz, qw, cx, cy, cz); - MAP_OBJ_CHANGE(); - - return EINA_TRUE; -} - -EOLIAN static Eina_Bool -_efl_gfx_map_map_lightning_3d(Eo *eo_obj, void *_pd EINA_UNUSED, double lx, double ly, double lz, int lr, int lg, int lb, int ar, int ag, int ab) -{ - Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj, EINA_FALSE); - Evas_Map *m; - - if (!obj->map->cur.map) - { - if (!_map_populate(eo_obj, 0)) - return EINA_FALSE; - } - - m = (Evas_Map *) obj->map->cur.map; - _map_util_3d_lighting(m, lx, ly, lz, lr, lg, lb, ar, ag, ab); - MAP_OBJ_CHANGE(); - - return EINA_TRUE; -} - -EOLIAN static Eina_Bool -_efl_gfx_map_map_perspective_3d(Eo *eo_obj, void *_pd EINA_UNUSED, double px, double py, double z0, double foc) -{ - Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj, EINA_FALSE); - Evas_Map *m; - - if (!obj->map->cur.map) - { - if (!_map_populate(eo_obj, 0)) - return EINA_FALSE; - } - - m = (Evas_Map *) obj->map->cur.map; - _map_util_3d_perspective(m, px, py, z0, foc); - MAP_OBJ_CHANGE(); - - return EINA_TRUE; -} - -EOLIAN static Eina_Bool -_efl_gfx_map_map_dup(Eo *eo_obj, void *_pd EINA_UNUSED, const Efl_Gfx_Map *other) -{ - evas_object_map_set(eo_obj, evas_object_map_get(other)); - return EINA_TRUE; + op->perspective_3d.z0 = z0; + op->perspective_3d.foc = foc; } #include "canvas/efl_gfx_map.eo.c" diff --git a/src/lib/evas/canvas/efl_gfx_map.eo b/src/lib/evas/canvas/efl_gfx_map.eo index 720a972875..15f7449c65 100644 --- a/src/lib/evas/canvas/efl_gfx_map.eo +++ b/src/lib/evas/canvas/efl_gfx_map.eo @@ -9,55 +9,37 @@ mixin Efl.Gfx.Map (Efl.Interface, Efl.Object) positioning at target. This allows rotation, perspective, scale and lots of other effects, depending on the map that is used. - Each map point may carry a multiplier color. If properly - calculated, these can do shading effects on the object, producing - 3D effects. + Each map point may carry a multiplier color. If properly calculated, + these can do shading effects on the object, producing 3D effects. At the moment of writing, maps can only have 4 points (no more, no less). - Note: For now this mixin is only compatible with $Efl.Canvas.Object and - shouldn't be used anywhere else. + @since 1.20 ]] - data: null; methods { - @property map_enable @pure_virtual { - [[Whether map transformation is enabled on this object. + map_has { + [[Read-only property indicating whether an object is mapped. - The default map enable state is off ($false). The other - properties and methods in this class have no effect until - this property is enabled. + This will be $true if any transformation is applied to this object. ]] - set { - [[Enable or disable the use of map for this object. On - enable, the object geometry will be saved, and the new - geometry will change (position and size) to reflect the - map geometry set. - ]] - } - get { - legacy: evas_object_map_enable_get; - } - values { - enabled: bool; [[Enabled state.]] - } + return: bool; [[$true if the object is mapped.]] } map_reset { [[Resets the map transformation to its default state. This will reset all transformations to identity, meaning the points' colors, positions and UV coordinates will be reset to their default - values. This does not reset the @.map_enable flag. - - @since 1.20 + values. @.map_has will then return $false. This function will + not modify the values of @.map_smooth or @.map_alpha. ]] } @property map_clockwise { [[Clockwise state of a map (read-only). This determines if the output points (X and Y. Z is not used) are - clockwise or counter-clockwise. This can be used for "back-face culling". This - is where you hide objects that "face away" from you. In this case objects - that are not clockwise. + clockwise or counter-clockwise. This can be used for "back-face + culling". This is where you hide objects that "face away" from you. + In this case objects that are not clockwise. ]] get {} values { @@ -78,18 +60,22 @@ mixin Efl.Gfx.Map (Efl.Interface, Efl.Object) @property map_alpha { [[Alpha flag for map rendering. - This sets alpha flag for map rendering. If the object is a type that has - its own alpha settings, then this will take precedence. Only image objects - have this currently ($Efl.Canvas.Image and its friends). - Setting this off stops alpha blending of the map area, and is - useful if you know the object and/or all sub-objects is 100% solid. + This sets alpha flag for map rendering. If the object is a type that + has its own alpha settings, then this will take precedence. Only + image objects support this currently ($Efl.Canvas.Image and its + friends). Setting this off stops alpha blending of the map area, + and is useful if you know the object and/or all sub-objects is 100% + solid. + + Note that this may conflict with @.map_smooth depending on which + algorithm is used for anti-aliasing. ]] values { alpha: bool; [[$true by default.]] } } - @property map_point_coord { - [[Map point's coordinate. + @property map_raw_coord { + [[A point's absolute coordinate on the canvas. This sets/gets the fixed point's coordinate in the map. Note that points describe the outline of a quadrangle and are ordered either clockwise @@ -105,31 +91,39 @@ mixin Efl.Gfx.Map (Efl.Interface, Efl.Object) Remember all coordinates are canvas global ones like with move and resize in the canvas. + + This function should rarely be used as it overrides any other + transformation set. This property can be read to get the 4 points + positions on the canvas, or set to manually place them. ]] keys { idx: int; [[ID of the point, from 0 to 3 (included).]] } values { - x: double; [[Point X Coordinate.]] - y: double; [[Point Y Coordinate.]] - z: double; [[Point Z Coordinate hint (pre-perspective transform).]] + x: double; [[Point X coordinate in absolute pixel coordinates.]] + y: double; [[Point Y coordinate in absolute pixel coordinates.]] + z: double; [[Point Z coordinate hint (pre-perspective transform).]] } } - @property map_point_image_uv { + @property map_uv { [[Map point's U and V texture source point. - This sets/gets the U and V coordinates for the point. This determines which - coordinate in the source image is mapped to the given point, much like - OpenGL and textures. Notes that these points do select the pixel, but - are double floating point values to allow for accuracy and sub-pixel - selection. + This sets/gets the U and V coordinates for the point. This determines + which coordinate in the source image is mapped to the given point, + much like OpenGL and textures. Valid values range from 0.0 to 1.0. + + By default the points are set in a clockwise order, as such: + - 0: top-left, i.e. (0.0, 0.0), + - 1: top-right, i.e. (1.0, 0.0), + - 2: bottom-right, i.e. (1.0, 1.0), + - 3: bottom-left, i.e. (0.0, 1.0). ]] keys { idx: int; [[ID of the point, from 0 to 3 (included).]] } values { - u: double; [[X coordinate within the image/texture source.]] - v: double; [[Y coordinate within the image/texture source.]] + u: double; [[Relative X coordinate within the image, from 0 to 1.]] + v: double; [[Relative Y coordinate within the image, from 0 to 1.]] } } @property map_color { @@ -155,102 +149,131 @@ mixin Efl.Gfx.Map (Efl.Interface, Efl.Object) a: int; [[Alpha (0 - 255)]] } } - @property map_move_sync { - [[Status of object move synchronization for map rendering. + // FIXME: pivot & center need to be optional, but double(0.5) doesn't work! + rotate { + [[Apply a rotation to the object. - If the flag is set as enabled, the map will be moved as the object - is moved. - ]] - values { - enable: bool; [[$true by default.]] - } - } - map_rotate { - [[Change the map to apply the given rotation. + This rotates the object clockwise by $degrees degrees, around the + center specified by the relative position ($cx, $cy) in the $pivot + object. If $pivot is $null then this object is used as its own pivot + center. 360 degrees is a full rotation, equivalent to no rotation. + Negative values for $degrees will rotate clockwise by that amount. - This rotates the indicated map's coordinates around the center coordinate - given by $cx and $cy as the rotation center. The points will have their - X and Y coordinates rotated clockwise by $degrees degrees (360.0 is a - full rotation). Negative values for degrees will rotate counter-clockwise - by that amount. All coordinates are canvas global coordinates. + The coordinates are set relative to the given $pivot object. If its + geometry changes, then the absolute position of the rotation center + will change accordingly. + + By default, the center is at (0.5, 0.5). 0.0 means left or top while + 1.0 means right or bottom of the $pivot object. ]] params { degrees: double; [[CCW rotation in degrees.]] - cx: double; [[X coordinate of the rotation center.]] - cy: double; [[Y coordinate of the rotation center.]] + pivot: Efl.Gfx; [[A pivot object for the center point, can be $null.]] + cx: double; [[X relative coordinate of the center point.]] + cy: double; [[y relative coordinate of the center point.]] } - return: bool; [[$false in case of error.]] } - map_zoom { - [[Change the map to apply the given zooming. + rotate_3d { + [[Rotate the object around 3 axes in 3D. - Like evas_map_util_rotate(), this zooms the points of the map from a center - point. That center is defined by $cx and $cy. The $zoomx and $zoomy - parameters specify how much to zoom in the X and Y direction respectively. - A value of 1.0 means "don't zoom". 2.0 means "double the size". 0.5 is - "half the size" etc. All coordinates are canvas global coordinates. - ]] - params { - zoomx: double; [[Zoom in X direction]] - zoomy: double; [[Zoom in Y direction]] - cx: double; [[X coordinate of the center point.]] - cy: double; [[Y coordinate of the center point.]] - } - return: bool; [[$false in case of error.]] - } - map_rotate_3d { - [[Rotate the map around 3 axes in 3D + This will rotate in 3D and not just around the "Z" axis as the case + with @.rotate. This will rotate around the X, Y and Z axes. The + Z axis points "into" the screen with low values at the screen and + higher values further away. The X axis runs from left to right on + the screen and the Y axis from top to bottom. - This will rotate not just around the "Z" axis as in evas_map_util_rotate() - (which is a convenience call for those only wanting 2D). This will rotate - around the X, Y and Z axes. The Z axis points "into" the screen with low - values at the screen and higher values further away. The X axis runs from - left to right on the screen and the Y axis from top to bottom. Like with - evas_map_util_rotate() you provide a center point to rotate around (in 3D). + As with @.rotate, you provide a pivot and center point to rotate + around (in 3D). The Z coordinate of this center point is an absolute + value, and not a relative one like X and Y, as objects are flat in a + 2D space. ]] params { dx: double; [[Rotation in degrees around X axis (0 to 360).]] dy: double; [[Rotation in degrees around Y axis (0 to 360).]] dz: double; [[Rotation in degrees around Z axis (0 to 360).]] - cx: double; [[Rotation's center X position.]] - cy: double; [[Rotation's center Y position.]] - cz: double; [[Rotation's center Z position.]] + pivot: Efl.Gfx; [[A pivot object for the center point, can be $null.]] + cx: double; [[X relative coordinate of the center point.]] + cy: double; [[y relative coordinate of the center point.]] + cz: double; [[Z absolute coordinate of the center point.]] } - return: bool; [[$false in case of error.]] } - map_quat_rotate { - [[Rotate the map in 3D using a unit quaternion. + rotate_quat { + [[Rotate the object in 3D using a unit quaternion. - This will rotate in 3D using a unit quaternion. Like with - evas_map_util_3d_rotate() you provide a center point - to rotate around (in 3D). + This is similar to @.rotate_3d but uses a unit quaternion (also + known as versor) rather than a direct angle-based rotation around a + center point. Use this to avoid gimbal locks. + + As with @.rotate, you provide a pivot and center point to rotate + around (in 3D). The Z coordinate of this center point is an absolute + value, and not a relative one like X and Y, as objects are flat in a + 2D space. ]] params { qx: double; [[The x component of the imaginary part of the quaternion.]] qy: double; [[The y component of the imaginary part of the quaternion.]] qz: double; [[The z component of the imaginary part of the quaternion.]] qw: double; [[The w component of the real part of the quaternion.]] - cx: double; [[Rotation's center x.]] - cy: double; [[Rotation's center y.]] - cz: double; [[Rotation's center z.]] + pivot: Efl.Gfx; [[A pivot object for the center point, can be $null.]] + cx: double; [[X relative coordinate of the center point.]] + cy: double; [[y relative coordinate of the center point.]] + cz: double; [[Z absolute coordinate of the center point.]] } - return: bool; [[$false in case of error.]] } - map_lightning_3d { - [[Perform lighting calculations on the given Map + zoom { + [[Apply a zoom to the object. - This is used to apply lighting calculations (from a single light source) - to a given map. The R, G and B values of each vertex will be modified to - reflect the lighting based on the light point coordinates, the light - color and the ambient color, and at what angle the map is facing the - light source. A surface should have its points be declared in a - clockwise fashion if the face is "facing" towards you (as opposed to - away from you) as faces have a "logical" side for lighting. + This zooms the points of the map from a center point. That center is + defined by $cx and $cy. The $zoomx and $zoomy parameters specify how + much to zoom in the X and Y direction respectively. + A value of 1.0 means "don't zoom". 2.0 means "double the size". 0.5 is + "half the size" etc. + + By default, the center is at (0.5, 0.5). 0.0 means left or top while + 1.0 means right or bottom. ]] params { - lx: double; [[X coordinate in space of light point.]] - ly: double; [[Y coordinate in space of light point.]] - lz: double; [[Z coordinate in space of light point.]] + zoomx: double; [[Zoom in X direction]] + zoomy: double; [[Zoom in Y direction]] + pivot: Efl.Gfx; [[A pivot object for the center point, can be $null.]] + cx: double; [[X relative coordinate of the center point.]] + cy: double; [[y relative coordinate of the center point.]] + } + } + translate { + [[Apply a translation to the object using map. + + This does not change the real geometry of the object but will affect + its visible position. + ]] + params { + dx: double; [[Distance in pixels along the X axis.]] + dy: double; [[Distance in pixels along the Y axis.]] + dz: double; [[Distance in pixels along the Z axis.]] + } + } + lightning_3d { + [[Apply a lightning effect on the object. + + This is used to apply lighting calculations (from a single light + source) to a given mapped object. The R, G and B values of each + vertex will be modified to reflect the lighting based on the light + point coordinates, the light color and the ambient color, and at + what angle the map is facing the light source. A surface should have + its points be declared in a clockwise fashion if the face is + "facing" towards you (as opposed to away from you) as faces have a + "logical" side for lighting. + + The coordinates are set relative to the given $pivot object. If its + geometry changes, then the absolute position of the rotation center + will change accordingly. The Z position is absolute. If the $pivot + is $null then this object will be its own pivot. + ]] + params { + pivot: Efl.Gfx; [[A pivot object for the light point, can be $null.]] + lx: double; [[X relative coordinate in space of light point.]] + ly: double; [[Y relative coordinate in space of light point.]] + lz: double; [[Z absolute coordinate in space of light point.]] lr: int; [[Light red value (0 - 255).]] lg: int; [[Light green value (0 - 255).]] lb: int; [[Light blue value (0 - 255).]] @@ -258,9 +281,8 @@ mixin Efl.Gfx.Map (Efl.Interface, Efl.Object) ag: int; [[Ambient color green value (0 - 255).]] ab: int; [[Ambient color blue value (0 - 255).]] } - return: bool; [[$false in case of error.]] } - map_perspective_3d { + perspective_3d { [[Apply a perspective transform to the map This applies a given perspective (3D) to the map coordinates. X, Y and Z @@ -275,29 +297,23 @@ mixin Efl.Gfx.Map (Efl.Interface, Efl.Object) between the camera lens plane itself (at or closer than this rendering results are undefined) and the "z0" z value. This allows for some "depth" control and $foc must be greater than 0. + + The coordinates are set relative to the given $pivot object. If its + geometry changes, then the absolute position of the rotation center + will change accordingly. The Z position is absolute. If the $pivot + is $null then this object will be its own pivot. ]] params { - px: double; [[The perspective distance X coordinate]] - py: double; [[The perspective distance Y coordinate]] - z0: double; [[The "0" z plane value]] - foc: double; [[The focal distance]] + pivot: Efl.Gfx; [[A pivot object for the infinite point, can be $null.]] + px: double; [[The perspective distance X relative coordinate.]] + py: double; [[The perspective distance Y relative coordinate.]] + z0: double; [[The "0" Z plane value.]] + foc: double; [[The focal distance, must be greater than 0.]] } - return: bool; [[$false in case of error.]] - } - map_dup { - [[Duplicate the map information from another object.]] - params { - other: const(Efl.Gfx.Map); [[Map object to duplicate]] - } - return: bool; [[$false in case of error.]] } } implements { + Efl.Object.constructor; + Efl.Object.destructor; } } - - -// Porting notes: - -// Skipped APIs: -// evas_map_util_object_move_sync_{set,get} diff --git a/src/lib/evas/canvas/evas_main.c b/src/lib/evas/canvas/evas_main.c index 6af60da3ca..91757c5b2d 100644 --- a/src/lib/evas/canvas/evas_main.c +++ b/src/lib/evas/canvas/evas_main.c @@ -88,6 +88,8 @@ evas_init(void) if (!evas_thread_init()) goto shutdown_filter; + _efl_gfx_map_init(); + eina_log_timing(_evas_log_dom_global, EINA_LOG_STATE_STOP, EINA_LOG_STATE_INIT); @@ -141,6 +143,8 @@ evas_shutdown(void) evas_cserve2_shutdown(); #endif + _efl_gfx_map_shutdown(); + evas_font_path_global_clear(); eina_cow_del(evas_object_proxy_cow); eina_cow_del(evas_object_map_cow); diff --git a/src/lib/evas/canvas/evas_map.c b/src/lib/evas/canvas/evas_map.c index 820c0da2a6..fab6331759 100644 --- a/src/lib/evas/canvas/evas_map.c +++ b/src/lib/evas/canvas/evas_map.c @@ -137,16 +137,15 @@ evas_object_map_move_sync(Evas_Object *eo_obj) Evas_Map * _evas_map_new(int count, Eina_Bool sync) { - int i; - int alloc; Evas_Map *m; + int alloc; /* Adjust allocation such that: at least 4 points, and always an even * number: this allows the software engine to work efficiently */ alloc = (count < 4) ? 4 : count; if (alloc & 0x1) alloc ++; - m = calloc(1, sizeof(Evas_Map) + (alloc * sizeof(Evas_Map_Point))); + m = malloc(sizeof(Evas_Map) + (alloc * sizeof(Evas_Map_Point))); if (!m) return NULL; m->move_sync.enabled = sync; m->count = count; @@ -154,7 +153,7 @@ _evas_map_new(int count, Eina_Bool sync) m->alpha = 1; m->smooth = 1; m->magic = MAGIC_MAP; - for (i = 0; i < count; i++) + for (int i = 0; i < count; i++) { m->points[i].r = 255; m->points[i].g = 255; @@ -416,9 +415,9 @@ _evas_object_map_parent_check(Evas_Object *eo_parent) } #endif -static void -_map_map_enable_set(Eo *eo_obj, Evas_Object_Protected_Data *obj, - Eina_Bool enabled, Eina_Bool default_move_sync) +void +_evas_object_map_enable_set(Eo *eo_obj, Evas_Object_Protected_Data *obj, + Eina_Bool enabled) { Eina_Bool pchange = EINA_FALSE; @@ -436,7 +435,7 @@ _map_map_enable_set(Eo *eo_obj, Evas_Object_Protected_Data *obj, if (!obj->map->cur.map) { EINA_COW_WRITE_BEGIN(evas_object_map_cow, obj->map, Evas_Object_Map_Data, map_write) - map_write->cur.map = _evas_map_new(4, default_move_sync); + map_write->cur.map = _evas_map_new(4, EINA_FALSE); EINA_COW_WRITE_END(evas_object_map_cow, obj->map, map_write); } evas_object_mapped_clip_across_mark(eo_obj, obj); @@ -484,26 +483,19 @@ _map_map_enable_set(Eo *eo_obj, Evas_Object_Protected_Data *obj, } } -EOLIAN void -_efl_canvas_object_efl_gfx_map_map_enable_set(Eo *eo_obj, void *_pd EINA_UNUSED, Eina_Bool enabled) -{ - Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS); - - _map_map_enable_set(eo_obj, obj, enabled, EINA_TRUE); -} - EAPI void -evas_object_map_enable_set(Efl_Gfx_Map *eo_obj, Eina_Bool enabled) +evas_object_map_enable_set(Eo *eo_obj, Eina_Bool enabled) { Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj); - _map_map_enable_set(eo_obj, obj, enabled, EINA_FALSE); + _evas_object_map_enable_set(eo_obj, obj, enabled); } -EOLIAN Eina_Bool -_efl_canvas_object_efl_gfx_map_map_enable_get(Eo *eo_obj EINA_UNUSED, void *_pd EINA_UNUSED) +EAPI Eina_Bool +evas_object_map_enable_get(const Eo *eo_obj) { - Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS); + Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj, EINA_FALSE); + return obj->map->cur.usemap; } @@ -984,6 +976,22 @@ evas_map_util_zoom(Evas_Map *m, double zoomx, double zoomy, Evas_Coord cx, Evas_ _map_util_zoom(m, zoomx, zoomy, (double) cx, (double) cy); } +void +_map_util_translate(Evas_Map *m, double dx, double dy, double dz) +{ + Evas_Map_Point *p, *p_end; + + p = m->points; + p_end = p + m->count; + + for (; p < p_end; p++) + { + p->px = (p->x += dx); + p->py = (p->y += dy); + p->z += dz; + } +} + void _map_util_3d_rotate(Evas_Map *m, double dx, double dy, double dz, double cx, double cy, double cz) @@ -1045,9 +1053,9 @@ evas_map_util_3d_rotate(Evas_Map *m, double dx, double dy, double dz, _map_util_3d_rotate(m, dx, dy, dz, (double) cx, (double) cy, (double) cz); } -EAPI void -evas_map_util_quat_rotate(Evas_Map *m, double qx, double qy, double qz, - double qw, double cx, double cy, double cz) +void +_map_util_quat_rotate(Evas_Map *m, double qx, double qy, double qz, + double qw, double cx, double cy, double cz) { Eina_Quaternion q; Eina_Point_3D c; @@ -1086,6 +1094,17 @@ evas_map_util_quat_rotate(Evas_Map *m, double qx, double qy, double qz, } } +EAPI void +evas_map_util_quat_rotate(Evas_Map *m, double qx, double qy, double qz, + double qw, double cx, double cy, double cz) +{ + MAGIC_CHECK(m, Evas_Map, MAGIC_MAP); + return; + MAGIC_CHECK_END(); + + _map_util_quat_rotate(m, qx, qy, qz, qw, cx, cy, cz); +} + void _map_util_3d_lighting(Evas_Map *m, double lx, double ly, double lz, diff --git a/src/lib/evas/canvas/evas_map.h b/src/lib/evas/canvas/evas_map.h index f1287bcf40..39377f66d9 100644 --- a/src/lib/evas/canvas/evas_map.h +++ b/src/lib/evas/canvas/evas_map.h @@ -11,9 +11,12 @@ Evas_Map *_evas_map_new(int count, Eina_Bool sync); void _evas_map_calc_map_geometry(Evas_Object *eo_obj); void _map_util_rotate(Evas_Map *m, double degrees, double cx, double cy); void _map_util_zoom(Evas_Map *m, double zoomx, double zoomy, double cx, double cy); +void _map_util_translate(Evas_Map *m, double dx, double dy, double dz); void _map_util_3d_rotate(Evas_Map *m, double dx, double dy, double dz, double cx, double cy, double cz); void _map_util_3d_lighting(Evas_Map *m, double lx, double ly, double lz, int lr, int lg, int lb, int ar, int ag, int ab); void _map_util_3d_perspective(Evas_Map *m, double px, double py, double z0, double foc); +void _map_util_quat_rotate(Evas_Map *m, double qx, double qy, double qz, double qw, double cx, double cy, double cz); +void _evas_object_map_enable_set(Eo *eo_obj, Evas_Object_Protected_Data *obj, Eina_Bool enabled); static inline void _evas_map_util_points_populate(Evas_Map *m, const double x, const double y, @@ -85,5 +88,15 @@ error: if (z) *z = 0; } +#define MAP_OBJ_CHANGE() do { \ + _evas_map_calc_map_geometry(eo_obj); \ + evas_object_change(eo_obj, obj); \ + obj->changed_map = EINA_TRUE; \ + } while (0) + +#define MAP_POPULATE_DEFAULT(m, z) \ + _evas_map_util_points_populate(m, obj->cur->geometry.x, obj->cur->geometry.y, \ + obj->cur->geometry.w, obj->cur->geometry.h, z) + #endif // EVAS_MAP_H diff --git a/src/lib/evas/canvas/evas_render.c b/src/lib/evas/canvas/evas_render.c index 7e2ab4fa49..7d9a138deb 100644 --- a/src/lib/evas/canvas/evas_render.c +++ b/src/lib/evas/canvas/evas_render.c @@ -486,6 +486,8 @@ _evas_render_phase1_direct(Evas_Public_Data *e, _evas_mask_redraw_set(e, obj); } + _evas_object_gfx_map_update(obj); + RD(0, " pre-render-done smart:%p|%p [%p, %i] | [%p, %i] has_map:%i had_map:%i\n", obj->smart.smart, obj->is_smart ? evas_object_smart_members_get_direct(eo_obj) : NULL, @@ -1121,6 +1123,7 @@ _evas_render_phase1_object_process(Phase1_Context *p1ctx, } #endif + _evas_object_gfx_map_update(obj); map = _evas_render_has_map(obj); hmap = _evas_render_had_map(obj); can_map = _evas_render_can_map(obj); @@ -1243,6 +1246,7 @@ _evas_render_check_pending_objects(Eina_Array *pending_objects, Evas *eo_e EINA_ if (!obj->layer) goto clean_stuff; + _evas_object_gfx_map_update(obj); EINA_PREFETCH(&(obj->cur->clipper)); EINA_PREFETCH(&(obj->cur->cache.clip)); //If the children are in active objects, They should be cleaned up. @@ -1358,10 +1362,12 @@ _evas_render_can_use_overlay(Evas_Public_Data *e, Evas_Object *eo_obj) /* Check if any one is the stack make this object mapped */ eo_tmp = eo_obj; tmp = efl_data_scope_get(eo_tmp, EFL_CANVAS_OBJECT_CLASS); + _evas_object_gfx_map_update(tmp); while (tmp && !(_evas_render_has_map(tmp) && !_evas_render_can_map(tmp))) { eo_tmp = tmp->smart.parent; tmp = efl_data_scope_get(eo_tmp, EFL_CANVAS_OBJECT_CLASS); + if (tmp) _evas_object_gfx_map_update(tmp); } if (tmp && _evas_render_has_map(tmp) && !_evas_render_can_map(tmp)) @@ -1725,6 +1731,7 @@ evas_render_mapped(Evas_Public_Data *evas, Evas_Object *eo_obj, proxy_src_clip = proxy_render_data->source_clip; evas_object_clip_recalc(obj); + _evas_object_gfx_map_update(obj); /* leave early if clipper is not visible */ if ((obj->cur->clipper) && (!obj->cur->clipper->cur->visible)) diff --git a/src/lib/evas/include/evas_inline.x b/src/lib/evas/include/evas_inline.x index d2b6a70c42..a48251a7b5 100644 --- a/src/lib/evas/include/evas_inline.x +++ b/src/lib/evas/include/evas_inline.x @@ -31,6 +31,13 @@ _evas_render_can_map(Evas_Object_Protected_Data *obj) return obj->func->can_map(obj->object); } +static inline void +_evas_object_gfx_map_update(Evas_Object_Protected_Data *obj) +{ + if (!obj->gfx_map_has) return; + _efl_gfx_map_update(obj->object); +} + static inline int _evas_object_event_new(void) { diff --git a/src/lib/evas/include/evas_private.h b/src/lib/evas/include/evas_private.h index 3c7ec1639f..f46c928ef2 100644 --- a/src/lib/evas/include/evas_private.h +++ b/src/lib/evas/include/evas_private.h @@ -1222,6 +1222,8 @@ struct _Evas_Object_Protected_Data Eina_Bool snapshot_needs_redraw : 1; Eina_Bool snapshot_no_obscure : 1; + Eina_Bool gfx_map_has : 1; + Eina_Bool gfx_map_update : 1; struct { Eina_Bool pass_events : 1; @@ -1891,6 +1893,11 @@ void _evas_canvas3d_eet_file_free(Evas_Canvas3D_File_Eet* eet_file); void evas_filter_init(void); void evas_filter_shutdown(void); +/* Efl.Gfx.Map */ +void _efl_gfx_map_init(void); +void _efl_gfx_map_shutdown(void); +void _efl_gfx_map_update(Eo *eo_obj); + /* Ector */ Ector_Surface *evas_ector_get(Evas_Public_Data *evas, void *output);