Mercurial > MadButterfly
comparison src/redraw_man.c @ 15:c2ce186a5c37
X_main uses rdman_redraw_all()
author | Thinker K.F. Li <thinker@branda.to> |
---|---|
date | Fri, 01 Aug 2008 01:40:07 +0800 |
parents | d34232f15863 |
children | e17e12b112c4 |
comparison
equal
deleted
inserted
replaced
14:d34232f15863 | 15:c2ce186a5c37 |
---|---|
1 #include <stdio.h> | 1 #include <stdio.h> |
2 #include <stdlib.h> | 2 #include <stdlib.h> |
3 #include <string.h> | 3 #include <string.h> |
4 #include <cairo.h> | |
4 #include "mb_types.h" | 5 #include "mb_types.h" |
5 #include "shapes.h" | 6 #include "shapes.h" |
6 #include "tools.h" | 7 #include "tools.h" |
7 #include "redraw_man.h" | 8 #include "redraw_man.h" |
8 | 9 |
10 #define ERR -1 | 11 #define ERR -1 |
11 | 12 |
12 #define OFFSET(type, field) ((void *)&((type *)NULL)->field - (void *)NULL) | 13 #define OFFSET(type, field) ((void *)&((type *)NULL)->field - (void *)NULL) |
13 #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) |
14 | 15 |
15 int redraw_man_init(redraw_man_t *rdman) { | 16 int redraw_man_init(redraw_man_t *rdman, cairo_t *cr) { |
16 extern void redraw_man_destroy(redraw_man_t *rdman); | 17 extern void redraw_man_destroy(redraw_man_t *rdman); |
17 | 18 |
18 memset(rdman, 0, sizeof(redraw_man_t)); | 19 memset(rdman, 0, sizeof(redraw_man_t)); |
19 | 20 |
20 rdman->geo_pool = elmpool_new(sizeof(geo_t), 128); | 21 rdman->geo_pool = elmpool_new(sizeof(geo_t), 128); |
30 rdman->root_coord = elmpool_elm_alloc(rdman->coord_pool); | 31 rdman->root_coord = elmpool_elm_alloc(rdman->coord_pool); |
31 if(rdman->root_coord == NULL) | 32 if(rdman->root_coord == NULL) |
32 redraw_man_destroy(rdman); | 33 redraw_man_destroy(rdman); |
33 rdman->n_coords = 1; | 34 rdman->n_coords = 1; |
34 coord_init(rdman->root_coord, NULL); | 35 coord_init(rdman->root_coord, NULL); |
36 | |
37 rdman->cr = cr; | |
35 | 38 |
36 return OK; | 39 return OK; |
37 } | 40 } |
38 | 41 |
39 void redraw_man_destroy(redraw_man_t *rdman) { | 42 void redraw_man_destroy(redraw_man_t *rdman) { |
130 visit != NULL; | 133 visit != NULL; |
131 visit = STAILQ_NEXT(geo_t, next, visit)) | 134 visit = STAILQ_NEXT(geo_t, next, visit)) |
132 visit->order = ++next_order; | 135 visit->order = ++next_order; |
133 rdman->next_geo_order = next_order; | 136 rdman->next_geo_order = next_order; |
134 } | 137 } |
138 geo->flags |= GEF_DIRTY; | |
135 | 139 |
136 sh_attach_coord(shape, coord); | 140 sh_attach_coord(shape, coord); |
137 | 141 |
138 return OK; | 142 return OK; |
139 } | 143 } |
235 static int add_dirty_area(redraw_man_t *rdman, area_t *area) { | 239 static int add_dirty_area(redraw_man_t *rdman, area_t *area) { |
236 int max_dirty_areas; | 240 int max_dirty_areas; |
237 int r; | 241 int r; |
238 | 242 |
239 if(rdman->n_dirty_areas >= rdman->max_dirty_areas) { | 243 if(rdman->n_dirty_areas >= rdman->max_dirty_areas) { |
244 /* every geo object and coord object can contribute 2 areas. */ | |
240 max_dirty_areas = (rdman->n_geos + rdman->n_coords) * 2; | 245 max_dirty_areas = (rdman->n_geos + rdman->n_coords) * 2; |
241 r = extend_memblk((void **)&rdman->dirty_areas, | 246 r = extend_memblk((void **)&rdman->dirty_areas, |
242 sizeof(area_t *) * rdman->n_dirty_areas, | 247 sizeof(area_t *) * rdman->n_dirty_areas, |
243 sizeof(area_t *) * max_dirty_areas); | 248 sizeof(area_t *) * max_dirty_areas); |
244 if(r != OK) | 249 if(r != OK) |
318 } | 323 } |
319 elms[j] = elms[i]; | 324 elms[j] = elms[i]; |
320 } | 325 } |
321 } | 326 } |
322 | 327 |
323 static void make_redrawing_members(redraw_man_t *rdman, coord_t *coord) { | 328 static void update_shape_geo(shape_t *shape) { |
329 switch(shape->sh_type) { | |
330 case SHT_PATH: | |
331 sh_path_transform(shape); | |
332 break; | |
333 } | |
334 } | |
335 | |
336 static void area_to_positions(area_t *area, co_aix (*poses)[2]) { | |
337 poses[0][0] = area->x; | |
338 poses[0][1] = area->y; | |
339 poses[1][0] = area->x + area->w; | |
340 poses[1][1] = area->y + area->h;; | |
341 } | |
342 | |
343 static int compute_coord_area(coord_t *coord) { | |
324 shape_t *shape; | 344 shape_t *shape; |
325 | 345 geo_t *geo; |
346 co_aix (*poses)[2]; | |
347 int cnt, pos_cnt; | |
348 int i; | |
349 | |
350 cnt = 0; | |
326 for(shape = STAILQ_HEAD(coord->members); | 351 for(shape = STAILQ_HEAD(coord->members); |
327 shape != NULL; | 352 shape != NULL; |
328 shape = STAILQ_NEXT(shape_t, coord_mem_next, shape)) { | 353 shape = STAILQ_NEXT(shape_t, coord_mem_next, shape)) { |
329 shape->geo->flags &= ~GEF_DIRTY; | 354 SWAP(shape->geo->cur_area, shape->geo->last_area, area_t *); |
330 add_dirty_geo(rdman, shape->geo); | 355 update_shape_geo(shape); |
331 } | 356 cnt++; |
332 } | 357 } |
333 | 358 |
334 static void compute_coord_area(coord_t *coord) { | 359 poses = (co_aix (*)[2])malloc(sizeof(co_aix [2]) * 2 * cnt); |
335 } | 360 if(poses == NULL) |
336 | 361 return ERR; |
337 static void update_shape_geo(shape_t *shape) { | 362 |
363 pos_cnt = 0; | |
364 for(shape = STAILQ_HEAD(coord->members); | |
365 shape != NULL; | |
366 shape = STAILQ_NEXT(shape_t, coord_mem_next, shape)) { | |
367 geo = shape->geo; | |
368 | |
369 area_to_positions(&geo->areas[0], poses + pos_cnt); | |
370 pos_cnt += 2; | |
371 area_to_positions(&geo->areas[1], poses + pos_cnt); | |
372 pos_cnt += 2; | |
373 } | |
374 | |
375 for(i = 0; i < pos_cnt; i++) | |
376 coord_trans_pos(coord, &poses[i][0], &poses[i][1]); | |
377 | |
378 area_init(coord->cur_area, cnt, poses); | |
379 free(poses); | |
380 | |
381 return OK; | |
338 } | 382 } |
339 | 383 |
340 static void draw_shape(redraw_man_t *rdman, shape_t *shape) { | 384 static void draw_shape(redraw_man_t *rdman, shape_t *shape) { |
341 } | 385 switch(shape->sh_type) { |
342 | 386 case SHT_PATH: |
343 static void clip_and_show(redraw_man_t *rdman, int n_dirty_areas, | 387 sh_path_draw(shape, rdman->cr); |
344 area_t **dirty_areas) { | 388 break; |
389 } | |
390 } | |
391 | |
392 static void make_clip(redraw_man_t *rdman, int n_dirty_areas, | |
393 area_t **dirty_areas) { | |
394 int i; | |
395 area_t *area; | |
396 cairo_t *cr; | |
397 | |
398 cr = rdman->cr; | |
399 | |
400 cairo_reset_clip(cr); | |
401 for(i = 0; i < n_dirty_areas; i++) { | |
402 area = dirty_areas[i]; | |
403 cairo_rectangle(cr, area->x, area->y, area->w, area->h); | |
404 } | |
405 cairo_clip(cr); | |
406 } | |
407 | |
408 static void draw_shapes_in_areas(redraw_man_t *rdman, | |
409 int n_areas, | |
410 area_t **areas) { | |
411 geo_t *visit_geo; | |
412 int i; | |
413 | |
414 for(visit_geo = STAILQ_HEAD(rdman->all_geos); | |
415 visit_geo != NULL; | |
416 visit_geo = STAILQ_NEXT(geo_t, next, visit_geo)) { | |
417 if(visit_geo->flags & GEF_DIRTY) { | |
418 visit_geo->flags &= ~GEF_DIRTY; | |
419 update_shape_geo(visit_geo->shape); | |
420 } | |
421 for(i = 0; i < n_areas; i++) { | |
422 if(is_overlay(visit_geo->cur_area, areas[i])) { | |
423 draw_shape(rdman, visit_geo->shape); | |
424 break; | |
425 } | |
426 } | |
427 } | |
345 } | 428 } |
346 | 429 |
347 /*! \brief Re-draw all changed shapes or shapes affected by changed coords. | 430 /*! \brief Re-draw all changed shapes or shapes affected by changed coords. |
348 * | 431 * |
349 * A coord object has a geo to keep track the range that it's members will | 432 * A coord object has a geo to keep track the range that it's members will |
369 * - only if a shape object is dirty. | 452 * - only if a shape object is dirty. |
370 * - put new and old value of area of geo to list of dirty areas. | 453 * - put new and old value of area of geo to list of dirty areas. |
371 * - Scan all shapes and redraw shapes overlaid with dirty areas. | 454 * - Scan all shapes and redraw shapes overlaid with dirty areas. |
372 * | 455 * |
373 * dirty flag of coord objects is cleared after update. | 456 * dirty flag of coord objects is cleared after update. |
374 * | 457 * dirty flag of geo objects is also cleared after recomputing. |
375 * assert(n_dirty_geos <= (num_of(shape) + num_of(coord))) | 458 * Clean dirty flag can prevent redundant computing for geo and |
376 * Because | 459 * corod objects. |
377 * - num_of(geo from coord) < num_of(coord) | 460 * |
378 * - num_of(geo from shape) < num_of(shape) | |
379 */ | 461 */ |
380 int rdman_redraw_changed(redraw_man_t *rdman) { | 462 int rdman_redraw_changed(redraw_man_t *rdman) { |
381 int i; | 463 int i, r; |
382 int n_dirty_coords; | 464 int n_dirty_coords; |
383 coord_t **dirty_coords; | 465 coord_t **dirty_coords; |
384 coord_t *visit_coord; | 466 coord_t *visit_coord; |
385 geo_t *visit_geo, **dirty_geos; | 467 geo_t *visit_geo, **dirty_geos; |
386 int n_dirty_geos; | 468 int n_dirty_geos; |
405 /* Dirty member, here, and members of this coord | 487 /* Dirty member, here, and members of this coord |
406 * will not be visited anymore. */ | 488 * will not be visited anymore. */ |
407 visit_coord->flags &= ~COF_DIRTY; | 489 visit_coord->flags &= ~COF_DIRTY; |
408 | 490 |
409 SWAP(visit_coord->cur_area, visit_coord->last_area, area_t *); | 491 SWAP(visit_coord->cur_area, visit_coord->last_area, area_t *); |
410 compute_coord_area(visit_coord); | 492 r = compute_coord_area(visit_coord); |
493 if(r == ERR) | |
494 return ERR; | |
411 add_dirty_area(rdman, visit_coord->cur_area); | 495 add_dirty_area(rdman, visit_coord->cur_area); |
412 add_dirty_area(rdman, visit_coord->last_area); | 496 add_dirty_area(rdman, visit_coord->last_area); |
413 make_redrawing_members(rdman, visit_coord); | |
414 } | 497 } |
415 } | 498 } |
416 rdman->n_dirty_coords = 0; | 499 rdman->n_dirty_coords = 0; |
417 } | 500 } |
418 | 501 |
428 SWAP(visit_geo->cur_area, visit_geo->last_area, area_t *); | 511 SWAP(visit_geo->cur_area, visit_geo->last_area, area_t *); |
429 update_shape_geo(visit_geo->shape); | 512 update_shape_geo(visit_geo->shape); |
430 add_dirty_area(rdman, visit_geo->cur_area); | 513 add_dirty_area(rdman, visit_geo->cur_area); |
431 add_dirty_area(rdman, visit_geo->last_area); | 514 add_dirty_area(rdman, visit_geo->last_area); |
432 } | 515 } |
516 rdman->n_dirty_geos = 0; | |
517 } | |
433 | 518 |
434 n_dirty_areas = rdman->n_dirty_areas; | 519 n_dirty_areas = rdman->n_dirty_areas; |
435 dirty_areas = rdman->dirty_areas; | 520 dirty_areas = rdman->dirty_areas; |
436 for(visit_geo = STAILQ_HEAD(rdman->all_geos); | 521 if(n_dirty_areas > 0) { |
437 visit_geo != NULL; | 522 make_clip(rdman, n_dirty_areas, dirty_areas); |
438 visit_geo = STAILQ_NEXT(geo_t, next, visit_geo)) { | 523 draw_shapes_in_areas(rdman, n_dirty_areas, dirty_areas); |
439 for(i = 0; i < n_dirty_areas; i++) { | 524 rdman->n_dirty_areas = 0; |
440 if(is_overlay(visit_geo->cur_area, | 525 } |
441 dirty_areas[i])) { | 526 |
442 draw_shape(rdman, visit_geo->shape); | 527 return OK; |
443 break; | 528 } |
444 } | 529 |
445 } | 530 int rdman_redraw_all(redraw_man_t *rdman) { |
531 geo_t *geo; | |
532 | |
533 /* TODO: update dirty coord and it's members. */ | |
534 for(geo = STAILQ_HEAD(rdman->all_geos); | |
535 geo != NULL; | |
536 geo = STAILQ_NEXT(geo_t, next, geo)) { | |
537 if(geo->flags & GEF_DIRTY) { | |
538 geo->flags &= ~GEF_DIRTY; | |
539 update_shape_geo(geo->shape); | |
446 } | 540 } |
447 clip_and_show(rdman, n_dirty_areas, dirty_areas); | 541 draw_shape(rdman, geo->shape); |
448 } | 542 } |
449 | 543 |
450 return OK; | 544 return OK; |
451 } | 545 } |
452 | 546 |
539 geo_t **overlays; | 633 geo_t **overlays; |
540 co_aix pos[2][2]; | 634 co_aix pos[2][2]; |
541 int n; | 635 int n; |
542 int i; | 636 int i; |
543 | 637 |
544 redraw_man_init(&rdman); | 638 redraw_man_init(&rdman, NULL); |
545 coords[0] = rdman.root_coord; | 639 coords[0] = rdman.root_coord; |
546 for(i = 1; i < 3; i++) { | 640 for(i = 1; i < 3; i++) { |
547 coords[i] = rdman_coord_new(&rdman, rdman.root_coord); | 641 coords[i] = rdman_coord_new(&rdman, rdman.root_coord); |
548 } | 642 } |
549 for(i = 0; i < 5; i++) { | 643 for(i = 0; i < 5; i++) { |