diff options
author | David Walter Seikel | 2012-01-04 18:41:13 +1000 |
---|---|---|
committer | David Walter Seikel | 2012-01-04 18:41:13 +1000 |
commit | dd7595a3475407a7fa96a97393bae8c5220e8762 (patch) | |
tree | e341e911d7eb911a51684a7412ef7f7c7605d28e /libraries/evas/src/lib/engines/common/evas_tiler.c | |
parent | Add the skeleton. (diff) | |
download | SledjHamr-dd7595a3475407a7fa96a97393bae8c5220e8762.zip SledjHamr-dd7595a3475407a7fa96a97393bae8c5220e8762.tar.gz SledjHamr-dd7595a3475407a7fa96a97393bae8c5220e8762.tar.bz2 SledjHamr-dd7595a3475407a7fa96a97393bae8c5220e8762.tar.xz |
Add the base Enlightenment Foundation Libraries - eina, eet, evas, ecore, embryo, and edje.
Note that embryo wont be used, but I'm not sure yet if you can build edje without it.
Diffstat (limited to 'libraries/evas/src/lib/engines/common/evas_tiler.c')
-rw-r--r-- | libraries/evas/src/lib/engines/common/evas_tiler.c | 1391 |
1 files changed, 1391 insertions, 0 deletions
diff --git a/libraries/evas/src/lib/engines/common/evas_tiler.c b/libraries/evas/src/lib/engines/common/evas_tiler.c new file mode 100644 index 0000000..0bbe811 --- /dev/null +++ b/libraries/evas/src/lib/engines/common/evas_tiler.c | |||
@@ -0,0 +1,1391 @@ | |||
1 | #include "evas_common.h" | ||
2 | #ifdef EVAS_RECT_SPLIT | ||
3 | |||
4 | static inline void rect_list_node_pool_set_max(int max); | ||
5 | static inline void rect_list_node_pool_flush(void); | ||
6 | static inline list_node_t *rect_list_node_pool_get(void); | ||
7 | static inline void rect_list_node_pool_put(list_node_t *node); | ||
8 | static inline void rect_init(rect_t *r, int x, int y, int w, int h); | ||
9 | static inline void rect_list_append_node(list_t *rects, list_node_t *node); | ||
10 | static inline void rect_list_append(list_t *rects, const rect_t r); | ||
11 | static inline void rect_list_append_xywh(list_t *rects, int x, int y, int w, int h); | ||
12 | static inline void rect_list_concat(list_t *rects, list_t *other); | ||
13 | static inline list_node_t *rect_list_unlink_next(list_t *rects, list_node_t *parent_node); | ||
14 | static inline void rect_list_del_next(list_t *rects, list_node_t *parent_node); | ||
15 | static inline void rect_list_clear(list_t *rects); | ||
16 | static inline void rect_list_del_split_strict(list_t *rects, const rect_t del_r); | ||
17 | static inline void rect_list_add_split_strict(list_t *rects, list_node_t *node); | ||
18 | static inline list_node_t *rect_list_add_split_fuzzy(list_t *rects, list_node_t *node, int accepted_error); | ||
19 | static inline void rect_list_merge_rects(list_t *rects, list_t *to_merge, int accepted_error); | ||
20 | static inline void rect_list_add_split_fuzzy_and_merge(list_t *rects, list_node_t *node, int split_accepted_error, int merge_accepted_error); | ||
21 | static inline void rect_print(const rect_t r); | ||
22 | static inline void rect_list_print(const list_t rects); | ||
23 | |||
24 | static const list_node_t list_node_zeroed = { NULL }; | ||
25 | static const list_t list_zeroed = { NULL, NULL }; | ||
26 | |||
27 | typedef struct list_node_pool | ||
28 | { | ||
29 | list_node_t *node; | ||
30 | int len; | ||
31 | int max; | ||
32 | } list_node_pool_t; | ||
33 | |||
34 | static list_node_pool_t list_node_pool = { NULL, 0, 1024 }; | ||
35 | |||
36 | static inline void | ||
37 | rect_list_node_pool_set_max(int max) | ||
38 | { | ||
39 | int diff; | ||
40 | |||
41 | diff = list_node_pool.len - max; | ||
42 | for (; diff > 0 && list_node_pool.node; diff--) | ||
43 | { | ||
44 | list_node_t *node; | ||
45 | |||
46 | node = list_node_pool.node; | ||
47 | list_node_pool.node = node->next; | ||
48 | list_node_pool.len--; | ||
49 | |||
50 | free(node); | ||
51 | } | ||
52 | |||
53 | list_node_pool.max = max; | ||
54 | } | ||
55 | |||
56 | static inline void | ||
57 | rect_list_node_pool_flush(void) | ||
58 | { | ||
59 | while (list_node_pool.node) | ||
60 | { | ||
61 | list_node_t *node; | ||
62 | |||
63 | node = list_node_pool.node; | ||
64 | list_node_pool.node = node->next; | ||
65 | list_node_pool.len--; | ||
66 | |||
67 | free(node); | ||
68 | } | ||
69 | } | ||
70 | |||
71 | static inline list_node_t * | ||
72 | rect_list_node_pool_get(void) | ||
73 | { | ||
74 | if (list_node_pool.node) | ||
75 | { | ||
76 | list_node_t *node; | ||
77 | |||
78 | node = list_node_pool.node; | ||
79 | list_node_pool.node = node->next; | ||
80 | list_node_pool.len--; | ||
81 | |||
82 | return node; | ||
83 | } | ||
84 | else return malloc(sizeof(rect_node_t)); | ||
85 | } | ||
86 | |||
87 | static inline void | ||
88 | rect_list_node_pool_put(list_node_t *node) | ||
89 | { | ||
90 | if (list_node_pool.len < list_node_pool.max) | ||
91 | { | ||
92 | node->next = list_node_pool.node; | ||
93 | list_node_pool.node = node; | ||
94 | list_node_pool.len++; | ||
95 | } | ||
96 | else free(node); | ||
97 | } | ||
98 | |||
99 | static inline void | ||
100 | rect_init(rect_t *r, int x, int y, int w, int h) | ||
101 | { | ||
102 | r->area = w * h; | ||
103 | |||
104 | r->left = x; | ||
105 | r->top = y; | ||
106 | |||
107 | r->right = x + w; | ||
108 | r->bottom = y + h; | ||
109 | |||
110 | r->width = w; | ||
111 | r->height = h; | ||
112 | } | ||
113 | |||
114 | static inline void | ||
115 | rect_print(const rect_t r) | ||
116 | { | ||
117 | INF("<rect(%d, %d, %d, %d)>", r.left, r.top, r.width, r.height); | ||
118 | } | ||
119 | |||
120 | static inline void | ||
121 | rect_list_print(const list_t rects) | ||
122 | { | ||
123 | list_node_t *node; | ||
124 | int len; | ||
125 | |||
126 | len = 0; | ||
127 | for (node = rects.head; node; node = node->next) len++; | ||
128 | |||
129 | putchar('['); | ||
130 | for (node = rects.head; node; node = node->next) | ||
131 | { | ||
132 | rect_print(((rect_node_t *)node)->rect); | ||
133 | if (node->next) | ||
134 | { | ||
135 | putchar(','); | ||
136 | if (len < 4) putchar(' '); | ||
137 | else | ||
138 | { | ||
139 | putchar('\n'); | ||
140 | putchar(' '); | ||
141 | } | ||
142 | } | ||
143 | } | ||
144 | putchar(']'); | ||
145 | } | ||
146 | |||
147 | static inline void | ||
148 | rect_list_append_node(list_t *rects, list_node_t *node) | ||
149 | { | ||
150 | if (rects->tail) | ||
151 | { | ||
152 | rects->tail->next = node; | ||
153 | rects->tail = node; | ||
154 | } | ||
155 | else | ||
156 | { | ||
157 | rects->head = node; | ||
158 | rects->tail = node; | ||
159 | } | ||
160 | } | ||
161 | |||
162 | static inline void | ||
163 | rect_list_append(list_t *rects, const rect_t r) | ||
164 | { | ||
165 | rect_node_t *rect_node; | ||
166 | |||
167 | rect_node = (rect_node_t *)rect_list_node_pool_get(); | ||
168 | rect_node->rect = r; | ||
169 | rect_node->_lst = list_node_zeroed; | ||
170 | |||
171 | rect_list_append_node(rects, (list_node_t *)rect_node); | ||
172 | } | ||
173 | |||
174 | static inline void | ||
175 | rect_list_append_xywh(list_t *rects, int x, int y, int w, int h) | ||
176 | { | ||
177 | rect_t r; | ||
178 | |||
179 | rect_init(&r, x, y, w, h); | ||
180 | rect_list_append(rects, r); | ||
181 | } | ||
182 | |||
183 | static inline void | ||
184 | rect_list_concat(list_t *rects, list_t *other) | ||
185 | { | ||
186 | if (!other->head) | ||
187 | return; | ||
188 | |||
189 | if (rects->tail) | ||
190 | { | ||
191 | rects->tail->next = other->head; | ||
192 | rects->tail = other->tail; | ||
193 | } | ||
194 | else | ||
195 | { | ||
196 | rects->head = other->head; | ||
197 | rects->tail = other->tail; | ||
198 | } | ||
199 | *other = list_zeroed; | ||
200 | } | ||
201 | |||
202 | static inline list_node_t * | ||
203 | rect_list_unlink_next(list_t *rects, list_node_t *parent_node) | ||
204 | { | ||
205 | list_node_t *node; | ||
206 | |||
207 | if (parent_node) | ||
208 | { | ||
209 | node = parent_node->next; | ||
210 | parent_node->next = node->next; | ||
211 | } | ||
212 | else | ||
213 | { | ||
214 | node = rects->head; | ||
215 | rects->head = node->next; | ||
216 | } | ||
217 | |||
218 | if (rects->tail == node) rects->tail = parent_node; | ||
219 | *node = list_node_zeroed; | ||
220 | return node; | ||
221 | } | ||
222 | |||
223 | static inline void | ||
224 | rect_list_del_next(list_t *rects, list_node_t *parent_node) | ||
225 | { | ||
226 | list_node_t *node; | ||
227 | |||
228 | node = rect_list_unlink_next(rects, parent_node); | ||
229 | rect_list_node_pool_put(node); | ||
230 | } | ||
231 | |||
232 | static inline void | ||
233 | rect_list_clear(list_t *rects) | ||
234 | { | ||
235 | list_node_t *node; | ||
236 | |||
237 | node = rects->head; | ||
238 | while (node) | ||
239 | { | ||
240 | list_node_t *aux; | ||
241 | |||
242 | aux = node->next; | ||
243 | rect_list_node_pool_put(node); | ||
244 | node = aux; | ||
245 | } | ||
246 | *rects = list_zeroed; | ||
247 | } | ||
248 | |||
249 | static inline void | ||
250 | _calc_intra_rect_area(const rect_t a, const rect_t b, int *width, int *height) | ||
251 | { | ||
252 | int max_left, min_right, max_top, min_bottom; | ||
253 | |||
254 | if (a.left < b.left) max_left = b.left; | ||
255 | else max_left = a.left; | ||
256 | |||
257 | if (a.right < b.right) min_right = a.right; | ||
258 | else min_right = b.right; | ||
259 | |||
260 | *width = min_right - max_left; | ||
261 | |||
262 | if (a.top < b.top) max_top = b.top; | ||
263 | else max_top = a.top; | ||
264 | |||
265 | if (a.bottom < b.bottom) min_bottom = a.bottom; | ||
266 | else min_bottom = b.bottom; | ||
267 | |||
268 | *height = min_bottom - max_top; | ||
269 | } | ||
270 | |||
271 | static inline void | ||
272 | _split_strict(list_t *dirty, const rect_t current, rect_t r) | ||
273 | { | ||
274 | int h_1, h_2, w_1, w_2; | ||
275 | |||
276 | h_1 = current.top - r.top; | ||
277 | h_2 = r.bottom - current.bottom; | ||
278 | w_1 = current.left - r.left; | ||
279 | w_2 = r.right - current.right; | ||
280 | |||
281 | if (h_1 > 0) | ||
282 | { | ||
283 | /* .--.r (b) .---.r2 | ||
284 | * | | | | | ||
285 | * .-------.cur (a) .---.r '---' | ||
286 | * | | | | -> | | + | ||
287 | * | `--' | `---' | ||
288 | * `-------' | ||
289 | */ | ||
290 | rect_list_append_xywh(dirty, r.left, r.top, r.width, h_1); | ||
291 | r.height -= h_1; | ||
292 | r.top = current.top; | ||
293 | } | ||
294 | |||
295 | if (h_2 > 0) | ||
296 | { | ||
297 | /* .-------.cur (a) | ||
298 | * | .---. | .---.r | ||
299 | * | | | | -> | | | ||
300 | * `-------' `---' + .---.r2 | ||
301 | * | | | | | ||
302 | * `---'r (b) `---' | ||
303 | */ | ||
304 | rect_list_append_xywh(dirty, r.left, current.bottom, r.width, h_2); | ||
305 | r.height -= h_2; | ||
306 | } | ||
307 | |||
308 | if (w_1 > 0) | ||
309 | { | ||
310 | /* (b) r .----.cur (a) | ||
311 | * .--|-. | .--.r2 .-.r | ||
312 | * | | | | -> | | + | | | ||
313 | * `--|-' | `--' `-' | ||
314 | * `----' | ||
315 | */ | ||
316 | rect_list_append_xywh(dirty, r.left, r.top, w_1, r.height); | ||
317 | /* not necessary to keep these, r (b) will be destroyed */ | ||
318 | /* r.width -= w_1; */ | ||
319 | /* r.left = current.left; */ | ||
320 | } | ||
321 | |||
322 | if (w_2 > 0) | ||
323 | { | ||
324 | /* .----.cur (a) | ||
325 | * | | | ||
326 | * | .-|--.r (b) .-.r .--.r2 | ||
327 | * | | | | -> | | + | | | ||
328 | * | `-|--' `-' `--' | ||
329 | * `----' | ||
330 | */ | ||
331 | rect_list_append_xywh(dirty, current.right, r.top, w_2, r.height); | ||
332 | /* not necessary to keep this, r (b) will be destroyed */ | ||
333 | /* r.width -= w_2; */ | ||
334 | } | ||
335 | } | ||
336 | |||
337 | static inline void | ||
338 | rect_list_del_split_strict(list_t *rects, const rect_t del_r) | ||
339 | { | ||
340 | list_t modified = list_zeroed; | ||
341 | list_node_t *cur_node, *prev_node; | ||
342 | |||
343 | prev_node = NULL; | ||
344 | cur_node = rects->head; | ||
345 | while (cur_node) | ||
346 | { | ||
347 | int intra_width, intra_height; | ||
348 | rect_t current; | ||
349 | |||
350 | current = ((rect_node_t*)cur_node)->rect; | ||
351 | |||
352 | _calc_intra_rect_area(del_r, current, &intra_width, &intra_height); | ||
353 | if ((intra_width <= 0) || (intra_height <= 0)) | ||
354 | { | ||
355 | /* .---.current .---.del_r | ||
356 | * | | | | | ||
357 | * `---+---.del_r `---+---.current | ||
358 | * | | | | | ||
359 | * `---' `---' | ||
360 | * no interception, nothing to do | ||
361 | */ | ||
362 | prev_node = cur_node; | ||
363 | cur_node = cur_node->next; | ||
364 | } | ||
365 | else if ((intra_width == current.width) && | ||
366 | (intra_height == current.height)) | ||
367 | { | ||
368 | /* .-------.del_r | ||
369 | * | .---. | | ||
370 | * | | | | | ||
371 | * | `---'current | ||
372 | * `-------' | ||
373 | * current is contained, remove from rects | ||
374 | */ | ||
375 | cur_node = cur_node->next; | ||
376 | rect_list_del_next(rects, prev_node); | ||
377 | } | ||
378 | else | ||
379 | { | ||
380 | _split_strict(&modified, del_r, current); | ||
381 | cur_node = cur_node->next; | ||
382 | rect_list_del_next(rects, prev_node); | ||
383 | } | ||
384 | } | ||
385 | |||
386 | rect_list_concat(rects, &modified); | ||
387 | } | ||
388 | |||
389 | static inline void | ||
390 | rect_list_add_split_strict(list_t *rects, list_node_t *node) | ||
391 | { | ||
392 | list_t dirty = list_zeroed; | ||
393 | list_t new_dirty = list_zeroed; | ||
394 | list_node_t *cur_node; | ||
395 | |||
396 | if (!rects->head) | ||
397 | { | ||
398 | rect_list_append_node(rects, node); | ||
399 | return; | ||
400 | } | ||
401 | |||
402 | rect_list_append_node(&dirty, node); | ||
403 | |||
404 | cur_node = rects->head; | ||
405 | while (dirty.head) | ||
406 | { | ||
407 | rect_t current; | ||
408 | |||
409 | if (!cur_node) | ||
410 | { | ||
411 | rect_list_concat(rects, &dirty); | ||
412 | break; | ||
413 | } | ||
414 | |||
415 | current = ((rect_node_t*)cur_node)->rect; | ||
416 | |||
417 | while (dirty.head) | ||
418 | { | ||
419 | int intra_width, intra_height; | ||
420 | rect_t r; | ||
421 | |||
422 | r = ((rect_node_t *)dirty.head)->rect; | ||
423 | _calc_intra_rect_area(r, current, &intra_width, &intra_height); | ||
424 | if ((intra_width == r.width) && (intra_height == r.height)) | ||
425 | /* .-------.cur | ||
426 | * | .---.r| | ||
427 | * | | | | | ||
428 | * | `---' | | ||
429 | * `-------' | ||
430 | */ | ||
431 | rect_list_del_next(&dirty, NULL); | ||
432 | else if ((intra_width <= 0) || (intra_height <= 0)) | ||
433 | { | ||
434 | /* .---.cur .---.r | ||
435 | * | | | | | ||
436 | * `---+---.r `---+---.cur | ||
437 | * | | | | | ||
438 | * `---' `---' | ||
439 | */ | ||
440 | list_node_t *tmp; | ||
441 | tmp = rect_list_unlink_next(&dirty, NULL); | ||
442 | rect_list_append_node(&new_dirty, tmp); | ||
443 | } | ||
444 | else | ||
445 | { | ||
446 | _split_strict(&new_dirty, current, r); | ||
447 | rect_list_del_next(&dirty, NULL); | ||
448 | } | ||
449 | } | ||
450 | dirty = new_dirty; | ||
451 | new_dirty = list_zeroed; | ||
452 | |||
453 | cur_node = cur_node->next; | ||
454 | } | ||
455 | } | ||
456 | |||
457 | static inline void | ||
458 | _calc_intra_outer_rect_area(const rect_t a, const rect_t b, | ||
459 | rect_t *intra, rect_t *outer) | ||
460 | { | ||
461 | int min_left, max_left, min_right, max_right; | ||
462 | int min_top, max_top, min_bottom, max_bottom; | ||
463 | |||
464 | if (a.left < b.left) | ||
465 | { | ||
466 | max_left = b.left; | ||
467 | min_left = a.left; | ||
468 | } | ||
469 | else | ||
470 | { | ||
471 | max_left = a.left; | ||
472 | min_left = b.left; | ||
473 | } | ||
474 | |||
475 | if (a.right < b.right) | ||
476 | { | ||
477 | min_right = a.right; | ||
478 | max_right = b.right; | ||
479 | } | ||
480 | else | ||
481 | { | ||
482 | min_right = b.right; | ||
483 | max_right = a.right; | ||
484 | } | ||
485 | |||
486 | intra->left = max_left; | ||
487 | intra->right = min_right; | ||
488 | intra->width = min_right - max_left; | ||
489 | |||
490 | outer->left = min_left; | ||
491 | outer->right = max_right; | ||
492 | outer->width = max_right - min_left; | ||
493 | |||
494 | if (a.top < b.top) | ||
495 | { | ||
496 | max_top = b.top; | ||
497 | min_top = a.top; | ||
498 | } | ||
499 | else | ||
500 | { | ||
501 | max_top = a.top; | ||
502 | min_top = b.top; | ||
503 | } | ||
504 | |||
505 | if (a.bottom < b.bottom) | ||
506 | { | ||
507 | min_bottom = a.bottom; | ||
508 | max_bottom = b.bottom; | ||
509 | } | ||
510 | else | ||
511 | { | ||
512 | min_bottom = b.bottom; | ||
513 | max_bottom = a.bottom; | ||
514 | } | ||
515 | |||
516 | intra->top = max_top; | ||
517 | intra->bottom = min_bottom; | ||
518 | intra->height = min_bottom - max_top; | ||
519 | if ((intra->width > 0) && (intra->height > 0)) | ||
520 | intra->area = intra->width * intra->height; | ||
521 | else | ||
522 | intra->area = 0; | ||
523 | |||
524 | outer->top = min_top; | ||
525 | outer->bottom = max_bottom; | ||
526 | outer->height = max_bottom - min_top; | ||
527 | outer->area = outer->width * outer->height; | ||
528 | } | ||
529 | |||
530 | enum | ||
531 | { | ||
532 | SPLIT_FUZZY_ACTION_NONE, | ||
533 | SPLIT_FUZZY_ACTION_SPLIT, | ||
534 | SPLIT_FUZZY_ACTION_MERGE | ||
535 | }; | ||
536 | |||
537 | static inline int | ||
538 | _split_fuzzy(list_t *dirty, const rect_t a, rect_t *b) | ||
539 | { | ||
540 | int h_1, h_2, w_1, w_2, action; | ||
541 | |||
542 | h_1 = a.top - b->top; | ||
543 | h_2 = b->bottom - a.bottom; | ||
544 | w_1 = a.left - b->left; | ||
545 | w_2 = b->right - a.right; | ||
546 | |||
547 | action = SPLIT_FUZZY_ACTION_NONE; | ||
548 | |||
549 | if (h_1 > 0) | ||
550 | { | ||
551 | /* .--.r (b) .---.r2 | ||
552 | * | | | | | ||
553 | * .-------.cur (a) .---.r '---' | ||
554 | * | | | | -> | | + | ||
555 | * | `--' | `---' | ||
556 | * `-------' | ||
557 | */ | ||
558 | rect_list_append_xywh(dirty, b->left, b->top, b->width, h_1); | ||
559 | b->height -= h_1; | ||
560 | b->top = a.top; | ||
561 | action = SPLIT_FUZZY_ACTION_SPLIT; | ||
562 | } | ||
563 | |||
564 | if (h_2 > 0) | ||
565 | { | ||
566 | /* .-------.cur (a) | ||
567 | * | .---. | .---.r | ||
568 | * | | | | -> | | | ||
569 | * `-------' `---' + .---.r2 | ||
570 | * | | | | | ||
571 | * `---'r (b) `---' | ||
572 | */ | ||
573 | rect_list_append_xywh(dirty, b->left, a.bottom, b->width, h_2); | ||
574 | b->height -= h_2; | ||
575 | action = SPLIT_FUZZY_ACTION_SPLIT; | ||
576 | } | ||
577 | |||
578 | if (((w_1 > 0) || (w_2 > 0)) && (a.height == b->height)) | ||
579 | return SPLIT_FUZZY_ACTION_MERGE; | ||
580 | |||
581 | if (w_1 > 0) | ||
582 | { | ||
583 | /* (b) r .----.cur (a) | ||
584 | * .--|-. | .--.r2 .-.r | ||
585 | * | | | | -> | | + | | | ||
586 | * `--|-' | `--' `-' | ||
587 | * `----' | ||
588 | */ | ||
589 | rect_list_append_xywh(dirty, b->left, b->top, w_1, b->height); | ||
590 | /* not necessary to keep these, r (b) will be destroyed */ | ||
591 | /* b->width -= w_1; */ | ||
592 | /* b->left = a.left; */ | ||
593 | action = SPLIT_FUZZY_ACTION_SPLIT; | ||
594 | } | ||
595 | |||
596 | if (w_2 > 0) | ||
597 | { | ||
598 | /* .----.cur (a) | ||
599 | * | | | ||
600 | * | .-|--.r (b) .-.r .--.r2 | ||
601 | * | | | | -> | | + | | | ||
602 | * | `-|--' `-' `--' | ||
603 | * `----' | ||
604 | */ | ||
605 | rect_list_append_xywh(dirty, a.right, b->top, w_2, b->height); | ||
606 | /* not necessary to keep these, r (b) will be destroyed */ | ||
607 | /* b->width -= w_2; */ | ||
608 | action = SPLIT_FUZZY_ACTION_SPLIT; | ||
609 | } | ||
610 | |||
611 | return action; | ||
612 | } | ||
613 | |||
614 | static inline list_node_t * | ||
615 | rect_list_add_split_fuzzy(list_t *rects, list_node_t *node, int accepted_error) | ||
616 | { | ||
617 | list_t dirty = list_zeroed; | ||
618 | list_node_t *old_last; | ||
619 | |||
620 | old_last = rects->tail; | ||
621 | |||
622 | if (!rects->head) | ||
623 | { | ||
624 | rect_list_append_node(rects, node); | ||
625 | return old_last; | ||
626 | } | ||
627 | |||
628 | rect_list_append_node(&dirty, node); | ||
629 | while (dirty.head) | ||
630 | { | ||
631 | list_node_t *d_node, *cur_node, *prev_cur_node; | ||
632 | int keep_dirty; | ||
633 | rect_t r; | ||
634 | |||
635 | d_node = rect_list_unlink_next(&dirty, NULL); | ||
636 | r = ((rect_node_t *)d_node)->rect; | ||
637 | |||
638 | prev_cur_node = NULL; | ||
639 | cur_node = rects->head; | ||
640 | keep_dirty = 1; | ||
641 | while (cur_node) | ||
642 | { | ||
643 | int area, action; | ||
644 | rect_t current, intra, outer; | ||
645 | |||
646 | current = ((rect_node_t *)cur_node)->rect; | ||
647 | |||
648 | _calc_intra_outer_rect_area(r, current, &intra, &outer); | ||
649 | area = current.area + r.area - intra.area; | ||
650 | |||
651 | if ((intra.width == r.width) && (intra.height == r.height)) | ||
652 | { | ||
653 | /* .-------.cur | ||
654 | * | .---.r| | ||
655 | * | | | | | ||
656 | * | `---' | | ||
657 | * `-------' | ||
658 | */ | ||
659 | keep_dirty = 0; | ||
660 | break; | ||
661 | } | ||
662 | else if ((intra.width == current.width) && | ||
663 | (intra.height == current.height)) | ||
664 | { | ||
665 | /* .-------.r | ||
666 | * | .---.cur | ||
667 | * | | | | | ||
668 | * | `---' | | ||
669 | * `-------' | ||
670 | */ | ||
671 | if (old_last == cur_node) | ||
672 | old_last = prev_cur_node; | ||
673 | cur_node = cur_node->next; | ||
674 | rect_list_del_next(rects, prev_cur_node); | ||
675 | } | ||
676 | else if ((outer.area - area) <= accepted_error) | ||
677 | { | ||
678 | /* .-----------. bounding box (outer) | ||
679 | * |.---. .---.| | ||
680 | * ||cur| |r || | ||
681 | * || | | || | ||
682 | * |`---' `---'| | ||
683 | * `-----------' | ||
684 | * merge them, remove both and add merged | ||
685 | */ | ||
686 | rect_node_t *n; | ||
687 | |||
688 | if (old_last == cur_node) | ||
689 | old_last = prev_cur_node; | ||
690 | |||
691 | n = (rect_node_t *)rect_list_unlink_next(rects, prev_cur_node); | ||
692 | n->rect = outer; | ||
693 | rect_list_append_node(&dirty, (list_node_t *)n); | ||
694 | |||
695 | keep_dirty = 0; | ||
696 | break; | ||
697 | } | ||
698 | else if (intra.area <= accepted_error) | ||
699 | { | ||
700 | /* .---.cur .---.r | ||
701 | * | | | | | ||
702 | * `---+---.r `---+---.cur | ||
703 | * | | | | | ||
704 | * `---' `---' | ||
705 | * no split, no merge | ||
706 | */ | ||
707 | prev_cur_node = cur_node; | ||
708 | cur_node = cur_node->next; | ||
709 | } | ||
710 | else | ||
711 | { | ||
712 | /* split is required */ | ||
713 | action = _split_fuzzy(&dirty, current, &r); | ||
714 | if (action == SPLIT_FUZZY_ACTION_MERGE) | ||
715 | { | ||
716 | /* horizontal merge is possible: remove both, add merged */ | ||
717 | rect_node_t *n; | ||
718 | |||
719 | if (old_last == cur_node) | ||
720 | old_last = prev_cur_node; | ||
721 | |||
722 | n = (rect_node_t *) | ||
723 | rect_list_unlink_next(rects, prev_cur_node); | ||
724 | |||
725 | n->rect.left = outer.left; | ||
726 | n->rect.width = outer.width; | ||
727 | n->rect.right = outer.right; | ||
728 | n->rect.area = outer.width * r.height; | ||
729 | rect_list_append_node(&dirty, (list_node_t *)n); | ||
730 | } | ||
731 | else if (action == SPLIT_FUZZY_ACTION_NONE) | ||
732 | { | ||
733 | /* | ||
734 | * this rect check was totally useless, | ||
735 | * should never happen | ||
736 | */ | ||
737 | /* prev_cur_node = cur_node; */ | ||
738 | /* cur_node = cur_node->next; */ | ||
739 | WRN("Should not get here!"); | ||
740 | abort(); | ||
741 | } | ||
742 | |||
743 | keep_dirty = 0; | ||
744 | break; | ||
745 | } | ||
746 | } | ||
747 | |||
748 | if (UNLIKELY(keep_dirty)) rect_list_append_node(rects, d_node); | ||
749 | else rect_list_node_pool_put(d_node); | ||
750 | } | ||
751 | |||
752 | return old_last; | ||
753 | } | ||
754 | |||
755 | static inline void | ||
756 | _calc_outer_rect_area(const rect_t a, const rect_t b, rect_t *outer) | ||
757 | { | ||
758 | int min_left, max_right; | ||
759 | int min_top, max_bottom; | ||
760 | |||
761 | if (a.left < b.left) min_left = a.left; | ||
762 | else min_left = b.left; | ||
763 | |||
764 | if (a.right < b.right) max_right = b.right; | ||
765 | else max_right = a.right; | ||
766 | |||
767 | outer->left = min_left; | ||
768 | outer->right = max_right; | ||
769 | outer->width = max_right - min_left; | ||
770 | |||
771 | if (a.top < b.top) min_top = a.top; | ||
772 | else min_top = b.top; | ||
773 | |||
774 | if (a.bottom < b.bottom) max_bottom = b.bottom; | ||
775 | else max_bottom = a.bottom; | ||
776 | |||
777 | outer->top = min_top; | ||
778 | outer->bottom = max_bottom; | ||
779 | outer->height = max_bottom - min_top; | ||
780 | |||
781 | outer->area = outer->width * outer->height; | ||
782 | } | ||
783 | |||
784 | static inline void | ||
785 | rect_list_merge_rects(list_t *rects, list_t *to_merge, int accepted_error) | ||
786 | { | ||
787 | while (to_merge->head) | ||
788 | { | ||
789 | list_node_t *node, *parent_node; | ||
790 | rect_t r1; | ||
791 | int merged; | ||
792 | |||
793 | r1 = ((rect_node_t *)to_merge->head)->rect; | ||
794 | |||
795 | merged = 0; | ||
796 | parent_node = NULL; | ||
797 | node = rects->head; | ||
798 | while (node) | ||
799 | { | ||
800 | rect_t r2, outer; | ||
801 | int area; | ||
802 | |||
803 | r2 = ((rect_node_t *)node)->rect; | ||
804 | |||
805 | _calc_outer_rect_area(r1, r2, &outer); | ||
806 | area = r1.area + r2.area; /* intra area is taken as 0 */ | ||
807 | if (outer.area - area <= accepted_error) | ||
808 | { | ||
809 | /* | ||
810 | * remove both r1 and r2, create r3 | ||
811 | * actually r3 uses r2 instance, saves memory | ||
812 | */ | ||
813 | rect_node_t *n; | ||
814 | |||
815 | n = (rect_node_t *)rect_list_unlink_next(rects, parent_node); | ||
816 | n->rect = outer; | ||
817 | rect_list_append_node(to_merge, (list_node_t *)n); | ||
818 | merged = 1; | ||
819 | break; | ||
820 | } | ||
821 | |||
822 | parent_node = node; | ||
823 | node = node->next; | ||
824 | } | ||
825 | |||
826 | if (!merged) | ||
827 | { | ||
828 | list_node_t *n; | ||
829 | n = rect_list_unlink_next(to_merge, NULL); | ||
830 | rect_list_append_node(rects, n); | ||
831 | } | ||
832 | else | ||
833 | rect_list_del_next(to_merge, NULL); | ||
834 | } | ||
835 | } | ||
836 | |||
837 | static inline void | ||
838 | rect_list_add_split_fuzzy_and_merge(list_t *rects, | ||
839 | list_node_t *node, | ||
840 | int split_accepted_error, | ||
841 | int merge_accepted_error) | ||
842 | { | ||
843 | list_node_t *n; | ||
844 | |||
845 | n = rect_list_add_split_fuzzy(rects, node, split_accepted_error); | ||
846 | if (n && n->next) | ||
847 | { | ||
848 | list_t to_merge; | ||
849 | |||
850 | /* split list into 2 segments, already merged and to merge */ | ||
851 | to_merge.head = n->next; | ||
852 | to_merge.tail = rects->tail; | ||
853 | rects->tail = n; | ||
854 | n->next = NULL; | ||
855 | |||
856 | rect_list_merge_rects(rects, &to_merge, merge_accepted_error); | ||
857 | } | ||
858 | } | ||
859 | #endif /* EVAS_RECT_SPLIT */ | ||
860 | |||
861 | #define TILE(tb, x, y) ((tb)->tiles.tiles[((y) * (tb)->tiles.w) + (x)]) | ||
862 | |||
863 | #ifdef RECTUPDATE | ||
864 | #elif defined(EVAS_RECT_SPLIT) | ||
865 | #else | ||
866 | /* | ||
867 | static int tilebuf_x_intersect(Tilebuf *tb, int x, int w, int *x1, int *x2, int *x1_fill, int *x2_fill); | ||
868 | static int tilebuf_y_intersect(Tilebuf *tb, int y, int h, int *y1, int *y2, int *y1_fill, int *y2_fill); | ||
869 | static int tilebuf_intersect(int tsize, int tlen, int tnum, int x, int w, int *x1, int *x2, int *x1_fill, int *x2_fill); | ||
870 | */ | ||
871 | #endif | ||
872 | /* | ||
873 | static void tilebuf_setup(Tilebuf *tb); | ||
874 | */ | ||
875 | |||
876 | EAPI void | ||
877 | evas_common_tilebuf_init(void) | ||
878 | { | ||
879 | } | ||
880 | |||
881 | EAPI Tilebuf * | ||
882 | evas_common_tilebuf_new(int w, int h) | ||
883 | { | ||
884 | Tilebuf *tb; | ||
885 | |||
886 | tb = calloc(1, sizeof(Tilebuf)); | ||
887 | if (!tb) return NULL; | ||
888 | |||
889 | tb->tile_size.w = 8; | ||
890 | tb->tile_size.h = 8; | ||
891 | tb->outbuf_w = w; | ||
892 | tb->outbuf_h = h; | ||
893 | |||
894 | return tb; | ||
895 | } | ||
896 | |||
897 | EAPI void | ||
898 | evas_common_tilebuf_free(Tilebuf *tb) | ||
899 | { | ||
900 | #ifdef RECTUPDATE | ||
901 | /* | ||
902 | evas_common_regionbuf_free(tb->rb); | ||
903 | */ | ||
904 | #elif defined(EVAS_RECT_SPLIT) | ||
905 | rect_list_clear(&tb->rects); | ||
906 | rect_list_node_pool_flush(); | ||
907 | #else | ||
908 | /* | ||
909 | if (tb->tiles.tiles) free(tb->tiles.tiles); | ||
910 | */ | ||
911 | #endif | ||
912 | free(tb); | ||
913 | } | ||
914 | |||
915 | EAPI void | ||
916 | evas_common_tilebuf_set_tile_size(Tilebuf *tb, int tw, int th) | ||
917 | { | ||
918 | tb->tile_size.w = tw; | ||
919 | tb->tile_size.h = th; | ||
920 | /* | ||
921 | tilebuf_setup(tb); | ||
922 | */ | ||
923 | } | ||
924 | |||
925 | EAPI void | ||
926 | evas_common_tilebuf_get_tile_size(Tilebuf *tb, int *tw, int *th) | ||
927 | { | ||
928 | if (tw) *tw = tb->tile_size.w; | ||
929 | if (th) *th = tb->tile_size.h; | ||
930 | } | ||
931 | |||
932 | #ifdef EVAS_RECT_SPLIT | ||
933 | static inline int | ||
934 | _add_redraw(list_t *rects, int x, int y, int w, int h) | ||
935 | { | ||
936 | rect_node_t *rn; | ||
937 | /* we dont need to do this fuzz stuff - it actually creates overdraw bugs | ||
938 | * when evas shouldnt draw at all. | ||
939 | x >>= 1; | ||
940 | y >>= 1; | ||
941 | w += 2; | ||
942 | w >>= 1; | ||
943 | h += 2; | ||
944 | h >>= 1; | ||
945 | */ | ||
946 | rn = (rect_node_t *)rect_list_node_pool_get(); | ||
947 | rn->_lst = list_node_zeroed; | ||
948 | rect_init(&rn->rect, x, y, w, h); | ||
949 | //INF("ACCOUNTING: add_redraw: %4d,%4d %3dx%3d", x, y, w, h); | ||
950 | //testing on my core2 duo desktop - fuzz of 32 or 48 is best. | ||
951 | #define FUZZ 32 | ||
952 | rect_list_add_split_fuzzy_and_merge(rects, (list_node_t *)rn, | ||
953 | FUZZ * FUZZ, FUZZ * FUZZ); | ||
954 | return 1; | ||
955 | } | ||
956 | #endif | ||
957 | |||
958 | EAPI int | ||
959 | evas_common_tilebuf_add_redraw(Tilebuf *tb, int x, int y, int w, int h) | ||
960 | { | ||
961 | #ifdef RECTUPDATE | ||
962 | /* | ||
963 | int i; | ||
964 | |||
965 | if ((w <= 0) || (h <= 0)) return 0; | ||
966 | RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, tb->outbuf_w, tb->outbuf_h); | ||
967 | if ((w <= 0) || (h <= 0)) return 0; | ||
968 | for (i = 0; i < h; i++) | ||
969 | evas_common_regionbuf_span_add(tb->rb, x, x + w - 1, y + i); | ||
970 | return 1; | ||
971 | */ | ||
972 | #elif defined(EVAS_RECT_SPLIT) | ||
973 | if ((w <= 0) || (h <= 0)) return 0; | ||
974 | RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, tb->outbuf_w, tb->outbuf_h); | ||
975 | if ((w <= 0) || (h <= 0)) return 0; | ||
976 | // optimize a common case -> adding the exact same rect 2x in a row | ||
977 | if ((tb->prev_add.x == x) && (tb->prev_add.y == y) && | ||
978 | (tb->prev_add.w == w) && (tb->prev_add.h == h)) return 1; | ||
979 | tb->prev_add.x = x; tb->prev_add.y = y; | ||
980 | tb->prev_add.w = w; tb->prev_add.h = h; | ||
981 | tb->prev_del.w = 0; tb->prev_del.h = 0; | ||
982 | return _add_redraw(&tb->rects, x, y, w, h); | ||
983 | #else | ||
984 | /* | ||
985 | int tx1, tx2, ty1, ty2, tfx1, tfx2, tfy1, tfy2, xx, yy; | ||
986 | int num; | ||
987 | |||
988 | if ((w <= 0) || (h <= 0)) return 0; | ||
989 | RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, tb->outbuf_w, tb->outbuf_h); | ||
990 | if ((w <= 0) || (h <= 0)) return 0; | ||
991 | num = 0; | ||
992 | // wipes out any motion vectors in tiles it touches into redraws | ||
993 | if (tilebuf_x_intersect(tb, x, w, &tx1, &tx2, &tfx1, &tfx2) && | ||
994 | tilebuf_y_intersect(tb, y, h, &ty1, &ty2, &tfy1, &tfy2)) | ||
995 | { | ||
996 | Tilebuf_Tile *tbt; | ||
997 | int delta_x; | ||
998 | int delta_y; | ||
999 | |||
1000 | tbt = &(TILE(tb, tx1, ty1)); | ||
1001 | delta_x = tx2 - tx1 + 1; | ||
1002 | delta_y = ty2 - ty1 + 1; | ||
1003 | for (yy = delta_y; yy > 0; yy--) | ||
1004 | { | ||
1005 | Tilebuf_Tile *tbti; | ||
1006 | |||
1007 | tbti = tbt; | ||
1008 | for (xx = delta_x; xx > 0; xx--) | ||
1009 | { | ||
1010 | tbti->redraw = 1; | ||
1011 | tbti++; | ||
1012 | } | ||
1013 | tbt += tb->tiles.w; | ||
1014 | } | ||
1015 | num = (tx2 - tx1 + 1) * (ty2 - ty1 + 1); | ||
1016 | } | ||
1017 | return num; | ||
1018 | */ | ||
1019 | #endif | ||
1020 | } | ||
1021 | |||
1022 | EAPI int | ||
1023 | evas_common_tilebuf_del_redraw(Tilebuf *tb, int x, int y, int w, int h) | ||
1024 | { | ||
1025 | #ifdef RECTUPDATE | ||
1026 | /* | ||
1027 | int i; | ||
1028 | |||
1029 | for (i = 0; i < h; i++) | ||
1030 | evas_common_regionbuf_span_del(tb->rb, x, x + w - 1, y + i); | ||
1031 | */ | ||
1032 | #elif defined(EVAS_RECT_SPLIT) | ||
1033 | rect_t r; | ||
1034 | |||
1035 | if (!tb->rects.head) return 0; | ||
1036 | if ((w <= 0) || (h <= 0)) return 0; | ||
1037 | RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, tb->outbuf_w, tb->outbuf_h); | ||
1038 | if ((w <= 0) || (h <= 0)) return 0; | ||
1039 | |||
1040 | /* we dont need to do this fuzz stuff - it actually creates overdraw bugs | ||
1041 | * when evas shouldnt draw at all. | ||
1042 | x += 1; | ||
1043 | y += 1; | ||
1044 | x >>= 1; | ||
1045 | y >>= 1; | ||
1046 | w -= 1; | ||
1047 | w >>= 1; | ||
1048 | h -= 1; | ||
1049 | h >>= 1; | ||
1050 | |||
1051 | if ((w <= 0) || (h <= 0)) return 0; | ||
1052 | */ | ||
1053 | |||
1054 | // optimize a common case -> deleting the exact same rect 2x in a row | ||
1055 | if ((tb->prev_del.x == x) && (tb->prev_del.y == y) && | ||
1056 | (tb->prev_del.w == w) && (tb->prev_del.h == h)) return 1; | ||
1057 | tb->prev_del.x = x; tb->prev_del.y = y; | ||
1058 | tb->prev_del.w = w; tb->prev_del.h = h; | ||
1059 | tb->prev_add.w = 0; tb->prev_add.h = 0; | ||
1060 | rect_init(&r, x, y, w, h); | ||
1061 | |||
1062 | rect_list_del_split_strict(&tb->rects, r); | ||
1063 | tb->need_merge = 1; | ||
1064 | return 0; | ||
1065 | #else | ||
1066 | /* | ||
1067 | int tx1, tx2, ty1, ty2, tfx1, tfx2, tfy1, tfy2, xx, yy; | ||
1068 | int num; | ||
1069 | |||
1070 | num = 0; | ||
1071 | // wipes out any motion vectors in tiles it touches into redraws | ||
1072 | if (tilebuf_x_intersect(tb, x, w, &tx1, &tx2, &tfx1, &tfx2) && | ||
1073 | tilebuf_y_intersect(tb, y, h, &ty1, &ty2, &tfy1, &tfy2)) | ||
1074 | { | ||
1075 | Tilebuf_Tile *tbt; | ||
1076 | int delta_y; | ||
1077 | int delta_x; | ||
1078 | |||
1079 | if (!tfx1) tx1++; | ||
1080 | if (!tfx2) tx2--; | ||
1081 | if (!tfy1) ty1++; | ||
1082 | if (!tfy2) ty2--; | ||
1083 | |||
1084 | tbt = &(TILE(tb, tx1, ty1)); | ||
1085 | delta_x = tx2 - tx1 + 1; | ||
1086 | delta_y = ty2 - ty1 + 1; | ||
1087 | for (yy = delta_y; yy > 0; yy--) | ||
1088 | { | ||
1089 | Tilebuf_Tile *tbti; | ||
1090 | |||
1091 | tbti = tbt; | ||
1092 | for (xx = delta_x; xx > 0; xx--) | ||
1093 | { | ||
1094 | tbti->redraw = 0; | ||
1095 | tbti++; | ||
1096 | } | ||
1097 | tbt += tb->tiles.w; | ||
1098 | } | ||
1099 | num = (tx2 - tx1 + 1) * (ty2 - ty1 + 1); | ||
1100 | } | ||
1101 | return num; | ||
1102 | */ | ||
1103 | #endif | ||
1104 | } | ||
1105 | |||
1106 | EAPI int | ||
1107 | evas_common_tilebuf_add_motion_vector(Tilebuf *tb __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__, int dx __UNUSED__, int dy __UNUSED__, int alpha __UNUSED__) | ||
1108 | { | ||
1109 | #ifdef EVAS_RECT_SPLIT | ||
1110 | /* motion vector handling never has been used -> disable it | ||
1111 | list_t lr = list_zeroed; | ||
1112 | int num; | ||
1113 | |||
1114 | num = _add_redraw(&lr, x, y, w, h); | ||
1115 | num += _add_redraw(&lr, x + dx, y + dy, w, h); | ||
1116 | while (lr.head) | ||
1117 | { | ||
1118 | list_node_t *node = rect_list_unlink_next(&lr, NULL); | ||
1119 | rect_list_add_split_fuzzy_and_merge(&tb->rects, node, | ||
1120 | FUZZ * FUZZ, FUZZ * FUZZ); | ||
1121 | } | ||
1122 | return num; | ||
1123 | */ | ||
1124 | return 0; | ||
1125 | #else | ||
1126 | /* | ||
1127 | int num; | ||
1128 | |||
1129 | num = evas_common_tilebuf_add_redraw(tb, x, y, w, h); | ||
1130 | num += evas_common_tilebuf_add_redraw(tb, x + dx, y + dy, w, h); | ||
1131 | return num; | ||
1132 | */ | ||
1133 | #endif | ||
1134 | } | ||
1135 | |||
1136 | EAPI void | ||
1137 | evas_common_tilebuf_clear(Tilebuf *tb) | ||
1138 | { | ||
1139 | #ifdef RECTUPDATE | ||
1140 | /* | ||
1141 | evas_common_regionbuf_clear(tb->rb); | ||
1142 | */ | ||
1143 | #elif defined(EVAS_RECT_SPLIT) | ||
1144 | tb->prev_add.x = tb->prev_add.y = tb->prev_add.w = tb->prev_add.h = 0; | ||
1145 | tb->prev_del.x = tb->prev_del.y = tb->prev_del.w = tb->prev_del.h = 0; | ||
1146 | rect_list_clear(&tb->rects); | ||
1147 | tb->need_merge = 0; | ||
1148 | #else | ||
1149 | /* | ||
1150 | if (!tb->tiles.tiles) return; | ||
1151 | memset(tb->tiles.tiles, 0, tb->tiles.w * tb->tiles.h * sizeof(Tilebuf_Tile)); | ||
1152 | */ | ||
1153 | #endif | ||
1154 | } | ||
1155 | |||
1156 | EAPI Tilebuf_Rect * | ||
1157 | evas_common_tilebuf_get_render_rects(Tilebuf *tb) | ||
1158 | { | ||
1159 | #ifdef RECTUPDATE | ||
1160 | /* | ||
1161 | return evas_common_regionbuf_rects_get(tb->rb); | ||
1162 | */ | ||
1163 | #elif defined(EVAS_RECT_SPLIT) | ||
1164 | list_node_t *n; | ||
1165 | Tilebuf_Rect *rects = NULL; | ||
1166 | |||
1167 | if (tb->need_merge) { | ||
1168 | list_t to_merge; | ||
1169 | to_merge = tb->rects; | ||
1170 | tb->rects = list_zeroed; | ||
1171 | rect_list_merge_rects(&tb->rects, &to_merge, FUZZ * FUZZ); | ||
1172 | tb->need_merge = 0; | ||
1173 | } | ||
1174 | |||
1175 | for (n = tb->rects.head; n; n = n->next) { | ||
1176 | rect_t cur; | ||
1177 | |||
1178 | cur = ((rect_node_t *)n)->rect; | ||
1179 | /* disable fuzz - created bugs. | ||
1180 | cur.left <<= 1; | ||
1181 | cur.top <<= 1; | ||
1182 | cur.width <<= 1; | ||
1183 | cur.height <<= 1; | ||
1184 | */ | ||
1185 | RECTS_CLIP_TO_RECT(cur.left, cur.top, cur.width, cur.height, | ||
1186 | 0, 0, tb->outbuf_w, tb->outbuf_h); | ||
1187 | if ((cur.width > 0) && (cur.height > 0)) | ||
1188 | { | ||
1189 | Tilebuf_Rect *r; | ||
1190 | |||
1191 | r = malloc(sizeof(Tilebuf_Rect)); | ||
1192 | r->x = cur.left; | ||
1193 | r->y = cur.top; | ||
1194 | r->w = cur.width; | ||
1195 | r->h = cur.height; | ||
1196 | |||
1197 | rects = (Tilebuf_Rect *)eina_inlist_append(EINA_INLIST_GET(rects), EINA_INLIST_GET(r)); | ||
1198 | } | ||
1199 | } | ||
1200 | return rects; | ||
1201 | |||
1202 | #else | ||
1203 | /* | ||
1204 | Tilebuf_Rect *rects = NULL; | ||
1205 | Tilebuf_Tile *tbt; | ||
1206 | int x, y; | ||
1207 | |||
1208 | tbt = &(TILE(tb, 0, 0)); | ||
1209 | for (y = 0; y < tb->tiles.h; y++) | ||
1210 | { | ||
1211 | for (x = 0; x < tb->tiles.w; x++, tbt++) | ||
1212 | { | ||
1213 | if (tbt->redraw) | ||
1214 | { | ||
1215 | Tilebuf_Tile *tbti; | ||
1216 | int can_expand_x = 1, can_expand_y = 1; | ||
1217 | Tilebuf_Rect *r = NULL; | ||
1218 | int xx = 0, yy = 0; | ||
1219 | r = malloc(sizeof(Tilebuf_Rect)); | ||
1220 | r->_list_data.next = NULL; | ||
1221 | r->_list_data.prev = NULL; | ||
1222 | r->_list_data.last = NULL; | ||
1223 | |||
1224 | // amalgamate tiles | ||
1225 | #if 1 | ||
1226 | tbti = tbt; | ||
1227 | while (can_expand_x) | ||
1228 | { | ||
1229 | tbti++; | ||
1230 | xx++; | ||
1231 | if ((x + xx) >= tb->tiles.w) | ||
1232 | can_expand_x = 0; | ||
1233 | else if (!(tbti->redraw)) | ||
1234 | can_expand_x = 0; | ||
1235 | if (can_expand_x) | ||
1236 | tbti->redraw = 0; | ||
1237 | } | ||
1238 | tbti = tbt; | ||
1239 | while (can_expand_y) | ||
1240 | { | ||
1241 | int i; | ||
1242 | |||
1243 | tbti += tb->tiles.w; | ||
1244 | yy++; | ||
1245 | if ((y + yy) >= tb->tiles.h) | ||
1246 | can_expand_y = 0; | ||
1247 | if (can_expand_y) | ||
1248 | { | ||
1249 | Tilebuf_Tile *tbtj; | ||
1250 | |||
1251 | tbtj = tbti; | ||
1252 | for (i = x; i < x + xx; i++, tbtj++) | ||
1253 | { | ||
1254 | if (!(tbtj->redraw)) | ||
1255 | { | ||
1256 | can_expand_y = 0; | ||
1257 | break; | ||
1258 | } | ||
1259 | } | ||
1260 | } | ||
1261 | if (can_expand_y) | ||
1262 | { | ||
1263 | Tilebuf_Tile *tbtj; | ||
1264 | |||
1265 | tbtj = tbti; | ||
1266 | for (i = x; i < x + xx; i++, tbtj++) | ||
1267 | tbtj->redraw = 0; | ||
1268 | } | ||
1269 | } | ||
1270 | tbt->redraw = 0; | ||
1271 | #else | ||
1272 | xx = 1; | ||
1273 | yy = 1; | ||
1274 | #endif | ||
1275 | r->x = x * tb->tile_size.w; | ||
1276 | r->y = y * tb->tile_size.h; | ||
1277 | r->w = (xx) * tb->tile_size.w; | ||
1278 | r->h = (yy) * tb->tile_size.h; | ||
1279 | rects = eina_inlist_append(rects, r); | ||
1280 | x = x + (xx - 1); | ||
1281 | tbt += xx - 1; | ||
1282 | } | ||
1283 | } | ||
1284 | } | ||
1285 | return rects; | ||
1286 | */ | ||
1287 | #endif | ||
1288 | } | ||
1289 | |||
1290 | EAPI void | ||
1291 | evas_common_tilebuf_free_render_rects(Tilebuf_Rect *rects) | ||
1292 | { | ||
1293 | while (rects) | ||
1294 | { | ||
1295 | Tilebuf_Rect *r; | ||
1296 | |||
1297 | r = rects; | ||
1298 | rects = (Tilebuf_Rect *)eina_inlist_remove(EINA_INLIST_GET(rects), EINA_INLIST_GET(r)); | ||
1299 | free(r); | ||
1300 | } | ||
1301 | } | ||
1302 | |||
1303 | /* need a way of getting rectangles to: blit, re-render */ | ||
1304 | |||
1305 | |||
1306 | |||
1307 | |||
1308 | |||
1309 | /* internal usage */ | ||
1310 | /* | ||
1311 | static void | ||
1312 | tilebuf_setup(Tilebuf *tb) | ||
1313 | { | ||
1314 | if ((tb->outbuf_w <= 0) || (tb->outbuf_h <= 0)) return; | ||
1315 | #ifdef RECTUPDATE | ||
1316 | tb->rb = evas_common_regionbuf_new(tb->outbuf_w, tb->outbuf_h); | ||
1317 | #elif defined(EVAS_RECT_SPLIT) | ||
1318 | tb->rects = list_zeroed; | ||
1319 | #else | ||
1320 | if (tb->tiles.tiles) free(tb->tiles.tiles); | ||
1321 | tb->tiles.tiles = NULL; | ||
1322 | |||
1323 | tb->tiles.w = (tb->outbuf_w + (tb->tile_size.w - 1)) / tb->tile_size.w; | ||
1324 | tb->tiles.h = (tb->outbuf_h + (tb->tile_size.h - 1)) / tb->tile_size.h; | ||
1325 | |||
1326 | tb->tiles.tiles = malloc(tb->tiles.w * tb->tiles.h * sizeof(Tilebuf_Tile)); | ||
1327 | |||
1328 | if (!tb->tiles.tiles) | ||
1329 | { | ||
1330 | tb->tiles.w = 0; | ||
1331 | tb->tiles.h = 0; | ||
1332 | return; | ||
1333 | } | ||
1334 | memset(tb->tiles.tiles, 0, tb->tiles.w * tb->tiles.h * sizeof(Tilebuf_Tile)); | ||
1335 | #endif | ||
1336 | } | ||
1337 | */ | ||
1338 | |||
1339 | #ifdef RECTUPDATE | ||
1340 | #elif defined(EVAS_RECT_SPLIT) | ||
1341 | #else | ||
1342 | /* | ||
1343 | static int | ||
1344 | tilebuf_x_intersect(Tilebuf *tb, int x, int w, int *x1, int *x2, int *x1_fill, int *x2_fill) | ||
1345 | { | ||
1346 | return tilebuf_intersect(tb->tile_size.w, tb->outbuf_w, tb->tiles.w, | ||
1347 | x, w, x1, x2, x1_fill, x2_fill); | ||
1348 | } | ||
1349 | |||
1350 | static int | ||
1351 | tilebuf_y_intersect(Tilebuf *tb, int y, int h, int *y1, int *y2, int *y1_fill, int *y2_fill) | ||
1352 | { | ||
1353 | return tilebuf_intersect(tb->tile_size.h, tb->outbuf_h, tb->tiles.h, | ||
1354 | y, h, y1, y2, y1_fill, y2_fill); | ||
1355 | } | ||
1356 | |||
1357 | static int | ||
1358 | tilebuf_intersect(int tsize, int tlen, int tnum, int x, int w, int *x1, int *x2, int *x1_fill, int *x2_fill) | ||
1359 | { | ||
1360 | int p1, p2; | ||
1361 | |||
1362 | // initial clip out of region | ||
1363 | if ((x + w) <= 0) return 0; | ||
1364 | if (x >= tlen) return 0; | ||
1365 | |||
1366 | // adjust x & w so it all fits in region | ||
1367 | if (x < 0) | ||
1368 | { | ||
1369 | w += x; | ||
1370 | x = 0; | ||
1371 | } | ||
1372 | if (w < 0) return 0; | ||
1373 | if ((x + w) > tlen) w = tlen - x; | ||
1374 | |||
1375 | // now figure if the first edge is fully filling its tile | ||
1376 | p1 = (x) / tsize; | ||
1377 | if ((p1 * tsize) == (x)) *x1_fill = 1; | ||
1378 | else *x1_fill = 0; | ||
1379 | *x1 = p1; | ||
1380 | |||
1381 | // now figure if the last edge is fully filling its tile | ||
1382 | p2 = (x + w - 1) / tsize; | ||
1383 | if (((p2 + 1) * tsize) == (x + w)) *x2_fill = 1; | ||
1384 | else *x2_fill = 0; | ||
1385 | *x2 = p2; | ||
1386 | |||
1387 | return 1; | ||
1388 | tnum = 0; | ||
1389 | } | ||
1390 | */ | ||
1391 | #endif | ||