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;
44 // WARN: Do not merge below code to SLP until it is fixed.
45 // It has an infinite loop bug.
49 // FIXME: this causes an infinite loop somewhere... hard to debug
50 if (obj->prev.map->count == obj->cur.map->count)
52 const Evas_Map_Point *p2;
54 p = obj->cur.map->points;
55 p_end = p + obj->cur.map->count;
56 p2 = obj->prev.map->points;
58 for (; p < p_end; p++, p2++)
60 if ((p->a != p2->a) ||
68 if ((p->x != p2->x) ||
84 p = obj->cur.map->points;
85 p_end = p + obj->cur.map->count;
91 for (; p < p_end; p++)
93 if (p->x < x1) x1 = p->x;
94 if (p->x > x2) x2 = p->x;
95 if (p->y < y1) y1 = p->y;
96 if (p->y > y2) y2 = p->y;
98 if (obj->cur.map->normal_geometry.x != x1) ch = 1;
99 if (obj->cur.map->normal_geometry.y != y1) ch = 1;
100 if (obj->cur.map->normal_geometry.w != (x2 - x1)) ch = 1;
101 if (obj->cur.map->normal_geometry.h != (y2 - y1)) ch = 1;
102 obj->cur.map->normal_geometry.x = x1;
103 obj->cur.map->normal_geometry.y = y1;
104 obj->cur.map->normal_geometry.w = (x2 - x1);
105 obj->cur.map->normal_geometry.h = (y2 - y1);
106 if (ch) _evas_map_calc_geom_change(obj);
109 static inline Evas_Map *
110 _evas_map_new(int count)
116 /* Adjust allocation such that: at least 4 points, and always an even
117 * number: this allows the software engine to work efficiently */
118 alloc = (count < 4) ? 4 : count;
119 if (alloc & 0x1) alloc ++;
121 m = calloc(1, sizeof(Evas_Map) + (alloc * sizeof(Evas_Map_Point)));
127 m->magic = MAGIC_MAP;
128 for (i = 0; i < count; i++)
130 m->points[i].r = 255;
131 m->points[i].g = 255;
132 m->points[i].b = 255;
133 m->points[i].a = 255;
138 static inline Eina_Bool
139 _evas_map_copy(Evas_Map *dst, const Evas_Map *src)
141 if (dst->count != src->count)
143 ERR("cannot copy map of different sizes: dst=%i, src=%i", dst->count, src->count);
146 memcpy(dst->points, src->points, src->count * sizeof(Evas_Map_Point));
147 dst->smooth = src->smooth;
148 dst->alpha = src->alpha;
149 dst->persp = src->persp;
153 static inline Evas_Map *
154 _evas_map_dup(const Evas_Map *orig)
156 Evas_Map *copy = _evas_map_new(orig->count);
157 if (!copy) return NULL;
158 memcpy(copy->points, orig->points, orig->count * sizeof(Evas_Map_Point));
159 copy->smooth = orig->smooth;
160 copy->alpha = orig->alpha;
161 copy->persp = orig->persp;
166 _evas_map_free(Evas_Object *obj, Evas_Map *m)
171 obj->layer->evas->engine.func->image_map_surface_free
172 (obj->layer->evas->engine.data.output, m->surface);
178 /****************************************************************************/
179 /* util functions for manipulating maps, so you don't need to know the math */
180 /****************************************************************************/
182 _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)
184 Evas_Map_Point *p = m->points;
211 for (i = 0; i < 4; i++)
219 evas_map_coords_get(const Evas_Map *m, Evas_Coord x, Evas_Coord y,
220 Evas_Coord *mx, Evas_Coord *my, int grab)
222 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
226 int i, j, edges, edge[m->count][2], douv;
228 double u[2] = { 0.0, 0.0 };
229 double v[2] = { 0.0, 0.0 };
231 if (m->count < 4) return 0;
232 // FIXME need to handle grab mode and extrapolte coords outside
236 Evas_Coord ymin, ymax;
238 ymin = m->points[0].y;
239 ymax = m->points[0].y;
240 for (i = 1; i < m->count; i++)
242 if (m->points[i].y < ymin) ymin = m->points[i].y;
243 else if (m->points[i].y > ymax) ymax = m->points[i].y;
245 if (y <= ymin) y = ymin + 1;
246 if (y >= ymax) y = ymax - 1;
249 for (i = 0; i < m->count; i++)
251 j = (i + 1) % m->count;
252 if ((m->points[i].y <= y) && (m->points[j].y > y))
258 else if ((m->points[j].y <= y) && (m->points[i].y > y))
266 if ((mx) || (my)) douv = 1;
267 for (i = 0; i < (edges - 1); i+= 2)
272 yd = m->points[edge[i][1]].y - m->points[edge[i][0]].y;
275 yp = y - m->points[edge[i][0]].y;
276 xe[0] = m->points[edge[i][1]].x - m->points[edge[i][0]].x;
277 xe[0] = m->points[edge[i][0]].x + ((xe[0] * yp) / yd);
280 u[0] = m->points[edge[i][1]].u - m->points[edge[i][0]].u;
281 u[0] = m->points[edge[i][0]].u + ((u[0] * yp) / yd);
282 v[0] = m->points[edge[i][1]].v - m->points[edge[i][0]].v;
283 v[0] = m->points[edge[i][0]].v + ((v[0] * yp) / yd);
288 xe[0] = m->points[edge[i][0]].x;
291 u[0] = m->points[edge[i][0]].u;
292 v[0] = m->points[edge[i][0]].v;
295 yd = m->points[edge[j][1]].y - m->points[edge[j][0]].y;
298 yp = y - m->points[edge[j][0]].y;
299 xe[1] = m->points[edge[j][1]].x - m->points[edge[j][0]].x;
300 xe[1] = m->points[edge[j][0]].x + ((xe[1] * yp) / yd);
303 u[1] = m->points[edge[j][1]].u - m->points[edge[j][0]].u;
304 u[1] = m->points[edge[j][0]].u + ((u[1] * yp) / yd);
305 v[1] = m->points[edge[j][1]].v - m->points[edge[j][0]].v;
306 v[1] = m->points[edge[j][0]].v + ((v[1] * yp) / yd);
311 xe[1] = m->points[edge[j][0]].x;
314 u[1] = m->points[edge[j][0]].u;
315 v[1] = m->points[edge[j][0]].v;
322 ti = xe[0]; xe[0] = xe[1]; xe[1] = ti;
327 td = u[0]; u[0] = u[1]; u[1] = td;
328 td = v[0]; v[0] = v[1]; v[1] = td;
331 if ((x >= xe[0]) && (x < xe[1]))
336 *mx = u[0] + (((x - xe[0]) * (u[1] - u[0])) /
339 *my = v[0] + (((x - xe[0]) * (v[1] - v[0])) /
349 *mx = u[0] + (((x - xe[0]) * (u[1] - u[0])) /
352 *my = v[0] + (((x - xe[0]) * (v[1] - v[0])) /
362 evas_map_inside_get(const Evas_Map *m, Evas_Coord x, Evas_Coord y)
364 return evas_map_coords_get(m, x, y, NULL, NULL, 0);
368 evas_object_map_enable_set(Evas_Object *obj, Eina_Bool enabled)
370 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
375 if (obj->cur.usemap == enabled) return;
376 obj->cur.usemap = enabled;
380 obj->cur.map = _evas_map_new(4);
381 evas_object_mapped_clip_across_mark(obj);
382 // obj->cur.map->normal_geometry = obj->cur.geometry;
388 _evas_map_calc_geom_change(obj);
389 evas_object_mapped_clip_across_mark(obj);
390 //FIXME: Since the last frame is not updated when map is
391 //disabled, afterimage problem is happened in s/w rendering.
392 //Need to find out the fundamental reason then fix it.
393 evas_damage_rectangle_add(obj->layer->evas,
396 obj->layer->evas->output.w,
397 obj->layer->evas->output.h);
400 _evas_map_calc_map_geometry(obj);
401 /* This is a bit heavy handed, but it fixes the case of same geometry, but
402 * changed colour or UV settings. */
403 evas_object_change(obj);
407 evas_object_map_enable_get(const Evas_Object *obj)
409 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
412 return obj->cur.usemap;
417 evas_object_map_source_set(Evas_Object *obj, Evas_Object *src)
419 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
422 (void)src; /* method still needs to be implemented. */
426 evas_object_map_source_get(const Evas_Object *obj)
428 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
435 evas_object_map_set(Evas_Object *obj, const Evas_Map *map)
437 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
445 if (obj->cur.map->surface)
447 obj->layer->evas->engine.func->image_map_surface_free
448 (obj->layer->evas->engine.data.output,
449 obj->cur.map->surface);
450 obj->cur.map->surface = NULL;
452 obj->prev.geometry = obj->cur.map->normal_geometry;
455 _evas_map_free(obj, obj->cur.map);
457 evas_object_mapped_clip_across_mark(obj);
460 _evas_map_free(obj, obj->cur.map);
462 if (!obj->cur.usemap) _evas_map_calc_geom_change(obj);
463 else _evas_map_calc_map_geometry(obj);
466 evas_object_mapped_clip_across_mark(obj);
467 //FIXME: Since the last frame is not updated when map is
468 //disabled, afterimage problem is happened in s/w
469 //rendering. Need to find out the fundamental reason
471 evas_damage_rectangle_add(obj->layer->evas,
474 obj->layer->evas->output.w,
475 obj->layer->evas->output.h);
481 if ((obj->cur.map) && (obj->cur.map->count == map->count))
483 Evas_Map *omap = obj->cur.map;
484 obj->cur.map = _evas_map_new(map->count);
485 memcpy(obj->cur.map, omap, sizeof(Evas_Map) + (map->count * sizeof(Evas_Map_Point)));
486 _evas_map_copy(obj->cur.map, map);
487 if (obj->prev.map == omap) obj->prev.map = NULL;
492 if (obj->cur.map) evas_map_free(obj->cur.map);
493 obj->cur.map = _evas_map_dup(map);
495 evas_object_mapped_clip_across_mark(obj);
497 _evas_map_calc_map_geometry(obj);
500 EAPI const Evas_Map *
501 evas_object_map_get(const Evas_Object *obj)
503 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
511 evas_map_new(int count)
515 ERR("map point count (%i) != 4 is unsupported!", count);
519 return _evas_map_new(count);
523 evas_map_smooth_set(Evas_Map *m, Eina_Bool enabled)
525 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
533 evas_map_smooth_get(const Evas_Map *m)
535 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
543 evas_map_alpha_set(Evas_Map *m, Eina_Bool enabled)
545 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
553 evas_map_alpha_get(const Evas_Map *m)
555 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
563 evas_map_dup(const Evas_Map *m)
565 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
569 return _evas_map_dup(m);
573 evas_map_free(Evas_Map *m)
575 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
579 _evas_map_free(NULL, m);
583 evas_map_count_get(const Evas_Map *m)
585 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
593 evas_map_point_coord_set(Evas_Map *m, int idx, Evas_Coord x, Evas_Coord y, Evas_Coord z)
595 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
601 if (idx >= m->count) return;
609 evas_map_point_coord_get(const Evas_Map *m, int idx, Evas_Coord *x, Evas_Coord *y, Evas_Coord *z)
611 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
615 const Evas_Map_Point *p;
617 if (idx >= m->count) goto error;
631 evas_map_point_image_uv_set(Evas_Map *m, int idx, double u, double v)
633 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
639 if (idx >= m->count) return;
646 evas_map_point_image_uv_get(const Evas_Map *m, int idx, double *u, double *v)
648 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
652 const Evas_Map_Point *p;
654 if (idx >= m->count) goto error;
666 evas_map_point_color_set(Evas_Map *m, int idx, int r, int g, int b, int a)
668 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
674 if (idx >= m->count) return;
683 evas_map_point_color_get(const Evas_Map *m, int idx, int *r, int *g, int *b, int *a)
685 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
689 const Evas_Map_Point *p;
691 if (idx >= m->count) return;
700 evas_map_util_points_populate_from_object_full(Evas_Map *m, const Evas_Object *obj, Evas_Coord z)
702 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
708 ERR("map has count=%d where 4 was expected.", m->count);
711 _evas_map_util_points_populate(m, obj->cur.geometry.x, obj->cur.geometry.y,
712 obj->cur.geometry.w, obj->cur.geometry.h, z);
716 evas_map_util_points_populate_from_object(Evas_Map *m, const Evas_Object *obj)
718 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
722 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
728 ERR("map has count=%d where 4 was expected.", m->count);
731 _evas_map_util_points_populate(m, obj->cur.geometry.x, obj->cur.geometry.y,
732 obj->cur.geometry.w, obj->cur.geometry.h, 0);
736 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)
738 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
744 ERR("map has count=%d where 4 was expected.", m->count);
747 _evas_map_util_points_populate(m, x, y, w, h, z);
751 evas_map_util_points_color_set(Evas_Map *m, int r, int g, int b, int a)
753 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
757 Evas_Map_Point *p, *p_end;
760 p_end = p + m->count;
761 for (; p < p_end; p++)
771 evas_map_util_rotate(Evas_Map *m, double degrees, Evas_Coord cx, Evas_Coord cy)
773 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
777 double r = (degrees * M_PI) / 180.0;
778 Evas_Map_Point *p, *p_end;
781 p_end = p + m->count;
783 for (; p < p_end; p++)
792 x = xx - (y * sin(r));
793 y = yy + (y * cos(r));
795 p->px = p->x = x + cx;
796 p->py = p->y = y + cy;
801 evas_map_util_zoom(Evas_Map *m, double zoomx, double zoomy, Evas_Coord cx, Evas_Coord cy)
803 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
807 Evas_Map_Point *p, *p_end;
810 p_end = p + m->count;
812 for (; p < p_end; p++)
819 x = (((double)x) * zoomx);
820 y = (((double)y) * zoomy);
822 p->px = p->x = x + cx;
823 p->py = p->y = y + cy;
828 evas_map_util_3d_rotate(Evas_Map *m, double dx, double dy, double dz,
829 Evas_Coord cx, Evas_Coord cy, Evas_Coord cz)
831 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
835 double rz = (dz * M_PI) / 180.0;
836 double rx = (dx * M_PI) / 180.0;
837 double ry = (dy * M_PI) / 180.0;
838 Evas_Map_Point *p, *p_end;
841 p_end = p + m->count;
843 for (; p < p_end; p++)
845 double x, y, z, xx, yy, zz;
855 x = xx - (y * sin(rz));
856 y = yy + (y * cos(rz));
863 x = xx - (z * sin(ry));
864 z = zz + (z * cos(ry));
871 z = zz - (y * sin(rx));
872 y = yy + (y * cos(rx));
875 p->px = p->x = x + cx;
876 p->py = p->y = y + cy;
882 evas_map_util_3d_lighting(Evas_Map *m,
883 Evas_Coord lx, Evas_Coord ly, Evas_Coord lz,
884 int lr, int lg, int lb, int ar, int ag, int ab)
886 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
892 for (i = 0; i < m->count; i++)
895 double nx, ny, nz, x1, y1, z1, x2, y2, z2, ln, br;
896 int h, j, mr, mg, mb;
902 h = (i - 1 + 4) % 4 + (i & ~0x3); // prev point
903 j = (i + 1) % 4 + (i & ~0x3); // next point
905 x1 = m->points[h].x - x;
906 y1 = m->points[h].y - y;
907 z1 = m->points[h].z - z;
909 x2 = m->points[j].x - x;
910 y2 = m->points[j].y - y;
911 z2 = m->points[j].z - z;
912 nx = (y1 * z2) - (z1 * y2);
913 ny = (z1 * x2) - (x1 * z2);
914 nz = (x1 * y2) - (y1 * x2);
916 ln = (nx * nx) + (ny * ny) + (nz * nz);
926 // calc point -> light vector
931 ln = (x * x) + (y * y) + (z * z);
941 // brightness - tan (0.0 -> 1.0 brightness really)
942 br = (nx * x) + (ny * y) + (nz * z);
943 if (br < 0.0) br = 0.0;
945 mr = ar + ((lr - ar) * br);
946 mg = ag + ((lg - ag) * br);
947 mb = ab + ((lb - ab) * br);
948 if (m->points[i].a != 255)
950 mr = (mr * m->points[i].a) / 255;
951 mg = (mg * m->points[i].a) / 255;
952 mb = (mb * m->points[i].a) / 255;
954 m->points[i].r = (m->points[i].r * mr) / 255;
955 m->points[i].g = (m->points[i].g * mg) / 255;
956 m->points[i].b = (m->points[i].b * mb) / 255;
961 evas_map_util_3d_perspective(Evas_Map *m,
962 Evas_Coord px, Evas_Coord py,
963 Evas_Coord z0, Evas_Coord foc)
965 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
969 Evas_Map_Point *p, *p_end;
972 p_end = p + m->count;
979 if (foc <= 0) return;
981 for (; p < p_end; p++)
988 zz = ((p->z - z0) + foc);
1002 evas_map_util_clockwise_get(Evas_Map *m)
1004 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
1011 if (m->count < 3) return EINA_FALSE;
1014 for (i = 0; i < m->count; i++)
1016 j = (i + 1) % m->count;
1017 k = (i + 2) % m->count;
1019 ((m->points[j].x - m->points[i].x) *
1020 (m->points[k].y - m->points[j].y))
1022 ((m->points[j].y - m->points[i].y) *
1023 (m->points[k].x - m->points[j].x));
1025 else if (c > 0) count++;
1027 if (count > 0) return EINA_TRUE;