1 | /* -*- mode: C; c-file-style: "linux" -*- */ |
---|
2 | /* GdkPixbuf library - Main loading interface. |
---|
3 | * |
---|
4 | * Copyright (C) 1999 The Free Software Foundation |
---|
5 | * |
---|
6 | * Authors: Miguel de Icaza <miguel@gnu.org> |
---|
7 | * Federico Mena-Quintero <federico@gimp.org> |
---|
8 | * |
---|
9 | * This library is free software; you can redistribute it and/or |
---|
10 | * modify it under the terms of the GNU Lesser General Public |
---|
11 | * License as published by the Free Software Foundation; either |
---|
12 | * version 2 of the License, or (at your option) any later version. |
---|
13 | * |
---|
14 | * This library is distributed in the hope that it will be useful, |
---|
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
17 | * Lesser General Public License for more details. |
---|
18 | * |
---|
19 | * You should have received a copy of the GNU Lesser General Public |
---|
20 | * License along with this library; if not, write to the |
---|
21 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
---|
22 | * Boston, MA 02111-1307, USA. |
---|
23 | */ |
---|
24 | |
---|
25 | #include <config.h> |
---|
26 | #include <stdlib.h> |
---|
27 | #include <stdio.h> |
---|
28 | #include <string.h> |
---|
29 | #include <glib.h> |
---|
30 | #include <errno.h> |
---|
31 | #include "gdk-pixbuf-private.h" |
---|
32 | #include "gdk-pixbuf-io.h" |
---|
33 | |
---|
34 | #ifdef G_OS_WIN32 |
---|
35 | #define STRICT |
---|
36 | #include <windows.h> |
---|
37 | #undef STRICT |
---|
38 | #endif |
---|
39 | |
---|
40 | static gint |
---|
41 | format_check (GdkPixbufModule *module, guchar *buffer, int size) |
---|
42 | { |
---|
43 | int j; |
---|
44 | gchar m; |
---|
45 | GdkPixbufModulePattern *pattern; |
---|
46 | |
---|
47 | for (pattern = module->info->signature; pattern->prefix; pattern++) { |
---|
48 | for (j = 0; j < size && pattern->prefix[j] != 0; j++) { |
---|
49 | m = pattern->mask ? pattern->mask[j] : ' '; |
---|
50 | if (m == ' ') { |
---|
51 | if (buffer[j] != pattern->prefix[j]) |
---|
52 | break; |
---|
53 | } |
---|
54 | else if (m == '!') { |
---|
55 | if (buffer[j] == pattern->prefix[j]) |
---|
56 | break; |
---|
57 | } |
---|
58 | else if (m == 'z') { |
---|
59 | if (buffer[j] != 0) |
---|
60 | break; |
---|
61 | } |
---|
62 | else if (m == 'n') { |
---|
63 | if (buffer[j] == 0) |
---|
64 | break; |
---|
65 | } |
---|
66 | } |
---|
67 | if (pattern->prefix[j] == 0) |
---|
68 | return pattern->relevance; |
---|
69 | } |
---|
70 | return 0; |
---|
71 | } |
---|
72 | |
---|
73 | static GSList *file_formats = NULL; |
---|
74 | |
---|
75 | static void gdk_pixbuf_io_init (); |
---|
76 | |
---|
77 | static GSList * |
---|
78 | get_file_formats () |
---|
79 | { |
---|
80 | if (file_formats == NULL) |
---|
81 | gdk_pixbuf_io_init (); |
---|
82 | |
---|
83 | return file_formats; |
---|
84 | } |
---|
85 | |
---|
86 | |
---|
87 | #ifdef USE_GMODULE |
---|
88 | |
---|
89 | static gboolean |
---|
90 | scan_string (const char **pos, GString *out) |
---|
91 | { |
---|
92 | const char *p = *pos, *q = *pos; |
---|
93 | char *tmp, *tmp2; |
---|
94 | gboolean quoted; |
---|
95 | |
---|
96 | while (g_ascii_isspace (*p)) |
---|
97 | p++; |
---|
98 | |
---|
99 | if (!*p) |
---|
100 | return FALSE; |
---|
101 | else if (*p == '"') { |
---|
102 | p++; |
---|
103 | quoted = FALSE; |
---|
104 | for (q = p; (*q != '"') || quoted; q++) { |
---|
105 | if (!*q) |
---|
106 | return FALSE; |
---|
107 | quoted = (*q == '\\') && !quoted; |
---|
108 | } |
---|
109 | |
---|
110 | tmp = g_strndup (p, q - p); |
---|
111 | tmp2 = g_strcompress (tmp); |
---|
112 | g_string_truncate (out, 0); |
---|
113 | g_string_append (out, tmp2); |
---|
114 | g_free (tmp); |
---|
115 | g_free (tmp2); |
---|
116 | } |
---|
117 | |
---|
118 | q++; |
---|
119 | *pos = q; |
---|
120 | |
---|
121 | return TRUE; |
---|
122 | } |
---|
123 | |
---|
124 | static gboolean |
---|
125 | scan_int (const char **pos, int *out) |
---|
126 | { |
---|
127 | int i = 0; |
---|
128 | char buf[32]; |
---|
129 | const char *p = *pos; |
---|
130 | |
---|
131 | while (g_ascii_isspace (*p)) |
---|
132 | p++; |
---|
133 | |
---|
134 | if (*p < '0' || *p > '9') |
---|
135 | return FALSE; |
---|
136 | |
---|
137 | while ((*p >= '0') && (*p <= '9') && i < sizeof (buf)) { |
---|
138 | buf[i] = *p; |
---|
139 | i++; |
---|
140 | p++; |
---|
141 | } |
---|
142 | |
---|
143 | if (i == sizeof (buf)) |
---|
144 | return FALSE; |
---|
145 | else |
---|
146 | buf[i] = '\0'; |
---|
147 | |
---|
148 | *out = atoi (buf); |
---|
149 | |
---|
150 | *pos = p; |
---|
151 | |
---|
152 | return TRUE; |
---|
153 | } |
---|
154 | |
---|
155 | static gboolean |
---|
156 | skip_space (const char **pos) |
---|
157 | { |
---|
158 | const char *p = *pos; |
---|
159 | |
---|
160 | while (g_ascii_isspace (*p)) |
---|
161 | p++; |
---|
162 | |
---|
163 | *pos = p; |
---|
164 | |
---|
165 | return !(*p == '\0'); |
---|
166 | } |
---|
167 | |
---|
168 | #ifdef G_OS_WIN32 |
---|
169 | |
---|
170 | /* DllMain function needed to tuck away the gdk-pixbuf DLL name */ |
---|
171 | G_WIN32_DLLMAIN_FOR_DLL_NAME (static, dll_name) |
---|
172 | |
---|
173 | static char * |
---|
174 | get_toplevel (void) |
---|
175 | { |
---|
176 | static char *toplevel = NULL; |
---|
177 | |
---|
178 | if (toplevel == NULL) |
---|
179 | toplevel = g_win32_get_package_installation_subdirectory |
---|
180 | (GETTEXT_PACKAGE, dll_name, ""); |
---|
181 | |
---|
182 | return toplevel; |
---|
183 | } |
---|
184 | |
---|
185 | static char * |
---|
186 | get_sysconfdir (void) |
---|
187 | { |
---|
188 | static char *sysconfdir = NULL; |
---|
189 | |
---|
190 | if (sysconfdir == NULL) |
---|
191 | sysconfdir = g_win32_get_package_installation_subdirectory |
---|
192 | (GETTEXT_PACKAGE, dll_name, "etc"); |
---|
193 | |
---|
194 | return sysconfdir; |
---|
195 | } |
---|
196 | |
---|
197 | #undef GTK_SYSCONFDIR |
---|
198 | #define GTK_SYSCONFDIR get_sysconfdir() |
---|
199 | |
---|
200 | static void |
---|
201 | correct_prefix (gchar **path) |
---|
202 | { |
---|
203 | if (strncmp (*path, PREFIX "/", strlen (PREFIX "/")) == 0 || |
---|
204 | strncmp (*path, PREFIX "\\", strlen (PREFIX "\\")) == 0) |
---|
205 | { |
---|
206 | /* This is an entry put there by gdk-pixbuf-query-loaders on the |
---|
207 | * packager's system. On Windows a prebuilt GTK+ package can be |
---|
208 | * installed in a random location. The gdk-pixbuf.loaders file |
---|
209 | * distributed in such a package contains paths from the package |
---|
210 | * builder's machine. Replace the build-time prefix with the |
---|
211 | * installation prefix on this machine. |
---|
212 | */ |
---|
213 | gchar *tem = *path; |
---|
214 | *path = g_strconcat (get_toplevel (), tem + strlen (PREFIX), NULL); |
---|
215 | g_free (tem); |
---|
216 | } |
---|
217 | } |
---|
218 | |
---|
219 | #endif |
---|
220 | |
---|
221 | static gchar * |
---|
222 | gdk_pixbuf_get_module_file (void) |
---|
223 | { |
---|
224 | gchar *result = g_strdup (g_getenv ("GDK_PIXBUF_MODULE_FILE")); |
---|
225 | |
---|
226 | if (!result) |
---|
227 | result = g_build_filename (GTK_SYSCONFDIR, "gtk-2.0", "gdk-pixbuf.loaders", NULL); |
---|
228 | |
---|
229 | return result; |
---|
230 | } |
---|
231 | |
---|
232 | static void |
---|
233 | gdk_pixbuf_io_init () |
---|
234 | { |
---|
235 | GIOChannel *channel; |
---|
236 | gchar *line_buf; |
---|
237 | gsize term; |
---|
238 | GString *tmp_buf = g_string_new (NULL); |
---|
239 | gboolean have_error = FALSE; |
---|
240 | GdkPixbufModule *module = NULL; |
---|
241 | gchar *filename = gdk_pixbuf_get_module_file (); |
---|
242 | int flags; |
---|
243 | int n_patterns = 0; |
---|
244 | GdkPixbufModulePattern *pattern; |
---|
245 | GError *error = NULL; |
---|
246 | |
---|
247 | channel = g_io_channel_new_file (filename, "r", &error); |
---|
248 | if (!channel) { |
---|
249 | g_warning ("Can not open pixbuf loader module file '%s': %s", |
---|
250 | filename, error->message); |
---|
251 | return; |
---|
252 | } |
---|
253 | |
---|
254 | while (!have_error && g_io_channel_read_line (channel, &line_buf, NULL, &term, NULL) == G_IO_STATUS_NORMAL) { |
---|
255 | const char *p; |
---|
256 | |
---|
257 | p = line_buf; |
---|
258 | |
---|
259 | line_buf[term] = 0; |
---|
260 | |
---|
261 | if (!skip_space (&p)) { |
---|
262 | /* Blank line marking the end of a module |
---|
263 | */ |
---|
264 | if (module && *p != '#') { |
---|
265 | #ifdef G_OS_WIN32 |
---|
266 | correct_prefix (&module->module_path); |
---|
267 | #endif |
---|
268 | file_formats = g_slist_prepend (file_formats, module); |
---|
269 | module = NULL; |
---|
270 | } |
---|
271 | |
---|
272 | goto next_line; |
---|
273 | } |
---|
274 | |
---|
275 | if (*p == '#') |
---|
276 | goto next_line; |
---|
277 | |
---|
278 | if (!module) { |
---|
279 | /* Read a module location |
---|
280 | */ |
---|
281 | module = g_new0 (GdkPixbufModule, 1); |
---|
282 | n_patterns = 0; |
---|
283 | |
---|
284 | if (!scan_string (&p, tmp_buf)) { |
---|
285 | g_warning ("Error parsing loader info in '%s'\n %s", |
---|
286 | filename, line_buf); |
---|
287 | have_error = TRUE; |
---|
288 | } |
---|
289 | module->module_path = g_strdup (tmp_buf->str); |
---|
290 | } |
---|
291 | else if (!module->module_name) { |
---|
292 | module->info = g_new0 (GdkPixbufFormat, 1); |
---|
293 | if (!scan_string (&p, tmp_buf)) { |
---|
294 | g_warning ("Error parsing loader info in '%s'\n %s", |
---|
295 | filename, line_buf); |
---|
296 | have_error = TRUE; |
---|
297 | } |
---|
298 | module->info->name = g_strdup (tmp_buf->str); |
---|
299 | module->module_name = module->info->name; |
---|
300 | |
---|
301 | if (!scan_int (&p, &flags)) { |
---|
302 | g_warning ("Error parsing loader info in '%s'\n %s", |
---|
303 | filename, line_buf); |
---|
304 | have_error = TRUE; |
---|
305 | } |
---|
306 | module->info->flags = flags; |
---|
307 | |
---|
308 | if (!scan_string (&p, tmp_buf)) { |
---|
309 | g_warning ("Error parsing loader info in '%s'\n %s", |
---|
310 | filename, line_buf); |
---|
311 | have_error = TRUE; |
---|
312 | } |
---|
313 | if (tmp_buf->str[0] != 0) |
---|
314 | module->info->domain = g_strdup (tmp_buf->str); |
---|
315 | |
---|
316 | if (!scan_string (&p, tmp_buf)) { |
---|
317 | g_warning ("Error parsing loader info in '%s'\n %s", |
---|
318 | filename, line_buf); |
---|
319 | have_error = TRUE; |
---|
320 | } |
---|
321 | module->info->description = g_strdup (tmp_buf->str); |
---|
322 | } |
---|
323 | else if (!module->info->mime_types) { |
---|
324 | int n = 1; |
---|
325 | module->info->mime_types = g_new0 (gchar*, 1); |
---|
326 | while (scan_string (&p, tmp_buf)) { |
---|
327 | if (tmp_buf->str[0] != 0) { |
---|
328 | module->info->mime_types = |
---|
329 | g_realloc (module->info->mime_types, (n + 1) * sizeof (gchar*)); |
---|
330 | module->info->mime_types[n - 1] = g_strdup (tmp_buf->str); |
---|
331 | module->info->mime_types[n] = 0; |
---|
332 | n++; |
---|
333 | } |
---|
334 | } |
---|
335 | } |
---|
336 | else if (!module->info->extensions) { |
---|
337 | int n = 1; |
---|
338 | module->info->extensions = g_new0 (gchar*, 1); |
---|
339 | while (scan_string (&p, tmp_buf)) { |
---|
340 | if (tmp_buf->str[0] != 0) { |
---|
341 | module->info->extensions = |
---|
342 | g_realloc (module->info->extensions, (n + 1) * sizeof (gchar*)); |
---|
343 | module->info->extensions[n - 1] = g_strdup (tmp_buf->str); |
---|
344 | module->info->extensions[n] = 0; |
---|
345 | n++; |
---|
346 | } |
---|
347 | } |
---|
348 | } |
---|
349 | else { |
---|
350 | n_patterns++; |
---|
351 | module->info->signature = (GdkPixbufModulePattern *) |
---|
352 | g_realloc (module->info->signature, (n_patterns + 1) * sizeof (GdkPixbufModulePattern)); |
---|
353 | pattern = module->info->signature + n_patterns; |
---|
354 | pattern->prefix = NULL; |
---|
355 | pattern->mask = NULL; |
---|
356 | pattern->relevance = 0; |
---|
357 | pattern--; |
---|
358 | if (!scan_string (&p, tmp_buf)) |
---|
359 | goto context_error; |
---|
360 | pattern->prefix = g_strdup (tmp_buf->str); |
---|
361 | |
---|
362 | if (!scan_string (&p, tmp_buf)) |
---|
363 | goto context_error; |
---|
364 | if (*tmp_buf->str) |
---|
365 | pattern->mask = g_strdup (tmp_buf->str); |
---|
366 | else |
---|
367 | pattern->mask = NULL; |
---|
368 | |
---|
369 | if (!scan_int (&p, &pattern->relevance)) |
---|
370 | goto context_error; |
---|
371 | |
---|
372 | goto next_line; |
---|
373 | |
---|
374 | context_error: |
---|
375 | g_free (pattern->prefix); |
---|
376 | g_free (pattern->mask); |
---|
377 | g_free (pattern); |
---|
378 | g_warning ("Error parsing loader info in '%s'\n %s", |
---|
379 | filename, line_buf); |
---|
380 | have_error = TRUE; |
---|
381 | } |
---|
382 | next_line: |
---|
383 | g_free (line_buf); |
---|
384 | } |
---|
385 | g_string_free (tmp_buf, TRUE); |
---|
386 | g_io_channel_unref (channel); |
---|
387 | g_free (filename); |
---|
388 | } |
---|
389 | |
---|
390 | /* actually load the image handler - gdk_pixbuf_get_module only get a */ |
---|
391 | /* reference to the module to load, it doesn't actually load it */ |
---|
392 | /* perhaps these actions should be combined in one function */ |
---|
393 | gboolean |
---|
394 | _gdk_pixbuf_load_module (GdkPixbufModule *image_module, |
---|
395 | GError **error) |
---|
396 | { |
---|
397 | char *path; |
---|
398 | GModule *module; |
---|
399 | gpointer sym; |
---|
400 | |
---|
401 | g_return_val_if_fail (image_module->module == NULL, FALSE); |
---|
402 | |
---|
403 | path = image_module->module_path; |
---|
404 | module = g_module_open (path, G_MODULE_BIND_LAZY); |
---|
405 | |
---|
406 | if (!module) { |
---|
407 | g_set_error (error, |
---|
408 | GDK_PIXBUF_ERROR, |
---|
409 | GDK_PIXBUF_ERROR_FAILED, |
---|
410 | _("Unable to load image-loading module: %s: %s"), |
---|
411 | path, g_module_error ()); |
---|
412 | return FALSE; |
---|
413 | } |
---|
414 | |
---|
415 | image_module->module = module; |
---|
416 | |
---|
417 | if (g_module_symbol (module, "fill_vtable", &sym)) { |
---|
418 | GdkPixbufModuleFillVtableFunc func = (GdkPixbufModuleFillVtableFunc) sym; |
---|
419 | (* func) (image_module); |
---|
420 | return TRUE; |
---|
421 | } else { |
---|
422 | g_set_error (error, |
---|
423 | GDK_PIXBUF_ERROR, |
---|
424 | GDK_PIXBUF_ERROR_FAILED, |
---|
425 | _("Image-loading module %s does not export the proper interface; perhaps it's from a different GTK version?"), |
---|
426 | path); |
---|
427 | return FALSE; |
---|
428 | } |
---|
429 | } |
---|
430 | #else |
---|
431 | |
---|
432 | #define module(type) \ |
---|
433 | extern void MODULE_ENTRY (type, fill_info) (GdkPixbufFormat *info); \ |
---|
434 | extern void MODULE_ENTRY (type, fill_vtable) (GdkPixbufModule *module) |
---|
435 | |
---|
436 | module (png); |
---|
437 | module (bmp); |
---|
438 | module (wbmp); |
---|
439 | module (gif); |
---|
440 | module (ico); |
---|
441 | module (ani); |
---|
442 | module (jpeg); |
---|
443 | module (pnm); |
---|
444 | module (ras); |
---|
445 | module (tiff); |
---|
446 | module (xpm); |
---|
447 | module (xbm); |
---|
448 | module (tga); |
---|
449 | |
---|
450 | gboolean |
---|
451 | _gdk_pixbuf_load_module (GdkPixbufModule *image_module, |
---|
452 | GError **error) |
---|
453 | { |
---|
454 | GdkPixbufModuleFillInfoFunc fill_info = NULL; |
---|
455 | GdkPixbufModuleFillVtableFunc fill_vtable = NULL; |
---|
456 | |
---|
457 | image_module->module = (void *) 1; |
---|
458 | |
---|
459 | if (FALSE) { |
---|
460 | /* Ugly hack so we can use else if unconditionally below ;-) */ |
---|
461 | } |
---|
462 | |
---|
463 | #ifdef INCLUDE_png |
---|
464 | else if (strcmp (image_module->module_name, "png") == 0) { |
---|
465 | fill_info = MODULE_ENTRY (png, fill_info); |
---|
466 | fill_vtable = MODULE_ENTRY (png, fill_vtable); |
---|
467 | } |
---|
468 | #endif |
---|
469 | |
---|
470 | #ifdef INCLUDE_bmp |
---|
471 | else if (strcmp (image_module->module_name, "bmp") == 0) { |
---|
472 | fill_info = MODULE_ENTRY (bmp, fill_info); |
---|
473 | fill_vtable = MODULE_ENTRY (bmp, fill_vtable); |
---|
474 | } |
---|
475 | #endif |
---|
476 | |
---|
477 | #ifdef INCLUDE_wbmp |
---|
478 | else if (strcmp (image_module->module_name, "wbmp") == 0) { |
---|
479 | fill_info = MODULE_ENTRY (wbmp, fill_info); |
---|
480 | fill_vtable = MODULE_ENTRY (wbmp, fill_vtable); |
---|
481 | } |
---|
482 | #endif |
---|
483 | |
---|
484 | #ifdef INCLUDE_gif |
---|
485 | else if (strcmp (image_module->module_name, "gif") == 0) { |
---|
486 | fill_info = MODULE_ENTRY (gif, fill_info); |
---|
487 | fill_vtable = MODULE_ENTRY (gif, fill_vtable); |
---|
488 | } |
---|
489 | #endif |
---|
490 | |
---|
491 | #ifdef INCLUDE_ico |
---|
492 | else if (strcmp (image_module->module_name, "ico") == 0) { |
---|
493 | fill_info = MODULE_ENTRY (ico, fill_info); |
---|
494 | fill_vtable = MODULE_ENTRY (ico, fill_vtable); |
---|
495 | } |
---|
496 | #endif |
---|
497 | |
---|
498 | #ifdef INCLUDE_ani |
---|
499 | else if (strcmp (image_module->module_name, "ani") == 0) { |
---|
500 | fill_info = MODULE_ENTRY (ani, fill_info); |
---|
501 | fill_vtable = MODULE_ENTRY (ani, fill_vtable); |
---|
502 | } |
---|
503 | #endif |
---|
504 | |
---|
505 | #ifdef INCLUDE_jpeg |
---|
506 | else if (strcmp (image_module->module_name, "jpeg") == 0) { |
---|
507 | fill_info = MODULE_ENTRY (jpeg, fill_info); |
---|
508 | fill_vtable = MODULE_ENTRY (jpeg, fill_vtable); |
---|
509 | } |
---|
510 | #endif |
---|
511 | |
---|
512 | #ifdef INCLUDE_pnm |
---|
513 | else if (strcmp (image_module->module_name, "pnm") == 0) { |
---|
514 | fill_info = MODULE_ENTRY (pnm, fill_info); |
---|
515 | fill_vtable = MODULE_ENTRY (pnm, fill_vtable); |
---|
516 | } |
---|
517 | #endif |
---|
518 | |
---|
519 | #ifdef INCLUDE_ras |
---|
520 | else if (strcmp (image_module->module_name, "ras") == 0) { |
---|
521 | fill_info = MODULE_ENTRY (ras, fill_info); |
---|
522 | fill_vtable = MODULE_ENTRY (ras, fill_vtable); |
---|
523 | } |
---|
524 | #endif |
---|
525 | |
---|
526 | #ifdef INCLUDE_tiff |
---|
527 | else if (strcmp (image_module->module_name, "tiff") == 0) { |
---|
528 | fill_info = MODULE_ENTRY (tiff, fill_info); |
---|
529 | fill_vtable = MODULE_ENTRY (tiff, fill_vtable); |
---|
530 | } |
---|
531 | #endif |
---|
532 | |
---|
533 | #ifdef INCLUDE_xpm |
---|
534 | else if (strcmp (image_module->module_name, "xpm") == 0) { |
---|
535 | fill_info = MODULE_ENTRY (xpm, fill_info); |
---|
536 | fill_vtable = MODULE_ENTRY (xpm, fill_vtable); |
---|
537 | } |
---|
538 | #endif |
---|
539 | |
---|
540 | #ifdef INCLUDE_xbm |
---|
541 | else if (strcmp (image_module->module_name, "xbm") == 0) { |
---|
542 | fill_info = MODULE_ENTRY (xbm, fill_info); |
---|
543 | fill_vtable = MODULE_ENTRY (xbm, fill_vtable); |
---|
544 | } |
---|
545 | #endif |
---|
546 | |
---|
547 | #ifdef INCLUDE_tga |
---|
548 | else if (strcmp (image_module->module_name, "tga") == 0) { |
---|
549 | fill_info = MODULE_ENTRY (tga, fill_info); |
---|
550 | fill_vtable = MODULE_ENTRY (tga, fill_vtable); |
---|
551 | } |
---|
552 | #endif |
---|
553 | |
---|
554 | if (fill_vtable) { |
---|
555 | (* fill_vtable) (image_module); |
---|
556 | image_module->info = g_new0 (GdkPixbufFormat, 1); |
---|
557 | (* fill_info) (image_module->info); |
---|
558 | |
---|
559 | return TRUE; |
---|
560 | } else { |
---|
561 | g_set_error (error, |
---|
562 | GDK_PIXBUF_ERROR, |
---|
563 | GDK_PIXBUF_ERROR_UNKNOWN_TYPE, |
---|
564 | _("Image type '%s' is not supported"), |
---|
565 | image_module->module_name); |
---|
566 | |
---|
567 | return FALSE; |
---|
568 | } |
---|
569 | } |
---|
570 | |
---|
571 | static void |
---|
572 | gdk_pixbuf_io_init () |
---|
573 | { |
---|
574 | gchar *included_formats[] = { |
---|
575 | "ani", "png", "bmp", "wbmp", "gif", |
---|
576 | "ico", "jpeg", "pnm", "ras", "tiff", |
---|
577 | "xpm", "xbm", "tga", |
---|
578 | NULL |
---|
579 | }; |
---|
580 | gchar **name; |
---|
581 | GdkPixbufModule *module = NULL; |
---|
582 | |
---|
583 | for (name = included_formats; *name; name++) { |
---|
584 | module = g_new0 (GdkPixbufModule, 1); |
---|
585 | module->module_name = *name; |
---|
586 | if (_gdk_pixbuf_load_module (module, NULL)) |
---|
587 | file_formats = g_slist_prepend (file_formats, module); |
---|
588 | else |
---|
589 | g_free (module); |
---|
590 | } |
---|
591 | } |
---|
592 | |
---|
593 | #endif |
---|
594 | |
---|
595 | |
---|
596 | |
---|
597 | GdkPixbufModule * |
---|
598 | _gdk_pixbuf_get_named_module (const char *name, |
---|
599 | GError **error) |
---|
600 | { |
---|
601 | GSList *modules; |
---|
602 | |
---|
603 | for (modules = get_file_formats (); modules; modules = g_slist_next (modules)) { |
---|
604 | GdkPixbufModule *module = (GdkPixbufModule *)modules->data; |
---|
605 | if (!strcmp (name, module->module_name)) |
---|
606 | return module; |
---|
607 | } |
---|
608 | |
---|
609 | g_set_error (error, |
---|
610 | GDK_PIXBUF_ERROR, |
---|
611 | GDK_PIXBUF_ERROR_UNKNOWN_TYPE, |
---|
612 | _("Image type '%s' is not supported"), |
---|
613 | name); |
---|
614 | |
---|
615 | return NULL; |
---|
616 | } |
---|
617 | |
---|
618 | GdkPixbufModule * |
---|
619 | _gdk_pixbuf_get_module (guchar *buffer, guint size, |
---|
620 | const gchar *filename, |
---|
621 | GError **error) |
---|
622 | { |
---|
623 | GSList *modules; |
---|
624 | |
---|
625 | gint score, best = 0; |
---|
626 | GdkPixbufModule *selected = NULL; |
---|
627 | for (modules = get_file_formats (); modules; modules = g_slist_next (modules)) { |
---|
628 | GdkPixbufModule *module = (GdkPixbufModule *)modules->data; |
---|
629 | score = format_check (module, buffer, size); |
---|
630 | if (score > best) { |
---|
631 | best = score; |
---|
632 | selected = module; |
---|
633 | } |
---|
634 | if (score >= 100) |
---|
635 | break; |
---|
636 | } |
---|
637 | if (selected != NULL) |
---|
638 | return selected; |
---|
639 | |
---|
640 | if (filename) |
---|
641 | g_set_error (error, |
---|
642 | GDK_PIXBUF_ERROR, |
---|
643 | GDK_PIXBUF_ERROR_UNKNOWN_TYPE, |
---|
644 | _("Couldn't recognize the image file format for file '%s'"), |
---|
645 | filename); |
---|
646 | else |
---|
647 | g_set_error (error, |
---|
648 | GDK_PIXBUF_ERROR, |
---|
649 | GDK_PIXBUF_ERROR_UNKNOWN_TYPE, |
---|
650 | _("Unrecognized image file format")); |
---|
651 | |
---|
652 | |
---|
653 | return NULL; |
---|
654 | } |
---|
655 | |
---|
656 | |
---|
657 | static void |
---|
658 | prepared_notify (GdkPixbuf *pixbuf, |
---|
659 | GdkPixbufAnimation *anim, |
---|
660 | gpointer user_data) |
---|
661 | { |
---|
662 | if (pixbuf != NULL) |
---|
663 | g_object_ref (pixbuf); |
---|
664 | *((GdkPixbuf **)user_data) = pixbuf; |
---|
665 | } |
---|
666 | |
---|
667 | GdkPixbuf * |
---|
668 | _gdk_pixbuf_generic_image_load (GdkPixbufModule *module, |
---|
669 | FILE *f, |
---|
670 | GError **error) |
---|
671 | { |
---|
672 | guchar buffer[4096]; |
---|
673 | size_t length; |
---|
674 | GdkPixbuf *pixbuf = NULL; |
---|
675 | gpointer context; |
---|
676 | |
---|
677 | if (module->load != NULL) |
---|
678 | return (* module->load) (f, error); |
---|
679 | |
---|
680 | context = module->begin_load (NULL, prepared_notify, NULL, &pixbuf, error); |
---|
681 | |
---|
682 | if (!context) |
---|
683 | return NULL; |
---|
684 | |
---|
685 | while (!feof (f)) { |
---|
686 | length = fread (buffer, 1, sizeof (buffer), f); |
---|
687 | if (length > 0) |
---|
688 | if (!module->load_increment (context, buffer, length, error)) { |
---|
689 | module->stop_load (context, NULL); |
---|
690 | if (pixbuf != NULL) |
---|
691 | g_object_unref (pixbuf); |
---|
692 | return NULL; |
---|
693 | } |
---|
694 | } |
---|
695 | |
---|
696 | if (!module->stop_load (context, error)) { |
---|
697 | if (pixbuf != NULL) |
---|
698 | g_object_unref (pixbuf); |
---|
699 | return NULL; |
---|
700 | } |
---|
701 | |
---|
702 | return pixbuf; |
---|
703 | } |
---|
704 | |
---|
705 | /** |
---|
706 | * gdk_pixbuf_new_from_file: |
---|
707 | * @filename: Name of file to load. |
---|
708 | * @error: Return location for an error |
---|
709 | * |
---|
710 | * Creates a new pixbuf by loading an image from a file. The file format is |
---|
711 | * detected automatically. If %NULL is returned, then @error will be set. |
---|
712 | * Possible errors are in the #GDK_PIXBUF_ERROR and #G_FILE_ERROR domains. |
---|
713 | * |
---|
714 | * Return value: A newly-created pixbuf with a reference count of 1, or %NULL if |
---|
715 | * any of several error conditions occurred: the file could not be opened, |
---|
716 | * there was no loader for the file's format, there was not enough memory to |
---|
717 | * allocate the image buffer, or the image file contained invalid data. |
---|
718 | **/ |
---|
719 | GdkPixbuf * |
---|
720 | gdk_pixbuf_new_from_file (const char *filename, |
---|
721 | GError **error) |
---|
722 | { |
---|
723 | GdkPixbuf *pixbuf; |
---|
724 | int size; |
---|
725 | FILE *f; |
---|
726 | guchar buffer [128]; |
---|
727 | GdkPixbufModule *image_module; |
---|
728 | |
---|
729 | g_return_val_if_fail (filename != NULL, NULL); |
---|
730 | |
---|
731 | f = fopen (filename, "rb"); |
---|
732 | if (!f) { |
---|
733 | g_set_error (error, |
---|
734 | G_FILE_ERROR, |
---|
735 | g_file_error_from_errno (errno), |
---|
736 | _("Failed to open file '%s': %s"), |
---|
737 | filename, g_strerror (errno)); |
---|
738 | return NULL; |
---|
739 | } |
---|
740 | |
---|
741 | size = fread (&buffer, 1, sizeof (buffer), f); |
---|
742 | if (size == 0) { |
---|
743 | g_set_error (error, |
---|
744 | GDK_PIXBUF_ERROR, |
---|
745 | GDK_PIXBUF_ERROR_CORRUPT_IMAGE, |
---|
746 | _("Image file '%s' contains no data"), |
---|
747 | filename); |
---|
748 | |
---|
749 | fclose (f); |
---|
750 | return NULL; |
---|
751 | } |
---|
752 | |
---|
753 | image_module = _gdk_pixbuf_get_module (buffer, size, filename, error); |
---|
754 | if (image_module == NULL) { |
---|
755 | fclose (f); |
---|
756 | return NULL; |
---|
757 | } |
---|
758 | |
---|
759 | if (image_module->module == NULL) |
---|
760 | if (!_gdk_pixbuf_load_module (image_module, error)) { |
---|
761 | fclose (f); |
---|
762 | return NULL; |
---|
763 | } |
---|
764 | |
---|
765 | fseek (f, 0, SEEK_SET); |
---|
766 | pixbuf = _gdk_pixbuf_generic_image_load (image_module, f, error); |
---|
767 | fclose (f); |
---|
768 | |
---|
769 | if (pixbuf == NULL && error != NULL && *error == NULL) { |
---|
770 | /* I don't trust these crufty longjmp()'ing image libs |
---|
771 | * to maintain proper error invariants, and I don't |
---|
772 | * want user code to segfault as a result. We need to maintain |
---|
773 | * the invariastable/gdk-pixbuf/nt that error gets set if NULL is returned. |
---|
774 | */ |
---|
775 | |
---|
776 | g_warning ("Bug! gdk-pixbuf loader '%s' didn't set an error on failure.", image_module->module_name); |
---|
777 | g_set_error (error, |
---|
778 | GDK_PIXBUF_ERROR, |
---|
779 | GDK_PIXBUF_ERROR_FAILED, |
---|
780 | _("Failed to load image '%s': reason not known, probably a corrupt image file"), |
---|
781 | filename); |
---|
782 | |
---|
783 | } else if (error != NULL && *error != NULL) { |
---|
784 | |
---|
785 | /* Add the filename to the error message */ |
---|
786 | GError *e = *error; |
---|
787 | gchar *old; |
---|
788 | |
---|
789 | old = e->message; |
---|
790 | |
---|
791 | e->message = g_strdup_printf (_("Failed to load image '%s': %s"), |
---|
792 | filename, old); |
---|
793 | |
---|
794 | g_free (old); |
---|
795 | } |
---|
796 | |
---|
797 | return pixbuf; |
---|
798 | } |
---|
799 | |
---|
800 | /** |
---|
801 | * gdk_pixbuf_new_from_xpm_data: |
---|
802 | * @data: Pointer to inline XPM data. |
---|
803 | * |
---|
804 | * Creates a new pixbuf by parsing XPM data in memory. This data is commonly |
---|
805 | * the result of including an XPM file into a program's C source. |
---|
806 | * |
---|
807 | * Return value: A newly-created pixbuf with a reference count of 1. |
---|
808 | **/ |
---|
809 | GdkPixbuf * |
---|
810 | gdk_pixbuf_new_from_xpm_data (const char **data) |
---|
811 | { |
---|
812 | GdkPixbuf *(* load_xpm_data) (const char **data); |
---|
813 | GdkPixbuf *pixbuf; |
---|
814 | GError *error = NULL; |
---|
815 | GdkPixbufModule *xpm_module = _gdk_pixbuf_get_named_module ("xpm", &error); |
---|
816 | if (xpm_module == NULL) { |
---|
817 | g_warning ("Error loading XPM image loader: %s", error->message); |
---|
818 | g_error_free (error); |
---|
819 | return NULL; |
---|
820 | } |
---|
821 | |
---|
822 | if (xpm_module->module == NULL) { |
---|
823 | if (!_gdk_pixbuf_load_module (xpm_module, &error)) { |
---|
824 | g_warning ("Error loading XPM image loader: %s", error->message); |
---|
825 | g_error_free (error); |
---|
826 | return NULL; |
---|
827 | } |
---|
828 | } |
---|
829 | |
---|
830 | if (xpm_module->load_xpm_data == NULL) { |
---|
831 | g_warning ("gdk-pixbuf XPM module lacks XPM data capability"); |
---|
832 | return NULL; |
---|
833 | } else |
---|
834 | load_xpm_data = xpm_module->load_xpm_data; |
---|
835 | |
---|
836 | pixbuf = (* load_xpm_data) (data); |
---|
837 | return pixbuf; |
---|
838 | } |
---|
839 | |
---|
840 | static void |
---|
841 | collect_save_options (va_list opts, |
---|
842 | gchar ***keys, |
---|
843 | gchar ***vals) |
---|
844 | { |
---|
845 | gchar *key; |
---|
846 | gchar *val; |
---|
847 | gchar *next; |
---|
848 | gint count; |
---|
849 | |
---|
850 | count = 0; |
---|
851 | *keys = NULL; |
---|
852 | *vals = NULL; |
---|
853 | |
---|
854 | next = va_arg (opts, gchar*); |
---|
855 | while (next) |
---|
856 | { |
---|
857 | key = next; |
---|
858 | val = va_arg (opts, gchar*); |
---|
859 | |
---|
860 | ++count; |
---|
861 | |
---|
862 | /* woo, slow */ |
---|
863 | *keys = g_realloc (*keys, sizeof(gchar*) * (count + 1)); |
---|
864 | *vals = g_realloc (*vals, sizeof(gchar*) * (count + 1)); |
---|
865 | |
---|
866 | (*keys)[count-1] = g_strdup (key); |
---|
867 | (*vals)[count-1] = g_strdup (val); |
---|
868 | |
---|
869 | (*keys)[count] = NULL; |
---|
870 | (*vals)[count] = NULL; |
---|
871 | |
---|
872 | next = va_arg (opts, gchar*); |
---|
873 | } |
---|
874 | } |
---|
875 | |
---|
876 | static gboolean |
---|
877 | gdk_pixbuf_real_save (GdkPixbuf *pixbuf, |
---|
878 | FILE *filehandle, |
---|
879 | const char *type, |
---|
880 | gchar **keys, |
---|
881 | gchar **values, |
---|
882 | GError **error) |
---|
883 | { |
---|
884 | GdkPixbufModule *image_module = NULL; |
---|
885 | |
---|
886 | image_module = _gdk_pixbuf_get_named_module (type, error); |
---|
887 | |
---|
888 | if (image_module == NULL) |
---|
889 | return FALSE; |
---|
890 | |
---|
891 | if (image_module->module == NULL) |
---|
892 | if (!_gdk_pixbuf_load_module (image_module, error)) |
---|
893 | return FALSE; |
---|
894 | |
---|
895 | if (image_module->save == NULL) { |
---|
896 | g_set_error (error, |
---|
897 | GDK_PIXBUF_ERROR, |
---|
898 | GDK_PIXBUF_ERROR_UNSUPPORTED_OPERATION, |
---|
899 | _("This build of gdk-pixbuf does not support saving the image format: %s"), |
---|
900 | type); |
---|
901 | return FALSE; |
---|
902 | } |
---|
903 | |
---|
904 | return (* image_module->save) (filehandle, pixbuf, |
---|
905 | keys, values, |
---|
906 | error); |
---|
907 | } |
---|
908 | |
---|
909 | |
---|
910 | /** |
---|
911 | * gdk_pixbuf_save: |
---|
912 | * @pixbuf: a #GdkPixbuf. |
---|
913 | * @filename: name of file to save. |
---|
914 | * @type: name of file format. |
---|
915 | * @error: return location for error, or %NULL |
---|
916 | * @Varargs: list of key-value save options |
---|
917 | * |
---|
918 | * Saves pixbuf to a file in @type, which is currently "jpeg" or |
---|
919 | * "png". If @error is set, %FALSE will be returned. Possible errors include |
---|
920 | * those in the #GDK_PIXBUF_ERROR domain and those in the #G_FILE_ERROR domain. |
---|
921 | * |
---|
922 | * The variable argument list should be %NULL-terminated; if not empty, |
---|
923 | * it should contain pairs of strings that modify the save |
---|
924 | * parameters. For example: |
---|
925 | * <informalexample><programlisting> |
---|
926 | * gdk_pixbuf_save (pixbuf, handle, "jpeg", &error, |
---|
927 | * "quality", "100", NULL); |
---|
928 | * </programlisting></informalexample> |
---|
929 | * |
---|
930 | * Currently only few parameters exist. JPEG images can be saved with a |
---|
931 | * "quality" parameter; its value should be in the range [0,100]. |
---|
932 | * Text chunks can be attached to PNG images by specifying parameters of |
---|
933 | * the form "tEXt::key", where key is an ASCII string of length 1-79. |
---|
934 | * The values are UTF-8 encoded strings. |
---|
935 | * |
---|
936 | * Return value: whether an error was set |
---|
937 | **/ |
---|
938 | |
---|
939 | gboolean |
---|
940 | gdk_pixbuf_save (GdkPixbuf *pixbuf, |
---|
941 | const char *filename, |
---|
942 | const char *type, |
---|
943 | GError **error, |
---|
944 | ...) |
---|
945 | { |
---|
946 | gchar **keys = NULL; |
---|
947 | gchar **values = NULL; |
---|
948 | va_list args; |
---|
949 | gboolean result; |
---|
950 | |
---|
951 | va_start (args, error); |
---|
952 | |
---|
953 | collect_save_options (args, &keys, &values); |
---|
954 | |
---|
955 | va_end (args); |
---|
956 | |
---|
957 | result = gdk_pixbuf_savev (pixbuf, filename, type, |
---|
958 | keys, values, |
---|
959 | error); |
---|
960 | |
---|
961 | g_strfreev (keys); |
---|
962 | g_strfreev (values); |
---|
963 | |
---|
964 | return result; |
---|
965 | } |
---|
966 | |
---|
967 | /** |
---|
968 | * gdk_pixbuf_savev: |
---|
969 | * @pixbuf: a #GdkPixbuf. |
---|
970 | * @filename: name of file to save. |
---|
971 | * @type: name of file format. |
---|
972 | * @option_keys: name of options to set, %NULL-terminated |
---|
973 | * @option_values: values for named options |
---|
974 | * @error: return location for error, or %NULL |
---|
975 | * |
---|
976 | * Saves pixbuf to a file in @type, which is currently "jpeg" or "png". |
---|
977 | * If @error is set, %FALSE will be returned. See gdk_pixbuf_save () for more |
---|
978 | * details. |
---|
979 | * |
---|
980 | * Return value: whether an error was set |
---|
981 | **/ |
---|
982 | |
---|
983 | gboolean |
---|
984 | gdk_pixbuf_savev (GdkPixbuf *pixbuf, |
---|
985 | const char *filename, |
---|
986 | const char *type, |
---|
987 | char **option_keys, |
---|
988 | char **option_values, |
---|
989 | GError **error) |
---|
990 | { |
---|
991 | FILE *f = NULL; |
---|
992 | gboolean result; |
---|
993 | |
---|
994 | |
---|
995 | g_return_val_if_fail (filename != NULL, FALSE); |
---|
996 | g_return_val_if_fail (type != NULL, FALSE); |
---|
997 | |
---|
998 | f = fopen (filename, "wb"); |
---|
999 | |
---|
1000 | if (f == NULL) { |
---|
1001 | g_set_error (error, |
---|
1002 | G_FILE_ERROR, |
---|
1003 | g_file_error_from_errno (errno), |
---|
1004 | _("Failed to open '%s' for writing: %s"), |
---|
1005 | filename, g_strerror (errno)); |
---|
1006 | return FALSE; |
---|
1007 | } |
---|
1008 | |
---|
1009 | |
---|
1010 | result = gdk_pixbuf_real_save (pixbuf, f, type, |
---|
1011 | option_keys, option_values, |
---|
1012 | error); |
---|
1013 | |
---|
1014 | |
---|
1015 | if (!result) { |
---|
1016 | g_return_val_if_fail (error == NULL || *error != NULL, FALSE); |
---|
1017 | fclose (f); |
---|
1018 | return FALSE; |
---|
1019 | } |
---|
1020 | |
---|
1021 | if (fclose (f) < 0) { |
---|
1022 | g_set_error (error, |
---|
1023 | G_FILE_ERROR, |
---|
1024 | g_file_error_from_errno (errno), |
---|
1025 | _("Failed to close '%s' while writing image, all data may not have been saved: %s"), |
---|
1026 | filename, g_strerror (errno)); |
---|
1027 | return FALSE; |
---|
1028 | } |
---|
1029 | |
---|
1030 | return TRUE; |
---|
1031 | } |
---|
1032 | |
---|
1033 | /** |
---|
1034 | * gdk_pixbuf_format_get_name: |
---|
1035 | * @format: a #GdkPixbufFormat |
---|
1036 | * |
---|
1037 | * Returns the name of the format. |
---|
1038 | * |
---|
1039 | * Return value: the name of the format. |
---|
1040 | * |
---|
1041 | * Since: 2.2 |
---|
1042 | */ |
---|
1043 | gchar * |
---|
1044 | gdk_pixbuf_format_get_name (GdkPixbufFormat *format) |
---|
1045 | { |
---|
1046 | g_return_val_if_fail (format != NULL, NULL); |
---|
1047 | |
---|
1048 | return g_strdup (format->name); |
---|
1049 | } |
---|
1050 | |
---|
1051 | /** |
---|
1052 | * gdk_pixbuf_format_get_description: |
---|
1053 | * @format: a #GdkPixbufFormat |
---|
1054 | * |
---|
1055 | * Returns a description of the format. |
---|
1056 | * |
---|
1057 | * Return value: a description of the format. |
---|
1058 | * |
---|
1059 | * Since: 2.2 |
---|
1060 | */ |
---|
1061 | gchar * |
---|
1062 | gdk_pixbuf_format_get_description (GdkPixbufFormat *format) |
---|
1063 | { |
---|
1064 | gchar *domain; |
---|
1065 | gchar *description; |
---|
1066 | g_return_val_if_fail (format != NULL, NULL); |
---|
1067 | |
---|
1068 | if (format->domain != NULL) |
---|
1069 | domain = format->domain; |
---|
1070 | else |
---|
1071 | domain = GETTEXT_PACKAGE; |
---|
1072 | description = dgettext (domain, format->description); |
---|
1073 | |
---|
1074 | return g_strdup (description); |
---|
1075 | } |
---|
1076 | |
---|
1077 | /** |
---|
1078 | * gdk_pixbuf_format_get_mime_types: |
---|
1079 | * @format: a #GdkPixbufFormat |
---|
1080 | * |
---|
1081 | * Returns the mime types supported by the format. |
---|
1082 | * |
---|
1083 | * Return value: a %NULL-terminated array of mime types. |
---|
1084 | * |
---|
1085 | * Since: 2.2 |
---|
1086 | */ |
---|
1087 | gchar ** |
---|
1088 | gdk_pixbuf_format_get_mime_types (GdkPixbufFormat *format) |
---|
1089 | { |
---|
1090 | g_return_val_if_fail (format != NULL, NULL); |
---|
1091 | |
---|
1092 | return g_strdupv (format->mime_types); |
---|
1093 | } |
---|
1094 | |
---|
1095 | /** |
---|
1096 | * gdk_pixbuf_format_get_extensions: |
---|
1097 | * @format: a #GdkPixbufFormat |
---|
1098 | * |
---|
1099 | * Returns the filename extensions typically used for files in the |
---|
1100 | * given format. |
---|
1101 | * |
---|
1102 | * Return value: a %NULL-terminated array of filename extensions. |
---|
1103 | * |
---|
1104 | * Since: 2.2 |
---|
1105 | */ |
---|
1106 | gchar ** |
---|
1107 | gdk_pixbuf_format_get_extensions (GdkPixbufFormat *format) |
---|
1108 | { |
---|
1109 | g_return_val_if_fail (format != NULL, NULL); |
---|
1110 | |
---|
1111 | return g_strdupv (format->extensions); |
---|
1112 | } |
---|
1113 | |
---|
1114 | /** |
---|
1115 | * gdk_pixbuf_format_is_writable: |
---|
1116 | * @format: a #GdkPixbufFormat |
---|
1117 | * |
---|
1118 | * Returns whether pixbufs can be saved in the given format. |
---|
1119 | * |
---|
1120 | * Return value: whether pixbufs can be saved in the given format. |
---|
1121 | * |
---|
1122 | * Since: 2.2 |
---|
1123 | */ |
---|
1124 | gboolean |
---|
1125 | gdk_pixbuf_format_is_writable (GdkPixbufFormat *format) |
---|
1126 | { |
---|
1127 | g_return_val_if_fail (format != NULL, FALSE); |
---|
1128 | |
---|
1129 | return (format->flags & GDK_PIXBUF_FORMAT_WRITABLE) != 0; |
---|
1130 | } |
---|
1131 | |
---|
1132 | GdkPixbufFormat * |
---|
1133 | _gdk_pixbuf_get_format (GdkPixbufModule *module) |
---|
1134 | { |
---|
1135 | g_return_val_if_fail (module != NULL, NULL); |
---|
1136 | |
---|
1137 | return module->info; |
---|
1138 | } |
---|
1139 | |
---|
1140 | /** |
---|
1141 | * gdk_pixbuf_get_formats: |
---|
1142 | * |
---|
1143 | * Obtains the available information about the image formats supported |
---|
1144 | * by GdkPixbuf. |
---|
1145 | * |
---|
1146 | * Returns: A list of #GdkPixbufFormat<!-- -->s describing the supported |
---|
1147 | * image formats. The list should be freed when it is no longer needed, |
---|
1148 | * but the structures themselves are owned by #GdkPixbuf and should not be |
---|
1149 | * freed. |
---|
1150 | * |
---|
1151 | * Since: 2.2 |
---|
1152 | */ |
---|
1153 | GSList * |
---|
1154 | gdk_pixbuf_get_formats (void) |
---|
1155 | { |
---|
1156 | GSList *result = NULL; |
---|
1157 | GSList *modules; |
---|
1158 | |
---|
1159 | for (modules = get_file_formats (); modules; modules = g_slist_next (modules)) { |
---|
1160 | GdkPixbufModule *module = (GdkPixbufModule *)modules->data; |
---|
1161 | GdkPixbufFormat *info = _gdk_pixbuf_get_format (module); |
---|
1162 | result = g_slist_prepend (result, info); |
---|
1163 | } |
---|
1164 | |
---|
1165 | return result; |
---|
1166 | } |
---|
1167 | |
---|
1168 | |
---|
1169 | |
---|
1170 | |
---|
1171 | |
---|