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;
40 Eina_Bool ch = EINA_FALSE;
42 if (!obj->cur.map) return;
43 /* WARN: Do not merge below code to SLP until it is fixed.
44 It has an infinite loop bug.
47 // FIXME: this causes an infinite loop somewhere... hard to debug
48 if (obj->prev.map->count == obj->cur.map->count)
50 const Evas_Map_Point *p2;
52 p = obj->cur.map->points;
53 p_end = p + obj->cur.map->count;
54 p2 = obj->prev.map->points;
56 for (; p < p_end; p++, p2++)
58 if ((p->a != p2->a) ||
66 if ((p->x != p2->x) ||
80 WARN: DO NOT REMOVE THIS COMMENT. LEAVE IT AS IS UNTIL FIXED. */
82 p = obj->cur.map->points;
83 p_end = p + obj->cur.map->count;
89 for (; p < p_end; p++)
91 if (p->x < x1) x1 = p->x;
92 if (p->x > x2) x2 = p->x;
93 if (p->y < y1) y1 = p->y;
94 if (p->y > y2) y2 = p->y;
96 if (obj->cur.map->normal_geometry.x != x1) ch = 1;
97 if (obj->cur.map->normal_geometry.y != y1) ch = 1;
98 if (obj->cur.map->normal_geometry.w != (x2 - x1)) ch = 1;
99 if (obj->cur.map->normal_geometry.h != (y2 - y1)) ch = 1;
100 obj->cur.map->normal_geometry.x = x1;
101 obj->cur.map->normal_geometry.y = y1;
102 obj->cur.map->normal_geometry.w = (x2 - x1);
103 obj->cur.map->normal_geometry.h = (y2 - y1);
104 if (ch) _evas_map_calc_geom_change(obj);
107 static inline Evas_Map *
108 _evas_map_new(int count)
114 /* Adjust allocation such that: at least 4 points, and always an even
115 * number: this allows the software engine to work efficiently */
116 alloc = (count < 4) ? 4 : count;
117 if (alloc & 0x1) alloc ++;
119 m = calloc(1, sizeof(Evas_Map) + (alloc * sizeof(Evas_Map_Point)));
125 m->magic = MAGIC_MAP;
126 for (i = 0; i < count; i++)
128 m->points[i].r = 255;
129 m->points[i].g = 255;
130 m->points[i].b = 255;
131 m->points[i].a = 255;
136 static inline Eina_Bool
137 _evas_map_copy(Evas_Map *dst, const Evas_Map *src)
139 if (dst->count != src->count)
141 ERR("cannot copy map of different sizes: dst=%i, src=%i", dst->count, src->count);
144 memcpy(dst->points, src->points, src->count * sizeof(Evas_Map_Point));
145 dst->smooth = src->smooth;
146 dst->alpha = src->alpha;
147 dst->persp = src->persp;
151 static inline Evas_Map *
152 _evas_map_dup(const Evas_Map *orig)
154 Evas_Map *copy = _evas_map_new(orig->count);
155 if (!copy) return NULL;
156 memcpy(copy->points, orig->points, orig->count * sizeof(Evas_Map_Point));
157 copy->smooth = orig->smooth;
158 copy->alpha = orig->alpha;
159 copy->persp = orig->persp;
164 _evas_map_free(Evas_Object *obj, Evas_Map *m)
169 obj->layer->evas->engine.func->image_map_surface_free
170 (obj->layer->evas->engine.data.output, m->surface);
176 /****************************************************************************/
177 /* util functions for manipulating maps, so you don't need to know the math */
178 /****************************************************************************/
180 _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)
182 Evas_Map_Point *p = m->points;
209 for (i = 0; i < 4; i++)
217 evas_map_coords_get(const Evas_Map *m, Evas_Coord x, Evas_Coord y,
218 Evas_Coord *mx, Evas_Coord *my, int grab)
220 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
224 int i, j, edges, edge[m->count][2], douv;
226 double u[2] = { 0.0, 0.0 };
227 double v[2] = { 0.0, 0.0 };
229 if (m->count < 4) return 0;
230 // FIXME need to handle grab mode and extrapolte coords outside
234 Evas_Coord ymin, ymax;
236 ymin = m->points[0].y;
237 ymax = m->points[0].y;
238 for (i = 1; i < m->count; i++)
240 if (m->points[i].y < ymin) ymin = m->points[i].y;
241 else if (m->points[i].y > ymax) ymax = m->points[i].y;
243 if (y <= ymin) y = ymin + 1;
244 if (y >= ymax) y = ymax - 1;
247 for (i = 0; i < m->count; i++)
249 j = (i + 1) % m->count;
250 if ((m->points[i].y <= y) && (m->points[j].y > y))
256 else if ((m->points[j].y <= y) && (m->points[i].y > y))
264 if ((mx) || (my)) douv = 1;
265 for (i = 0; i < (edges - 1); i+= 2)
270 yd = m->points[edge[i][1]].y - m->points[edge[i][0]].y;
273 yp = y - m->points[edge[i][0]].y;
274 xe[0] = m->points[edge[i][1]].x - m->points[edge[i][0]].x;
275 xe[0] = m->points[edge[i][0]].x + ((xe[0] * yp) / yd);
278 u[0] = m->points[edge[i][1]].u - m->points[edge[i][0]].u;
279 u[0] = m->points[edge[i][0]].u + ((u[0] * yp) / yd);
280 v[0] = m->points[edge[i][1]].v - m->points[edge[i][0]].v;
281 v[0] = m->points[edge[i][0]].v + ((v[0] * yp) / yd);
286 xe[0] = m->points[edge[i][0]].x;
289 u[0] = m->points[edge[i][0]].u;
290 v[0] = m->points[edge[i][0]].v;
293 yd = m->points[edge[j][1]].y - m->points[edge[j][0]].y;
296 yp = y - m->points[edge[j][0]].y;
297 xe[1] = m->points[edge[j][1]].x - m->points[edge[j][0]].x;
298 xe[1] = m->points[edge[j][0]].x + ((xe[1] * yp) / yd);
301 u[1] = m->points[edge[j][1]].u - m->points[edge[j][0]].u;
302 u[1] = m->points[edge[j][0]].u + ((u[1] * yp) / yd);
303 v[1] = m->points[edge[j][1]].v - m->points[edge[j][0]].v;
304 v[1] = m->points[edge[j][0]].v + ((v[1] * yp) / yd);
309 xe[1] = m->points[edge[j][0]].x;
312 u[1] = m->points[edge[j][0]].u;
313 v[1] = m->points[edge[j][0]].v;
320 ti = xe[0]; xe[0] = xe[1]; xe[1] = ti;
325 td = u[0]; u[0] = u[1]; u[1] = td;
326 td = v[0]; v[0] = v[1]; v[1] = td;
329 if ((x >= xe[0]) && (x < xe[1]))
334 *mx = u[0] + (((x - xe[0]) * (u[1] - u[0])) /
337 *my = v[0] + (((x - xe[0]) * (v[1] - v[0])) /
347 *mx = u[0] + (((x - xe[0]) * (u[1] - u[0])) /
350 *my = v[0] + (((x - xe[0]) * (v[1] - v[0])) /
360 evas_map_inside_get(const Evas_Map *m, Evas_Coord x, Evas_Coord y)
362 return evas_map_coords_get(m, x, y, NULL, NULL, 0);
366 evas_object_map_enable_set(Evas_Object *obj, Eina_Bool enabled)
368 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
373 if (obj->cur.usemap == enabled) return;
374 obj->cur.usemap = enabled;
378 obj->cur.map = _evas_map_new(4);
379 evas_object_mapped_clip_across_mark(obj);
380 // obj->cur.map->normal_geometry = obj->cur.geometry;
386 _evas_map_calc_geom_change(obj);
387 evas_object_mapped_clip_across_mark(obj);
388 //FIXME: Since the last frame is not updated when map is
389 //disabled, afterimage problem is happened in s/w rendering.
390 //Need to find out the fundamental reason then fix it.
391 evas_damage_rectangle_add(obj->layer->evas,
394 obj->layer->evas->output.w,
395 obj->layer->evas->output.h);
398 _evas_map_calc_map_geometry(obj);
399 /* This is a bit heavy handed, but it fixes the case of same geometry, but
400 * changed colour or UV settings. */
401 evas_object_change(obj);
405 evas_object_map_enable_get(const Evas_Object *obj)
407 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
410 return obj->cur.usemap;
415 evas_object_map_source_set(Evas_Object *obj, Evas_Object *src)
417 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
420 (void)src; /* method still needs to be implemented. */
424 evas_object_map_source_get(const Evas_Object *obj)
426 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
433 evas_object_map_set(Evas_Object *obj, const Evas_Map *map)
435 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
443 if (obj->cur.map->surface)
445 obj->layer->evas->engine.func->image_map_surface_free
446 (obj->layer->evas->engine.data.output,
447 obj->cur.map->surface);
448 obj->cur.map->surface = NULL;
450 obj->prev.geometry = obj->cur.map->normal_geometry;
453 _evas_map_free(obj, obj->cur.map);
455 evas_object_mapped_clip_across_mark(obj);
458 _evas_map_free(obj, obj->cur.map);
460 if (!obj->cur.usemap) _evas_map_calc_geom_change(obj);
461 else _evas_map_calc_map_geometry(obj);
464 evas_object_mapped_clip_across_mark(obj);
465 //FIXME: Since the last frame is not updated when map is
466 //disabled, afterimage problem is happened in s/w
467 //rendering. Need to find out the fundamental reason
469 evas_damage_rectangle_add(obj->layer->evas,
472 obj->layer->evas->output.w,
473 obj->layer->evas->output.h);
479 if ((obj->cur.map) && (obj->cur.map->count == map->count))
481 Evas_Map *omap = obj->cur.map;
482 obj->cur.map = _evas_map_new(map->count);
483 memcpy(obj->cur.map, omap, sizeof(Evas_Map) + (map->count * sizeof(Evas_Map_Point)));
484 _evas_map_copy(obj->cur.map, map);
485 if (obj->prev.map == omap) obj->prev.map = NULL;
490 if (obj->cur.map) evas_map_free(obj->cur.map);
491 obj->cur.map = _evas_map_dup(map);
493 evas_object_mapped_clip_across_mark(obj);
495 _evas_map_calc_map_geometry(obj);
498 EAPI const Evas_Map *
499 evas_object_map_get(const Evas_Object *obj)
501 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
509 evas_map_new(int count)
513 ERR("map point count (%i) != 4 is unsupported!", count);
517 return _evas_map_new(count);
521 evas_map_smooth_set(Evas_Map *m, Eina_Bool enabled)
523 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
531 evas_map_smooth_get(const Evas_Map *m)
533 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
541 evas_map_alpha_set(Evas_Map *m, Eina_Bool enabled)
543 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
551 evas_map_alpha_get(const Evas_Map *m)
553 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
561 evas_map_dup(const Evas_Map *m)
563 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
567 return _evas_map_dup(m);
571 evas_map_free(Evas_Map *m)
573 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
577 _evas_map_free(NULL, m);
581 evas_map_count_get(const Evas_Map *m)
583 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
591 evas_map_point_coord_set(Evas_Map *m, int idx, Evas_Coord x, Evas_Coord y, Evas_Coord z)
593 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
599 if (idx >= m->count) return;
607 evas_map_point_coord_get(const Evas_Map *m, int idx, Evas_Coord *x, Evas_Coord *y, Evas_Coord *z)
609 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
613 const Evas_Map_Point *p;
615 if (idx >= m->count) goto error;
629 evas_map_point_image_uv_set(Evas_Map *m, int idx, double u, double v)
631 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
637 if (idx >= m->count) return;
644 evas_map_point_image_uv_get(const Evas_Map *m, int idx, double *u, double *v)
646 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
650 const Evas_Map_Point *p;
652 if (idx >= m->count) goto error;
664 evas_map_point_color_set(Evas_Map *m, int idx, int r, int g, int b, int a)
666 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
672 if (idx >= m->count) return;
681 evas_map_point_color_get(const Evas_Map *m, int idx, int *r, int *g, int *b, int *a)
683 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
687 const Evas_Map_Point *p;
689 if (idx >= m->count) return;
698 evas_map_util_points_populate_from_object_full(Evas_Map *m, const Evas_Object *obj, Evas_Coord z)
700 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
706 ERR("map has count=%d where 4 was expected.", m->count);
709 _evas_map_util_points_populate(m, obj->cur.geometry.x, obj->cur.geometry.y,
710 obj->cur.geometry.w, obj->cur.geometry.h, z);
714 evas_map_util_points_populate_from_object(Evas_Map *m, const Evas_Object *obj)
716 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
720 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
726 ERR("map has count=%d where 4 was expected.", m->count);
729 _evas_map_util_points_populate(m, obj->cur.geometry.x, obj->cur.geometry.y,
730 obj->cur.geometry.w, obj->cur.geometry.h, 0);
734 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)
736 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
742 ERR("map has count=%d where 4 was expected.", m->count);
745 _evas_map_util_points_populate(m, x, y, w, h, z);
749 evas_map_util_points_color_set(Evas_Map *m, int r, int g, int b, int a)
751 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
755 Evas_Map_Point *p, *p_end;
758 p_end = p + m->count;
759 for (; p < p_end; p++)
769 evas_map_util_rotate(Evas_Map *m, double degrees, Evas_Coord cx, Evas_Coord cy)
771 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
775 double r = (degrees * M_PI) / 180.0;
776 Evas_Map_Point *p, *p_end;
779 p_end = p + m->count;
781 for (; p < p_end; p++)
790 x = xx - (y * sin(r));
791 y = yy + (y * cos(r));
793 p->px = p->x = x + cx;
794 p->py = p->y = y + cy;
799 evas_map_util_zoom(Evas_Map *m, double zoomx, double zoomy, Evas_Coord cx, Evas_Coord cy)
801 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
805 Evas_Map_Point *p, *p_end;
808 p_end = p + m->count;
810 for (; p < p_end; p++)
817 x = (((double)x) * zoomx);
818 y = (((double)y) * zoomy);
820 p->px = p->x = x + cx;
821 p->py = p->y = y + cy;
826 evas_map_util_3d_rotate(Evas_Map *m, double dx, double dy, double dz,
827 Evas_Coord cx, Evas_Coord cy, Evas_Coord cz)
829 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
833 double rz = (dz * M_PI) / 180.0;
834 double rx = (dx * M_PI) / 180.0;
835 double ry = (dy * M_PI) / 180.0;
836 Evas_Map_Point *p, *p_end;
839 p_end = p + m->count;
841 for (; p < p_end; p++)
843 double x, y, z, xx, yy, zz;
853 x = xx - (y * sin(rz));
854 y = yy + (y * cos(rz));
861 x = xx - (z * sin(ry));
862 z = zz + (z * cos(ry));
869 z = zz - (y * sin(rx));
870 y = yy + (y * cos(rx));
873 p->px = p->x = x + cx;
874 p->py = p->y = y + cy;
880 evas_map_util_3d_lighting(Evas_Map *m,
881 Evas_Coord lx, Evas_Coord ly, Evas_Coord lz,
882 int lr, int lg, int lb, int ar, int ag, int ab)
884 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
890 for (i = 0; i < m->count; i++)
893 double nx, ny, nz, x1, y1, z1, x2, y2, z2, ln, br;
894 int h, j, mr, mg, mb;
900 h = (i - 1 + 4) % 4 + (i & ~0x3); // prev point
901 j = (i + 1) % 4 + (i & ~0x3); // next point
903 x1 = m->points[h].x - x;
904 y1 = m->points[h].y - y;
905 z1 = m->points[h].z - z;
907 x2 = m->points[j].x - x;
908 y2 = m->points[j].y - y;
909 z2 = m->points[j].z - z;
910 nx = (y1 * z2) - (z1 * y2);
911 ny = (z1 * x2) - (x1 * z2);
912 nz = (x1 * y2) - (y1 * x2);
914 ln = (nx * nx) + (ny * ny) + (nz * nz);
924 // calc point -> light vector
929 ln = (x * x) + (y * y) + (z * z);
939 // brightness - tan (0.0 -> 1.0 brightness really)
940 br = (nx * x) + (ny * y) + (nz * z);
941 if (br < 0.0) br = 0.0;
943 mr = ar + ((lr - ar) * br);
944 mg = ag + ((lg - ag) * br);
945 mb = ab + ((lb - ab) * br);
946 if (m->points[i].a != 255)
948 mr = (mr * m->points[i].a) / 255;
949 mg = (mg * m->points[i].a) / 255;
950 mb = (mb * m->points[i].a) / 255;
952 m->points[i].r = (m->points[i].r * mr) / 255;
953 m->points[i].g = (m->points[i].g * mg) / 255;
954 m->points[i].b = (m->points[i].b * mb) / 255;
959 evas_map_util_3d_perspective(Evas_Map *m,
960 Evas_Coord px, Evas_Coord py,
961 Evas_Coord z0, Evas_Coord foc)
963 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
967 Evas_Map_Point *p, *p_end;
970 p_end = p + m->count;
977 if (foc <= 0) return;
979 for (; p < p_end; p++)
986 zz = ((p->z - z0) + foc);
1000 evas_map_util_clockwise_get(Evas_Map *m)
1002 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
1009 if (m->count < 3) return EINA_FALSE;
1012 for (i = 0; i < m->count; i++)
1014 j = (i + 1) % m->count;
1015 k = (i + 2) % m->count;
1017 ((m->points[j].x - m->points[i].x) *
1018 (m->points[k].y - m->points[j].y))
1020 ((m->points[j].y - m->points[i].y) *
1021 (m->points[k].x - m->points[j].x));
1023 else if (c > 0) count++;
1025 if (count > 0) return EINA_TRUE;