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