comparison src/redraw_man.c @ 535:a545f126d2bf Android_Skia

pcached_area replaces owner_mems_area
author Thinker K.F. Li <thinker@branda.to>
date Sun, 16 May 2010 22:59:24 +0800
parents 9f2d07a60493
children b6b3dbeaedf3
comparison
equal deleted inserted replaced
534:9f2d07a60493 535:a545f126d2bf
37 * clean in preorder of tree traversal. The redraw_man_t::dirty_coords 37 * clean in preorder of tree traversal. The redraw_man_t::dirty_coords
38 * list are sorted to keep ordering before cleaning. 38 * list are sorted to keep ordering before cleaning.
39 * Whenever a coord is marked dirty and put into redraw_man_t::dirty_coords 39 * Whenever a coord is marked dirty and put into redraw_man_t::dirty_coords
40 * list, all it's children should also be marked. 40 * list, all it's children should also be marked.
41 * 41 *
42 * The procedure of clean coords comprises recomputing aggregate 42 * The procedure of clean coords comprises recomputing aggregated
43 * transform matrix and area where members spreading in. The aggregated 43 * transform matrix and area where members spreading in. The aggregated
44 * transform matrix can reduce number of matrix mul to transform 44 * transform matrix can reduce number of matrix mul to transform
45 * positions from space of a coord to the closest cached ancestor coord. 45 * positions from space of a coord to the closest cached ancestor coord.
46 * 46 *
47 * The list is inspected before drawing to recompute new shape, size, 47 * The list is inspected before drawing to recompute new shape, size,
285 * - Cached ancestors of redraw_man_t::dirty_geos 285 * - Cached ancestors of redraw_man_t::dirty_geos
286 * - Cached ancestors of redraw_man_t::dirty_coords 286 * - Cached ancestors of redraw_man_t::dirty_coords
287 * - Cached ancestors of zeroed ones should also be zeroed. 287 * - Cached ancestors of zeroed ones should also be zeroed.
288 * - zeroing 288 * - zeroing
289 * - Add more dirty areas if canvas should be fully redrawed. 289 * - Add more dirty areas if canvas should be fully redrawed.
290 * - From leaf to root. 290 * - From leaves to root.
291 * - Adjust area of child cached coords.
291 * - add aggregated dirty areas from descendant cached coords to ancestors. 292 * - add aggregated dirty areas from descendant cached coords to ancestors.
292 * - Must include old area of cached coords if it is just clean and 293 * - Must include old area of cached coords if it is just clean and
293 * parent cached one is not just clean. 294 * parent cached one is not just clean.
294 * - Just clean is a coord cleaned in last time of cleaning coords. 295 * - Just clean is a coord cleaned in last time of cleaning coords.
295 * - draw dirty areas 296 * - draw dirty areas
296 * - areas are rounded to N at first. 297 * - areas are rounded to N at first.
297 * - from leaf to root. 298 * - from leaves to root.
298 */ 299 */
299 300
300 #ifndef ASSERT 301 #ifndef ASSERT
301 #define ASSERT(x) 302 #define ASSERT(x)
302 #endif 303 #endif
587 return info; 588 return info;
588 589
589 info->owner = coord; 590 info->owner = coord;
590 info->canvas = canvas; 591 info->canvas = canvas;
591 DARRAY_INIT(&info->dirty_areas); 592 DARRAY_INIT(&info->dirty_areas);
593
594 bzero(info->pcache_areas, sizeof(area_t) * 2);
595 info->pcache_cur_area = &info->pcache_areas[0];
596 info->pcache_last_area = &info->pcache_areas[1];
592 597
593 return info; 598 return info;
594 } 599 }
595 600
596 static void coord_canvas_info_free(redraw_man_t *rdman, 601 static void coord_canvas_info_free(redraw_man_t *rdman,
725 FORMEMBERS(saved_coord, member) { 730 FORMEMBERS(saved_coord, member) {
726 rdman_shape_free(rdman, member->shape); 731 rdman_shape_free(rdman, member->shape);
727 } 732 }
728 rdman_coord_free(rdman, saved_coord); 733 rdman_coord_free(rdman, saved_coord);
729 } 734 }
730 #if 0
731 FORMEMBERS(saved_coord, member) {
732 rdman_shape_free(rdman, member->shape);
733 }
734 #endif
735 /* Resources of root_coord is free by elmpool_free() or 735 /* Resources of root_coord is free by elmpool_free() or
736 * caller; for canvas 736 * caller; for canvas
737 */ 737 */
738 738
739 shape = saved_shape = STAILQ_HEAD(rdman->shapes); 739 while((shape = STAILQ_HEAD(rdman->shapes)) != NULL) {
740 while(shape && (shape = STAILQ_NEXT(shape_t, sh_next, shape))) { 740 rdman_shape_free(rdman, shape);
741 rdman_shape_free(rdman, saved_shape); 741 }
742 #if 0
743 STAILQ_REMOVE(rdman->shapes, shape_t, sh_next, saved_shape);
744 #endif
745 saved_shape = shape;
746 }
747 if(saved_shape != NULL)
748 rdman_shape_free(rdman, saved_shape);
749 742
750 coord_canvas_info_free(rdman, rdman->root_coord->canvas_info); 743 coord_canvas_info_free(rdman, rdman->root_coord->canvas_info);
751 744
752 /* XXX: paints are not freed, here. All resources of paints would 745 /* XXX: paints are not freed, here. All resources of paints would
753 * be reclaimed by freeing elmpools. 746 * be reclaimed by freeing elmpools.
1288 canvas2p[5] = shift_y; 1281 canvas2p[5] = shift_y;
1289 1282
1290 matrix_mul(paggr, canvas2p, canvas2pdev_matrix); 1283 matrix_mul(paggr, canvas2p, canvas2pdev_matrix);
1291 } 1284 }
1292 1285
1293 /*! \brief Compute area for a cached coord. 1286 /*! \brief Compute area in parent cached coord for a cached coord.
1294 * 1287 *
1295 * The coordination system of cached coord and descendants is resized, 1288 * The coordination system of cached coord and descendants is resized,
1296 * and shifted. It makes all descendants bound by a box, canvas box, 1289 * and shifted. It makes all descendants bound by a box, canvas box,
1297 * at 0, 0 and size is the same as the canvas. 1290 * at 0, 0 and size is the same as the canvas.
1298 * 1291 *
1299 * The bounding box where the canvas would be draw on the canvas on 1292 * The bounding box where the canvas would be draw on the canvas on
1300 * ancestral cached coord can be retreived by shifting and resizing 1293 * ancestral cached coord can be retreived by shifting and resizing
1301 * canvas box in reverse and transform to coordination system of 1294 * canvas box in reverse and transform to coordination system of
1302 * ancestral cached coord. 1295 * ancestral cached coord.
1303 */ 1296 */
1304 static void compute_cached_coord_area(coord_t *coord) { 1297 static void compute_pcache_area(coord_t *coord) {
1305 co_aix *cached2pdev; 1298 co_aix cached2pdev[6];
1306 int c_w, c_h; 1299 int c_w, c_h;
1307 canvas_t *canvas; 1300 canvas_t *canvas;
1308 co_aix poses[4][2]; 1301 co_aix poses[4][2];
1309 1302
1310 compute_cached_2_pdev_matrix(coord, cached2pdev); 1303 compute_cached_2_pdev_matrix(coord, cached2pdev);
1323 matrix_trans_pos(cached2pdev, &poses[0][0], &poses[0][1]); 1316 matrix_trans_pos(cached2pdev, &poses[0][0], &poses[0][1]);
1324 matrix_trans_pos(cached2pdev, &poses[1][0], &poses[1][1]); 1317 matrix_trans_pos(cached2pdev, &poses[1][0], &poses[1][1]);
1325 matrix_trans_pos(cached2pdev, &poses[2][0], &poses[2][1]); 1318 matrix_trans_pos(cached2pdev, &poses[2][0], &poses[2][1]);
1326 matrix_trans_pos(cached2pdev, &poses[3][0], &poses[3][1]); 1319 matrix_trans_pos(cached2pdev, &poses[3][0], &poses[3][1]);
1327 1320
1328 area_init(coord_get_area(coord), 4, poses); 1321 area_init(coord_get_pcache_area(coord), 4, poses);
1329 } 1322 }
1330 1323
1331 static int coord_update_area_4_cached_children(coord_t *coord) { 1324 /*! \brief Compute area of a coord.
1332 coord_t *child; 1325 */
1333 /*! \note poses is shared by invokings, it is not support reentrying. */ 1326 static int
1327 compute_area(coord_t *coord) {
1334 static co_aix (*poses)[2]; 1328 static co_aix (*poses)[2];
1335 static int max_poses = 0; 1329 static int max_poses = 0;
1336 area_t *cur_area; 1330 geo_t *geo;
1337 int cnt, pos_cnt; 1331 int cnt, pos_cnt;
1338 1332
1339 cnt = 1; 1333 cnt = 0;
1340 FORCHILDREN(coord, child) { 1334 FORMEMBERS(coord, geo) {
1341 if(child->flags & COF_OWN_CANVAS) { 1335 cnt++;
1342 compute_cached_coord_area(child); 1336 }
1343 cnt++; 1337
1344 }
1345 }
1346
1347 if(max_poses < (cnt * 2)) { 1338 if(max_poses < (cnt * 2)) {
1348 free(poses); 1339 free(poses);
1349 max_poses = cnt * 2; 1340 max_poses = cnt * 2;
1350 poses = (co_aix (*)[2])malloc(sizeof(co_aix [2]) * max_poses); 1341 poses = (co_aix (*)[2])malloc(sizeof(co_aix [2]) * max_poses);
1351 if(poses == NULL) 1342 if(poses == NULL)
1352 return ERR; 1343 return ERR;
1353 } 1344 }
1354 1345
1355 pos_cnt = 0;
1356 FORCHILDREN(coord, child) {
1357 if(child->flags & COF_OWN_CANVAS) {
1358 area_to_positions(coord_get_area(child), poses + pos_cnt);
1359 pos_cnt += 2;
1360 }
1361 }
1362
1363 cur_area = coord_get_area(coord);
1364 area_to_positions(cur_area, poses + pos_cnt);
1365 pos_cnt += 2;
1366
1367 area_init(cur_area, pos_cnt, poses);
1368
1369 return OK;
1370 }
1371
1372 static int coord_clean_members_n_compute_area(coord_t *coord) {
1373 geo_t *geo;
1374 /*! \note poses is shared by invokings, it is not support reentrying. */
1375 static co_aix (*poses)[2];
1376 static int max_poses = 0;
1377 int cnt, pos_cnt;
1378
1379 /* Clean member shapes. */
1380 cnt = 0;
1381 FORMEMBERS(coord, geo) {
1382 clean_shape(geo->shape);
1383 cnt++;
1384 }
1385
1386 if(max_poses < (cnt * 2)) {
1387 free(poses);
1388 max_poses = cnt * 2;
1389 poses = (co_aix (*)[2])malloc(sizeof(co_aix [2]) * max_poses);
1390 if(poses == NULL)
1391 return ERR;
1392 }
1393
1394 /* Compute area of the coord. */
1395 pos_cnt = 0; 1346 pos_cnt = 0;
1396 FORMEMBERS(coord, geo) { 1347 FORMEMBERS(coord, geo) {
1397 area_to_positions(geo->cur_area, poses + pos_cnt); 1348 area_to_positions(geo->cur_area, poses + pos_cnt);
1398 pos_cnt += 2; 1349 pos_cnt += 2;
1399 } 1350 }
1400 1351
1401 area_init(coord->cur_area, pos_cnt, poses); 1352 area_init(coord_get_area(coord), pos_cnt, poses);
1402 1353
1354 return OK;
1355 }
1356
1357 static int coord_clean_members_n_compute_area(coord_t *coord) {
1358 geo_t *geo;
1359 int r;
1360 /*! \note poses is shared by invokings, it is not support reentrying. */
1361
1362 /* Clean member shapes. */
1363 FORMEMBERS(coord, geo) {
1364 clean_shape(geo->shape);
1365 }
1366
1367 r = compute_area(coord);
1368 if(r != OK)
1369 return ERR;
1370
1403 return OK; 1371 return OK;
1404 } 1372 }
1405 1373
1406 /*! \brief Clean dirty coords. 1374 /*! \brief Clean dirty coords.
1375 *
1376 * This function compute aggregation matrix and area for dirty
1377 * coords. But, aggregation matrix of a cached coord is different from
1378 * normal one. (see compute_aggr_of_cached_coord()).
1407 * 1379 *
1408 * \note coords their opacity != 1 are also traded as cached ones. 1380 * \note coords their opacity != 1 are also traded as cached ones.
1409 */ 1381 */
1410 static int clean_coord(redraw_man_t *rdman, coord_t *coord) { 1382 static int clean_coord(redraw_man_t *rdman, coord_t *coord) {
1411 int r; 1383 int r;
1412 1384
1413 setup_canvas_info(rdman, coord); 1385 setup_canvas_info(rdman, coord);
1414 1386
1415 if(coord->flags & COF_OWN_CANVAS) 1387 compute_aggr(coord);
1416 compute_aggr_of_cached_coord(coord);
1417 else
1418 compute_aggr_of_coord(coord);
1419 1388
1420 /* Areas of cached coords are computed in two phase. 1389 /* Areas of cached coords are computed in two phase.
1421 * Phase 1 works like other normal ones. Phase 2, collects 1390 * Phase 1 works like other normal ones. Phase 2, collects
1422 * all areas of descendants to compute a minimum covering area. 1391 * all areas of descendants to compute a minimum covering area.
1423 * Phase 2 is performed by zeroing_coord(). 1392 * Phase 2 is performed by zeroing_coord().
1424 */ 1393 */
1425 r = coord_clean_members_n_compute_area(coord); 1394 r = coord_clean_members_n_compute_area(coord);
1426 if(r != OK) 1395 if(r != OK)
1427 return ERR; 1396 return ERR;
1428 1397
1429 r = coord_update_area_4_cached_children(coord);
1430 if(r != OK)
1431 return ERR;
1432
1433 coord->flags &= ~COF_DIRTY; 1398 coord->flags &= ~COF_DIRTY;
1434 1399
1435 return OK; 1400 return OK;
1436 } 1401 }
1437 1402
1438 /*! \brief Clean coord_t objects. 1403 /*! \brief Clean coord_t objects.
1439 * 1404 *
1440 * It computes aggregation matrix and area for dirty coords. 1405 * It computes aggregation matrix and area for dirty coords.
1406 *
1407 * This function also responsible for computing area of parent cached
1408 * coord, coord_canvas_info_t::pcache_cur_area, for its cached children.
1441 */ 1409 */
1442 static int clean_rdman_coords(redraw_man_t *rdman) { 1410 static int clean_rdman_coords(redraw_man_t *rdman) {
1443 coord_t *coord; 1411 coord_t *coord, *child;
1444 coord_t **dirty_coords; 1412 coord_t **dirty_coords;
1445 int n_dirty_coords; 1413 int n_dirty_coords;
1446 int i, r; 1414 int i, r;
1447 1415
1448 n_dirty_coords = rdman->dirty_coords.num; 1416 n_dirty_coords = rdman->dirty_coords.num;
1455 if(!(coord->flags & COF_DIRTY)) 1423 if(!(coord->flags & COF_DIRTY))
1456 continue; 1424 continue;
1457 r = clean_coord(rdman, coord); 1425 r = clean_coord(rdman, coord);
1458 if(r != OK) 1426 if(r != OK)
1459 return ERR; 1427 return ERR;
1428 /* TODO: ponstponse adding dirty areas until zeroing.
1429 * Because, aggregated matrix would changed when
1430 * zeroing
1431 */
1460 /* These two steps can be avoided for drawing all. */ 1432 /* These two steps can be avoided for drawing all. */
1461 add_dirty_area(rdman, coord, &coord->areas[0]); 1433 add_dirty_area(rdman, coord, &coord->areas[0]);
1462 add_dirty_area(rdman, coord, &coord->areas[1]); 1434 add_dirty_area(rdman, coord, &coord->areas[1]);
1435
1436 /* Computes coord_canvas_info_t::pcache_cur_area */
1437 FORCHILDREN(coord, child) {
1438 if(coord_get_flags(child, COF_OWN_CANVAS)) {
1439 SWAP(child->canvas_info->pcache_cur_area,
1440 child->canvas_info->pcache_last_area,
1441 area_t *);
1442 compute_pcache_area(child);
1443 add_dirty_area(rdman, coord,
1444 coord_get_pcache_area(child));
1445 add_dirty_area(rdman, coord,
1446 coord_get_pcache_last_area(child));
1447 }
1448 }
1463 } 1449 }
1464 } 1450 }
1465 return OK; 1451 return OK;
1466 } 1452 }
1467 1453
1516 coord_clear_zeroing(coord); 1502 coord_clear_zeroing(coord);
1517 1503
1518 /* 1504 /*
1519 * Compute minimum overing area of sub-graphic 1505 * Compute minimum overing area of sub-graphic
1520 */ 1506 */
1521 area = &coord->canvas_info->owner_mems_area; 1507 area = coord_get_area(coord);
1522 min_x = area->x; 1508 min_x = area->x;
1523 min_y = area->y; 1509 min_y = area->y;
1524 max_x = min_x + area->w; 1510 max_x = min_x + area->w;
1525 max_y = min_y + area->h; 1511 max_y = min_y + area->h;
1526 1512
1566 /* 1552 /*
1567 * Adjust matrics of descendants to align left-top corner of 1553 * Adjust matrics of descendants to align left-top corner of
1568 * minimum covering area with origin of space defined by 1554 * minimum covering area with origin of space defined by
1569 * zeroing coord. 1555 * zeroing coord.
1570 */ 1556 */
1571 saved_area = coord_get_area(coord);
1572 coord->cur_area = &coord->canvas_info->owner_mems_area;
1573 FOR_COORDS_PREORDER(coord, cur) { 1557 FOR_COORDS_PREORDER(coord, cur) {
1558 if(coord_get_flags(cur, COF_OWN_CANVAS) && coord != cur) {
1559 /*
1560 * Cached coords are zeroed from root to leaves, so
1561 * changes of aggr_matrix would be propagated to next
1562 * level of cached.
1563 */
1564 preorder_coord_skip_subtree(cur);
1565 }
1566 /* Shift space */
1574 aggr = coord_get_aggr_matrix(cur); 1567 aggr = coord_get_aggr_matrix(cur);
1575 aggr[3] -= min_x; 1568 aggr[3] -= min_x;
1576 aggr[5] -= min_y; 1569 aggr[5] -= min_y;
1577 if(coord_get_flags(cur, COF_OWN_CANVAS) && coord != cur) { 1570
1578 /* 1571 coord_clean_members_n_compute_area(cur);
1579 * Coords, zeroing, is zeroed in preorder of tree. 1572 }
1580 * So, they are zeroed after ancesters with correctly
1581 * coord_t::aggr_matrix of parent coord to zeroing.
1582 */
1583 preorder_coord_skip_subtree(cur);
1584 #if 0
1585 /* Parent had called coord_clean_members_n_compute_area().
1586 * So, the area of this coord had been recomputed.
1587 */
1588 area = coord_get_area(cur);
1589 area->x -= min_x;
1590 area->y -= min_y;
1591 #endif
1592 } else {
1593 coord_clean_members_n_compute_area(cur);
1594 coord_update_area_4_cached_children(cur);
1595 }
1596 }
1597 coord->cur_area = saved_area;
1598 1573
1599 /* 1574 /*
1600 * Setup canvas 1575 * Setup canvas
1576 *
1577 * Canvas of a cached coord is not setted in
1578 * coord_canvas_info_new(). It should be setted, here.
1601 */ 1579 */
1602 if(canvas == NULL || w > c_w || h > c_w) { 1580 if(canvas == NULL || w > c_w || h > c_w) {
1603 if(canvas) 1581 if(canvas)
1604 canvas_free(canvas); 1582 canvas_free(canvas);
1605 canvas = canvas_new(w, h); 1583 canvas = canvas_new(w, h);
1606 _coord_set_canvas(coord, canvas); 1584 _coord_set_canvas(coord, canvas);
1607 } 1585 }
1608 1586
1609 compute_cached_coord_area(coord); 1587 compute_pcache_area(coord);
1610 1588
1611 /* Since aggregated matrix had been changed to make descendants 1589 /* Since aggregated matrix had been changed to make descendants
1612 * falling on the canvas, size or/and position of all descendants 1590 * falling on the canvas, size or/and position of all descendants
1613 * are chagned, and new canvas was created. So, a dirty area that 1591 * are chagned, and new canvas was created. So, a dirty area that
1614 * covers all space of the canvas is created to force redrawing 1592 * covers all space of the canvas is created to force redrawing
1637 /* Mark all cached ancestral coords of dirty geos */ 1615 /* Mark all cached ancestral coords of dirty geos */
1638 n_dirty_geos = rdman->dirty_geos.num; 1616 n_dirty_geos = rdman->dirty_geos.num;
1639 dirty_geos = rdman->dirty_geos.ds; 1617 dirty_geos = rdman->dirty_geos.ds;
1640 for(i = 0; i < n_dirty_geos; i++) { 1618 for(i = 0; i < n_dirty_geos; i++) {
1641 geo = dirty_geos[i]; 1619 geo = dirty_geos[i];
1642 coord = geo_get_coord(geo)->canvas_info->owner; 1620 coord = coord_get_cached(geo_get_coord(geo));
1643 while(!coord_get_flags(coord, COF_MUST_ZEROING | COF_TEMP_MARK)) { 1621 while(!coord_get_flags(coord, COF_MUST_ZEROING | COF_TEMP_MARK)) {
1644 if(coord_is_root(coord)) 1622 if(coord_is_root(coord))
1645 break; 1623 break;
1646 coord_set_flags(coord, COF_TEMP_MARK); 1624 coord_set_flags(coord, COF_TEMP_MARK);
1647 coord = coord->parent->canvas_info->owner; 1625 coord = coord_get_cached(coord_get_parent(coord));
1648 } 1626 }
1649 } 1627 }
1650 1628
1651 /* Mark all cached ancestral coords of dirty coords */ 1629 /* Mark all cached ancestral coords of dirty coords */
1652 n_dirty_coords = rdman->dirty_coords.num; 1630 n_dirty_coords = rdman->dirty_coords.num;
1653 dirty_coords = rdman->dirty_coords.ds; 1631 dirty_coords = rdman->dirty_coords.ds;
1654 for(i = 0; i < n_dirty_coords; i++) { 1632 for(i = 0; i < n_dirty_coords; i++) {
1655 coord = dirty_coords[i]->canvas_info->owner; 1633 coord = coord_get_cached(dirty_coords[i]);
1656 while(!coord_get_flags(coord, COF_MUST_ZEROING | COF_TEMP_MARK)) { 1634 while(!coord_get_flags(coord, COF_MUST_ZEROING | COF_TEMP_MARK)) {
1657 if(coord_is_root(coord)) 1635 if(coord_is_root(coord))
1658 break; 1636 break;
1659 coord_set_flags(coord, COF_TEMP_MARK); 1637 coord_set_flags(coord, COF_TEMP_MARK);
1660 coord = coord->parent->canvas_info->owner; 1638 coord = coord_get_cached(coord_get_parent(coord));
1661 } 1639 }
1662 } 1640 }
1663 1641
1664 /* Add all marked coords into redraw_man_t::zeroing_coords list */ 1642 /* Add all marked coords into redraw_man_t::zeroing_coords list */
1665 FOR_COORDS_PREORDER(rdman->root_coord, coord) { 1643 FOR_COORDS_PREORDER(rdman->root_coord, coord) {
1686 int i; 1664 int i;
1687 coords_t *all_zeroing; 1665 coords_t *all_zeroing;
1688 coord_t *coord; 1666 coord_t *coord;
1689 1667
1690 all_zeroing = &rdman->zeroing_coords; 1668 all_zeroing = &rdman->zeroing_coords;
1691 for(i = all_zeroing->num - 1; i >= 0; i--) { 1669 for(i = 0; i < all_zeroing->num; i++) {
1692 coord = all_zeroing->ds[i]; 1670 coord = all_zeroing->ds[i];
1693 zeroing_coord(rdman, coord); 1671 zeroing_coord(rdman, coord);
1694 } 1672 }
1695 1673
1696 return OK; 1674 return OK;
1704 */ 1682 */
1705 static void add_aggr_dirty_areas_to_ancestor(redraw_man_t *rdman, 1683 static void add_aggr_dirty_areas_to_ancestor(redraw_man_t *rdman,
1706 coord_t *coord) { 1684 coord_t *coord) {
1707 int i; 1685 int i;
1708 int n_areas; 1686 int n_areas;
1687 int enable_poses1 = 0;
1709 co_aix poses0[2][2], poses1[2][2]; 1688 co_aix poses0[2][2], poses1[2][2];
1710 co_aix reverse[6]; 1689 co_aix reverse[6];
1711 co_aix canvas2pdev_matrix[6]; 1690 co_aix canvas2pdev_matrix[6];
1712 area_t **areas, *area; 1691 area_t **areas, *area;
1713 area_t *area0, *area1; 1692 area_t *area0, *area1;
1716 n_areas = _coord_get_dirty_areas(coord)->num; 1695 n_areas = _coord_get_dirty_areas(coord)->num;
1717 areas = _coord_get_dirty_areas(coord)->ds; 1696 areas = _coord_get_dirty_areas(coord)->ds;
1718 if(n_areas == 0) 1697 if(n_areas == 0)
1719 abort(); /* should not happen! */ 1698 abort(); /* should not happen! */
1720 1699
1721 area0 = coord->canvas_info->aggr_dirty_areas; 1700 area0 = _coord_get_aggr_dirty_areas(coord);
1722 area1 = area0 + 1; 1701 area1 = area0 + 1;
1723 1702
1724 /* TODO: Since both cur & last area of coords are added into dirty 1703 /* TODO: Since both cur & last area of coords are added into dirty
1725 * area list, position of both areas shoud be adjusted for 1704 * area list, position of both areas shoud be adjusted for
1726 * all descendants when zeroing a cached coord. 1705 * all descendants when zeroing a cached coord.
1729 area = areas[i]; 1708 area = areas[i];
1730 if(area->w != 0 || area->h != 0) 1709 if(area->w != 0 || area->h != 0)
1731 break; 1710 break;
1732 } 1711 }
1733 1712
1734 if(i < n_areas) { 1713 if(i >= n_areas)
1735 area = areas[i++]; 1714 return;
1736 poses0[0][0] = area->x; 1715
1737 poses0[0][1] = area->y; 1716 area = areas[i++];
1738 poses0[1][0] = area->x + area->w; 1717 poses0[0][0] = area->x;
1739 poses0[1][1] = area->y + area->h; 1718 poses0[0][1] = area->y;
1740 } else { 1719 poses0[1][0] = area->x + area->w;
1741 poses0[0][0] = 0; 1720 poses0[1][1] = area->y + area->h;
1742 poses0[0][1] = 0;
1743 poses0[1][0] = 0;
1744 poses0[1][1] = 0;
1745 }
1746 1721
1747 if(i < n_areas) { 1722 if(i < n_areas) {
1748 area = areas[i++]; 1723 area = areas[i++];
1749 poses1[0][0] = area->x; 1724 poses1[0][0] = area->x;
1750 poses1[0][1] = area->y; 1725 poses1[0][1] = area->y;
1754 poses1[0][0] = 0; 1729 poses1[0][0] = 0;
1755 poses1[0][1] = 0; 1730 poses1[0][1] = 0;
1756 poses1[1][0] = 0; 1731 poses1[1][0] = 0;
1757 poses1[1][1] = 0; 1732 poses1[1][1] = 0;
1758 } 1733 }
1759 1734
1760 for(; i < n_areas - 1;) { 1735 for(; i < n_areas - 1;) {
1761 /* Even areas */ 1736 /* Even areas */
1762 area = areas[i++]; 1737 area = areas[i++];
1763 if(area->w != 0 || area->h != 0) { 1738 if(area->w != 0 || area->h != 0) {
1764 poses0[0][0] = MB_MIN(poses0[0][0], area->x); 1739 poses0[0][0] = MB_MIN(poses0[0][0], area->x);
1773 poses1[0][1] = MB_MIN(poses1[0][1], area->y); 1748 poses1[0][1] = MB_MIN(poses1[0][1], area->y);
1774 poses1[1][0] = MB_MAX(poses1[1][0], area->x + area->w); 1749 poses1[1][0] = MB_MAX(poses1[1][0], area->x + area->w);
1775 poses1[1][1] = MB_MAX(poses1[1][1], area->y + area->h); 1750 poses1[1][1] = MB_MAX(poses1[1][1], area->y + area->h);
1776 } 1751 }
1777 } 1752 }
1778 1753
1779 if(i < n_areas) { 1754 if(i < n_areas) {
1780 area = areas[i]; 1755 area = areas[i];
1781 if(area->w != 0 || area->h != 0) { 1756 if(area->w != 0 || area->h != 0) {
1782 poses0[0][0] = MB_MIN(poses0[0][0], area->x); 1757 poses0[0][0] = MB_MIN(poses0[0][0], area->x);
1783 poses0[0][1] = MB_MIN(poses0[0][1], area->y); 1758 poses0[0][1] = MB_MIN(poses0[0][1], area->y);
1784 poses0[1][0] = MB_MAX(poses0[1][0], area->x + area->w); 1759 poses0[1][0] = MB_MAX(poses0[1][0], area->x + area->w);
1785 poses0[1][1] = MB_MAX(poses0[1][1], area->y + area->h); 1760 poses0[1][1] = MB_MAX(poses0[1][1], area->y + area->h);
1786 } 1761 }
1787 } 1762 }
1788 1763
1789 parent = coord->parent; 1764 parent = coord_get_parent(coord);
1790 pcached_coord = parent->canvas_info->owner; 1765 pcached_coord = coord_get_cached(parent);
1791 1766
1792 compute_cached_2_pdev_matrix(coord, canvas2pdev_matrix); 1767 compute_cached_2_pdev_matrix(coord, canvas2pdev_matrix);
1793 1768
1794 /* Add dirty areas to parent cached coord. */ 1769 /* Add dirty areas to parent cached coord. */
1795 matrix_trans_pos(canvas2pdev_matrix, poses0[0], poses0[0] + 1); 1770 matrix_trans_pos(canvas2pdev_matrix, poses0[0], poses0[0] + 1);
1796 matrix_trans_pos(canvas2pdev_matrix, poses0[1], poses0[1] + 1); 1771 matrix_trans_pos(canvas2pdev_matrix, poses0[1], poses0[1] + 1);
1797 area_init(area0, 2, poses0); 1772 area_init(area0, 2, poses0);
1798 add_dirty_area(rdman, pcached_coord, area0); 1773 add_dirty_area(rdman, pcached_coord, area0);
1799 1774
1800 matrix_trans_pos(canvas2pdev_matrix, poses1[0], poses1[0] + 1); 1775 matrix_trans_pos(canvas2pdev_matrix, poses1[0], poses1[0] + 1);
1801 matrix_trans_pos(canvas2pdev_matrix, poses1[1], poses1[1] + 1); 1776 matrix_trans_pos(canvas2pdev_matrix, poses1[1], poses1[1] + 1);
1802 area_init(area1, 2, poses1); 1777 area_init(area1, 2, poses1);
1803 if(area1->w != 0 || area1->h != 0) 1778 add_dirty_area(rdman, pcached_coord, area1);
1804 if(area0->x != area1->x || area0->y != area1->y ||
1805 area0->w != area1->w || area0->h != area1->h)
1806 add_dirty_area(rdman, pcached_coord, area1);
1807 1779
1808 if(coord_get_flags(coord, COF_JUST_CLEAN) && 1780 if(coord_get_flags(coord, COF_JUST_CLEAN) &&
1809 !coord_get_flags(pcached_coord, COF_JUST_CLEAN)) 1781 !coord_get_flags(pcached_coord, COF_JUST_CLEAN))
1810 add_dirty_area(rdman, pcached_coord, coord->last_area); 1782 add_dirty_area(rdman, pcached_coord, coord->last_area);
1811 } 1783 }
1820 */ 1792 */
1821 static int add_rdman_aggr_dirty_areas(redraw_man_t *rdman) { 1793 static int add_rdman_aggr_dirty_areas(redraw_man_t *rdman) {
1822 int i; 1794 int i;
1823 int n_zeroing; 1795 int n_zeroing;
1824 coord_t **zeroings; 1796 coord_t **zeroings;
1825 coord_t *coord; 1797 coord_t *coord, *pcached_coord;
1826 1798
1827 n_zeroing = rdman->zeroing_coords.num; 1799 n_zeroing = rdman->zeroing_coords.num;
1828 zeroings = rdman->zeroing_coords.ds; 1800 zeroings = rdman->zeroing_coords.ds;
1829 for(i = n_zeroing - 1; i >= 0; i--) { 1801 for(i = n_zeroing - 1; i >= 0; i--) {
1830 coord = zeroings[i]; 1802 coord = zeroings[i];
1831 if(!coord_is_root(coord)) 1803 pcached_coord = coord_get_cached(coord_get_parent(coord));
1804 if(!coord_is_root(coord) && !coord_is_zeroing(pcached_coord))
1832 add_aggr_dirty_areas_to_ancestor(rdman, coord); 1805 add_aggr_dirty_areas_to_ancestor(rdman, coord);
1833 } 1806 }
1834 1807
1835 return OK; 1808 return OK;
1836 } 1809 }
1864 * 1837 *
1865 * The procedure of clean dirty coords and shapes include 3 major steps. 1838 * The procedure of clean dirty coords and shapes include 3 major steps.
1866 * 1839 *
1867 * - Add dirty coords and shapes to rdman. 1840 * - Add dirty coords and shapes to rdman.
1868 * - All descendants of a dirty coord are also dirty, except 1841 * - All descendants of a dirty coord are also dirty, except
1869 * descent coords and their descendants. 1842 * descendants of cached descendants.
1870 * - Recompute aggregated transformation matrix from root to leaves 1843 * - Recompute aggregated transformation matrix from root to leaves
1871 * for dirty coords. 1844 * for dirty coords.
1872 * - The aggregated transformation matrix for a cached coord is 1845 * - The aggregated transformation matrix for a cached coord is
1873 * different from other coords. 1846 * different from other coords.
1874 * - Compute new area for every dirty coord. 1847 * - Compute new area for every dirty coord.
1875 * - Area of a dirty coord is an aggregation of areas of all members. 1848 * - Area of a dirty coord is an aggregation of areas of all members.
1876 * - A cached coord has two type of areas, one is for members of the cached 1849 * - A cached coord has two type of areas, one is for members of the cached
1877 * coord, another one is for the block that cached coord and descendants 1850 * coord, another one is for the block that cached coord and descendants
1878 * will be mapped in parent cached coord. 1851 * will be mapped in parent cached coord.
1879 * - Areas, for parent cached coord, of non-dirty cached coord 1852 * - Areas, for parent cached coord (pcache_cur_area), of
1880 * would be recomputed when cleaning parent coord. 1853 * non-dirty cached coord would be recomputed when cleaning
1854 * parent coord.
1855 * - Areas, for parent cached coord (pcache_cur_area), of dirty
1856 * cached coord would be recomputed when zeroing the cached
1857 * coord. (because zeroing would change aggregated matrix, and
1858 * zeroing was performed after cleaning)
1881 * - Areas, for members, of dirty cached coord would only be 1859 * - Areas, for members, of dirty cached coord would only be
1882 * recomputed when cleaning the coord. 1860 * recomputed when cleaning the coord.
1861 * - Perform zeroing on some cached coords that
1862 * - dirty, is,
1863 * - dirty descendants, has.
1883 * - Propagate dirty areas to dirty area list of parent cached coord 1864 * - Propagate dirty areas to dirty area list of parent cached coord
1884 * for every cached coords, not only for dirty cached coords. 1865 * for every cached coords, not only for dirty cached coords.
1885 * 1866 *
1886 * The cur_area of a cached coord is where members of the coord will 1867 * The cur_area of a cached coord is where members of the coord will
1887 * be draw in cache buffer, i.e. surface. The area of the cached 1868 * be draw in cache buffer, i.e. surface. The area of the cached
1888 * coord and descendants is described by cached_cur_area and 1869 * coord and descendants is described by pcache_cur_area and
1889 * cached_last_area in coord_canvas_info_t. 1870 * pcache_last_area in coord_canvas_info_t.
1890 */ 1871 */
1891 static int clean_rdman_dirties(redraw_man_t *rdman) { 1872 static int rdman_clean_dirties(redraw_man_t *rdman) {
1892 int r; 1873 int r;
1893 int i; 1874 int i;
1894 coord_t **coords, *coord; 1875 coord_t **coords, *coord;
1895 geo_t **geos; 1876 geo_t **geos;
1896 1877
1899 * by clean_coord(). 1880 * by clean_coord().
1900 */ 1881 */
1901 coords = rdman->dirty_coords.ds; 1882 coords = rdman->dirty_coords.ds;
1902 for(i = 0; i < rdman->dirty_coords.num; i++) { 1883 for(i = 0; i < rdman->dirty_coords.num; i++) {
1903 coord = coords[i]; 1884 coord = coords[i];
1904 if(!coord_get_flags(coord, COF_OWN_CANVAS)) 1885 SWAP(coord->cur_area, coord->last_area, area_t *);
1905 SWAP(coord->cur_area, coord->last_area, area_t *);
1906 else {
1907 coord->last_area = coord->cur_area;
1908 coord->cur_area = &coord->canvas_info->owner_mems_area;
1909 /* coord->cur_area are reseted to another area at
1910 * #RST.
1911 *
1912 * coord->cur_area of a cached coord is aggregated
1913 * area. But, its meaning is changed back to be area
1914 * of members to compute. It can avoid specialized
1915 * code for cached coords to change meaning of
1916 * cur_area temporary when computing area of a cached
1917 * coord.
1918 */
1919 }
1920 } 1886 }
1921 1887
1922 geos = rdman->dirty_geos.ds; 1888 geos = rdman->dirty_geos.ds;
1923 for(i = 0; i < rdman->dirty_geos.num; i++) 1889 for(i = 0; i < rdman->dirty_geos.num; i++)
1924 if(geos[i]->flags & GEF_DIRTY) 1890 if(geos[i]->flags & GEF_DIRTY)
1925 SWAP(geos[i]->cur_area, geos[i]->last_area, area_t *); 1891 SWAP(geos[i]->cur_area, geos[i]->last_area, area_t *);
1926 1892
1927 r = clean_rdman_coords(rdman); 1893 r = clean_rdman_coords(rdman);
1928 if(r != OK) 1894 if(r != OK)
1929 return ERR; 1895 return ERR;
1930 1896
1897 /* Mark COF_JUST_CLEAN */
1931 coords = rdman->dirty_coords.ds; 1898 coords = rdman->dirty_coords.ds;
1932 for(i = 0; i < rdman->dirty_coords.num; i++) { 1899 for(i = 0; i < rdman->dirty_coords.num; i++) {
1933 /* Mark dirty coords COF_JUST_CLEAN to identify coords that 1900 /* Mark dirty coords COF_JUST_CLEAN to identify coords that
1934 * has changed their matrix and respective coordination 1901 * has changed their matrix and respective coordination
1935 * system. It helps zeroing_coord() to avoid fully redrawing 1902 * system. It helps zeroing_coord() to avoid fully redrawing
1936 * all descednants of a cached coord that had not changed its 1903 * all descednants of a cached coord that had not changed its
1937 * matrix. 1904 * matrix.
1938 */ 1905 */
1939 coord = coords[i]; 1906 coord = coords[i];
1940 coord_set_flags(coord, COF_JUST_CLEAN); 1907 coord_set_flags(coord, COF_JUST_CLEAN);
1941 1908 }
1942 /* #RST: reset coord->cur_area, here */ 1909 /* TODO: save area of cached coord and descendants in
1943 coord->cur_area = 1910 * cached_dirty_area for parent cached coord space.
1944 (coord->last_area == coord->areas)? 1911 */
1945 coord->areas + 1: coord->areas;
1946 }
1947 1912
1948 r = clean_rdman_geos(rdman); 1913 r = clean_rdman_geos(rdman);
1949 if(r != OK) 1914 if(r != OK)
1950 return ERR; 1915 return ERR;
1951 1916
2264 int i; 2229 int i;
2265 coord_t *coord, **coords; 2230 coord_t *coord, **coords;
2266 int n_areas; 2231 int n_areas;
2267 area_t **areas; 2232 area_t **areas;
2268 2233
2269 r = clean_rdman_dirties(rdman); 2234 r = rdman_clean_dirties(rdman);
2270 if(r != OK) 2235 if(r != OK)
2271 return ERR; 2236 return ERR;
2272 2237
2273 if(rdman->n_dirty_areas > 0) { 2238 if(rdman->n_dirty_areas > 0) {
2274 /*! \brief Draw shapes in preorder of coord tree and support opacity 2239 /*! \brief Draw shapes in preorder of coord tree and support opacity
2381 } 2346 }
2382 2347
2383 int rdman_force_clean(redraw_man_t *rdman) { 2348 int rdman_force_clean(redraw_man_t *rdman) {
2384 int r; 2349 int r;
2385 2350
2386 r = clean_rdman_dirties(rdman); 2351 r = rdman_clean_dirties(rdman);
2387 2352
2388 return r; 2353 return r;
2389 } 2354 }
2390 2355
2391 /*! \page man_obj Manage Objects. 2356 /*! \page man_obj Manage Objects.