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