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