comparison 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
comparison
equal deleted inserted replaced
520:f106b57b8660 521:fa2ccf39ba53
1103 * 1103 *
1104 * A changed coord_t object is marked as dirty and put 1104 * A changed coord_t object is marked as dirty and put
1105 * into dirty_coords list. rdman_coord_changed() should be called 1105 * into dirty_coords list. rdman_coord_changed() should be called
1106 * for a coord after it been changed to notify redraw manager to 1106 * for a coord after it been changed to notify redraw manager to
1107 * redraw shapes grouped by it. 1107 * redraw shapes grouped by it.
1108 *
1109 * Once a coord is changed, all its descendants are also put marked
1110 * dirty.
1108 */ 1111 */
1109 int rdman_coord_changed(redraw_man_t *rdman, coord_t *coord) { 1112 int rdman_coord_changed(redraw_man_t *rdman, coord_t *coord) {
1110 coord_t *child; 1113 coord_t *child;
1111 1114
1112 if(coord->flags & COF_DIRTY) 1115 if(coord->flags & COF_DIRTY)
1126 if(child->flags & (COF_DIRTY | COF_HIDDEN)) { 1129 if(child->flags & (COF_DIRTY | COF_HIDDEN)) {
1127 preorder_coord_skip_subtree(child); 1130 preorder_coord_skip_subtree(child);
1128 continue; 1131 continue;
1129 } 1132 }
1130 1133
1131 add_dirty_coord(rdman, child);
1132
1133 if(child->flags & COF_OWN_CANVAS) { 1134 if(child->flags & COF_OWN_CANVAS) {
1134 preorder_coord_skip_subtree(child); 1135 preorder_coord_skip_subtree(child);
1135 continue; 1136 continue;
1136 } 1137 }
1138
1139 add_dirty_coord(rdman, child);
1137 } 1140 }
1138 1141
1139 return OK; 1142 return OK;
1140 } 1143 }
1141 1144
1251 */ 1254 */
1252 coord->canvas_info = coord->parent->canvas_info; 1255 coord->canvas_info = coord->parent->canvas_info;
1253 } 1256 }
1254 } 1257 }
1255 1258
1259 /* \brief Compute matrix from cached canvas to parent device space.
1260 */
1261 static void compute_cached_2_pdev_matrix(coord_t *coord,
1262 co_aix canvas2pdev_matrix[6]) {
1263 coord_t *parent;
1264 co_aix *aggr;
1265 co_aix *matrix, *paggr;
1266 co_aix scale_x, scale_y;
1267 co_aix shift_x, shift_y;
1268 co_aix canvas2p[6];
1269
1270 aggr = coord_get_aggr_matrix(coord);
1271 matrix = coord->matrix;
1272 parent = coord->parent;
1273 paggr = coord_get_aggr_matrix(parent);
1274
1275 scale_x = matrix[0] / aggr[0];
1276 scale_y = matrix[3] / aggr[3];
1277 shift_x = matrix[2] - scale_x * aggr[2];
1278 shift_y = matrix[5] - scale_y * aggr[5];
1279
1280 canvas2p[0] = scale_x;
1281 canvas2p[1] = 0;
1282 canvas2p[2] = shift_x;
1283 canvas2p[3] = 0;
1284 canvas2p[4] = scale_y;
1285 canvas2p[5] = shift_y;
1286
1287 matrix_mul(paggr, canvas2p, canvas2pdev_matrix);
1288 }
1289
1290 /*! \brief Compute area for a cached coord.
1291 *
1292 * The coordination system of cached coord and descendants is resized,
1293 * and shifted. It makes all descendants bound by a box, canvas box,
1294 * at 0, 0 and size is the same as the canvas.
1295 *
1296 * The bounding box where the canvas would be draw on the canvas on
1297 * ancestral cached coord can be retreived by shifting and resizing
1298 * canvas box in reverse and transform to coordination system of
1299 * ancestral cached coord.
1300 */
1301 static void compute_cached_coord_area(coord_t *coord) {
1302 co_aix *cached2pdev;
1303 int c_w, c_h;
1304 canvas_t *canvas;
1305 co_aix poses[4][2];
1306
1307 compute_cached_2_pdev_matrix(coord, cached2pdev);
1308
1309 canvas = _coord_get_canvas(coord);
1310 canvas_get_size(canvas, &c_w, &c_h);
1311
1312 poses[0][0] = 0;
1313 poses[0][1] = 0;
1314 poses[1][0] = c_w;
1315 poses[1][1] = c_h;
1316 poses[2][0] = 0;
1317 poses[2][1] = c_h;
1318 poses[3][0] = c_w;
1319 poses[3][1] = 0;
1320 matrix_trans_pos(cached2pdev, &poses[0][0], &poses[0][1]);
1321 matrix_trans_pos(cached2pdev, &poses[1][0], &poses[1][1]);
1322 matrix_trans_pos(cached2pdev, &poses[2][0], &poses[2][1]);
1323 matrix_trans_pos(cached2pdev, &poses[3][0], &poses[3][1]);
1324
1325 area_init(coord_get_area(coord), 4, poses);
1326 }
1327
1328 static int coord_update_area_4_cached_children(coord_t *coord) {
1329 coord_t *child;
1330 /*! \note poses is shared by invokings, it is not support reentrying. */
1331 static co_aix (*poses)[2];
1332 static int max_poses = 0;
1333 area_t *cur_area;
1334 int cnt, pos_cnt;
1335
1336 cnt = 1;
1337 FORCHILDREN(coord, child) {
1338 if(child->flags & COF_OWN_CANVAS) {
1339 compute_cached_coord_area(child);
1340 cnt++;
1341 }
1342 }
1343
1344 if(max_poses < (cnt * 2)) {
1345 free(poses);
1346 max_poses = cnt * 2;
1347 poses = (co_aix (*)[2])malloc(sizeof(co_aix [2]) * max_poses);
1348 if(poses == NULL)
1349 return ERR;
1350 }
1351
1352 FORCHILDREN(coord, child) {
1353 if(child->flags & COF_OWN_CANVAS) {
1354 area_to_positions(coord_get_area(child), poses + pos_cnt);
1355 pos_cnt += 2;
1356 }
1357 }
1358
1359 cur_area = coord_get_area(coord);
1360 area_to_positions(cur_area, poses + pos_cnt);
1361 pos_cnt += 2;
1362
1363 area_init(cur_area, pos_cnt, poses);
1364
1365 return OK;
1366 }
1367
1256 static int coord_clean_members_n_compute_area(coord_t *coord) { 1368 static int coord_clean_members_n_compute_area(coord_t *coord) {
1257 geo_t *geo; 1369 geo_t *geo;
1258 /*! \note poses is shared by invokings, it is not support reentrying. */ 1370 /*! \note poses is shared by invokings, it is not support reentrying. */
1259 static co_aix (*poses)[2]; 1371 static co_aix (*poses)[2];
1260 static int max_poses = 0; 1372 static int max_poses = 0;
1281 area_to_positions(geo->cur_area, poses + pos_cnt); 1393 area_to_positions(geo->cur_area, poses + pos_cnt);
1282 pos_cnt += 2; 1394 pos_cnt += 2;
1283 } 1395 }
1284 1396
1285 area_init(coord->cur_area, pos_cnt, poses); 1397 area_init(coord->cur_area, pos_cnt, poses);
1286 1398
1287 return OK; 1399 return OK;
1288 } 1400 }
1289 1401
1290 /*! \brief Clean dirty coords. 1402 /*! \brief Clean dirty coords.
1291 * 1403 *
1308 */ 1420 */
1309 r = coord_clean_members_n_compute_area(coord); 1421 r = coord_clean_members_n_compute_area(coord);
1310 if(r != OK) 1422 if(r != OK)
1311 return ERR; 1423 return ERR;
1312 1424
1425 r = coord_update_area_4_cached_children(coord);
1426 if(r != OK)
1427 return ERR;
1428
1313 coord->flags &= ~COF_DIRTY; 1429 coord->flags &= ~COF_DIRTY;
1314 1430
1315 return OK; 1431 return OK;
1316 } 1432 }
1317 1433
1318 /*! \brief Clean coord_t objects. 1434 /*! \brief Clean coord_t objects.
1435 *
1436 * It computes aggregation matrix and area for dirty coords.
1319 */ 1437 */
1320 static int clean_rdman_coords(redraw_man_t *rdman) { 1438 static int clean_rdman_coords(redraw_man_t *rdman) {
1321 coord_t *coord; 1439 coord_t *coord;
1322 coord_t **dirty_coords; 1440 coord_t **dirty_coords;
1323 int n_dirty_coords; 1441 int n_dirty_coords;
1325 1443
1326 n_dirty_coords = rdman->dirty_coords.num; 1444 n_dirty_coords = rdman->dirty_coords.num;
1327 if(n_dirty_coords > 0) { 1445 if(n_dirty_coords > 0) {
1328 dirty_coords = rdman->dirty_coords.ds; 1446 dirty_coords = rdman->dirty_coords.ds;
1329 _insert_sort((void **)dirty_coords, n_dirty_coords, 1447 _insert_sort((void **)dirty_coords, n_dirty_coords,
1330 OFFSET(coord_t, order)); 1448 OFFSET(coord_t, order)); /* ascend order */
1331 for(i = 0; i < n_dirty_coords; i++) { 1449 for(i = 0; i < n_dirty_coords; i++) {
1332 coord = dirty_coords[i]; 1450 coord = dirty_coords[i];
1333 if(!(coord->flags & COF_DIRTY)) 1451 if(!(coord->flags & COF_DIRTY))
1334 continue; 1452 continue;
1335 r = clean_coord(rdman, coord); 1453 r = clean_coord(rdman, coord);
1374 * sub-graphic to origin of the space. 1492 * sub-graphic to origin of the space.
1375 */ 1493 */
1376 static 1494 static
1377 void zeroing_coord(redraw_man_t *rdman, coord_t *coord) { 1495 void zeroing_coord(redraw_man_t *rdman, coord_t *coord) {
1378 coord_t *cur; 1496 coord_t *cur;
1379 area_t *area; 1497 area_t *area, *saved_area;
1380 co_aix min_x, min_y; 1498 co_aix min_x, min_y;
1381 co_aix max_x, max_y; 1499 co_aix max_x, max_y;
1382 co_aix x, y; 1500 co_aix x, y;
1383 int w, h; 1501 int w, h;
1384 int c_w, c_h; 1502 int c_w, c_h;
1385 mbe_t *canvas; 1503 mbe_t *canvas;
1386 co_aix *aggr; 1504 co_aix *aggr;
1387 co_aix poses[2][2]; 1505 co_aix poses[4][2];
1388 1506
1389 if(coord->parent == NULL) /*! \note Should not zeroing root coord */ 1507 if(coord->parent == NULL) /*! \note Should not zeroing root coord */
1390 abort(); 1508 abort();
1391 if(!(coord_is_zeroing(coord))) 1509 if(!(coord_is_zeroing(coord)))
1392 abort(); 1510 abort();
1423 } 1541 }
1424 1542
1425 w = max_x - min_x; 1543 w = max_x - min_x;
1426 h = max_y - min_y; 1544 h = max_y - min_y;
1427 1545
1428 /*
1429 * Setup area of the coord
1430 */
1431 aggr = coord_get_aggr_matrix(coord);
1432 x = y = 0;
1433 coord_trans_pos(coord->parent, &x, &y);
1434 poses[0][0] = x;
1435 poses[0][1] = y;
1436 x = w;
1437 y = h;
1438 coord_trans_pos(coord->parent, &x, &y);
1439 poses[1][0] = x;
1440 poses[1][1] = y;
1441
1442 area_init(coord_get_area(coord), 2, poses);
1443
1444 canvas = _coord_get_canvas(coord); 1546 canvas = _coord_get_canvas(coord);
1445 if(canvas) 1547 if(canvas)
1446 canvas_get_size(canvas, &c_w, &c_h); 1548 canvas_get_size(canvas, &c_w, &c_h);
1447 else 1549 else
1448 c_w = c_h = 0; 1550 c_w = c_h = 0;
1449 1551
1552 /* Without COF_JUST_CLEAN means the coordination system and matrix
1553 * of the coord have not changed since last time of zeroing. So,
1554 * if canvas box cover all descendants, we don't need rezeroing,
1555 * and avoid redraw all descendants.
1556 */
1450 if(!coord_get_flags(coord, COF_JUST_CLEAN) && 1557 if(!coord_get_flags(coord, COF_JUST_CLEAN) &&
1451 min_x >= 0 && min_y >= 0 && max_x <= c_w && max_y <= c_h) 1558 min_x >= 0 && min_y >= 0 && max_x <= c_w && max_y <= c_h)
1452 /* Canvas fully cover sub-graphic. */ 1559 /* Canvas fully cover sub-graphic. */
1453 return; 1560 return;
1454 1561
1455 /* 1562 /*
1456 * Adjust matrics of descendants to align left-top corner of 1563 * Adjust matrics of descendants to align left-top corner of
1457 * minimum covering area with origin of space defined by 1564 * minimum covering area with origin of space defined by
1458 * zeroing coord. 1565 * zeroing coord.
1459 */ 1566 */
1567 saved_area = coord_get_area(coord);
1568 coord->cur_area = &coord->canvas_info->owner_mems_area;
1460 FOR_COORDS_PREORDER(coord, cur) { 1569 FOR_COORDS_PREORDER(coord, cur) {
1461 aggr = coord_get_aggr_matrix(cur); 1570 aggr = coord_get_aggr_matrix(cur);
1462 aggr[3] -= min_x; 1571 aggr[3] -= min_x;
1463 aggr[5] -= min_y; 1572 aggr[5] -= min_y;
1464 if(coord_get_flags(cur, COF_OWN_CANVAS)) { 1573 if(coord_get_flags(cur, COF_OWN_CANVAS) && coord != cur) {
1465 /* 1574 /*
1466 * Coords, zeroing, is zeroed in preorder of tree. 1575 * Coords, zeroing, is zeroed in preorder of tree.
1467 * So, they are zeroed after ancesters with correctly 1576 * So, they are zeroed after ancesters with correctly
1468 * coord_t::aggr_matrix of parent coord to zeroing. 1577 * coord_t::aggr_matrix of parent coord to zeroing.
1469 */ 1578 */
1470 preorder_coord_skip_subtree(cur); 1579 preorder_coord_skip_subtree(cur);
1580 #if 0
1581 /* Parent had called coord_clean_members_n_compute_area().
1582 * So, the area of this coord had been recomputed.
1583 */
1471 area = coord_get_area(cur); 1584 area = coord_get_area(cur);
1472 area->x -= min_x; 1585 area->x -= min_x;
1473 area->y -= min_y; 1586 area->y -= min_y;
1474 } else 1587 #endif
1588 } else {
1475 coord_clean_members_n_compute_area(cur); 1589 coord_clean_members_n_compute_area(cur);
1476 } 1590 coord_update_area_4_cached_children(cur);
1591 }
1592 }
1593 coord->cur_area = saved_area;
1477 1594
1478 /* 1595 /*
1479 * Setup canvas 1596 * Setup canvas
1480 */ 1597 */
1481 if(canvas == NULL || w > c_w || h > c_w) { 1598 if(canvas == NULL || w > c_w || h > c_w) {
1483 canvas_free(canvas); 1600 canvas_free(canvas);
1484 canvas = canvas_new(w, h); 1601 canvas = canvas_new(w, h);
1485 _coord_set_canvas(coord, canvas); 1602 _coord_set_canvas(coord, canvas);
1486 } 1603 }
1487 1604
1605 compute_cached_coord_area(coord);
1606
1607 /* Since aggregated matrix had been changed to make descendants
1608 * falling on the canvas, size or/and position of all descendants
1609 * are chagned, and new canvas was created. So, a dirty area that
1610 * covers all space of the canvas is created to force redrawing
1611 * all descendants.
1612 */
1488 area = &coord->canvas_info->cached_dirty_area; 1613 area = &coord->canvas_info->cached_dirty_area;
1489 area->x = 0; 1614 area->x = 0;
1490 area->y = 0; 1615 area->y = 0;
1491 area->w = w; 1616 area->w = w;
1492 area->h = h; 1617 area->h = h;
1503 int n_dirty_geos; 1628 int n_dirty_geos;
1504 geo_t **dirty_geos, *geo; 1629 geo_t **dirty_geos, *geo;
1505 int n_dirty_coords; 1630 int n_dirty_coords;
1506 coord_t **dirty_coords, *coord; 1631 coord_t **dirty_coords, *coord;
1507 1632
1508 /* Mark all cached ancestor coords of dirty geos */ 1633 /* Mark all cached ancestral coords of dirty geos */
1509 n_dirty_geos = rdman->dirty_geos.num; 1634 n_dirty_geos = rdman->dirty_geos.num;
1510 dirty_geos = rdman->dirty_geos.ds; 1635 dirty_geos = rdman->dirty_geos.ds;
1511 for(i = 0; i < n_dirty_geos; i++) { 1636 for(i = 0; i < n_dirty_geos; i++) {
1512 geo = dirty_geos[i]; 1637 geo = dirty_geos[i];
1513 coord = geo_get_coord(geo)->canvas_info->owner; 1638 coord = geo_get_coord(geo)->canvas_info->owner;
1517 break; 1642 break;
1518 coord = coord->parent->canvas_info->owner; 1643 coord = coord->parent->canvas_info->owner;
1519 } 1644 }
1520 } 1645 }
1521 1646
1522 /* Mark all cached ancestor coords of dirty coords */ 1647 /* Mark all cached ancestral coords of dirty coords */
1523 n_dirty_coords = rdman->dirty_coords.num; 1648 n_dirty_coords = rdman->dirty_coords.num;
1524 dirty_coords = rdman->dirty_coords.ds; 1649 dirty_coords = rdman->dirty_coords.ds;
1525 for(i = 0; i < n_dirty_coords; i++) { 1650 for(i = 0; i < n_dirty_coords; i++) {
1526 coord = dirty_coords[i]->canvas_info->owner; 1651 coord = dirty_coords[i]->canvas_info->owner;
1527 while(!coord_get_flags(coord, COF_MUST_ZEROING | COF_TEMP_MARK)) { 1652 while(!coord_get_flags(coord, COF_MUST_ZEROING | COF_TEMP_MARK)) {
1567 } 1692 }
1568 1693
1569 return OK; 1694 return OK;
1570 } 1695 }
1571 1696
1572 /* \brief Compute matrix from cached canvas to parent device space.
1573 */
1574 static void compute_cached_2_pdev_matrix(coord_t *coord,
1575 co_aix canvas2pdev_matrix[6]) {
1576 coord_t *parent;
1577 co_aix *aggr;
1578 co_aix *matrix, *paggr;
1579 co_aix scale_x, scale_y;
1580 co_aix shift_x, shift_y;
1581 co_aix canvas2p[6];
1582
1583 aggr = coord_get_aggr_matrix(coord);
1584 matrix = coord->matrix;
1585 parent = coord->parent;
1586 paggr = coord_get_aggr_matrix(parent);
1587
1588 scale_x = matrix[0] / aggr[0];
1589 scale_y = matrix[3] / aggr[3];
1590 shift_x = matrix[2] - scale_x * aggr[2];
1591 shift_y = matrix[5] - scale_y * aggr[5];
1592
1593 canvas2p[0] = scale_x;
1594 canvas2p[1] = 0;
1595 canvas2p[2] = shift_x;
1596 canvas2p[3] = 0;
1597 canvas2p[4] = scale_y;
1598 canvas2p[5] = shift_y;
1599
1600 matrix_mul(paggr, canvas2p, canvas2pdev_matrix);
1601 }
1602
1603 /*! \brief Add aggregated dirty areas to ancestor. 1697 /*! \brief Add aggregated dirty areas to ancestor.
1604 * 1698 *
1605 * Dirty areas are aggregated into two areas. It assumes that even or odd 1699 * Dirty areas are aggregated into two areas. It assumes that even or odd
1606 * ones are old areas or new areas repsective. So, all even ones are 1700 * ones are old areas or new areas repsective. So, all even ones are
1607 * aggregated in an area, and odd ones are in another. 1701 * aggregated in an area, and odd ones are in another.
1707 if(coord_get_flags(coord, COF_JUST_CLEAN) && 1801 if(coord_get_flags(coord, COF_JUST_CLEAN) &&
1708 !coord_get_flags(pcached_coord, COF_JUST_CLEAN)) 1802 !coord_get_flags(pcached_coord, COF_JUST_CLEAN))
1709 add_dirty_area(rdman, pcached_coord, coord->last_area); 1803 add_dirty_area(rdman, pcached_coord, coord->last_area);
1710 } 1804 }
1711 1805
1806 /* Aggregate dirty areas and propgate them to ancestor cached coord.
1807 *
1808 * The aggregation is performed from leaves to root. But, this
1809 * function do not aggregate dirty areas for root coord. The dirty
1810 * areas of a cached coord are aggregated into two areas, one for old
1811 * areas and one or new areas. Both aggregation areas are add into
1812 * dirty_areas list of closet ancestral cached coord.
1813 */
1712 static int add_rdman_aggr_dirty_areas(redraw_man_t *rdman) { 1814 static int add_rdman_aggr_dirty_areas(redraw_man_t *rdman) {
1713 int i; 1815 int i;
1714 int n_zeroing; 1816 int n_zeroing;
1715 coord_t **zeroings; 1817 coord_t **zeroings;
1716 coord_t *coord; 1818 coord_t *coord;
1724 } 1826 }
1725 1827
1726 return OK; 1828 return OK;
1727 } 1829 }
1728 1830
1831 /* Aggregate dirty areas for root coord.
1832 *
1833 * Because, root coord has no parent coord, so its aggregation dirty
1834 * areas are not added into dirty_areas of ancestral cached coord.
1835 * So, it is aggregated in a separated function.
1836 */
1729 static int add_rdman_cached_dirty_areas(redraw_man_t *rdman) { 1837 static int add_rdman_cached_dirty_areas(redraw_man_t *rdman) {
1730 int i; 1838 int i;
1731 coord_t *coord, **dirty_coords; 1839 coord_t *coord, **dirty_coords;
1732 int n_dirty_coords; 1840 int n_dirty_coords;
1733 1841
1761 if(!coord_get_flags(coord, COF_OWN_CANVAS)) 1869 if(!coord_get_flags(coord, COF_OWN_CANVAS))
1762 SWAP(coord->cur_area, coord->last_area, area_t *); 1870 SWAP(coord->cur_area, coord->last_area, area_t *);
1763 else { 1871 else {
1764 coord->last_area = coord->cur_area; 1872 coord->last_area = coord->cur_area;
1765 coord->cur_area = &coord->canvas_info->owner_mems_area; 1873 coord->cur_area = &coord->canvas_info->owner_mems_area;
1874 /* coord->cur_area are reseted to another area at
1875 * #RST.
1876 *
1877 * coord->cur_area of a cached coord is aggregated
1878 * area. But, its meaning is changed back to be area
1879 * of members to compute. It can avoid specialized
1880 * code for cached coords to change meaning of
1881 * cur_area temporary when computing area of a cached
1882 * coord.
1883 */
1766 } 1884 }
1767 } 1885 }
1768 } 1886 }
1769 1887
1770 geos = rdman->dirty_geos.ds; 1888 geos = rdman->dirty_geos.ds;
1776 if(r != OK) 1894 if(r != OK)
1777 return ERR; 1895 return ERR;
1778 1896
1779 coords = rdman->dirty_coords.ds; 1897 coords = rdman->dirty_coords.ds;
1780 for(i = 0; i < rdman->dirty_coords.num; i++) { 1898 for(i = 0; i < rdman->dirty_coords.num; i++) {
1899 /* Mark dirty coords COF_JUST_CLEAN to identify coords that
1900 * has changed their matrix and respective coordination
1901 * system. It helps zeroing_coord() to avoid fully redrawing
1902 * all descednants of a cached coord that had not changed its
1903 * matrix.
1904 */
1781 coord = coords[i]; 1905 coord = coords[i];
1782 coord_set_flags(coord, COF_JUST_CLEAN); 1906 coord_set_flags(coord, COF_JUST_CLEAN);
1907
1908 /* #RST: reset coord->cur_area, here */
1783 coord->cur_area = 1909 coord->cur_area =
1784 (coord->last_area == coord->areas)? 1910 (coord->last_area == coord->areas)?
1785 coord->areas + 1: coord->areas; 1911 coord->areas + 1: coord->areas;
1786 } 1912 }
1787 1913