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++) {