evas: Implement evas map support in eo as a mixin

It relies a bit on evas legacy APIs and will only work on
evas objects (Efl.Canvas.Object) for now.

The main difference with Evas_Map is that there is no
separate map object, as the functions apply directly to
any canvas object.

For convenience, most functions will automatically populate
the map if there was no previous map info. While this may
be convenient, the object's size changes still need to
be tracked to update the map info.
This commit is contained in:
Jean-Philippe Andre 2016-06-28 15:40:41 +09:00
parent a49bddd124
commit b13ae2fb82
3 changed files with 800 additions and 58 deletions

View File

@ -6590,4 +6590,21 @@ EAPI void evas_object_map_set(Evas_Object *obj, const Evas_Map *map);
*/
EAPI const Evas_Map *evas_object_map_get(const Evas_Object *obj);
/**
* @brief Enable or disable the map that is set.
*
* Enable or disable the use of map for the object @c obj. On enable, the
* object geometry will be saved, and the new geometry will change (position
* and size) to reflect the map geometry set.
*
* If the object doesn't have a map set (with @ref evas_object_map_set), the
* initial geometry will be undefined. It is advised to always set a map to the
* object first, and then call this function to enable its use.
*
* @param[in] enabled Enabled state.
*
* @ingroup Evas_Object
*/
EAPI void evas_object_map_enable_set(Evas_Object *obj, Eina_Bool enabled);
#include "canvas/efl_gfx_map.eo.legacy.h"

View File

@ -12,13 +12,28 @@ mixin Efl.Gfx.Map (Eo.Interface, Eo.Base)
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).
Usually, it will be necessary to update the map points (start afresh with
@.map_populate) whenever the object geometry changes.
Note: For now this mixin is only compatible with $Efl.Canvas.Object and
shouldn't be used anywhere else.
Note: There are a few differences with legacy $Evas_Map:
- A map is now a property of an object, rather than a separate entity.
- @.map_move_sync is enabled by default
- @.map_populate will be called automatically if another map function
is called while the object has no map info.
]]
data: null;
methods {
@property map_enable @virtual_pure {
[[Whether map transformation is enabled on this object.
The default map enable state is off ($false).
The default map enable state is off ($false). The other
properties and methods in this class have no effect until
this property is enabled.
]]
set {
[[Enable or disable the use of map for this object. On
@ -26,7 +41,6 @@ mixin Efl.Gfx.Map (Eo.Interface, Eo.Base)
geometry will change (position and size) to reflect the
map geometry set.
]]
legacy: evas_object_map_enable_set;
}
get {
legacy: evas_object_map_enable_get;
@ -35,7 +49,293 @@ mixin Efl.Gfx.Map (Eo.Interface, Eo.Base)
enabled: bool; [[Enabled state.]]
}
}
@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.
]]
get {}
values {
cw: bool; [[$true if CW, $false if CCW.]]
}
}
@property map_smooth {
[[Smoothing state for map rendering.
This sets smoothing for map rendering. If the object is a type that has
its own smoothing settings, then both the smooth settings for this object
and the map must be turned off. By default smooth maps are enabled.
]]
values {
smooth: bool; [[$true by default.]]
}
}
@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.
]]
values {
alpha: bool; [[$true by default.]]
}
}
@property map_point_coord {
[[Map point's coordinate.
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
or counter-clockwise. It is suggested to keep your quadrangles concave and
non-complex, though these polygon modes may work, they may not render
a desired set of output. The quadrangle will use points 0 and 1 , 1 and 2,
2 and 3, and 3 and 0 to describe the edges of the quadrangle.
The X and Y and Z coordinates are in canvas units. Z is optional and may
or may not be honored in drawing. Z is a hint and does not affect the
X and Y rendered coordinates. It may be used for calculating fills with
perspective correct rendering.
Remember all coordinates are canvas global ones like with move and resize
in the canvas.
]]
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).]]
}
}
@property map_point_image_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.
]]
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.]]
}
}
@property map_color {
[[Color of a vertex in the map.
This sets the color of the vertex in the map. Colors will be linearly
interpolated between vertex points through the map. Color will multiply
the "texture" pixels (like GL_MODULATE in OpenGL). The default color of
a vertex in a map is white solid (255, 255, 255, 255) which means it will
have no affect on modifying the texture pixels.
The color values must be premultiplied (ie. $a >= {$r, $g, $b}).
]]
keys {
idx: int; [[ID of the point, from 0 to 3 (included).
-1 can be used to set the color for all points,
but it is invalid for get().]]
}
values {
r: int; [[Red (0 - 255)]]
g: int; [[Green (0 - 255)]]
b: int; [[Blue (0 - 255)]]
a: int; [[Alpha (0 - 255)]]
}
}
@property map_move_sync {
[[Status of object move synchronization for map rendering.
If the flag is set as enabled, the map will be moved as the object
is moved.
]]
values {
enable: bool; [[$true by default.]]
}
}
@property map_point_z {
[[Value of Z coordinate of point $idx.
Useful to call @.map_populate without changing Z.
]]
get {}
keys {
idx: int;
}
values {
z: double;
}
}
map_populate {
[[Populate source and destination map points to match this object.
]]
params {
z: double @optional; [[Point Z coordinate (pre-perpective transform),
used for all 4 points. 0 by default.]]
}
return: bool; [[$false in case of error.]]
}
map_populate_manual {
[[Populate source and destination map points to match given geometry.
Similar to @.map_populate, this call takes raw values instead of
querying this object's unmapped geometry. The given size will be
used to calculate destination points (@.map_point_coord) and set the
image uv (@.map_point_image_uv).
]]
params {
x: double;
y: double;
w: double;
h: double;
z: double @optional; [[Point Z coordinate (pre-perpective transform),
used for all 4 points. 0 by default.]]
}
return: bool; [[$false in case of error.]]
}
map_rotate {
[[Change the map to apply the given rotation.
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.
]]
params {
degrees: double; [[CCW rotation in degrees.]]
cx: double; [[X coordinate of the rotation center.]]
cy: double; [[Y coordinate of the rotation center.]]
}
return: bool; [[$false in case of error.]]
}
map_zoom {
[[Change the map to apply the given zooming.
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;
zoomy: double;
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()
(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).
]]
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.]]
}
return: bool; [[$false in case of error.]]
}
map_quat_rotate {
[[Rotate the map 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).
]]
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.]]
}
return: bool; [[$false in case of error.]]
}
map_lightning_3d {
[[Perform lighting calculations on the given Map
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.
]]
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.]]
lr: int; [[light red value (0 - 255).]]
lg: int; [[light green value (0 - 255).]]
lb: int; [[light blue value (0 - 255).]]
ar: int; [[ambient color red value (0 - 255).]]
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 {
[[Apply a perspective transform to the map
This applies a given perspective (3D) to the map coordinates. X, Y and Z
values are used. The px and py points specify the "infinite distance" point
in the 3D conversion (where all lines converge to like when artists draw
3D by hand). The $z0 value specifies the z value at which there is a 1:1
mapping between spatial coordinates and screen coordinates. Any points
on this z value will not have their X and Y values modified in the transform.
Those further away (Z value higher) will shrink into the distance, and
those less than this value will expand and become bigger. The $foc value
determines the "focal length" of the camera. This is in reality the distance
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.
]]
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]]
}
return: bool; [[$false in case of error.]]
}
map_dup {
[[Duplicate the map information from another object.]]
params {
other: const(Efl.Gfx.Map);
}
return: bool; [[$false in case of error.]]
}
}
implements {
}
}
// Porting notes:
// Skipped APIs:
// evas_map_util_object_move_sync_{set,get}

View File

@ -145,7 +145,7 @@ evas_object_map_move_sync(Evas_Object *eo_obj)
}
static inline Evas_Map *
_evas_map_new(int count)
_evas_map_new(int count, Eina_Bool sync)
{
int i;
int alloc;
@ -158,6 +158,7 @@ _evas_map_new(int count)
m = calloc(1, sizeof(Evas_Map) + (alloc * sizeof(Evas_Map_Point)));
if (!m) return NULL;
m->move_sync.enabled = sync;
m->count = count;
m->persp.foc = 0;
m->alpha = 1;
@ -194,7 +195,7 @@ _evas_map_copy(Evas_Map *dst, const Evas_Map *src)
static inline Evas_Map *
_evas_map_dup(const Evas_Map *orig)
{
Evas_Map *copy = _evas_map_new(orig->count);
Evas_Map *copy = _evas_map_new(orig->count, EINA_FALSE);
if (!copy) return NULL;
memcpy(copy->points, orig->points, orig->count * sizeof(Evas_Map_Point));
copy->smooth = orig->smooth;
@ -229,7 +230,7 @@ _evas_map_free(Evas_Object *eo_obj, Evas_Map *m)
/* util functions for manipulating maps, so you don't need to know the math */
/****************************************************************************/
static inline void
_evas_map_util_points_populate(Evas_Map *m, const Evas_Coord x, const Evas_Coord y, const Evas_Coord w, const Evas_Coord h, const Evas_Coord z)
_evas_map_util_points_populate(Evas_Map *m, const double x, const double y, const double w, const double h, const double z)
{
Evas_Map_Point *p = m->points;
int i;
@ -463,10 +464,10 @@ _evas_object_map_parent_check(Evas_Object *eo_parent)
return EINA_TRUE;
}
EOLIAN void
_efl_canvas_object_efl_gfx_map_map_enable_set(Eo *eo_obj, void *_pd EINA_UNUSED, Eina_Bool enabled)
static void
_map_map_enable_set(Eo *eo_obj, Evas_Object_Protected_Data *obj,
Eina_Bool enabled, Eina_Bool default_move_sync)
{
Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
Eina_Bool pchange = EINA_FALSE;
enabled = !!enabled;
@ -483,7 +484,7 @@ _efl_canvas_object_efl_gfx_map_map_enable_set(Eo *eo_obj, void *_pd EINA_UNUSED,
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);
map_write->cur.map = _evas_map_new(4, default_move_sync);
EINA_COW_WRITE_END(evas_object_map_cow, obj->map, map_write);
}
evas_object_mapped_clip_across_mark(eo_obj, obj);
@ -533,6 +534,22 @@ _efl_canvas_object_efl_gfx_map_map_enable_set(Eo *eo_obj, void *_pd EINA_UNUSED,
}
}
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 = eo_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_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj);
_map_map_enable_set(eo_obj, obj, enabled, EINA_FALSE);
}
EOLIAN Eina_Bool
_efl_canvas_object_efl_gfx_map_map_enable_get(Eo *eo_obj EINA_UNUSED, void *_pd EINA_UNUSED)
{
@ -652,7 +669,7 @@ evas_map_new(int count)
return NULL;
}
return _evas_map_new(count);
return _evas_map_new(count, EINA_FALSE);
}
EAPI void
@ -750,8 +767,23 @@ evas_map_count_get(const Evas_Map *m)
return m->count;
}
static inline void
_map_point_coord_set(Evas_Map *m, int idx, double x, double y, double z)
{
Evas_Map_Point *p;
EINA_SAFETY_ON_FALSE_RETURN((idx >= 0) && (idx < m->count));
p = m->points + idx;
p->x = p->px = x;
p->y = p->py = y;
p->z = z;
}
/* FIXME: coordinates should be float/double for accuracy.
Rotation center position will be flickered by rounding problem. */
Rotation center position will be flickered by rounding problem.
Now fixed in EO APIs.
*/
EAPI void
evas_map_point_coord_set(Evas_Map *m, int idx, Evas_Coord x, Evas_Coord y, Evas_Coord z)
{
@ -759,35 +791,37 @@ evas_map_point_coord_set(Evas_Map *m, int idx, Evas_Coord x, Evas_Coord y, Evas_
return;
MAGIC_CHECK_END();
Evas_Map_Point *p;
_map_point_coord_set(m, idx, x, y, z);
}
static inline void
_map_point_coord_get(const Evas_Map *m, int idx, double *x, double *y, double *z)
{
const Evas_Map_Point *p;
EINA_SAFETY_ON_FALSE_GOTO(m && (idx >= 0) && (idx < m->count), error);
if (idx >= m->count) return;
p = m->points + idx;
p->x = p->px = x;
p->y = p->py = y;
p->z = z;
if (x) *x = p->x;
if (y) *y = p->y;
if (z) *z = p->z;
return;
error:
if (x) *x = 0;
if (y) *y = 0;
if (z) *z = 0;
}
EAPI void
evas_map_point_coord_get(const Evas_Map *m, int idx, Evas_Coord *x, Evas_Coord *y, Evas_Coord *z)
{
MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
goto error;
MAGIC_CHECK_END();
double dx, dy, dz;
const Evas_Map_Point *p;
if (idx >= m->count) goto error;
p = m->points + idx;
if (x) *x = lround(p->x);
if (y) *y = lround(p->y);
if (z) *z = lround(p->z);
return;
error:
if (x) *x = 0;
if (y) *y = 0;
if (z) *z = 0;
_map_point_coord_get(m, idx, &dx, &dy, &dz);
if (x) *x = lround(dx);
if (y) *y = lround(dy);
if (z) *z = lround(dz);
}
EAPI void
@ -799,7 +833,7 @@ evas_map_point_image_uv_set(Evas_Map *m, int idx, double u, double v)
Evas_Map_Point *p;
if (idx >= m->count) return;
if ((idx < 0) || (idx >= m->count)) return;
p = m->points + idx;
p->u = u;
p->v = v;
@ -814,7 +848,7 @@ evas_map_point_image_uv_get(const Evas_Map *m, int idx, double *u, double *v)
const Evas_Map_Point *p;
if (idx >= m->count) goto error;
if ((idx < 0) || (idx >= m->count)) goto error;
p = m->points + idx;
if (u) *u = p->u;
if (v) *v = p->v;
@ -834,7 +868,7 @@ evas_map_point_color_set(Evas_Map *m, int idx, int r, int g, int b, int a)
Evas_Map_Point *p;
if (idx >= m->count) return;
if ((idx < 0) || (idx >= m->count)) return;
p = m->points + idx;
p->r = r;
p->g = g;
@ -851,12 +885,18 @@ evas_map_point_color_get(const Evas_Map *m, int idx, int *r, int *g, int *b, int
const Evas_Map_Point *p;
if (idx >= m->count) return;
if ((idx < 0) || (idx >= m->count)) goto error;
p = m->points + idx;
if (r) *r = p->r;
if (g) *g = p->g;
if (b) *b = p->b;
if (a) *a = p->a;
error:
if (r) *r = 255;
if (g) *g = 255;
if (b) *b = 255;
if (a) *a = 255;
}
EAPI void
@ -938,13 +978,9 @@ evas_map_util_points_color_set(Evas_Map *m, int r, int g, int b, int a)
}
}
EAPI void
evas_map_util_rotate(Evas_Map *m, double degrees, Evas_Coord cx, Evas_Coord cy)
static void
_map_util_rotate(Evas_Map *m, double degrees, double cx, double cy)
{
MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
return;
MAGIC_CHECK_END();
double r = (degrees * M_PI) / 180.0;
Evas_Map_Point *p, *p_end;
@ -969,12 +1005,18 @@ evas_map_util_rotate(Evas_Map *m, double degrees, Evas_Coord cx, Evas_Coord cy)
}
EAPI void
evas_map_util_zoom(Evas_Map *m, double zoomx, double zoomy, Evas_Coord cx, Evas_Coord cy)
evas_map_util_rotate(Evas_Map *m, double degrees, Evas_Coord cx, Evas_Coord cy)
{
MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
return;
MAGIC_CHECK_END();
_map_util_rotate(m, degrees, (double) cx, (double) cy);
}
static void
_map_util_zoom(Evas_Map *m, double zoomx, double zoomy, double cx, double cy)
{
Evas_Map_Point *p, *p_end;
p = m->points;
@ -987,8 +1029,8 @@ evas_map_util_zoom(Evas_Map *m, double zoomx, double zoomy, Evas_Coord cx, Evas_
x = p->x - cx;
y = p->y - cy;
x = (((double)x) * zoomx);
y = (((double)y) * zoomy);
x *= zoomx;
y *= zoomy;
p->px = p->x = x + cx;
p->py = p->y = y + cy;
@ -996,13 +1038,19 @@ evas_map_util_zoom(Evas_Map *m, double zoomx, double zoomy, Evas_Coord cx, Evas_
}
EAPI void
evas_map_util_3d_rotate(Evas_Map *m, double dx, double dy, double dz,
Evas_Coord cx, Evas_Coord cy, Evas_Coord cz)
evas_map_util_zoom(Evas_Map *m, double zoomx, double zoomy, Evas_Coord cx, Evas_Coord cy)
{
MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
return;
MAGIC_CHECK_END();
_map_util_zoom(m, zoomx, zoomy, (double) cx, (double) cy);
}
static void
_map_util_3d_rotate(Evas_Map *m, double dx, double dy, double dz,
double cx, double cy, double cz)
{
double rz = (dz * M_PI) / 180.0;
double rx = (dx * M_PI) / 180.0;
double ry = (dy * M_PI) / 180.0;
@ -1049,6 +1097,17 @@ evas_map_util_3d_rotate(Evas_Map *m, double dx, double dy, double dz,
}
}
EAPI void
evas_map_util_3d_rotate(Evas_Map *m, double dx, double dy, double dz,
Evas_Coord cx, Evas_Coord cy, Evas_Coord cz)
{
MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
return;
MAGIC_CHECK_END();
_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)
@ -1090,15 +1149,11 @@ evas_map_util_quat_rotate(Evas_Map *m, double qx, double qy, double qz,
}
}
EAPI void
evas_map_util_3d_lighting(Evas_Map *m,
Evas_Coord lx, Evas_Coord ly, Evas_Coord lz,
int lr, int lg, int lb, int ar, int ag, int ab)
static 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)
{
MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
return;
MAGIC_CHECK_END();
int i;
for (i = 0; i < m->count; i++)
@ -1170,14 +1225,21 @@ evas_map_util_3d_lighting(Evas_Map *m,
}
EAPI void
evas_map_util_3d_perspective(Evas_Map *m,
Evas_Coord px, Evas_Coord py,
Evas_Coord z0, Evas_Coord foc)
evas_map_util_3d_lighting(Evas_Map *m,
Evas_Coord lx, Evas_Coord ly, Evas_Coord lz,
int lr, int lg, int lb, int ar, int ag, int ab)
{
MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
return;
MAGIC_CHECK_END();
_map_util_3d_lighting(m, (double) lx, (double) ly, (double)
lz, lr, lg, lb, ar, ag, ab);
}
static void
_map_util_3d_perspective(Evas_Map *m, double px, double py, double z0, double foc)
{
Evas_Map_Point *p, *p_end;
p = m->points;
@ -1210,6 +1272,18 @@ evas_map_util_3d_perspective(Evas_Map *m,
}
}
EAPI void
evas_map_util_3d_perspective(Evas_Map *m,
Evas_Coord px, Evas_Coord py,
Evas_Coord z0, Evas_Coord foc)
{
MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
return;
MAGIC_CHECK_END();
_map_util_3d_perspective(m, (double) px, (double) py, (double) z0, (double) foc);
}
EAPI Eina_Bool
evas_map_util_clockwise_get(Evas_Map *m)
{
@ -1365,4 +1439,355 @@ evas_map_object_move_diff_set(Evas_Map *m,
m->move_sync.diff_y += diff_y;
}
/* Efl.Gfx.Map implementation - relies on legacy for now */
// note: cur vs. prev is not handled
#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)
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_Map *m;
if (!obj->map->cur.map)
{
if (smooth) return;
if (!efl_gfx_map_populate(eo_obj, 0))
return;
}
m = (Evas_Map *) obj->map->cur.map;
m->smooth = smooth;
MAP_OBJ_CHANGE();
}
EOLIAN static Eina_Bool
_efl_gfx_map_map_smooth_get(Eo *eo_obj, void *_pd EINA_UNUSED)
{
const Evas_Map *om = evas_object_map_get(eo_obj);
return om ? om->smooth : EINA_TRUE;
}
EOLIAN static void
_efl_gfx_map_map_alpha_set(Eo *eo_obj, void *_pd EINA_UNUSED, Eina_Bool alpha)
{
Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj);
Evas_Map *m;
if (!obj->map->cur.map)
{
if (alpha) return;
if (!efl_gfx_map_populate(eo_obj, 0))
return;
}
m = (Evas_Map *) obj->map->cur.map;
m->alpha = alpha;
MAP_OBJ_CHANGE();
}
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;
}
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)
{
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 && !efl_gfx_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
_efl_gfx_map_map_point_coord_get(Eo *eo_obj, void *_pd EINA_UNUSED, int idx, double *x, double *y, double *z)
{
const Evas_Map *om = evas_object_map_get(eo_obj);
_map_point_coord_get(om, idx, x, y, z);
}
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 && !efl_gfx_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 && !efl_gfx_map_populate(eo_obj, 0))
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();
}
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)
{
const Evas_Map *om = evas_object_map_get(eo_obj);
evas_map_point_color_get(om, idx, r, g, b, a);
}
EOLIAN static void
_efl_gfx_map_map_move_sync_set(Eo *eo_obj, void *_pd EINA_UNUSED, Eina_Bool enable)
{
Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj);
Evas_Map *m;
if (!obj->map->cur.map)
{
if (enable) return;
if (!efl_gfx_map_populate(eo_obj, 0))
return;
}
m = (Evas_Map *) obj->map->cur.map;
m->move_sync.enabled = enable;
MAP_OBJ_CHANGE();
}
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_populate(Eo *eo_obj, void *_pd EINA_UNUSED, double z)
{
Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj, EINA_FALSE);
Evas_Map *m;
if (!obj->map->cur.map)
{
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);
}
else
{
m = (Evas_Map *) obj->map->cur.map;
MAP_POPULATE_DEFAULT(m, z);
MAP_OBJ_CHANGE();
}
return EINA_TRUE;
}
EOLIAN static Eina_Bool
_efl_gfx_map_map_populate_manual(Eo *eo_obj, void *_pd EINA_UNUSED, double x, double y, double w, double h, double z)
{
Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj, EINA_FALSE);
Evas_Map *m;
if (!obj->map->cur.map)
{
m = _evas_map_new(4, EINA_TRUE);
if (!m) return EINA_FALSE;
_evas_map_util_points_populate(m, x, y, w, h, z);
evas_object_map_set(eo_obj, m);
evas_map_free(m);
}
else
{
m = (Evas_Map *) obj->map->cur.map;
_evas_map_util_points_populate(m, x, y, w, h, z);
MAP_OBJ_CHANGE();
}
return 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 (!efl_gfx_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 (!efl_gfx_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 (!efl_gfx_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 (!efl_gfx_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 (!efl_gfx_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 (!efl_gfx_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 double
_efl_gfx_map_map_point_z_get(Eo *eo_obj, void *_pd EINA_UNUSED, int idx)
{
Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj, 0.0);
EINA_SAFETY_ON_FALSE_RETURN_VAL((idx >= 0) && (idx < 4), 0.0);
const Evas_Map *m = obj->map->cur.map;
const Evas_Map_Point *p = m ? (m->points + idx) : NULL;
return p ? p->z : 0.0;
}
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"