evas map: Introduce new API for maps (Efl.Gfx.Map)

This implements an entirely new API model for Evas Map by relying
on high-level transformations on the object rather than an external
Evas_Map structure that needs to be constantly updated manually.

The implementation relies on Evas_Map.

To rotate an object all you need to do now is
  efl_gfx_map_rotate(obj, 45.0, NULL, 0.5, 0.5);

Or with a C++ syntax:
  obj.rotate(45.0, NULL, 0.5, 0.5);

Or even simply (with default arguments):
  obj.rotate(45.0);

The map transformation functions are:
 - rotate
 - rotate_3d
 - rotate_quat
 - zoom
 - translate (new!)
 - perspective_3d
 - lightning_3d

@feature
This commit is contained in:
Jean-Philippe Andre 2017-04-26 15:11:51 +09:00
parent d111c6e1dd
commit 0a224da86f
14 changed files with 938 additions and 561 deletions

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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;

View File

@ -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"
/**

View File

@ -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; }
}

View File

@ -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"

View File

@ -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}

View File

@ -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);

View File

@ -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,

View File

@ -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

View File

@ -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))

View File

@ -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)
{

View File

@ -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);