Mercurial > MadButterfly
comparison src/redraw_man.c @ 537:3a7e3c1cd6e6 Android_Skia
[mq]: propagate_areas.diff
author | Thinker K.F. Li <thinker@branda.to> |
---|---|
date | Sat, 22 May 2010 22:31:18 +0800 |
parents | b6b3dbeaedf3 |
children | a1d49b6355c3 |
comparison
equal
deleted
inserted
replaced
536:b6b3dbeaedf3 | 537:3a7e3c1cd6e6 |
---|---|
469 coord_set_zeroing(coord); | 469 coord_set_zeroing(coord); |
470 ADD_DATA(coords, zeroing_coords, coord); | 470 ADD_DATA(coords, zeroing_coords, coord); |
471 return OK; | 471 return OK; |
472 } | 472 } |
473 | 473 |
474 static int add_dirty_pcache_area_coord(rdraw_man_t *rdman, coord_t *coord) { | 474 static int add_dirty_pcache_area_coord(redraw_man_t *rdman, coord_t *coord) { |
475 coord_set_flags(coord, COF_DIRTY_PCACHE_AREA); | 475 coord_set_flags(coord, COF_DIRTY_PCACHE_AREA); |
476 ADD_DATA(coords, dirty_pcache_area_coords, coord); | 476 ADD_DATA(coords, dirty_pcache_area_coords, coord); |
477 return OK; | 477 return OK; |
478 } | 478 } |
479 | 479 |
1244 | 1244 |
1245 if(coord->opacity != 1 || coord_is_cached(coord)) { | 1245 if(coord->opacity != 1 || coord_is_cached(coord)) { |
1246 if(!coord_is_cached(coord)) { | 1246 if(!coord_is_cached(coord)) { |
1247 /* canvas is assigned latter, in zeroing_coord() */ | 1247 /* canvas is assigned latter, in zeroing_coord() */ |
1248 coord->canvas_info = coord_canvas_info_new(rdman, coord, NULL); | 1248 coord->canvas_info = coord_canvas_info_new(rdman, coord, NULL); |
1249 coord_set_flags(coord->flags, COF_OWN_CANVAS); | 1249 coord_set_flags(coord, COF_OWN_CANVAS); |
1250 } | 1250 } |
1251 } else { | 1251 } else { |
1252 if(coord_is_cached(coord)) { | 1252 if(coord_is_cached(coord)) { |
1253 canvas_free(_coord_get_canvas(coord)); | 1253 canvas_free(_coord_get_canvas(coord)); |
1254 coord_canvas_info_free(rdman, coord->canvas_info); | 1254 coord_canvas_info_free(rdman, coord->canvas_info); |
1306 */ | 1306 */ |
1307 static void compute_pcache_area(coord_t *coord) { | 1307 static void compute_pcache_area(coord_t *coord) { |
1308 co_aix cached2pdev[6]; | 1308 co_aix cached2pdev[6]; |
1309 int c_w, c_h; | 1309 int c_w, c_h; |
1310 canvas_t *canvas; | 1310 canvas_t *canvas; |
1311 coord_canvas_info_t *canvas_info; | |
1311 co_aix poses[4][2]; | 1312 co_aix poses[4][2]; |
1312 | 1313 |
1314 canvas_info = coord->canvas_info; | |
1315 SWAP(canvas_info->pcache_cur_area, canvas_info->pcache_last_area, | |
1316 area_t *); | |
1313 compute_cached_2_pdev_matrix(coord, cached2pdev); | 1317 compute_cached_2_pdev_matrix(coord, cached2pdev); |
1314 | 1318 |
1315 canvas = _coord_get_canvas(coord); | 1319 canvas = _coord_get_canvas(coord); |
1316 canvas_get_size(canvas, &c_w, &c_h); | 1320 canvas_get_size(canvas, &c_w, &c_h); |
1317 | 1321 |
1327 matrix_trans_pos(cached2pdev, &poses[1][0], &poses[1][1]); | 1331 matrix_trans_pos(cached2pdev, &poses[1][0], &poses[1][1]); |
1328 matrix_trans_pos(cached2pdev, &poses[2][0], &poses[2][1]); | 1332 matrix_trans_pos(cached2pdev, &poses[2][0], &poses[2][1]); |
1329 matrix_trans_pos(cached2pdev, &poses[3][0], &poses[3][1]); | 1333 matrix_trans_pos(cached2pdev, &poses[3][0], &poses[3][1]); |
1330 | 1334 |
1331 area_init(coord_get_pcache_area(coord), 4, poses); | 1335 area_init(coord_get_pcache_area(coord), 4, poses); |
1336 | |
1337 coord_set_flags(coord, COF_DIRTY_PCACHE_AREA); | |
1332 } | 1338 } |
1333 | 1339 |
1334 /*! \brief Compute area of a coord. | 1340 /*! \brief Compute area of a coord. |
1335 */ | 1341 */ |
1336 static int | 1342 static int |
1404 */ | 1410 */ |
1405 r = coord_clean_members_n_compute_area(coord); | 1411 r = coord_clean_members_n_compute_area(coord); |
1406 if(r != OK) | 1412 if(r != OK) |
1407 return ERR; | 1413 return ERR; |
1408 | 1414 |
1409 add_dirty_area(rdman, coord->cur_area); | 1415 add_dirty_area(rdman, coord, coord->cur_area); |
1410 add_dirty_area(rdman, coord->last_area); | 1416 add_dirty_area(rdman, coord, coord->last_area); |
1411 | 1417 |
1412 coord_clear_flags(coord, COF_DIRTY); | 1418 coord_clear_flags(coord, COF_DIRTY); |
1413 coord_set_flags(coord, COF_JUST_CLEAN); | 1419 coord_set_flags(coord, COF_JUST_CLEAN); |
1414 | 1420 |
1415 FORCHILDREN(coord, child) { | 1421 FORCHILDREN(coord, child) { |
1440 OFFSET(coord_t, order)); /* ascend order */ | 1446 OFFSET(coord_t, order)); /* ascend order */ |
1441 for(i = 0; i < n_dirty_coords; i++) { | 1447 for(i = 0; i < n_dirty_coords; i++) { |
1442 coord = dirty_coords[i]; | 1448 coord = dirty_coords[i]; |
1443 if(!coord_get_flags(coord, COF_DIRTY | COF_JUST_CLEAN)) | 1449 if(!coord_get_flags(coord, COF_DIRTY | COF_JUST_CLEAN)) |
1444 continue; | 1450 continue; |
1445 SWAP(coord->cur_area, coord->last_area, coord_t *); | 1451 SWAP(coord->cur_area, coord->last_area, area_t *); |
1446 r = clean_coord(rdman, coord); | 1452 r = clean_coord(rdman, coord); |
1447 if(r != OK) | 1453 if(r != OK) |
1448 return ERR; | 1454 return ERR; |
1449 } | 1455 } |
1450 } | 1456 } |
1524 | 1530 |
1525 if(x > max_x) | 1531 if(x > max_x) |
1526 max_x = x; | 1532 max_x = x; |
1527 if(y > max_y) | 1533 if(y > max_y) |
1528 max_y = y; | 1534 max_y = y; |
1529 if(coord_is_cached(cur->flags)) | 1535 if(coord_is_cached(cur)) |
1530 preorder_coord_skip_subtree(cur); | 1536 preorder_coord_skip_subtree(cur); |
1531 } | 1537 } |
1532 | 1538 |
1533 w = max_x - min_x; | 1539 w = max_x - min_x; |
1534 h = max_y - min_y; | 1540 h = max_y - min_y; |
1541 | 1547 |
1542 /* Without COF_JUST_CLEAN means the coordination system and matrix | 1548 /* Without COF_JUST_CLEAN means the coordination system and matrix |
1543 * of the coord have not changed since last time of zeroing. So, | 1549 * of the coord have not changed since last time of zeroing. So, |
1544 * if canvas box cover all descendants, we don't need rezeroing, | 1550 * if canvas box cover all descendants, we don't need rezeroing, |
1545 * and avoid redraw all descendants. | 1551 * and avoid redraw all descendants. |
1552 * | |
1553 * Width and height of actually drawing area should not be smaller | |
1554 * than half of canvas's width and height. | |
1546 */ | 1555 */ |
1547 if(!coord_get_flags(coord, COF_JUST_CLEAN) && | 1556 if(!coord_get_flags(coord, COF_JUST_CLEAN) && |
1548 min_x >= 0 && min_y >= 0 && max_x <= c_w && max_y <= c_h) | 1557 min_x >= 0 && min_y >= 0 && max_x <= c_w && max_y <= c_h && |
1558 h >= (c_h >> 2) && w >= (c_w >> 2)) { | |
1549 /* Canvas fully cover sub-graphic. */ | 1559 /* Canvas fully cover sub-graphic. */ |
1560 coord_set_flags(coord, COF_SKIP_ZERO); | |
1550 return; | 1561 return; |
1562 } | |
1551 | 1563 |
1552 /* | 1564 /* |
1553 * Adjust matrics of descendants to align left-top corner of | 1565 * Adjust matrics of descendants to align left-top corner of |
1554 * minimum covering area with origin of space defined by | 1566 * minimum covering area with origin of space defined by |
1555 * zeroing coord. | 1567 * zeroing coord. |
1582 canvas_free(canvas); | 1594 canvas_free(canvas); |
1583 canvas = canvas_new(w, h); | 1595 canvas = canvas_new(w, h); |
1584 _coord_set_canvas(coord, canvas); | 1596 _coord_set_canvas(coord, canvas); |
1585 } | 1597 } |
1586 | 1598 |
1587 compute_pcache_area(coord); | |
1588 | |
1589 /* Since aggregated matrix had been changed to make descendants | |
1590 * falling on the canvas, size or/and position of all descendants | |
1591 * are chagned, and new canvas was created. So, a dirty area that | |
1592 * covers all space of the canvas is created to force redrawing | |
1593 * all descendants. | |
1594 */ | |
1595 area = &coord->canvas_info->cached_dirty_area; | |
1596 area->x = 0; | |
1597 area->y = 0; | |
1598 area->w = w; | |
1599 area->h = h; | |
1600 DARRAY_CLEAN(_coord_get_dirty_areas(coord)); | |
1601 add_dirty_area(rdman, coord, area); | |
1602 | |
1603 coord_set_flags(coord, COF_JUST_ZERO); | 1599 coord_set_flags(coord, COF_JUST_ZERO); |
1604 } | 1600 } |
1605 | 1601 |
1606 /*! \brief Add canvas owner of dirty geos to redraw_man_t::zeroing_coords. | 1602 /*! \brief Add canvas owner of dirty geos to redraw_man_t::zeroing_coords. |
1607 * | 1603 * |
1668 int i; | 1664 int i; |
1669 coords_t *all_zeroing; | 1665 coords_t *all_zeroing; |
1670 coord_t *coord; | 1666 coord_t *coord; |
1671 | 1667 |
1672 all_zeroing = &rdman->zeroing_coords; | 1668 all_zeroing = &rdman->zeroing_coords; |
1673 for(i = 0; i < all_zeroing->num; i++) { | 1669 /* From leaft to root. |
1670 * REASON: The size of canvas is also effected by cached descedants. | |
1671 */ | |
1672 for(i = all_zeroing->num - 1; i >= 0; i--) { | |
1674 coord = all_zeroing->ds[i]; | 1673 coord = all_zeroing->ds[i]; |
1675 zeroing_coord(rdman, coord); | 1674 zeroing_coord(rdman, coord); |
1676 } | 1675 compute_pcache_area(coord); |
1677 | 1676 } |
1677 | |
1678 return OK; | |
1679 } | |
1680 | |
1681 /*! \brief Compute pcache_area for coords whoes pcache_area is dirty. | |
1682 */ | |
1683 static int | |
1684 compute_rdman_coords_pcache_area(redraw_man_t *rdman) { | |
1685 coords_t *all_coords; | |
1686 coord_t *coord; | |
1687 int i; | |
1688 | |
1689 all_coords = &rdman->dirty_pcache_area_coords; | |
1690 for(i = 0; i < all_coords->num; i++) { | |
1691 coord = all_coords->ds[i]; | |
1692 if(coord_get_flags(coord, COF_DIRTY_PCACHE_AREA)) | |
1693 compute_pcache_area(coord); | |
1694 } | |
1678 return OK; | 1695 return OK; |
1679 } | 1696 } |
1680 | 1697 |
1681 /*! \brief Add aggregated dirty areas to ancestor. | 1698 /*! \brief Add aggregated dirty areas to ancestor. |
1682 * | 1699 * |
1784 if(coord_get_flags(coord, COF_JUST_CLEAN) && | 1801 if(coord_get_flags(coord, COF_JUST_CLEAN) && |
1785 !coord_get_flags(pcached_coord, COF_JUST_CLEAN)) | 1802 !coord_get_flags(pcached_coord, COF_JUST_CLEAN)) |
1786 add_dirty_area(rdman, pcached_coord, coord->last_area); | 1803 add_dirty_area(rdman, pcached_coord, coord->last_area); |
1787 } | 1804 } |
1788 | 1805 |
1806 /*! \brief To test if redrawing all elements on the canvas of a cached coord. | |
1807 */ | |
1808 #define IS_CACHE_REDRAW_ALL(co) \ | |
1809 (coord_get_flags((co), COF_JUST_CLEAN | COF_JUST_ZERO)) | |
1810 | |
1789 /* Aggregate dirty areas and propagate them to ancestor cached coord. | 1811 /* Aggregate dirty areas and propagate them to ancestor cached coord. |
1790 * | 1812 * |
1791 * The aggregation is performed from leaves to root. But, this | 1813 * The aggregation is performed from leaves to root. But, this |
1792 * function do not aggregate dirty areas for root coord. The dirty | 1814 * function do not aggregate dirty areas for root coord. The dirty |
1793 * areas of a cached coord are aggregated into two areas, one for old | 1815 * areas of a cached coord are aggregated into two areas, one for old |
1797 static int add_rdman_aggr_dirty_areas(redraw_man_t *rdman) { | 1819 static int add_rdman_aggr_dirty_areas(redraw_man_t *rdman) { |
1798 int i; | 1820 int i; |
1799 int n_zeroing; | 1821 int n_zeroing; |
1800 coord_t **zeroings; | 1822 coord_t **zeroings; |
1801 coord_t *coord, *pcached_coord; | 1823 coord_t *coord, *pcached_coord; |
1802 | 1824 int n_dpca_coords; /* number of dirty pcache area coords */ |
1825 coord_t **dpca_coords; /* dirty pcache area coords */ | |
1826 | |
1827 /* Add aggregated areas to parent cached one for coords in zeroing | |
1828 * list | |
1829 */ | |
1803 n_zeroing = rdman->zeroing_coords.num; | 1830 n_zeroing = rdman->zeroing_coords.num; |
1804 zeroings = rdman->zeroing_coords.ds; | 1831 zeroings = rdman->zeroing_coords.ds; |
1805 for(i = n_zeroing - 1; i >= 0; i--) { | 1832 for(i = 0; i < n_zeroing; i++) { |
1833 if(coord_get_flags(coord, COF_TEMP_MARK)) | |
1834 continue; | |
1835 coord_set_flags(coord, COF_TEMP_MARK); | |
1836 | |
1806 coord = zeroings[i]; | 1837 coord = zeroings[i]; |
1807 pcached_coord = coord_get_cached(coord_get_parent(coord)); | 1838 pcached_coord = coord_get_cached(coord_get_parent(coord)); |
1808 if(!coord_is_root(coord) && !coord_is_zeroing(pcached_coord)) | 1839 |
1840 if(coord_is_root(coord) || IS_CACHE_REDRAW_ALL(pcached_coord)) | |
1841 continue; | |
1842 | |
1843 if(IS_CACHE_REDRAW_ALL(coord)) { | |
1844 add_dirty_area(rdman, pcached_coord, | |
1845 coord_get_pcache_area(coord)); | |
1846 add_dirty_area(rdman, pcached_coord, | |
1847 coord_get_pcache_last_area(coord)); | |
1848 } else { | |
1809 add_aggr_dirty_areas_to_ancestor(rdman, coord); | 1849 add_aggr_dirty_areas_to_ancestor(rdman, coord); |
1850 } | |
1851 } | |
1852 | |
1853 /* Add pcache_areas to parent cached one for coord that is | |
1854 * non-zeroing and its parent is changed. | |
1855 */ | |
1856 n_dpca_coords = rdman->dirty_pcache_area_coords.num; | |
1857 dpca_coords = rdman->dirty_pcache_area_coords.ds; | |
1858 for(i = 0; i < n_dpca_coords; i++) { | |
1859 if(coord_get_flags(coord, COF_TEMP_MARK)) | |
1860 continue; | |
1861 coord_set_flags(coord, COF_TEMP_MARK); | |
1862 | |
1863 coord = dpca_coords[i]; | |
1864 pcached_coord = coord_get_cached(coord_get_parent(coord)); | |
1865 | |
1866 if(coord_is_root(coord) || IS_CACHE_REDRAW_ALL(pcached_coord)) | |
1867 continue; | |
1868 | |
1869 add_dirty_area(rdman, pcached_coord, | |
1870 coord_get_pcache_area(coord)); | |
1871 add_dirty_area(rdman, pcached_coord, | |
1872 coord_get_pcache_last_area(coord)); | |
1873 } | |
1874 | |
1875 /* Remove temporary mark */ | |
1876 for(i = 0; i < n_zeroing; i++) { | |
1877 coord_clear_flags(zeroing[i], COF_TEMP_MARK); | |
1878 } | |
1879 for(i = 0; i < n_dpca_coords; i++) { | |
1880 coord_clear_flags(dpca_coords[i], COF_TEMP_MARK); | |
1810 } | 1881 } |
1811 | 1882 |
1812 return OK; | 1883 return OK; |
1813 } | 1884 } |
1814 | 1885 |
1914 | 1985 |
1915 r = zeroing_rdman_coords(rdman); | 1986 r = zeroing_rdman_coords(rdman); |
1916 if(r != OK) | 1987 if(r != OK) |
1917 return ERR; | 1988 return ERR; |
1918 | 1989 |
1990 r = compute_rdman_coords_pcache_area(rdman); | |
1991 if(r != OK) | |
1992 return ERR; | |
1993 | |
1919 r = add_rdman_aggr_dirty_areas(rdman); | 1994 r = add_rdman_aggr_dirty_areas(rdman); |
1920 if(r != OK) | 1995 if(r != OK) |
1921 return ERR; | 1996 return ERR; |
1922 | 1997 |
1923 r = add_rdman_cached_dirty_areas(rdman); | 1998 r = add_rdman_cached_dirty_areas(rdman); |