[cairo] newbie clipping question

David L idht4n at hotmail.com
Sun Oct 15 11:32:05 PDT 2006


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?

Thanks...

            David


// compile lke this:
// g++ -o cairoex `pkg-config --cflags --libs gtk+-2.0` cairoex.cpp
#include <stdio.h>
#include <gtk/gtk.h>

#define DAREA_SIZE (50)

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

void redraw(double *exposeRect)
{
  cairo_t *cr;
  cr = gdk_cairo_create (darea->window);

  if (exposeRect == 0) {
    cairo_rectangle (cr,
                     0.0, 0.0,
                     DAREA_SIZE, DAREA_SIZE);
  } else {
    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 onRedrawTimeout(gpointer data)
{
  redraw(0);
  redrawTimeout = 0;
  return FALSE;
}


gint onDrawingAreaEvent(GtkWidget *item, GdkEvent *event)
{

  //  printf("Saw event: %d %d\n", event->type, event->button.state);


  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;
    redraw(exposeRect);
    return TRUE;
  }

  case GDK_SCROLL: {
    if (event->scroll.direction == GDK_SCROLL_DOWN) {
      zoom *= 1.1;
    } else {
      zoom /= 1.1;
    }
    printf("Zoom = %f\n", zoom);
    if (!redrawTimeout) {
      redrawTimeout = g_timeout_add(50, onRedrawTimeout, 0);
    }
    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_add_events(GTK_WIDGET(darea), GDK_BUTTON_PRESS_MASK );

  gtk_widget_show_all(window);
  gtk_main();

}

_________________________________________________________________
Find a local pizza place, music store, museum and more…then map the best 
route!  http://local.live.com



More information about the cairo mailing list