1 #include "evas_common.h"
2 #include "evas_private.h"
6 _evas_map_calc_geom_change(Evas_Object *obj)
8 int is, was = 0, pass = 0;
10 evas_object_change(obj);
11 evas_object_clip_dirty(obj);
12 if (obj->layer->evas->events_frozen <= 0)
14 evas_object_recalc_clippees(obj);
17 if (!obj->smart.smart)
19 is = evas_object_is_in_output_rect(obj,
20 obj->layer->evas->pointer.x,
21 obj->layer->evas->pointer.y, 1, 1);
22 if ((is ^ was) && obj->cur.visible)
23 evas_event_feed_mouse_move(obj->layer->evas,
24 obj->layer->evas->pointer.x,
25 obj->layer->evas->pointer.y,
26 obj->layer->evas->last_timestamp,
31 evas_object_inform_call_move(obj);
32 evas_object_inform_call_resize(obj);
36 _evas_map_calc_map_geometry(Evas_Object *obj)
38 Evas_Coord x1, x2, y1, y2;
39 const Evas_Map_Point *p, *p_end;
42 if (!obj->cur.map) return;
43 p = obj->cur.map->points;
44 p_end = p + obj->cur.map->count;
50 for (; p < p_end; p++)
52 if (p->x < x1) x1 = p->x;
53 if (p->x > x2) x2 = p->x;
54 if (p->y < y1) y1 = p->y;
55 if (p->y > y2) y2 = p->y;
58 if (obj->cur.map->normal_geometry.x != x1) ch = 1;
59 if (obj->cur.map->normal_geometry.y != y1) ch = 1;
60 if (obj->cur.map->normal_geometry.w != (x2 - x1)) ch = 1;
61 if (obj->cur.map->normal_geometry.h != (y2 - y1)) ch = 1;
62 obj->cur.map->normal_geometry.x = x1;
63 obj->cur.map->normal_geometry.y = y1;
64 obj->cur.map->normal_geometry.w = (x2 - x1);
65 obj->cur.map->normal_geometry.h = (y2 - y1);
66 if (ch) _evas_map_calc_geom_change(obj);
69 static inline Evas_Map *
70 _evas_map_new(int count)
76 /* Adjust allocation such that: at least 4 points, and always an even
77 * number: this allows the software engine to work efficiently */
78 alloc = (count < 4) ? 4 : count;
79 if (alloc & 0x1) alloc ++;
81 m = calloc(1, sizeof(Evas_Map) + (alloc * sizeof(Evas_Map_Point)));
87 for (i = 0; i < count; i++)
97 static inline Eina_Bool
98 _evas_map_copy(Evas_Map *dst, const Evas_Map *src)
100 if (dst->count != src->count)
102 ERR("cannot copy map of different sizes: dst=%i, src=%i", dst->count, src->count);
105 memcpy(dst->points, src->points, src->count * sizeof(Evas_Map_Point));
106 dst->smooth = src->smooth;
107 dst->alpha = src->alpha;
108 dst->persp = src->persp;
112 static inline Evas_Map *
113 _evas_map_dup(const Evas_Map *orig)
115 Evas_Map *copy = _evas_map_new(orig->count);
116 if (!copy) return NULL;
117 memcpy(copy->points, orig->points, orig->count * sizeof(Evas_Map_Point));
118 copy->smooth = orig->smooth;
119 copy->alpha = orig->alpha;
120 copy->persp = orig->persp;
125 _evas_map_free(Evas_Object *obj, Evas_Map *m)
130 obj->layer->evas->engine.func->image_map_surface_free
131 (obj->layer->evas->engine.data.output, m->surface);
137 evas_map_coords_get(const Evas_Map *m, Evas_Coord x, Evas_Coord y,
138 Evas_Coord *mx, Evas_Coord *my, int grab)
140 int i, j, edges, edge[m->count][2], douv;
142 double u[2] = { 0.0, 0.0 };
143 double v[2] = { 0.0, 0.0 };
145 if (m->count < 4) return 0;
146 // FIXME need to handle grab mode and extrapolte coords outside
150 Evas_Coord ymin, ymax;
152 ymin = m->points[0].y;
153 ymax = m->points[0].y;
154 for (i = 1; i < m->count; i++)
156 if (m->points[i].y < ymin) ymin = m->points[i].y;
157 else if (m->points[i].y > ymax) ymax = m->points[i].y;
159 if (y <= ymin) y = ymin + 1;
160 if (y >= ymax) y = ymax - 1;
163 for (i = 0; i < m->count; i++)
165 j = (i + 1) % m->count;
166 if ((m->points[i].y <= y) && (m->points[j].y > y))
172 else if ((m->points[j].y <= y) && (m->points[i].y > y))
180 if ((mx) || (my)) douv = 1;
181 for (i = 0; i < (edges - 1); i+= 2)
186 yd = m->points[edge[i][1]].y - m->points[edge[i][0]].y;
189 yp = y - m->points[edge[i][0]].y;
190 xe[0] = m->points[edge[i][1]].x - m->points[edge[i][0]].x;
191 xe[0] = m->points[edge[i][0]].x + ((xe[0] * yp) / yd);
194 u[0] = m->points[edge[i][1]].u - m->points[edge[i][0]].u;
195 u[0] = m->points[edge[i][0]].u + ((u[0] * yp) / yd);
196 v[0] = m->points[edge[i][1]].v - m->points[edge[i][0]].v;
197 v[0] = m->points[edge[i][0]].v + ((v[0] * yp) / yd);
202 xe[0] = m->points[edge[i][0]].x;
205 u[0] = m->points[edge[i][0]].u;
206 v[0] = m->points[edge[i][0]].v;
209 yd = m->points[edge[j][1]].y - m->points[edge[j][0]].y;
212 yp = y - m->points[edge[j][0]].y;
213 xe[1] = m->points[edge[j][1]].x - m->points[edge[j][0]].x;
214 xe[1] = m->points[edge[j][0]].x + ((xe[1] * yp) / yd);
217 u[1] = m->points[edge[j][1]].u - m->points[edge[j][0]].u;
218 u[1] = m->points[edge[j][0]].u + ((u[1] * yp) / yd);
219 v[1] = m->points[edge[j][1]].v - m->points[edge[j][0]].v;
220 v[1] = m->points[edge[j][0]].v + ((v[1] * yp) / yd);
225 xe[1] = m->points[edge[j][0]].x;
228 u[1] = m->points[edge[j][0]].u;
229 v[1] = m->points[edge[j][0]].v;
236 ti = xe[0]; xe[0] = xe[1]; xe[1] = ti;
241 td = u[0]; u[0] = u[1]; u[1] = td;
242 td = v[0]; v[0] = v[1]; v[1] = td;
245 if ((x >= xe[0]) && (x < xe[1]))
250 *mx = u[0] + (((x - xe[0]) * (u[1] - u[0])) /
253 *my = v[0] + (((x - xe[0]) * (v[1] - v[0])) /
263 *mx = u[0] + (((x - xe[0]) * (u[1] - u[0])) /
266 *my = v[0] + (((x - xe[0]) * (v[1] - v[0])) /
276 evas_map_inside_get(const Evas_Map *m, Evas_Coord x, Evas_Coord y)
278 return evas_map_coords_get(m, x, y, NULL, NULL, 0);
283 * Enable or disable the map that is set.
285 * This enables the map that is set or disables it. On enable, the object
286 * geometry will be saved, and the new geometry will change (position and
287 * size) to reflect the map geometry set. If none is set yet, this may be
288 * an undefined geometry, unless you have already set the map with
289 * evas_object_map_set(). It is suggested you first set a map with
290 * evas_object_map_set() with valid useful coordinates then enable and
291 * disable the map with evas_object_map_enable_set() as needed.
293 * @param obj object to enable the map on
294 * @param enabled enabled state
297 evas_object_map_enable_set(Evas_Object *obj, Eina_Bool enabled)
299 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
303 if (obj->cur.usemap == enabled) return;
304 obj->cur.usemap = enabled;
308 obj->cur.map = _evas_map_new(4);
309 evas_object_mapped_clip_across_mark(obj);
310 // obj->cur.map->normal_geometry = obj->cur.geometry;
316 _evas_map_calc_geom_change(obj);
317 evas_object_mapped_clip_across_mark(obj);
320 _evas_map_calc_map_geometry(obj);
321 /* This is a bit heavy handed, but it fixes the case of same geometry, but
322 * changed colour or UV settings. */
323 evas_object_change(obj);
327 * Get the map enabled state
329 * This returns the currently enabled state of the map on the object indicated.
330 * The default map enable state is off. You can enable and disable it with
331 * evas_object_map_enable_set().
333 * @param obj object to get the map enabled state from
334 * @return the map enabled state
337 evas_object_map_enable_get(const Evas_Object *obj)
339 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
342 return obj->cur.usemap;
347 * Set the map source object
349 * This sets the object from which the map is taken - can be any object that
350 * has map enabled on it.
352 * Currently not implemented. for future use.
354 * @param obj object to set the map source of
355 * @param src the source object from which the map is taken
358 evas_object_map_source_set(Evas_Object *obj, Evas_Object *src)
360 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
363 (void)src; /* method still needs to be implemented. */
367 * Get the map source object
369 * See evas_object_map_source_set()
371 * @param obj object to set the map source of
372 * @return the object set as the source
375 evas_object_map_source_get(const Evas_Object *obj)
377 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
384 * Set current object transformation map.
386 * This sets the map on a given object. It is copied from the @p map pointer,
387 * so there is no need to keep the @p map object if you don't need it anymore.
389 * A map is a set of 4 points which have canvas x, y coordinates per point,
390 * with an optional z point value as a hint for perspective correction, if it
391 * is available. As well each point has u and v coordinates. These are like
392 * "texture coordinates" in OpenGL in that they define a point in the source
393 * image that is mapped to that map vertex/point. The u corresponds to the x
394 * coordinate of this mapped point and v, the y coordinate. Note that these
395 * coordinates describe a bounding region to sample. If you have a 200x100
396 * source image and want to display it at 200x100 with proper pixel
397 * precision, then do:
400 * Evas_Map *m = evas_map_new(4);
401 * evas_map_point_coord_set(m, 0, 0, 0, 0);
402 * evas_map_point_coord_set(m, 1, 200, 0, 0);
403 * evas_map_point_coord_set(m, 2, 200, 100, 0);
404 * evas_map_point_coord_set(m, 3, 0, 100, 0);
405 * evas_map_point_image_uv_set(m, 0, 0, 0);
406 * evas_map_point_image_uv_set(m, 1, 200, 0);
407 * evas_map_point_image_uv_set(m, 2, 200, 100);
408 * evas_map_point_image_uv_set(m, 3, 0, 100);
409 * evas_object_map_set(obj, m);
413 * Note that the map points a uv coordinates match the image geometry. If
414 * the @p map parameter is NULL, the stored map will be freed and geometry
415 * prior to enabling/setting a map will be restored.
417 * @param obj object to change transformation map
418 * @param map new map to use
420 * @see evas_map_new()
423 evas_object_map_set(Evas_Object *obj, const Evas_Map *map)
425 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
432 if (obj->cur.map->surface)
434 obj->layer->evas->engine.func->image_map_surface_free
435 (obj->layer->evas->engine.data.output,
436 obj->cur.map->surface);
437 obj->cur.map->surface = NULL;
439 obj->prev.geometry = obj->cur.map->normal_geometry;
442 _evas_map_free(obj, obj->cur.map);
444 evas_object_mapped_clip_across_mark(obj);
447 _evas_map_free(obj, obj->cur.map);
449 if (!obj->cur.usemap) _evas_map_calc_geom_change(obj);
450 else _evas_map_calc_map_geometry(obj);
452 evas_object_mapped_clip_across_mark(obj);
457 if (obj->cur.map && obj->cur.map->count == map->count)
459 Evas_Map *omap = obj->cur.map;
460 obj->cur.map = _evas_map_new(map->count);
461 memcpy(obj->cur.map, omap, sizeof(Evas_Map) + (map->count * sizeof(Evas_Map_Point)));
462 _evas_map_copy(obj->cur.map, map);
467 if (obj->cur.map) evas_map_free(obj->cur.map);
468 obj->cur.map = _evas_map_dup(map);
470 evas_object_mapped_clip_across_mark(obj);
472 _evas_map_calc_map_geometry(obj);
476 * Get current object transformation map.
478 * This returns the current internal map set on the indicated object. It is
479 * intended for read-only acces and is only valid as long as the object is
480 * not deleted or the map on the object is not changed. If you wish to modify
481 * the map and set it back do the following:
484 * const Evas_Map *m = evas_object_map_get(obj);
485 * Evas_Map *m2 = evas_map_dup(m);
486 * evas_map_util_rotate(m2, 30.0, 0, 0);
487 * evas_object_map_set(obj);
491 * @param obj object to query transformation map.
492 * @return map reference to map in use. This is an internal data structure, so
495 * @see evas_object_map_set()
497 EAPI const Evas_Map *
498 evas_object_map_get(const Evas_Object *obj)
500 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
503 if (obj->cur.map) return obj->cur.map;
508 * Create map of transformation points to be later used with an evas object.
510 * This creates a set of points (currently only 4 is supported. no other
511 * number for @p count will work). That is empty and ready to be modified
512 * with evas_map calls.
514 * @param count number of points in the map. *
515 * @return a newly allocated map or NULL on errors.
517 * @see evas_map_free()
518 * @see evas_map_dup()
519 * @see evas_map_point_coord_set()
520 * @see evas_map_point_image_uv_set()
521 * @see evas_map_util_points_populate_from_object_full()
522 * @see evas_map_util_points_populate_from_object()
524 * @see evas_object_map_set()
527 evas_map_new(int count)
531 ERR("num (%i) < 4 is unsupported!", count);
534 return _evas_map_new(count);
538 * Set the smoothing for map rendering
540 * This sets smoothing for map rendering. If the object is a type that has
541 * its own smoothing settings, then both the smooth settings for this object
542 * and the map must be turned off. By default smooth maps are enabled.
544 * @param m map to modify. Must not be NULL.
545 * @param enabled enable or disable smooth map rendering
548 evas_map_smooth_set(Evas_Map *m, Eina_Bool enabled)
555 * get the smoothing for map rendering
557 * This gets smoothing for map rendering.
559 * @param m map to get the smooth from. Must not be NULL.
562 evas_map_smooth_get(const Evas_Map *m)
569 * Set the alpha flag for map rendering
571 * This sets alpha flag for map rendering. If the object is a type that has
572 * its own alpha settings, then this will take precedence. Only image objects
573 * have this currently. Fits stops alpha blending of the map area, and is
574 * useful if you know the object and/or all sub-objects is 100% solid.
576 * @param m map to modify. Must not be NULL.
577 * @param enabled enable or disable alpha map rendering
580 evas_map_alpha_set(Evas_Map *m, Eina_Bool enabled)
587 * get the alpha flag for map rendering
589 * This gets the alph flag for map rendering.
591 * @param m map to get the alpha from. Must not be NULL.
594 evas_map_alpha_get(const Evas_Map *m)
601 * Copy a previously allocated map.
603 * This makes a duplicate of the @p m object and returns it.
605 * @param m map to copy. Must not be NULL.
606 * @return newly allocated map with the same count and contents as @p m.
609 evas_map_dup(const Evas_Map *m)
612 return _evas_map_dup(m);
616 * Free a previously allocated map.
618 * This frees a givem map @p m and all memory associated with it. You must NOT
619 * free a map returned by evas_object_map_get() as this is internal.
621 * @param m map to free.
624 evas_map_free(Evas_Map *m)
627 _evas_map_free(NULL, m);
633 * Returns the number of points in a map. Should be at least 4.
635 * @param m map to get size.
636 * @return -1 on error, points otherwise.
639 evas_map_count_get(const Evas_Map *m)
646 * Change the map point's coordinate.
648 * This sets the fixen point's coordinate in the map. Note that points
649 * describe the outline of a quadrangle and are ordered either clockwise
650 * or anit-clock-wise. It is suggested to keep your quadrangles concave and
651 * non-complex, though these polygon modes may work, they may not render
652 * a desired set of output. The quadrangle will use points 0 and 1 , 1 and 2,
653 * 2 and 3, and 3 and 0 to describe the edges of the quandrangle.
655 * The X and Y and Z coordinates are in canvas units. Z is optional and may
656 * or may not be honored in drawing. Z is a hint and does not affect the
657 * X and Y rendered coordinates. It may be used for calculating fills with
658 * perspective correct rendering.
660 * Remember all coordinates are canvas global ones like with move and reize
663 * @param m map to change point. Must not be @c NULL.
664 * @param idx index of point to change. Must be smaller than map size.
665 * @param x Point X Coordinate
666 * @param y Point Y Coordinate
667 * @param z Point Z Coordinate hint (pre-perspective transform)
669 * @see evas_map_util_rotate()
670 * @see evas_map_util_zoom()
671 * @see evas_map_util_points_populate_from_object_full()
672 * @see evas_map_util_points_populate_from_object()
675 evas_map_point_coord_set(Evas_Map *m, int idx, Evas_Coord x, Evas_Coord y, Evas_Coord z)
679 if (idx >= m->count) return;
687 * Get the map point's coordinate.
689 * This returns the coordinates of the given point in the map.
691 * @param m map to query point.
692 * @param idx index of point to query. Must be smaller than map size.
693 * @param x where to return the X coordinate.
694 * @param y where to return the Y coordinate.
695 * @param z where to return the Z coordinate.
698 evas_map_point_coord_get(const Evas_Map *m, int idx, Evas_Coord *x, Evas_Coord *y, Evas_Coord *z)
700 const Evas_Map_Point *p;
703 if (idx >= m->count) goto error;
717 * Change the map point's U and V texture source point
719 * This sets the U and V coordinates for the point. This determines which
720 * coordinate in the source image is mapped to the given point, much like
721 * OpenGL and textures. Notes that these points do select the pixel, but
722 * are double floating point values to allow for accuracy and sub-pixel
725 * @param m map to change the point of.
726 * @param idx index of point to change. Must be smaller than map size.
727 * @param u the X coordinate within the image/texture source
728 * @param v the Y coordinate within the image/texture source
730 * @see evas_map_point_coord_set()
731 * @see evas_object_map_set()
732 * @see evas_map_util_points_populate_from_object_full()
733 * @see evas_map_util_points_populate_from_object()
736 evas_map_point_image_uv_set(Evas_Map *m, int idx, double u, double v)
740 if (idx >= m->count) return;
747 * Get the map point's U and V texture source points
749 * This returns the texture points set by evas_map_point_image_uv_set().
751 * @param m map to query point.
752 * @param idx index of point to query. Must be smaller than map size.
753 * @param u where to write the X coordinate within the image/texture source
754 * @param v where to write the Y coordinate within the image/texture source
757 evas_map_point_image_uv_get(const Evas_Map *m, int idx, double *u, double *v)
759 const Evas_Map_Point *p;
761 if (idx >= m->count) goto error;
773 * Set the color of a vertex in the map
775 * This sets the color of the vertex in the map. Colors will be linearly
776 * interpolated between vertex points through the map. Color will multiply
777 * the "texture" pixels (like GL_MODULATE in OpenGL). The default color of
778 * a vertex in a map is white solid (255, 255, 255, 255) which means it will
779 * have no affect on modifying the texture pixels.
781 * @param m map to change the color of.
782 * @param idx index of point to change. Must be smaller than map size.
783 * @param r red (0 - 255)
784 * @param g green (0 - 255)
785 * @param b blue (0 - 255)
786 * @param a alpha (0 - 255)
788 * @see evas_map_util_points_color_set()
789 * @see evas_map_point_coord_set()
790 * @see evas_object_map_set()
793 evas_map_point_color_set(Evas_Map *m, int idx, int r, int g, int b, int a)
797 if (idx >= m->count) return;
806 * Get the color set on a vertex in the map
808 * This gets the color set by evas_map_point_color_set() on the given vertex
811 * @param m map to get the color of the vertex from.
812 * @param idx index of point get. Must be smaller than map size.
813 * @param r pointer to red return
814 * @param g pointer to green return
815 * @param b pointer to blue return
816 * @param a pointer to alpha return (0 - 255)
818 * @see evas_map_point_coord_set()
819 * @see evas_object_map_set()
822 evas_map_point_color_get(const Evas_Map *m, int idx, int *r, int *g, int *b, int *a)
824 const Evas_Map_Point *p;
826 if (idx >= m->count) return;
834 /****************************************************************************/
835 /* util functions for manipulating maps, so you don't need to know the math */
836 /****************************************************************************/
838 _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)
840 Evas_Map_Point *p = m->points;
877 * Populate source and destination map points to match exactly object.
879 * Usually one initialize map of an object to match it's original
880 * position and size, then transform these with evas_map_util_*
881 * functions, such as evas_map_util_rotate() or
882 * evas_map_util_3d_rotate(). The original set is done by this
883 * function, avoiding code duplication all around.
885 * @param m map to change all 4 points (must be of size 4).
886 * @param obj object to use unmapped geometry to populate map coordinates.
887 * @param z Point Z Coordinate hint (pre-perspective transform). This value
888 * will be used for all four points.
890 * @see evas_map_util_points_populate_from_object()
891 * @see evas_map_point_coord_set()
892 * @see evas_map_point_image_uv_set()
895 evas_map_util_points_populate_from_object_full(Evas_Map *m, const Evas_Object *obj, Evas_Coord z)
897 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
907 ERR("map has count=%d where 4 was expected.", m->count);
910 _evas_map_util_points_populate(m, obj->cur.geometry.x, obj->cur.geometry.y,
911 obj->cur.geometry.w, obj->cur.geometry.h, z);
915 * Populate source and destination map points to match exactly object.
917 * Usually one initialize map of an object to match it's original
918 * position and size, then transform these with evas_map_util_*
919 * functions, such as evas_map_util_rotate() or
920 * evas_map_util_3d_rotate(). The original set is done by this
921 * function, avoiding code duplication all around.
923 * Z Point coordinate is assumed as 0 (zero).
925 * @param m map to change all 4 points (must be of size 4).
926 * @param obj object to use unmapped geometry to populate map coordinates.
928 * @see evas_map_util_points_populate_from_object_full()
929 * @see evas_map_util_points_populate_from_geometry()
930 * @see evas_map_point_coord_set()
931 * @see evas_map_point_image_uv_set()
934 evas_map_util_points_populate_from_object(Evas_Map *m, const Evas_Object *obj)
936 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
946 ERR("map has count=%d where 4 was expected.", m->count);
949 _evas_map_util_points_populate(m, obj->cur.geometry.x, obj->cur.geometry.y,
950 obj->cur.geometry.w, obj->cur.geometry.h, 0);
954 * Populate source and destination map points to match given geometry.
956 * Similar to evas_map_util_points_populate_from_object_full(), this
957 * call takes raw values instead of querying object's unmapped
958 * geometry. The given width will be used to calculate destination
959 * points (evas_map_point_coord_set()) and set the image uv
960 * (evas_map_point_image_uv_set()).
962 * @param m map to change all 4 points (must be of size 4).
963 * @param x Point X Coordinate
964 * @param y Point Y Coordinate
965 * @param w width to use to calculate second and third points.
966 * @param h height to use to calculate third and fourth points.
967 * @param z Point Z Coordinate hint (pre-perspective transform). This value
968 * will be used for all four points.
970 * @see evas_map_util_points_populate_from_object()
971 * @see evas_map_point_coord_set()
972 * @see evas_map_point_image_uv_set()
975 evas_map_util_points_populate_from_geometry(Evas_Map *m, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h, Evas_Coord z)
984 ERR("map has count=%d where 4 was expected.", m->count);
987 _evas_map_util_points_populate(m, x, y, w, h, z);
991 * Set color of all points to given color.
993 * This call is useful to reuse maps after they had 3d lightning or
994 * any other colorization applied before.
996 * @param m map to change the color of.
997 * @param r red (0 - 255)
998 * @param g green (0 - 255)
999 * @param b blue (0 - 255)
1000 * @param a alpha (0 - 255)
1002 * @see evas_map_point_color_set()
1005 evas_map_util_points_color_set(Evas_Map *m, int r, int g, int b, int a)
1007 Evas_Map_Point *p, *p_end;
1014 p_end = p + m->count;
1015 for (; p < p_end; p++)
1025 * Change the map to apply the given rotation.
1027 * This rotates the indicated map's coordinates around the center coordinate
1028 * given by @p cx and @p cy as the rotation center. The points will have their
1029 * X and Y coordinates rotated clockwise by @p degrees degress (360.0 is a
1030 * full rotation). Negative values for degrees will rotate counter-clockwise
1031 * by that amount. All coordinates are canvas global coordinates.
1033 * @param m map to change.
1034 * @param degrees amount of degrees from 0.0 to 360.0 to rotate.
1035 * @param cx rotation's center horizontal position.
1036 * @param cy rotation's center vertical position.
1038 * @see evas_map_point_coord_set()
1039 * @see evas_map_util_zoom()
1042 evas_map_util_rotate(Evas_Map *m, double degrees, Evas_Coord cx, Evas_Coord cy)
1044 double r = (degrees * M_PI) / 180.0;
1045 Evas_Map_Point *p, *p_end;
1049 p_end = p + m->count;
1051 for (; p < p_end; p++)
1053 Evas_Coord x, y, xx, yy;
1060 x = xx + (y * cos(r + (M_PI / 2.0)));
1061 y = yy + (y * sin(r + (M_PI / 2.0)));
1071 * Change the map to apply the given zooming.
1073 * Like evas_map_util_rotate(), this zooms the points of the map from a center
1074 * point. That center is defined by @p cx and @p cy. The @p zoomx and @p zoomy
1075 * parameters specific how much to zoom in the X and Y direction respectively.
1076 * A value of 1.0 means "don't zoom". 2.0 means "dobule the size". 0.5 is
1077 * "half the size" etc. All coordinates are canvas global coordinates.
1079 * @param m map to change.
1080 * @param zoomx horizontal zoom to use.
1081 * @param zoomy vertical zoom to use.
1082 * @param cx zooming center horizontal position.
1083 * @param cy zooming center vertical position.
1085 * @see evas_map_point_coord_set()
1086 * @see evas_map_util_rotate()
1089 evas_map_util_zoom(Evas_Map *m, double zoomx, double zoomy, Evas_Coord cx, Evas_Coord cy)
1091 Evas_Map_Point *p, *p_end;
1095 p_end = p + m->count;
1097 for (; p < p_end; p++)
1104 x = (((double)x) * zoomx);
1105 y = (((double)y) * zoomy);
1115 * Rotate the map around 3 axes in 3D
1117 * This will rotate not just around the "Z" axis as in evas_map_util_rotate()
1118 * (which is a convenience call for those only wanting 2D). This will rotate
1119 * around the X, Y and Z axes. The Z axis points "into" the screen with low
1120 * values at the screen and higher values further away. The X axis runs from
1121 * left to right on the screen and the Y axis from top to bottom. Like with
1122 * evas_map_util_rotate(0 you provide a center point to rotate around (in 3D).
1124 * @param m map to change.
1125 * @param dx amount of degrees from 0.0 to 360.0 to rotate arount X axis.
1126 * @param dy amount of degrees from 0.0 to 360.0 to rotate arount Y axis.
1127 * @param dz amount of degrees from 0.0 to 360.0 to rotate arount Z axis.
1128 * @param cx rotation's center horizontal position.
1129 * @param cy rotation's center vertical position.
1130 * @param cz rotation's center vertical position.
1133 evas_map_util_3d_rotate(Evas_Map *m, double dx, double dy, double dz,
1134 Evas_Coord cx, Evas_Coord cy, Evas_Coord cz)
1136 double rz = (dz * M_PI) / 180.0;
1137 double rx = (dx * M_PI) / 180.0;
1138 double ry = (dy * M_PI) / 180.0;
1139 Evas_Map_Point *p, *p_end;
1143 p_end = p + m->count;
1145 for (; p < p_end; p++)
1147 double x, y, z, xx, yy, zz;
1157 x = xx + (y * cos(rz + M_PI_2));
1158 y = yy + (y * sin(rz + M_PI_2));
1165 x = xx + (z * cos(ry + M_PI_2));
1166 z = zz + (z * sin(ry + M_PI_2));
1173 z = zz + (y * cos(rx + M_PI_2));
1174 y = yy + (y * sin(rx + M_PI_2));
1186 * Perform lighting calculations on the given Map
1188 * This is used to apply lighting calculations (from a single light source)
1189 * to a given map. The R, G and B values of each vertex will be modified to
1190 * reflect the lighting based on the lixth point coordinates, the light
1191 * color and the ambient color, and at what angle the map is facing the
1192 * light source. A surface should have its points be declared in a
1193 * clockwise fashion if the face is "facing" towards you (as opposed to
1194 * away from you) as faces have a "logical" side for lighting.
1196 * @param m map to change.
1197 * @param lx X coordinate in space of light point
1198 * @param ly Y coordinate in space of light point
1199 * @param lz Z coordinate in space of light point
1200 * @param lr light red value (0 - 255)
1201 * @param lg light green value (0 - 255)
1202 * @param lb light blue value (0 - 255)
1203 * @param ar ambient color red value (0 - 255)
1204 * @param ag ambient color green value (0 - 255)
1205 * @param ab ambient color blue value (0 - 255)
1208 evas_map_util_3d_lighting(Evas_Map *m,
1209 Evas_Coord lx, Evas_Coord ly, Evas_Coord lz,
1210 int lr, int lg, int lb, int ar, int ag, int ab)
1216 for (i = 0; i < m->count; i++)
1219 double nx, ny, nz, x1, y1, z1, x2, y2, z2, ln, br;
1220 int h, j, mr, mg, mb;
1225 printf("Normal %d\n",i);
1227 h = (i - 1 + 4) % 4 + (i & ~0x3); // prev point
1228 j = (i + 1) % 4 + (i & ~0x3); // next point
1229 printf("\tNext/Prev: %2d/%2d\n",h,j);
1231 x1 = m->points[h].x - x;
1232 y1 = m->points[h].y - y;
1233 z1 = m->points[h].z - z;
1235 x2 = m->points[j].x - x;
1236 y2 = m->points[j].y - y;
1237 z2 = m->points[j].z - z;
1238 printf("\tX: %3.2lf,%3.2lf,%3.2lf\n",x,y,z);
1239 printf("\tX1: %3.2lf,%3.2lf,%3.2lf\n",x1,y1,z1);
1240 printf("\tX2: %3.2lf,%3.2lf,%3.2lf\n",x2,y2,z2);
1241 nx = (y1 * z2) - (z1 * y2);
1242 ny = (z1 * x2) - (x1 * z2);
1243 nz = (x1 * y2) - (y1 * x2);
1245 ln = (nx * nx) + (ny * ny) + (nz * nz);
1247 printf("\tLength: %3.2lf\n",ln);
1255 printf("\tpoint %2d: %3.2lf,%3.2lf,%3.2lf normal: %3.2lf %3.2lf %3.2lf\n",i,x,y,z,nx,ny,nz);
1257 // calc point -> light vector
1262 ln = (x * x) + (y * y) + (z * z);
1272 // brightness - tan (0.0 -> 1.0 brightness really)
1273 br = (nx * x) + (ny * y) + (nz * z);
1274 if (br < 0.0) br = 0.0;
1276 mr = ar + ((lr - ar) * br);
1277 mg = ag + ((lg - ag) * br);
1278 mb = ab + ((lb - ab) * br);
1279 if (m->points[i].a != 255){
1280 mr = (mr * m->points[i].a) / 255;
1281 mg = (mg * m->points[i].a) / 255;
1282 mb = (mb * m->points[i].a) / 255;
1284 m->points[i].r = (m->points[i].r * mr) / 255;
1285 m->points[i].g = (m->points[i].g * mg) / 255;
1286 m->points[i].b = (m->points[i].b * mb) / 255;
1291 * Apply a perspective transform to the map
1293 * This applies a given perspective (3D) to the map coordinates. X, Y and Z
1294 * values are used. The px and py points specify the "infinite distance" point
1295 * in the 3D conversion (where all lines converge to like when artists draw
1296 * 3D by hand). The @p z0 value specifis the z value at which there is a 1:1
1297 * mapping between spatial coorinates and screen coordinates. Any points
1298 * on this z value will not have their X and Y values modified in the transform.
1299 * Those further away (Z value higher) will shrink into the distance, and
1300 * those less than this value will expand and become bigger. The @p foc value
1301 * determines the "focal length" of the camera. This is in reality the distance
1302 * between the camera lens plane itself (at or closer than this rendering
1303 * results are undefined) and the "z0" z value. This allows for some "depth"
1304 * control and @p foc must be greater than 0.
1306 * @param m map to change.
1307 * @param px The pespective distance X coordinate
1308 * @param py The pespective distance Y coordinate
1309 * @param z0 The "0" z plane value
1310 * @param foc The focal distance
1313 evas_map_util_3d_perspective(Evas_Map *m,
1314 Evas_Coord px, Evas_Coord py,
1315 Evas_Coord z0, Evas_Coord foc)
1317 Evas_Map_Point *p, *p_end;
1321 p_end = p + m->count;
1327 for (; p < p_end; p++)
1329 Evas_Coord x, y, zz;
1336 zz = ((p->z - z0) + foc);
1351 * Get the clockwise state of a map
1353 * This determines if the output points (X and Y. Z is not used) are
1354 * clockwise or anti-clockwise. This can be used for "back-face culling". This
1355 * is where you hide objects that "face away" from you. In this case objects
1356 * that are not clockwise.
1358 * @param m map to query.
1359 * @return 1 if clockwise, 0 otherwise
1362 evas_map_util_clockwise_get(Evas_Map *m)
1368 if (m->count < 3) return 0;
1371 for (i = 0; i < m->count; i++)
1373 j = (i + 1) % m->count;
1374 k = (i + 2) % m->count;
1376 ((m->points[j].x - m->points[i].x) *
1377 (m->points[k].y - m->points[j].y))
1379 ((m->points[j].y - m->points[i].y) *
1380 (m->points[k].x - m->points[j].x));
1382 else if (c > 0) count++;
1384 if (count > 0) return 1;