[cairo] newbie clipping question

David L idht4n at hotmail.com
Sun Oct 15 17:07:37 PDT 2006

>On Sun, 2006-10-15 at 11:32 -0700, David L wrote:
> > I'm writing a gtk+ app with cairo that has a zoom function.
> > When I zoom way in on the cairo drawing area, the redraws
> > become extremely slow.  There's an example application below
> > that demonstrates my problem.  It draws a line from (0,0) to
> > (10*zoom, 10*zoom), where zoom is variable and controled
> > by the mouse wheel.  When the zoom level is high (most of
> > the line is outside the clipping rectangle), redraws are really
> > slow and my whole X-windows environment is not very responsive.
> >
> > Am I doing something wrong, or is it just not possible to have
> > the clipping rectangle be a very small fraction of the drawn
> > image?
>I think things will be much better if you confine yourself
>to drawing in your expose handler. GTK+ will provide cairo
>with a good idea of what it needs to draw and doesn't in that
>(See gdk_window_invalidate_rect() for how to trigger exposes
>on application content changes.)
Thanks for the feedback... I tried changing the redraw function
to look like this:

gint onRedrawTimeout(gpointer data)
  GdkRectangle rect;
  rect.x = 0;
  rect.y = 0;
  rect.width = DAREA_SIZE;
  rect.height = DAREA_SIZE;
  redrawTimeout = 0;
  return FALSE;

It still seems much slower than I would have expected.

>Still, cairo isn't very smart about clipping out geometry
>early the rendering pipeline ... I'd expect big lines to be
>OK, but big curves or complex geometry are going to be slow.

Even a single straight line seems very slow in my example
for a zoom level of ~3200.  In fact, the example below takes
about 30 seconds just to draw a single straight line on my
Pentium D 2.80GHz.  I haven't yet installed the proprietary
driver for my ATI graphics card yet, but 30 seconds still
seems pretty slow to draw one line!


#include <stdio.h>
#include <gtk/gtk.h>
#include <sys/time.h>

#define DAREA_SIZE (50)

GtkWidget *darea;
double zoom = 3200.0;
int redrawTimeout;

void onExpose(double *exposeRect)

  cairo_t *cr;
  cr = gdk_cairo_create (darea->window);

  cairo_rectangle (cr,
                   exposeRect[0], exposeRect[1], exposeRect[2],

  cairo_clip (cr);

  /* draw white background */
  cairo_move_to(cr, 0.0, 0.0);
  cairo_line_to(cr, DAREA_SIZE, 0.0);
  cairo_line_to(cr, DAREA_SIZE, DAREA_SIZE);
  cairo_line_to(cr, 0.0, DAREA_SIZE);
  cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);

  /* draw line at currrent zoom level */
  cairo_move_to(cr, 0.0, 0.0);
  cairo_line_to(cr, 10*zoom, 10*zoom);
  cairo_set_source_rgb(cr, 1.0, 0.0, 0.0);

  cairo_destroy (cr);

gint onDrawingAreaEvent(GtkWidget *item, GdkEvent *event)
  switch (event->type) {
  case GDK_EXPOSE: {
    double exposeRect[4];
    exposeRect[0] = event->expose.area.x;
    exposeRect[1] = event->expose.area.y;
    exposeRect[2] = event->expose.area.width;
    exposeRect[3] = event->expose.area.height;
    return TRUE;

int main(int argc, char *argv[])
  gtk_init(&argc, &argv);

  GtkWidget *window;
  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  GtkWidget *vbox;
  vbox = gtk_vbox_new(FALSE, 0);
  gtk_container_add (GTK_CONTAINER(window), vbox);

  darea = gtk_drawing_area_new();

  gtk_box_pack_start(GTK_BOX(vbox), darea, TRUE, TRUE, 0);
  gtk_widget_set_size_request (GTK_WIDGET (darea), DAREA_SIZE, DAREA_SIZE);

  gtk_signal_connect(GTK_OBJECT(darea), "event", 
GTK_SIGNAL_FUNC(onDrawingAreaEvent), 0);


The next generation of Search—say hello!  

More information about the cairo mailing list