diff options
Diffstat (limited to 'libraries/evas/src/lib/canvas/evas_map.c')
-rw-r--r-- | libraries/evas/src/lib/canvas/evas_map.c | 1031 |
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 | |||
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 (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 | |||
111 | static 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 | |||
140 | static 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 | |||
155 | static 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 | |||
167 | static 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 | /****************************************************************************/ | ||
183 | static 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 | |||
220 | Eina_Bool | ||
221 | evas_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 | |||
363 | Eina_Bool | ||
364 | evas_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 | |||
369 | EAPI void | ||
370 | evas_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 | |||
408 | EAPI Eina_Bool | ||
409 | evas_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 | |||
418 | EAPI void | ||
419 | evas_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 | |||
427 | EAPI Evas_Object * | ||
428 | evas_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 | |||
436 | EAPI void | ||
437 | evas_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 | |||
502 | EAPI const Evas_Map * | ||
503 | evas_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 | |||
512 | EAPI Evas_Map * | ||
513 | evas_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 | |||
524 | EAPI void | ||
525 | evas_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 | |||
534 | EAPI Eina_Bool | ||
535 | evas_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 | |||
544 | EAPI void | ||
545 | evas_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 | |||
554 | EAPI Eina_Bool | ||
555 | evas_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 | |||
564 | EAPI Evas_Map * | ||
565 | evas_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 | |||
574 | EAPI void | ||
575 | evas_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 | |||
584 | EAPI int | ||
585 | evas_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 | |||
594 | EAPI void | ||
595 | evas_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 | |||
610 | EAPI void | ||
611 | evas_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 | |||
632 | EAPI void | ||
633 | evas_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 | |||
647 | EAPI void | ||
648 | evas_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 | |||
667 | EAPI void | ||
668 | evas_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 | |||
684 | EAPI void | ||
685 | evas_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 | |||
701 | EAPI void | ||
702 | evas_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 | |||
717 | EAPI void | ||
718 | evas_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 | |||
737 | EAPI void | ||
738 | 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) | ||
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 | |||
752 | EAPI void | ||
753 | evas_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 | |||
772 | EAPI void | ||
773 | evas_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 | |||
802 | EAPI void | ||
803 | evas_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 | |||
829 | EAPI void | ||
830 | evas_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 | |||
883 | EAPI void | ||
884 | evas_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 | |||
962 | EAPI void | ||
963 | evas_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 | |||
1003 | EAPI Eina_Bool | ||
1004 | evas_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 | } | ||