[cairo] Slow painting of images

Haakon Riiser haakon.riiser at fys.uio.no
Wed Oct 26 05:12:26 PDT 2005


I've recently started experimenting with the Cairo library, and I
think I'm doing something wrong.  I'm trying to display some PNG
images, and although it works, it is _extremely_ slow.  Take a look
at the test program shown below (btw, it is based on some sample code
I found in the cairo-demo package).  At first I thought it was slow
because the PNG image is reloaded every time the picture is drawn,
but I tried moving the loading of the PNG image away so that it was
only done once, and it didn't appear to make things faster.  Thanks
in advance for any help!

/* ------------------------------------------------------------------------ */
#include <stdio.h>
#include <stdlib.h>
#include <cairo.h>
#include <cairo-xlib.h>

typedef struct win {
        Display *dpy;
        int scr;

        Window win;
        GC gc;

        int width, height;
        KeyCode quit_code;
} win_t;

static void win_init(win_t *win);
static void win_draw(win_t *win);
static void win_handle_events(win_t *win);

int
main(int argc, char *argv[])
{
        win_t win;

        win.dpy = XOpenDisplay(0);
        if (win.dpy == NULL) {
                fprintf(stderr, "failed to open display\n");
                return 1;
        }

        win_init(&win);
        win_handle_events(&win);
        XDestroyWindow(win.dpy, win.win);
        XCloseDisplay(win.dpy);

	return 0;
}

static void
win_init(win_t *win)
{
        Window root;

        win->width = 800;
        win->height = 800;

        root = DefaultRootWindow(win->dpy);
        win->scr = DefaultScreen(win->dpy);
        win->win = XCreateSimpleWindow(win->dpy, root, 0, 0,
                                       win->width, win->height, 0,
                                       BlackPixel(win->dpy, win->scr),
                                       BlackPixel(win->dpy, win->scr));
        win->quit_code = XKeysymToKeycode(win->dpy, XStringToKeysym("Q"));
        XSelectInput(win->dpy, win->win, KeyPressMask |
                                         StructureNotifyMask |
                                         ExposureMask);
        XMapWindow(win->dpy, win->win);
}

Visual *visual;
cairo_t *cr;
cairo_surface_t *surface;
cairo_surface_t *surface_xlib;

static void
win_draw(win_t *win)
{
        int w, h;

        visual = DefaultVisual(win->dpy, DefaultScreen(win->dpy));
        XClearWindow(win->dpy, win->win);
        surface_xlib = cairo_xlib_surface_create(win->dpy, win->win, visual,
                                                 win->width, win->height);

        cr = cairo_create(surface_xlib);
        surface = cairo_image_surface_create_from_png("image.png");

        w = cairo_image_surface_get_width(surface);
        h = cairo_image_surface_get_height(surface);

        cairo_scale(cr, (double) win->width / w, (double) win->height / h);
        cairo_set_source_surface(cr, surface, 0, 0);
        cairo_paint(cr);

        if (cairo_status(cr)) {
                printf("Cairo is unhappy: %s\n",
                       cairo_status_to_string (cairo_status (cr)));
                exit(0);
        }

        cairo_surface_destroy(surface);
        cairo_destroy(cr);
}

static void
win_handle_events(win_t *win)
{
        XEvent xev;

        for (;;) {
                XNextEvent(win->dpy, &xev);
                switch(xev.type) {
                case KeyPress:
                        {
                                XKeyEvent *kev = &xev.xkey;

                                if (kev->keycode == win->quit_code) {
                                        return;
                                }
                                break;
                        }
                case ConfigureNotify:
                        {
                                XConfigureEvent *cev = &xev.xconfigure;

                                win->width = cev->width;
                                win->height = cev->height;
                                break;
                        }
                case Expose:
                        {
                                XExposeEvent *eev = &xev.xexpose;

                                if (eev->count == 0)
                                        win_draw(win);
                                break;
                        }
                }
        }
}
/* ------------------------------------------------------------------------ */

-- 
 Haakon


More information about the cairo mailing list