Mercurial > MadButterfly
comparison src/redraw_man.c @ 16:e17e12b112c4
A simple animation using rdman_redraw_changed().
author | Thinker K.F. Li <thinker@branda.to> |
---|---|
date | Fri, 01 Aug 2008 18:20:28 +0800 |
parents | c2ce186a5c37 |
children | 41f0907b27ac |
comparison
equal
deleted
inserted
replaced
15:c2ce186a5c37 | 16:e17e12b112c4 |
---|---|
10 #define OK 0 | 10 #define OK 0 |
11 #define ERR -1 | 11 #define ERR -1 |
12 | 12 |
13 #define OFFSET(type, field) ((void *)&((type *)NULL)->field - (void *)NULL) | 13 #define OFFSET(type, field) ((void *)&((type *)NULL)->field - (void *)NULL) |
14 #define SWAP(a, b, t) do { t c; c = a; a = b; b = c; } while(0) | 14 #define SWAP(a, b, t) do { t c; c = a; a = b; b = c; } while(0) |
15 | |
16 /*! \brief Sort a list of element by a unsigned integer. | |
17 * | |
18 * The result is in ascend order. The unsigned integers is | |
19 * at offset specified by 'off' from start address of elemnts. | |
20 */ | |
21 static void _insert_sort(void **elms, int num, int off) { | |
22 int i, j; | |
23 unsigned int val; | |
24 | |
25 for(i = 1; i < num; i++) { | |
26 val = *(unsigned int *)(elms[i] + off); | |
27 for(j = i; j > 0; j--) { | |
28 if(*(unsigned int *)(elms[j - 1] + off) <= val) | |
29 break; | |
30 elms[j] = elms[j - 1]; | |
31 } | |
32 elms[j] = elms[i]; | |
33 } | |
34 } | |
35 | |
36 static int extend_memblk(void **buf, int o_size, int n_size) { | |
37 void *new_buf; | |
38 | |
39 new_buf = realloc(*buf, n_size); | |
40 if(new_buf == NULL) | |
41 return ERR; | |
42 | |
43 if(new_buf != *buf) | |
44 *buf = new_buf; | |
45 | |
46 return OK; | |
47 } | |
48 | |
49 static int add_dirty_geo(redraw_man_t *rdman, geo_t *geo) { | |
50 int max_dirty_geos; | |
51 int r; | |
52 | |
53 if(rdman->n_dirty_geos >= rdman->max_dirty_geos) { | |
54 max_dirty_geos = rdman->n_geos; | |
55 r = extend_memblk((void **)&rdman->dirty_geos, | |
56 sizeof(geo_t *) * rdman->n_dirty_geos, | |
57 sizeof(geo_t *) * max_dirty_geos); | |
58 if(r != OK) | |
59 return ERR; | |
60 rdman->max_dirty_geos = max_dirty_geos; | |
61 } | |
62 | |
63 rdman->dirty_geos[rdman->n_dirty_geos++] = geo; | |
64 return OK; | |
65 } | |
66 | |
67 static int add_dirty_area(redraw_man_t *rdman, area_t *area) { | |
68 int max_dirty_areas; | |
69 int r; | |
70 | |
71 if(rdman->n_dirty_areas >= rdman->max_dirty_areas) { | |
72 /* every geo object and coord object can contribute 2 areas. */ | |
73 max_dirty_areas = (rdman->n_geos + rdman->n_coords) * 2; | |
74 r = extend_memblk((void **)&rdman->dirty_areas, | |
75 sizeof(area_t *) * rdman->n_dirty_areas, | |
76 sizeof(area_t *) * max_dirty_areas); | |
77 if(r != OK) | |
78 return ERR; | |
79 rdman->max_dirty_areas = max_dirty_areas; | |
80 } | |
81 | |
82 rdman->dirty_areas[rdman->n_dirty_areas++] = area; | |
83 return OK; | |
84 } | |
15 | 85 |
16 int redraw_man_init(redraw_man_t *rdman, cairo_t *cr) { | 86 int redraw_man_init(redraw_man_t *rdman, cairo_t *cr) { |
17 extern void redraw_man_destroy(redraw_man_t *rdman); | 87 extern void redraw_man_destroy(redraw_man_t *rdman); |
18 | 88 |
19 memset(rdman, 0, sizeof(redraw_man_t)); | 89 memset(rdman, 0, sizeof(redraw_man_t)); |
114 return n_overlays; | 184 return n_overlays; |
115 } | 185 } |
116 | 186 |
117 int rdman_add_shape(redraw_man_t *rdman, shape_t *shape, coord_t *coord) { | 187 int rdman_add_shape(redraw_man_t *rdman, shape_t *shape, coord_t *coord) { |
118 geo_t *geo; | 188 geo_t *geo; |
189 #ifdef GEO_ORDER | |
119 geo_t *visit; | 190 geo_t *visit; |
120 unsigned int next_order; | 191 unsigned int next_order; |
192 #endif | |
193 int r; | |
121 | 194 |
122 geo = elmpool_elm_alloc(rdman->geo_pool); | 195 geo = elmpool_elm_alloc(rdman->geo_pool); |
123 if(geo == NULL) | 196 if(geo == NULL) |
124 return ERR; | 197 return ERR; |
125 sh_attach_geo(shape, geo); | 198 sh_attach_geo(shape, geo); |
126 STAILQ_INS_TAIL(rdman->all_geos, geo_t, next, geo); | 199 STAILQ_INS_TAIL(rdman->all_geos, geo_t, next, geo); |
127 rdman->n_geos++; | 200 rdman->n_geos++; |
128 | 201 |
202 #ifdef GEO_ORDER | |
203 /* TODO: remove order number. */ | |
129 geo->order = ++rdman->next_geo_order; | 204 geo->order = ++rdman->next_geo_order; |
130 if(geo->order == 0) { | 205 if(geo->order == 0) { |
131 next_order = 0; | 206 next_order = 0; |
132 for(visit = STAILQ_HEAD(rdman->all_geos); | 207 for(visit = STAILQ_HEAD(rdman->all_geos); |
133 visit != NULL; | 208 visit != NULL; |
134 visit = STAILQ_NEXT(geo_t, next, visit)) | 209 visit = STAILQ_NEXT(geo_t, next, visit)) |
135 visit->order = ++next_order; | 210 visit->order = ++next_order; |
136 rdman->next_geo_order = next_order; | 211 rdman->next_geo_order = next_order; |
137 } | 212 } |
213 #endif | |
214 | |
215 /* New one should be dirty to recompute it when drawing. */ | |
138 geo->flags |= GEF_DIRTY; | 216 geo->flags |= GEF_DIRTY; |
217 r = add_dirty_geo(rdman, geo); | |
218 if(r != OK) | |
219 return ERR; | |
139 | 220 |
140 sh_attach_coord(shape, coord); | 221 sh_attach_coord(shape, coord); |
141 | 222 |
142 return OK; | 223 return OK; |
143 } | 224 } |
200 rdman->n_coords--; | 281 rdman->n_coords--; |
201 | 282 |
202 return OK; | 283 return OK; |
203 } | 284 } |
204 | 285 |
205 static int extend_memblk(void **buf, int o_size, int n_size) { | |
206 void *new_buf; | |
207 | |
208 new_buf = realloc(*buf, n_size); | |
209 if(new_buf == NULL) | |
210 return ERR; | |
211 | |
212 if(new_buf != *buf) { | |
213 memcpy(new_buf, *buf, o_size); | |
214 free(*buf); | |
215 *buf = new_buf; | |
216 } | |
217 | |
218 return OK; | |
219 } | |
220 | |
221 static int add_dirty_geo(redraw_man_t *rdman, geo_t *geo) { | |
222 int max_dirty_geos; | |
223 int r; | |
224 | |
225 if(rdman->n_dirty_geos >= rdman->max_dirty_geos) { | |
226 max_dirty_geos = rdman->n_geos; | |
227 r = extend_memblk((void **)&rdman->dirty_geos, | |
228 sizeof(geo_t *) * rdman->n_dirty_geos, | |
229 sizeof(geo_t *) * max_dirty_geos); | |
230 if(r != OK) | |
231 return ERR; | |
232 rdman->max_dirty_geos = max_dirty_geos; | |
233 } | |
234 | |
235 rdman->dirty_geos[rdman->n_dirty_geos++] = geo; | |
236 return OK; | |
237 } | |
238 | |
239 static int add_dirty_area(redraw_man_t *rdman, area_t *area) { | |
240 int max_dirty_areas; | |
241 int r; | |
242 | |
243 if(rdman->n_dirty_areas >= rdman->max_dirty_areas) { | |
244 /* every geo object and coord object can contribute 2 areas. */ | |
245 max_dirty_areas = (rdman->n_geos + rdman->n_coords) * 2; | |
246 r = extend_memblk((void **)&rdman->dirty_areas, | |
247 sizeof(area_t *) * rdman->n_dirty_areas, | |
248 sizeof(area_t *) * max_dirty_areas); | |
249 if(r != OK) | |
250 return ERR; | |
251 rdman->max_dirty_areas = max_dirty_areas; | |
252 } | |
253 | |
254 rdman->dirty_areas[++rdman->n_dirty_areas] = area; | |
255 return OK; | |
256 } | |
257 | |
258 /*! \brief Mark a coord is changed. | 286 /*! \brief Mark a coord is changed. |
259 * | 287 * |
260 * A changed coord_t object is marked as dirty and put | 288 * A changed coord_t object is marked as dirty and put |
261 * into dirty_coords list. | 289 * into dirty_coords list. |
262 */ | 290 */ |
263 int rdman_coord_changed(redraw_man_t *rdman, coord_t *coord) { | 291 int rdman_coord_changed(redraw_man_t *rdman, coord_t *coord) { |
292 coord_t *child; | |
264 int max_dirty_coords; | 293 int max_dirty_coords; |
265 int r; | 294 int r; |
266 | 295 |
267 if(coord->flags & COF_DIRTY) | 296 if(coord->flags & COF_DIRTY) |
268 return OK; | 297 return OK; |
275 sizeof(coord_t *) * rdman->n_dirty_coords, | 304 sizeof(coord_t *) * rdman->n_dirty_coords, |
276 sizeof(coord_t *) * max_dirty_coords); | 305 sizeof(coord_t *) * max_dirty_coords); |
277 rdman->max_dirty_coords = max_dirty_coords; | 306 rdman->max_dirty_coords = max_dirty_coords; |
278 } | 307 } |
279 | 308 |
280 rdman->dirty_coords[rdman->n_dirty_coords++] = coord; | 309 /* Make the coord and child coords dirty. */ |
281 coord->flags |= COF_DIRTY; | 310 for(child = coord; |
311 child != NULL; | |
312 child = preorder_coord_subtree(coord, child)) { | |
313 rdman->dirty_coords[rdman->n_dirty_coords++] = coord; | |
314 coord->flags |= COF_DIRTY; | |
315 } | |
282 | 316 |
283 return OK; | 317 return OK; |
284 } | 318 } |
285 | 319 |
286 /*! \brief Mark a shape is changed. | 320 /*! \brief Mark a shape is changed. |
303 geo->flags |= GEF_DIRTY; | 337 geo->flags |= GEF_DIRTY; |
304 | 338 |
305 return OK; | 339 return OK; |
306 } | 340 } |
307 | 341 |
308 /*! \brief Sort a list of element by a unsigned integer. | 342 static void clean_shape(shape_t *shape) { |
309 * | |
310 * The result is in ascend order. The unsigned integers is | |
311 * at offset specified by 'off' from start address of elemnts. | |
312 */ | |
313 static void _insert_sort(void **elms, int num, int off) { | |
314 int i, j; | |
315 unsigned int val; | |
316 | |
317 for(i = 1; i < num; i++) { | |
318 val = *(unsigned int *)(elms[i] + off); | |
319 for(j = i; j > 0; j--) { | |
320 if(*(unsigned int *)(elms[j - 1] + off) <= val) | |
321 break; | |
322 elms[j] = elms[j - 1]; | |
323 } | |
324 elms[j] = elms[i]; | |
325 } | |
326 } | |
327 | |
328 static void update_shape_geo(shape_t *shape) { | |
329 switch(shape->sh_type) { | 343 switch(shape->sh_type) { |
330 case SHT_PATH: | 344 case SHT_PATH: |
331 sh_path_transform(shape); | 345 sh_path_transform(shape); |
332 break; | 346 break; |
333 } | 347 } |
348 shape->geo->flags &= ~GEF_DIRTY; | |
334 } | 349 } |
335 | 350 |
336 static void area_to_positions(area_t *area, co_aix (*poses)[2]) { | 351 static void area_to_positions(area_t *area, co_aix (*poses)[2]) { |
337 poses[0][0] = area->x; | 352 poses[0][0] = area->x; |
338 poses[0][1] = area->y; | 353 poses[0][1] = area->y; |
339 poses[1][0] = area->x + area->w; | 354 poses[1][0] = area->x + area->w; |
340 poses[1][1] = area->y + area->h;; | 355 poses[1][1] = area->y + area->h;; |
341 } | 356 } |
342 | 357 |
343 static int compute_coord_area(coord_t *coord) { | 358 static int clean_coord(coord_t *coord) { |
344 shape_t *shape; | 359 shape_t *shape; |
345 geo_t *geo; | 360 geo_t *geo; |
346 co_aix (*poses)[2]; | 361 co_aix (*poses)[2]; |
347 int cnt, pos_cnt; | 362 int cnt, pos_cnt; |
348 int i; | 363 int i; |
349 | 364 |
365 compute_aggr_of_coord(coord); | |
366 | |
367 /* Clean member shapes. */ | |
350 cnt = 0; | 368 cnt = 0; |
351 for(shape = STAILQ_HEAD(coord->members); | 369 for(shape = STAILQ_HEAD(coord->members); |
352 shape != NULL; | 370 shape != NULL; |
353 shape = STAILQ_NEXT(shape_t, coord_mem_next, shape)) { | 371 shape = STAILQ_NEXT(shape_t, coord_mem_next, shape)) { |
354 SWAP(shape->geo->cur_area, shape->geo->last_area, area_t *); | 372 geo = shape->geo; |
355 update_shape_geo(shape); | 373 SWAP(geo->cur_area, geo->last_area, area_t *); |
374 clean_shape(shape); | |
356 cnt++; | 375 cnt++; |
357 } | 376 } |
358 | 377 |
378 /* Compute area of the coord. */ | |
359 poses = (co_aix (*)[2])malloc(sizeof(co_aix [2]) * 2 * cnt); | 379 poses = (co_aix (*)[2])malloc(sizeof(co_aix [2]) * 2 * cnt); |
360 if(poses == NULL) | 380 if(poses == NULL) |
361 return ERR; | 381 return ERR; |
362 | 382 |
363 pos_cnt = 0; | 383 pos_cnt = 0; |
370 pos_cnt += 2; | 390 pos_cnt += 2; |
371 area_to_positions(&geo->areas[1], poses + pos_cnt); | 391 area_to_positions(&geo->areas[1], poses + pos_cnt); |
372 pos_cnt += 2; | 392 pos_cnt += 2; |
373 } | 393 } |
374 | 394 |
395 #if 0 | |
375 for(i = 0; i < pos_cnt; i++) | 396 for(i = 0; i < pos_cnt; i++) |
376 coord_trans_pos(coord, &poses[i][0], &poses[i][1]); | 397 coord_trans_pos(coord, &poses[i][0], &poses[i][1]); |
377 | 398 #endif |
378 area_init(coord->cur_area, cnt, poses); | 399 |
400 SWAP(coord->cur_area, coord->last_area, area_t *); | |
401 area_init(coord->cur_area, pos_cnt, poses); | |
379 free(poses); | 402 free(poses); |
380 | 403 |
404 coord->flags &= ~COF_DIRTY; | |
405 | |
406 return OK; | |
407 } | |
408 | |
409 static int clean_rdman_coords(redraw_man_t *rdman) { | |
410 coord_t *coord; | |
411 coord_t **dirty_coords; | |
412 int n_dirty_coords; | |
413 int i, r; | |
414 | |
415 n_dirty_coords = rdman->n_dirty_coords; | |
416 if(n_dirty_coords > 0) { | |
417 dirty_coords = rdman->dirty_coords; | |
418 _insert_sort((void **)dirty_coords, n_dirty_coords, | |
419 OFFSET(coord_t, order)); | |
420 for(i = 0; i < n_dirty_coords; i++) { | |
421 coord = dirty_coords[i]; | |
422 if(!(coord->flags & COF_DIRTY)) | |
423 continue; | |
424 r = clean_coord(coord); | |
425 if(r != OK) | |
426 return ERR; | |
427 /* These two steps can be avoided for drawing all. */ | |
428 add_dirty_area(rdman, &coord->areas[0]); | |
429 add_dirty_area(rdman, &coord->areas[1]); | |
430 } | |
431 rdman->n_dirty_coords = 0; | |
432 } | |
381 return OK; | 433 return OK; |
382 } | 434 } |
383 | 435 |
384 static void draw_shape(redraw_man_t *rdman, shape_t *shape) { | 436 static void draw_shape(redraw_man_t *rdman, shape_t *shape) { |
385 switch(shape->sh_type) { | 437 switch(shape->sh_type) { |
387 sh_path_draw(shape, rdman->cr); | 439 sh_path_draw(shape, rdman->cr); |
388 break; | 440 break; |
389 } | 441 } |
390 } | 442 } |
391 | 443 |
444 static void clean_clip(cairo_t *cr) { | |
445 cairo_pattern_t *pt; | |
446 | |
447 pt = cairo_get_source(cr); | |
448 cairo_pattern_reference(pt); | |
449 /* TODO: clean to background color. */ | |
450 cairo_set_source_rgb(cr, 0, 0, 0); | |
451 cairo_fill_preserve(cr); | |
452 cairo_set_source(cr, pt); | |
453 cairo_pattern_destroy(pt); | |
454 } | |
455 | |
392 static void make_clip(redraw_man_t *rdman, int n_dirty_areas, | 456 static void make_clip(redraw_man_t *rdman, int n_dirty_areas, |
393 area_t **dirty_areas) { | 457 area_t **dirty_areas) { |
394 int i; | 458 int i; |
395 area_t *area; | 459 area_t *area; |
396 cairo_t *cr; | 460 cairo_t *cr; |
400 cairo_reset_clip(cr); | 464 cairo_reset_clip(cr); |
401 for(i = 0; i < n_dirty_areas; i++) { | 465 for(i = 0; i < n_dirty_areas; i++) { |
402 area = dirty_areas[i]; | 466 area = dirty_areas[i]; |
403 cairo_rectangle(cr, area->x, area->y, area->w, area->h); | 467 cairo_rectangle(cr, area->x, area->y, area->w, area->h); |
404 } | 468 } |
469 clean_clip(cr); | |
405 cairo_clip(cr); | 470 cairo_clip(cr); |
406 } | 471 } |
407 | 472 |
408 static void draw_shapes_in_areas(redraw_man_t *rdman, | 473 static void draw_shapes_in_areas(redraw_man_t *rdman, |
409 int n_areas, | 474 int n_areas, |
412 int i; | 477 int i; |
413 | 478 |
414 for(visit_geo = STAILQ_HEAD(rdman->all_geos); | 479 for(visit_geo = STAILQ_HEAD(rdman->all_geos); |
415 visit_geo != NULL; | 480 visit_geo != NULL; |
416 visit_geo = STAILQ_NEXT(geo_t, next, visit_geo)) { | 481 visit_geo = STAILQ_NEXT(geo_t, next, visit_geo)) { |
417 if(visit_geo->flags & GEF_DIRTY) { | 482 if(visit_geo->flags & GEF_DIRTY) |
418 visit_geo->flags &= ~GEF_DIRTY; | 483 clean_shape(visit_geo->shape); |
419 update_shape_geo(visit_geo->shape); | |
420 } | |
421 for(i = 0; i < n_areas; i++) { | 484 for(i = 0; i < n_areas; i++) { |
422 if(is_overlay(visit_geo->cur_area, areas[i])) { | 485 if(is_overlay(visit_geo->cur_area, areas[i])) { |
423 draw_shape(rdman, visit_geo->shape); | 486 draw_shape(rdman, visit_geo->shape); |
424 break; | 487 break; |
425 } | 488 } |
459 * corod objects. | 522 * corod objects. |
460 * | 523 * |
461 */ | 524 */ |
462 int rdman_redraw_changed(redraw_man_t *rdman) { | 525 int rdman_redraw_changed(redraw_man_t *rdman) { |
463 int i, r; | 526 int i, r; |
464 int n_dirty_coords; | |
465 coord_t **dirty_coords; | |
466 coord_t *visit_coord; | |
467 geo_t *visit_geo, **dirty_geos; | 527 geo_t *visit_geo, **dirty_geos; |
468 int n_dirty_geos; | 528 int n_dirty_geos; |
469 int n_dirty_areas; | 529 int n_dirty_areas; |
470 area_t **dirty_areas; | 530 area_t **dirty_areas; |
471 | 531 |
472 if(rdman->n_dirty_coords > 0) { | 532 r = clean_rdman_coords(rdman); |
473 _insert_sort((void **)rdman->dirty_coords, | 533 if(r != OK) |
474 rdman->n_dirty_coords, | 534 return ERR; |
475 OFFSET(coord_t, order)); | |
476 n_dirty_coords = rdman->n_dirty_coords; | |
477 dirty_coords = rdman->dirty_coords; | |
478 for(i = 0; i < n_dirty_coords; i++) { | |
479 if(!(dirty_coords[i]->flags & COF_DIRTY)) | |
480 continue; | |
481 | |
482 update_aggr_matrix(dirty_coords[i]); | |
483 for(visit_coord = dirty_coords[i]; | |
484 visit_coord != NULL; | |
485 visit_coord = preorder_coord_subtree(dirty_coords[i], | |
486 visit_coord)) { | |
487 /* Dirty member, here, and members of this coord | |
488 * will not be visited anymore. */ | |
489 visit_coord->flags &= ~COF_DIRTY; | |
490 | |
491 SWAP(visit_coord->cur_area, visit_coord->last_area, area_t *); | |
492 r = compute_coord_area(visit_coord); | |
493 if(r == ERR) | |
494 return ERR; | |
495 add_dirty_area(rdman, visit_coord->cur_area); | |
496 add_dirty_area(rdman, visit_coord->last_area); | |
497 } | |
498 } | |
499 rdman->n_dirty_coords = 0; | |
500 } | |
501 | 535 |
502 n_dirty_geos = rdman->n_dirty_geos; | 536 n_dirty_geos = rdman->n_dirty_geos; |
503 if(n_dirty_geos > 0) { | 537 if(n_dirty_geos > 0) { |
504 dirty_geos = rdman->dirty_geos; | 538 dirty_geos = rdman->dirty_geos; |
505 for(i = 0; i < n_dirty_geos; i++) { | 539 for(i = 0; i < n_dirty_geos; i++) { |
506 visit_geo = dirty_geos[i]; | 540 visit_geo = dirty_geos[i]; |
507 if(!(visit_geo->flags & GEF_DIRTY)) | 541 if(!(visit_geo->flags & GEF_DIRTY)) |
508 continue; | 542 continue; |
509 | 543 |
510 visit_geo->flags &= ~GEF_DIRTY; | |
511 SWAP(visit_geo->cur_area, visit_geo->last_area, area_t *); | 544 SWAP(visit_geo->cur_area, visit_geo->last_area, area_t *); |
512 update_shape_geo(visit_geo->shape); | 545 clean_shape(visit_geo->shape); |
513 add_dirty_area(rdman, visit_geo->cur_area); | 546 add_dirty_area(rdman, visit_geo->cur_area); |
514 add_dirty_area(rdman, visit_geo->last_area); | 547 add_dirty_area(rdman, visit_geo->last_area); |
515 } | 548 } |
516 rdman->n_dirty_geos = 0; | 549 rdman->n_dirty_geos = 0; |
517 } | 550 } |
521 if(n_dirty_areas > 0) { | 554 if(n_dirty_areas > 0) { |
522 make_clip(rdman, n_dirty_areas, dirty_areas); | 555 make_clip(rdman, n_dirty_areas, dirty_areas); |
523 draw_shapes_in_areas(rdman, n_dirty_areas, dirty_areas); | 556 draw_shapes_in_areas(rdman, n_dirty_areas, dirty_areas); |
524 rdman->n_dirty_areas = 0; | 557 rdman->n_dirty_areas = 0; |
525 } | 558 } |
559 rdman->n_dirty_areas = 0; | |
560 | |
561 cairo_reset_clip(rdman->cr); | |
526 | 562 |
527 return OK; | 563 return OK; |
528 } | 564 } |
529 | 565 |
530 int rdman_redraw_all(redraw_man_t *rdman) { | 566 int rdman_redraw_all(redraw_man_t *rdman) { |
531 geo_t *geo; | 567 geo_t *geo; |
532 | 568 |
533 /* TODO: update dirty coord and it's members. */ | 569 clean_rdman_coords(rdman); |
570 rdman->n_dirty_areas = 0; | |
571 | |
572 cairo_reset_clip(rdman->cr); | |
534 for(geo = STAILQ_HEAD(rdman->all_geos); | 573 for(geo = STAILQ_HEAD(rdman->all_geos); |
535 geo != NULL; | 574 geo != NULL; |
536 geo = STAILQ_NEXT(geo_t, next, geo)) { | 575 geo = STAILQ_NEXT(geo_t, next, geo)) { |
537 if(geo->flags & GEF_DIRTY) { | 576 if(geo->flags & GEF_DIRTY) |
538 geo->flags &= ~GEF_DIRTY; | 577 clean_shape(geo->shape); |
539 update_shape_geo(geo->shape); | |
540 } | |
541 draw_shape(rdman, geo->shape); | 578 draw_shape(rdman, geo->shape); |
542 } | 579 } |
543 | 580 cairo_reset_clip(rdman->cr); |
544 return OK; | 581 |
545 } | 582 return OK; |
583 } | |
584 | |
585 /* | |
586 * Dirty of geo | |
587 * A geo is dirty when any of the shape, size or positions is changed. | |
588 * It's geo and positions should be recomputed before drawing. So, | |
589 * dirty geos are marked as dirty and put into dirty_geos list. | |
590 * The list is inspected before drawing to make sure the right shape, | |
591 * size, and positions. | |
592 * | |
593 * Dirty of coord | |
594 * A coord is dirty when it's transformation matrix being changed. | |
595 * Dirty coords are marked as dirty and put into dirty_coords list. | |
596 * Once a coord is dirty, every member geos of it are also dirty. | |
597 * Because, their shape, size and positions will be changed. But, | |
598 * they are not marked as dirty and put into dirty_geos list, since | |
599 * all these member geos will be recomputed for computing new current | |
600 * area of the coord. The changes of a coord also affect child | |
601 * coords. Once parent is dirty, all children are also dirty for | |
602 * their aggregate matrix out of date. Dirty coords should be | |
603 * clean in preorder of tree traversal. The dirty_coords list | |
604 * are sorted to keep the order before cleaning. | |
605 * Whenever a coord is marked dirty and put into dirty_coords list, | |
606 * all it's children should also be marked and put. | |
607 * | |
608 * The procedure of clean coords comprises recomputing aggregate | |
609 * tranform matrix and area where members spreading in. | |
610 * | |
611 * The list is inspected before drawing to recompute new shape, size, | |
612 * and positions of member geos of coords in the list. The drity | |
613 * flag of member geos will be clean. | |
614 * | |
615 * Clean coords should be performed before clean geos, since clean | |
616 * coords will also clean member geos. | |
617 */ | |
546 | 618 |
547 /* | 619 /* |
548 * When redraw an area, the affected elements may also extend to | 620 * When redraw an area, the affected elements may also extend to |
549 * outside of the area. Since the order of drawing will change | 621 * outside of the area. Since the order of drawing will change |
550 * the result, it will infect more and more elements to keep | 622 * the result, it will infect more and more elements to keep |