1 #include "evas_map.h"
2
3 static void
_evas_map_calc_geom_change(Evas_Object * eo_obj)4 _evas_map_calc_geom_change(Evas_Object *eo_obj)
5 {
6 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
7 if (!obj) return;
8 evas_object_change(eo_obj, obj);
9 evas_object_clip_dirty(eo_obj, obj);
10 if (!(obj->layer->evas->is_frozen))
11 {
12 evas_object_recalc_clippees(obj);
13 if (!obj->is_smart && obj->cur->visible)
14 {
15 _evas_canvas_event_pointer_in_list_mouse_move_feed(obj->layer->evas, NULL, eo_obj, obj, 1, 1,
16 EINA_TRUE, NULL);
17 }
18 }
19 evas_object_inform_call_move(eo_obj, obj);
20 evas_object_inform_call_resize(eo_obj, obj);
21 }
22
23 void
_evas_map_calc_map_geometry(Evas_Object * eo_obj)24 _evas_map_calc_map_geometry(Evas_Object *eo_obj)
25 {
26 Evas_Coord x1, x2, yy1, yy2;
27 const Evas_Map_Point *p, *p_end;
28 Eina_Bool ch = EINA_FALSE;
29
30 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
31 if (!obj) return;
32 if (!obj->map->cur.map) return;
33 if (obj->map->prev.map)
34 {
35 if (obj->map->prev.map != obj->map->cur.map)
36 {
37 // FIXME: this causes an infinite loop somewhere... hard to debug
38 if (obj->map->prev.map->count == obj->map->cur.map->count)
39 {
40 const Evas_Map_Point *p2;
41
42 p = obj->map->cur.map->points;
43 p2 = obj->map->prev.map->points;
44 if (memcmp(p, p2, sizeof(Evas_Map_Point) *
45 obj->map->prev.map->count) != 0)
46 ch = EINA_TRUE;
47 if (!ch)
48 {
49 EINA_COW_WRITE_BEGIN(evas_object_map_cow, obj->map, Evas_Object_Map_Data, map_write)
50 {
51 if (map_write->cache_map) evas_map_free(map_write->cache_map);
52 map_write->cache_map = map_write->cur.map;
53 map_write->cur.map = map_write->prev.map;
54 }
55 EINA_COW_WRITE_END(evas_object_map_cow, obj->map, map_write);
56 }
57 }
58 else
59 ch = EINA_TRUE;
60 }
61 }
62 else
63 ch = EINA_TRUE;
64
65 p = obj->map->cur.map->points;
66 p_end = p + obj->map->cur.map->count;
67 x1 = x2 = lround(p->x);
68 yy1 = yy2 = lround(p->y);
69 p++;
70 for (; p < p_end; p++)
71 {
72 Evas_Coord x, y;
73
74 x = lround(p->x);
75 y = lround(p->y);
76 if (x < x1) x1 = x;
77 if (x > x2) x2 = x;
78 if (y < yy1) yy1 = y;
79 if (y > yy2) yy2 = y;
80 }
81 // this causes clip-out bugs now mapped objs canbe opaque!!!
82 // // add 1 pixel of fuzz around the map region to ensure updates are correct
83 // x1 -= 1; yy1 -= 1;
84 // x2 += 1; yy2 += 1;
85 if (obj->map->cur.map->normal_geometry.x != x1) ch = 1;
86 if (obj->map->cur.map->normal_geometry.y != yy1) ch = 1;
87 if (obj->map->cur.map->normal_geometry.w != (x2 - x1)) ch = 1;
88 if (obj->map->cur.map->normal_geometry.h != (yy2 - yy1)) ch = 1;
89 obj->map->cur.map->normal_geometry.x = x1;
90 obj->map->cur.map->normal_geometry.y = yy1;
91 obj->map->cur.map->normal_geometry.w = (x2 - x1);
92 obj->map->cur.map->normal_geometry.h = (yy2 - yy1);
93
94 /* if change_map is true, it means that the prev map data
95 did not render before. even though both prev and cur
96 has same map points we need to draw it */
97 obj->changed_map |= ch;
98
99 // This shouldn't really be needed, but without it we do have case
100 // where the clip is wrong when a map doesn't change, so always forcing
101 // it, as long as someone doesn't find a better fix.
102 evas_object_clip_dirty(eo_obj, obj);
103 if (ch) _evas_map_calc_geom_change(eo_obj);
104 }
105
106 static void
evas_object_map_move_sync(Evas_Object * eo_obj)107 evas_object_map_move_sync(Evas_Object *eo_obj)
108 {
109 Evas_Object_Protected_Data *obj;
110 Evas_Map *m;
111 Evas_Map_Point *p;
112 Evas_Coord diff_x, diff_y;
113 int i, count;
114
115 obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
116 if (!obj) return;
117
118 if ((!obj->map->cur.map->move_sync.enabled) ||
119 ((obj->map->cur.map->move_sync.diff_x == 0) &&
120 (obj->map->cur.map->move_sync.diff_y == 0)))
121 return;
122
123 m = obj->map->cur.map;
124 p = m->points;
125 count = m->count;
126 diff_x = m->move_sync.diff_x;
127 diff_y = m->move_sync.diff_y;
128
129 for (i = 0; i < count; i++, p++)
130 {
131 p->px += diff_x;
132 p->py += diff_y;
133 p->x += diff_x;
134 p->y += diff_y;
135 }
136 m->move_sync.diff_x = 0;
137 m->move_sync.diff_y = 0;
138
139 _evas_map_calc_map_geometry(eo_obj);
140 }
141
142 static void
_evas_map_init(Evas_Map * m,int count,Eina_Bool sync)143 _evas_map_init(Evas_Map *m, int count, Eina_Bool sync)
144 {
145 m->move_sync.enabled = sync;
146 m->count = count;
147 m->alpha = 1;
148 m->smooth = 1;
149 m->magic = MAGIC_MAP;
150 for (int i = 0; i < count; i++)
151 {
152 m->points[i].r = 255;
153 m->points[i].g = 255;
154 m->points[i].b = 255;
155 m->points[i].a = 255;
156 }
157 }
158
159 Evas_Map *
_evas_map_new(int count,Eina_Bool sync)160 _evas_map_new(int count, Eina_Bool sync)
161 {
162 Evas_Map *m;
163 int alloc;
164
165 /* Adjust allocation such that: at least 4 points, and always an even
166 * number: this allows the software engine to work efficiently */
167 alloc = (count < 4) ? 4 : count;
168 if (alloc & 0x1) alloc ++;
169
170 m = calloc(1, sizeof(Evas_Map) + (alloc * sizeof(Evas_Map_Point)));
171 if (!m) return NULL;
172 _evas_map_init(m, count, sync);
173 return m;
174 }
175
176 void
_evas_map_reset(Evas_Map * m)177 _evas_map_reset(Evas_Map *m)
178 {
179 int alloc, count;
180 Eina_Bool sync;
181
182 if (!m) return;
183
184 /* Adjust allocation such that: at least 4 points, and always an even
185 * number: this allows the software engine to work efficiently */
186 alloc = (m->count < 4) ? 4 : m->count;
187 if (alloc & 0x1) alloc ++;
188
189 count = m->count;
190 sync = m->move_sync.enabled;
191 memset(m, 0, sizeof(Evas_Map) + (alloc * sizeof(Evas_Map_Point)));
192 _evas_map_init(m, count, sync);
193 }
194
195 static inline Eina_Bool
_evas_map_copy(Evas_Map * dst,const Evas_Map * src)196 _evas_map_copy(Evas_Map *dst, const Evas_Map *src)
197 {
198 if (dst->count != src->count)
199 {
200 ERR("cannot copy map of different sizes: dst=%i, src=%i", dst->count, src->count);
201 return EINA_FALSE;
202 }
203 if (dst == src) return EINA_TRUE;
204 if (dst->points != src->points)
205 memcpy(dst->points, src->points, src->count * sizeof(Evas_Map_Point));
206 dst->smooth = src->smooth;
207 dst->alpha = src->alpha;
208 dst->move_sync = src->move_sync;
209 dst->persp = src->persp;
210 return EINA_TRUE;
211 }
212
213 static inline Evas_Map *
_evas_map_dup(const Evas_Map * orig)214 _evas_map_dup(const Evas_Map *orig)
215 {
216 Evas_Map *copy = _evas_map_new(orig->count, EINA_FALSE);
217 if (!copy) return NULL;
218 memcpy(copy->points, orig->points, orig->count * sizeof(Evas_Map_Point));
219 copy->smooth = orig->smooth;
220 copy->alpha = orig->alpha;
221 copy->move_sync = orig->move_sync;
222 copy->persp = orig->persp;
223 return copy;
224 }
225
226 static inline void
_evas_map_free(Evas_Object * eo_obj,Evas_Map * m)227 _evas_map_free(Evas_Object *eo_obj, Evas_Map *m)
228 {
229 if (eo_obj)
230 {
231 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
232 if ((obj) && (obj->map->spans))
233 {
234 obj->layer->evas->engine.func->image_map_clean(ENC, obj->map->spans);
235 EINA_COW_WRITE_BEGIN(evas_object_map_cow, obj->map, Evas_Object_Map_Data, map_write)
236 {
237 free(map_write->spans);
238 map_write->spans = NULL;
239 }
240 EINA_COW_WRITE_END(evas_object_map_cow, obj->map, map_write);
241 }
242 }
243 m->magic = 0;
244 free(m);
245 }
246
247 EAPI Eina_Bool
evas_map_coords_get(const Evas_Map * m,double x,double y,double * mx,double * my,int grab)248 evas_map_coords_get(const Evas_Map *m, double x, double y,
249 double *mx, double *my, int grab)
250 {
251 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
252 return EINA_FALSE;
253 MAGIC_CHECK_END();
254
255 if (m->count < 4) return EINA_FALSE;
256
257 Eina_Bool inside = evas_map_inside_get(m, x, y);
258 if ((!mx) && (!my)) return inside;
259
260 // FIXME: need to handle grab mode and extrapolate coords outside map
261 if (grab && !inside) return EINA_FALSE;
262
263 int i, j, edges, edge[m->count][2];
264 Eina_Bool douv = EINA_FALSE;
265 double xe[2];
266 double u[2] = { 0.0, 0.0 };
267 double v[2] = { 0.0, 0.0 };
268
269 /*
270 if (grab)
271 {
272 double ymin, ymax;
273
274 ymin = m->points[0].y;
275 ymax = m->points[0].y;
276 for (i = 1; i < m->count; i++)
277 {
278 if (m->points[i].y < ymin) ymin = m->points[i].y;
279 else if (m->points[i].y > ymax) ymax = m->points[i].y;
280 }
281 if (y <= ymin) y = ymin + 1;
282 if (y >= ymax) y = ymax - 1;
283 }
284 */
285 edges = EINA_FALSE;
286 for (i = 0; i < m->count; i++)
287 {
288 j = (i + 1) % m->count;
289 if ((m->points[i].y <= y) && (m->points[j].y > y))
290 {
291 edge[edges][0] = i;
292 edge[edges][1] = j;
293 edges++;
294 }
295 else if ((m->points[j].y <= y) && (m->points[i].y > y))
296 {
297 edge[edges][0] = j;
298 edge[edges][1] = i;
299 edges++;
300 }
301 }
302 if ((mx) || (my)) douv = EINA_TRUE;
303 for (i = 0; i < (edges - 1); i+= 2)
304 {
305 double yp, yd;
306
307 j = i + 1;
308 yd = m->points[edge[i][1]].y - m->points[edge[i][0]].y;
309 if (yd > 0)
310 {
311 yp = y - m->points[edge[i][0]].y;
312 xe[0] = m->points[edge[i][1]].x - m->points[edge[i][0]].x;
313 xe[0] = m->points[edge[i][0]].x + ((xe[0] * yp) / yd);
314 if (douv)
315 {
316 u[0] = m->points[edge[i][1]].u - m->points[edge[i][0]].u;
317 u[0] = m->points[edge[i][0]].u + ((u[0] * yp) / yd);
318 v[0] = m->points[edge[i][1]].v - m->points[edge[i][0]].v;
319 v[0] = m->points[edge[i][0]].v + ((v[0] * yp) / yd);
320 }
321 }
322 else
323 {
324 xe[0] = m->points[edge[i][0]].x;
325 if (douv)
326 {
327 u[0] = m->points[edge[i][0]].u;
328 v[0] = m->points[edge[i][0]].v;
329 }
330 }
331 yd = m->points[edge[j][1]].y - m->points[edge[j][0]].y;
332 if (yd > 0)
333 {
334 yp = y - m->points[edge[j][0]].y;
335 xe[1] = m->points[edge[j][1]].x - m->points[edge[j][0]].x;
336 xe[1] = m->points[edge[j][0]].x + ((xe[1] * yp) / yd);
337 if (douv)
338 {
339 u[1] = m->points[edge[j][1]].u - m->points[edge[j][0]].u;
340 u[1] = m->points[edge[j][0]].u + ((u[1] * yp) / yd);
341 v[1] = m->points[edge[j][1]].v - m->points[edge[j][0]].v;
342 v[1] = m->points[edge[j][0]].v + ((v[1] * yp) / yd);
343 }
344 }
345 else
346 {
347 xe[1] = m->points[edge[j][0]].x;
348 if (douv)
349 {
350 u[1] = m->points[edge[j][0]].u;
351 v[1] = m->points[edge[j][0]].v;
352 }
353 }
354 if (xe[0] > xe[1])
355 {
356 int ti;
357
358 ti = xe[0]; xe[0] = xe[1]; xe[1] = ti;
359 if (douv)
360 {
361 double td;
362
363 td = u[0]; u[0] = u[1]; u[1] = td;
364 td = v[0]; v[0] = v[1]; v[1] = td;
365 }
366 }
367 if ((x >= xe[0]) && (x < xe[1]))
368 {
369 if (douv)
370 {
371 if (mx)
372 *mx = u[0] + (((x - xe[0]) * (u[1] - u[0])) /
373 (xe[1] - xe[0]));
374 if (my)
375 *my = v[0] + (((x - xe[0]) * (v[1] - v[0])) /
376 (xe[1] - xe[0]));
377 }
378 return EINA_TRUE;
379 }
380 /*
381 if (grab)
382 {
383 if (douv)
384 {
385 if (mx)
386 *mx = u[0] + (((x - xe[0]) * (u[1] - u[0])) /
387 (xe[1] - xe[0]));
388 if (my)
389 *my = v[0] + (((x - xe[0]) * (v[1] - v[0])) /
390 (xe[1] - xe[0]));
391 }
392 return EINA_TRUE;
393 }
394 */
395 }
396 return EINA_FALSE;
397 }
398
399 Eina_Bool
evas_map_inside_get(const Evas_Map * m,Evas_Coord x,Evas_Coord y)400 evas_map_inside_get(const Evas_Map *m, Evas_Coord x, Evas_Coord y)
401 {
402 int i = 0, j = m->count - 1;
403 double pt1_x, pt1_y, pt2_x, pt2_y, tmp_x;
404 Eina_Bool inside = EINA_FALSE;
405
406 //Check the point inside the map coords by using Jordan curve theorem.
407 for (i = 0; i < m->count; i++)
408 {
409 pt1_x = m->points[i].x;
410 pt1_y = m->points[i].y;
411 pt2_x = m->points[j].x;
412 pt2_y = m->points[j].y;
413
414 //Is the point inside the map on y axis?
415 if (((y >= pt1_y) && (y < pt2_y)) || ((y >= pt2_y) && (y < pt1_y)))
416 {
417 //Check the point is left side of the line segment.
418 tmp_x = (pt1_x + ((pt2_x - pt1_x) / (pt2_y - pt1_y)) *
419 ((double)y - pt1_y));
420 if ((double)x < tmp_x) inside = !inside;
421 }
422 j = i;
423 }
424 return inside;
425 }
426
427 #if 0
428 static Eina_Bool
429 _evas_object_map_parent_check(Evas_Object *eo_parent)
430 {
431 const Eina_Inlist *list;
432 const Evas_Object_Protected_Data *o;
433
434 if (!eo_parent) return EINA_FALSE;
435 Evas_Object_Protected_Data *parent = efl_data_scope_get(eo_parent, EFL_CANVAS_OBJECT_CLASS);
436 if (!parent) return EINA_FALSE;
437 list = evas_object_smart_members_get_direct(parent->smart.parent);
438 EINA_INLIST_FOREACH(list, o)
439 if (o->map->cur.usemap) break;
440 if (o) return EINA_FALSE; /* Still some child have a map enable */
441 parent->child_has_map = EINA_FALSE;
442 _evas_object_map_parent_check(parent->smart.parent);
443 return EINA_TRUE;
444 }
445 #endif
446
447 void
_evas_object_map_enable_set(Eo * eo_obj,Evas_Object_Protected_Data * obj,Eina_Bool enabled)448 _evas_object_map_enable_set(Eo *eo_obj, Evas_Object_Protected_Data *obj,
449 Eina_Bool enabled)
450 {
451 Eina_Bool pchange = EINA_FALSE;
452
453 enabled = !!enabled;
454 if (obj->map->cur.usemap == enabled) return;
455 pchange = obj->changed;
456
457 evas_object_async_block(obj);
458 EINA_COW_WRITE_BEGIN(evas_object_map_cow, obj->map, Evas_Object_Map_Data, map_write)
459 map_write->cur.usemap = enabled;
460 EINA_COW_WRITE_END(evas_object_map_cow, obj->map, map_write);
461
462 if (enabled)
463 {
464 if (!obj->map->cur.map)
465 {
466 EINA_COW_WRITE_BEGIN(evas_object_map_cow, obj->map, Evas_Object_Map_Data, map_write)
467 map_write->cur.map = _evas_map_new(4, EINA_FALSE);
468 EINA_COW_WRITE_END(evas_object_map_cow, obj->map, map_write);
469 }
470 evas_object_mapped_clip_across_mark(eo_obj, obj);
471 // obj->map->cur.map->normal_geometry = obj->cur->geometry;
472 }
473 else
474 {
475 if (obj->map->surface)
476 {
477 EINA_COW_WRITE_BEGIN(evas_object_map_cow, obj->map, Evas_Object_Map_Data, map_write)
478 {
479 obj->layer->evas->engine.func->image_free(ENC, map_write->surface);
480 map_write->surface = NULL;
481 }
482 EINA_COW_WRITE_END(evas_object_map_cow, obj->map, map_write);
483 }
484 if (obj->map->cur.map)
485 {
486 _evas_map_calc_geom_change(eo_obj);
487 evas_object_mapped_clip_across_mark(eo_obj, obj);
488 }
489 }
490 _evas_map_calc_map_geometry(eo_obj);
491 /* This is a bit heavy handed, but it fixes the case of same geometry, but
492 * changed colour or UV settings. */
493 evas_object_change(eo_obj, obj);
494 if (!obj->changed_pchange) obj->changed_pchange = pchange;
495 obj->changed_map = EINA_TRUE;
496
497 if (enabled)
498 {
499 Evas_Object *eo_parents;
500 Evas_Object_Protected_Data *parents = NULL;
501 for (eo_parents = obj->smart.parent; eo_parents; eo_parents = parents->smart.parent)
502 {
503 parents = efl_data_scope_get(eo_parents, EFL_CANVAS_OBJECT_CLASS);
504 if (!parents) break;
505 parents->child_has_map = EINA_TRUE;
506 }
507 evas_object_update_bounding_box(eo_obj, obj, NULL);
508 }
509 else
510 {
511 evas_object_update_bounding_box(eo_obj, obj, NULL);
512 }
513 }
514
515 EAPI void
evas_object_map_enable_set(Eo * eo_obj,Eina_Bool enabled)516 evas_object_map_enable_set(Eo *eo_obj, Eina_Bool enabled)
517 {
518 Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj);
519
520 _evas_object_map_enable_set(eo_obj, obj, enabled);
521 }
522
523 EAPI Eina_Bool
evas_object_map_enable_get(const Eo * eo_obj)524 evas_object_map_enable_get(const Eo *eo_obj)
525 {
526 Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj, EINA_FALSE);
527
528 return obj->map->cur.usemap;
529 }
530
531 EAPI void
evas_object_map_set(Evas_Object * eo_obj,const Evas_Map * map)532 evas_object_map_set(Evas_Object *eo_obj, const Evas_Map *map)
533 {
534 Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj);
535
536 evas_object_async_block(obj);
537
538 // check if the new map and current map attributes are same
539 if (map && obj->map->cur.map &&
540 (obj->map->cur.map->alpha == map->alpha) &&
541 (obj->map->cur.map->smooth == map->smooth) &&
542 (obj->map->cur.map->move_sync.enabled == map->move_sync.enabled) &&
543 (obj->map->cur.map->move_sync.diff_x == map->move_sync.diff_x) &&
544 (obj->map->cur.map->move_sync.diff_y == map->move_sync.diff_y) &&
545 (obj->map->cur.map->count == map->count))
546 {
547 const Evas_Map_Point *p1, *p2;
548 p1 = obj->map->cur.map->points;
549 p2 = map->points;
550 if (!memcmp(p1, p2, sizeof(Evas_Map_Point) * map->count) &&
551 !memcmp(&map->persp, &obj->map->cur.map->persp, sizeof(map->persp)))
552 return;
553 }
554 /* changed_pchange means map's change.
555 * This flag will be used to decide whether to redraw the map surface.
556 * And value of flag would be EINA_FALSE after rendering. */
557 obj->changed_pchange = EINA_TRUE;
558
559 if ((!map) || (map->count < 4))
560 {
561 if (obj->map->surface)
562 {
563 EINA_COW_WRITE_BEGIN(evas_object_map_cow, obj->map, Evas_Object_Map_Data, map_write)
564 {
565 obj->layer->evas->engine.func->image_free(ENC, map_write->surface);
566 map_write->surface = NULL;
567 }
568 EINA_COW_WRITE_END(evas_object_map_cow, obj->map, map_write);
569 }
570 if (obj->map->cur.map)
571 {
572 obj->changed_map = EINA_TRUE;
573
574 EINA_COW_STATE_WRITE_BEGIN(obj, state_write, prev)
575 {
576 state_write->geometry = obj->map->cur.map->normal_geometry;
577 }
578 EINA_COW_STATE_WRITE_END(obj, state_write, prev);
579
580 EINA_COW_WRITE_BEGIN(evas_object_map_cow, obj->map, Evas_Object_Map_Data, map_write)
581 {
582 if (map_write->prev.map == map_write->cur.map)
583 map_write->cur.map = NULL;
584 else if (!map_write->cache_map)
585 {
586 map_write->cache_map = map_write->cur.map;
587 map_write->cur.map = NULL;
588 }
589 else
590 {
591 _evas_map_free(eo_obj, map_write->cur.map);
592 map_write->cur.map = NULL;
593 }
594 }
595 EINA_COW_WRITE_END(evas_object_map_cow, obj->map, map_write);
596
597 if (!obj->map->prev.map)
598 {
599 evas_object_update_bounding_box(eo_obj, obj, NULL);
600 evas_object_mapped_clip_across_mark(eo_obj, obj);
601 return;
602 }
603
604 if (!obj->map->cur.usemap) _evas_map_calc_geom_change(eo_obj);
605 else _evas_map_calc_map_geometry(eo_obj);
606 if (obj->map->cur.usemap)
607 evas_object_mapped_clip_across_mark(eo_obj, obj);
608 }
609 evas_object_update_bounding_box(eo_obj, obj, NULL);
610 return;
611 }
612
613 if (obj->map->prev.map != NULL &&
614 obj->map->prev.map == obj->map->cur.map)
615 {
616 EINA_COW_WRITE_BEGIN(evas_object_map_cow, obj->map, Evas_Object_Map_Data, map_write)
617 map_write->cur.map = NULL;
618 EINA_COW_WRITE_END(evas_object_map_cow, obj->map, map_write);
619 }
620
621 if (!obj->map->cur.map && obj->map->cache_map)
622 {
623 EINA_COW_WRITE_BEGIN(evas_object_map_cow, obj->map, Evas_Object_Map_Data, map_write)
624 {
625 map_write->cur.map = map_write->cache_map;
626 map_write->cache_map = NULL;
627 }
628 EINA_COW_WRITE_END(evas_object_map_cow, obj->map, map_write);
629 }
630
631 // We do have the same exact count of point in this map, so just copy it
632 if ((obj->map->cur.map) && (obj->map->cur.map->count == map->count))
633 _evas_map_copy(obj->map->cur.map, map);
634 else
635 {
636 if (obj->map->cur.map) _evas_map_free(eo_obj, obj->map->cur.map);
637 EINA_COW_WRITE_BEGIN(evas_object_map_cow, obj->map, Evas_Object_Map_Data, map_write)
638 map_write->cur.map = _evas_map_dup(map);
639 EINA_COW_WRITE_END(evas_object_map_cow, obj->map, map_write);
640 if (obj->map->cur.usemap)
641 evas_object_mapped_clip_across_mark(eo_obj, obj);
642 }
643
644 evas_object_update_bounding_box(eo_obj, obj, NULL);
645 _evas_map_calc_map_geometry(eo_obj);
646 }
647
648 EAPI const Evas_Map *
evas_object_map_get(const Evas_Object * eo_obj)649 evas_object_map_get(const Evas_Object *eo_obj)
650 {
651 Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN((Eo *) eo_obj, NULL);
652
653 evas_object_async_block(obj);
654 return obj->map->cur.map;
655 }
656
657 EAPI Evas_Map *
evas_map_new(int count)658 evas_map_new(int count)
659 {
660 if ((count <= 0) || (count % 4 != 0))
661 {
662 ERR("map point count (%i) should be multiples of 4!", count);
663 return NULL;
664 }
665
666 return _evas_map_new(count, EINA_FALSE);
667 }
668
669 EAPI void
evas_map_smooth_set(Evas_Map * m,Eina_Bool enabled)670 evas_map_smooth_set(Evas_Map *m, Eina_Bool enabled)
671 {
672 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
673 return;
674 MAGIC_CHECK_END();
675
676 m->smooth = enabled;
677 }
678
679 EAPI Eina_Bool
evas_map_smooth_get(const Evas_Map * m)680 evas_map_smooth_get(const Evas_Map *m)
681 {
682 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
683 return EINA_FALSE;
684 MAGIC_CHECK_END();
685
686 return m->smooth;
687 }
688
689 EAPI void
evas_map_alpha_set(Evas_Map * m,Eina_Bool enabled)690 evas_map_alpha_set(Evas_Map *m, Eina_Bool enabled)
691 {
692 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
693 return;
694 MAGIC_CHECK_END();
695
696 m->alpha = enabled;
697 }
698
699 EAPI Eina_Bool
evas_map_alpha_get(const Evas_Map * m)700 evas_map_alpha_get(const Evas_Map *m)
701 {
702 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
703 return EINA_FALSE;
704 MAGIC_CHECK_END();
705
706 return m->alpha;
707 }
708
709 EAPI void
evas_map_util_object_move_sync_set(Evas_Map * m,Eina_Bool enabled)710 evas_map_util_object_move_sync_set(Evas_Map *m, Eina_Bool enabled)
711 {
712 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
713 return;
714 MAGIC_CHECK_END();
715
716 if (!enabled)
717 {
718 m->move_sync.diff_x = 0;
719 m->move_sync.diff_y = 0;
720 }
721 m->move_sync.enabled = !!enabled;
722 }
723
724 EAPI Eina_Bool
evas_map_util_object_move_sync_get(const Evas_Map * m)725 evas_map_util_object_move_sync_get(const Evas_Map *m)
726 {
727 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
728 return EINA_FALSE;
729 MAGIC_CHECK_END();
730
731 return m->move_sync.enabled;
732 }
733
734 EAPI Evas_Map *
evas_map_dup(const Evas_Map * m)735 evas_map_dup(const Evas_Map *m)
736 {
737 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
738 return NULL;
739 MAGIC_CHECK_END();
740
741 return _evas_map_dup(m);
742 }
743
744 EAPI void
evas_map_free(Evas_Map * m)745 evas_map_free(Evas_Map *m)
746 {
747 if (!m) return;
748 _evas_map_free(NULL, m);
749 }
750
751 EAPI int
evas_map_count_get(const Evas_Map * m)752 evas_map_count_get(const Evas_Map *m)
753 {
754 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
755 return -1;
756 MAGIC_CHECK_END();
757
758 return m->count;
759 }
760
761 /* FIXME: coordinates should be float/double for accuracy.
762 Rotation center position will be flickered by rounding problem.
763 Now fixed in EO APIs.
764 */
765 EAPI void
evas_map_point_coord_set(Evas_Map * m,int idx,Evas_Coord x,Evas_Coord y,Evas_Coord z)766 evas_map_point_coord_set(Evas_Map *m, int idx, Evas_Coord x, Evas_Coord y, Evas_Coord z)
767 {
768 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
769 return;
770 MAGIC_CHECK_END();
771
772 _map_point_coord_set(m, idx, x, y, z);
773 }
774
775 EAPI void
evas_map_point_coord_get(const Evas_Map * m,int idx,Evas_Coord * x,Evas_Coord * y,Evas_Coord * z)776 evas_map_point_coord_get(const Evas_Map *m, int idx, Evas_Coord *x, Evas_Coord *y, Evas_Coord *z)
777 {
778 double dx, dy, dz;
779
780 _map_point_coord_get(m, idx, &dx, &dy, &dz);
781 if (x) *x = lround(dx);
782 if (y) *y = lround(dy);
783 if (z) *z = lround(dz);
784 }
785
786 EAPI void
evas_map_point_image_uv_set(Evas_Map * m,int idx,double u,double v)787 evas_map_point_image_uv_set(Evas_Map *m, int idx, double u, double v)
788 {
789 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
790 return;
791 MAGIC_CHECK_END();
792
793 Evas_Map_Point *p;
794
795 if ((idx < 0) || (idx >= m->count)) return;
796 p = m->points + idx;
797 p->u = u;
798 p->v = v;
799 }
800
801 EAPI void
evas_map_point_image_uv_get(const Evas_Map * m,int idx,double * u,double * v)802 evas_map_point_image_uv_get(const Evas_Map *m, int idx, double *u, double *v)
803 {
804 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
805 goto error;
806 MAGIC_CHECK_END();
807
808 const Evas_Map_Point *p;
809
810 if ((idx < 0) || (idx >= m->count)) goto error;
811 p = m->points + idx;
812 if (u) *u = p->u;
813 if (v) *v = p->v;
814 return;
815
816 error:
817 if (u) *u = 0.0;
818 if (v) *v = 0.0;
819 }
820
821 EAPI void
evas_map_point_color_set(Evas_Map * m,int idx,int r,int g,int b,int a)822 evas_map_point_color_set(Evas_Map *m, int idx, int r, int g, int b, int a)
823 {
824 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
825 return;
826 MAGIC_CHECK_END();
827
828 Evas_Map_Point *p;
829
830 if ((idx < 0) || (idx >= m->count)) return;
831 p = m->points + idx;
832 p->r = r;
833 p->g = g;
834 p->b = b;
835 p->a = a;
836 }
837
838 EAPI void
evas_map_point_color_get(const Evas_Map * m,int idx,int * r,int * g,int * b,int * a)839 evas_map_point_color_get(const Evas_Map *m, int idx, int *r, int *g, int *b, int *a)
840 {
841 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
842 return;
843 MAGIC_CHECK_END();
844
845 const Evas_Map_Point *p;
846
847 if ((idx < 0) || (idx >= m->count)) goto error;
848 p = m->points + idx;
849 if (r) *r = p->r;
850 if (g) *g = p->g;
851 if (b) *b = p->b;
852 if (a) *a = p->a;
853 return;
854
855 error:
856 if (r) *r = 255;
857 if (g) *g = 255;
858 if (b) *b = 255;
859 if (a) *a = 255;
860 }
861
862 EAPI void
evas_map_util_points_populate_from_object_full(Evas_Map * m,const Evas_Object * eo_obj,Evas_Coord z)863 evas_map_util_points_populate_from_object_full(Evas_Map *m, const Evas_Object *eo_obj, Evas_Coord z)
864 {
865 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
866 return;
867 MAGIC_CHECK_END();
868
869 MAGIC_CHECK(eo_obj, Evas_Object, MAGIC_OBJ);
870 return;
871 MAGIC_CHECK_END();
872 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
873
874 if (!obj) return;
875 if (m->count != 4)
876 {
877 ERR("map has count=%d where 4 was expected.", m->count);
878 return;
879 }
880 _evas_map_util_points_populate(m, obj->cur->geometry.x, obj->cur->geometry.y,
881 obj->cur->geometry.w, obj->cur->geometry.h, z);
882 }
883
884 EAPI void
evas_map_util_points_populate_from_object(Evas_Map * m,const Evas_Object * eo_obj)885 evas_map_util_points_populate_from_object(Evas_Map *m, const Evas_Object *eo_obj)
886 {
887 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
888 return;
889 MAGIC_CHECK_END();
890
891 MAGIC_CHECK(eo_obj, Evas_Object, MAGIC_OBJ);
892 return;
893 MAGIC_CHECK_END();
894 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
895
896 if (!obj) return;
897 if (m->count != 4)
898 {
899 ERR("map has count=%d where 4 was expected.", m->count);
900 return;
901 }
902 _evas_map_util_points_populate(m, obj->cur->geometry.x, obj->cur->geometry.y,
903 obj->cur->geometry.w, obj->cur->geometry.h, 0);
904 }
905
906 EAPI void
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)907 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)
908 {
909 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
910 return;
911 MAGIC_CHECK_END();
912
913 if (m->count != 4)
914 {
915 ERR("map has count=%d where 4 was expected.", m->count);
916 return;
917 }
918 _evas_map_util_points_populate(m, x, y, w, h, z);
919 }
920
921 EAPI void
evas_map_util_points_color_set(Evas_Map * m,int r,int g,int b,int a)922 evas_map_util_points_color_set(Evas_Map *m, int r, int g, int b, int a)
923 {
924 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
925 return;
926 MAGIC_CHECK_END();
927
928 Evas_Map_Point *p, *p_end;
929
930 p = m->points;
931 p_end = p + m->count;
932 for (; p < p_end; p++)
933 {
934 p->r = r;
935 p->g = g;
936 p->b = b;
937 p->a = a;
938 }
939 }
940
941 void
_map_util_rotate(Evas_Map * m,double degrees,double cx,double cy)942 _map_util_rotate(Evas_Map *m, double degrees, double cx, double cy)
943 {
944 double r = (degrees * M_PI) / 180.0;
945 Evas_Map_Point *p, *p_end;
946
947 p = m->points;
948 p_end = p + m->count;
949
950 for (; p < p_end; p++)
951 {
952 double x, y, xx, yy;
953
954 x = p->x - cx;
955 y = p->y - cy;
956
957 xx = x * cos(r);
958 yy = x * sin(r);
959 x = xx - (y * sin(r));
960 y = yy + (y * cos(r));
961
962 p->px = p->x = x + cx;
963 p->py = p->y = y + cy;
964 }
965 }
966
967 EAPI void
evas_map_util_rotate(Evas_Map * m,double degrees,Evas_Coord cx,Evas_Coord cy)968 evas_map_util_rotate(Evas_Map *m, double degrees, Evas_Coord cx, Evas_Coord cy)
969 {
970 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
971 return;
972 MAGIC_CHECK_END();
973
974 _map_util_rotate(m, degrees, (double) cx, (double) cy);
975 }
976
977 void
_map_util_zoom(Evas_Map * m,double zoomx,double zoomy,double cx,double cy)978 _map_util_zoom(Evas_Map *m, double zoomx, double zoomy, double cx, double cy)
979 {
980 Evas_Map_Point *p, *p_end;
981
982 p = m->points;
983 p_end = p + m->count;
984
985 for (; p < p_end; p++)
986 {
987 double x, y;
988
989 x = p->x - cx;
990 y = p->y - cy;
991
992 x *= zoomx;
993 y *= zoomy;
994
995 p->px = p->x = x + cx;
996 p->py = p->y = y + cy;
997 }
998 }
999
1000 EAPI void
evas_map_util_zoom(Evas_Map * m,double zoomx,double zoomy,Evas_Coord cx,Evas_Coord cy)1001 evas_map_util_zoom(Evas_Map *m, double zoomx, double zoomy, Evas_Coord cx, Evas_Coord cy)
1002 {
1003 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
1004 return;
1005 MAGIC_CHECK_END();
1006
1007 _map_util_zoom(m, zoomx, zoomy, (double) cx, (double) cy);
1008 }
1009
1010 void
_map_util_translate(Evas_Map * m,double dx,double dy,double dz)1011 _map_util_translate(Evas_Map *m, double dx, double dy, double dz)
1012 {
1013 Evas_Map_Point *p, *p_end;
1014
1015 p = m->points;
1016 p_end = p + m->count;
1017
1018 for (; p < p_end; p++)
1019 {
1020 p->px = (p->x += dx);
1021 p->py = (p->y += dy);
1022 p->z += dz;
1023 }
1024 }
1025
1026 void
_map_util_3d_rotate(Evas_Map * m,double dx,double dy,double dz,double cx,double cy,double cz)1027 _map_util_3d_rotate(Evas_Map *m, double dx, double dy, double dz,
1028 double cx, double cy, double cz)
1029 {
1030 double rz = (dz * M_PI) / 180.0;
1031 double rx = (dx * M_PI) / 180.0;
1032 double ry = (dy * M_PI) / 180.0;
1033 Evas_Map_Point *p, *p_end;
1034
1035 p = m->points;
1036 p_end = p + m->count;
1037
1038 for (; p < p_end; p++)
1039 {
1040 double x, y, z, xx, yy, zz;
1041
1042 x = p->x - cx;
1043 y = p->y - cy;
1044 z = p->z - cz;
1045
1046 if (!EINA_DBL_EQ(rz, 0.0))
1047 {
1048 xx = x * cos(rz);
1049 yy = x * sin(rz);
1050 x = xx - (y * sin(rz));
1051 y = yy + (y * cos(rz));
1052 }
1053
1054 if (!EINA_DBL_EQ(ry, 0.0))
1055 {
1056 xx = x * cos(ry);
1057 zz = x * sin(ry);
1058 x = xx - (z * sin(ry));
1059 z = zz + (z * cos(ry));
1060 }
1061
1062 if (!EINA_DBL_EQ(rx, 0.0))
1063 {
1064 zz = z * cos(rx);
1065 yy = z * sin(rx);
1066 z = zz - (y * sin(rx));
1067 y = yy + (y * cos(rx));
1068 }
1069
1070 p->px = p->x = x + cx;
1071 p->py = p->y = y + cy;
1072 p->z = z + cz;
1073 }
1074 }
1075
1076 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)1077 evas_map_util_3d_rotate(Evas_Map *m, double dx, double dy, double dz,
1078 Evas_Coord cx, Evas_Coord cy, Evas_Coord cz)
1079 {
1080 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
1081 return;
1082 MAGIC_CHECK_END();
1083
1084 _map_util_3d_rotate(m, dx, dy, dz, (double) cx, (double) cy, (double) cz);
1085 }
1086
1087 void
_map_util_quat_rotate(Evas_Map * m,double qx,double qy,double qz,double qw,double cx,double cy,double cz)1088 _map_util_quat_rotate(Evas_Map *m, double qx, double qy, double qz,
1089 double qw, double cx, double cy, double cz)
1090 {
1091 Eina_Quaternion q;
1092 Eina_Point_3D c;
1093
1094 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
1095 return;
1096 MAGIC_CHECK_END();
1097
1098 Evas_Map_Point *p, *p_end;
1099
1100 p = m->points;
1101 p_end = p + m->count;
1102
1103 q.x = qx;
1104 q.y = qy;
1105 q.z = qz;
1106 q.w = qw;
1107
1108 c.x = cx;
1109 c.y = cy;
1110 c.z = cz;
1111
1112 for (; p < p_end; p++)
1113 {
1114 Eina_Point_3D current;
1115
1116 current.x = p->x;
1117 current.y = p->y;
1118 current.z = p->z;
1119
1120 eina_quaternion_rotate(¤t, &c, &q);
1121
1122 p->px = p->x = current.x;
1123 p->py = p->y = current.y;
1124 p->z = current.z;
1125 }
1126 }
1127
1128 EAPI void
evas_map_util_quat_rotate(Evas_Map * m,double qx,double qy,double qz,double qw,double cx,double cy,double cz)1129 evas_map_util_quat_rotate(Evas_Map *m, double qx, double qy, double qz,
1130 double qw, double cx, double cy, double cz)
1131 {
1132 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
1133 return;
1134 MAGIC_CHECK_END();
1135
1136 _map_util_quat_rotate(m, qx, qy, qz, qw, cx, cy, cz);
1137 }
1138
1139 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)1140 _map_util_3d_lighting(Evas_Map *m,
1141 double lx, double ly, double lz,
1142 int lr, int lg, int lb, int ar, int ag, int ab)
1143 {
1144 int i;
1145
1146 for (i = 0; i < m->count; i++)
1147 {
1148 double x, y, z;
1149 double nx, ny, nz, x1, yy1, z1, x2, yy2, z2, ln, br;
1150 int h, j, mr, mg, mb;
1151
1152 x = m->points[i].x;
1153 y = m->points[i].y;
1154 z = m->points[i].z;
1155 // calc normal
1156 h = (i - 1 + 4) % 4 + (i & ~0x3); // prev point
1157 j = (i + 1) % 4 + (i & ~0x3); // next point
1158
1159 x1 = m->points[h].x - x;
1160 yy1 = m->points[h].y - y;
1161 z1 = m->points[h].z - z;
1162
1163 x2 = m->points[j].x - x;
1164 yy2 = m->points[j].y - y;
1165 z2 = m->points[j].z - z;
1166 nx = (yy1 * z2) - (z1 * yy2);
1167 ny = (z1 * x2) - (x1 * z2);
1168 nz = (x1 * yy2) - (yy1 * x2);
1169
1170 ln = (nx * nx) + (ny * ny) + (nz * nz);
1171 ln = sqrt(ln);
1172
1173 if (!EINA_DBL_EQ(ln, 0.0))
1174 {
1175 nx /= ln;
1176 ny /= ln;
1177 nz /= ln;
1178 }
1179
1180 // calc point -> light vector
1181 x = lx - x;
1182 y = ly - y;
1183 z = lz - z;
1184
1185 ln = (x * x) + (y * y) + (z * z);
1186 ln = sqrt(ln);
1187
1188 if (!EINA_DBL_EQ(ln, 0.0))
1189 {
1190 x /= ln;
1191 y /= ln;
1192 z /= ln;
1193 }
1194
1195 // brightness - tan (0.0 -> 1.0 brightness really)
1196 br = (nx * x) + (ny * y) + (nz * z);
1197 if (br < 0.0) br = 0.0;
1198
1199 mr = ar + ((lr - ar) * br);
1200 mg = ag + ((lg - ag) * br);
1201 mb = ab + ((lb - ab) * br);
1202 if (m->points[i].a != 255)
1203 {
1204 mr = (mr * m->points[i].a) / 255;
1205 mg = (mg * m->points[i].a) / 255;
1206 mb = (mb * m->points[i].a) / 255;
1207 }
1208 m->points[i].r = (m->points[i].r * mr) / 255;
1209 m->points[i].g = (m->points[i].g * mg) / 255;
1210 m->points[i].b = (m->points[i].b * mb) / 255;
1211 }
1212 }
1213
1214 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)1215 evas_map_util_3d_lighting(Evas_Map *m,
1216 Evas_Coord lx, Evas_Coord ly, Evas_Coord lz,
1217 int lr, int lg, int lb, int ar, int ag, int ab)
1218 {
1219 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
1220 return;
1221 MAGIC_CHECK_END();
1222
1223 _map_util_3d_lighting(m, (double) lx, (double) ly, (double)
1224 lz, lr, lg, lb, ar, ag, ab);
1225 }
1226
1227 void
_map_util_3d_perspective(Evas_Map * m,double px,double py,double z0,double foc)1228 _map_util_3d_perspective(Evas_Map *m, double px, double py, double z0, double foc)
1229 {
1230 Evas_Map_Point *p, *p_end;
1231
1232 p = m->points;
1233 p_end = p + m->count;
1234
1235 m->persp.px = px;
1236 m->persp.py = py;
1237 m->persp.z0 = z0;
1238 m->persp.foc = foc;
1239
1240 if (foc <= 0) return;
1241
1242 for (; p < p_end; p++)
1243 {
1244 double x, y, zz;
1245
1246 x = p->x - px;
1247 y = p->y - py;
1248
1249 zz = ((p->z - z0) + foc);
1250
1251 if (zz > 0)
1252 {
1253 x = (x * foc) / zz;
1254 y = (y * foc) / zz;
1255 }
1256
1257 p->x = px + x;
1258 p->y = py + y;
1259 }
1260 }
1261
1262 EAPI void
evas_map_util_3d_perspective(Evas_Map * m,Evas_Coord px,Evas_Coord py,Evas_Coord z0,Evas_Coord foc)1263 evas_map_util_3d_perspective(Evas_Map *m,
1264 Evas_Coord px, Evas_Coord py,
1265 Evas_Coord z0, Evas_Coord foc)
1266 {
1267 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
1268 return;
1269 MAGIC_CHECK_END();
1270
1271 _map_util_3d_perspective(m, (double) px, (double) py, (double) z0, (double) foc);
1272 }
1273
1274 EAPI Eina_Bool
evas_map_util_clockwise_get(Evas_Map * m)1275 evas_map_util_clockwise_get(Evas_Map *m)
1276 {
1277 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
1278 return EINA_FALSE;
1279 MAGIC_CHECK_END();
1280
1281 int i, j, k, count;
1282 long long c;
1283
1284 if (m->count < 3) return EINA_FALSE;
1285
1286 count = 0;
1287 for (i = 0; i < m->count; i++)
1288 {
1289 j = (i + 1) % m->count;
1290 k = (i + 2) % m->count;
1291 c =
1292 ((m->points[j].x - m->points[i].x) *
1293 (m->points[k].y - m->points[j].y))
1294 -
1295 ((m->points[j].y - m->points[i].y) *
1296 (m->points[k].x - m->points[j].x));
1297 if (c < 0) count--;
1298 else if (c > 0) count++;
1299 }
1300 if (count > 0) return EINA_TRUE;
1301 return EINA_FALSE;
1302 }
1303
1304 /****************************************************************************/
1305 /* If the return value is true, the map surface should be redrawn. */
1306 /****************************************************************************/
1307 Eina_Bool
evas_object_map_update(Evas_Object * eo_obj,int x,int y,int imagew,int imageh,int uvw,int uvh)1308 evas_object_map_update(Evas_Object *eo_obj,
1309 int x, int y,
1310 int imagew, int imageh,
1311 int uvw, int uvh)
1312 {
1313 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
1314 const Evas_Map_Point *p, *p_end;
1315 RGBA_Map_Point *pts, *pt;
1316
1317 if (!obj) return EINA_FALSE;
1318 if (obj->map->spans)
1319 {
1320 if (obj->map->spans->x != x || obj->map->spans->y != y ||
1321 obj->map->spans->image.w != imagew || obj->map->spans->image.h != imageh ||
1322 obj->map->spans->uv.w != uvw || obj->map->spans->uv.h != uvh)
1323 obj->changed_map = EINA_TRUE;
1324 }
1325 else
1326 {
1327 obj->changed_map = EINA_TRUE;
1328 }
1329
1330 evas_object_map_move_sync(eo_obj);
1331
1332 if (!obj->changed_map) return EINA_FALSE;
1333
1334 if (obj->map->spans && obj->map->cur.map->count != obj->map->spans->count)
1335 {
1336 EINA_COW_WRITE_BEGIN(evas_object_map_cow, obj->map, Evas_Object_Map_Data, map_write)
1337 {
1338 if (map_write->spans)
1339 {
1340 // Destroy engine side spans
1341 free(map_write->spans);
1342 }
1343 map_write->spans = NULL;
1344 }
1345 EINA_COW_WRITE_END(evas_object_map_cow, obj->map, map_write);
1346 }
1347
1348 if (!obj->map->spans)
1349 {
1350 EINA_COW_WRITE_BEGIN(evas_object_map_cow, obj->map, Evas_Object_Map_Data, map_write)
1351 map_write->spans = calloc(1, sizeof (RGBA_Map) +
1352 sizeof (RGBA_Map_Point) * (map_write->cur.map->count - 1));
1353 EINA_COW_WRITE_END(evas_object_map_cow, obj->map, map_write);
1354 }
1355
1356 if (!obj->map->spans) return EINA_FALSE;
1357
1358 EINA_COW_WRITE_BEGIN(evas_object_map_cow, obj->map, Evas_Object_Map_Data, map_write)
1359 {
1360 map_write->spans->count = obj->map->cur.map->count;
1361 map_write->spans->x = x;
1362 map_write->spans->y = y;
1363 map_write->spans->uv.w = uvw;
1364 map_write->spans->uv.h = uvh;
1365 map_write->spans->image.w = imagew;
1366 map_write->spans->image.h = imageh;
1367
1368 pts = obj->map->spans->pts;
1369
1370 p = obj->map->cur.map->points;
1371 p_end = p + obj->map->cur.map->count;
1372 pt = pts;
1373 }
1374 EINA_COW_WRITE_END(evas_object_map_cow, obj->map, map_write);
1375
1376 pts[0].px = obj->map->cur.map->persp.px << FP;
1377 pts[0].py = obj->map->cur.map->persp.py << FP;
1378 pts[0].foc = obj->map->cur.map->persp.foc << FP;
1379 pts[0].z0 = obj->map->cur.map->persp.z0 << FP;
1380 // draw geom +x +y
1381 for (; p < p_end; p++, pt++)
1382 {
1383 pt->x = (lround(p->x) + x) * FP1;
1384 pt->y = (lround(p->y) + y) * FP1;
1385 pt->z = (lround(p->z) ) * FP1;
1386 pt->fx = p->x + (float) x;
1387 pt->fy = p->y + (float) y;
1388 pt->fz = p->z;
1389 if ((uvw == 0) || (imagew == 0)) pt->u = 0;
1390 else pt->u = ((lround(p->u) * imagew) / uvw) * FP1;
1391 if ((uvh == 0) || (imageh == 0)) pt->v = 0;
1392 else pt->v = ((lround(p->v) * imageh) / uvh) * FP1;
1393 if (pt->u < 0) pt->u = 0;
1394 else if (pt->u > (imagew * FP1)) pt->u = (imagew * FP1);
1395 if (pt->v < 0) pt->v = 0;
1396 else if (pt->v > (imageh * FP1)) pt->v = (imageh * FP1);
1397 pt->col = ARGB_JOIN(p->a, p->r, p->g, p->b);
1398 }
1399 if (obj->map->cur.map->count & 0x1)
1400 {
1401 pts[obj->map->cur.map->count] = pts[obj->map->cur.map->count -1];
1402 }
1403
1404 // Request engine to update it's point
1405
1406 obj->changed_map = EINA_FALSE;
1407
1408 return obj->changed_pchange;
1409 }
1410
1411 void
evas_map_object_move_diff_set(Evas_Map * m,Evas_Coord diff_x,Evas_Coord diff_y)1412 evas_map_object_move_diff_set(Evas_Map *m,
1413 Evas_Coord diff_x,
1414 Evas_Coord diff_y)
1415 {
1416 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
1417 return;
1418 MAGIC_CHECK_END();
1419
1420 m->move_sync.diff_x += diff_x;
1421 m->move_sync.diff_y += diff_y;
1422 }
1423