Mercurial > MadButterfly
diff src/redraw_man.c @ 1067:7b4e80ab671a openvg
merge from default branch
author | Thinker K.F. Li <thinker@codemud.net> |
---|---|
date | Wed, 01 Dec 2010 12:25:56 +0800 |
parents | b42d69ab8857 a8d20bc8ce40 |
children | d09f603438d8 |
line wrap: on
line diff
--- a/src/redraw_man.c Mon Jul 19 15:44:49 2010 +0800 +++ b/src/redraw_man.c Wed Dec 01 12:25:56 2010 +0800 @@ -1,3 +1,5 @@ +// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- +// vim: sw=4:ts=8:sts=4 #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -158,7 +160,7 @@ * - areas of descendants of cached coord are in space defined * by aggr_matrix of cached coord. * - descendants are marked with \ref COF_ANCESTOR_CACHE - * + * * Since *_transform of shapes compute area with aggr_matrix that is * derived from aggr_matrix of a cached ancestor, area of * \ref COF_ANCESTOR_CACHE ones should be transformed to device space in @@ -237,7 +239,7 @@ * process of adjusting left-top of bounding box is zeroing. * * Following is rules. - * - zeroing on a cached coord is performed by adjust coord_t::aggr_matrix + * - zeroing on a cached coord is performed by adjust coord_t::aggr_matrix * of the cached coord and descendnats. * - Clean coords works just like before without change. * - in preorder @@ -302,6 +304,38 @@ #define ASSERT(x) #endif +/* + * Conitions for coords. + */ +#define coord_is_cached(co) ((co)->flags & COF_OWN_CANVAS) +#define coord_is_always_cached(co) ((co)->flags & COF_ALWAYS_CACHE) +#define coord_is_fast_cached(co) ((co)->flags & COF_FAST_MASK) +#define coord_is_precise_cached(co) ((co)->flags & COF_PRECISE_MASK) +#define coord_is_zeroing(co) ((co)->flags & COF_MUST_ZEROING) +#define coord_set_zeroing(co) \ + do { (co)->flags |= COF_MUST_ZEROING; } while(0) +#define coord_clear_zeroing(co) \ + do { (co)->flags &= ~COF_MUST_ZEROING; } while(0) +#define coord_set_flags(co, _flags) \ + do { (co)->flags |= (_flags); } while(0) +#define coord_get_parent(co) ((co)->parent) +#define coord_get_flags(co, _flags) ((co)->flags & (_flags)) +#define coord_clear_flags(co, _flags) \ + do { (co)->flags &= ~(_flags); } while(0) + +#define coord_get_pcache_area(coord) ((coord)->canvas_info->pcache_cur_area) +#define coord_get_pcache_last_area(coord) \ + ((coord)->canvas_info->pcache_last_area) +#define coord_get_cached(coord) ((coord)->canvas_info->owner) +#define _coord_get_dirty_areas(coord) (&(coord)->canvas_info->dirty_areas) +#define _coord_get_aggr_dirty_areas(coord) \ + ((coord)->canvas_info->aggr_dirty_areas) +#define coord_get_2pdev(coord) ((coord)->canvas_info->cache_2_pdev) +#define coord_get_2pdev_rev(coord) ((coord)->canvas_info->cache_2_pdev_rev) +#define coord_get_aggr2pdev(coord) ((coord)->canvas_info->aggr_2_pdev) +#define coord_get_aggr2pdev_rev(coord) ((coord)->canvas_info->aggr_2_pdev_rev) + + /* NOTE: bounding box should also consider width of stroke. */ @@ -336,12 +370,14 @@ extern void sh_dummy_fill(shape_t *, mbe_t *); #endif /* UNITTEST */ -static subject_t *ob_subject_alloc(ob_factory_t *factory); -static void ob_subject_free(ob_factory_t *factory, subject_t *subject); -static observer_t *ob_observer_alloc(ob_factory_t *factory); -static void ob_observer_free(ob_factory_t *factory, observer_t *observer); -static subject_t *ob_get_parent_subject(ob_factory_t *factory, - subject_t *cur_subject); +static subject_t *observer_subject_alloc(observer_factory_t *factory); +static void observer_subject_free(observer_factory_t *factory, + subject_t *subject); +static observer_t *observer_observer_alloc(observer_factory_t *factory); +static void observer_observer_free(observer_factory_t *factory, + observer_t *observer); +static subject_t *observer_get_parent_subject(observer_factory_t *factory, + subject_t *cur_subject); /* Functions for children. */ #define FORCHILDREN(coord, child) \ for((child) = STAILQ_HEAD((coord)->children); \ @@ -456,10 +492,10 @@ static int add_dirty_area(redraw_man_t *rdman, coord_t *coord, area_t *area) { int r; - + if(area->w < 0.01 || area->h < 0.01) return OK; - + rdman->n_dirty_areas++; r = areas_add(_coord_get_dirty_areas(coord), area); return r == 0? OK: ERR; @@ -472,8 +508,10 @@ } static int add_dirty_pcache_area_coord(redraw_man_t *rdman, coord_t *coord) { - coord_set_flags(coord, COF_DIRTY_PCACHE_AREA); - ADD_DATA(coords, dirty_pcache_area_coords, coord); + if(!coord_get_flags(coord, COF_DIRTY_PCACHE_AREA)) { + coord_set_flags(coord, COF_DIRTY_PCACHE_AREA); + ADD_DATA(coords, zeroing_coords, coord); + } return OK; } @@ -515,26 +553,41 @@ free(rdman->free_objs.objs); } - +#ifdef UNITTEST +/*! \brief This is only used for unittest. + */ +typedef struct { + co_aix parent_2_cache[6]; + int w, h; +} mock_mbe_t; +#endif static mbe_t *canvas_new(int w, int h) { #ifndef UNITTEST mbe_surface_t *surface; mbe_t *cr; - + surface = mbe_image_surface_create(MB_IFMT_ARGB32, w, h); cr = mbe_create(surface); return cr; #else - return NULL; + mock_mbe_t *mbe; + + mbe = malloc(sizeof(mock_mbe_t)); + mbe->w = w; + mbe->h = h; + + return (mbe_t *)mbe; #endif } static void canvas_free(mbe_t *canvas) { #ifndef UNITTEST mbe_destroy(canvas); +#else + free(canvas); #endif } @@ -546,8 +599,11 @@ *w = mbe_image_surface_get_width(surface); *h = mbe_image_surface_get_height(surface); #else - *w = 0; - *h = 0; + mock_mbe_t *mbe; + + mbe = (mock_mbe_t *)canvas; + *w = mbe->w; + *h = mbe->h; #endif } @@ -584,22 +640,29 @@ coord->num_members--; } -static coord_canvas_info_t *coord_canvas_info_new(redraw_man_t *rdman, - coord_t *coord, - mbe_t *canvas) { +/*! \brief Create a new canvas and respective info struct for a coord. + */ +static coord_canvas_info_t * +coord_canvas_info_new(redraw_man_t *rdman, coord_t *coord, + mbe_t *canvas) { coord_canvas_info_t *info; + static co_aix id[6] = {1, 0, 0, 0, 1, 0}; info = (coord_canvas_info_t *)elmpool_elm_alloc(rdman->coord_canvas_pool); if(info == NULL) return info; - + info->owner = coord; info->canvas = canvas; DARRAY_INIT(&info->dirty_areas); - + bzero(info->pcache_areas, sizeof(area_t) * 2); info->pcache_cur_area = &info->pcache_areas[0]; info->pcache_last_area = &info->pcache_areas[1]; + memcpy(info->cache_2_pdev, id, sizeof(co_aix) * 6); + memcpy(info->cache_2_pdev_rev, id, sizeof(co_aix) * 6); + memcpy(info->aggr_2_pdev, id, sizeof(co_aix) * 6); + memcpy(info->aggr_2_pdev_rev, id, sizeof(co_aix) * 6); return info; } @@ -615,24 +678,33 @@ int redraw_man_init(redraw_man_t *rdman, mbe_t *cr, mbe_t *backend) { extern void redraw_man_destroy(redraw_man_t *rdman); + extern int _sh_path_size; + extern int _sh_rect_size; extern int _paint_color_size; + extern int _paint_linear_size; + extern int _paint_radial_size; + extern int _paint_image_size; observer_t *addrm_ob; extern void addrm_monitor_hdlr(event_t *evt, void *arg); memset(rdman, 0, sizeof(redraw_man_t)); DARRAY_INIT(&rdman->dirty_coords); - DARRAY_INIT(&rdman->dirty_pcache_area_coords); DARRAY_INIT(&rdman->dirty_geos); DARRAY_INIT(&rdman->gen_geos); DARRAY_INIT(&rdman->zeroing_coords); - + rdman->geo_pool = elmpool_new(sizeof(geo_t), 128); rdman->coord_pool = elmpool_new(sizeof(coord_t), 16); rdman->shnode_pool = elmpool_new(sizeof(shnode_t), 16); + rdman->sh_path_pool = elmpool_new(_sh_path_size, 16); + rdman->sh_rect_pool = elmpool_new(_sh_rect_size, 16); rdman->observer_pool = elmpool_new(sizeof(observer_t), 32); rdman->subject_pool = elmpool_new(sizeof(subject_t), 32); rdman->paint_color_pool = elmpool_new(_paint_color_size, 64); + rdman->paint_linear_pool = elmpool_new(_paint_linear_size, 64); + rdman->paint_radial_pool = elmpool_new(_paint_radial_size, 64); + rdman->paint_image_pool = elmpool_new(_paint_image_size, 64); rdman->pent_pool = elmpool_new(sizeof(mb_prop_entry_t), 128); rdman->coord_canvas_pool = elmpool_new(sizeof(coord_canvas_info_t), 16); if(!(rdman->geo_pool && rdman->coord_pool && rdman->shnode_pool && @@ -640,16 +712,16 @@ rdman->paint_color_pool && rdman->coord_canvas_pool)) goto err; - rdman->ob_factory.subject_alloc = ob_subject_alloc; - rdman->ob_factory.subject_free = ob_subject_free; - rdman->ob_factory.observer_alloc = ob_observer_alloc; - rdman->ob_factory.observer_free = ob_observer_free; - rdman->ob_factory.get_parent_subject = ob_get_parent_subject; + rdman->observer_factory.subject_alloc = observer_subject_alloc; + rdman->observer_factory.subject_free = observer_subject_free; + rdman->observer_factory.observer_alloc = observer_observer_alloc; + rdman->observer_factory.observer_free = observer_observer_free; + rdman->observer_factory.get_parent_subject = observer_get_parent_subject; rdman->redraw = - subject_new(&rdman->ob_factory, rdman, OBJT_RDMAN); + subject_new(&rdman->observer_factory, rdman, OBJT_RDMAN); rdman->addrm_monitor = - subject_new(&rdman->ob_factory, rdman, OBJT_RDMAN); + subject_new(&rdman->observer_factory, rdman, OBJT_RDMAN); if(!(rdman->redraw && rdman->addrm_monitor)) goto err; @@ -666,7 +738,7 @@ rdman->n_coords = 1; coord_init(rdman->root_coord, NULL); mb_prop_store_init(&rdman->root_coord->obj.props, rdman->pent_pool); - rdman->root_coord->mouse_event = subject_new(&rdman->ob_factory, + rdman->root_coord->mouse_event = subject_new(&rdman->observer_factory, rdman->root_coord, OBJT_COORD); coord_set_flags(rdman->root_coord, COF_OWN_CANVAS); @@ -678,7 +750,7 @@ rdman->backend = backend; STAILQ_INIT(rdman->shapes); - + /* \note To make root coord always have at leat one observer. * It triggers mouse interpreter to be installed on root. */ @@ -697,18 +769,27 @@ elmpool_free(rdman->coord_pool); if(rdman->shnode_pool) elmpool_free(rdman->shnode_pool); + if(rdman->sh_path_pool) + elmpool_free(rdman->sh_path_pool); + if(rdman->sh_rect_pool) + elmpool_free(rdman->sh_rect_pool); if(rdman->observer_pool) elmpool_free(rdman->observer_pool); if(rdman->subject_pool) elmpool_free(rdman->subject_pool); if(rdman->paint_color_pool) elmpool_free(rdman->paint_color_pool); + if(rdman->paint_linear_pool) + elmpool_free(rdman->paint_linear_pool); + if(rdman->paint_radial_pool) + elmpool_free(rdman->paint_radial_pool); + if(rdman->paint_image_pool) + elmpool_free(rdman->paint_image_pool); if(rdman->pent_pool) elmpool_free(rdman->pent_pool); if(rdman->coord_canvas_pool) elmpool_free(rdman->coord_canvas_pool); DARRAY_DESTROY(&rdman->dirty_coords); - DARRAY_DESTROY(&rdman->dirty_pcache_area_coords); DARRAY_DESTROY(&rdman->dirty_geos); DARRAY_DESTROY(&rdman->gen_geos); DARRAY_DESTROY(&rdman->zeroing_coords); @@ -717,7 +798,7 @@ void redraw_man_destroy(redraw_man_t *rdman) { coord_t *coord, *saved_coord; - shape_t *shape, *saved_shape; + shape_t *shape; geo_t *member; mb_prop_store_destroy(&rdman->props); @@ -729,7 +810,6 @@ * successfully. */ DARRAY_CLEAN(&rdman->dirty_coords); - DARRAY_CLEAN(&rdman->dirty_pcache_area_coords); DARRAY_CLEAN(&rdman->dirty_geos); coord = postorder_coord_subtree(rdman->root_coord, NULL); @@ -748,24 +828,28 @@ while((shape = STAILQ_HEAD(rdman->shapes)) != NULL) { rdman_shape_free(rdman, shape); } - + coord_canvas_info_free(rdman, rdman->root_coord->canvas_info); /* XXX: paints are not freed, here. All resources of paints would * be reclaimed by freeing elmpools. */ - + elmpool_free(rdman->coord_pool); elmpool_free(rdman->geo_pool); elmpool_free(rdman->shnode_pool); + elmpool_free(rdman->sh_path_pool); + elmpool_free(rdman->sh_rect_pool); elmpool_free(rdman->observer_pool); elmpool_free(rdman->subject_pool); elmpool_free(rdman->paint_color_pool); + elmpool_free(rdman->paint_linear_pool); + elmpool_free(rdman->paint_radial_pool); + elmpool_free(rdman->paint_image_pool); elmpool_free(rdman->pent_pool); elmpool_free(rdman->coord_canvas_pool); DARRAY_DESTROY(&rdman->dirty_coords); - DARRAY_DESTROY(&rdman->dirty_pcache_area_coords); DARRAY_DESTROY(&rdman->dirty_geos); DARRAY_DESTROY(&rdman->gen_geos); DARRAY_DESTROY(&rdman->zeroing_coords); @@ -802,9 +886,9 @@ geo = elmpool_elm_alloc(rdman->geo_pool); if(geo == NULL) return ERR; - + geo_init(geo); - geo->mouse_event = subject_new(&rdman->ob_factory, geo, OBJT_GEO); + geo->mouse_event = subject_new(&rdman->observer_factory, geo, OBJT_GEO); subject_set_monitor(geo->mouse_event, rdman->addrm_monitor); geo_attach_coord(geo, coord); @@ -854,7 +938,7 @@ rdman_paint_stroke(rdman, (paint_t *)NULL, shape); if(shape->fill != NULL) rdman_paint_fill(rdman, (paint_t *)NULL, shape); - + if(geo != NULL) { subject_free(geo->mouse_event); geo_detach_coord(geo, shape->coord); @@ -869,7 +953,7 @@ if(rdman->last_mouse_over == (mb_obj_t *)shape) rdman->last_mouse_over = NULL; - + return OK; } @@ -889,7 +973,7 @@ shape_t *shape; if(rdman_is_dirty(rdman)) { - if(!(paint->flags & PNTF_FREE)) + if(paint->flags & PNTF_FREE) return ERR; add_free_obj(rdman, paint, (free_func_t)rdman_paint_free); paint->flags |= PNTF_FREE; @@ -901,26 +985,26 @@ FORPAINTMEMBERS(paint, shnode) { if(saved_shnode) { RM_PAINTMEMBER(paint, saved_shnode); - + shape = saved_shnode->shape; if(shape->stroke == paint) rdman_paint_stroke(rdman, (paint_t *)NULL, shape); if(shape->fill == paint) rdman_paint_fill(rdman, (paint_t *)NULL, shape); - + shnode_free(rdman, saved_shnode); } saved_shnode = shnode; } if(saved_shnode) { RM_PAINTMEMBER(paint, saved_shnode); - + shape = saved_shnode->shape; if(shape->stroke == paint) rdman_paint_stroke(rdman, (paint_t *)NULL, shape); if(shape->fill == paint) rdman_paint_fill(rdman, (paint_t *)NULL, shape); - + shnode_free(rdman, saved_shnode); } @@ -952,7 +1036,7 @@ coord_init(coord, parent); mb_prop_store_init(&coord->obj.props, rdman->pent_pool); - coord->mouse_event = subject_new(&rdman->ob_factory, + coord->mouse_event = subject_new(&rdman->observer_factory, coord, OBJT_COORD); subject_set_monitor(coord->mouse_event, rdman->addrm_monitor); @@ -988,7 +1072,7 @@ if(coord->flags & COF_FREE) return ERR; - + coord->flags |= COF_FREE; coord_hide(coord); if(!(coord->flags & COF_DIRTY)) { @@ -1033,7 +1117,7 @@ if(!(member->flags & GEF_FREE)) return ERR; } - + if(cm_cnt || rdman_is_dirty(rdman)) return rdman_coord_free_postponse(rdman, coord); @@ -1226,10 +1310,11 @@ } shape->geo->flags &= ~GEF_DIRTY; - if(is_coord_subtree_hidden(shape->coord)) - sh_hide(shape); + if(sh_get_flags(shape, GEF_HIDDEN) || + is_coord_subtree_hidden(shape->coord)) + sh_set_flags(shape, GEF_NOT_SHOWED); else - sh_show(shape); + sh_clear_flags(shape, GEF_NOT_SHOWED); } /*! \brief Setup canvas_info for the coord. @@ -1242,7 +1327,7 @@ if(coord->parent == NULL) return; - if(coord->opacity != 1 || coord_is_cached(coord)) { + if(coord->opacity != 1 || coord_is_always_cached(coord)) { if(!coord_is_cached(coord)) { /* canvas is assigned latter, in zeroing_coord() */ coord->canvas_info = coord_canvas_info_new(rdman, coord, NULL); @@ -1264,8 +1349,8 @@ /* \brief Compute matrix from cached canvas to parent device space. */ -static void compute_cached_2_pdev_matrix(coord_t *coord, - co_aix canvas2pdev_matrix[6]) { +static void compute_cached_2_pdev_matrix(coord_t *coord) { + co_aix *canvas2pdev_matrix = coord_get_2pdev(coord); coord_t *parent; co_aix *aggr; co_aix *matrix, *paggr; @@ -1277,9 +1362,9 @@ matrix = coord->matrix; parent = coord->parent; paggr = coord_get_aggr_matrix(parent); - + scale_x = matrix[0] / aggr[0]; - scale_y = matrix[3] / aggr[3]; + scale_y = matrix[4] / aggr[4]; shift_x = matrix[2] - scale_x * aggr[2]; shift_y = matrix[5] - scale_y * aggr[5]; @@ -1291,6 +1376,8 @@ canvas2p[5] = shift_y; matrix_mul(paggr, canvas2p, canvas2pdev_matrix); + + compute_reverse(canvas2pdev_matrix, coord_get_2pdev_rev(coord)); } /*! \brief Compute area in parent cached coord for a cached coord. @@ -1303,22 +1390,21 @@ * ancestral cached coord can be retreived by shifting and resizing * canvas box in reverse and transform to coordination system of * ancestral cached coord. - */ + */ static void compute_pcache_area(coord_t *coord) { - co_aix cached2pdev[6]; + co_aix *cached2pdev = coord_get_2pdev(coord); int c_w, c_h; canvas_t *canvas; coord_canvas_info_t *canvas_info; co_aix poses[4][2]; - + canvas_info = coord->canvas_info; SWAP(canvas_info->pcache_cur_area, canvas_info->pcache_last_area, area_t *); - compute_cached_2_pdev_matrix(coord, cached2pdev); - + canvas = _coord_get_canvas(coord); canvas_get_size(canvas, &c_w, &c_h); - + poses[0][0] = 0; poses[0][1] = 0; poses[1][0] = c_w; @@ -1331,28 +1417,29 @@ matrix_trans_pos(cached2pdev, &poses[1][0], &poses[1][1]); matrix_trans_pos(cached2pdev, &poses[2][0], &poses[2][1]); matrix_trans_pos(cached2pdev, &poses[3][0], &poses[3][1]); - + area_init(coord_get_pcache_area(coord), 4, poses); - coord_set_flags(coord, COF_DIRTY_PCACHE_AREA); + coord_clear_flags(coord, COF_DIRTY_PCACHE_AREA); } /*! \brief Compute area of a coord. */ static int compute_area(coord_t *coord) { - static co_aix (*poses)[2]; + static co_aix (*poses)[2] = NULL; static int max_poses = 0; geo_t *geo; int cnt, pos_cnt; - + cnt = 0; FORMEMBERS(coord, geo) { cnt++; } - + if(max_poses < (cnt * 2)) { - free(poses); + if(poses) + free(poses); max_poses = cnt * 2; poses = (co_aix (*)[2])malloc(sizeof(co_aix [2]) * max_poses); if(poses == NULL) @@ -1374,7 +1461,7 @@ geo_t *geo; int r; /*! \note poses is shared by invokings, it is not support reentrying. */ - + /* Clean member shapes. */ FORMEMBERS(coord, geo) { clean_shape(geo->shape); @@ -1396,9 +1483,8 @@ * \note coords their opacity != 1 are also traded as cached ones. */ static int clean_coord(redraw_man_t *rdman, coord_t *coord) { - coord_t *child; int r; - + setup_canvas_info(rdman, coord); compute_aggr(coord); @@ -1412,17 +1498,14 @@ if(r != OK) return ERR; + /* Dirty areas of cached one is added after update pcache_areas. + */ add_dirty_area(rdman, coord, coord->cur_area); add_dirty_area(rdman, coord, coord->last_area); - + coord_clear_flags(coord, COF_DIRTY); coord_set_flags(coord, COF_JUST_CLEAN); - - FORCHILDREN(coord, child) { - if(coord_is_cached(child)) - add_dirty_pcache_area_coord(rdman, child); - } - + return OK; } @@ -1434,7 +1517,7 @@ * coord, coord_canvas_info_t::pcache_cur_area, for its cached children. */ static int clean_rdman_coords(redraw_man_t *rdman) { - coord_t *coord, *child; + coord_t *coord; coord_t **dirty_coords; int n_dirty_coords; int i, r; @@ -1476,7 +1559,7 @@ add_dirty_area(rdman, coord, visit_geo->cur_area); add_dirty_area(rdman, coord, visit_geo->last_area); } - } + } return OK; } @@ -1489,7 +1572,7 @@ static void zeroing_coord(redraw_man_t *rdman, coord_t *coord) { coord_t *cur; - area_t *area, *saved_area; + area_t *area; geo_t *geo; co_aix min_x, min_y; co_aix max_x, max_y; @@ -1498,7 +1581,6 @@ int c_w, c_h; mbe_t *canvas; co_aix *aggr; - co_aix poses[4][2]; if(coord->parent == NULL) /*! \note Should not zeroing root coord */ abort(); @@ -1519,26 +1601,44 @@ for(cur = preorder_coord_subtree(coord, coord); cur != NULL; cur = preorder_coord_subtree(coord, cur)) { - area = coord_get_area(cur); + if(coord_is_cached(cur)) { + preorder_coord_skip_subtree(cur); + /* This means pcache_area of descendants must be computed + * before zeroing ancestor cached one. + * (See add_rdman_zeroing_n_pcache_coords()) + */ + area = coord_get_pcache_area(cur); + } else + area = coord_get_area(cur); + + if(area->w == 0 && area->h == 0) + continue; + + if(min_x == max_x && min_y == max_y) { + min_x = area->x; + max_x = area->x + area->w; + min_y = area->y; + max_y = area->y + area->h; + continue; + } + if(area->x < min_x) min_x = area->x; if(area->y < min_y) min_y = area->y; - + x = area->x + area->w; y = area->y + area->h; - + if(x > max_x) max_x = x; if(y > max_y) max_y = y; - if(coord_is_cached(cur)) - preorder_coord_skip_subtree(cur); } w = max_x - min_x; h = max_y - min_y; - + canvas = _coord_get_canvas(coord); if(canvas) canvas_get_size(canvas, &c_w, &c_h); @@ -1560,7 +1660,7 @@ coord_set_flags(coord, COF_SKIP_ZERO); return; } - + /* * Adjust matrics of descendants to align left-top corner of * minimum covering area with origin of space defined by @@ -1577,9 +1677,9 @@ } /* Shift space */ aggr = coord_get_aggr_matrix(cur); - aggr[3] -= min_x; + aggr[2] -= min_x; aggr[5] -= min_y; - + FOR_COORD_MEMBERS(coord, geo) { /* \see GEO_SWAP() */ if(!geo_get_flags(geo, GEF_SWAP)) @@ -1587,7 +1687,7 @@ } coord_clean_members_n_compute_area(cur); } - + /* * Setup canvas * @@ -1604,16 +1704,29 @@ coord_set_flags(coord, COF_JUST_ZERO); } -/*! \brief Add canvas owner of dirty geos to redraw_man_t::zeroing_coords. +/*! \brief Add coords that need to perform zeroing or re-compute pcache_area. + * + * A coord that need to perform zeroing has one or more dirty members + * in its descendants. * - * All possible coords that need a zeroing have at least one dirty geo. + * To zeroing a coord, pcache_area of first level cached descendants + * must be updated. To update the pcache_area of a cached coord, the + * cached coord also need to perform zeroing. So, zeroing and + * re-computing pcache_area are interleaved. + * + * The pcache_area of a cached coord must be re-computed if its + * parent/ancestors is dirty/just cleaned, or it must be zeroed. It + * means cached coord with jsut cleaned parent should also re-compute + * pcache_area. So, this function also check and add coords for this + * situation. */ -static int add_rdman_zeroing_coords(redraw_man_t *rdman) { +static int add_rdman_zeroing_n_pcache_coords(redraw_man_t *rdman) { int i; int n_dirty_geos; geo_t **dirty_geos, *geo; int n_dirty_coords; coord_t **dirty_coords, *coord; + coord_t *parent_coord; /* Mark all cached ancestral coords of dirty geos */ n_dirty_geos = rdman->dirty_geos.num; @@ -1628,7 +1741,7 @@ coord = coord_get_cached(coord_get_parent(coord)); } } - + /* Mark all cached ancestral coords of dirty coords */ n_dirty_coords = rdman->dirty_coords.num; dirty_coords = rdman->dirty_coords.ds; @@ -1641,23 +1754,28 @@ coord = coord_get_cached(coord_get_parent(coord)); } } - + /* Add all marked coords into redraw_man_t::zeroing_coords list */ FOR_COORDS_PREORDER(rdman->root_coord, coord) { - if(!coord_is_cached(coord)) + if(!coord_is_cached(coord) || coord_is_root(coord)) continue; /* skip coords that is not cached */ - + if(!coord_get_flags(coord, COF_TEMP_MARK)) { - if(coord_get_flags(coord, COF_DIRTY_PCACHE_AREA)) + parent_coord = coord_get_parent(coord); + /* The pcache_area of a cached coord that is a child of a + * just cleaned one must be recomputed. + */ + if(coord_get_flags(parent_coord, COF_JUST_CLEAN)) add_dirty_pcache_area_coord(rdman, coord); + preorder_coord_skip_subtree(coord); continue; } add_zeroing_coord(rdman, coord); - + coord_clear_flags(coord, COF_TEMP_MARK); } - + return OK; } @@ -1671,7 +1789,7 @@ int i; coords_t *all_zeroing; coord_t *coord; - + all_zeroing = &rdman->zeroing_coords; /*! Zeroing is performed from leaves to root. * @@ -1686,34 +1804,43 @@ */ for(i = all_zeroing->num - 1; i >= 0; i--) { coord = all_zeroing->ds[i]; - zeroing_coord(rdman, coord); + if(coord_is_zeroing(coord)) + zeroing_coord(rdman, coord); + compute_cached_2_pdev_matrix(coord); + /* This is required by ancester cached ones to perform + * zeroing. + */ compute_pcache_area(coord); } - + return OK; } -/*! \brief Compute pcache_area for coords whoes pcache_area is dirty. +/*! \brief Update aggregated cache_2_pdev matrix for cached coords. * - * coord_t::dirty_pcache_area_coords also includes part of coords in - * coord_t::zeroing_coords. The pcache_area of coords that is in - * coord_t::dirty_pcache_area_coords, but is not in - * coord_t::zeroing_coords should be computed here. - * zeroing_rdman_coords() is responsible for computing pcache_area for - * zeroing ones. + * This is perfromed from root to leaves. Aggregated cache_2_pdev is + * named as aggr_2_pdev field of canvas_info_t. It is the matrix to + * transform a point from space of a cached coord to the space of root + * coord. */ static int -compute_rdman_coords_pcache_area(redraw_man_t *rdman) { - coords_t *all_coords; - coord_t *coord; +update_aggr_pdev(redraw_man_t *rdman) { int i; - - all_coords = &rdman->dirty_pcache_area_coords; - for(i = 0; i < all_coords->num; i++) { - coord = all_coords->ds[i]; - if(coord_get_flags(coord, COF_DIRTY_PCACHE_AREA)) - compute_pcache_area(coord); + coords_t *all_zeroing; + coord_t *coord, *parent_cached; + + all_zeroing = &rdman->zeroing_coords; + for(i = 0; i < all_zeroing->num; i++) { + coord = all_zeroing->ds[i]; + parent_cached = coord_get_cached(coord_get_parent(coord)); + matrix_mul(coord_get_2pdev(parent_cached), + coord_get_2pdev(coord), + coord_get_aggr2pdev(coord)); + matrix_mul(coord_get_2pdev_rev(coord), + coord_get_2pdev_rev(parent_cached), + coord_get_aggr2pdev_rev(coord)); } + return OK; } @@ -1727,19 +1854,31 @@ coord_t *coord) { int i; int n_areas; - int enable_poses1 = 0; co_aix poses0[2][2], poses1[2][2]; - co_aix reverse[6]; - co_aix canvas2pdev_matrix[6]; + co_aix *canvas2pdev_matrix; area_t **areas, *area; area_t *area0, *area1; coord_t *parent, *pcached_coord; n_areas = _coord_get_dirty_areas(coord)->num; areas = _coord_get_dirty_areas(coord)->ds; - if(n_areas == 0) - abort(); /* should not happen! */ - + if(n_areas == 0) { + /* Go here for cached one that is descendant of another zeroed + * one, but itself is not zeroed. It is here for recomputing + * pcache areas. + */ + if(coord_get_flags(coord, COF_JUST_CLEAN | COF_JUST_ZERO)) + abort(); /* should not happen! */ + + parent = coord_get_parent(coord); + pcached_coord = coord_get_cached(parent); + area = coord_get_pcache_area(coord); + add_dirty_area(rdman, pcached_coord, area); + area = coord_get_pcache_last_area(coord); + add_dirty_area(rdman, pcached_coord, area); + return; + } + area0 = _coord_get_aggr_dirty_areas(coord); area1 = area0 + 1; @@ -1755,13 +1894,13 @@ if(i >= n_areas) return; - + area = areas[i++]; poses0[0][0] = area->x; poses0[0][1] = area->y; poses0[1][0] = area->x + area->w; poses0[1][1] = area->y + area->h; - + if(i < n_areas) { area = areas[i++]; poses1[0][0] = area->x; @@ -1774,7 +1913,7 @@ poses1[1][0] = 0; poses1[1][1] = 0; } - + for(; i < n_areas - 1;) { /* Even areas */ area = areas[i++]; @@ -1793,7 +1932,7 @@ poses1[1][1] = MB_MAX(poses1[1][1], area->y + area->h); } } - + if(i < n_areas) { area = areas[i]; if(area->w != 0 || area->h != 0) { @@ -1803,18 +1942,18 @@ poses0[1][1] = MB_MAX(poses0[1][1], area->y + area->h); } } - + parent = coord_get_parent(coord); pcached_coord = coord_get_cached(parent); - - compute_cached_2_pdev_matrix(coord, canvas2pdev_matrix); + + canvas2pdev_matrix = coord_get_2pdev(coord); /* Add dirty areas to parent cached coord. */ matrix_trans_pos(canvas2pdev_matrix, poses0[0], poses0[0] + 1); matrix_trans_pos(canvas2pdev_matrix, poses0[1], poses0[1] + 1); area_init(area0, 2, poses0); add_dirty_area(rdman, pcached_coord, area0); - + matrix_trans_pos(canvas2pdev_matrix, poses1[0], poses1[0] + 1); matrix_trans_pos(canvas2pdev_matrix, poses1[1], poses1[1] + 1); area_init(area1, 2, poses1); @@ -1840,29 +1979,18 @@ */ static int add_rdman_aggr_dirty_areas(redraw_man_t *rdman) { int i; - int n_zeroing; - coord_t **zeroings; - coord_t *coord, *pcached_coord; - int n_dpca_coords; /* number of dirty pcache area coords */ - coord_t **dpca_coords; /* dirty pcache area coords */ - - /* Add aggregated areas to parent cached one for coords in zeroing - * list - */ - n_zeroing = rdman->zeroing_coords.num; - zeroings = rdman->zeroing_coords.ds; - for(i = 0; i < n_zeroing; i++) { - if(coord_get_flags(coord, COF_TEMP_MARK)) - continue; - coord_set_flags(coord, COF_TEMP_MARK); - - coord = zeroings[i]; - pcached_coord = coord_get_cached(coord_get_parent(coord)); - - if(coord_is_root(coord) || IS_CACHE_REDRAW_ALL(pcached_coord)) - continue; - + coord_t *coord, *parent_coord, *pcached_coord; + int n_zeroing_coords; /* number of dirty pcache area coords */ + coord_t **zeroing_coords; /* dirty pcache area coords */ + + n_zeroing_coords = rdman->zeroing_coords.num; + zeroing_coords = rdman->zeroing_coords.ds; + for(i = n_zeroing_coords - 1; i >= 0; i--) { + coord = zeroing_coords[i]; if(IS_CACHE_REDRAW_ALL(coord)) { + parent_coord = coord_get_parent(coord); + pcached_coord = coord_get_cached(parent_coord); + add_dirty_area(rdman, pcached_coord, coord_get_pcache_area(coord)); add_dirty_area(rdman, pcached_coord, @@ -1871,36 +1999,6 @@ add_aggr_dirty_areas_to_ancestor(rdman, coord); } } - - /* Add pcache_areas to parent cached one for coord that is - * non-zeroing and its parent is changed. - */ - n_dpca_coords = rdman->dirty_pcache_area_coords.num; - dpca_coords = rdman->dirty_pcache_area_coords.ds; - for(i = 0; i < n_dpca_coords; i++) { - if(coord_get_flags(coord, COF_TEMP_MARK)) - continue; - coord_set_flags(coord, COF_TEMP_MARK); - - coord = dpca_coords[i]; - pcached_coord = coord_get_cached(coord_get_parent(coord)); - - if(coord_is_root(coord) || IS_CACHE_REDRAW_ALL(pcached_coord)) - continue; - - add_dirty_area(rdman, pcached_coord, - coord_get_pcache_area(coord)); - add_dirty_area(rdman, pcached_coord, - coord_get_pcache_last_area(coord)); - } - - /* Remove temporary mark */ - for(i = 0; i < n_zeroing; i++) { - coord_clear_flags(zeroings[i], COF_TEMP_MARK); - } - for(i = 0; i < n_dpca_coords; i++) { - coord_clear_flags(dpca_coords[i], COF_TEMP_MARK); - } return OK; } @@ -1981,13 +2079,15 @@ GEO_SWAP(geo); } } - + + /* XXX: some geo may swap two times. Should avoid it. + */ geos = rdman->dirty_geos.ds; for(i = 0; i < rdman->dirty_geos.num; i++) { geo = geos[i]; GEO_SWAP(geo); } - + r = clean_rdman_coords(rdman); if(r != OK) return ERR; @@ -2003,7 +2103,7 @@ /* Zeroing must be performed after clearing to get latest position * of shapes for computing new bounding box */ - r = add_rdman_zeroing_coords(rdman); + r = add_rdman_zeroing_n_pcache_coords(rdman); if(r != OK) return ERR; @@ -2011,11 +2111,11 @@ if(r != OK) return ERR; - r = compute_rdman_coords_pcache_area(rdman); + r = add_rdman_aggr_dirty_areas(rdman); if(r != OK) return ERR; - - r = add_rdman_aggr_dirty_areas(rdman); + + r = update_aggr_pdev(rdman); if(r != OK) return ERR; @@ -2035,17 +2135,13 @@ for(i = 0; i < rdman->zeroing_coords.num; i++) coord_clear_flags(coords[i], COF_JUST_CLEAN | COF_JUST_ZERO | COF_SKIP_ZERO); - coords = rdman->dirty_pcache_area_coords.ds; - for(i = 0; i < rdman->dirty_pcache_area_coords.num; i++) - coord_clear_flags(coords[i], - COF_JUST_CLEAN | COF_JUST_ZERO | COF_SKIP_ZERO); /* \see GEO_SWAP() */ for(i = 0; i < rdman->dirty_geos.num; i++) { geo = geos[i]; geo_clear_flags(geo, GEF_SWAP); } - + return OK; } @@ -2059,28 +2155,28 @@ mbe_set_line_width(cr, shape->stroke_width); } -static void fill_path_preserve(redraw_man_t *rdman) { - mbe_fill_preserve(rdman->cr); +static void fill_path_preserve(redraw_man_t *rdman, mbe_t *cr) { + mbe_fill_preserve(cr); } -static void fill_path(redraw_man_t *rdman) { - mbe_fill(rdman->cr); +static void fill_path(redraw_man_t *rdman, mbe_t *cr) { + mbe_fill(cr); } -static void stroke_path(redraw_man_t *rdman) { - mbe_stroke(rdman->cr); +static void stroke_path(redraw_man_t *rdman, mbe_t *cr) { + mbe_stroke(cr); } #else static void set_shape_stroke_param(shape_t *shape, mbe_t *cr) { } -static void fill_path_preserve(redraw_man_t *rdman) { +static void fill_path_preserve(redraw_man_t *rdman, mbe_t *cr) { } -static void fill_path(redraw_man_t *rdman) { +static void fill_path(redraw_man_t *rdman, mbe_t *cr) { } -static void stroke_path(redraw_man_t *rdman) { +static void stroke_path(redraw_man_t *rdman, mbe_t *cr) { } #endif @@ -2120,20 +2216,20 @@ fill = shape->fill; if(shape->fill) { - fill->prepare(fill, cr); + fill->prepare(fill, cr, shape); if(shape->stroke) - fill_path_preserve(rdman); + fill_path_preserve(rdman, cr); else - fill_path(rdman); + fill_path(rdman, cr); } stroke = shape->stroke; if(stroke) { - stroke->prepare(stroke, cr); + stroke->prepare(stroke, cr, shape); set_shape_stroke_param(shape, cr); - stroke_path(rdman); + stroke_path(rdman, cr); } - } + } } #ifndef UNITTEST @@ -2141,22 +2237,36 @@ mbe_clear(canvas); } -#define make_clip(canvas, n_dirty_areas, dirty_areas) \ - mbe_scissoring(canvas, n_dirty_areas, dirty_areas) +static void make_clip(mbe_t *cr, int n_dirty_areas, + area_t **dirty_areas) { + int i; + area_t *area; + + mbe_new_path(cr); + for(i = 0; i < n_dirty_areas; i++) { + area = dirty_areas[i]; + if(area->w < 0.1 || area->h < 0.1) + continue; + mbe_rectangle(cr, area->x, area->y, area->w, area->h); + } + mbe_clip(cr); +} static void reset_clip(canvas_t *cr) { - mbe_reset_scissoring(cr); + mbe_reset_clip(cr); } static void copy_cr_2_backend(redraw_man_t *rdman, int n_dirty_areas, area_t **dirty_areas) { if(n_dirty_areas) make_clip(rdman->backend, n_dirty_areas, dirty_areas); - + mbe_copy_source(rdman->cr, rdman->backend); } #else /* UNITTEST */ -#define make_clip(canvas, n_dirty_areas, dirty_areas) +static void make_clip(mbe_t *cr, int n_dirty_areas, + area_t **dirty_areas) { +} static void clear_canvas(canvas_t *canvas) { } @@ -2169,27 +2279,39 @@ } #endif /* UNITTEST */ -static void update_cached_canvas_2_parent(redraw_man_t *rdman, - coord_t *coord) { - mbe_t *pcanvas, *canvas; +static void +_update_cached_canvas_2_parent(redraw_man_t *rdman, co_aix reverse[6], + mbe_t *canvas, mbe_t *pcanvas, + co_aix opacity) { mbe_surface_t *surface; mbe_pattern_t *pattern; - co_aix reverse[6]; - co_aix canvas2pdev_matrix[6]; - - if(coord_is_root(coord)) - return; - - compute_cached_2_pdev_matrix(coord, canvas2pdev_matrix); - compute_reverse(canvas2pdev_matrix, reverse); - canvas = _coord_get_canvas(coord); - pcanvas = _coord_get_canvas(coord->parent); surface = mbe_get_target(canvas); pattern = mbe_pattern_create_for_surface(surface); mbe_pattern_set_matrix(pattern, reverse); mbe_set_source(pcanvas, pattern); - mbe_paint_with_alpha(pcanvas, coord->opacity); + mbe_paint_with_alpha(pcanvas, opacity); +} + +static void update_cached_canvas_2_parent(redraw_man_t *rdman, + coord_t *coord) { + mbe_t *pcanvas, *canvas; + co_aix *c2pdev_reverse; + + if(coord_is_root(coord)) + return; + + c2pdev_reverse = coord_get_2pdev_rev(coord); + + canvas = _coord_get_canvas(coord); + pcanvas = _coord_get_canvas(coord->parent); +#ifndef UNITTEST + _update_cached_canvas_2_parent(rdman, c2pdev_reverse, canvas, pcanvas, + coord->opacity); +#else + memcpy(((mock_mbe_t *)canvas)->parent_2_cache, c2pdev_reverse, + sizeof(co_aix) * 6); +#endif } static int draw_coord_shapes_in_dirty_areas(redraw_man_t *rdman, @@ -2205,11 +2327,11 @@ if(coord->flags & COF_HIDDEN) return OK; - + areas = _coord_get_dirty_areas(coord)->ds; n_areas = _coord_get_dirty_areas(coord)->num; canvas = _coord_get_canvas(coord); - + member = FIRST_MEMBER(coord); mem_idx = 0; child = FIRST_CHILD(coord); @@ -2217,7 +2339,8 @@ if(child && child->before_pmem == mem_idx) { if(coord_is_cached(child)) { if(!(child->flags & COF_HIDDEN) && - is_area_in_areas(coord_get_area(child), n_areas, areas)) { + is_area_in_areas(coord_get_pcache_area(child), + n_areas, areas)) { update_cached_canvas_2_parent(rdman, child); dirty = 1; } @@ -2228,7 +2351,7 @@ child = NEXT_CHILD(child); } else { ASSERT(member != NULL); - if((!(member->flags & GEF_HIDDEN)) && + if((!(member->flags & GEF_NOT_SHOWED)) && is_geo_in_areas(member, n_areas, areas)) { draw_shape(rdman, canvas, member->shape); dirty = 1; @@ -2251,9 +2374,9 @@ mbe_surface_t *surface; int i; int r; - + canvas = _coord_get_canvas(coord); - + if(IS_CACHE_REDRAW_ALL(coord)) { /* * full_area covers all dirty areas of the cached coord. @@ -2269,7 +2392,7 @@ areas = _coord_get_dirty_areas(coord)->ds; n_areas = _coord_get_dirty_areas(coord)->num; - + for(i = 0; i < n_areas; i++) { area = areas[i]; area->x = floorf(area->x); @@ -2282,7 +2405,7 @@ clear_canvas(canvas); r = draw_coord_shapes_in_dirty_areas(rdman, coord); - + reset_clip(canvas); return OK; @@ -2306,8 +2429,10 @@ draw_dirty_cached_coord(rdman, coord); coord_set_flags(coord, COF_TEMP_MARK); } - for(i = 0; i < num; i++) + for(i = 0; i < num; i++) { + coord = zeroings[i]; coord_clear_flags(coord, COF_TEMP_MARK); + } draw_dirty_cached_coord(rdman, rdman->root_coord); } @@ -2350,10 +2475,10 @@ event_t event; subject_t *redraw; int i; - coord_t *coord, **coords; + coord_t *coord; int n_areas; area_t **areas; - + r = rdman_clean_dirties(rdman); if(r != OK) return ERR; @@ -2378,8 +2503,7 @@ DARRAY_CLEAN(&rdman->dirty_coords); DARRAY_CLEAN(&rdman->dirty_geos); DARRAY_CLEAN(&rdman->zeroing_coords); - DARRAY_CLEAN(&rdman->dirty_pcache_area_coords); - + /* Free postponsed removing */ free_free_objs(rdman); @@ -2441,7 +2565,7 @@ geo_t *rdman_geos(redraw_man_t *rdman, geo_t *last) { geo_t *next; coord_t *coord; - + if(last == NULL) { coord = rdman->root_coord; while(coord != NULL && FIRST_MEMBER(coord) == NULL) @@ -2497,48 +2621,51 @@ * Implment factory and strategy functions for observers and subjects. * @{ */ -static subject_t *ob_subject_alloc(ob_factory_t *factory) { +static subject_t *observer_subject_alloc(observer_factory_t *factory) { redraw_man_t *rdman; subject_t *subject; - rdman = MEM2OBJ(factory, redraw_man_t, ob_factory); + rdman = MEM2OBJ(factory, redraw_man_t, observer_factory); subject = elmpool_elm_alloc(rdman->subject_pool); return subject; } -static void ob_subject_free(ob_factory_t *factory, subject_t *subject) { +static void +observer_subject_free(observer_factory_t *factory, subject_t *subject) { redraw_man_t *rdman; - rdman = MEM2OBJ(factory, redraw_man_t, ob_factory); + rdman = MEM2OBJ(factory, redraw_man_t, observer_factory); elmpool_elm_free(rdman->subject_pool, subject); } -static observer_t *ob_observer_alloc(ob_factory_t *factory) { +static observer_t *observer_observer_alloc(observer_factory_t *factory) { redraw_man_t *rdman; observer_t *observer; - rdman = MEM2OBJ(factory, redraw_man_t, ob_factory); + rdman = MEM2OBJ(factory, redraw_man_t, observer_factory); observer = elmpool_elm_alloc(rdman->observer_pool); return observer; } -static void ob_observer_free(ob_factory_t *factory, observer_t *observer) { +static void +observer_observer_free(observer_factory_t *factory, observer_t *observer) { redraw_man_t *rdman; - rdman = MEM2OBJ(factory, redraw_man_t, ob_factory); + rdman = MEM2OBJ(factory, redraw_man_t, observer_factory); elmpool_elm_free(rdman->observer_pool, observer); } -static subject_t *ob_get_parent_subject(ob_factory_t *factory, - subject_t *cur_subject) { +static subject_t * +observer_get_parent_subject(observer_factory_t *factory, + subject_t *cur_subject) { redraw_man_t *rdman; coord_t *coord, *parent_coord; geo_t *geo; subject_t *parent; - rdman = MEM2OBJ(factory, redraw_man_t, ob_factory); + rdman = MEM2OBJ(factory, redraw_man_t, observer_factory); switch(cur_subject->obj_type) { case OBJT_GEO: geo = (geo_t *)cur_subject->obj; @@ -2570,15 +2697,15 @@ mb_img_data_t *img_data; paint_t *paint; mb_img_ldr_t *ldr = rdman_img_ldr(rdman); - + img_data = MB_IMG_LDR_LOAD(ldr, img_id); if(img_data == NULL) return NULL; - + paint = rdman_paint_image_new(rdman, img_data); if(paint == NULL) MB_IMG_DATA_FREE(img_data); - + return paint; } @@ -2593,6 +2720,7 @@ co_aix w, h; int trans_cnt; int draw_cnt; + mbe_t *last_draw; }; void sh_dummy_free(shape_t *sh) { @@ -2616,8 +2744,8 @@ dummy->trans_cnt = 0; dummy->draw_cnt = 0; dummy->shape.free = sh_dummy_free; - - rdman_shape_man(rdman, (shape_t *)dummy); + + rdman_man_shape(rdman, (shape_t *)dummy); return (shape_t *)dummy; } @@ -2626,7 +2754,7 @@ sh_dummy_t *dummy = (sh_dummy_t *)shape; co_aix poses[2][2]; co_aix x1, y1, x2, y2; - + if(shape->geo && shape->coord) { x1 = dummy->x; y1 = dummy->y; @@ -2639,7 +2767,7 @@ poses[0][1] = y1; poses[1][0] = x2; poses[1][1] = y2; - + if(shape->geo) geo_from_positions(shape->geo, 2, poses); } @@ -2651,6 +2779,7 @@ dummy = (sh_dummy_t *)shape; dummy->draw_cnt++; + dummy->last_draw = cr; } static void dummy_paint_prepare(paint_t *paint, mbe_t *cr) { @@ -2703,7 +2832,7 @@ CU_ASSERT(dummys[0]->draw_cnt == 1); CU_ASSERT(dummys[1]->draw_cnt == 1); CU_ASSERT(dummys[2]->draw_cnt == 1); - + coords[2]->matrix[2] = 100; coords[2]->matrix[5] = 100; rdman_coord_changed(rdman, coords[0]); @@ -2741,12 +2870,168 @@ CU_ASSERT(test_free_pass == 4); } +static void +test_setup_canvas_info(void) { + redraw_man_t *rdman; + redraw_man_t _rdman; + coord_t *coord; + + redraw_man_init(&_rdman, NULL, NULL); + rdman = &_rdman; + + coord = rdman_coord_new(rdman, rdman->root_coord); + CU_ASSERT(coord->parent == rdman->root_coord); + + coord_set_opacity(coord, 0.9); + setup_canvas_info(rdman, coord); + + CU_ASSERT(coord->canvas_info != rdman->root_coord->canvas_info); + + coord_set_opacity(coord, 1); + setup_canvas_info(rdman, coord); + + CU_ASSERT(coord->canvas_info == rdman->root_coord->canvas_info); +} + +static void +test_own_canvas_area(void) { + redraw_man_t *rdman; + redraw_man_t _rdman; + coord_t *coord1, *coord2; + sh_dummy_t *sh; + + redraw_man_init(&_rdman, NULL, NULL); + rdman = &_rdman; + + coord1 = rdman_coord_new(rdman, rdman->root_coord); + CU_ASSERT(coord1->parent == rdman->root_coord); + + coord2 = rdman_coord_new(rdman, coord1); + CU_ASSERT(coord2->parent == coord1); + + coord_set_opacity(coord2, 0.9); + rdman_coord_changed(rdman, coord2); + + sh = (sh_dummy_t *)sh_dummy_new(rdman, 100, 100, 20, 20); + rdman_add_shape(rdman, (shape_t *)sh, coord2); + rdman_shape_changed(rdman, (shape_t *)sh); + + clean_coord(rdman, coord2); + + /* Parent cached coord must be updated */ + CU_ASSERT(geo_get_area(coord2)->x == 100); + CU_ASSERT(geo_get_area(coord2)->y == 100); + CU_ASSERT(geo_get_area(coord2)->w <= 22 && geo_get_area(coord2)->w >= 19); + CU_ASSERT(geo_get_area(coord2)->h <= 22 && geo_get_area(coord2)->h >= 19); + + redraw_man_destroy(rdman); +} + +static void +test_own_canvas(void) { + redraw_man_t *rdman; + redraw_man_t _rdman; + coord_t *coord1, *coord2; + sh_dummy_t *sh; + + redraw_man_init(&_rdman, NULL, NULL); + rdman = &_rdman; + + coord1 = rdman_coord_new(rdman, rdman->root_coord); + CU_ASSERT(coord1->parent == rdman->root_coord); + + coord2 = rdman_coord_new(rdman, coord1); + CU_ASSERT(coord2->parent == coord1); + + coord_set_opacity(coord2, 0.9); + rdman_coord_changed(rdman, coord2); + + sh = (sh_dummy_t *)sh_dummy_new(rdman, 100, 100, 20, 20); + rdman_add_shape(rdman, (shape_t *)sh, coord2); + rdman_shape_changed(rdman, (shape_t *)sh); + + rdman_clean_dirties(rdman); + + /* Parent cached coord must be updated */ + CU_ASSERT(_coord_get_dirty_areas(rdman->root_coord)->num == 1); + + CU_ASSERT(geo_get_area(coord2)->x == 0); + CU_ASSERT(geo_get_area(coord2)->y == 0); + CU_ASSERT(geo_get_area(coord2)->w <= 22 && geo_get_area(coord2)->w >= 19); + CU_ASSERT(geo_get_area(coord2)->h <= 22 && geo_get_area(coord2)->h >= 19); + + redraw_man_destroy(rdman); +} + +static void +test_own_canvas_redraw(void) { + redraw_man_t *rdman; + redraw_man_t _rdman; + coord_t *coord1, *coord2; + sh_dummy_t *sh; + paint_t *paint; + co_aix *parent_2_cache; + + redraw_man_init(&_rdman, NULL, NULL); + rdman = &_rdman; + + coord1 = rdman_coord_new(rdman, rdman->root_coord); + CU_ASSERT(coord1->parent == rdman->root_coord); + + coord2 = rdman_coord_new(rdman, coord1); + CU_ASSERT(coord2->parent == coord1); + + coord_set_opacity(coord2, 0.9); + rdman_coord_changed(rdman, coord2); + + sh = (sh_dummy_t *)sh_dummy_new(rdman, 100, 100, 20, 20); + rdman_add_shape(rdman, (shape_t *)sh, coord2); + rdman_shape_changed(rdman, (shape_t *)sh); + + paint = dummy_paint_new(rdman); + rdman_paint_fill(rdman, paint, (shape_t *)sh); + + rdman_redraw_all(rdman); + + CU_ASSERT(sh->draw_cnt == 1); + CU_ASSERT(sh->last_draw == _coord_get_canvas(coord2)); + + parent_2_cache = ((mock_mbe_t *)_coord_get_canvas(coord2))->parent_2_cache; + CU_ASSERT(parent_2_cache[0] == 1); + CU_ASSERT(parent_2_cache[1] == 0); + CU_ASSERT(parent_2_cache[2] == -100); + CU_ASSERT(parent_2_cache[3] == 0); + CU_ASSERT(parent_2_cache[4] == 1); + CU_ASSERT(parent_2_cache[5] == -100); + + coord2->matrix[2] = 20; + coord2->matrix[5] = 30; + rdman_coord_changed(rdman, coord2); + rdman_redraw_changed(rdman); + + /* To test if transform matrix of cached coord working */ + parent_2_cache = ((mock_mbe_t *)_coord_get_canvas(coord2))->parent_2_cache; + CU_ASSERT(parent_2_cache[0] == 1); + CU_ASSERT(parent_2_cache[1] == 0); + CU_ASSERT(parent_2_cache[2] == -120); + CU_ASSERT(parent_2_cache[3] == 0); + CU_ASSERT(parent_2_cache[4] == 1); + CU_ASSERT(parent_2_cache[5] == -130); + + rdman_paint_free(rdman, paint); + redraw_man_destroy(rdman); +} + 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); + CU_ADD_TEST(suite, test_setup_canvas_info); + CU_ADD_TEST(suite, test_own_canvas_area); + CU_ADD_TEST(suite, test_own_canvas); + CU_ADD_TEST(suite, test_own_canvas_redraw); return suite; }