ca3441828db7d061a9af605fcd05c673e86b567c
[framework/uifw/evas.git] / src / lib / canvas / evas_map.c
1 #include "evas_common.h"
2 #include "evas_private.h"
3 #include <math.h>
4
5 static void
6 _evas_map_calc_geom_change(Evas_Object *obj)
7 {
8    int is, was = 0, pass = 0;
9
10    evas_object_change(obj);
11    evas_object_clip_dirty(obj);
12    if (obj->layer->evas->events_frozen <= 0)
13      {
14         evas_object_recalc_clippees(obj);
15         if (!pass)
16           {
17              if (!obj->smart.smart)
18                {
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,
27                                                NULL);
28                }
29           }
30      }
31    evas_object_inform_call_move(obj);
32    evas_object_inform_call_resize(obj);
33 }
34
35 static void
36 _evas_map_calc_map_geometry(Evas_Object *obj)
37 {
38    Evas_Coord x1, x2, y1, y2;
39    const Evas_Map_Point *p, *p_end;
40    Eina_Bool ch = EINA_FALSE;
41
42    if (!obj->cur.map) return;
43    /* WARN: Do not merge below code to SLP until it is fixed.
44       It has an infinite loop bug.
45    if (obj->prev.map)
46      {
47         // FIXME: this causes an infinite loop somewhere... hard to debug
48         if (obj->prev.map->count == obj->cur.map->count)
49           {
50              const Evas_Map_Point *p2;
51
52              p = obj->cur.map->points;
53              p_end = p + obj->cur.map->count;
54              p2 = obj->prev.map->points;
55
56              for (; p < p_end; p++, p2++)
57                {
58                   if ((p->a != p2->a) ||
59                       (p->r != p2->r) ||
60                       (p->g != p2->g) ||
61                       (p->b != p2->b))
62                     {
63                        ch = 1;
64                        break;
65                     }
66                   if ((p->x != p2->x) ||
67                       (p->y != p2->y) ||
68                       (p->z != p2->z))
69                     {
70                        ch = 1;
71                        break;
72                     }
73                }
74           }
75         else
76            ch = 1;
77      }
78    else
79       ch = 1;
80    WARN: DO NOT REMOVE THIS COMMENT. LEAVE IT AS IS UNTIL FIXED. */
81
82    p = obj->cur.map->points;
83    p_end = p + obj->cur.map->count;
84    x1 = p->x;
85    x2 = p->x;
86    y1 = p->y;
87    y2 = p->y;
88    p++;
89    for (; p < p_end; p++)
90      {
91         if (p->x < x1) x1 = p->x;
92         if (p->x > x2) x2 = p->x;
93         if (p->y < y1) y1 = p->y;
94         if (p->y > y2) y2 = p->y;
95      }
96    if (obj->cur.map->normal_geometry.x != x1) ch = 1;
97    if (obj->cur.map->normal_geometry.y != y1) ch = 1;
98    if (obj->cur.map->normal_geometry.w != (x2 - x1)) ch = 1;
99    if (obj->cur.map->normal_geometry.h != (y2 - y1)) ch = 1;
100    obj->cur.map->normal_geometry.x = x1;
101    obj->cur.map->normal_geometry.y = y1;
102    obj->cur.map->normal_geometry.w = (x2 - x1);
103    obj->cur.map->normal_geometry.h = (y2 - y1);
104    if (ch) _evas_map_calc_geom_change(obj);
105 }
106
107 static inline Evas_Map *
108 _evas_map_new(int count)
109 {
110    int i;
111    int alloc;
112    Evas_Map *m;
113
114    /* Adjust allocation such that: at least 4 points, and always an even
115     * number: this allows the software engine to work efficiently */
116    alloc = (count < 4) ? 4 : count;
117    if (alloc & 0x1) alloc ++;
118
119    m = calloc(1, sizeof(Evas_Map) + (alloc * sizeof(Evas_Map_Point)));
120    if (!m) return NULL;
121    m->count = count;
122    m->persp.foc = 0;
123    m->alpha = 1;
124    m->smooth = 1;
125    m->magic = MAGIC_MAP;
126    for (i = 0; i < count; i++)
127      {
128         m->points[i].r = 255;
129         m->points[i].g = 255;
130         m->points[i].b = 255;
131         m->points[i].a = 255;
132      }
133    return m;
134 }
135
136 static inline Eina_Bool
137 _evas_map_copy(Evas_Map *dst, const Evas_Map *src)
138 {
139    if (dst->count != src->count)
140      {
141         ERR("cannot copy map of different sizes: dst=%i, src=%i", dst->count, src->count);
142         return EINA_FALSE;
143      }
144    memcpy(dst->points, src->points, src->count * sizeof(Evas_Map_Point));
145    dst->smooth = src->smooth;
146    dst->alpha = src->alpha;
147    dst->persp = src->persp;
148    return EINA_TRUE;
149 }
150
151 static inline Evas_Map *
152 _evas_map_dup(const Evas_Map *orig)
153 {
154    Evas_Map *copy = _evas_map_new(orig->count);
155    if (!copy) return NULL;
156    memcpy(copy->points, orig->points, orig->count * sizeof(Evas_Map_Point));
157    copy->smooth = orig->smooth;
158    copy->alpha = orig->alpha;
159    copy->persp = orig->persp;
160    return copy;
161 }
162
163 static inline void
164 _evas_map_free(Evas_Object *obj, Evas_Map *m)
165 {
166    if (obj)
167      {
168         if (m->surface)
169           obj->layer->evas->engine.func->image_map_surface_free
170           (obj->layer->evas->engine.data.output, m->surface);
171      }
172    m->magic = 0;
173    free(m);
174 }
175
176 /****************************************************************************/
177 /* util functions for manipulating maps, so you don't need to know the math */
178 /****************************************************************************/
179 static inline void
180 _evas_map_util_points_populate(Evas_Map *m, const Evas_Coord x, const Evas_Coord y, const Evas_Coord w, const Evas_Coord h, const Evas_Coord z)
181 {
182    Evas_Map_Point *p = m->points;
183    int i;
184
185    p[0].x = x;
186    p[0].y = y;
187    p[0].z = z;
188    p[0].u = 0.0;
189    p[0].v = 0.0;
190
191    p[1].x = x + w;
192    p[1].y = y;
193    p[1].z = z;
194    p[1].u = w;
195    p[1].v = 0.0;
196
197    p[2].x = x + w;
198    p[2].y = y + h;
199    p[2].z = z;
200    p[2].u = w;
201    p[2].v = h;
202
203    p[3].x = x;
204    p[3].y = y + h;
205    p[3].z = z;
206    p[3].u = 0.0;
207    p[3].v = h;
208
209    for (i = 0; i < 4; i++)
210      {
211         p[i].px = p[i].x;
212         p[i].py = p[i].y;
213      }
214 }
215
216 Eina_Bool
217 evas_map_coords_get(const Evas_Map *m, Evas_Coord x, Evas_Coord y,
218                     Evas_Coord *mx, Evas_Coord *my, int grab)
219 {
220    MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
221    return EINA_FALSE;
222    MAGIC_CHECK_END();
223
224    int i, j, edges, edge[m->count][2], douv;
225    Evas_Coord xe[2];
226    double u[2] = { 0.0, 0.0 };
227    double v[2] = { 0.0, 0.0 };
228
229    if (m->count < 4) return 0;
230    // FIXME need to handle grab mode and extrapolte coords outside
231    // map
232    if (grab)
233      {
234         Evas_Coord ymin, ymax;
235
236         ymin = m->points[0].y;
237         ymax = m->points[0].y;
238         for (i = 1; i < m->count; i++)
239           {
240              if (m->points[i].y < ymin) ymin = m->points[i].y;
241              else if (m->points[i].y > ymax) ymax = m->points[i].y;
242           }
243         if (y <= ymin) y = ymin + 1;
244         if (y >= ymax) y = ymax - 1;
245      }
246    edges = 0;
247    for (i = 0; i < m->count; i++)
248      {
249         j = (i + 1) % m->count;
250         if ((m->points[i].y <= y) && (m->points[j].y > y))
251           {
252              edge[edges][0] = i;
253              edge[edges][1] = j;
254              edges++;
255           }
256         else if ((m->points[j].y <= y) && (m->points[i].y > y))
257           {
258              edge[edges][0] = j;
259              edge[edges][1] = i;
260              edges++;
261           }
262      }
263    douv = 0;
264    if ((mx) || (my)) douv = 1;
265    for (i = 0; i < (edges - 1); i+= 2)
266      {
267         Evas_Coord yp, yd;
268
269         j = i + 1;
270         yd = m->points[edge[i][1]].y - m->points[edge[i][0]].y;
271         if (yd > 0)
272           {
273              yp = y - m->points[edge[i][0]].y;
274              xe[0] = m->points[edge[i][1]].x - m->points[edge[i][0]].x;
275              xe[0] = m->points[edge[i][0]].x + ((xe[0] * yp) / yd);
276              if (douv)
277                {
278                   u[0] = m->points[edge[i][1]].u - m->points[edge[i][0]].u;
279                   u[0] = m->points[edge[i][0]].u + ((u[0] * yp) / yd);
280                   v[0] = m->points[edge[i][1]].v - m->points[edge[i][0]].v;
281                   v[0] = m->points[edge[i][0]].v + ((v[0] * yp) / yd);
282                }
283           }
284         else
285           {
286              xe[0] = m->points[edge[i][0]].x;
287              if (douv)
288                {
289                   u[0] = m->points[edge[i][0]].u;
290                   v[0] = m->points[edge[i][0]].v;
291                }
292           }
293         yd = m->points[edge[j][1]].y - m->points[edge[j][0]].y;
294         if (yd > 0)
295           {
296              yp = y - m->points[edge[j][0]].y;
297              xe[1] = m->points[edge[j][1]].x - m->points[edge[j][0]].x;
298              xe[1] = m->points[edge[j][0]].x + ((xe[1] * yp) / yd);
299              if (douv)
300                {
301                   u[1] = m->points[edge[j][1]].u - m->points[edge[j][0]].u;
302                   u[1] = m->points[edge[j][0]].u + ((u[1] * yp) / yd);
303                   v[1] = m->points[edge[j][1]].v - m->points[edge[j][0]].v;
304                   v[1] = m->points[edge[j][0]].v + ((v[1] * yp) / yd);
305                }
306           }
307         else
308           {
309              xe[1] = m->points[edge[j][0]].x;
310              if (douv)
311                {
312                   u[1] = m->points[edge[j][0]].u;
313                   v[1] = m->points[edge[j][0]].v;
314                }
315           }
316         if (xe[0] > xe[1])
317           {
318              int ti;
319
320              ti = xe[0]; xe[0] = xe[1]; xe[1] = ti;
321              if (douv)
322                {
323                   double td;
324
325                   td = u[0]; u[0] = u[1]; u[1] = td;
326                   td = v[0]; v[0] = v[1]; v[1] = td;
327                }
328           }
329         if ((x >= xe[0]) && (x < xe[1]))
330           {
331              if (douv)
332                {
333                   if (mx)
334                     *mx = u[0] + (((x - xe[0]) * (u[1] - u[0])) /
335                                   (xe[1] - xe[0]));
336                  if (my)
337                     *my = v[0] + (((x - xe[0]) * (v[1] - v[0])) /
338                                   (xe[1] - xe[0]));
339                }
340              return EINA_TRUE;
341           }
342         if (grab)
343           {
344              if (douv)
345                {
346                   if (mx)
347                     *mx = u[0] + (((x - xe[0]) * (u[1] - u[0])) /
348                                   (xe[1] - xe[0]));
349                   if (my)
350                     *my = v[0] + (((x - xe[0]) * (v[1] - v[0])) /
351                                   (xe[1] - xe[0]));
352                }
353              return EINA_TRUE;
354           }
355      }
356    return EINA_FALSE;
357 }
358
359 Eina_Bool
360 evas_map_inside_get(const Evas_Map *m, Evas_Coord x, Evas_Coord y)
361 {
362    return evas_map_coords_get(m, x, y, NULL, NULL, 0);
363 }
364
365 EAPI void
366 evas_object_map_enable_set(Evas_Object *obj, Eina_Bool enabled)
367 {
368    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
369    return;
370    MAGIC_CHECK_END();
371
372    enabled = !!enabled;
373    if (obj->cur.usemap == enabled) return;
374    obj->cur.usemap = enabled;
375    if (enabled)
376      {
377         if (!obj->cur.map)
378           obj->cur.map = _evas_map_new(4);
379         evas_object_mapped_clip_across_mark(obj);
380 //        obj->cur.map->normal_geometry = obj->cur.geometry;
381      }
382    else
383      {
384         if (obj->cur.map)
385           {
386              _evas_map_calc_geom_change(obj);
387              evas_object_mapped_clip_across_mark(obj);
388              //FIXME: Since the last frame is not updated when map is
389              //disabled, afterimage problem is happened in s/w rendering.
390              //Need to find out the fundamental reason then fix it.
391              evas_damage_rectangle_add(obj->layer->evas,
392                                        0,
393                                        0,
394                                        obj->layer->evas->output.w,
395                                        obj->layer->evas->output.h);
396           }
397      }
398    _evas_map_calc_map_geometry(obj);
399    /* This is a bit heavy handed, but it fixes the case of same geometry, but
400     * changed colour or UV settings. */
401    evas_object_change(obj);
402 }
403
404 EAPI Eina_Bool
405 evas_object_map_enable_get(const Evas_Object *obj)
406 {
407    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
408    return EINA_FALSE;
409    MAGIC_CHECK_END();
410    return obj->cur.usemap;
411 }
412
413
414 EAPI void
415 evas_object_map_source_set(Evas_Object *obj, Evas_Object *src)
416 {
417    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
418    return;
419    MAGIC_CHECK_END();
420    (void)src; /* method still needs to be implemented. */
421 }
422
423 EAPI Evas_Object *
424 evas_object_map_source_get(const Evas_Object *obj)
425 {
426    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
427    return NULL;
428    MAGIC_CHECK_END();
429    return NULL;
430 }
431
432 EAPI void
433 evas_object_map_set(Evas_Object *obj, const Evas_Map *map)
434 {
435    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
436    return;
437    MAGIC_CHECK_END();
438
439    if (!map)
440      {
441         if (obj->cur.map)
442           {
443              if (obj->cur.map->surface)
444                {
445                   obj->layer->evas->engine.func->image_map_surface_free
446                     (obj->layer->evas->engine.data.output,
447                      obj->cur.map->surface);
448                   obj->cur.map->surface = NULL;
449                }
450              obj->prev.geometry = obj->cur.map->normal_geometry;
451              if (!obj->prev.map)
452                {
453                   _evas_map_free(obj, obj->cur.map);
454                   obj->cur.map = NULL;
455                   evas_object_mapped_clip_across_mark(obj);
456                   return;
457                }
458              _evas_map_free(obj, obj->cur.map);
459              obj->cur.map = NULL;
460              if (!obj->cur.usemap) _evas_map_calc_geom_change(obj);
461              else _evas_map_calc_map_geometry(obj);
462              if (obj->cur.usemap)
463                {
464                   evas_object_mapped_clip_across_mark(obj);
465                   //FIXME: Since the last frame is not updated when map is
466                   //disabled, afterimage problem is happened in s/w
467                   //rendering. Need to find out the fundamental reason
468                   //then fix it.
469                   evas_damage_rectangle_add(obj->layer->evas,
470                                             0,
471                                             0,
472                                             obj->layer->evas->output.w,
473                                             obj->layer->evas->output.h);
474                }
475           }
476         return;
477      }
478
479    if ((obj->cur.map) && (obj->cur.map->count == map->count))
480      {
481         Evas_Map *omap = obj->cur.map;
482         obj->cur.map = _evas_map_new(map->count);
483         memcpy(obj->cur.map, omap, sizeof(Evas_Map) + (map->count * sizeof(Evas_Map_Point)));
484         _evas_map_copy(obj->cur.map, map);
485         if (obj->prev.map == omap) obj->prev.map = NULL;
486         free(omap);
487      }
488    else
489      {
490         if (obj->cur.map) evas_map_free(obj->cur.map);
491         obj->cur.map = _evas_map_dup(map);
492         if (obj->cur.usemap)
493            evas_object_mapped_clip_across_mark(obj);
494      }
495    _evas_map_calc_map_geometry(obj);
496 }
497
498 EAPI const Evas_Map *
499 evas_object_map_get(const Evas_Object *obj)
500 {
501    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
502    return NULL;
503    MAGIC_CHECK_END();
504
505    return obj->cur.map;
506 }
507
508 EAPI Evas_Map *
509 evas_map_new(int count)
510 {
511    if (count != 4)
512      {
513         ERR("map point count (%i) != 4 is unsupported!", count);
514         return NULL;
515      }
516
517    return _evas_map_new(count);
518 }
519
520 EAPI void
521 evas_map_smooth_set(Evas_Map *m, Eina_Bool enabled)
522 {
523    MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
524    return;
525    MAGIC_CHECK_END();
526
527    m->smooth = enabled;
528 }
529
530 EAPI Eina_Bool
531 evas_map_smooth_get(const Evas_Map *m)
532 {
533    MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
534    return EINA_FALSE;
535    MAGIC_CHECK_END();
536
537    return m->smooth;
538 }
539
540 EAPI void
541 evas_map_alpha_set(Evas_Map *m, Eina_Bool enabled)
542 {
543    MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
544    return;
545    MAGIC_CHECK_END();
546
547    m->alpha = enabled;
548 }
549
550 EAPI Eina_Bool
551 evas_map_alpha_get(const Evas_Map *m)
552 {
553    MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
554    return EINA_FALSE;
555    MAGIC_CHECK_END();
556
557    return m->alpha;
558 }
559
560 EAPI Evas_Map *
561 evas_map_dup(const Evas_Map *m)
562 {
563    MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
564    return NULL;
565    MAGIC_CHECK_END();
566
567    return _evas_map_dup(m);
568 }
569
570 EAPI void
571 evas_map_free(Evas_Map *m)
572 {
573    MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
574    return;
575    MAGIC_CHECK_END();
576
577    _evas_map_free(NULL, m);
578 }
579
580 EAPI int
581 evas_map_count_get(const Evas_Map *m)
582 {
583    MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
584    return -1;
585    MAGIC_CHECK_END();
586
587    return m->count;
588 }
589
590 EAPI void
591 evas_map_point_coord_set(Evas_Map *m, int idx, Evas_Coord x, Evas_Coord y, Evas_Coord z)
592 {
593    MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
594    return;
595    MAGIC_CHECK_END();
596
597    Evas_Map_Point *p;
598
599    if (idx >= m->count) return;
600    p = m->points + idx;
601    p->x = p->px = x;
602    p->y = p->py = y;
603    p->z = z;
604 }
605
606 EAPI void
607 evas_map_point_coord_get(const Evas_Map *m, int idx, Evas_Coord *x, Evas_Coord *y, Evas_Coord *z)
608 {
609    MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
610    goto error;
611    MAGIC_CHECK_END();
612
613    const Evas_Map_Point *p;
614
615    if (idx >= m->count) goto error;
616    p = m->points + idx;
617    if (x) *x = p->x;
618    if (y) *y = p->y;
619    if (z) *z = p->z;
620    return;
621
622  error:
623    if (x) *x = 0;
624    if (y) *y = 0;
625    if (z) *z = 0;
626 }
627
628 EAPI void
629 evas_map_point_image_uv_set(Evas_Map *m, int idx, double u, double v)
630 {
631    MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
632    return;
633    MAGIC_CHECK_END();
634
635    Evas_Map_Point *p;
636
637    if (idx >= m->count) return;
638    p = m->points + idx;
639    p->u = u;
640    p->v = v;
641 }
642
643 EAPI void
644 evas_map_point_image_uv_get(const Evas_Map *m, int idx, double *u, double *v)
645 {
646    MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
647    goto error;
648    MAGIC_CHECK_END();
649
650    const Evas_Map_Point *p;
651
652    if (idx >= m->count) goto error;
653    p = m->points + idx;
654    if (u) *u = p->u;
655    if (v) *v = p->v;
656    return;
657
658  error:
659    if (u) *u = 0.0;
660    if (v) *v = 0.0;
661 }
662
663 EAPI void
664 evas_map_point_color_set(Evas_Map *m, int idx, int r, int g, int b, int a)
665 {
666    MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
667    return;
668    MAGIC_CHECK_END();
669
670    Evas_Map_Point *p;
671
672    if (idx >= m->count) return;
673    p = m->points + idx;
674    p->r = r;
675    p->g = g;
676    p->b = b;
677    p->a = a;
678 }
679
680 EAPI void
681 evas_map_point_color_get(const Evas_Map *m, int idx, int *r, int *g, int *b, int *a)
682 {
683    MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
684    return;
685    MAGIC_CHECK_END();
686
687    const Evas_Map_Point *p;
688
689    if (idx >= m->count) return;
690    p = m->points + idx;
691    if (r) *r = p->r;
692    if (g) *g = p->g;
693    if (b) *b = p->b;
694    if (a) *a = p->a;
695 }
696
697 EAPI void
698 evas_map_util_points_populate_from_object_full(Evas_Map *m, const Evas_Object *obj, Evas_Coord z)
699 {
700    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
701    return;
702    MAGIC_CHECK_END();
703
704    if (m->count != 4)
705      {
706         ERR("map has count=%d where 4 was expected.", m->count);
707         return;
708      }
709    _evas_map_util_points_populate(m, obj->cur.geometry.x, obj->cur.geometry.y,
710                                   obj->cur.geometry.w, obj->cur.geometry.h, z);
711 }
712
713 EAPI void
714 evas_map_util_points_populate_from_object(Evas_Map *m, const Evas_Object *obj)
715 {
716    MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
717    return;
718    MAGIC_CHECK_END();
719
720    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
721    return;
722    MAGIC_CHECK_END();
723
724    if (m->count != 4)
725      {
726         ERR("map has count=%d where 4 was expected.", m->count);
727         return;
728      }
729    _evas_map_util_points_populate(m, obj->cur.geometry.x, obj->cur.geometry.y,
730                                   obj->cur.geometry.w, obj->cur.geometry.h, 0);
731 }
732
733 EAPI void
734 evas_map_util_points_populate_from_geometry(Evas_Map *m, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h, Evas_Coord z)
735 {
736    MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
737    return;
738    MAGIC_CHECK_END();
739
740    if (m->count != 4)
741      {
742         ERR("map has count=%d where 4 was expected.", m->count);
743         return;
744      }
745    _evas_map_util_points_populate(m, x, y, w, h, z);
746 }
747
748 EAPI void
749 evas_map_util_points_color_set(Evas_Map *m, int r, int g, int b, int a)
750 {
751    MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
752    return;
753    MAGIC_CHECK_END();
754
755    Evas_Map_Point *p, *p_end;
756
757    p = m->points;
758    p_end = p + m->count;
759    for (; p < p_end; p++)
760      {
761         p->r = r;
762         p->g = g;
763         p->b = b;
764         p->a = a;
765      }
766 }
767
768 EAPI void
769 evas_map_util_rotate(Evas_Map *m, double degrees, Evas_Coord cx, Evas_Coord cy)
770 {
771    MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
772    return;
773    MAGIC_CHECK_END();
774
775    double r = (degrees * M_PI) / 180.0;
776    Evas_Map_Point *p, *p_end;
777
778    p = m->points;
779    p_end = p + m->count;
780
781    for (; p < p_end; p++)
782      {
783         double x, y, xx, yy;
784
785         x = p->x - cx;
786         y = p->y - cy;
787
788         xx = x * cos(r);
789         yy = x * sin(r);
790         x = xx - (y * sin(r));
791         y = yy + (y * cos(r));
792
793         p->px = p->x = x + cx;
794         p->py = p->y = y + cy;
795      }
796 }
797
798 EAPI void
799 evas_map_util_zoom(Evas_Map *m, double zoomx, double zoomy, Evas_Coord cx, Evas_Coord cy)
800 {
801    MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
802    return;
803    MAGIC_CHECK_END();
804
805    Evas_Map_Point *p, *p_end;
806
807    p = m->points;
808    p_end = p + m->count;
809
810    for (; p < p_end; p++)
811      {
812         double x, y;
813
814         x = p->x - cx;
815         y = p->y - cy;
816
817         x = (((double)x) * zoomx);
818         y = (((double)y) * zoomy);
819
820         p->px = p->x = x + cx;
821         p->py = p->y = y + cy;
822      }
823 }
824
825 EAPI void
826 evas_map_util_3d_rotate(Evas_Map *m, double dx, double dy, double dz,
827                         Evas_Coord cx, Evas_Coord cy, Evas_Coord cz)
828 {
829    MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
830    return;
831    MAGIC_CHECK_END();
832
833    double rz = (dz * M_PI) / 180.0;
834    double rx = (dx * M_PI) / 180.0;
835    double ry = (dy * M_PI) / 180.0;
836    Evas_Map_Point *p, *p_end;
837
838    p = m->points;
839    p_end = p + m->count;
840
841    for (; p < p_end; p++)
842      {
843         double x, y, z, xx, yy, zz;
844
845         x = p->x - cx;
846         y = p->y - cy;
847         z = p->z - cz;
848
849         if (rz != 0.0)
850           {
851              xx = x * cos(rz);
852              yy = x * sin(rz);
853              x = xx - (y * sin(rz));
854              y = yy + (y * cos(rz));
855           }
856
857         if (ry != 0.0)
858           {
859              xx = x * cos(ry);
860              zz = x * sin(ry);
861              x = xx - (z * sin(ry));
862              z = zz + (z * cos(ry));
863           }
864
865         if (rx != 0.0)
866           {
867              zz = z * cos(rx);
868              yy = z * sin(rx);
869              z = zz - (y * sin(rx));
870              y = yy + (y * cos(rx));
871           }
872
873         p->px = p->x = x + cx;
874         p->py = p->y = y + cy;
875         p->z = z + cz;
876      }
877 }
878
879 EAPI void
880 evas_map_util_3d_lighting(Evas_Map *m,
881                           Evas_Coord lx, Evas_Coord ly, Evas_Coord lz,
882                           int lr, int lg, int lb, int ar, int ag, int ab)
883 {
884    MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
885    return;
886    MAGIC_CHECK_END();
887
888    int i;
889
890    for (i = 0; i < m->count; i++)
891      {
892         double x, y, z;
893         double nx, ny, nz, x1, y1, z1, x2, y2, z2, ln, br;
894         int h, j, mr, mg, mb;
895
896         x = m->points[i].x;
897         y = m->points[i].y;
898         z = m->points[i].z;
899         // calc normal
900         h = (i - 1 + 4) % 4 + (i & ~0x3); // prev point
901         j = (i + 1)     % 4 + (i & ~0x3); // next point
902
903         x1 = m->points[h].x - x;
904         y1 = m->points[h].y - y;
905         z1 = m->points[h].z - z;
906
907         x2 = m->points[j].x - x;
908         y2 = m->points[j].y - y;
909         z2 = m->points[j].z - z;
910         nx = (y1 * z2) - (z1 * y2);
911         ny = (z1 * x2) - (x1 * z2);
912         nz = (x1 * y2) - (y1 * x2);
913
914         ln = (nx * nx) + (ny * ny) + (nz * nz);
915         ln = sqrt(ln);
916
917         if (ln != 0.0)
918           {
919              nx /= ln;
920              ny /= ln;
921              nz /= ln;
922           }
923
924         // calc point -> light vector
925         x = lx - x;
926         y = ly - y;
927         z = lz - z;
928
929         ln = (x * x) + (y * y) + (z * z);
930         ln = sqrt(ln);
931
932         if (ln != 0.0)
933           {
934              x /= ln;
935              y /= ln;
936              z /= ln;
937           }
938
939         // brightness - tan (0.0 -> 1.0 brightness really)
940         br = (nx * x) + (ny * y) + (nz * z);
941         if (br < 0.0) br = 0.0;
942
943         mr = ar + ((lr - ar) * br);
944         mg = ag + ((lg - ag) * br);
945         mb = ab + ((lb - ab) * br);
946         if (m->points[i].a != 255)
947           {
948              mr = (mr * m->points[i].a) / 255;
949              mg = (mg * m->points[i].a) / 255;
950              mb = (mb * m->points[i].a) / 255;
951           }
952         m->points[i].r = (m->points[i].r * mr) / 255;
953         m->points[i].g = (m->points[i].g * mg) / 255;
954         m->points[i].b = (m->points[i].b * mb) / 255;
955      }
956 }
957
958 EAPI void
959 evas_map_util_3d_perspective(Evas_Map *m,
960                              Evas_Coord px, Evas_Coord py,
961                              Evas_Coord z0, Evas_Coord foc)
962 {
963    MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
964    return;
965    MAGIC_CHECK_END();
966
967    Evas_Map_Point *p, *p_end;
968
969    p = m->points;
970    p_end = p + m->count;
971
972    m->persp.px = px;
973    m->persp.py = py;
974    m->persp.z0 = z0;
975    m->persp.foc = foc;
976
977    if (foc <= 0) return;
978
979    for (; p < p_end; p++)
980      {
981         double x, y, zz;
982
983         x = p->x - px;
984         y = p->y - py;
985
986         zz = ((p->z - z0) + foc);
987
988         if (zz > 0)
989           {
990              x = (x * foc) / zz;
991              y = (y * foc) / zz;
992           }
993
994         p->x = px + x;
995         p->y = py + y;
996      }
997 }
998
999 EAPI Eina_Bool
1000 evas_map_util_clockwise_get(Evas_Map *m)
1001 {
1002    MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
1003    return EINA_FALSE;
1004    MAGIC_CHECK_END();
1005
1006    int i, j, k, count;
1007    long long c;
1008
1009    if (m->count < 3) return EINA_FALSE;
1010
1011    count = 0;
1012    for (i = 0; i < m->count; i++)
1013      {
1014         j = (i + 1) % m->count;
1015         k = (i + 2) % m->count;
1016         c =
1017           ((m->points[j].x - m->points[i].x) *
1018            (m->points[k].y - m->points[j].y))
1019           -
1020           ((m->points[j].y - m->points[i].y) *
1021            (m->points[k].x - m->points[j].x));
1022         if (c < 0) count--;
1023         else if (c > 0) count++;
1024      }
1025    if (count > 0) return EINA_TRUE;
1026    return EINA_FALSE;
1027 }