# HG changeset patch # User Thinker K.F. Li # Date 1217526007 -28800 # Node ID c2ce186a5c3769fd1a87bdbedbd5cf06b0dbf05b # Parent d34232f15863bba22a882656ebded4a9a7418658 X_main uses rdman_redraw_all() diff -r d34232f15863 -r c2ce186a5c37 src/Makefile --- a/src/Makefile Thu Jul 31 17:43:20 2008 +0800 +++ b/src/Makefile Fri Aug 01 01:40:07 2008 +0800 @@ -1,7 +1,7 @@ SRCS = coord.c geo.c shape_path.c redraw_man.c tools.c OBJS = ${SRCS:C/(.*)\.c/\1.o/g} TESTCASE_OBJS = ${SRCS:C/(.*)\.c/testcase-\1.o/g} -CFLAGS = -Wall -I/usr/local/include `pkg-config --cflags cairo` +CFLAGS+= -Wall -I/usr/local/include `pkg-config --cflags cairo` LDFLAGS = `pkg-config --libs cairo` BINS = testcase X_main diff -r d34232f15863 -r c2ce186a5c37 src/X_main.c --- a/src/X_main.c Thu Jul 31 17:43:20 2008 +0800 +++ b/src/X_main.c Fri Aug 01 01:40:07 2008 +0800 @@ -14,7 +14,7 @@ shape_t *path; coord_t *coord; - redraw_man_init(&rdman); + redraw_man_init(&rdman, cr); coord = rdman.root_coord; path = sh_path_new("M 22,89.36218 C -34,-0.63782 39,-9.637817 82,12.36218 C 125,34.36218 142,136.36218 142,136.36218 C 100.66667,125.36218 74.26756,123.42795 22,89.36218 z "); @@ -23,9 +23,12 @@ coord->aggr_matrix[2] = 20; coord->aggr_matrix[4] = 0.8; coord->aggr_matrix[5] = 20; + rdman_coord_changed(&rdman, coord); rdman_add_shape(&rdman, (shape_t *)path, coord); - sh_path_transform(path); - sh_path_draw(path, cr); + + rdman_redraw_all(&rdman); + + redraw_man_destroy(&rdman); sh_path_free(path); } diff -r d34232f15863 -r c2ce186a5c37 src/coord.c --- a/src/coord.c Thu Jul 31 17:43:20 2008 +0800 +++ b/src/coord.c Fri Aug 01 01:40:07 2008 +0800 @@ -87,6 +87,8 @@ } co->matrix[0] = 1; co->matrix[4] = 1; + co->cur_area = &co->areas[0]; + co->last_area = &co->areas[1]; } void coord_trans_pos(coord_t *co, co_aix *x, co_aix *y) { diff -r d34232f15863 -r c2ce186a5c37 src/geo.c --- a/src/geo.c Thu Jul 31 17:43:20 2008 +0800 +++ b/src/geo.c Fri Aug 01 01:40:07 2008 +0800 @@ -31,12 +31,12 @@ return _is_overlay(r1, r2); } -void geo_init(geo_t *g, int n_pos, co_aix pos[][2]) { +void area_init(area_t *area, int n_pos, co_aix pos[][2]) { co_aix min_x, max_x; co_aix min_y, max_y; co_aix x, y; int i; - + min_x = max_x = pos[0][0]; min_y = max_y = pos[0][1]; for(i = 1; i < n_pos; i++) { @@ -52,13 +52,16 @@ max_y = y; } + area->x = min_x; + area->w = max_x - min_x; + area->y = min_y; + area->h = max_y - min_y; +} + +void geo_init(geo_t *g, int n_pos, co_aix pos[][2]) { g->cur_area = g->areas; g->last_area = g->areas + 1; - - g->cur_area->x = min_x; - g->cur_area->w = max_x - min_x; - g->cur_area->y = min_y; - g->cur_area->h = max_y - min_y; + area_init(g->cur_area, n_pos, pos); } void geo_mark_overlay(geo_t *g, int n_others, geo_t **others, diff -r d34232f15863 -r c2ce186a5c37 src/mb_types.h --- a/src/mb_types.h Thu Jul 31 17:43:20 2008 +0800 +++ b/src/mb_types.h Fri Aug 01 01:40:07 2008 +0800 @@ -27,6 +27,7 @@ #define GEF_DIRTY 0x1 extern int is_overlay(area_t *r1, area_t *r2); +extern void area_init(area_t *area, int n_pos, co_aix pos[][2]); extern void geo_init(geo_t *g, int n_pos, co_aix pos[][2]); extern void geo_mark_overlay(geo_t *g, int n_others, geo_t **others, int *n_overlays, geo_t **overlays); @@ -55,6 +56,7 @@ unsigned int order; unsigned int flags; area_t *cur_area, *last_area; + area_t areas[2]; co_aix matrix[6]; co_aix aggr_matrix[6]; diff -r d34232f15863 -r c2ce186a5c37 src/redraw_man.c --- a/src/redraw_man.c Thu Jul 31 17:43:20 2008 +0800 +++ b/src/redraw_man.c Fri Aug 01 01:40:07 2008 +0800 @@ -1,6 +1,7 @@ #include #include #include +#include #include "mb_types.h" #include "shapes.h" #include "tools.h" @@ -12,7 +13,7 @@ #define OFFSET(type, field) ((void *)&((type *)NULL)->field - (void *)NULL) #define SWAP(a, b, t) do { t c; c = a; a = b; b = c; } while(0) -int redraw_man_init(redraw_man_t *rdman) { +int redraw_man_init(redraw_man_t *rdman, cairo_t *cr) { extern void redraw_man_destroy(redraw_man_t *rdman); memset(rdman, 0, sizeof(redraw_man_t)); @@ -33,6 +34,8 @@ rdman->n_coords = 1; coord_init(rdman->root_coord, NULL); + rdman->cr = cr; + return OK; } @@ -132,6 +135,7 @@ visit->order = ++next_order; rdman->next_geo_order = next_order; } + geo->flags |= GEF_DIRTY; sh_attach_coord(shape, coord); @@ -237,6 +241,7 @@ int r; if(rdman->n_dirty_areas >= rdman->max_dirty_areas) { + /* every geo object and coord object can contribute 2 areas. */ max_dirty_areas = (rdman->n_geos + rdman->n_coords) * 2; r = extend_memblk((void **)&rdman->dirty_areas, sizeof(area_t *) * rdman->n_dirty_areas, @@ -320,28 +325,106 @@ } } -static void make_redrawing_members(redraw_man_t *rdman, coord_t *coord) { - shape_t *shape; - - for(shape = STAILQ_HEAD(coord->members); - shape != NULL; - shape = STAILQ_NEXT(shape_t, coord_mem_next, shape)) { - shape->geo->flags &= ~GEF_DIRTY; - add_dirty_geo(rdman, shape->geo); +static void update_shape_geo(shape_t *shape) { + switch(shape->sh_type) { + case SHT_PATH: + sh_path_transform(shape); + break; } } -static void compute_coord_area(coord_t *coord) { +static void area_to_positions(area_t *area, co_aix (*poses)[2]) { + poses[0][0] = area->x; + poses[0][1] = area->y; + poses[1][0] = area->x + area->w; + poses[1][1] = area->y + area->h;; } -static void update_shape_geo(shape_t *shape) { +static int compute_coord_area(coord_t *coord) { + shape_t *shape; + geo_t *geo; + co_aix (*poses)[2]; + int cnt, pos_cnt; + int i; + + cnt = 0; + for(shape = STAILQ_HEAD(coord->members); + shape != NULL; + shape = STAILQ_NEXT(shape_t, coord_mem_next, shape)) { + SWAP(shape->geo->cur_area, shape->geo->last_area, area_t *); + update_shape_geo(shape); + cnt++; + } + + poses = (co_aix (*)[2])malloc(sizeof(co_aix [2]) * 2 * cnt); + if(poses == NULL) + return ERR; + + pos_cnt = 0; + for(shape = STAILQ_HEAD(coord->members); + shape != NULL; + shape = STAILQ_NEXT(shape_t, coord_mem_next, shape)) { + geo = shape->geo; + + area_to_positions(&geo->areas[0], poses + pos_cnt); + pos_cnt += 2; + area_to_positions(&geo->areas[1], poses + pos_cnt); + pos_cnt += 2; + } + + for(i = 0; i < pos_cnt; i++) + coord_trans_pos(coord, &poses[i][0], &poses[i][1]); + + area_init(coord->cur_area, cnt, poses); + free(poses); + + return OK; } static void draw_shape(redraw_man_t *rdman, shape_t *shape) { + switch(shape->sh_type) { + case SHT_PATH: + sh_path_draw(shape, rdman->cr); + break; + } } -static void clip_and_show(redraw_man_t *rdman, int n_dirty_areas, - area_t **dirty_areas) { +static void make_clip(redraw_man_t *rdman, int n_dirty_areas, + area_t **dirty_areas) { + int i; + area_t *area; + cairo_t *cr; + + cr = rdman->cr; + + cairo_reset_clip(cr); + for(i = 0; i < n_dirty_areas; i++) { + area = dirty_areas[i]; + cairo_rectangle(cr, area->x, area->y, area->w, area->h); + } + cairo_clip(cr); +} + +static void draw_shapes_in_areas(redraw_man_t *rdman, + int n_areas, + area_t **areas) { + geo_t *visit_geo; + int i; + + for(visit_geo = STAILQ_HEAD(rdman->all_geos); + visit_geo != NULL; + visit_geo = STAILQ_NEXT(geo_t, next, visit_geo)) { + if(visit_geo->flags & GEF_DIRTY) { + visit_geo->flags &= ~GEF_DIRTY; + update_shape_geo(visit_geo->shape); + } + for(i = 0; i < n_areas; i++) { + if(is_overlay(visit_geo->cur_area, areas[i])) { + draw_shape(rdman, visit_geo->shape); + break; + } + } + } } /*! \brief Re-draw all changed shapes or shapes affected by changed coords. @@ -371,14 +454,13 @@ * - Scan all shapes and redraw shapes overlaid with dirty areas. * * dirty flag of coord objects is cleared after update. + * dirty flag of geo objects is also cleared after recomputing. + * Clean dirty flag can prevent redundant computing for geo and + * corod objects. * - * assert(n_dirty_geos <= (num_of(shape) + num_of(coord))) - * Because - * - num_of(geo from coord) < num_of(coord) - * - num_of(geo from shape) < num_of(shape) */ int rdman_redraw_changed(redraw_man_t *rdman) { - int i; + int i, r; int n_dirty_coords; coord_t **dirty_coords; coord_t *visit_coord; @@ -407,10 +489,11 @@ visit_coord->flags &= ~COF_DIRTY; SWAP(visit_coord->cur_area, visit_coord->last_area, area_t *); - compute_coord_area(visit_coord); + r = compute_coord_area(visit_coord); + if(r == ERR) + return ERR; add_dirty_area(rdman, visit_coord->cur_area); add_dirty_area(rdman, visit_coord->last_area); - make_redrawing_members(rdman, visit_coord); } } rdman->n_dirty_coords = 0; @@ -430,21 +513,32 @@ add_dirty_area(rdman, visit_geo->cur_area); add_dirty_area(rdman, visit_geo->last_area); } + rdman->n_dirty_geos = 0; + } - n_dirty_areas = rdman->n_dirty_areas; - dirty_areas = rdman->dirty_areas; - for(visit_geo = STAILQ_HEAD(rdman->all_geos); - visit_geo != NULL; - visit_geo = STAILQ_NEXT(geo_t, next, visit_geo)) { - for(i = 0; i < n_dirty_areas; i++) { - if(is_overlay(visit_geo->cur_area, - dirty_areas[i])) { - draw_shape(rdman, visit_geo->shape); - break; - } - } + n_dirty_areas = rdman->n_dirty_areas; + dirty_areas = rdman->dirty_areas; + if(n_dirty_areas > 0) { + make_clip(rdman, n_dirty_areas, dirty_areas); + draw_shapes_in_areas(rdman, n_dirty_areas, dirty_areas); + rdman->n_dirty_areas = 0; + } + + return OK; +} + +int rdman_redraw_all(redraw_man_t *rdman) { + geo_t *geo; + + /* TODO: update dirty coord and it's members. */ + for(geo = STAILQ_HEAD(rdman->all_geos); + geo != NULL; + geo = STAILQ_NEXT(geo_t, next, geo)) { + if(geo->flags & GEF_DIRTY) { + geo->flags &= ~GEF_DIRTY; + update_shape_geo(geo->shape); } - clip_and_show(rdman, n_dirty_areas, dirty_areas); + draw_shape(rdman, geo->shape); } return OK; @@ -541,7 +635,7 @@ int n; int i; - redraw_man_init(&rdman); + redraw_man_init(&rdman, NULL); coords[0] = rdman.root_coord; for(i = 1; i < 3; i++) { coords[i] = rdman_coord_new(&rdman, rdman.root_coord); diff -r d34232f15863 -r c2ce186a5c37 src/redraw_man.h --- a/src/redraw_man.h Thu Jul 31 17:43:20 2008 +0800 +++ b/src/redraw_man.h Fri Aug 01 01:40:07 2008 +0800 @@ -1,6 +1,7 @@ #ifndef __REDRAW_MAN_H_ #define __REDRAW_MAN_H_ +#include #include "tools.h" #include "mb_types.h" @@ -42,9 +43,11 @@ int max_dirty_areas; int n_dirty_areas; area_t **dirty_areas; + + cairo_t *cr; } redraw_man_t; -extern int redraw_man_init(redraw_man_t *rdman); +extern int redraw_man_init(redraw_man_t *rdman, cairo_t *cr); extern void redraw_man_destroy(redraw_man_t *rdman); extern int rdman_find_overlaid_shapes(redraw_man_t *rdman, geo_t *geo, @@ -54,6 +57,9 @@ extern int rdman_remove_shape(redraw_man_t *rdman, shape_t *shape); extern coord_t *rdman_coord_new(redraw_man_t *rdman, coord_t *parent); extern int rdman_coord_free(redraw_man_t *rdman, coord_t *coord); +extern int rdman_coord_changed(redraw_man_t *rdman, coord_t *coord); +extern int rdman_redraw_changed(redraw_man_t *rdman); +extern int rdman_redraw_all(redraw_man_t *rdman); #endif /* __REDRAW_MAN_H_ */ diff -r d34232f15863 -r c2ce186a5c37 src/shape_path.c --- a/src/shape_path.c Thu Jul 31 17:43:20 2008 +0800 +++ b/src/shape_path.c Fri Aug 01 01:40:07 2008 +0800 @@ -431,7 +431,7 @@ cmd_len = path->cmd_len; cmds = path->dev_data; args = (co_aix *)(cmds + cmd_len); - x = y = 0; + x = y = x1 = y1 = x2 = y2 = 0; for(i = 0; i < cmd_len; i++) { cmd = *cmds++; switch(cmd) {