1 /* -*- Mode: C; c-basic-offset: 2; -*- */
2 /* GdkPixbuf library - test loaders
3  *
4  * Copyright (C) 2014 Red Hat, Inc.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include "gdk-pixbuf/gdk-pixbuf.h"
21 #include "test-common.h"
22 #include <string.h>
23 
24 #ifdef G_OS_UNIX
25 #include <fcntl.h>
26 #include <sys/mman.h>
27 #include <unistd.h>
28 #endif
29 
30 #ifdef G_OS_UNIX
31 
32 typedef struct {
33   void *buf;
34   gsize len;
35 } MappedBuf;
36 
37 static void
destroy_buf_unmap(gpointer data)38 destroy_buf_unmap (gpointer data)
39 {
40   MappedBuf *buf = data;
41   int r;
42 
43   r = munmap (buf->buf, buf->len);
44   g_assert_cmpint (r, ==, 0);
45   g_free (buf);
46 }
47 #endif
48 
49 static GdkPixbuf *
get_readonly_pixbuf(void)50 get_readonly_pixbuf (void)
51 {
52   GdkPixbuf *reference;
53   GdkPixbuf *result;
54   GBytes *bytes;
55   GError *error = NULL;
56 
57   reference = gdk_pixbuf_new_from_file (g_test_get_filename (G_TEST_DIST, "test-image.png", NULL), &error);
58   g_assert_no_error (error);
59 
60 #ifdef G_OS_UNIX
61   {
62     MappedBuf *buf;
63     int pagesize;
64     int pages;
65     int r;
66     int zero_fd;
67     gsize pixlen;
68 
69     pagesize = sysconf (_SC_PAGESIZE);
70     g_assert_cmpint (pagesize, >, 0);
71 
72     pixlen = gdk_pixbuf_get_byte_length (reference);
73     pages = pixlen / pagesize + 1;
74 
75     buf = g_new0 (MappedBuf, 1);
76     buf->len = pages * pagesize;
77     zero_fd = open("/dev/zero", O_RDWR);
78     g_assert(zero_fd != -1);
79     buf->buf = mmap (NULL, buf->len, PROT_READ | PROT_WRITE, MAP_PRIVATE, zero_fd, 0);
80     g_assert (buf->buf != NULL);
81     close(zero_fd);
82 
83     memcpy (buf->buf, gdk_pixbuf_get_pixels (reference), pixlen);
84 
85     r = mprotect (buf->buf, buf->len, PROT_READ);
86     g_assert_cmpint (r, ==, 0);
87 
88     bytes = g_bytes_new_with_free_func (buf->buf, buf->len, destroy_buf_unmap, buf);
89   }
90 #else
91   bytes = g_bytes_new (gdk_pixbuf_get_pixels (reference), gdk_pixbuf_get_byte_length (reference));
92 #endif
93 
94   result = gdk_pixbuf_new_from_bytes (bytes,
95 				      gdk_pixbuf_get_colorspace (reference),
96 				      gdk_pixbuf_get_has_alpha (reference),
97 				      gdk_pixbuf_get_bits_per_sample (reference),
98 				      gdk_pixbuf_get_width (reference),
99 				      gdk_pixbuf_get_height (reference),
100 				      gdk_pixbuf_get_rowstride (reference));
101   g_object_unref (reference);
102   g_bytes_unref (bytes);
103 
104   return result;
105 }
106 
107 static void
test_mutate_readonly(void)108 test_mutate_readonly (void)
109 {
110   GdkPixbuf *src;
111   GdkPixbuf *dest;
112 
113   if (!format_supported ("png"))
114     {
115       g_test_skip ("format not supported");
116       return;
117     }
118 
119   src = get_readonly_pixbuf ();
120   gdk_pixbuf_scale (src, src,
121 		    0, 0,
122 		    gdk_pixbuf_get_width (src) / 4,
123 		    gdk_pixbuf_get_height (src) / 4,
124 		    0, 0, 0.5, 0.5,
125 		    GDK_INTERP_NEAREST);
126   g_object_unref (src);
127 
128   src = get_readonly_pixbuf ();
129 
130   dest = gdk_pixbuf_scale_simple (src,
131 				  gdk_pixbuf_get_width (src) / 4,
132 				  gdk_pixbuf_get_height (src) / 4,
133 				  GDK_INTERP_NEAREST);
134   g_object_unref (dest);
135 
136   dest = gdk_pixbuf_composite_color_simple (src,
137 					    gdk_pixbuf_get_width (src) / 4,
138 					    gdk_pixbuf_get_height (src) / 4,
139 					    GDK_INTERP_NEAREST,
140 					    128,
141 					    8,
142 					    G_MAXUINT32,
143 					    G_MAXUINT32/2);
144   g_object_unref (dest);
145 
146   dest = gdk_pixbuf_rotate_simple (src, 180);
147   g_object_unref (dest);
148 
149   dest = gdk_pixbuf_flip (src, TRUE);
150   g_object_unref (dest);
151   dest = gdk_pixbuf_flip (src, FALSE);
152   g_object_unref (dest);
153 
154   g_object_unref (src);
155 }
156 
157 static void
test_read_pixel_bytes(void)158 test_read_pixel_bytes (void)
159 {
160   GdkPixbuf *src;
161   GBytes *bytes;
162 
163   if (!format_supported ("png"))
164     {
165       g_test_skip ("format not supported");
166       return;
167     }
168 
169   src = get_readonly_pixbuf ();
170   bytes = gdk_pixbuf_read_pixel_bytes (src);
171   g_object_unref (src);
172   g_bytes_unref (bytes);
173 
174   src = get_readonly_pixbuf ();
175   /* Force a mutable conversion */
176   (void) gdk_pixbuf_get_pixels (src);
177   bytes = gdk_pixbuf_read_pixel_bytes (src);
178   g_object_unref (src);
179   g_bytes_unref (bytes);
180 }
181 
182 int
main(int argc,char ** argv)183 main (int argc, char **argv)
184 {
185   g_test_init (&argc, &argv, NULL);
186 
187   g_test_add_func ("/pixbuf/readonly/mutate", test_mutate_readonly);
188   g_test_add_func ("/pixbuf/readonly/readpixelbytes", test_read_pixel_bytes);
189 
190   return g_test_run ();
191 }
192