summaryrefslogtreecommitdiffstats
path: root/src/display/canvas-arena.cpp
diff options
context:
space:
mode:
authorKrzysztof Kosi??ski <tweenk.pl@gmail.com>2011-07-28 05:04:08 +0000
committerKrzysztof KosiƄski <tweenk.pl@gmail.com>2011-07-28 05:04:08 +0000
commit905b8a96963f78358abfd109c0c49758c6fe4e9d (patch)
treef36eff88e8cc148264f9ea46df7b525c6a9ea80e /src/display/canvas-arena.cpp
parentAdd deferred allocation functionality to DrawingSurface (diff)
downloadinkscape-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.cpp125
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);
}