/* * Compile with: * cc `pkg-config --cflags --libs gtk+-3.0` bug.c -o bug */ #include #include void dump (cairo_surface_t *surface, char *path) { if (cairo_surface_write_to_png (surface, path) == CAIRO_STATUS_WRITE_ERROR) printf ("error writing to %s\n", path); } void draw_checkerboard (cairo_surface_t *surface) { cairo_t *cr; int i, j; cr = cairo_create (surface); cairo_set_source_rgb (cr, 0, 0, 0); cairo_rectangle (cr, 0, 0, 10, 10); cairo_fill (cr); cairo_set_source_rgb (cr, 1, 1, 1); for (i = 0; i < 10; ++i) for (j = 0; j < 10; ++j) if ((i % 2) == (j % 2)) { cairo_rectangle (cr, i, j, 1, 1); cairo_fill (cr); } cairo_destroy (cr); } void draw (cairo_t *cr) { cairo_surface_t *surface, *pat_surface; cairo_pattern_t *pattern; cairo_matrix_t _matrix; cairo_matrix_t *matrix = &_matrix; surface = cairo_get_target (cr); surface = cairo_surface_create_similar (surface, CAIRO_CONTENT_COLOR, 10, 10); draw_checkerboard (surface); pat_surface = cairo_surface_create_for_rectangle (surface, 0, 0, 2, 2); cairo_matrix_init_identity (matrix); cairo_matrix_scale (matrix, 1 / 50., 1 / 50.); pattern = cairo_pattern_create_for_surface (pat_surface); cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD); cairo_pattern_set_matrix (pattern, matrix); cairo_set_source (cr, pattern); cairo_rectangle (cr, 0, 0, 100, 100); cairo_fill (cr); cairo_pattern_destroy (pattern); cairo_surface_destroy (pat_surface); cairo_surface_destroy (surface); } void image (char *path) { cairo_surface_t *surface = NULL; cairo_t *cr = NULL; surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, 100, 100); cr = cairo_create (surface); draw (cr); dump (surface, path); cairo_destroy (cr); cairo_surface_destroy (surface); } gboolean window_draw (GtkWidget *widget, cairo_t *cr, gpointer path) { draw (cr); dump (cairo_get_target (cr), (char *)path); g_idle_add ((GSourceFunc)gtk_main_quit, NULL); return FALSE; } void xlib (char *path) { GtkWidget *window = NULL; gtk_init (NULL, NULL); window = gtk_window_new (GTK_WINDOW_POPUP); gtk_widget_set_size_request (window, 100, 100); g_signal_connect (G_OBJECT (window), "draw", G_CALLBACK (window_draw), path); gtk_widget_show (window); gtk_main (); gtk_widget_destroy (window); } void usage (char *s) { printf ("usage: %s \n", s); exit (1); } int main (int argc, char **argv) { if (argc != 3) usage (argv[0]); if (g_str_equal (argv[1], "image")) image (argv[2]); else if (g_str_equal (argv[1], "xlib")) xlib (argv[2]); else usage (argv[0]); return 0; }