[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
>case.
>
>(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;
  gdk_window_invalidate_rect(darea->window,
                             &rect,
                             FALSE);
  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!

         David

#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],
                   exposeRect[3]);


  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_close_path(cr);
  cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
  cairo_fill(cr);

  /* 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_stroke(cr);

  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;
    onExpose(exposeRect);
    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);

  gtk_widget_show_all(window);
  gtk_main();
}

_________________________________________________________________
The next generation of Search—say hello!  
http://imagine-windowslive.com/minisites/searchlaunch/?locale=en-us&FORM=WLMTAG



More information about the cairo mailing list