diff options
| author | Krzysztof Kosi??ski <tweenk.pl@gmail.com> | 2011-07-28 05:04:08 +0000 |
|---|---|---|
| committer | Krzysztof KosiĆski <tweenk.pl@gmail.com> | 2011-07-28 05:04:08 +0000 |
| commit | 905b8a96963f78358abfd109c0c49758c6fe4e9d (patch) | |
| tree | f36eff88e8cc148264f9ea46df7b525c6a9ea80e /src/display/canvas-arena.cpp | |
| parent | Add deferred allocation functionality to DrawingSurface (diff) | |
| download | inkscape-905b8a96963f78358abfd109c0c49758c6fe4e9d.tar.gz inkscape-905b8a96963f78358abfd109c0c49758c6fe4e9d.zip | |
Per-item render cache.
Cache some offscreen data to facilitate smoother navigation.
(bzr r10347.1.20)
Diffstat (limited to 'src/display/canvas-arena.cpp')
| -rw-r--r-- | src/display/canvas-arena.cpp | 125 |
1 files changed, 10 insertions, 115 deletions
diff --git a/src/display/canvas-arena.cpp b/src/display/canvas-arena.cpp index 1d5cfe826..0f653a258 100644 --- a/src/display/canvas-arena.cpp +++ b/src/display/canvas-arena.cpp @@ -33,10 +33,8 @@ static void sp_canvas_arena_destroy(GtkObject *object); static void sp_canvas_arena_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags); static void sp_canvas_arena_render (SPCanvasItem *item, SPCanvasBuf *buf); -static void sp_canvas_arena_render_cache (SPCanvasItem *item, Geom::IntRect const &area); -static void sp_canvas_arena_dirty_cache (SPCanvasArena *arena, NRRectL *area); static double sp_canvas_arena_point (SPCanvasItem *item, Geom::Point p, SPCanvasItem **actual_item); -static void sp_canvas_arena_visible_area_changed (SPCanvasItem *item, Geom::IntRect const &old_area, Geom::IntRect const &new_area); +static void sp_canvas_arena_viewbox_changed (SPCanvasItem *item, Geom::IntRect const &new_area); static gint sp_canvas_arena_event (SPCanvasItem *item, GdkEvent *event); static gint sp_canvas_arena_send_event (SPCanvasArena *arena, GdkEvent *event); @@ -98,7 +96,7 @@ sp_canvas_arena_class_init (SPCanvasArenaClass *klass) item_class->render = sp_canvas_arena_render; item_class->point = sp_canvas_arena_point; item_class->event = sp_canvas_arena_event; - item_class->visible_area_changed = sp_canvas_arena_visible_area_changed; + item_class->viewbox_changed = sp_canvas_arena_viewbox_changed; } static void @@ -110,11 +108,9 @@ sp_canvas_arena_init (SPCanvasArena *arena) arena->arena->canvasarena = arena; arena->root = NRArenaGroup::create(arena->arena); nr_arena_group_set_transparent (NR_ARENA_GROUP (arena->root), TRUE); + nr_arena_item_set_cache(arena->root, true); arena->active = NULL; - arena->cache = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1, 1); - arena->cache_area = Geom::IntRect::from_xywh(0,0,1,1); - arena->dirty = cairo_region_create(); nr_active_object_add_listener ((NRActiveObject *) arena->arena, (NRObjectEventVector *) &carenaev, sizeof (carenaev), arena); } @@ -140,11 +136,6 @@ sp_canvas_arena_destroy (GtkObject *object) nr_object_unref ((NRObject *) arena->arena); arena->arena = NULL; } - if (arena->cache) { - cairo_surface_destroy(arena->cache); - arena->cache = NULL; - } - cairo_region_destroy(arena->dirty); if (GTK_OBJECT_CLASS (parent_class)->destroy) (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); @@ -209,42 +200,8 @@ sp_canvas_arena_render (SPCanvasItem *item, SPCanvasBuf *buf) Geom::OptIntRect r = buf->rect; if (!r || r->hasZeroArea()) return; - - cairo_rectangle_int_t crect; - crect.x = r->left(); - crect.y = r->top(); - crect.width = r->width(); - crect.height = r->height(); - if (cairo_region_contains_rectangle(arena->dirty, &crect) != CAIRO_REGION_OVERLAP_OUT) { - sp_canvas_arena_render_cache(item, *r); - cairo_region_subtract_rectangle(arena->dirty, &crect); - } - - cairo_save(buf->ct); - cairo_translate(buf->ct, -r->left(), -r->top()); - cairo_set_source_surface(buf->ct, arena->cache, arena->cache_area.left(), arena->cache_area.top()); - cairo_paint(buf->ct); - cairo_restore(buf->ct); -} - -static void sp_canvas_arena_render_cache (SPCanvasItem *item, Geom::IntRect const &area) -{ - SPCanvasArena *arena = SP_CANVAS_ARENA (item); - - Geom::OptIntRect r = Geom::intersect(arena->cache_area, area); - if (!r || r->hasZeroArea()) return; // nothing to do - - Inkscape::DrawingSurface cache(arena->cache, arena->cache_area.min()); - Inkscape::DrawingContext ct(cache); - ct.rectangle(area); - ct.clip(); - - { Inkscape::DrawingContext::Save save(ct); - ct.setSource(0,0,0,0); - ct.setOperator(CAIRO_OPERATOR_SOURCE); - ct.paint(); - } + Inkscape::DrawingContext ct(buf->ct, r->min()); nr_arena_item_invoke_update (arena->root, Geom::IntRect::infinite(), &arena->gc, NR_ARENA_ITEM_STATE_BBOX | NR_ARENA_ITEM_STATE_RENDER, @@ -252,17 +209,6 @@ static void sp_canvas_arena_render_cache (SPCanvasItem *item, Geom::IntRect cons nr_arena_item_invoke_render (ct, arena->root, *r, 0); } -static void -sp_canvas_arena_dirty_cache (SPCanvasArena *arena, NRRectL *area) -{ - cairo_rectangle_int_t rect; - rect.x = area->x0; - rect.y = area->y0; - rect.width = area->x1 - area->x0; - rect.height = area->y1 - area->y0; - cairo_region_union_rectangle(arena->dirty, &rect); -} - static double sp_canvas_arena_point (SPCanvasItem *item, Geom::Point p, SPCanvasItem **actual_item) { @@ -285,64 +231,14 @@ sp_canvas_arena_point (SPCanvasItem *item, Geom::Point p, SPCanvasItem **actual_ } static void -sp_canvas_arena_visible_area_changed (SPCanvasItem *item, Geom::IntRect const &old_area, Geom::IntRect const &new_area) +sp_canvas_arena_viewbox_changed (SPCanvasItem *item, Geom::IntRect const &new_area) { SPCanvasArena *arena = SP_CANVAS_ARENA(item); - - cairo_surface_t *new_cache = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, - new_area.width(), new_area.height()); - cairo_t *ct = cairo_create(new_cache); - cairo_set_source_surface(ct, arena->cache, old_area.left() - new_area.left(), old_area.top() - new_area.top()); - cairo_set_operator(ct, CAIRO_OPERATOR_SOURCE); - cairo_paint(ct); - cairo_destroy(ct); - cairo_surface_destroy(arena->cache); - arena->cache = new_cache; - arena->cache_area = new_area; - - cairo_rectangle_int_t crect; - crect.x = new_area.left(); - crect.y = new_area.top(); - crect.width = new_area.width(); - crect.height = new_area.height(); - cairo_region_intersect_rectangle(arena->dirty, &crect); - - // invalidate newly exposed areas - /* - * +----------------------+ - * | top strip | - * +-------+------+-------+ - * | | | | - * | left | old | right | - * | strip | area | strip | - * | | | | - * +-------+------+-------+ - * | bottom strip | - * +----------------------+ - */ - - // top strip - if (new_area.top() < old_area.top()) { - NRRectL top_strip(new_area.left(), new_area.top(), new_area.right(), old_area.top()); - sp_canvas_arena_dirty_cache(arena, &top_strip); - } - // left strip - if (new_area.left() < old_area.left()) { - NRRectL left_strip(new_area.left(), std::max(new_area.top(), old_area.top()), - old_area.left(), std::min(new_area.bottom(), old_area.bottom())); - sp_canvas_arena_dirty_cache(arena, &left_strip); - } - // right strip - if (new_area.right() > old_area.right()) { - NRRectL right_strip(old_area.right(), std::max(new_area.top(), old_area.top()), - new_area.right(), std::min(new_area.bottom(), old_area.bottom())); - sp_canvas_arena_dirty_cache(arena, &right_strip); - } - // bottom strip - if (new_area.bottom() > old_area.bottom()) { - NRRectL bottom_strip(new_area.left(), old_area.bottom(), new_area.right(), new_area.bottom()); - sp_canvas_arena_dirty_cache(arena, &bottom_strip); - } + // make the cache limit larger than screen to facilitate smooth scrolling + Geom::IntRect expanded = new_area; + Geom::IntPoint expansion(new_area.width()/2, new_area.height()/2); + expanded.expandBy(expansion); + nr_arena_set_cache_limit(arena->arena, expanded); } static gint @@ -445,7 +341,6 @@ static void sp_canvas_arena_request_render (NRArena */*arena*/, NRRectL *area, void *data) { if (!area) return; - sp_canvas_arena_dirty_cache (SP_CANVAS_ARENA(data), area); sp_canvas_request_redraw (SP_CANVAS_ITEM (data)->canvas, area->x0, area->y0, area->x1, area->y1); } |
