From b13ae2fb8299807f057e79b514933cb6a33e770c Mon Sep 17 00:00:00 2001 From: Jean-Philippe Andre Date: Tue, 28 Jun 2016 15:40:41 +0900 Subject: [PATCH] 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. --- src/lib/evas/Evas_Legacy.h | 17 + src/lib/evas/canvas/efl_gfx_map.eo | 304 +++++++++++++++- src/lib/evas/canvas/evas_map.c | 537 ++++++++++++++++++++++++++--- 3 files changed, 800 insertions(+), 58 deletions(-) diff --git a/src/lib/evas/Evas_Legacy.h b/src/lib/evas/Evas_Legacy.h index c3f5267d5e..7dc867bb1f 100644 --- a/src/lib/evas/Evas_Legacy.h +++ b/src/lib/evas/Evas_Legacy.h @@ -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" diff --git a/src/lib/evas/canvas/efl_gfx_map.eo b/src/lib/evas/canvas/efl_gfx_map.eo index ea9e3635f7..22703617b3 100644 --- a/src/lib/evas/canvas/efl_gfx_map.eo +++ b/src/lib/evas/canvas/efl_gfx_map.eo @@ -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} diff --git a/src/lib/evas/canvas/evas_map.c b/src/lib/evas/canvas/evas_map.c index 4f07bfbb5d..72d41694d1 100644 --- a/src/lib/evas/canvas/evas_map.c +++ b/src/lib/evas/canvas/evas_map.c @@ -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"