1 #include <gtk/gtk.h> 2 #include <config.h> 3 #include "../test/utils.h" 4 #include "gtk-utils.h" 5 6 pixman_image_t * 7 pixman_image_from_file (const char *filename, pixman_format_code_t format) 8 { 9 GdkPixbuf *pixbuf; 10 pixman_image_t *image; 11 int width, height; 12 uint32_t *data, *d; 13 uint8_t *gdk_data; 14 int n_channels; 15 int j, i; 16 int stride; 17 18 if (!(pixbuf = gdk_pixbuf_new_from_file (filename, NULL))) 19 return NULL; 20 21 image = NULL; 22 23 width = gdk_pixbuf_get_width (pixbuf); 24 height = gdk_pixbuf_get_height (pixbuf); 25 n_channels = gdk_pixbuf_get_n_channels (pixbuf); 26 gdk_data = gdk_pixbuf_get_pixels (pixbuf); 27 stride = gdk_pixbuf_get_rowstride (pixbuf); 28 29 if (!(data = malloc (width * height * sizeof (uint32_t)))) 30 goto out; 31 32 d = data; 33 for (j = 0; j < height; ++j) 34 { 35 uint8_t *gdk_line = gdk_data; 36 37 for (i = 0; i < width; ++i) 38 { 39 int r, g, b, a; 40 uint32_t pixel; 41 42 r = gdk_line[0]; 43 g = gdk_line[1]; 44 b = gdk_line[2]; 45 46 if (n_channels == 4) 47 a = gdk_line[3]; 48 else 49 a = 0xff; 50 51 r = (r * a + 127) / 255; 52 g = (g * a + 127) / 255; 53 b = (b * a + 127) / 255; 54 55 pixel = (a << 24) | (r << 16) | (g << 8) | b; 56 57 *d++ = pixel; 58 gdk_line += n_channels; 59 } 60 61 gdk_data += stride; 62 } 63 64 image = pixman_image_create_bits ( 65 format, width, height, data, width * 4); 66 67 out: 68 g_object_unref (pixbuf); 69 return image; 70 } 71 72 GdkPixbuf * 73 pixbuf_from_argb32 (uint32_t *bits, 74 int width, 75 int height, 76 int stride) 77 { 78 GdkPixbuf *pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 79 8, width, height); 80 int p_stride = gdk_pixbuf_get_rowstride (pixbuf); 81 guint32 *p_bits = (guint32 *)gdk_pixbuf_get_pixels (pixbuf); 82 int i; 83 84 for (i = 0; i < height; ++i) 85 { 86 uint32_t *src_row = &bits[i * (stride / 4)]; 87 uint32_t *dst_row = p_bits + i * (p_stride / 4); 88 89 a8r8g8b8_to_rgba_np (dst_row, src_row, width); 90 } 91 92 return pixbuf; 93 } 94 95 static gboolean 96 on_expose (GtkWidget *widget, GdkEventExpose *expose, gpointer data) 97 { 98 pixman_image_t *pimage = data; 99 int width = pixman_image_get_width (pimage); 100 int height = pixman_image_get_height (pimage); 101 int stride = pixman_image_get_stride (pimage); 102 cairo_surface_t *cimage; 103 cairo_format_t format; 104 cairo_t *cr; 105 106 if (pixman_image_get_format (pimage) == PIXMAN_x8r8g8b8) 107 format = CAIRO_FORMAT_RGB24; 108 else 109 format = CAIRO_FORMAT_ARGB32; 110 111 cimage = cairo_image_surface_create_for_data ( 112 (uint8_t *)pixman_image_get_data (pimage), 113 format, width, height, stride); 114 115 cr = gdk_cairo_create (widget->window); 116 117 cairo_rectangle (cr, 0, 0, width, height); 118 cairo_set_source_surface (cr, cimage, 0, 0); 119 cairo_fill (cr); 120 121 cairo_destroy (cr); 122 cairo_surface_destroy (cimage); 123 124 return TRUE; 125 } 126 127 void 128 show_image (pixman_image_t *image) 129 { 130 GtkWidget *window; 131 int width, height; 132 int argc; 133 char **argv; 134 char *arg0 = g_strdup ("pixman-test-program"); 135 pixman_format_code_t format; 136 pixman_image_t *copy; 137 138 argc = 1; 139 argv = (char **)&arg0; 140 141 gtk_init (&argc, &argv); 142 143 window = gtk_window_new (GTK_WINDOW_TOPLEVEL); 144 width = pixman_image_get_width (image); 145 height = pixman_image_get_height (image); 146 147 gtk_window_set_default_size (GTK_WINDOW (window), width, height); 148 149 format = pixman_image_get_format (image); 150 151 /* We always display the image as if it contains sRGB data. That 152 * means that no conversion should take place when the image 153 * has the a8r8g8b8_sRGB format. 154 */ 155 switch (format) 156 { 157 case PIXMAN_a8r8g8b8_sRGB: 158 case PIXMAN_a8r8g8b8: 159 case PIXMAN_x8r8g8b8: 160 copy = pixman_image_ref (image); 161 break; 162 163 default: 164 copy = pixman_image_create_bits (PIXMAN_a8r8g8b8, 165 width, height, NULL, -1); 166 pixman_image_composite32 (PIXMAN_OP_SRC, 167 image, NULL, copy, 168 0, 0, 0, 0, 0, 0, 169 width, height); 170 break; 171 } 172 173 g_signal_connect (window, "expose_event", G_CALLBACK (on_expose), copy); 174 g_signal_connect (window, "delete_event", G_CALLBACK (gtk_main_quit), NULL); 175 176 gtk_widget_show (window); 177 178 gtk_main (); 179 } 180