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"