diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2009-07-27 18:20:22 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2009-07-27 18:23:11 +0100 |
commit | 2da01ed552d48808cdf3aa7798ddfb959d016f0f (patch) | |
tree | bb46f2c408e93b5e1f0cc0e70969967d62d802f0 /src/cairo-rtree.c | |
parent | 9f6a0f5668601c74886378d6cdb9588621d30e6d (diff) | |
download | cairo-2da01ed552d48808cdf3aa7798ddfb959d016f0f.tar.gz |
[rtree] Merge the common unpin_and_evict_unused() routine
Having written the same method to prune glyphs from the rtree three times,
I thought wise to add the common method to the core routines.
Diffstat (limited to 'src/cairo-rtree.c')
-rw-r--r-- | src/cairo-rtree.c | 50 |
1 files changed, 48 insertions, 2 deletions
diff --git a/src/cairo-rtree.c b/src/cairo-rtree.c index c0dfe3130..ba142b7ac 100644 --- a/src/cairo-rtree.c +++ b/src/cairo-rtree.c @@ -56,6 +56,7 @@ _cairo_rtree_node_create (cairo_rtree_t *rtree, node->children[0] = NULL; node->parent = parent; + node->owner = NULL; node->state = CAIRO_RTREE_NODE_AVAILABLE; node->pinned = FALSE; node->x = x; @@ -76,6 +77,8 @@ _cairo_rtree_node_destroy (cairo_rtree_t *rtree, cairo_rtree_node_t *node) cairo_list_del (&node->link); if (node->state == CAIRO_RTREE_NODE_OCCUPIED) { + if (node->owner != NULL) + *node->owner = NULL; if (rtree->evict != NULL) rtree->evict (node); } else { @@ -235,6 +238,8 @@ _cairo_rtree_evict_random (cairo_rtree_t *rtree, { if (node->width >= width && node->height >= height && cnt-- == 0) { if (node->state == CAIRO_RTREE_NODE_OCCUPIED) { + if (node->owner != NULL) + *node->owner = NULL; if (rtree->evict != NULL) rtree->evict (node); } else { @@ -274,12 +279,49 @@ void _cairo_rtree_unpin (cairo_rtree_t *rtree) { cairo_rtree_node_t *node, *next; + cairo_list_t can_collapse; + + if (cairo_list_is_empty (&rtree->pinned)) + return; + + cairo_list_init (&can_collapse); cairo_list_foreach_entry_safe (node, next, - cairo_rtree_node_t, &rtree->pinned, link) + cairo_rtree_node_t, + &rtree->pinned, + link) { node->pinned = FALSE; - cairo_list_move (&node->link, &rtree->evictable); + if (node->state == CAIRO_RTREE_NODE_OCCUPIED && node->owner == NULL) { + cairo_bool_t all_available; + int i; + + node->state = CAIRO_RTREE_NODE_AVAILABLE; + cairo_list_move (&node->link, &rtree->available); + + all_available = TRUE; + node = node->parent; + for (i = 0; i < 4 && node->children[i] != NULL && all_available; i++) + all_available &= node->children[i]->state == CAIRO_RTREE_NODE_AVAILABLE; + + if (all_available) { + cairo_list_move (&node->link, &can_collapse); + for (i = 0; i < 4 && node->children[i] != NULL; i++) + cairo_list_del (&node->children[i]->link); + } + } + else + { + cairo_list_move (&node->link, &rtree->evictable); + } + } + + cairo_list_foreach_entry_safe (node, next, + cairo_rtree_node_t, + &can_collapse, + link) + { + _cairo_rtree_node_collapse (rtree, node); } } @@ -315,6 +357,8 @@ _cairo_rtree_reset (cairo_rtree_t *rtree) int i; if (rtree->root.state == CAIRO_RTREE_NODE_OCCUPIED) { + if (rtree->root.owner != NULL) + *rtree->root.owner = NULL; if (rtree->evict != NULL) rtree->evict (&rtree->root); } else { @@ -338,6 +382,8 @@ _cairo_rtree_fini (cairo_rtree_t *rtree) int i; if (rtree->root.state == CAIRO_RTREE_NODE_OCCUPIED) { + if (rtree->root.owner != NULL) + *rtree->root.owner = NULL; if (rtree->evict != NULL) rtree->evict (&rtree->root); } else { |