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(&current, &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