| #include <gtk/gtk.h> |
| #include <config.h> |
| #include "../test/utils.h" |
| #include "gtk-utils.h" |
| |
| pixman_image_t * |
| pixman_image_from_file (const char *filename, pixman_format_code_t format) |
| { |
| GdkPixbuf *pixbuf; |
| pixman_image_t *image; |
| int width, height; |
| uint32_t *data, *d; |
| uint8_t *gdk_data; |
| int n_channels; |
| int j, i; |
| int stride; |
| |
| if (!(pixbuf = gdk_pixbuf_new_from_file (filename, NULL))) |
| return NULL; |
| |
| image = NULL; |
| |
| width = gdk_pixbuf_get_width (pixbuf); |
| height = gdk_pixbuf_get_height (pixbuf); |
| n_channels = gdk_pixbuf_get_n_channels (pixbuf); |
| gdk_data = gdk_pixbuf_get_pixels (pixbuf); |
| stride = gdk_pixbuf_get_rowstride (pixbuf); |
| |
| if (!(data = malloc (width * height * sizeof (uint32_t)))) |
| goto out; |
| |
| d = data; |
| for (j = 0; j < height; ++j) |
| { |
| uint8_t *gdk_line = gdk_data; |
| |
| for (i = 0; i < width; ++i) |
| { |
| int r, g, b, a; |
| uint32_t pixel; |
| |
| r = gdk_line[0]; |
| g = gdk_line[1]; |
| b = gdk_line[2]; |
| |
| if (n_channels == 4) |
| a = gdk_line[3]; |
| else |
| a = 0xff; |
| |
| r = (r * a + 127) / 255; |
| g = (g * a + 127) / 255; |
| b = (b * a + 127) / 255; |
| |
| pixel = (a << 24) | (r << 16) | (g << 8) | b; |
| |
| *d++ = pixel; |
| gdk_line += n_channels; |
| } |
| |
| gdk_data += stride; |
| } |
| |
| image = pixman_image_create_bits ( |
| format, width, height, data, width * 4); |
| |
| out: |
| g_object_unref (pixbuf); |
| return image; |
| } |
| |
| GdkPixbuf * |
| pixbuf_from_argb32 (uint32_t *bits, |
| int width, |
| int height, |
| int stride) |
| { |
| GdkPixbuf *pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, |
| 8, width, height); |
| int p_stride = gdk_pixbuf_get_rowstride (pixbuf); |
| guint32 *p_bits = (guint32 *)gdk_pixbuf_get_pixels (pixbuf); |
| int i; |
| |
| for (i = 0; i < height; ++i) |
| { |
| uint32_t *src_row = &bits[i * (stride / 4)]; |
| uint32_t *dst_row = p_bits + i * (p_stride / 4); |
| |
| a8r8g8b8_to_rgba_np (dst_row, src_row, width); |
| } |
| |
| return pixbuf; |
| } |
| |
| static gboolean |
| on_expose (GtkWidget *widget, GdkEventExpose *expose, gpointer data) |
| { |
| pixman_image_t *pimage = data; |
| int width = pixman_image_get_width (pimage); |
| int height = pixman_image_get_height (pimage); |
| int stride = pixman_image_get_stride (pimage); |
| cairo_surface_t *cimage; |
| cairo_format_t format; |
| cairo_t *cr; |
| |
| if (pixman_image_get_format (pimage) == PIXMAN_x8r8g8b8) |
| format = CAIRO_FORMAT_RGB24; |
| else |
| format = CAIRO_FORMAT_ARGB32; |
| |
| cimage = cairo_image_surface_create_for_data ( |
| (uint8_t *)pixman_image_get_data (pimage), |
| format, width, height, stride); |
| |
| cr = gdk_cairo_create (widget->window); |
| |
| cairo_rectangle (cr, 0, 0, width, height); |
| cairo_set_source_surface (cr, cimage, 0, 0); |
| cairo_fill (cr); |
| |
| cairo_destroy (cr); |
| cairo_surface_destroy (cimage); |
| |
| return TRUE; |
| } |
| |
| void |
| show_image (pixman_image_t *image) |
| { |
| GtkWidget *window; |
| int width, height; |
| int argc; |
| char **argv; |
| char *arg0 = g_strdup ("pixman-test-program"); |
| pixman_format_code_t format; |
| pixman_image_t *copy; |
| |
| argc = 1; |
| argv = (char **)&arg0; |
| |
| gtk_init (&argc, &argv); |
| |
| window = gtk_window_new (GTK_WINDOW_TOPLEVEL); |
| width = pixman_image_get_width (image); |
| height = pixman_image_get_height (image); |
| |
| gtk_window_set_default_size (GTK_WINDOW (window), width, height); |
| |
| format = pixman_image_get_format (image); |
| |
| /* We always display the image as if it contains sRGB data. That |
| * means that no conversion should take place when the image |
| * has the a8r8g8b8_sRGB format. |
| */ |
| switch (format) |
| { |
| case PIXMAN_a8r8g8b8_sRGB: |
| case PIXMAN_a8r8g8b8: |
| case PIXMAN_x8r8g8b8: |
| copy = pixman_image_ref (image); |
| break; |
| |
| default: |
| copy = pixman_image_create_bits (PIXMAN_a8r8g8b8, |
| width, height, NULL, -1); |
| pixman_image_composite32 (PIXMAN_OP_SRC, |
| image, NULL, copy, |
| 0, 0, 0, 0, 0, 0, |
| width, height); |
| break; |
| } |
| |
| g_signal_connect (window, "expose_event", G_CALLBACK (on_expose), copy); |
| g_signal_connect (window, "delete_event", G_CALLBACK (gtk_main_quit), NULL); |
| |
| gtk_widget_show (window); |
| |
| gtk_main (); |
| } |