[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 Searchsay hello!
http://imagine-windowslive.com/minisites/searchlaunch/?locale=en-us&FORM=WLMTAG
More information about the cairo
mailing list