Mercurial > MadButterfly
changeset 159:b90abd31a281
Postponse free of coords, shapes, and paints when the rdman is dirty.
- Life-cycle of shapes and paints are managed by rdman.
- Add redraw_man_t::free_objs to collect objects their freeing are
postonsed.
Know Issue:
- Bullet of tank are not removed from screen when it is go out the range
of the map.
author | Thinker K.F. Li <thinker@branda.to> |
---|---|
date | Sun, 05 Oct 2008 23:32:58 +0800 |
parents | c1cdd3fcd28f |
children | 147c93163ef0 |
files | examples/tank/tank_main.c src/X_main.c src/event.c src/mb_types.h src/paint.c src/paint.h src/redraw_man.c src/redraw_man.h src/shape_path.c src/shape_rect.c src/shape_text.c src/shapes.h tools/mb_c_source.m4 |
diffstat | 13 files changed, 378 insertions(+), 165 deletions(-) [+] |
line wrap: on
line diff
--- a/examples/tank/tank_main.c Fri Oct 03 10:22:08 2008 +0800 +++ b/examples/tank/tank_main.c Sun Oct 05 23:32:58 2008 +0800 @@ -320,15 +320,19 @@ static void bullet_go_out_map_and_redraw(event_t *event, void *arg) { tank_t *tank = (tank_t *)arg; tank_bullet_t *bullet; +#if 0 ob_factory_t *factory; subject_t *redraw; +#endif bullet = tank->bullet; mb_progm_free(bullet->progm); rdman_force_clean(bullet->rdman); +#if 0 factory = rdman_get_ob_factory(bullet->rdman); redraw = rdman_get_redraw_subject(bullet->rdman); subject_remove_observer(factory, redraw, bullet->ob_redraw); +#endif tank_bullet_free(tank->bullet); tank->bullet = NULL; } @@ -337,8 +341,10 @@ tank_t *tank = (tank_t *)arg; tank_bullet_t *bullet; redraw_man_t *rdman; +#if 0 subject_t *redraw; ob_factory_t *factory; +#endif bullet = tank->bullet; rdman = bullet->rdman; @@ -350,11 +356,14 @@ rdman_coord_changed(rdman, bullet->coord_pos); /*! \todo Simplify the procdure of using observer pattern. */ +#if 0 factory = rdman_get_ob_factory(rdman); redraw = rdman_get_redraw_subject(rdman); bullet->ob_redraw = subject_add_observer(factory, redraw, bullet_go_out_map_and_redraw, tank); +#endif + bullet_go_out_map_and_redraw(NULL, tank); } static void bullet_bang(tank_bullet_t *bullet, int map_x, int map_y) {
--- a/src/X_main.c Fri Oct 03 10:22:08 2008 +0800 +++ b/src/X_main.c Sun Oct 05 23:32:58 2008 +0800 @@ -148,15 +148,15 @@ coord2 = rdman_coord_new(&rdman, rdman.root_coord); coord3 = rdman_coord_new(&rdman, rdman.root_coord); - fill1 = paint_color_new(&rdman, 1, 1, 0, 0.5); - fill2 = paint_color_new(&rdman, 0, 1, 1, 0.5); - stroke = paint_color_new(&rdman, 0.4, 0.4, 0.4, 1); - text_stroke = paint_color_new(&rdman, 0.5, 0.5, 0.5, 1); + fill1 = rdman_paint_color_new(&rdman, 1, 1, 0, 0.5); + fill2 = rdman_paint_color_new(&rdman, 0, 1, 1, 0.5); + stroke = rdman_paint_color_new(&rdman, 0.4, 0.4, 0.4, 1); + text_stroke = rdman_paint_color_new(&rdman, 0.5, 0.5, 0.5, 1); face = cairo_get_font_face(tmpcr); - text = sh_text_new("hello \xe6\xbc\xa2\xe5\xad\x97", 10, h / 4, - 36.0, face); - text_fill = paint_radial_new(&rdman, 100, h / 4, 70); + text = rdman_shape_text_new(&rdman, "hello \xe6\xbc\xa2\xe5\xad\x97", + 10, h / 4, 36.0, face); + text_fill = rdman_paint_radial_new(&rdman, 100, h / 4, 70); grad_stop_init(text_stops, 0, 0.2, 0.9, 0.2, 1); grad_stop_init(text_stops + 1, 1, 0.9, 0.2, 0.2, 0.1); paint_radial_stops(text_fill, 2, text_stops); @@ -165,7 +165,7 @@ rdman_paint_fill(&rdman, text_fill, text); rdman_add_shape(&rdman, text, coord3); - path1 = 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 "); + path1 = rdman_shape_path_new(&rdman, "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 "); rdman_paint_fill(&rdman, fill1, path1); rdman_paint_stroke(&rdman, stroke, path1); coord1->matrix[0] = 0.8; @@ -174,7 +174,7 @@ coord1->matrix[4] = 0.8; coord1->matrix[5] = 20; - path2 = 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 "); + path2 = rdman_shape_path_new(&rdman, "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 "); rdman_paint_fill(&rdman, fill2, path2); rdman_paint_stroke(&rdman, stroke, path2); coord2->matrix[0] = -0.8; @@ -189,12 +189,12 @@ rdman_add_shape(&rdman, (shape_t *)path2, coord2); - fill3 = paint_linear_new(&rdman, 50, 50, 150, 150); + fill3 = rdman_paint_linear_new(&rdman, 50, 50, 150, 150); grad_stop_init(fill3_stops, 0, 1, 0, 0, 0.5); grad_stop_init(fill3_stops + 1, 0.5, 0, 1, 0, 0.5); grad_stop_init(fill3_stops + 2, 1, 0, 0, 1, 0.5); paint_linear_stops(fill3, 3, fill3_stops); - rect = sh_rect_new(50, 50, 100, 100, 20, 20); + rect = rdman_shape_rect_new(&rdman, 50, 50, 100, 100, 20, 20); rdman_paint_fill(&rdman, fill3, rect); rdman_add_shape(&rdman, (shape_t *)rect, rdman.root_coord); @@ -243,16 +243,16 @@ mb_tman_free(tman); } - fill1->free(fill1); - fill2->free(fill2); - stroke->free(stroke); - text_stroke->free(text_stroke); - text_fill->free(text_fill); + rdman_paint_free(&rdman, fill1); + rdman_paint_free(&rdman, fill2); + rdman_paint_free(&rdman, stroke); + rdman_paint_free(&rdman, text_stroke); + rdman_paint_free(&rdman, text_fill); + rdman_shape_free(&rdman, path1); + rdman_shape_free(&rdman, path2); + rdman_shape_free(&rdman, rect); + rdman_shape_free(&rdman, text); redraw_man_destroy(&rdman); - path1->free(path1); - path2->free(path2); - rect->free(rect); - text->free(text); cairo_destroy(tmpcr); cairo_surface_destroy(tmpsuf); }
--- a/src/event.c Fri Oct 03 10:22:08 2008 +0800 +++ b/src/event.c Sun Oct 05 23:32:58 2008 +0800 @@ -11,18 +11,6 @@ #define ARRAY_EXT_SZ 64 -static int extend_memblk(void **buf, int o_size, int n_size) { - void *new_buf; - - new_buf = realloc(*buf, n_size); - if(new_buf == NULL) - return ERR; - - *buf = new_buf; - - return OK; -} - DARRAY_DEFINE(geos, geo_t *); /*! \brief Add a geo_t object to general geo list.
--- a/src/mb_types.h Fri Oct 03 10:22:08 2008 +0800 +++ b/src/mb_types.h Sun Oct 05 23:32:58 2008 +0800 @@ -12,20 +12,26 @@ typedef struct _shnode shnode_t; typedef struct _paint paint_t; +struct _redraw_man; + /*! \brief Base of paint types. * - * Paints should be freed by users by calling paint_t::free() of + * Paints should be freed by users by calling rdman_paint_free() of * the paint. * * \todo move member functions to a seperate structure and setup a * singleton fro each paint type. */ struct _paint { + int flags; void (*prepare)(paint_t *paint, cairo_t *cr); - void (*free)(paint_t *paint); + void (*free)(struct _redraw_man *rdman, paint_t *paint); STAILQ(shnode_t) members; + paint_t *pnt_next; /*!< \brief Collect all paints of a rdman. */ }; +#define PNTF_FREE 0x1 + struct _shnode { shape_t *shape; shnode_t *next; @@ -110,7 +116,10 @@ * of parent. */ int num_members; - STAILQ(geo_t) members; /*!< All geo_t members in this coord. */ + STAILQ(geo_t) members; /*!< \brief All geo_t members in this coord. */ + + STAILQ(shape_t) shapes; /*!< \brief All shapes managed by the rdman. */ + subject_t *mouse_event; } coord_t; #define COF_DIRTY 0x1 @@ -158,6 +167,7 @@ co_aix stroke_width; int stroke_linecap:2; int stroke_linejoin:2; + struct _shape *sh_next; /*!< Link all shapes of a rdman together. */ void (*free)(shape_t *shape); }; enum { SHT_UNKNOW, SHT_PATH, SHT_TEXT, SHT_RECT };
--- a/src/paint.c Fri Oct 03 10:22:08 2008 +0800 +++ b/src/paint.c Sun Oct 05 23:32:58 2008 +0800 @@ -10,7 +10,6 @@ typedef struct _paint_color { paint_t paint; co_comp_t r, g, b, a; - redraw_man_t *rdman; } paint_color_t; int _paint_color_size = sizeof(paint_color_t); @@ -22,22 +21,19 @@ cairo_set_source_rgba(cr, color->r, color->g, color->b, color->a); } -static void paint_color_free(paint_t *paint) { - paint_color_t *color = (paint_color_t *)paint; - - shnode_list_free(color->rdman, paint->members); - elmpool_elm_free(color->rdman->paint_color_pool, paint); +static void paint_color_free(redraw_man_t *rdman, paint_t *paint) { + shnode_list_free(rdman, paint->members); + elmpool_elm_free(rdman->paint_color_pool, paint); } -paint_t *paint_color_new(redraw_man_t *rdman, - co_comp_t r, co_comp_t g, - co_comp_t b, co_comp_t a) { +paint_t *rdman_paint_color_new(redraw_man_t *rdman, + co_comp_t r, co_comp_t g, + co_comp_t b, co_comp_t a) { paint_color_t *color; color = (paint_color_t *)elmpool_elm_alloc(rdman->paint_color_pool); if(color == NULL) return NULL; - color->rdman = rdman; color->r = r; color->g = g; color->b = b; @@ -107,7 +103,7 @@ cairo_set_source(cr, ptn); } -static void paint_linear_free(paint_t *paint) { +static void paint_linear_free(redraw_man_t *rdman, paint_t *paint) { paint_linear_t *linear = (paint_linear_t *)paint; if(linear->ptn) @@ -115,8 +111,9 @@ free(paint); } -paint_t *paint_linear_new(redraw_man_t *rdman, - co_aix x1, co_aix y1, co_aix x2, co_aix y2) { +paint_t *rdman_paint_linear_new(redraw_man_t *rdman, + co_aix x1, co_aix y1, + co_aix x2, co_aix y2) { paint_linear_t *linear; linear = (paint_linear_t *)malloc(sizeof(paint_linear_t)); @@ -196,7 +193,7 @@ cairo_set_source(cr, radial->ptn); } -static void paint_radial_free(paint_t *paint) { +static void paint_radial_free(redraw_man_t *rdman, paint_t *paint) { paint_radial_t *radial = (paint_radial_t *)paint; if(radial->ptn) @@ -204,8 +201,8 @@ free(paint); } -paint_t *paint_radial_new(redraw_man_t *rdman, - co_aix cx, co_aix cy, co_aix r) { +paint_t *rdman_paint_radial_new(redraw_man_t *rdman, + co_aix cx, co_aix cy, co_aix r) { paint_radial_t *radial; radial = O_ALLOC(paint_radial_t);
--- a/src/paint.h Fri Oct 03 10:22:08 2008 +0800 +++ b/src/paint.h Sun Oct 05 23:32:58 2008 +0800 @@ -8,9 +8,9 @@ typedef float co_comp_t; -extern paint_t *paint_color_new(redraw_man_t *rdman, - co_comp_t r, co_comp_t g, - co_comp_t b, co_comp_t a); +extern paint_t *rdman_paint_color_new(redraw_man_t *rdman, + co_comp_t r, co_comp_t g, + co_comp_t b, co_comp_t a); extern void paint_color_set(paint_t *paint, co_comp_t r, co_comp_t g, co_comp_t b, co_comp_t a); @@ -19,9 +19,11 @@ co_comp_t *b, co_comp_t *a); #define paint_init(_paint, _prepare, _free) \ do { \ + (_paint)->flags = 0; \ (_paint)->prepare = _prepare; \ (_paint)->free = _free; \ STAILQ_INIT((_paint)->members); \ + (_paint)->pnt_next = NULL; \ } while(0) \ @@ -30,13 +32,14 @@ co_comp_t r, g, b, a; } grad_stop_t; -extern paint_t *paint_linear_new(redraw_man_t *rdman, - co_aix x1, co_aix y1, co_aix x2, co_aix y2); +extern paint_t *rdman_paint_linear_new(redraw_man_t *rdman, + co_aix x1, co_aix y1, + co_aix x2, co_aix y2); extern grad_stop_t *paint_linear_stops(paint_t *paint, int n_stops, grad_stop_t *stops); -extern paint_t *paint_radial_new(redraw_man_t *rdman, - co_aix cx, co_aix cy, co_aix r); +extern paint_t *rdman_paint_radial_new(redraw_man_t *rdman, + co_aix cx, co_aix cy, co_aix r); extern grad_stop_t *paint_radial_stops(paint_t *paint, int n_stops, grad_stop_t *stops);
--- a/src/redraw_man.c Fri Oct 03 10:22:08 2008 +0800 +++ b/src/redraw_man.c Sun Oct 05 23:32:58 2008 +0800 @@ -74,6 +74,16 @@ STAILQ_REMOVE((coord)->members, geo_t, coord_next, (member)) #define FIRST_MEMBER(coord) STAILQ_HEAD((coord)->members) +/* Functions for paint members. */ +#define FORPAINTMEMBERS(paint, member) \ + for((member) = STAILQ_HEAD((paint)->members); \ + (member) != NULL; \ + (member) = STAILQ_NEXT(paint_t, next, member)) +#define RM_PAINTMEMBER(paint, member) \ + STAILQ_REMOVE((paint)->members, shnode_t, next, member) +#define RM_PAINT(rdman, paint) \ + STAILQ_REMOVE((rdman)->paints, paint_t, pnt_next, paint) + /*! \brief Sort a list of element by a unsigned integer. * * The result is in ascend order. The unsigned integers is @@ -122,12 +132,42 @@ ADD_DATA(areas, dirty_areas, area); } -static int add_free_coord(redraw_man_t *rdman, coord_t *coord) { - ADD_DATA(coords, free_coords, coord); +static int add_free_obj(redraw_man_t *rdman, void *obj, + free_func_t free_func) { + int max; + free_obj_t *new_objs, *free_obj; + + if(rdman->free_objs.num >= rdman->free_objs.max) { + max = rdman->free_objs.num + ARRAY_EXT_SZ; + new_objs = realloc(rdman->free_objs.objs, + max * sizeof(free_obj_t)); + if(new_objs == NULL) + return ERR; + rdman->free_objs.max = max; + rdman->free_objs.objs = new_objs; + } + + free_obj = rdman->free_objs.objs + rdman->free_objs.num++; + free_obj->obj = obj; + free_obj->free_func = free_func; + + return OK; } -static int add_free_geo(redraw_man_t *rdman, geo_t *geo) { - ADD_DATA(geos, free_geos, geo); +static void free_free_objs(redraw_man_t *rdman) { + int i; + free_obj_t *free_obj; + + for(i = 0; i < rdman->free_objs.num; i++) { + free_obj = &rdman->free_objs.objs[i]; + free_obj->free_func(rdman, free_obj->obj); + } + rdman->free_objs.num = 0; +} + +static void free_objs_destroy(redraw_man_t *rdman) { + if(rdman->free_objs.objs != NULL) + free(rdman->free_objs.objs); } static void area_to_positions(area_t *area, co_aix (*poses)[2]) { @@ -269,29 +309,47 @@ rdman->cr = cr; rdman->backend = backend; + STAILQ_INIT(rdman->shapes); + STAILQ_INIT(rdman->paints); + return OK; } void redraw_man_destroy(redraw_man_t *rdman) { coord_t *coord, *saved_coord; + shape_t *shape, *saved_shape; geo_t *member; + free_free_objs(rdman); + free_objs_destroy(rdman); + coord = postorder_coord_subtree(rdman->root_coord, NULL); while(coord) { saved_coord = coord; coord = postorder_coord_subtree(rdman->root_coord, coord); FORMEMBERS(saved_coord, member) { - rdman_remove_shape(rdman, member->shape); + rdman_shape_free(rdman, member->shape); } rdman_coord_free(rdman, saved_coord); } FORMEMBERS(saved_coord, member) { - rdman_remove_shape(rdman, member->shape); + rdman_shape_free(rdman, member->shape); } /* Resources of root_coord is free by elmpool_free() or * caller; for canvas */ + shape = saved_shape = STAILQ_HEAD(rdman->shapes); + while(shape && (shape = STAILQ_NEXT(shape_t, sh_next, shape))) { + rdman_shape_free(rdman, saved_shape); +#if 0 + STAILQ_REMOVE(rdman->shapes, shape_t, sh_next, saved_shape); +#endif + saved_shape = shape; + } + if(saved_shape != NULL) + rdman_shape_free(rdman, saved_shape); + elmpool_free(rdman->coord_pool); elmpool_free(rdman->geo_pool); elmpool_free(rdman->shnode_pool); @@ -303,8 +361,6 @@ DARRAY_DESTROY(&rdman->dirty_geos); DARRAY_DESTROY(&rdman->dirty_areas); DARRAY_DESTROY(&rdman->gen_geos); - DARRAY_DESTROY(&rdman->free_coords); - DARRAY_DESTROY(&rdman->free_geos); } @@ -362,35 +418,95 @@ * is postponsed. * \todo redraw shape objects that overlaid with removed one. */ -int rdman_remove_shape(redraw_man_t *rdman, shape_t *shape) { +int rdman_shape_free(redraw_man_t *rdman, shape_t *shape) { geo_t *geo; - coord_t *coord; int r; geo = shape->geo; - coord = shape->coord; - if(rdman_is_dirty(rdman)) { + if(rdman_is_dirty(rdman) && geo != NULL) { + if(geo->flags & GEF_FREE) + return ERR; + geo->flags |= GEF_FREE | GEF_HIDDEN; if(!(geo->flags & GEF_DIRTY)) { r = add_dirty_geo(rdman, geo); if(r != OK) return ERR; } - r = add_free_geo(rdman, geo); + r = add_free_obj(rdman, shape, (free_func_t)rdman_shape_free); if(r != OK) return ERR; return OK; } - geo_detach_coord(geo, coord); - subject_free(&rdman->ob_factory, geo->mouse_event); - sh_detach_geo(shape); - elmpool_elm_free(rdman->geo_pool, geo); - sh_detach_coord(shape); + if(geo != NULL) { + geo_detach_coord(geo, shape->coord); + sh_detach_coord(shape); + sh_detach_geo(shape); + subject_free(&rdman->ob_factory, geo->mouse_event); + elmpool_elm_free(rdman->geo_pool, geo); + } + STAILQ_REMOVE(rdman->shapes, shape_t, sh_next, shape); + shape->free(shape); return OK; } +shnode_t *shnode_new(redraw_man_t *rdman, shape_t *shape) { + shnode_t *node; + + node = (shnode_t *)elmpool_elm_alloc(rdman->shnode_pool); + if(node) { + node->shape = shape; + node->next = NULL; + } + return node; +} + +int rdman_paint_free(redraw_man_t *rdman, paint_t *paint) { + shnode_t *shnode, *saved_shnode; + + if(rdman_is_dirty(rdman)) { + if(!(paint->flags & PNTF_FREE)) + return ERR; + add_free_obj(rdman, paint, (free_func_t)rdman_paint_free); + paint->flags |= PNTF_FREE; + return OK; + } + + /* Free member shapes that using this paint. */ + saved_shnode = NULL; + FORPAINTMEMBERS(paint, shnode) { + if(saved_shnode) { + RM_PAINTMEMBER(paint, saved_shnode); + shnode_free(rdman, saved_shnode); + } + saved_shnode = shnode; + } + if(saved_shnode) { + RM_PAINTMEMBER(paint, saved_shnode); + shnode_free(rdman, saved_shnode); + } + + RM_PAINT(rdman, paint); + paint->free(rdman, paint); + return OK; +} + +void _rdman_paint_real_remove_child(redraw_man_t *rdman, + paint_t *paint, + shape_t *shape) { + shnode_t *shnode; + + FORPAINTMEMBERS(paint, shnode) { + if(shnode->shape == shape) { + RM_PAINTMEMBER(paint, shnode); + shnode_free(rdman, shnode); + break; + } + } +} + coord_t *rdman_coord_new(redraw_man_t *rdman, coord_t *parent) { coord_t *coord, *root_coord; coord_t *visit; @@ -448,6 +564,9 @@ return ERR; if(rdman_is_dirty(rdman)) { + if(coord->flags & COF_FREE) + return ERR; + FORCHILDREN(coord, child) { if(!(child->flags & COF_FREE)) return ERR; @@ -462,7 +581,7 @@ if(r != OK) return ERR; } - r = add_free_coord(rdman, coord); + r = add_free_obj(rdman, coord, (free_func_t)rdman_coord_free); if(r != OK) return ERR; return OK; @@ -474,9 +593,6 @@ if(FIRST_CHILD(coord) != NULL) return ERR; - if(coord->flags & COF_FREE) - return ERR; - /* Free canvas (\ref redraw) */ if(coord->flags & COF_OWN_CANVAS) free_canvas(coord->canvas); @@ -500,14 +616,18 @@ for(coord = postorder_coord_subtree(subtree, prev_coord); coord != NULL; coord = postorder_coord_subtree(subtree, coord)) { + if(!(prev_coord->flags & COF_FREE)) { + r = rdman_coord_free(rdman, prev_coord); + if(r != OK) + return ERR; + } + prev_coord = coord; + } + if(!(prev_coord->flags & COF_FREE)) { r = rdman_coord_free(rdman, prev_coord); if(r != OK) return ERR; - prev_coord = coord; } - r = rdman_coord_free(rdman, prev_coord); - if(r != OK) - return ERR; return OK; } @@ -566,13 +686,11 @@ } int rdman_paint_changed(redraw_man_t *rdman, paint_t *paint) { - shnode_t *node; + shnode_t *shnode; int r; - for(node = STAILQ_HEAD(paint->members); - node != NULL; - node = STAILQ_NEXT(shnode_t, next, node)) { - r = _rdman_shape_changed(rdman, node->shape); + FORPAINTMEMBERS(paint, shnode) { + r = _rdman_shape_changed(rdman, shnode->shape); if(r != OK) return ERR; } @@ -986,9 +1104,6 @@ event_t event; ob_factory_t *factory; subject_t *redraw; - geo_t *geo; - coord_t *coord; - int i; r = clean_rdman_dirties(rdman); if(r != OK) @@ -1010,17 +1125,7 @@ rdman->dirty_areas.num = 0; /* Free postponsed removing */ - for(i = 0; i < rdman->free_geos.num; i++) { - geo = rdman->free_geos.ds[i]; - rdman_remove_shape(rdman, geo->shape); - } - DARRAY_CLEAN(&rdman->free_geos); - - for(i = 0; i < rdman->free_coords.num; i++) { - coord = rdman->free_coords.ds[i]; - rdman_remove_shape(rdman, coord); - } - DARRAY_CLEAN(&rdman->free_coords); + free_free_objs(rdman); factory = rdman_get_ob_factory(rdman); redraw = rdman_get_redraw_subject(rdman); @@ -1058,8 +1163,10 @@ */ int rdman_redraw_all(redraw_man_t *rdman) { + area_t area; +#ifndef UNITTEST cairo_surface_t *surface; - area_t area; +#endif int r; area.x = area.y = 0; @@ -1128,17 +1235,6 @@ return r; } -shnode_t *shnode_new(redraw_man_t *rdman, shape_t *shape) { - shnode_t *node; - - node = (shnode_t *)elmpool_elm_alloc(rdman->shnode_pool); - if(node) { - node->shape = shape; - node->next = NULL; - } - return node; -} - /*! \page dirty Dirty geo, coord, and area. * * \section dirty_of_ego Dirty of geo @@ -1174,6 +1270,28 @@ * coords will also clean member geos. */ +/*! \page man_obj Manage Objects. + * + * Shapes and paints should also be managed by redraw manager. Redraw + * manager must know life-cycle of shapes and paints to avoid to use them + * after being free. If a shape is released when it is dirty, redraw + * manager will try to access them, after released, for redrawing. + * We can make a copy information need by redraw manager to redraw them, + * but it is more complicate, and induce runtime overhead. + * + * So, redraw manage had better also manage life-cycle of shapes and paints. + * Shapes and paints should be created and freed through interfaces + * provided by redraw manager. To reduce overhead of interfaces, they can + * be implemented as C macros. + * + * To refactory redraw manage to manage life-cycle of shapes and paints, + * following functions/macros are introduced. + * - rdman_paint_*_new() + * - rdman_paint_free() + * - rdman_shape_*_new() + * - rdman_shape_free() + */ + /* * When redraw an area, the affected elements may also extend to * outside of the area. Since the order of drawing will change @@ -1284,7 +1402,12 @@ int draw_cnt; }; -shape_t *sh_dummy_new(co_aix x, co_aix y, co_aix w, co_aix h) { +void sh_dummy_free(shape_t *sh) { + free(sh); +} + +shape_t *sh_dummy_new(redraw_man_t *rdman, + co_aix x, co_aix y, co_aix w, co_aix h) { sh_dummy_t *dummy; dummy = (sh_dummy_t *)malloc(sizeof(sh_dummy_t)); @@ -1299,14 +1422,13 @@ dummy->h = h; dummy->trans_cnt = 0; dummy->draw_cnt = 0; + dummy->shape.free = sh_dummy_free; + + rdman_shape_man(rdman, (shape_t *)dummy); return (shape_t *)dummy; } -void sh_dummy_free(shape_t *sh) { - free(sh); -} - void sh_dummy_transform(shape_t *shape) { sh_dummy_t *dummy = (sh_dummy_t *)shape; co_aix poses[2][2]; @@ -1341,7 +1463,7 @@ static void dummy_paint_prepare(paint_t *paint, cairo_t *cr) { } -static void dummy_paint_free(paint_t *paint) { +static void dummy_paint_free(redraw_man_t *rdman, paint_t *paint) { if(paint) free(paint); } @@ -1358,7 +1480,7 @@ return paint; } -void test_rdman_redraw_changed(void) { +static void test_rdman_redraw_changed(void) { coord_t *coords[3]; shape_t *shapes[3]; sh_dummy_t **dummys; @@ -1373,7 +1495,7 @@ redraw_man_init(rdman, NULL, NULL); paint = dummy_paint_new(rdman); for(i = 0; i < 3; i++) { - shapes[i] = sh_dummy_new(0, 0, 50, 50); + shapes[i] = sh_dummy_new(rdman, 0, 0, 50, 50); rdman_paint_fill(rdman, paint, shapes[i]); coords[i] = rdman_coord_new(rdman, rdman->root_coord); coords[i]->matrix[2] = 10 + i * 100; @@ -1399,15 +1521,39 @@ CU_ASSERT(dummys[1]->draw_cnt == 2); CU_ASSERT(dummys[2]->draw_cnt == 2); - paint->free(paint); + rdman_paint_free(rdman, paint); redraw_man_destroy(rdman); } +static int test_free_pass = 0; + +static void test_free(redraw_man_t *rdman, void *obj) { + test_free_pass++; +} + +static void test_rdman_free_objs(void) { + redraw_man_t *rdman; + redraw_man_t _rdman; + int i; + + redraw_man_init(&_rdman, NULL, NULL); + rdman = &_rdman; + + test_free_pass = 0; + + for(i = 0; i < 4; i++) + add_free_obj(rdman, NULL, test_free); + + redraw_man_destroy(rdman); + CU_ASSERT(test_free_pass == 4); +} + CU_pSuite get_redraw_man_suite(void) { CU_pSuite suite; suite = CU_add_suite("Suite_redraw_man", NULL, NULL); CU_ADD_TEST(suite, test_rdman_redraw_changed); + CU_ADD_TEST(suite, test_rdman_free_objs); return suite; }
--- a/src/redraw_man.h Fri Oct 03 10:22:08 2008 +0800 +++ b/src/redraw_man.h Sun Oct 05 23:32:58 2008 +0800 @@ -6,6 +6,20 @@ #include "mb_types.h" #include "observer.h" +typedef struct _redraw_man redraw_man_t; + +typedef void (*free_func_t)(redraw_man_t *rdman, void *obj); +struct _free_obj { + void *obj; + free_func_t free_func; +}; +typedef struct _free_obj free_obj_t; +struct _free_objs { + int num, max; + free_obj_t *objs; +}; +typedef struct _free_objs free_objs_t; + DARRAY(coords, coord_t *); DARRAY(geos, geo_t *); DARRAY(areas, area_t *); @@ -25,7 +39,7 @@ * Dirty flag is clear when the transformation matrix of a coord * object been recomputed or when a geo_t objects been redrawed. */ -typedef struct _redraw_man { +struct _redraw_man { unsigned int next_coord_order; int n_coords; coord_t *root_coord; @@ -43,8 +57,10 @@ geos_t gen_geos; - coords_t free_coords; - geos_t free_geos; + STAILQ(shape_t) shapes; /*!< \brief All managed shapes. */ + STAILQ(paint_t) paints; /*!< \brief All managed paints. */ + + free_objs_t free_objs; cairo_t *cr; cairo_t *backend; @@ -52,7 +68,7 @@ ob_factory_t ob_factory; subject_t *redraw; /*!< \brief Notified after redrawing. */ -} redraw_man_t; +}; extern int redraw_man_init(redraw_man_t *rdman, cairo_t *cr, cairo_t *backend); @@ -62,7 +78,15 @@ geo_t ***overlays); extern int rdman_add_shape(redraw_man_t *rdman, shape_t *shape, coord_t *coord); -extern int rdman_remove_shape(redraw_man_t *rdman, shape_t *shape); +/*! \brief Make a shape been managed by a redraw manager. */ +#define rdman_shape_man(rdman, shape) \ + STAILQ_INS_TAIL(rdman->shapes, shape_t, sh_next, shape) +extern int rdman_shape_free(redraw_man_t *rdman, shape_t *shape); + +#define rdman_paint_man(rdman, paint) \ + STAILQ_INS_TAIL(rdman->paints, paint_t, pnt_next, shape) +extern int rdman_paint_free(redraw_man_t *rdman, paint_t *paint); + 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_subtree_free(redraw_man_t *rdman, coord_t *subtree); @@ -99,15 +123,31 @@ shnode_t, next, __node); \ } \ } while(0) +extern void _rdman_paint_real_remove_child(redraw_man_t *rdman, + paint_t *paint, + shape_t *shape); +#define _rdman_paint_remove_child(rdman, paint, shape) \ + do { \ + if((shape)->fill == (shape)->stroke && \ + (shape)->stroke == paint) \ + break; \ + _rdman_paint_real_remove_child(rdman, paint, shape); \ + } while(0) #define rdman_paint_fill(rdman, paint, shape) \ do { \ + if((shape)->fill == paint) \ + break; \ + _rdman_paint_remove_child(rdman, paint, shape); \ _rdman_paint_child(rdman, paint, shape); \ - shape->fill = paint; \ + (shape)->fill = paint; \ } while(0) #define rdman_paint_stroke(rdman, paint, shape) \ do { \ + if((shape)->stroke == paint) \ + break; \ + _rdman_paint_remove_child(rdman, paint, shape); \ _rdman_paint_child(rdman, paint, shape); \ - shape->stroke = paint; \ + (shape)->stroke = paint; \ } while(0) extern int rdman_paint_changed(redraw_man_t *rdman, paint_t *paint);
--- a/src/shape_path.c Fri Oct 03 10:22:08 2008 +0800 +++ b/src/shape_path.c Sun Oct 05 23:32:58 2008 +0800 @@ -4,6 +4,7 @@ #include <string.h> #include <cairo.h> #include "mb_types.h" +#include "redraw_man.h" /*! \brief Implement respective objects for SVG path tag. * @@ -660,7 +661,7 @@ /*! \brief Create a path from value of 'data' of SVG path. */ -shape_t *sh_path_new(char *data) { +shape_t *rdman_shape_path_new(redraw_man_t *rdman, char *data) { sh_path_t *path; int cmd_cnt, arg_cnt, fix_arg_cnt; int msz; @@ -705,6 +706,10 @@ path->shape.free = sh_path_free; +#ifndef UNITTEST + rdman_shape_man(rdman, (shape_t *)path); +#endif + return (shape_t *)path; } @@ -834,11 +839,11 @@ #include <CUnit/Basic.h> -void test_sh_path_new(void) { +void test_rdman_shape_path_new(void) { sh_path_t *path; co_aix *args; - path = (sh_path_t *)sh_path_new("M 33 25l33 55c 33 87 44 22 55 99L33 77z"); + path = (sh_path_t *)rdman_shape_path_new(NULL, "M 33 25l33 55c 33 87 44 22 55 99L33 77z"); CU_ASSERT(path != NULL); CU_ASSERT(path->cmd_len == ((5 + RESERVED_AIXS + 3) & ~0x3)); CU_ASSERT(path->arg_len == 12); @@ -867,7 +872,7 @@ coord_t coord; geo_t geo; - path = (sh_path_t *)sh_path_new("M 33 25l33 55C 33 87 44 22 55 99L33 77z"); + path = (sh_path_t *)rdman_shape_path_new(NULL, "M 33 25l33 55C 33 87 44 22 55 99L33 77z"); CU_ASSERT(path != NULL); CU_ASSERT(path->cmd_len == ((5 + RESERVED_AIXS + 3) & ~0x3)); CU_ASSERT(path->arg_len == 12); @@ -908,7 +913,8 @@ sh_path_t *path; path = (sh_path_t *) - sh_path_new(" M 33 25l33 55C 33 87 44 22 55 99L33 77z "); + rdman_shape_path_new(NULL, + " M 33 25l33 55C 33 87 44 22 55 99L33 77z "); CU_ASSERT(path != NULL); sh_path_free((shape_t *)path); } @@ -917,7 +923,7 @@ CU_pSuite suite; suite = CU_add_suite("Suite_shape_path", NULL, NULL); - CU_ADD_TEST(suite, test_sh_path_new); + CU_ADD_TEST(suite, test_rdman_shape_path_new); CU_ADD_TEST(suite, test_path_transform); return suite;
--- a/src/shape_rect.c Fri Oct 03 10:22:08 2008 +0800 +++ b/src/shape_rect.c Sun Oct 05 23:32:58 2008 +0800 @@ -16,8 +16,9 @@ free(shape); } -shape_t *sh_rect_new(co_aix x, co_aix y, co_aix w, co_aix h, - co_aix rx, co_aix ry) { +shape_t *rdman_shape_rect_new(redraw_man_t *rdman, + co_aix x, co_aix y, co_aix w, co_aix h, + co_aix rx, co_aix ry) { sh_rect_t *rect; rect = (sh_rect_t *)malloc(sizeof(sh_rect_t)); @@ -35,6 +36,8 @@ rect->ry = ry; rect->shape.free = sh_rect_free; + rdman_shape_man(rdman, (shape_t *)rect); + return (shape_t *)rect; }
--- a/src/shape_text.c Fri Oct 03 10:22:08 2008 +0800 +++ b/src/shape_text.c Sun Oct 05 23:32:58 2008 +0800 @@ -32,8 +32,9 @@ cairo_font_face_destroy(text->face); } -shape_t *sh_text_new(const char *txt, co_aix x, co_aix y, - co_aix font_size, cairo_font_face_t *face) { +shape_t *rdman_shape_text_new(redraw_man_t *rdman, + const char *txt, co_aix x, co_aix y, + co_aix font_size, cairo_font_face_t *face) { sh_text_t *text; text = (sh_text_t *)malloc(sizeof(sh_text_t)); @@ -56,6 +57,8 @@ text->shape.free = sh_text_free; + rdman_shape_man(rdman, (shape_t *)text); + return (shape_t *)text; }
--- a/src/shapes.h Fri Oct 03 10:22:08 2008 +0800 +++ b/src/shapes.h Sun Oct 05 23:32:58 2008 +0800 @@ -9,12 +9,18 @@ #include <cairo.h> #include "mb_types.h" +#include "redraw_man.h" /*! \page define_shape How to Define Shapes * - * A shape must include - * - *_new() and *_free() + * A shape implementation must include + * - rdman_shape_*_new() * - clear memory for shape_t member. + * - assign *_free() to \ref shape_t::free. + * - make new object been managed by a redraw manager. + * - call rdman_shape_man() + * - *_free() + * - assigned to \ref shape_t::free. * - *_transform() * - *_draw() * - first member variable of a shape type must be a shape_t. @@ -32,7 +38,7 @@ /*! \defgroup shape_path Shape of Path * @{ */ -extern shape_t *sh_path_new(char *data); +extern shape_t *rdman_shape_path_new(redraw_man_t *rdman, char *data); extern void sh_path_transform(shape_t *shape); extern void sh_path_draw(shape_t *shape, cairo_t *cr); /* @} */ @@ -40,8 +46,10 @@ /*! \defgroup shape_text Shape of Text * @{ */ -extern shape_t *sh_text_new(const char *txt, co_aix x, co_aix y, - co_aix font_size, cairo_font_face_t *face); +extern shape_t *rdman_shape_text_new(redraw_man_t *rdman, + const char *txt, co_aix x, co_aix y, + co_aix font_size, + cairo_font_face_t *face); extern void sh_text_set_text(shape_t *shape, const char *txt); extern void sh_text_transform(shape_t *shape); extern void sh_text_draw(shape_t *shape, cairo_t *cr); @@ -50,8 +58,10 @@ /*! \defgroup shape_rect Shape of Rectangle * @{ */ -extern shape_t *sh_rect_new(co_aix x, co_aix y, co_aix w, co_aix h, - co_aix rx, co_aix ry); +extern shape_t *rdman_shape_rect_new(redraw_man_t *rdman, + co_aix x, co_aix y, + co_aix w, co_aix h, + co_aix rx, co_aix ry); extern void sh_rect_transform(shape_t *shape); extern void sh_rect_draw(shape_t *shape, cairo_t *cr); extern void sh_rect_set(shape_t *shape, co_aix x, co_aix y,
--- a/tools/mb_c_source.m4 Fri Oct 03 10:22:08 2008 +0800 +++ b/tools/mb_c_source.m4 Sun Oct 05 23:32:58 2008 +0800 @@ -53,7 +53,7 @@ divert[]]) define([S_ADD_LINEAR_PAINT],[ - obj->$1 = paint_linear_new(rdman, $2, $3, $4, $5); + obj->$1 = rdman_paint_linear_new(rdman, $2, $3, $4, $5); ifelse(COUNT($6),0,,[dnl stops = (grad_stop_t *)malloc(sizeof(grad_stop_t) * n_$1_stops); memcpy(stops, $1_stops, sizeof(grad_stop_t) * n_$1_stops); @@ -62,7 +62,7 @@ ]) define([S_ADD_RADIAL_PAINT],[ - obj->$1 = paint_radial_new(rdman, $2, $3, $4); + obj->$1 = rdman_paint_radial_new(rdman, $2, $3, $4); ifelse(COUNT($5),0,,[ stops = (grad_stop_t *)malloc(sizeof(grad_stop_t) * n_$1_stops); memcpy(stops, $1_stops, sizeof(grad_stop_t) * n_$1_stops); @@ -85,12 +85,12 @@ ]]) define([S_ADD_RECT],[[ - obj->$1 = sh_rect_new($2, $3, $4, $5, $6, $7); + obj->$1 = rdman_shape_rect_new(rdman, $2, $3, $4, $5, $6, $7); rdman_add_shape(rdman, obj->$1, obj->$8); ]]) define([S_ADD_PATH],[[ - obj->$1 = sh_path_new("$2"); + obj->$1 = rdman_shape_path_new(rdman, "$2"); rdman_add_shape(rdman, obj->$1, obj->$3); ]]) @@ -99,7 +99,8 @@ ]]) define([S_ADD_TEXT],[[ - obj->$1 = sh_text_new("$2", $3, $4, $5, cairo_get_font_face(rdman->cr)); + obj->$1 = rdman_shape_text_new(rdman, "$2", $3, $4, $5, + cairo_get_font_face(rdman->cr)); rdman_add_shape(rdman, obj->$1, obj->$6); ]]) @@ -112,12 +113,12 @@ ]]) define([S_FILL_SHAPE],[dnl -[ obj->$1_fill = paint_color_new(rdman, $2, $3, $4, $5); +[ obj->$1_fill = rdman_paint_color_new(rdman, $2, $3, $4, $5); rdman_paint_fill(rdman, obj->$1_fill, obj->$1); ]]) define([S_STROKE_SHAPE],[dnl -[ obj->$1_stroke = paint_color_new(rdman, $2, $3, $4, $5); +[ obj->$1_stroke = rdman_paint_color_new(rdman, $2, $3, $4, $5); rdman_paint_stroke(rdman, obj->$1_stroke, obj->$1); ]]) @@ -203,36 +204,33 @@ define([F_ADD_LINEAR_PAINT],[[ stops = paint_linear_stops(obj->$1, 0, NULL); free(stops); - obj->$1->free(obj->$1); + rdman_paint_free(rdman, obj->$1); ]]) define([F_ADD_RADIAL_PAINT],[[ stops = paint_radial_stops(obj->$1, 0, NULL); free(stops); - obj->$1->free(obj->$1); + rdman_paint_free(rdman, obj->$1); ]]) define([F_ADD_PATH],[[ - rdman_remove_shape(rdman, obj->$1); - obj->$1->free(obj->$1); + rdman_shape_free(rdman, obj->$1); ]]) define([F_ADD_RECT],[[ - rdman_remove_shape(rdman, obj->$1); - obj->$1->free(obj->$1); + rdman_shape_free(rdman, obj->$1); ]]) define([F_ADD_TEXT],[[ - rdman_remove_shape(rdman, obj->$1); - obj->$1->free(obj->$1); + rdman_shape_free(rdman, obj->$1); ]]) define([F_FILL_SHAPE],[[ - obj->$1_fill->free(obj->$1_fill); + rdman_paint_free(rdman, obj->$1_fill); ]]) define([F_STROKE_SHAPE],[[ - obj->$1_stroke->free(obj->$1_stroke); + rdman_paint_free(rdman, obj->$1_stroke); ]]) define([CLEAR_VARS],[divert([-1])