Mercurial > MadButterfly
diff src/redraw_man.c @ 521:fa2ccf39ba53 Android_Skia
imported patch more_comment.diff
author | Thinker K.F. Li <thinker@branda.to> |
---|---|
date | Sat, 19 Dec 2009 08:22:07 +0800 |
parents | f106b57b8660 |
children | c3fe9e4bdec1 |
line wrap: on
line diff
--- a/src/redraw_man.c Thu Dec 17 16:13:35 2009 +0800 +++ b/src/redraw_man.c Sat Dec 19 08:22:07 2009 +0800 @@ -1105,6 +1105,9 @@ * into dirty_coords list. rdman_coord_changed() should be called * for a coord after it been changed to notify redraw manager to * redraw shapes grouped by it. + * + * Once a coord is changed, all its descendants are also put marked + * dirty. */ int rdman_coord_changed(redraw_man_t *rdman, coord_t *coord) { coord_t *child; @@ -1128,12 +1131,12 @@ continue; } - add_dirty_coord(rdman, child); - if(child->flags & COF_OWN_CANVAS) { preorder_coord_skip_subtree(child); continue; } + + add_dirty_coord(rdman, child); } return OK; @@ -1253,6 +1256,115 @@ } } +/* \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]) { + coord_t *parent; + co_aix *aggr; + co_aix *matrix, *paggr; + co_aix scale_x, scale_y; + co_aix shift_x, shift_y; + co_aix canvas2p[6]; + + aggr = coord_get_aggr_matrix(coord); + matrix = coord->matrix; + parent = coord->parent; + paggr = coord_get_aggr_matrix(parent); + + scale_x = matrix[0] / aggr[0]; + scale_y = matrix[3] / aggr[3]; + shift_x = matrix[2] - scale_x * aggr[2]; + shift_y = matrix[5] - scale_y * aggr[5]; + + canvas2p[0] = scale_x; + canvas2p[1] = 0; + canvas2p[2] = shift_x; + canvas2p[3] = 0; + canvas2p[4] = scale_y; + canvas2p[5] = shift_y; + + matrix_mul(paggr, canvas2p, canvas2pdev_matrix); +} + +/*! \brief Compute area for a cached coord. + * + * The coordination system of cached coord and descendants is resized, + * and shifted. It makes all descendants bound by a box, canvas box, + * at 0, 0 and size is the same as the canvas. + * + * The bounding box where the canvas would be draw on the canvas on + * 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_cached_coord_area(coord_t *coord) { + co_aix *cached2pdev; + int c_w, c_h; + canvas_t *canvas; + co_aix poses[4][2]; + + 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; + poses[1][1] = c_h; + poses[2][0] = 0; + poses[2][1] = c_h; + poses[3][0] = c_w; + poses[3][1] = 0; + matrix_trans_pos(cached2pdev, &poses[0][0], &poses[0][1]); + 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_area(coord), 4, poses); +} + +static int coord_update_area_4_cached_children(coord_t *coord) { + coord_t *child; + /*! \note poses is shared by invokings, it is not support reentrying. */ + static co_aix (*poses)[2]; + static int max_poses = 0; + area_t *cur_area; + int cnt, pos_cnt; + + cnt = 1; + FORCHILDREN(coord, child) { + if(child->flags & COF_OWN_CANVAS) { + compute_cached_coord_area(child); + cnt++; + } + } + + if(max_poses < (cnt * 2)) { + free(poses); + max_poses = cnt * 2; + poses = (co_aix (*)[2])malloc(sizeof(co_aix [2]) * max_poses); + if(poses == NULL) + return ERR; + } + + FORCHILDREN(coord, child) { + if(child->flags & COF_OWN_CANVAS) { + area_to_positions(coord_get_area(child), poses + pos_cnt); + pos_cnt += 2; + } + } + + cur_area = coord_get_area(coord); + area_to_positions(cur_area, poses + pos_cnt); + pos_cnt += 2; + + area_init(cur_area, pos_cnt, poses); + + return OK; +} + static int coord_clean_members_n_compute_area(coord_t *coord) { geo_t *geo; /*! \note poses is shared by invokings, it is not support reentrying. */ @@ -1283,7 +1395,7 @@ } area_init(coord->cur_area, pos_cnt, poses); - + return OK; } @@ -1310,12 +1422,18 @@ if(r != OK) return ERR; + r = coord_update_area_4_cached_children(coord); + if(r != OK) + return ERR; + coord->flags &= ~COF_DIRTY; return OK; } /*! \brief Clean coord_t objects. + * + * It computes aggregation matrix and area for dirty coords. */ static int clean_rdman_coords(redraw_man_t *rdman) { coord_t *coord; @@ -1327,7 +1445,7 @@ if(n_dirty_coords > 0) { dirty_coords = rdman->dirty_coords.ds; _insert_sort((void **)dirty_coords, n_dirty_coords, - OFFSET(coord_t, order)); + OFFSET(coord_t, order)); /* ascend order */ for(i = 0; i < n_dirty_coords; i++) { coord = dirty_coords[i]; if(!(coord->flags & COF_DIRTY)) @@ -1376,7 +1494,7 @@ static void zeroing_coord(redraw_man_t *rdman, coord_t *coord) { coord_t *cur; - area_t *area; + area_t *area, *saved_area; co_aix min_x, min_y; co_aix max_x, max_y; co_aix x, y; @@ -1384,7 +1502,7 @@ int c_w, c_h; mbe_t *canvas; co_aix *aggr; - co_aix poses[2][2]; + co_aix poses[4][2]; if(coord->parent == NULL) /*! \note Should not zeroing root coord */ abort(); @@ -1425,28 +1543,17 @@ w = max_x - min_x; h = max_y - min_y; - /* - * Setup area of the coord - */ - aggr = coord_get_aggr_matrix(coord); - x = y = 0; - coord_trans_pos(coord->parent, &x, &y); - poses[0][0] = x; - poses[0][1] = y; - x = w; - y = h; - coord_trans_pos(coord->parent, &x, &y); - poses[1][0] = x; - poses[1][1] = y; - - area_init(coord_get_area(coord), 2, poses); - canvas = _coord_get_canvas(coord); if(canvas) canvas_get_size(canvas, &c_w, &c_h); else c_w = c_h = 0; - + + /* Without COF_JUST_CLEAN means the coordination system and matrix + * of the coord have not changed since last time of zeroing. So, + * if canvas box cover all descendants, we don't need rezeroing, + * and avoid redraw all descendants. + */ if(!coord_get_flags(coord, COF_JUST_CLEAN) && min_x >= 0 && min_y >= 0 && max_x <= c_w && max_y <= c_h) /* Canvas fully cover sub-graphic. */ @@ -1457,23 +1564,33 @@ * minimum covering area with origin of space defined by * zeroing coord. */ + saved_area = coord_get_area(coord); + coord->cur_area = &coord->canvas_info->owner_mems_area; FOR_COORDS_PREORDER(coord, cur) { aggr = coord_get_aggr_matrix(cur); aggr[3] -= min_x; aggr[5] -= min_y; - if(coord_get_flags(cur, COF_OWN_CANVAS)) { + if(coord_get_flags(cur, COF_OWN_CANVAS) && coord != cur) { /* * Coords, zeroing, is zeroed in preorder of tree. * So, they are zeroed after ancesters with correctly * coord_t::aggr_matrix of parent coord to zeroing. */ preorder_coord_skip_subtree(cur); +#if 0 + /* Parent had called coord_clean_members_n_compute_area(). + * So, the area of this coord had been recomputed. + */ area = coord_get_area(cur); area->x -= min_x; area->y -= min_y; - } else +#endif + } else { coord_clean_members_n_compute_area(cur); + coord_update_area_4_cached_children(cur); + } } + coord->cur_area = saved_area; /* * Setup canvas @@ -1485,6 +1602,14 @@ _coord_set_canvas(coord, canvas); } + compute_cached_coord_area(coord); + + /* Since aggregated matrix had been changed to make descendants + * falling on the canvas, size or/and position of all descendants + * are chagned, and new canvas was created. So, a dirty area that + * covers all space of the canvas is created to force redrawing + * all descendants. + */ area = &coord->canvas_info->cached_dirty_area; area->x = 0; area->y = 0; @@ -1505,7 +1630,7 @@ int n_dirty_coords; coord_t **dirty_coords, *coord; - /* Mark all cached ancestor coords of dirty geos */ + /* Mark all cached ancestral coords of dirty geos */ n_dirty_geos = rdman->dirty_geos.num; dirty_geos = rdman->dirty_geos.ds; for(i = 0; i < n_dirty_geos; i++) { @@ -1519,7 +1644,7 @@ } } - /* Mark all cached ancestor coords of dirty coords */ + /* Mark all cached ancestral coords of dirty coords */ n_dirty_coords = rdman->dirty_coords.num; dirty_coords = rdman->dirty_coords.ds; for(i = 0; i < n_dirty_coords; i++) { @@ -1569,37 +1694,6 @@ return OK; } -/* \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]) { - coord_t *parent; - co_aix *aggr; - co_aix *matrix, *paggr; - co_aix scale_x, scale_y; - co_aix shift_x, shift_y; - co_aix canvas2p[6]; - - aggr = coord_get_aggr_matrix(coord); - matrix = coord->matrix; - parent = coord->parent; - paggr = coord_get_aggr_matrix(parent); - - scale_x = matrix[0] / aggr[0]; - scale_y = matrix[3] / aggr[3]; - shift_x = matrix[2] - scale_x * aggr[2]; - shift_y = matrix[5] - scale_y * aggr[5]; - - canvas2p[0] = scale_x; - canvas2p[1] = 0; - canvas2p[2] = shift_x; - canvas2p[3] = 0; - canvas2p[4] = scale_y; - canvas2p[5] = shift_y; - - matrix_mul(paggr, canvas2p, canvas2pdev_matrix); -} - /*! \brief Add aggregated dirty areas to ancestor. * * Dirty areas are aggregated into two areas. It assumes that even or odd @@ -1709,6 +1803,14 @@ add_dirty_area(rdman, pcached_coord, coord->last_area); } +/* Aggregate dirty areas and propgate them to ancestor cached coord. + * + * The aggregation is performed from leaves to root. But, this + * function do not aggregate dirty areas for root coord. The dirty + * areas of a cached coord are aggregated into two areas, one for old + * areas and one or new areas. Both aggregation areas are add into + * dirty_areas list of closet ancestral cached coord. + */ static int add_rdman_aggr_dirty_areas(redraw_man_t *rdman) { int i; int n_zeroing; @@ -1726,6 +1828,12 @@ return OK; } +/* Aggregate dirty areas for root coord. + * + * Because, root coord has no parent coord, so its aggregation dirty + * areas are not added into dirty_areas of ancestral cached coord. + * So, it is aggregated in a separated function. + */ static int add_rdman_cached_dirty_areas(redraw_man_t *rdman) { int i; coord_t *coord, **dirty_coords; @@ -1763,6 +1871,16 @@ else { coord->last_area = coord->cur_area; coord->cur_area = &coord->canvas_info->owner_mems_area; + /* coord->cur_area are reseted to another area at + * #RST. + * + * coord->cur_area of a cached coord is aggregated + * area. But, its meaning is changed back to be area + * of members to compute. It can avoid specialized + * code for cached coords to change meaning of + * cur_area temporary when computing area of a cached + * coord. + */ } } } @@ -1778,8 +1896,16 @@ coords = rdman->dirty_coords.ds; for(i = 0; i < rdman->dirty_coords.num; i++) { + /* Mark dirty coords COF_JUST_CLEAN to identify coords that + * has changed their matrix and respective coordination + * system. It helps zeroing_coord() to avoid fully redrawing + * all descednants of a cached coord that had not changed its + * matrix. + */ coord = coords[i]; coord_set_flags(coord, COF_JUST_CLEAN); + + /* #RST: reset coord->cur_area, here */ coord->cur_area = (coord->last_area == coord->areas)? coord->areas + 1: coord->areas;