/* gcc `pkg-config --cflags --libs cairo-xlib` -o slice slice.c * * Test case demonstrating cairo bug #10508: * * Transformed image source surfaces sometimes misrender to xlib surface target * https://bugs.freedesktop.org/show_bug.cgi?id=10508 * * This test case draws a transformed image to a window by continually * drawing the image over and over in single-pixel columns. The * results should be a static image showing four quadrants of * different colors, (with expected fading on the edges). * * The bug manifests itself by vertical mis-colored lines that appear * to sweep across the image as it redraws. The bug is intermittent, * but making your X server busy, (by, say, moving a window around), * appears to make it occur more regularly. */ #include #include #include #include #include #include #include /* for Region */ static void expose (Display *dpy, Window window, int window_width, int window_height, cairo_surface_t *image, int extents_x, int extents_y, int extents_width, int extents_height) { Pixmap pixmap; cairo_surface_t *backing; cairo_t *cr; cairo_matrix_t matrix; cairo_pattern_t *pattern; XGCValues gcv; GC gc; gcv.function = GXcopy; gcv.foreground = WhitePixel (dpy, DefaultScreen (dpy)); gc = XCreateGC (dpy, window, GCFunction | GCForeground, &gcv); pixmap = XCreatePixmap (dpy, window, extents_width, extents_height, DefaultDepth (dpy, DefaultScreen (dpy))); /* Clear background to white. */ XFillRectangle (dpy, pixmap, gc, 0, 0, extents_width, extents_height); backing = cairo_xlib_surface_create (dpy, pixmap, DefaultVisual (dpy, DefaultScreen (dpy)), extents_width, extents_height); cr = cairo_create (backing); /* Draw the scaled image surface */ cairo_translate (cr, - extents_x, - extents_y); cairo_scale (cr, 20, 20); pattern = cairo_pattern_create_for_surface (image); cairo_matrix_init_translate (&matrix, - 0.5, - 0.5); cairo_pattern_set_matrix (pattern, &matrix); cairo_set_source (cr, pattern); cairo_identity_matrix (cr); cairo_paint (cr); cairo_pattern_destroy (pattern); cairo_destroy (cr); cairo_surface_destroy (backing); XCopyArea (dpy, pixmap, window, gc, 0, 0, extents_width, extents_height, extents_x, extents_y); XFreePixmap (dpy, pixmap); XFreeGC (dpy, gc); } int main (void) { Display *dpy; Window root, window; int screen; int window_width = 100, window_height = 100; cairo_surface_t *source; KeyCode quit_code; XEvent xev; int i; #define SOURCE_SIZE 4 static uint32_t data[SOURCE_SIZE * SOURCE_SIZE] = { 0xffffffff, 0xffffffff, 0xffff0000, 0xffff0000, 0xffffffff, 0xffffffff, 0xffff0000, 0xffff0000, 0xff00ff00, 0xff00ff00, 0xff0000ff, 0xff0000ff, 0xff00ff00, 0xff00ff00, 0xff0000ff, 0xff0000ff }; source = cairo_image_surface_create_for_data ((unsigned char *) data, CAIRO_FORMAT_RGB24, SOURCE_SIZE, SOURCE_SIZE, SOURCE_SIZE * 4); dpy = XOpenDisplay(0); if (dpy == NULL) { fprintf(stderr, "Failed to open display\n"); return 1; } XSynchronize (dpy, 1); root = DefaultRootWindow(dpy); screen = DefaultScreen(dpy); window = XCreateSimpleWindow(dpy, root, 0, 0, window_width, window_height, 0, BlackPixel(dpy, screen), BlackPixel(dpy, screen)); quit_code = XKeysymToKeycode(dpy, XStringToKeysym("Q")); XSelectInput(dpy, window, KeyPressMask |ExposureMask |ButtonPressMask); XMapWindow(dpy, window); /* Wait for first expose xev. */ XWindowEvent(dpy, window, ExposureMask, &xev); /* Draw to demonstrate bug. */ expose (dpy, window, window_width, window_height, source, 0, 0, 100, 100); while (1) { for (i = 0; i < 100; i ++) { /* Quit on any key/button press to exit */ if (XCheckWindowEvent(dpy, window, KeyPressMask|ButtonPressMask, &xev)) goto DONE; expose (dpy, window, window_width, window_height, source, i, 0, 1, 100); usleep (10000); } } DONE: cairo_surface_destroy (source); XCloseDisplay (dpy); cairo_debug_reset_static_data (); return 0; }