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; Eo *ly = data;
if (!efl_gfx_map_enable_get(ly)) if (!efl_gfx_map_has(ly))
{ {
int x, y, w, h; efl_gfx_map_zoom(ly, 0.8, 0.8, NULL, 0.5, 0.5);
efl_gfx_map_reset(ly); efl_gfx_map_rotate(ly, 45, NULL, 0.5, 0.5);
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);
} }
else efl_gfx_map_reset(ly);
} }
static void static void

View File

@ -25,24 +25,6 @@ static const char *filter =
"print ('Evaluating filter: ' .. input.width .. 'x' .. input.height)" "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 * static inline Eo *
_image_create(Eo *win, const char *path) _image_create(Eo *win, const char *path)
{ {
@ -120,26 +102,6 @@ _close_do(void *data, const Efl_Event *ev EINA_UNUSED)
efl_del(win); 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 static void
_toggle_map(void *data, const Efl_Event *ev EINA_UNUSED) _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; Eo *snap;
snap = efl_key_wref_get(win, "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); efl_gfx_map_zoom(snap, 0.8, 0.8, NULL, 0.5, 0.5);
_map_do(snap, NULL); efl_gfx_map_rotate(snap, 20.0, NULL, 0.5, 0.5);
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);
} }
else efl_gfx_map_reset(snap);
} }
void 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_key_wref_set(win, "grid", grid);
efl_gfx_size_set(win, 400, 400); efl_gfx_size_set(win, 400, 400);
efl_gfx_visible_set(win, 1); 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 }; EINA_FALSE, EINA_FALSE, EINA_FALSE, EINA_FALSE, EINA_FALSE };
static void 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_raw_coord_set(d.target2, 0, d.px1 + 400, d.py1, 0);
efl_gfx_map_point_coord_set(d.target1, 1, d.px2, d.py2, 0); efl_gfx_map_raw_coord_set(d.target2, 1, d.px2 + 400, d.py2, 0);
efl_gfx_map_point_coord_set(d.target1, 2, d.px3, d.py3, 0); efl_gfx_map_raw_coord_set(d.target2, 2, d.px3 + 400, d.py3, 0);
efl_gfx_map_point_coord_set(d.target1, 3, d.px4, d.py4, 0); efl_gfx_map_raw_coord_set(d.target2, 3, d.px4 + 400, 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);
} }
static void static void

View File

@ -69,96 +69,81 @@ static Eina_Bool
_anim_cb(void *data) _anim_cb(void *data)
{ {
App_Data *ad = data; App_Data *ad = data;
Evas_Object *o, *ref; Evas_Object *o;
int r, g, b, a; int r, g, b, a, x, y, w, h, f;
int win_w, win_h, img_w, img_h; int win_w, win_h, mx, my;
Evas_Coord x, y, w, h;
evas_output_size_get(ad->canvas, &win_w, &win_h);
f = ad->frame;
r = ad->colors[ad->colors_index].r; r = ad->colors[ad->colors_index].r;
g = ad->colors[ad->colors_index].g; g = ad->colors[ad->colors_index].g;
b = ad->colors[ad->colors_index].b; b = ad->colors[ad->colors_index].b;
a = ad->colors[ad->colors_index].a; 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"); o = evas_object_name_find(ad->canvas, "obj1");
evas_object_geometry_get(o, &x, &y, &w, &h); efl_gfx_map_reset(o);
efl_gfx_map_rotate(o, 3 * f, NULL, 0.5, 0.5);
efl_gfx_map_populate(o, 0);
efl_gfx_map_rotate(o, 3 * ad->frame, x + (w / 2), y + (h / 2));
efl_gfx_map_smooth_set(o, ad->smooth); efl_gfx_map_smooth_set(o, ad->smooth);
efl_gfx_map_alpha_set(o, ad->alpha); efl_gfx_map_alpha_set(o, ad->alpha);
efl_gfx_map_color_set(o, -1, r, g, b, a); 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"); o = evas_object_name_find(ad->canvas, "obj2");
evas_object_geometry_get(o, &x, &y, &w, &h); efl_gfx_size_get(o, NULL, &h);
evas_object_image_size_get(o, &img_w, &img_h); efl_gfx_map_reset(o);
efl_gfx_map_smooth_set(o, ad->smooth);
efl_gfx_map_dup(o, ref); efl_gfx_map_alpha_set(o, ad->alpha);
efl_gfx_map_populate(o, 100); efl_gfx_map_color_set(o, -1, r, g, b, a);
efl_gfx_map_point_image_uv_set(o, 0, 0, 0); efl_gfx_map_translate(o, 0, 0, 100);
efl_gfx_map_point_image_uv_set(o, 1, img_w, 0); efl_gfx_map_rotate_3d(o, f * 6, f * 6, f * 6, NULL, 1./3., 10. / h, 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);
if (ad->apply_lighting) 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_lightning_3d(o, ad->canvas, 0.5, 0.5, -100.,
efl_gfx_map_enable_set(o, EINA_TRUE); 255, 255, 255, 0, 0, 0);
}
o = evas_object_name_find(ad->canvas, "obj3"); o = evas_object_name_find(ad->canvas, "obj3");
evas_object_geometry_get(o, &x, &y, &w, &h); efl_gfx_size_get(o, &w, &h);
evas_object_image_size_get(o, &img_w, &img_h); efl_gfx_map_reset(o);
efl_gfx_map_smooth_set(o, ad->smooth);
efl_gfx_map_dup(o, ref); efl_gfx_map_alpha_set(o, ad->alpha);
efl_gfx_map_populate_manual(o, x, y + (h / 2), w, h, -20); efl_gfx_map_color_set(o, -1, r, g, b, a);
efl_gfx_map_point_image_uv_set(o, 0, 0, 0); efl_gfx_map_translate(o, 0, h/2, -20);
efl_gfx_map_point_image_uv_set(o, 1, img_w, 0); efl_gfx_map_rotate_3d(o, 20, f * 6, 0, NULL, 0.5, 0.5, w / 2);
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);
if (ad->apply_perspective) 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) if (ad->apply_lighting)
{ {
Evas_Coord mx, my;
evas_pointer_canvas_xy_get(ad->canvas, &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 (ad->backface_culling)
{ efl_gfx_visible_set(o, efl_gfx_map_clockwise_get(o));
if (efl_gfx_map_clockwise_get(o))
evas_object_show(o);
else
evas_object_hide(o);
}
else else
evas_object_show(o); efl_gfx_visible_set(o, 1);
efl_gfx_map_enable_set(o, EINA_TRUE);
o = evas_object_name_find(ad->canvas, "obj4"); o = evas_object_name_find(ad->canvas, "obj4");
efl_gfx_geometry_get(o, &x, &y, &w, &h); efl_gfx_geometry_get(o, &x, &y, &w, &h);
efl_gfx_view_size_get(o, &img_w, &img_h); efl_gfx_map_reset(o);
efl_gfx_map_smooth_set(o, ad->smooth);
efl_gfx_map_dup(o, ref); efl_gfx_map_alpha_set(o, ad->alpha);
efl_gfx_map_point_coord_set(o, 0, x, y + h, 0); efl_gfx_map_raw_coord_set(o, 0, x, y + h, 0);
efl_gfx_map_point_coord_set(o, 1, x + w, y + h, 0); efl_gfx_map_raw_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_raw_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_raw_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_uv_set(o, 0, 0, 1);
efl_gfx_map_point_image_uv_set(o, 1, img_w, img_h); efl_gfx_map_uv_set(o, 1, 1, 1);
efl_gfx_map_point_image_uv_set(o, 2, img_w, 2 * (img_h / 3)); efl_gfx_map_uv_set(o, 2, 1, 2. / 3.);
efl_gfx_map_point_image_uv_set(o, 3, 0, 2 * (img_h / 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, 0, 200, 200, 200, 150);
efl_gfx_map_color_set(o, 1, 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, 2, 0, 0, 0, 0);
efl_gfx_map_color_set(o, 3, 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; 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); 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" #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_margin { get; set; }
Efl.Gfx.Size.Hint.hint_request { get; set; } Efl.Gfx.Size.Hint.hint_request { get; set; }
Efl.Gfx.Size.Hint.hint_weight { 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.Input.Interface.seat_event_filter { get; set; }
Efl.Loop_User.loop { get; } Efl.Loop_User.loop { get; }
} }

View File

@ -1,325 +1,701 @@
#include "evas_map.h" #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 #define MY_CLASS EFL_GFX_MAP_MIXIN
/* Efl.Gfx.Map implementation - relies on legacy for now */ typedef struct _Gfx_Map Gfx_Map;
// note: cur vs. prev is not handled 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 { \ enum _Gfx_Map_Op_Type {
_evas_map_calc_map_geometry(eo_obj); \ GFX_MAP_ROTATE_2D,
evas_object_change(eo_obj, obj); \ GFX_MAP_ROTATE_3D,
obj->changed_map = EINA_TRUE; \ GFX_MAP_ROTATE_QUAT,
} while (0) GFX_MAP_ZOOM,
GFX_MAP_TRANSLATE,
GFX_MAP_LIGHTNING_3D,
GFX_MAP_PERSPECTIVE_3D,
};
#define MAP_POPULATE_DEFAULT(m, z) \ struct _Gfx_Map_Op {
_evas_map_util_points_populate(m, obj->cur->geometry.x, obj->cur->geometry.y, \ EINA_INLIST;
obj->cur->geometry.w, obj->cur->geometry.h, z)
static Eina_Bool Gfx_Map_Op_Type op;
_map_populate(Eo *eo_obj, int z) 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); gfx_map_cow = eina_cow_add("Efl.Gfx.Map", sizeof(Gfx_Map), 8,
Evas_Map *m; &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 (!pd->cow->event_cbs)
if (!m) return EINA_FALSE; {
MAP_POPULATE_DEFAULT(m, z); MAPCOW_WRITE(pd, event_cbs, EINA_TRUE);
evas_object_map_set(eo_obj, m); efl_event_callback_add(eo_obj, EFL_GFX_EVENT_MOVE, _geometry_changed_cb, obj);
evas_map_free(m); 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 else
{ {
m = (Evas_Map *) obj->map->cur.map; _evas_map_util_points_populate(m, obj->cur->geometry.x, obj->cur->geometry.y,
MAP_POPULATE_DEFAULT(m, z); obj->cur->geometry.w, obj->cur->geometry.h, 0);
MAP_OBJ_CHANGE();
} }
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 EOLIAN static void
_efl_gfx_map_map_reset(Eo *eo_obj, void *_pd EINA_UNUSED) _efl_gfx_map_map_reset(Eo *eo_obj, Efl_Gfx_Map_Data *pd)
{
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)
{ {
Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj); 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; efl_event_callback_del(eo_obj, EFL_GFX_EVENT_MOVE, _geometry_changed_cb, obj);
if (!_map_populate(eo_obj, 0)) efl_event_callback_del(eo_obj, EFL_GFX_EVENT_RESIZE, _geometry_changed_cb, obj);
return;
} }
m = (Evas_Map *) obj->map->cur.map; eina_cow_memcpy(gfx_map_cow, (const Eina_Cow_Data * const *) &pd->cow,
m->smooth = smooth; (const Eina_Cow_Data *) &gfx_map_cow_default);
MAP_OBJ_CHANGE(); _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 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); Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj, EINA_TRUE);
return om ? om->smooth : 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 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_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 (x) *x = pd->cow->point[idx].x;
if (!_map_populate(eo_obj, 0)) if (y) *y = pd->cow->point[idx].y;
return; if (z) *z = pd->cow->point[idx].z;
return;
} }
m = (Evas_Map *) obj->map->cur.map; if (!m)
m->alpha = alpha; {
MAP_OBJ_CHANGE(); int X, Y, W, H;
}
EOLIAN static Eina_Bool X = obj->cur->geometry.x;
_efl_gfx_map_map_alpha_get(Eo *eo_obj, void *_pd EINA_UNUSED) Y = obj->cur->geometry.y;
{ W = obj->cur->geometry.w;
const Evas_Map *om = evas_object_map_get(eo_obj); H = obj->cur->geometry.h;
return om ? om->alpha : EINA_TRUE;
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 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)); EINA_SAFETY_ON_FALSE_RETURN((idx >= 0) && (idx < 4));
Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj); if (u) *u = pd->cow->point[idx].u;
Evas_Map *m; if (v) *v = pd->cow->point[idx].v;
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();
} }
EOLIAN static void 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); int kmin = 0, kmax = 3;
_map_point_coord_get(om, idx, x, y, z); 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)); EINA_SAFETY_ON_FALSE_RETURN((idx >= -1) && (idx < 4));
Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj); if ((idx != -1) &&
Evas_Map *m; (pd->cow->point[idx].r == r) && (pd->cow->point[idx].g == g) &&
(pd->cow->point[idx].b == b) && (pd->cow->point[idx].a == a))
if (!obj->map->cur.map && !_map_populate(eo_obj, 0))
return; return;
m = (Evas_Map *) obj->map->cur.map; if (idx >= 0)
if (idx == -1) kmin = kmax = idx;
evas_map_util_points_color_set(m, r, g, b, a);
else mcow = MAPCOW_BEGIN(pd);
evas_map_point_color_set(m, idx, r, g, b, a); for (int k = kmin; k <= kmax; k++)
MAP_OBJ_CHANGE(); {
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 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 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); Gfx_Map_Op *op;
Evas_Map *m;
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; ERR("Focal length must be greater than 0!");
if (!_map_populate(eo_obj, 0)) return;
return;
} }
m = (Evas_Map *) obj->map->cur.map; op = _gfx_map_op_add(eo_obj, pd, GFX_MAP_PERSPECTIVE_3D, pivot, px, py, 0);
m->move_sync.enabled = enable; if (!op) return;
MAP_OBJ_CHANGE();
}
EOLIAN static Eina_Bool op->perspective_3d.z0 = z0;
_efl_gfx_map_map_move_sync_get(Eo *eo_obj, void *_pd EINA_UNUSED) op->perspective_3d.foc = foc;
{
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;
} }
#include "canvas/efl_gfx_map.eo.c" #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 positioning at target. This allows rotation, perspective, scale and
lots of other effects, depending on the map that is used. lots of other effects, depending on the map that is used.
Each map point may carry a multiplier color. If properly Each map point may carry a multiplier color. If properly calculated,
calculated, these can do shading effects on the object, producing these can do shading effects on the object, producing 3D effects.
3D effects.
At the moment of writing, maps can only have 4 points (no more, no less). 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 @since 1.20
shouldn't be used anywhere else.
]] ]]
data: null;
methods { methods {
@property map_enable @pure_virtual { map_has {
[[Whether map transformation is enabled on this object. [[Read-only property indicating whether an object is mapped.
The default map enable state is off ($false). The other This will be $true if any transformation is applied to this object.
properties and methods in this class have no effect until
this property is enabled.
]] ]]
set { return: bool; [[$true if the object is mapped.]]
[[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.]]
}
} }
map_reset { map_reset {
[[Resets the map transformation to its default state. [[Resets the map transformation to its default state.
This will reset all transformations to identity, meaning the points' This will reset all transformations to identity, meaning the points'
colors, positions and UV coordinates will be reset to their default colors, positions and UV coordinates will be reset to their default
values. This does not reset the @.map_enable flag. values. @.map_has will then return $false. This function will
not modify the values of @.map_smooth or @.map_alpha.
@since 1.20
]] ]]
} }
@property map_clockwise { @property map_clockwise {
[[Clockwise state of a map (read-only). [[Clockwise state of a map (read-only).
This determines if the output points (X and Y. Z is not used) are 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 clockwise or counter-clockwise. This can be used for "back-face
is where you hide objects that "face away" from you. In this case objects culling". This is where you hide objects that "face away" from you.
that are not clockwise. In this case objects that are not clockwise.
]] ]]
get {} get {}
values { values {
@ -78,18 +60,22 @@ mixin Efl.Gfx.Map (Efl.Interface, Efl.Object)
@property map_alpha { @property map_alpha {
[[Alpha flag for map rendering. [[Alpha flag for map rendering.
This sets alpha flag for map rendering. If the object is a type that has This sets alpha flag for map rendering. If the object is a type that
its own alpha settings, then this will take precedence. Only image objects has its own alpha settings, then this will take precedence. Only
have this currently ($Efl.Canvas.Image and its friends). image objects support this currently ($Efl.Canvas.Image and its
Setting this off stops alpha blending of the map area, and is friends). Setting this off stops alpha blending of the map area,
useful if you know the object and/or all sub-objects is 100% solid. 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 { values {
alpha: bool; [[$true by default.]] alpha: bool; [[$true by default.]]
} }
} }
@property map_point_coord { @property map_raw_coord {
[[Map point's coordinate. [[A point's absolute coordinate on the canvas.
This sets/gets the fixed point's coordinate in the map. Note that points 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 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 Remember all coordinates are canvas global ones like with move and resize
in the canvas. 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 { keys {
idx: int; [[ID of the point, from 0 to 3 (included).]] idx: int; [[ID of the point, from 0 to 3 (included).]]
} }
values { values {
x: double; [[Point X Coordinate.]] x: double; [[Point X coordinate in absolute pixel coordinates.]]
y: double; [[Point Y Coordinate.]] y: double; [[Point Y coordinate in absolute pixel coordinates.]]
z: double; [[Point Z Coordinate hint (pre-perspective transform).]] 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. [[Map point's U and V texture source point.
This sets/gets the U and V coordinates for the point. This determines which This sets/gets the U and V coordinates for the point. This determines
coordinate in the source image is mapped to the given point, much like which coordinate in the source image is mapped to the given point,
OpenGL and textures. Notes that these points do select the pixel, but much like OpenGL and textures. Valid values range from 0.0 to 1.0.
are double floating point values to allow for accuracy and sub-pixel
selection. 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 { keys {
idx: int; [[ID of the point, from 0 to 3 (included).]] idx: int; [[ID of the point, from 0 to 3 (included).]]
} }
values { values {
u: double; [[X coordinate within the image/texture source.]] u: double; [[Relative X coordinate within the image, from 0 to 1.]]
v: double; [[Y coordinate within the image/texture source.]] v: double; [[Relative Y coordinate within the image, from 0 to 1.]]
} }
} }
@property map_color { @property map_color {
@ -155,102 +149,131 @@ mixin Efl.Gfx.Map (Efl.Interface, Efl.Object)
a: int; [[Alpha (0 - 255)]] a: int; [[Alpha (0 - 255)]]
} }
} }
@property map_move_sync { // FIXME: pivot & center need to be optional, but double(0.5) doesn't work!
[[Status of object move synchronization for map rendering. rotate {
[[Apply a rotation to the object.
If the flag is set as enabled, the map will be moved as the object This rotates the object clockwise by $degrees degrees, around the
is moved. 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
values { center. 360 degrees is a full rotation, equivalent to no rotation.
enable: bool; [[$true by default.]] Negative values for $degrees will rotate clockwise by that amount.
}
}
map_rotate {
[[Change the map to apply the given rotation.
This rotates the indicated map's coordinates around the center coordinate The coordinates are set relative to the given $pivot object. If its
given by $cx and $cy as the rotation center. The points will have their geometry changes, then the absolute position of the rotation center
X and Y coordinates rotated clockwise by $degrees degrees (360.0 is a will change accordingly.
full rotation). Negative values for degrees will rotate counter-clockwise
by that amount. All coordinates are canvas global coordinates. 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 { params {
degrees: double; [[CCW rotation in degrees.]] degrees: double; [[CCW rotation in degrees.]]
cx: double; [[X coordinate of the rotation center.]] pivot: Efl.Gfx; [[A pivot object for the center point, can be $null.]]
cy: double; [[Y coordinate of the rotation center.]] 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 { rotate_3d {
[[Change the map to apply the given zooming. [[Rotate the object around 3 axes in 3D.
Like evas_map_util_rotate(), this zooms the points of the map from a center This will rotate in 3D and not just around the "Z" axis as the case
point. That center is defined by $cx and $cy. The $zoomx and $zoomy with @.rotate. This will rotate around the X, Y and Z axes. The
parameters specify how much to zoom in the X and Y direction respectively. Z axis points "into" the screen with low values at the screen and
A value of 1.0 means "don't zoom". 2.0 means "double the size". 0.5 is higher values further away. The X axis runs from left to right on
"half the size" etc. All coordinates are canvas global coordinates. the screen and the Y axis from top to bottom.
]]
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 not just around the "Z" axis as in evas_map_util_rotate() As with @.rotate, you provide a pivot and center point to rotate
(which is a convenience call for those only wanting 2D). This will rotate around (in 3D). The Z coordinate of this center point is an absolute
around the X, Y and Z axes. The Z axis points "into" the screen with low value, and not a relative one like X and Y, as objects are flat in a
values at the screen and higher values further away. The X axis runs from 2D space.
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).
]] ]]
params { params {
dx: double; [[Rotation in degrees around X axis (0 to 360).]] dx: double; [[Rotation in degrees around X axis (0 to 360).]]
dy: double; [[Rotation in degrees around Y 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).]] dz: double; [[Rotation in degrees around Z axis (0 to 360).]]
cx: double; [[Rotation's center X position.]] pivot: Efl.Gfx; [[A pivot object for the center point, can be $null.]]
cy: double; [[Rotation's center Y position.]] cx: double; [[X relative coordinate of the center point.]]
cz: double; [[Rotation's center Z position.]] 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_quat {
[[Rotate the map in 3D using a unit quaternion. [[Rotate the object in 3D using a unit quaternion.
This will rotate in 3D using a unit quaternion. Like with This is similar to @.rotate_3d but uses a unit quaternion (also
evas_map_util_3d_rotate() you provide a center point known as versor) rather than a direct angle-based rotation around a
to rotate around (in 3D). 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 { params {
qx: double; [[The x component of the imaginary part of the quaternion.]] qx: double; [[The x component of the imaginary part of the quaternion.]]
qy: double; [[The y 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.]] qz: double; [[The z component of the imaginary part of the quaternion.]]
qw: double; [[The w component of the real part of the quaternion.]] qw: double; [[The w component of the real part of the quaternion.]]
cx: double; [[Rotation's center x.]] pivot: Efl.Gfx; [[A pivot object for the center point, can be $null.]]
cy: double; [[Rotation's center y.]] cx: double; [[X relative coordinate of the center point.]]
cz: double; [[Rotation's center z.]] 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 { zoom {
[[Perform lighting calculations on the given Map [[Apply a zoom to the object.
This is used to apply lighting calculations (from a single light source) This zooms the points of the map from a center point. That center is
to a given map. The R, G and B values of each vertex will be modified to defined by $cx and $cy. The $zoomx and $zoomy parameters specify how
reflect the lighting based on the light point coordinates, the light much to zoom in the X and Y direction respectively.
color and the ambient color, and at what angle the map is facing the A value of 1.0 means "don't zoom". 2.0 means "double the size". 0.5 is
light source. A surface should have its points be declared in a "half the size" etc.
clockwise fashion if the face is "facing" towards you (as opposed to
away from you) as faces have a "logical" side for lighting. By default, the center is at (0.5, 0.5). 0.0 means left or top while
1.0 means right or bottom.
]] ]]
params { params {
lx: double; [[X coordinate in space of light point.]] zoomx: double; [[Zoom in X direction]]
ly: double; [[Y coordinate in space of light point.]] zoomy: double; [[Zoom in Y direction]]
lz: double; [[Z coordinate in space of light point.]] 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).]] lr: int; [[Light red value (0 - 255).]]
lg: int; [[Light green value (0 - 255).]] lg: int; [[Light green value (0 - 255).]]
lb: int; [[Light blue 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).]] ag: int; [[Ambient color green value (0 - 255).]]
ab: int; [[Ambient color blue 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 [[Apply a perspective transform to the map
This applies a given perspective (3D) to the map coordinates. X, Y and Z 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 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" results are undefined) and the "z0" z value. This allows for some "depth"
control and $foc must be greater than 0. 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 { params {
px: double; [[The perspective distance X coordinate]] pivot: Efl.Gfx; [[A pivot object for the infinite point, can be $null.]]
py: double; [[The perspective distance Y coordinate]] px: double; [[The perspective distance X relative coordinate.]]
z0: double; [[The "0" z plane value]] py: double; [[The perspective distance Y relative coordinate.]]
foc: double; [[The focal distance]] 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 { 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()) if (!evas_thread_init())
goto shutdown_filter; goto shutdown_filter;
_efl_gfx_map_init();
eina_log_timing(_evas_log_dom_global, eina_log_timing(_evas_log_dom_global,
EINA_LOG_STATE_STOP, EINA_LOG_STATE_STOP,
EINA_LOG_STATE_INIT); EINA_LOG_STATE_INIT);
@ -141,6 +143,8 @@ evas_shutdown(void)
evas_cserve2_shutdown(); evas_cserve2_shutdown();
#endif #endif
_efl_gfx_map_shutdown();
evas_font_path_global_clear(); evas_font_path_global_clear();
eina_cow_del(evas_object_proxy_cow); eina_cow_del(evas_object_proxy_cow);
eina_cow_del(evas_object_map_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 *
_evas_map_new(int count, Eina_Bool sync) _evas_map_new(int count, Eina_Bool sync)
{ {
int i;
int alloc;
Evas_Map *m; Evas_Map *m;
int alloc;
/* Adjust allocation such that: at least 4 points, and always an even /* Adjust allocation such that: at least 4 points, and always an even
* number: this allows the software engine to work efficiently */ * number: this allows the software engine to work efficiently */
alloc = (count < 4) ? 4 : count; alloc = (count < 4) ? 4 : count;
if (alloc & 0x1) alloc ++; 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; if (!m) return NULL;
m->move_sync.enabled = sync; m->move_sync.enabled = sync;
m->count = count; m->count = count;
@ -154,7 +153,7 @@ _evas_map_new(int count, Eina_Bool sync)
m->alpha = 1; m->alpha = 1;
m->smooth = 1; m->smooth = 1;
m->magic = MAGIC_MAP; 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].r = 255;
m->points[i].g = 255; m->points[i].g = 255;
@ -416,9 +415,9 @@ _evas_object_map_parent_check(Evas_Object *eo_parent)
} }
#endif #endif
static void void
_map_map_enable_set(Eo *eo_obj, Evas_Object_Protected_Data *obj, _evas_object_map_enable_set(Eo *eo_obj, Evas_Object_Protected_Data *obj,
Eina_Bool enabled, Eina_Bool default_move_sync) Eina_Bool enabled)
{ {
Eina_Bool pchange = EINA_FALSE; 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) if (!obj->map->cur.map)
{ {
EINA_COW_WRITE_BEGIN(evas_object_map_cow, obj->map, Evas_Object_Map_Data, map_write) 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); EINA_COW_WRITE_END(evas_object_map_cow, obj->map, map_write);
} }
evas_object_mapped_clip_across_mark(eo_obj, obj); 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 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); 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 EAPI Eina_Bool
_efl_canvas_object_efl_gfx_map_map_enable_get(Eo *eo_obj EINA_UNUSED, void *_pd EINA_UNUSED) 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; 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); _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 void
_map_util_3d_rotate(Evas_Map *m, double dx, double dy, double dz, _map_util_3d_rotate(Evas_Map *m, double dx, double dy, double dz,
double cx, double cy, double cz) 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); _map_util_3d_rotate(m, dx, dy, dz, (double) cx, (double) cy, (double) cz);
} }
EAPI void void
evas_map_util_quat_rotate(Evas_Map *m, double qx, double qy, double qz, _map_util_quat_rotate(Evas_Map *m, double qx, double qy, double qz,
double qw, double cx, double cy, double cz) double qw, double cx, double cy, double cz)
{ {
Eina_Quaternion q; Eina_Quaternion q;
Eina_Point_3D c; 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 void
_map_util_3d_lighting(Evas_Map *m, _map_util_3d_lighting(Evas_Map *m,
double lx, double ly, double lz, 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 _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_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_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_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_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_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 static inline void
_evas_map_util_points_populate(Evas_Map *m, const double x, const double y, _evas_map_util_points_populate(Evas_Map *m, const double x, const double y,
@ -85,5 +88,15 @@ error:
if (z) *z = 0; 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 #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_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", RD(0, " pre-render-done smart:%p|%p [%p, %i] | [%p, %i] has_map:%i had_map:%i\n",
obj->smart.smart, obj->smart.smart,
obj->is_smart ? evas_object_smart_members_get_direct(eo_obj) : NULL, 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 #endif
_evas_object_gfx_map_update(obj);
map = _evas_render_has_map(obj); map = _evas_render_has_map(obj);
hmap = _evas_render_had_map(obj); hmap = _evas_render_had_map(obj);
can_map = _evas_render_can_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; if (!obj->layer) goto clean_stuff;
_evas_object_gfx_map_update(obj);
EINA_PREFETCH(&(obj->cur->clipper)); EINA_PREFETCH(&(obj->cur->clipper));
EINA_PREFETCH(&(obj->cur->cache.clip)); EINA_PREFETCH(&(obj->cur->cache.clip));
//If the children are in active objects, They should be cleaned up. //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 */ /* Check if any one is the stack make this object mapped */
eo_tmp = eo_obj; eo_tmp = eo_obj;
tmp = efl_data_scope_get(eo_tmp, EFL_CANVAS_OBJECT_CLASS); 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))) while (tmp && !(_evas_render_has_map(tmp) && !_evas_render_can_map(tmp)))
{ {
eo_tmp = tmp->smart.parent; eo_tmp = tmp->smart.parent;
tmp = efl_data_scope_get(eo_tmp, EFL_CANVAS_OBJECT_CLASS); 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)) 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; proxy_src_clip = proxy_render_data->source_clip;
evas_object_clip_recalc(obj); evas_object_clip_recalc(obj);
_evas_object_gfx_map_update(obj);
/* leave early if clipper is not visible */ /* leave early if clipper is not visible */
if ((obj->cur->clipper) && (!obj->cur->clipper->cur->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); 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 static inline int
_evas_object_event_new(void) _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_needs_redraw : 1;
Eina_Bool snapshot_no_obscure : 1; Eina_Bool snapshot_no_obscure : 1;
Eina_Bool gfx_map_has : 1;
Eina_Bool gfx_map_update : 1;
struct { struct {
Eina_Bool pass_events : 1; 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_init(void);
void evas_filter_shutdown(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 */
Ector_Surface *evas_ector_get(Evas_Public_Data *evas, void *output); Ector_Surface *evas_ector_get(Evas_Public_Data *evas, void *output);