[cairo] Scrolling/Panning Demo -- howto increase speed

Peter Groves pdgroves at gmail.com
Sat Dec 11 10:04:18 PST 2010

On Sat, 11 Dec 2010 17:20:33 +0100
Stefan Salewski <mail at ssalewski.de> wrote:

> I have written a small test application, which draws some graphics
> into a GTK drawing area. It supports zooming, scrolling and panning:
>  http://www.ssalewski.de/PetEd-Demo.html.en
> As expected scrolling and panning is not really fast, because I always
> redraw the whole content of the drawing area. For simple graphics this
> is ok, but for more complicated stuff (electronics schematics editor)
> it is not really nice.
> Is there an not too complicated way to increase performance? 
> Maybe copying part of the picture contents and redrawing only the
> changed area? (First I intended to always draw to a large buffer area
> and to copy only the visible zoomed in rectangle to the GTK drawing
> area. That would make panning really fast, but may introduce overhead
> for other operations.)

I have recently spent some time implementing custom scrolling with
cairo (and not using gtk's), and I found drawing to a large buffer
and then copying the visible portion not to work very well. It seems
(and I could be misinterpreting what I observed) that even an offscreen
very large cairo image surface is very slow to manipulate or copy from.
It seems very large single images need to be avoided even if they are

How my scrolling works now:

Let's call a single element I want to draw a 'glyph'. Each glyph has a
bounding box and an 'isVisible' flag. When I scroll there is a new
visible bounding box, so I recompute which elements are visible. When
the redraw happens, I use Cairo.translate to move the drawing
operations to the corner of the visible area in the scroll window. I
then draw all the visible glyphs. The glyphs can draw where they
believe they will be if they were on one large image and will end up in
the right place b/c of the tranlate operation. You can also have them
draw on a buffer the same size as the scroll window so you don't end up
with a big slow buffer. 

Another nice feature of cairo to use is that if you create a small
drawing surface and cache the drawing of a glyph on it, the background
is transparent by default and you can just copy the buffered image onto
the gtk drawing area and don't need to worry about the background of
the buffer overlapping with other drawing areas. So when you combine
this with the visible area trick above, you just have a small surface
for every glyph and their coordinates of the upper left corner, and
when you do a redraw you just translate the cairo context and copy all
the glyph-buffers that are visible onto your drawing area.

I know this may seem like overkill, but I really did implement the
solution you proposed and it worked but got very sluggish on large

hope that helps,

> Maybe smarter demos are available -- I was not able to find one, so I
> wrote it from scratch.
> Best regards
> Stefan Salewski
> --
> cairo mailing list
> cairo at cairographics.org
> http://lists.cairographics.org/mailman/listinfo/cairo

More information about the cairo mailing list