16ba797d6Smrg#include <gtk/gtk.h> 214b11b2bSmrg#ifdef HAVE_CONFIG_H 314b11b2bSmrg#include <pixman-config.h> 414b11b2bSmrg#endif 514b11b2bSmrg#include "utils.h" 66ba797d6Smrg#include "gtk-utils.h" 76ba797d6Smrg 8f4f78bb6Smrgpixman_image_t * 9f4f78bb6Smrgpixman_image_from_file (const char *filename, pixman_format_code_t format) 10f4f78bb6Smrg{ 11f4f78bb6Smrg GdkPixbuf *pixbuf; 12f4f78bb6Smrg pixman_image_t *image; 13f4f78bb6Smrg int width, height; 14f4f78bb6Smrg uint32_t *data, *d; 15f4f78bb6Smrg uint8_t *gdk_data; 16f4f78bb6Smrg int n_channels; 17f4f78bb6Smrg int j, i; 18f4f78bb6Smrg int stride; 19f4f78bb6Smrg 20f4f78bb6Smrg if (!(pixbuf = gdk_pixbuf_new_from_file (filename, NULL))) 21f4f78bb6Smrg return NULL; 22f4f78bb6Smrg 23f4f78bb6Smrg image = NULL; 24f4f78bb6Smrg 25f4f78bb6Smrg width = gdk_pixbuf_get_width (pixbuf); 26f4f78bb6Smrg height = gdk_pixbuf_get_height (pixbuf); 27f4f78bb6Smrg n_channels = gdk_pixbuf_get_n_channels (pixbuf); 28f4f78bb6Smrg gdk_data = gdk_pixbuf_get_pixels (pixbuf); 29f4f78bb6Smrg stride = gdk_pixbuf_get_rowstride (pixbuf); 30f4f78bb6Smrg 31f4f78bb6Smrg if (!(data = malloc (width * height * sizeof (uint32_t)))) 32f4f78bb6Smrg goto out; 33f4f78bb6Smrg 34f4f78bb6Smrg d = data; 35f4f78bb6Smrg for (j = 0; j < height; ++j) 36f4f78bb6Smrg { 37f4f78bb6Smrg uint8_t *gdk_line = gdk_data; 38f4f78bb6Smrg 39f4f78bb6Smrg for (i = 0; i < width; ++i) 40f4f78bb6Smrg { 41f4f78bb6Smrg int r, g, b, a; 42f4f78bb6Smrg uint32_t pixel; 43f4f78bb6Smrg 44f4f78bb6Smrg r = gdk_line[0]; 45f4f78bb6Smrg g = gdk_line[1]; 46f4f78bb6Smrg b = gdk_line[2]; 47f4f78bb6Smrg 48f4f78bb6Smrg if (n_channels == 4) 49f4f78bb6Smrg a = gdk_line[3]; 50f4f78bb6Smrg else 51f4f78bb6Smrg a = 0xff; 52f4f78bb6Smrg 53f4f78bb6Smrg r = (r * a + 127) / 255; 54f4f78bb6Smrg g = (g * a + 127) / 255; 55f4f78bb6Smrg b = (b * a + 127) / 255; 56f4f78bb6Smrg 57f4f78bb6Smrg pixel = (a << 24) | (r << 16) | (g << 8) | b; 58f4f78bb6Smrg 59f4f78bb6Smrg *d++ = pixel; 60f4f78bb6Smrg gdk_line += n_channels; 61f4f78bb6Smrg } 62f4f78bb6Smrg 63f4f78bb6Smrg gdk_data += stride; 64f4f78bb6Smrg } 65f4f78bb6Smrg 66f4f78bb6Smrg image = pixman_image_create_bits ( 67f4f78bb6Smrg format, width, height, data, width * 4); 68f4f78bb6Smrg 69f4f78bb6Smrgout: 70f4f78bb6Smrg g_object_unref (pixbuf); 71f4f78bb6Smrg return image; 72f4f78bb6Smrg} 73f4f78bb6Smrg 746ba797d6SmrgGdkPixbuf * 756ba797d6Smrgpixbuf_from_argb32 (uint32_t *bits, 766ba797d6Smrg int width, 776ba797d6Smrg int height, 786ba797d6Smrg int stride) 796ba797d6Smrg{ 806ba797d6Smrg GdkPixbuf *pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 816ba797d6Smrg 8, width, height); 826ba797d6Smrg int p_stride = gdk_pixbuf_get_rowstride (pixbuf); 836ba797d6Smrg guint32 *p_bits = (guint32 *)gdk_pixbuf_get_pixels (pixbuf); 849ad247e8Sjmcneill int i; 856ba797d6Smrg 869ad247e8Sjmcneill for (i = 0; i < height; ++i) 879ad247e8Sjmcneill { 889ad247e8Sjmcneill uint32_t *src_row = &bits[i * (stride / 4)]; 899ad247e8Sjmcneill uint32_t *dst_row = p_bits + i * (p_stride / 4); 906ba797d6Smrg 919ad247e8Sjmcneill a8r8g8b8_to_rgba_np (dst_row, src_row, width); 926ba797d6Smrg } 939ad247e8Sjmcneill 946ba797d6Smrg return pixbuf; 956ba797d6Smrg} 966ba797d6Smrg 976ba797d6Smrgstatic gboolean 9814b11b2bSmrgon_draw (GtkWidget *widget, cairo_t *cr, gpointer user_data) 996ba797d6Smrg{ 10014b11b2bSmrg pixman_image_t *pimage = user_data; 101f4f78bb6Smrg int width = pixman_image_get_width (pimage); 102f4f78bb6Smrg int height = pixman_image_get_height (pimage); 103f4f78bb6Smrg int stride = pixman_image_get_stride (pimage); 104f4f78bb6Smrg cairo_surface_t *cimage; 105f4f78bb6Smrg cairo_format_t format; 106f4f78bb6Smrg 107f4f78bb6Smrg if (pixman_image_get_format (pimage) == PIXMAN_x8r8g8b8) 108f4f78bb6Smrg format = CAIRO_FORMAT_RGB24; 109f4f78bb6Smrg else 110f4f78bb6Smrg format = CAIRO_FORMAT_ARGB32; 111f4f78bb6Smrg 112f4f78bb6Smrg cimage = cairo_image_surface_create_for_data ( 113f4f78bb6Smrg (uint8_t *)pixman_image_get_data (pimage), 114f4f78bb6Smrg format, width, height, stride); 115f4f78bb6Smrg 116f4f78bb6Smrg cairo_rectangle (cr, 0, 0, width, height); 117f4f78bb6Smrg cairo_set_source_surface (cr, cimage, 0, 0); 118f4f78bb6Smrg cairo_fill (cr); 119f4f78bb6Smrg 120f4f78bb6Smrg cairo_surface_destroy (cimage); 1216ba797d6Smrg 1226ba797d6Smrg return TRUE; 1236ba797d6Smrg} 1246ba797d6Smrg 1256ba797d6Smrgvoid 1266ba797d6Smrgshow_image (pixman_image_t *image) 1276ba797d6Smrg{ 1286ba797d6Smrg GtkWidget *window; 1299ad247e8Sjmcneill int width, height; 1306ba797d6Smrg int argc; 1316ba797d6Smrg char **argv; 1326ba797d6Smrg char *arg0 = g_strdup ("pixman-test-program"); 1336ba797d6Smrg pixman_format_code_t format; 1349ad247e8Sjmcneill pixman_image_t *copy; 1356ba797d6Smrg 1366ba797d6Smrg argc = 1; 1376ba797d6Smrg argv = (char **)&arg0; 1386ba797d6Smrg 1396ba797d6Smrg gtk_init (&argc, &argv); 1406ba797d6Smrg 1416ba797d6Smrg window = gtk_window_new (GTK_WINDOW_TOPLEVEL); 1426ba797d6Smrg width = pixman_image_get_width (image); 1436ba797d6Smrg height = pixman_image_get_height (image); 1446ba797d6Smrg 1456ba797d6Smrg gtk_window_set_default_size (GTK_WINDOW (window), width, height); 1469ad247e8Sjmcneill 1479ad247e8Sjmcneill format = pixman_image_get_format (image); 1489ad247e8Sjmcneill 149f4f78bb6Smrg /* We always display the image as if it contains sRGB data. That 150f4f78bb6Smrg * means that no conversion should take place when the image 151f4f78bb6Smrg * has the a8r8g8b8_sRGB format. 1529ad247e8Sjmcneill */ 1539ad247e8Sjmcneill switch (format) 1549ad247e8Sjmcneill { 1559ad247e8Sjmcneill case PIXMAN_a8r8g8b8_sRGB: 1569ad247e8Sjmcneill case PIXMAN_a8r8g8b8: 157f4f78bb6Smrg case PIXMAN_x8r8g8b8: 1589ad247e8Sjmcneill copy = pixman_image_ref (image); 1599ad247e8Sjmcneill break; 1609ad247e8Sjmcneill 1619ad247e8Sjmcneill default: 1629ad247e8Sjmcneill copy = pixman_image_create_bits (PIXMAN_a8r8g8b8, 1639ad247e8Sjmcneill width, height, NULL, -1); 1649ad247e8Sjmcneill pixman_image_composite32 (PIXMAN_OP_SRC, 1659ad247e8Sjmcneill image, NULL, copy, 1669ad247e8Sjmcneill 0, 0, 0, 0, 0, 0, 1679ad247e8Sjmcneill width, height); 1689ad247e8Sjmcneill break; 1699ad247e8Sjmcneill } 1709ad247e8Sjmcneill 17114b11b2bSmrg g_signal_connect (window, "draw", G_CALLBACK (on_draw), copy); 1726ba797d6Smrg g_signal_connect (window, "delete_event", G_CALLBACK (gtk_main_quit), NULL); 1736ba797d6Smrg 1746ba797d6Smrg gtk_widget_show (window); 1756ba797d6Smrg 1766ba797d6Smrg gtk_main (); 1776ba797d6Smrg} 178