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