summaryrefslogtreecommitdiff
path: root/src/lib/evas/canvas/evas_map.c
diff options
context:
space:
mode:
authorVincent Torri <vincent.torri@gmail.com>2012-11-04 11:51:42 +0000
committerVincent Torri <vincent.torri@gmail.com>2012-11-04 11:51:42 +0000
commitc15e9c6575c3b5f39ded167dda5259de3de96151 (patch)
tree5115d7ae3620af24c2bc094cd062575af7adeda9 /src/lib/evas/canvas/evas_map.c
parenta5ac6a987caec5a7f7596a25d0a065b9cc94c50c (diff)
merge: and now Evas
I've tested make -j 3 install and it works nicely I've tested expedite with software and opengl xlib, and it works. Not tested other engines, so please report any problems (engines or other) on the ML. TODO: examples and tests, I'll add them later ISSUE: Eina_Unicode size check. It indirectly depends on eina_config.h, which is created at the end of the configure script. So its size is always 0. I don't know how that size is used, so I can't do a lot, for now. SVN revision: 78895
Diffstat (limited to 'src/lib/evas/canvas/evas_map.c')
-rw-r--r--src/lib/evas/canvas/evas_map.c1220
1 files changed, 1220 insertions, 0 deletions
diff --git a/src/lib/evas/canvas/evas_map.c b/src/lib/evas/canvas/evas_map.c
new file mode 100644
index 0000000..3338d37
--- /dev/null
+++ b/src/lib/evas/canvas/evas_map.c
@@ -0,0 +1,1220 @@
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 *eo_obj)
7{
8 int is, was = 0;
9 Evas_Object_Protected_Data *obj = eo_data_get(eo_obj, EVAS_OBJ_CLASS);
10 evas_object_change(eo_obj, obj);
11 evas_object_clip_dirty(eo_obj, obj);
12 if (!(obj->layer->evas->is_frozen))
13 {
14 evas_object_recalc_clippees(eo_obj, obj);
15 if (!obj->is_smart)
16 {
17 is = evas_object_is_in_output_rect(eo_obj, obj,
18 obj->layer->evas->pointer.x,
19 obj->layer->evas->pointer.y, 1, 1);
20 if ((is ^ was) && obj->cur.visible)
21 evas_event_feed_mouse_move(obj->layer->evas->evas,
22 obj->layer->evas->pointer.x,
23 obj->layer->evas->pointer.y,
24 obj->layer->evas->last_timestamp,
25 NULL);
26 }
27 }
28 evas_object_inform_call_move(eo_obj, obj);
29 evas_object_inform_call_resize(eo_obj);
30}
31
32static void
33_evas_map_calc_map_geometry(Evas_Object *eo_obj)
34{
35 Evas_Coord x1, x2, yy1, yy2;
36 const Evas_Map_Point *p, *p_end;
37 Eina_Bool ch = EINA_FALSE;
38
39 Evas_Object_Protected_Data *obj = eo_data_get(eo_obj, EVAS_OBJ_CLASS);
40 if (!obj->cur.map) return;
41 // WARN: Do not merge below code to SLP until it is fixed.
42 // It has an infinite loop bug.
43 if (obj->prev.map)
44 {
45 if (obj->prev.map != obj->cur.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 p2 = obj->prev.map->points;
54 if (memcmp(p, p2, sizeof(Evas_Map_Point) *
55 obj->prev.map->count) != 0)
56 ch = EINA_TRUE;
57 if (!ch)
58 {
59 if (obj->cache_map) evas_map_free(obj->cache_map);
60 obj->cache_map = obj->cur.map;
61 obj->cur.map = obj->prev.map;
62 }
63 }
64 else
65 ch = EINA_TRUE;
66 }
67 }
68 else
69 ch = EINA_TRUE;
70
71 p = obj->cur.map->points;
72 p_end = p + obj->cur.map->count;
73 x1 = x2 = lround(p->x);
74 yy1 = yy2 = lround(p->y);
75 p++;
76 for (; p < p_end; p++)
77 {
78 Evas_Coord x, y;
79
80 x = lround(p->x);
81 y = lround(p->y);
82 if (x < x1) x1 = x;
83 if (x > x2) x2 = x;
84 if (y < yy1) yy1 = y;
85 if (y > yy2) yy2 = y;
86 }
87// this causes clip-out bugs now mapped objs canbe opaque!!!
88// // add 1 pixel of fuzz around the map region to ensure updates are correct
89// x1 -= 1; yy1 -= 1;
90// x2 += 1; yy2 += 1;
91 if (obj->cur.map->normal_geometry.x != x1) ch = 1;
92 if (obj->cur.map->normal_geometry.y != yy1) ch = 1;
93 if (obj->cur.map->normal_geometry.w != (x2 - x1)) ch = 1;
94 if (obj->cur.map->normal_geometry.h != (yy2 - yy1)) ch = 1;
95 obj->cur.map->normal_geometry.x = x1;
96 obj->cur.map->normal_geometry.y = yy1;
97 obj->cur.map->normal_geometry.w = (x2 - x1);
98 obj->cur.map->normal_geometry.h = (yy2 - yy1);
99 obj->changed_map = ch;
100 // This shouldn't really be needed, but without it we do have case
101 // where the clip is wrong when a map doesn't change, so always forcing
102 // it, as long as someone doesn't find a better fix.
103 evas_object_clip_dirty(eo_obj, obj);
104 if (ch) _evas_map_calc_geom_change(eo_obj);
105}
106
107static 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
136static 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 if (dst == src) return EINA_TRUE;
145 if (dst->points != src->points)
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
153static 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
165static inline void
166_evas_map_free(Evas_Object *eo_obj, Evas_Map *m)
167{
168 if (eo_obj)
169 {
170 Evas_Object_Protected_Data *obj = eo_data_get(eo_obj, EVAS_OBJ_CLASS);
171 if (obj->spans)
172 {
173 obj->layer->evas->engine.func->image_map_clean(obj->layer->evas->engine.data.output, obj->spans);
174 free(obj->spans);
175 obj->spans = NULL;
176 }
177 }
178 m->magic = 0;
179 free(m);
180}
181
182/****************************************************************************/
183/* util functions for manipulating maps, so you don't need to know the math */
184/****************************************************************************/
185static inline void
186_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)
187{
188 Evas_Map_Point *p = m->points;
189 int i;
190
191 p[0].x = x;
192 p[0].y = y;
193 p[0].z = z;
194 p[0].u = 0.0;
195 p[0].v = 0.0;
196
197 p[1].x = x + w;
198 p[1].y = y;
199 p[1].z = z;
200 p[1].u = w;
201 p[1].v = 0.0;
202
203 p[2].x = x + w;
204 p[2].y = y + h;
205 p[2].z = z;
206 p[2].u = w;
207 p[2].v = h;
208
209 p[3].x = x;
210 p[3].y = y + h;
211 p[3].z = z;
212 p[3].u = 0.0;
213 p[3].v = h;
214
215 for (i = 0; i < 4; i++)
216 {
217 p[i].px = p[i].x;
218 p[i].py = p[i].y;
219 }
220}
221
222Eina_Bool
223evas_map_coords_get(const Evas_Map *m, Evas_Coord x, Evas_Coord y,
224 Evas_Coord *mx, Evas_Coord *my, int grab)
225{
226 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
227 return EINA_FALSE;
228 MAGIC_CHECK_END();
229
230 int i, j, edges, edge[m->count][2], douv;
231 Evas_Coord xe[2];
232 double u[2] = { 0.0, 0.0 };
233 double v[2] = { 0.0, 0.0 };
234
235 if (m->count < 4) return 0;
236 // FIXME need to handle grab mode and extrapolte coords outside
237 // map
238 if (grab)
239 {
240 Evas_Coord ymin, ymax;
241
242 ymin = m->points[0].y;
243 ymax = m->points[0].y;
244 for (i = 1; i < m->count; i++)
245 {
246 if (m->points[i].y < ymin) ymin = m->points[i].y;
247 else if (m->points[i].y > ymax) ymax = m->points[i].y;
248 }
249 if (y <= ymin) y = ymin + 1;
250 if (y >= ymax) y = ymax - 1;
251 }
252 edges = 0;
253 for (i = 0; i < m->count; i++)
254 {
255 j = (i + 1) % m->count;
256 if ((m->points[i].y <= y) && (m->points[j].y > y))
257 {
258 edge[edges][0] = i;
259 edge[edges][1] = j;
260 edges++;
261 }
262 else if ((m->points[j].y <= y) && (m->points[i].y > y))
263 {
264 edge[edges][0] = j;
265 edge[edges][1] = i;
266 edges++;
267 }
268 }
269 douv = 0;
270 if ((mx) || (my)) douv = 1;
271 for (i = 0; i < (edges - 1); i+= 2)
272 {
273 Evas_Coord yp, yd;
274
275 j = i + 1;
276 yd = m->points[edge[i][1]].y - m->points[edge[i][0]].y;
277 if (yd > 0)
278 {
279 yp = y - m->points[edge[i][0]].y;
280 xe[0] = m->points[edge[i][1]].x - m->points[edge[i][0]].x;
281 xe[0] = m->points[edge[i][0]].x + ((xe[0] * yp) / yd);
282 if (douv)
283 {
284 u[0] = m->points[edge[i][1]].u - m->points[edge[i][0]].u;
285 u[0] = m->points[edge[i][0]].u + ((u[0] * yp) / yd);
286 v[0] = m->points[edge[i][1]].v - m->points[edge[i][0]].v;
287 v[0] = m->points[edge[i][0]].v + ((v[0] * yp) / yd);
288 }
289 }
290 else
291 {
292 xe[0] = m->points[edge[i][0]].x;
293 if (douv)
294 {
295 u[0] = m->points[edge[i][0]].u;
296 v[0] = m->points[edge[i][0]].v;
297 }
298 }
299 yd = m->points[edge[j][1]].y - m->points[edge[j][0]].y;
300 if (yd > 0)
301 {
302 yp = y - m->points[edge[j][0]].y;
303 xe[1] = m->points[edge[j][1]].x - m->points[edge[j][0]].x;
304 xe[1] = m->points[edge[j][0]].x + ((xe[1] * yp) / yd);
305 if (douv)
306 {
307 u[1] = m->points[edge[j][1]].u - m->points[edge[j][0]].u;
308 u[1] = m->points[edge[j][0]].u + ((u[1] * yp) / yd);
309 v[1] = m->points[edge[j][1]].v - m->points[edge[j][0]].v;
310 v[1] = m->points[edge[j][0]].v + ((v[1] * yp) / yd);
311 }
312 }
313 else
314 {
315 xe[1] = m->points[edge[j][0]].x;
316 if (douv)
317 {
318 u[1] = m->points[edge[j][0]].u;
319 v[1] = m->points[edge[j][0]].v;
320 }
321 }
322 if (xe[0] > xe[1])
323 {
324 int ti;
325
326 ti = xe[0]; xe[0] = xe[1]; xe[1] = ti;
327 if (douv)
328 {
329 double td;
330
331 td = u[0]; u[0] = u[1]; u[1] = td;
332 td = v[0]; v[0] = v[1]; v[1] = td;
333 }
334 }
335 if ((x >= xe[0]) && (x < xe[1]))
336 {
337 if (douv)
338 {
339 if (mx)
340 *mx = u[0] + (((x - xe[0]) * (u[1] - u[0])) /
341 (xe[1] - xe[0]));
342 if (my)
343 *my = v[0] + (((x - xe[0]) * (v[1] - v[0])) /
344 (xe[1] - xe[0]));
345 }
346 return EINA_TRUE;
347 }
348 if (grab)
349 {
350 if (douv)
351 {
352 if (mx)
353 *mx = u[0] + (((x - xe[0]) * (u[1] - u[0])) /
354 (xe[1] - xe[0]));
355 if (my)
356 *my = v[0] + (((x - xe[0]) * (v[1] - v[0])) /
357 (xe[1] - xe[0]));
358 }
359 return EINA_TRUE;
360 }
361 }
362 return EINA_FALSE;
363}
364
365Eina_Bool
366evas_map_inside_get(const Evas_Map *m, Evas_Coord x, Evas_Coord y)
367{
368 return evas_map_coords_get(m, x, y, NULL, NULL, 0);
369}
370
371static Eina_Bool
372_evas_object_map_parent_check(Evas_Object *eo_parent)
373{
374 const Eina_Inlist *list;
375 const Evas_Object_Protected_Data *o;
376
377 if (!eo_parent) return EINA_FALSE;
378 Evas_Object_Protected_Data *parent = eo_data_get(eo_parent, EVAS_OBJ_CLASS);
379 list = evas_object_smart_members_get_direct(parent->smart.parent);
380 EINA_INLIST_FOREACH(list, o)
381 if (o->cur.usemap) break ;
382 if (o) return EINA_FALSE; /* Still some child have a map enable */
383 parent->child_has_map = EINA_FALSE;
384 _evas_object_map_parent_check(parent->smart.parent);
385 return EINA_TRUE;
386}
387
388EAPI void
389evas_object_map_enable_set(Evas_Object *eo_obj, Eina_Bool enabled)
390{
391 MAGIC_CHECK(eo_obj, Evas_Object, MAGIC_OBJ);
392 return;
393 MAGIC_CHECK_END();
394 eo_do(eo_obj, evas_obj_map_enable_set(enabled));
395}
396
397void
398_map_enable_set(Eo *eo_obj, void *_pd, va_list *list)
399{
400 Eina_Bool enabled = va_arg(*list, int);
401
402 Evas_Object_Protected_Data *obj = _pd;
403 Eina_Bool pchange = EINA_FALSE;
404
405 enabled = !!enabled;
406 if (obj->cur.usemap == enabled) return;
407 pchange = obj->changed;
408 obj->cur.usemap = enabled;
409 if (enabled)
410 {
411 if (!obj->cur.map)
412 obj->cur.map = _evas_map_new(4);
413 evas_object_mapped_clip_across_mark(eo_obj, obj);
414// obj->cur.map->normal_geometry = obj->cur.geometry;
415 }
416 else
417 {
418 if (obj->map.surface)
419 {
420 obj->layer->evas->engine.func->image_map_surface_free
421 (obj->layer->evas->engine.data.output,
422 obj->map.surface);
423 obj->map.surface = NULL;
424 }
425 if (obj->cur.map)
426 {
427 _evas_map_calc_geom_change(eo_obj);
428 evas_object_mapped_clip_across_mark(eo_obj, obj);
429 }
430 }
431 _evas_map_calc_map_geometry(eo_obj);
432 /* This is a bit heavy handed, but it fixes the case of same geometry, but
433 * changed colour or UV settings. */
434 evas_object_change(eo_obj, obj);
435 if (!obj->changed_pchange) obj->changed_pchange = pchange;
436 obj->changed_map = EINA_TRUE;
437
438 if (enabled)
439 {
440 Evas_Object *eo_parents;
441 Evas_Object_Protected_Data *parents = NULL;
442 for (eo_parents = obj->smart.parent; eo_parents; eo_parents = parents->smart.parent)
443 {
444 parents = eo_data_get(eo_parents, EVAS_OBJ_CLASS);
445 parents->child_has_map = EINA_TRUE;
446 }
447 }
448 else
449 {
450 if (_evas_object_map_parent_check(obj->smart.parent))
451 evas_object_update_bounding_box(eo_obj, obj);
452 }
453}
454
455EAPI Eina_Bool
456evas_object_map_enable_get(const Evas_Object *eo_obj)
457{
458 MAGIC_CHECK(eo_obj, Evas_Object, MAGIC_OBJ);
459 return EINA_FALSE;
460 MAGIC_CHECK_END();
461 Eina_Bool enabled = EINA_FALSE;
462 eo_do((Eo *)eo_obj, evas_obj_map_enable_get(&enabled));
463 return enabled;
464}
465
466void
467_map_enable_get(Eo *eo_obj EINA_UNUSED, void *_pd, va_list *list)
468{
469 Eina_Bool *enabled = va_arg(*list, Eina_Bool *);
470 const Evas_Object_Protected_Data *obj = _pd;
471 *enabled = obj->cur.usemap;
472}
473
474EAPI void
475evas_object_map_set(Evas_Object *eo_obj, const Evas_Map *map)
476{
477 MAGIC_CHECK(eo_obj, Evas_Object, MAGIC_OBJ);
478 return;
479 MAGIC_CHECK_END();
480 eo_do(eo_obj, evas_obj_map_set(map));
481}
482
483void
484_map_set(Eo *eo_obj, void *_pd, va_list *list)
485{
486 const Evas_Map *map = va_arg(*list, const Evas_Map *);
487 Evas_Object_Protected_Data *obj = _pd;
488
489 if ((!map) || (map->count < 4))
490 {
491 if (obj->map.surface)
492 {
493 obj->layer->evas->engine.func->image_map_surface_free
494 (obj->layer->evas->engine.data.output,
495 obj->map.surface);
496 obj->map.surface = NULL;
497 }
498 if (obj->cur.map)
499 {
500 obj->changed_map = EINA_TRUE;
501 obj->prev.geometry = obj->cur.map->normal_geometry;
502
503 if (obj->prev.map == obj->cur.map)
504 obj->cur.map = NULL;
505 else if (!obj->cache_map)
506 {
507 obj->cache_map = obj->cur.map;
508 obj->cur.map = NULL;
509 }
510 else
511 {
512 _evas_map_free(eo_obj, obj->cur.map);
513 obj->cur.map = NULL;
514 }
515
516 if (!obj->prev.map)
517 {
518 evas_object_mapped_clip_across_mark(eo_obj, obj);
519 return;
520 }
521
522 if (!obj->cur.usemap) _evas_map_calc_geom_change(eo_obj);
523 else _evas_map_calc_map_geometry(eo_obj);
524 if (obj->cur.usemap)
525 evas_object_mapped_clip_across_mark(eo_obj, obj);
526 }
527 return;
528 }
529
530 if (obj->prev.map == obj->cur.map)
531 obj->cur.map = NULL;
532
533 if (!obj->cur.map)
534 {
535 obj->cur.map = obj->cache_map;
536 obj->cache_map = NULL;
537 }
538
539 // We do have the same exact count of point in this map, so just copy it
540 if ((obj->cur.map) && (obj->cur.map->count == map->count))
541 _evas_map_copy(obj->cur.map, map);
542 else
543 {
544 if (obj->cur.map) _evas_map_free(eo_obj, obj->cur.map);
545 obj->cur.map = _evas_map_dup(map);
546 if (obj->cur.usemap)
547 evas_object_mapped_clip_across_mark(eo_obj, obj);
548 }
549
550 _evas_map_calc_map_geometry(eo_obj);
551}
552
553EAPI const Evas_Map *
554evas_object_map_get(const Evas_Object *eo_obj)
555{
556 MAGIC_CHECK(eo_obj, Evas_Object, MAGIC_OBJ);
557 return NULL;
558 MAGIC_CHECK_END();
559 const Evas_Map *map = NULL;
560 eo_do((Eo *)eo_obj, evas_obj_map_get(&map));
561 return map;
562}
563
564void
565_map_get(Eo *eo_obj EINA_UNUSED, void *_pd, va_list *list)
566{
567 const Evas_Map **map = va_arg(*list, const Evas_Map **);
568 const Evas_Object_Protected_Data *obj = _pd;
569
570 *map = obj->cur.map;
571}
572
573EAPI Evas_Map *
574evas_map_new(int count)
575{
576 if (count != 4)
577 {
578 ERR("map point count (%i) != 4 is unsupported!", count);
579 return NULL;
580 }
581
582 return _evas_map_new(count);
583}
584
585EAPI void
586evas_map_smooth_set(Evas_Map *m, Eina_Bool enabled)
587{
588 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
589 return;
590 MAGIC_CHECK_END();
591
592 m->smooth = enabled;
593}
594
595EAPI Eina_Bool
596evas_map_smooth_get(const Evas_Map *m)
597{
598 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
599 return EINA_FALSE;
600 MAGIC_CHECK_END();
601
602 return m->smooth;
603}
604
605EAPI void
606evas_map_alpha_set(Evas_Map *m, Eina_Bool enabled)
607{
608 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
609 return;
610 MAGIC_CHECK_END();
611
612 m->alpha = enabled;
613}
614
615EAPI Eina_Bool
616evas_map_alpha_get(const Evas_Map *m)
617{
618 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
619 return EINA_FALSE;
620 MAGIC_CHECK_END();
621
622 return m->alpha;
623}
624
625EAPI Evas_Map *
626evas_map_dup(const Evas_Map *m)
627{
628 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
629 return NULL;
630 MAGIC_CHECK_END();
631
632 return _evas_map_dup(m);
633}
634
635EAPI void
636evas_map_free(Evas_Map *m)
637{
638 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
639 return;
640 MAGIC_CHECK_END();
641
642 _evas_map_free(NULL, m);
643}
644
645EAPI int
646evas_map_count_get(const Evas_Map *m)
647{
648 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
649 return -1;
650 MAGIC_CHECK_END();
651
652 return m->count;
653}
654
655EAPI void
656evas_map_point_coord_set(Evas_Map *m, int idx, Evas_Coord x, Evas_Coord y, Evas_Coord z)
657{
658 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
659 return;
660 MAGIC_CHECK_END();
661
662 Evas_Map_Point *p;
663
664 if (idx >= m->count) return;
665 p = m->points + idx;
666 p->x = p->px = x;
667 p->y = p->py = y;
668 p->z = z;
669}
670
671EAPI void
672evas_map_point_coord_get(const Evas_Map *m, int idx, Evas_Coord *x, Evas_Coord *y, Evas_Coord *z)
673{
674 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
675 goto error;
676 MAGIC_CHECK_END();
677
678 const Evas_Map_Point *p;
679
680 if (idx >= m->count) goto error;
681 p = m->points + idx;
682 if (x) *x = p->x;
683 if (y) *y = p->y;
684 if (z) *z = p->z;
685 return;
686
687 error:
688 if (x) *x = 0;
689 if (y) *y = 0;
690 if (z) *z = 0;
691}
692
693EAPI void
694evas_map_point_image_uv_set(Evas_Map *m, int idx, double u, double v)
695{
696 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
697 return;
698 MAGIC_CHECK_END();
699
700 Evas_Map_Point *p;
701
702 if (idx >= m->count) return;
703 p = m->points + idx;
704 p->u = u;
705 p->v = v;
706}
707
708EAPI void
709evas_map_point_image_uv_get(const Evas_Map *m, int idx, double *u, double *v)
710{
711 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
712 goto error;
713 MAGIC_CHECK_END();
714
715 const Evas_Map_Point *p;
716
717 if (idx >= m->count) goto error;
718 p = m->points + idx;
719 if (u) *u = p->u;
720 if (v) *v = p->v;
721 return;
722
723 error:
724 if (u) *u = 0.0;
725 if (v) *v = 0.0;
726}
727
728EAPI void
729evas_map_point_color_set(Evas_Map *m, int idx, int r, int g, int b, int a)
730{
731 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
732 return;
733 MAGIC_CHECK_END();
734
735 Evas_Map_Point *p;
736
737 if (idx >= m->count) return;
738 p = m->points + idx;
739 p->r = r;
740 p->g = g;
741 p->b = b;
742 p->a = a;
743}
744
745EAPI void
746evas_map_point_color_get(const Evas_Map *m, int idx, int *r, int *g, int *b, int *a)
747{
748 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
749 return;
750 MAGIC_CHECK_END();
751
752 const Evas_Map_Point *p;
753
754 if (idx >= m->count) return;
755 p = m->points + idx;
756 if (r) *r = p->r;
757 if (g) *g = p->g;
758 if (b) *b = p->b;
759 if (a) *a = p->a;
760}
761
762EAPI void
763evas_map_util_points_populate_from_object_full(Evas_Map *m, const Evas_Object *eo_obj, Evas_Coord z)
764{
765 MAGIC_CHECK(eo_obj, Evas_Object, MAGIC_OBJ);
766 return;
767 MAGIC_CHECK_END();
768 Evas_Object_Protected_Data *obj = eo_data_get(eo_obj, EVAS_OBJ_CLASS);
769
770 if (m->count != 4)
771 {
772 ERR("map has count=%d where 4 was expected.", m->count);
773 return;
774 }
775 _evas_map_util_points_populate(m, obj->cur.geometry.x, obj->cur.geometry.y,
776 obj->cur.geometry.w, obj->cur.geometry.h, z);
777}
778
779EAPI void
780evas_map_util_points_populate_from_object(Evas_Map *m, const Evas_Object *eo_obj)
781{
782 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
783 return;
784 MAGIC_CHECK_END();
785
786 MAGIC_CHECK(eo_obj, Evas_Object, MAGIC_OBJ);
787 return;
788 MAGIC_CHECK_END();
789 Evas_Object_Protected_Data *obj = eo_data_get(eo_obj, EVAS_OBJ_CLASS);
790
791 if (m->count != 4)
792 {
793 ERR("map has count=%d where 4 was expected.", m->count);
794 return;
795 }
796 _evas_map_util_points_populate(m, obj->cur.geometry.x, obj->cur.geometry.y,
797 obj->cur.geometry.w, obj->cur.geometry.h, 0);
798}
799
800EAPI void
801evas_map_util_points_populate_from_geometry(Evas_Map *m, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h, Evas_Coord z)
802{
803 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
804 return;
805 MAGIC_CHECK_END();
806
807 if (m->count != 4)
808 {
809 ERR("map has count=%d where 4 was expected.", m->count);
810 return;
811 }
812 _evas_map_util_points_populate(m, x, y, w, h, z);
813}
814
815EAPI void
816evas_map_util_points_color_set(Evas_Map *m, int r, int g, int b, int a)
817{
818 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
819 return;
820 MAGIC_CHECK_END();
821
822 Evas_Map_Point *p, *p_end;
823
824 p = m->points;
825 p_end = p + m->count;
826 for (; p < p_end; p++)
827 {
828 p->r = r;
829 p->g = g;
830 p->b = b;
831 p->a = a;
832 }
833}
834
835EAPI void
836evas_map_util_rotate(Evas_Map *m, double degrees, Evas_Coord cx, Evas_Coord cy)
837{
838 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
839 return;
840 MAGIC_CHECK_END();
841
842 double r = (degrees * M_PI) / 180.0;
843 Evas_Map_Point *p, *p_end;
844
845 p = m->points;
846 p_end = p + m->count;
847
848 for (; p < p_end; p++)
849 {
850 double x, y, xx, yy;
851
852 x = p->x - cx;
853 y = p->y - cy;
854
855 xx = x * cos(r);
856 yy = x * sin(r);
857 x = xx - (y * sin(r));
858 y = yy + (y * cos(r));
859
860 p->px = p->x = x + cx;
861 p->py = p->y = y + cy;
862 }
863}
864
865EAPI void
866evas_map_util_zoom(Evas_Map *m, double zoomx, double zoomy, Evas_Coord cx, Evas_Coord cy)
867{
868 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
869 return;
870 MAGIC_CHECK_END();
871
872 Evas_Map_Point *p, *p_end;
873
874 p = m->points;
875 p_end = p + m->count;
876
877 for (; p < p_end; p++)
878 {
879 double x, y;
880
881 x = p->x - cx;
882 y = p->y - cy;
883
884 x = (((double)x) * zoomx);
885 y = (((double)y) * zoomy);
886
887 p->px = p->x = x + cx;
888 p->py = p->y = y + cy;
889 }
890}
891
892EAPI void
893evas_map_util_3d_rotate(Evas_Map *m, double dx, double dy, double dz,
894 Evas_Coord cx, Evas_Coord cy, Evas_Coord cz)
895{
896 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
897 return;
898 MAGIC_CHECK_END();
899
900 double rz = (dz * M_PI) / 180.0;
901 double rx = (dx * M_PI) / 180.0;
902 double ry = (dy * M_PI) / 180.0;
903 Evas_Map_Point *p, *p_end;
904
905 p = m->points;
906 p_end = p + m->count;
907
908 for (; p < p_end; p++)
909 {
910 double x, y, z, xx, yy, zz;
911
912 x = p->x - cx;
913 y = p->y - cy;
914 z = p->z - cz;
915
916 if (rz != 0.0)
917 {
918 xx = x * cos(rz);
919 yy = x * sin(rz);
920 x = xx - (y * sin(rz));
921 y = yy + (y * cos(rz));
922 }
923
924 if (ry != 0.0)
925 {
926 xx = x * cos(ry);
927 zz = x * sin(ry);
928 x = xx - (z * sin(ry));
929 z = zz + (z * cos(ry));
930 }
931
932 if (rx != 0.0)
933 {
934 zz = z * cos(rx);
935 yy = z * sin(rx);
936 z = zz - (y * sin(rx));
937 y = yy + (y * cos(rx));
938 }
939
940 p->px = p->x = x + cx;
941 p->py = p->y = y + cy;
942 p->z = z + cz;
943 }
944}
945
946EAPI void
947evas_map_util_quat_rotate(Evas_Map *m, double qx, double qy, double qz,
948 double qw, double cx, double cy, double cz)
949{
950 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
951 return;
952 MAGIC_CHECK_END();
953
954 Evas_Map_Point *p, *p_end;
955
956 p = m->points;
957 p_end = p + m->count;
958
959 for (; p < p_end; p++)
960 {
961 double x, y, z, uvx, uvy, uvz, uuvx, uuvy, uuvz;
962
963 x = p->x - cx;
964 y = p->y - cy;
965 z = p->z - cz;
966
967 uvx = qy * z - qz * y;
968 uvy = qz * x - qx * z;
969 uvz = qx * y - qy * x;
970
971 uuvx = qy * uvz - qz * uvy;
972 uuvy = qz * uvx - qx * uvz;
973 uuvz = qx * uvy - qy * uvx;
974
975 uvx *= (2.0f * qw);
976 uvy *= (2.0f * qw);
977 uvz *= (2.0f * qw);
978
979 uuvx *= 2.0f;
980 uuvy *= 2.0f;
981 uuvz *= 2.0f;
982
983 p->px = p->x = cx + x + uvx + uuvx;
984 p->py = p->y = cy + y + uvy + uuvy;
985 p->z = cz + z + uvz + uuvz;
986 }
987}
988
989EAPI void
990evas_map_util_3d_lighting(Evas_Map *m,
991 Evas_Coord lx, Evas_Coord ly, Evas_Coord lz,
992 int lr, int lg, int lb, int ar, int ag, int ab)
993{
994 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
995 return;
996 MAGIC_CHECK_END();
997
998 int i;
999
1000 for (i = 0; i < m->count; i++)
1001 {
1002 double x, y, z;
1003 double nx, ny, nz, x1, yy1, z1, x2, yy2, z2, ln, br;
1004 int h, j, mr, mg, mb;
1005
1006 x = m->points[i].x;
1007 y = m->points[i].y;
1008 z = m->points[i].z;
1009 // calc normal
1010 h = (i - 1 + 4) % 4 + (i & ~0x3); // prev point
1011 j = (i + 1) % 4 + (i & ~0x3); // next point
1012
1013 x1 = m->points[h].x - x;
1014 yy1 = m->points[h].y - y;
1015 z1 = m->points[h].z - z;
1016
1017 x2 = m->points[j].x - x;
1018 yy2 = m->points[j].y - y;
1019 z2 = m->points[j].z - z;
1020 nx = (yy1 * z2) - (z1 * yy2);
1021 ny = (z1 * x2) - (x1 * z2);
1022 nz = (x1 * yy2) - (yy1 * x2);
1023
1024 ln = (nx * nx) + (ny * ny) + (nz * nz);
1025 ln = sqrt(ln);
1026
1027 if (ln != 0.0)
1028 {
1029 nx /= ln;
1030 ny /= ln;
1031 nz /= ln;
1032 }
1033
1034 // calc point -> light vector
1035 x = lx - x;
1036 y = ly - y;
1037 z = lz - z;
1038
1039 ln = (x * x) + (y * y) + (z * z);
1040 ln = sqrt(ln);
1041
1042 if (ln != 0.0)
1043 {
1044 x /= ln;
1045 y /= ln;
1046 z /= ln;
1047 }
1048
1049 // brightness - tan (0.0 -> 1.0 brightness really)
1050 br = (nx * x) + (ny * y) + (nz * z);
1051 if (br < 0.0) br = 0.0;
1052
1053 mr = ar + ((lr - ar) * br);
1054 mg = ag + ((lg - ag) * br);
1055 mb = ab + ((lb - ab) * br);
1056 if (m->points[i].a != 255)
1057 {
1058 mr = (mr * m->points[i].a) / 255;
1059 mg = (mg * m->points[i].a) / 255;
1060 mb = (mb * m->points[i].a) / 255;
1061 }
1062 m->points[i].r = (m->points[i].r * mr) / 255;
1063 m->points[i].g = (m->points[i].g * mg) / 255;
1064 m->points[i].b = (m->points[i].b * mb) / 255;
1065 }
1066}
1067
1068EAPI void
1069evas_map_util_3d_perspective(Evas_Map *m,
1070 Evas_Coord px, Evas_Coord py,
1071 Evas_Coord z0, Evas_Coord foc)
1072{
1073 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
1074 return;
1075 MAGIC_CHECK_END();
1076
1077 Evas_Map_Point *p, *p_end;
1078
1079 p = m->points;
1080 p_end = p + m->count;
1081
1082 m->persp.px = px;
1083 m->persp.py = py;
1084 m->persp.z0 = z0;
1085 m->persp.foc = foc;
1086
1087 if (foc <= 0) return;
1088
1089 for (; p < p_end; p++)
1090 {
1091 double x, y, zz;
1092
1093 x = p->x - px;
1094 y = p->y - py;
1095
1096 zz = ((p->z - z0) + foc);
1097
1098 if (zz > 0)
1099 {
1100 x = (x * foc) / zz;
1101 y = (y * foc) / zz;
1102 }
1103
1104 p->x = px + x;
1105 p->y = py + y;
1106 }
1107}
1108
1109EAPI Eina_Bool
1110evas_map_util_clockwise_get(Evas_Map *m)
1111{
1112 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
1113 return EINA_FALSE;
1114 MAGIC_CHECK_END();
1115
1116 int i, j, k, count;
1117 long long c;
1118
1119 if (m->count < 3) return EINA_FALSE;
1120
1121 count = 0;
1122 for (i = 0; i < m->count; i++)
1123 {
1124 j = (i + 1) % m->count;
1125 k = (i + 2) % m->count;
1126 c =
1127 ((m->points[j].x - m->points[i].x) *
1128 (m->points[k].y - m->points[j].y))
1129 -
1130 ((m->points[j].y - m->points[i].y) *
1131 (m->points[k].x - m->points[j].x));
1132 if (c < 0) count--;
1133 else if (c > 0) count++;
1134 }
1135 if (count > 0) return EINA_TRUE;
1136 return EINA_FALSE;
1137}
1138
1139void
1140evas_object_map_update(Evas_Object *eo_obj,
1141 int x, int y,
1142 int imagew, int imageh,
1143 int uvw, int uvh)
1144{
1145 Evas_Object_Protected_Data *obj = eo_data_get(eo_obj, EVAS_OBJ_CLASS);
1146 const Evas_Map_Point *p, *p_end;
1147 RGBA_Map_Point *pts, *pt;
1148
1149 if (obj->spans)
1150 {
1151 if (obj->spans->x != x || obj->spans->y != y ||
1152 obj->spans->image.w != imagew || obj->spans->image.h != imageh ||
1153 obj->spans->uv.w != uvw || obj->spans->uv.h != uvh)
1154 obj->changed_map = EINA_TRUE;
1155 }
1156 else
1157 {
1158 obj->changed_map = EINA_TRUE;
1159 }
1160
1161 if (!obj->changed_map) return ;
1162
1163 if (obj->cur.map && obj->spans && obj->cur.map->count != obj->spans->count)
1164 {
1165 if (obj->spans)
1166 {
1167 // Destroy engine side spans
1168 free(obj->spans);
1169 }
1170 obj->spans = NULL;
1171 }
1172
1173 if (!obj->spans)
1174 obj->spans = calloc(1, sizeof (RGBA_Map) +
1175 sizeof (RGBA_Map_Point) * (obj->cur.map->count - 1));
1176
1177 if (!obj->spans) return ;
1178
1179 obj->spans->count = obj->cur.map->count;
1180 obj->spans->x = x;
1181 obj->spans->y = y;
1182 obj->spans->uv.w = uvw;
1183 obj->spans->uv.h = uvh;
1184 obj->spans->image.w = imagew;
1185 obj->spans->image.h = imageh;
1186
1187 pts = obj->spans->pts;
1188
1189 p = obj->cur.map->points;
1190 p_end = p + obj->cur.map->count;
1191 pt = pts;
1192
1193 pts[0].px = obj->cur.map->persp.px << FP;
1194 pts[0].py = obj->cur.map->persp.py << FP;
1195 pts[0].foc = obj->cur.map->persp.foc << FP;
1196 pts[0].z0 = obj->cur.map->persp.z0 << FP;
1197 // draw geom +x +y
1198 for (; p < p_end; p++, pt++)
1199 {
1200 pt->x = (lround(p->x) + x) * FP1;
1201 pt->y = (lround(p->y) + y) * FP1;
1202 pt->z = (lround(p->z) ) * FP1;
1203 pt->fx = p->px;
1204 pt->fy = p->py;
1205 pt->fz = p->z;
1206 pt->u = ((lround(p->u) * imagew) / uvw) * FP1;
1207 pt->v = ((lround(p->v) * imageh) / uvh) * FP1;
1208 if (pt->u < 0) pt->u = 0;
1209 else if (pt->u > (imagew * FP1)) pt->u = (imagew * FP1);
1210 if (pt->v < 0) pt->v = 0;
1211 else if (pt->v > (imageh * FP1)) pt->v = (imageh * FP1);
1212 pt->col = ARGB_JOIN(p->a, p->r, p->g, p->b);
1213 }
1214 if (obj->cur.map->count & 0x1)
1215 {
1216 pts[obj->cur.map->count] = pts[obj->cur.map->count -1];
1217 }
1218
1219 // Request engine to update it's point
1220}