]> Pileus Git - ~andy/gtk/blob - gdk-pixbuf/gdk-pixbuf-io.c
Add a cast to avoid compiler warnings.
[~andy/gtk] / gdk-pixbuf / gdk-pixbuf-io.c
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
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <glib.h>
31 #include <errno.h>
32 #ifdef HAVE_UNISTD_H
33 #include <unistd.h>
34 #endif
35
36 #include "gdk-pixbuf-private.h"
37 #include "gdk-pixbuf-io.h"
38 #include "gdk-pixbuf-alias.h"
39
40 #include <glib/gstdio.h>
41
42 #ifdef G_OS_WIN32
43 #define STRICT
44 #include <windows.h>
45 #undef STRICT
46 #endif
47
48 static gint 
49 format_check (GdkPixbufModule *module, guchar *buffer, int size)
50 {
51         int i, j;
52         gchar m;
53         GdkPixbufModulePattern *pattern;
54         gboolean anchored;
55         gchar *prefix, *mask;
56
57         for (pattern = module->info->signature; pattern->prefix; pattern++) {
58                 if (pattern->mask && pattern->mask[0] == '*') {
59                         prefix = pattern->prefix + 1;
60                         mask = pattern->mask + 1;
61                         anchored = FALSE;
62                 }
63                 else {
64                         prefix = pattern->prefix;
65                         mask = pattern->mask;
66                         anchored = TRUE;
67                 }
68                 for (i = 0; i < size; i++) {
69                         for (j = 0; i + j < size && prefix[j] != 0; j++) {
70                                 m = mask ? mask[j] : ' ';
71                                 if (m == ' ') {
72                                         if (buffer[i + j] != prefix[j])
73                                                 break;
74                                 }
75                                 else if (m == '!') {
76                                         if (buffer[i + j] == prefix[j])
77                                                 break;
78                                 }
79                                 else if (m == 'z') {
80                                         if (buffer[i + j] != 0)
81                                                 break;
82                                 }
83                                 else if (m == 'n') {
84                                         if (buffer[i + j] == 0)
85                                                 break;
86                                 }
87                         } 
88
89                         if (prefix[j] == 0) 
90                                 return pattern->relevance;
91
92                         if (anchored)
93                                 break;
94                 }
95         }
96         return 0;
97 }
98
99 G_LOCK_DEFINE_STATIC (init_lock);
100 G_LOCK_DEFINE_STATIC (threadunsafe_loader_lock);
101
102 gboolean
103 _gdk_pixbuf_lock (GdkPixbufModule *image_module)
104 {
105         if (g_threads_got_initialized &&
106             !(image_module->info->flags & GDK_PIXBUF_FORMAT_THREADSAFE)) {
107                 G_LOCK (threadunsafe_loader_lock);
108
109                 return TRUE;
110         }
111
112         return FALSE;
113 }
114  
115 void
116 _gdk_pixbuf_unlock (GdkPixbufModule *image_module)
117 {
118         if (!(image_module->info->flags & GDK_PIXBUF_FORMAT_THREADSAFE)) {
119                 G_UNLOCK (threadunsafe_loader_lock);
120         }
121 }
122
123 static GSList *file_formats = NULL;
124
125 static void gdk_pixbuf_io_init ();
126
127 static GSList *
128 get_file_formats (void)
129 {
130         G_LOCK (init_lock);
131         if (file_formats == NULL)
132                 gdk_pixbuf_io_init ();
133         G_UNLOCK (init_lock);
134         
135         return file_formats;
136 }
137
138
139 #ifdef USE_GMODULE 
140
141 static gboolean
142 scan_string (const char **pos, GString *out)
143 {
144         const char *p = *pos, *q = *pos;
145         char *tmp, *tmp2;
146         gboolean quoted;
147         
148         while (g_ascii_isspace (*p))
149                 p++;
150         
151         if (!*p)
152                 return FALSE;
153         else if (*p == '"') {
154                 p++;
155                 quoted = FALSE;
156                 for (q = p; (*q != '"') || quoted; q++) {
157                         if (!*q)
158                                 return FALSE;
159                         quoted = (*q == '\\') && !quoted;
160                 }
161                 
162                 tmp = g_strndup (p, q - p);
163                 tmp2 = g_strcompress (tmp);
164                 g_string_truncate (out, 0);
165                 g_string_append (out, tmp2);
166                 g_free (tmp);
167                 g_free (tmp2);
168         }
169         
170         q++;
171         *pos = q;
172         
173         return TRUE;
174 }
175
176 static gboolean
177 scan_int (const char **pos, int *out)
178 {
179         int i = 0;
180         char buf[32];
181         const char *p = *pos;
182         
183         while (g_ascii_isspace (*p))
184                 p++;
185         
186         if (*p < '0' || *p > '9')
187                 return FALSE;
188         
189         while ((*p >= '0') && (*p <= '9') && i < sizeof (buf)) {
190                 buf[i] = *p;
191                 i++;
192                 p++;
193         }
194         
195         if (i == sizeof (buf))
196                 return FALSE;
197         else
198                 buf[i] = '\0';
199         
200         *out = atoi (buf);
201         
202         *pos = p;
203
204         return TRUE;
205 }
206
207 static gboolean
208 skip_space (const char **pos)
209 {
210         const char *p = *pos;
211         
212         while (g_ascii_isspace (*p))
213                 p++;
214   
215         *pos = p;
216         
217         return !(*p == '\0');
218 }
219   
220 #ifdef G_OS_WIN32
221
222 /* DllMain function needed to tuck away the gdk-pixbuf DLL name */
223 G_WIN32_DLLMAIN_FOR_DLL_NAME (static, dll_name)
224
225 static char *
226 get_toplevel (void)
227 {
228   static char *toplevel = NULL;
229
230   if (toplevel == NULL)
231     toplevel = g_win32_get_package_installation_subdirectory
232       (GETTEXT_PACKAGE, dll_name, "");
233
234   return toplevel;
235 }
236
237 static char *
238 get_sysconfdir (void)
239 {
240   static char *sysconfdir = NULL;
241
242   if (sysconfdir == NULL)
243     sysconfdir = g_win32_get_package_installation_subdirectory
244       (GETTEXT_PACKAGE, dll_name, "etc");
245
246   return sysconfdir;
247 }
248
249 #undef GTK_SYSCONFDIR
250 #define GTK_SYSCONFDIR get_sysconfdir()
251
252 static void
253 correct_prefix (gchar **path)
254 {
255   if (strncmp (*path, GTK_PREFIX "/", strlen (GTK_PREFIX "/")) == 0 ||
256       strncmp (*path, GTK_PREFIX "\\", strlen (GTK_PREFIX "\\")) == 0)
257     {
258       /* This is an entry put there by gdk-pixbuf-query-loaders on the
259        * packager's system. On Windows a prebuilt GTK+ package can be
260        * installed in a random location. The gdk-pixbuf.loaders file
261        * distributed in such a package contains paths from the package
262        * builder's machine. Replace the build-time prefix with the
263        * installation prefix on this machine.
264        */
265       gchar *tem = *path;
266       *path = g_strconcat (get_toplevel (), tem + strlen (GTK_PREFIX), NULL);
267       g_free (tem);
268     }
269 }
270
271 #endif  /* G_OS_WIN32 */
272
273 static gchar *
274 gdk_pixbuf_get_module_file (void)
275 {
276   gchar *result = g_strdup (g_getenv ("GDK_PIXBUF_MODULE_FILE"));
277
278   if (!result)
279           result = g_build_filename (GTK_SYSCONFDIR, "gtk-2.0", "gdk-pixbuf.loaders", NULL);
280
281   return result;
282 }
283
284 static void 
285 gdk_pixbuf_io_init (void)
286 {
287         GIOChannel *channel;
288         gchar *line_buf;
289         gsize term;
290         GString *tmp_buf = g_string_new (NULL);
291         gboolean have_error = FALSE;
292         GdkPixbufModule *module = NULL;
293         gchar *filename = gdk_pixbuf_get_module_file ();
294         int flags;
295         int n_patterns = 0;
296         GdkPixbufModulePattern *pattern;
297         GError *error = NULL;
298
299         channel = g_io_channel_new_file (filename, "r",  &error);
300         if (!channel) {
301                 g_warning ("Cannot open pixbuf loader module file '%s': %s",
302                            filename, error->message);
303                 return;
304         }
305         
306         while (!have_error && g_io_channel_read_line (channel, &line_buf, NULL, &term, NULL) == G_IO_STATUS_NORMAL) {
307                 const char *p;
308                 
309                 p = line_buf;
310
311                 line_buf[term] = 0;
312
313                 if (!skip_space (&p)) {
314                                 /* Blank line marking the end of a module
315                                  */
316                         if (module && *p != '#') {
317 #ifdef G_OS_WIN32
318                                 correct_prefix (&module->module_path);
319 #endif
320                                 file_formats = g_slist_prepend (file_formats, module);
321                                 module = NULL;
322                         }
323                         
324                         goto next_line;
325                 }
326
327                 if (*p == '#') 
328                         goto next_line;
329                 
330                 if (!module) {
331                                 /* Read a module location
332                                  */
333                         module = g_new0 (GdkPixbufModule, 1);
334                         n_patterns = 0;
335                         
336                         if (!scan_string (&p, tmp_buf)) {
337                                 g_warning ("Error parsing loader info in '%s'\n  %s", 
338                                            filename, line_buf);
339                                 have_error = TRUE;
340                         }
341                         module->module_path = g_strdup (tmp_buf->str);
342                 }
343                 else if (!module->module_name) {
344                         module->info = g_new0 (GdkPixbufFormat, 1);
345                         if (!scan_string (&p, tmp_buf)) {
346                                 g_warning ("Error parsing loader info in '%s'\n  %s", 
347                                            filename, line_buf);
348                                 have_error = TRUE;
349                         }
350                         module->info->name =  g_strdup (tmp_buf->str);
351                         module->module_name = module->info->name;
352
353                         if (!scan_int (&p, &flags)) {
354                                 g_warning ("Error parsing loader info in '%s'\n  %s", 
355                                            filename, line_buf);
356                                 have_error = TRUE;
357                         }
358                         module->info->flags = flags;
359                         
360                         if (!scan_string (&p, tmp_buf)) {
361                                 g_warning ("Error parsing loader info in '%s'\n  %s", 
362                                            filename, line_buf);
363                                 have_error = TRUE;
364                         }                       
365                         if (tmp_buf->str[0] != 0)
366                                 module->info->domain = g_strdup (tmp_buf->str);
367
368                         if (!scan_string (&p, tmp_buf)) {
369                                 g_warning ("Error parsing loader info in '%s'\n  %s", 
370                                            filename, line_buf);
371                                 have_error = TRUE;
372                         }                       
373                         module->info->description = g_strdup (tmp_buf->str);
374                 }
375                 else if (!module->info->mime_types) {
376                         int n = 1;
377                         module->info->mime_types = g_new0 (gchar*, 1);
378                         while (scan_string (&p, tmp_buf)) {
379                                 if (tmp_buf->str[0] != 0) {
380                                         module->info->mime_types =
381                                                 g_realloc (module->info->mime_types, (n + 1) * sizeof (gchar*));
382                                         module->info->mime_types[n - 1] = g_strdup (tmp_buf->str);
383                                         module->info->mime_types[n] = NULL;
384                                         n++;
385                                 }
386                         }
387                 }
388                 else if (!module->info->extensions) {
389                         int n = 1;
390                         module->info->extensions = g_new0 (gchar*, 1);
391                         while (scan_string (&p, tmp_buf)) {
392                                 if (tmp_buf->str[0] != 0) {
393                                         module->info->extensions =
394                                                 g_realloc (module->info->extensions, (n + 1) * sizeof (gchar*));
395                                         module->info->extensions[n - 1] = g_strdup (tmp_buf->str);
396                                         module->info->extensions[n] = NULL;
397                                         n++;
398                                 }
399                         }
400                 }
401                 else {
402                         n_patterns++;
403                         module->info->signature = (GdkPixbufModulePattern *)
404                                 g_realloc (module->info->signature, (n_patterns + 1) * sizeof (GdkPixbufModulePattern));
405                         pattern = module->info->signature + n_patterns;
406                         pattern->prefix = NULL;
407                         pattern->mask = NULL;
408                         pattern->relevance = 0;
409                         pattern--;
410                         if (!scan_string (&p, tmp_buf))
411                                 goto context_error;
412                         pattern->prefix = g_strdup (tmp_buf->str);
413                         
414                         if (!scan_string (&p, tmp_buf))
415                                 goto context_error;
416                         if (*tmp_buf->str)
417                                 pattern->mask = g_strdup (tmp_buf->str);
418                         else
419                                 pattern->mask = NULL;
420                         
421                         if (!scan_int (&p, &pattern->relevance))
422                                 goto context_error;
423                         
424                         goto next_line;
425
426                 context_error:
427                         g_free (pattern->prefix);
428                         g_free (pattern->mask);
429                         g_free (pattern);
430                         g_warning ("Error parsing loader info in '%s'\n  %s", 
431                                    filename, line_buf);
432                         have_error = TRUE;
433                 }
434         next_line:
435                 g_free (line_buf);
436         }
437         g_string_free (tmp_buf, TRUE);
438         g_io_channel_unref (channel);
439         g_free (filename);
440 }
441
442 /* actually load the image handler - gdk_pixbuf_get_module only get a */
443 /* reference to the module to load, it doesn't actually load it       */
444 /* perhaps these actions should be combined in one function           */
445 static gboolean
446 _gdk_pixbuf_load_module_unlocked (GdkPixbufModule *image_module,
447                                   GError         **error)
448 {
449         char *path;
450         GModule *module;
451         gpointer sym;
452                 
453         g_return_val_if_fail (image_module->module == NULL, FALSE);
454
455         path = image_module->module_path;
456         module = g_module_open (path, G_MODULE_BIND_LAZY);
457
458         if (!module) {
459                 g_set_error (error,
460                              GDK_PIXBUF_ERROR,
461                              GDK_PIXBUF_ERROR_FAILED,
462                              _("Unable to load image-loading module: %s: %s"),
463                              path, g_module_error ());
464                 return FALSE;
465         }
466
467         image_module->module = module;        
468         
469         if (g_module_symbol (module, "fill_vtable", &sym)) {
470                 GdkPixbufModuleFillVtableFunc func = (GdkPixbufModuleFillVtableFunc) sym;
471                 (* func) (image_module);
472                 return TRUE;
473         } else {
474                 g_set_error (error,
475                              GDK_PIXBUF_ERROR,
476                              GDK_PIXBUF_ERROR_FAILED,
477                              _("Image-loading module %s does not export the proper interface; perhaps it's from a different GTK version?"),
478                              path);
479                 return FALSE;
480         }
481 }
482
483 gboolean
484 _gdk_pixbuf_load_module (GdkPixbufModule *image_module,
485                          GError         **error)
486 {
487         gboolean ret;
488         gboolean locked = FALSE;
489
490         /* be extra careful, maybe the module initializes
491          * the thread system
492          */
493         if (g_threads_got_initialized)
494         {
495                 G_LOCK (init_lock);
496                 locked = TRUE;
497         }
498         ret = _gdk_pixbuf_load_module_unlocked (image_module, error);
499         if (locked)
500                 G_UNLOCK (init_lock);
501         return ret;
502 }
503
504 #else  /* !USE_GMODULE */
505
506 #define module(type) \
507   extern void MODULE_ENTRY (type, fill_info)   (GdkPixbufFormat *info);   \
508   extern void MODULE_ENTRY (type, fill_vtable) (GdkPixbufModule *module)
509
510 module (png);
511 module (bmp);
512 module (wbmp);
513 module (gif);
514 module (ico);
515 module (ani);
516 module (jpeg);
517 module (pnm);
518 module (ras);
519 module (tiff);
520 module (xpm);
521 module (xbm);
522 module (tga);
523 module (pcx);
524
525 gboolean
526 _gdk_pixbuf_load_module (GdkPixbufModule *image_module,
527                          GError         **error)
528 {
529         GdkPixbufModuleFillInfoFunc fill_info = NULL;
530         GdkPixbufModuleFillVtableFunc fill_vtable = NULL;
531
532         image_module->module = (void *) 1;
533
534         if (FALSE) {
535                 /* Ugly hack so we can use else if unconditionally below ;-) */
536         }
537         
538 #ifdef INCLUDE_png      
539         else if (strcmp (image_module->module_name, "png") == 0) {
540                 fill_info = MODULE_ENTRY (png, fill_info);
541                 fill_vtable = MODULE_ENTRY (png, fill_vtable);
542         }
543 #endif
544
545 #ifdef INCLUDE_bmp      
546         else if (strcmp (image_module->module_name, "bmp") == 0) {
547                 fill_info = MODULE_ENTRY (bmp, fill_info);
548                 fill_vtable = MODULE_ENTRY (bmp, fill_vtable);
549         }
550 #endif
551
552 #ifdef INCLUDE_wbmp
553         else if (strcmp (image_module->module_name, "wbmp") == 0) {
554                 fill_info = MODULE_ENTRY (wbmp, fill_info);
555                 fill_vtable = MODULE_ENTRY (wbmp, fill_vtable);
556         }
557 #endif
558
559 #ifdef INCLUDE_gif
560         else if (strcmp (image_module->module_name, "gif") == 0) {
561                 fill_info = MODULE_ENTRY (gif, fill_info);
562                 fill_vtable = MODULE_ENTRY (gif, fill_vtable);
563         }
564 #endif
565
566 #ifdef INCLUDE_ico
567         else if (strcmp (image_module->module_name, "ico") == 0) {
568                 fill_info = MODULE_ENTRY (ico, fill_info);
569                 fill_vtable = MODULE_ENTRY (ico, fill_vtable);
570         }
571 #endif
572
573 #ifdef INCLUDE_ani
574         else if (strcmp (image_module->module_name, "ani") == 0) {
575                 fill_info = MODULE_ENTRY (ani, fill_info);
576                 fill_vtable = MODULE_ENTRY (ani, fill_vtable);
577         }
578 #endif
579
580 #ifdef INCLUDE_jpeg
581         else if (strcmp (image_module->module_name, "jpeg") == 0) {
582                 fill_info = MODULE_ENTRY (jpeg, fill_info);
583                 fill_vtable = MODULE_ENTRY (jpeg, fill_vtable);
584         }
585 #endif
586
587 #ifdef INCLUDE_pnm
588         else if (strcmp (image_module->module_name, "pnm") == 0) {
589                 fill_info = MODULE_ENTRY (pnm, fill_info);
590                 fill_vtable = MODULE_ENTRY (pnm, fill_vtable);
591         }
592 #endif
593
594 #ifdef INCLUDE_ras
595         else if (strcmp (image_module->module_name, "ras") == 0) {
596                 fill_info = MODULE_ENTRY (ras, fill_info);
597                 fill_vtable = MODULE_ENTRY (ras, fill_vtable);
598         }
599 #endif
600
601 #ifdef INCLUDE_tiff
602         else if (strcmp (image_module->module_name, "tiff") == 0) {
603                 fill_info = MODULE_ENTRY (tiff, fill_info);
604                 fill_vtable = MODULE_ENTRY (tiff, fill_vtable);
605         }
606 #endif
607
608 #ifdef INCLUDE_xpm
609         else if (strcmp (image_module->module_name, "xpm") == 0) {
610                 fill_info = MODULE_ENTRY (xpm, fill_info);
611                 fill_vtable = MODULE_ENTRY (xpm, fill_vtable);
612         }
613 #endif
614
615 #ifdef INCLUDE_xbm
616         else if (strcmp (image_module->module_name, "xbm") == 0) {
617                 fill_info = MODULE_ENTRY (xbm, fill_info);
618                 fill_vtable = MODULE_ENTRY (xbm, fill_vtable);
619         }
620 #endif
621
622 #ifdef INCLUDE_tga
623         else if (strcmp (image_module->module_name, "tga") == 0) {
624                 fill_info = MODULE_ENTRY (tga, fill_info);
625                 fill_vtable = MODULE_ENTRY (tga, fill_vtable);
626         }
627 #endif
628         
629 #ifdef INCLUDE_pcx
630         else if (strcmp (image_module->module_name, "pcx") == 0) {
631                 fill_info = MODULE_ENTRY (pcx, fill_info);
632                 fill_vtable = MODULE_ENTRY (pcx, fill_vtable);
633         }
634 #endif
635         
636         if (fill_vtable) {
637                 (* fill_vtable) (image_module);
638                 image_module->info = g_new0 (GdkPixbufFormat, 1);
639                 (* fill_info) (image_module->info);
640
641                 return TRUE;
642         } else {
643                 g_set_error (error,
644                              GDK_PIXBUF_ERROR,
645                              GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
646                              _("Image type '%s' is not supported"),
647                              image_module->module_name);
648
649                 return FALSE;
650         }
651 }
652
653 static void 
654 gdk_pixbuf_io_init ()
655 {
656         gchar *included_formats[] = { 
657                 "ani", "png", "bmp", "wbmp", "gif", 
658                 "ico", "jpeg", "pnm", "ras", "tiff", 
659                 "xpm", "xbm", "tga", "pcx",
660                 NULL
661         };
662         gchar **name;
663         GdkPixbufModule *module = NULL;
664
665         for (name = included_formats; *name; name++) {
666                 module = g_new0 (GdkPixbufModule, 1);
667                 module->module_name = *name;
668                 if (_gdk_pixbuf_load_module (module, NULL))
669                         file_formats = g_slist_prepend (file_formats, module);
670                 else
671                         g_free (module);
672         }
673 }
674
675 #endif  /* !USE_GMODULE */
676
677 \f
678
679 GdkPixbufModule *
680 _gdk_pixbuf_get_named_module (const char *name,
681                               GError **error)
682 {
683         GSList *modules;
684
685         for (modules = get_file_formats (); modules; modules = g_slist_next (modules)) {
686                 GdkPixbufModule *module = (GdkPixbufModule *)modules->data;
687
688                 if (module->info->disabled)
689                         continue;
690
691                 if (!strcmp (name, module->module_name))
692                         return module;
693         }
694
695         g_set_error (error,
696                      GDK_PIXBUF_ERROR,
697                      GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
698                      _("Image type '%s' is not supported"),
699                      name);
700         
701         return NULL;
702 }
703
704 GdkPixbufModule *
705 _gdk_pixbuf_get_module (guchar *buffer, guint size,
706                         const gchar *filename,
707                         GError **error)
708 {
709         GSList *modules;
710
711         gint score, best = 0;
712         GdkPixbufModule *selected = NULL;
713         gchar *display_name = NULL;
714
715         for (modules = get_file_formats (); modules; modules = g_slist_next (modules)) {
716                 GdkPixbufModule *module = (GdkPixbufModule *)modules->data;
717
718                 if (module->info->disabled)
719                         continue;
720
721                 score = format_check (module, buffer, size);
722                 if (score > best) {
723                         best = score; 
724                         selected = module;
725                 }
726                 if (score >= 100) 
727                         break;
728         }
729         if (selected != NULL)
730                 return selected;
731
732         if (filename)
733         {
734                 display_name = g_filename_display_name (filename);
735                 g_set_error (error,
736                              GDK_PIXBUF_ERROR,
737                              GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
738                              _("Couldn't recognize the image file format for file '%s'"),
739                              display_name);
740                 g_free (display_name);
741         }
742         else
743                 g_set_error (error,
744                              GDK_PIXBUF_ERROR,
745                              GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
746                              _("Unrecognized image file format"));
747
748
749         return NULL;
750 }
751
752
753 static void
754 prepared_notify (GdkPixbuf *pixbuf, 
755                  GdkPixbufAnimation *anim, 
756                  gpointer user_data)
757 {
758         if (pixbuf != NULL)
759                 g_object_ref (pixbuf);
760         *((GdkPixbuf **)user_data) = pixbuf;
761 }
762
763 GdkPixbuf *
764 _gdk_pixbuf_generic_image_load (GdkPixbufModule *module,
765                                 FILE *f,
766                                 GError **error)
767 {
768         guchar buffer[4096];
769         size_t length;
770         GdkPixbuf *pixbuf = NULL;
771         GdkPixbufAnimation *animation = NULL;
772         gpointer context;
773         gboolean locked;
774
775         locked = _gdk_pixbuf_lock (module);
776
777         if (module->load != NULL) {
778                 pixbuf = (* module->load) (f, error);
779         } else if (module->begin_load != NULL) {
780                 
781                 context = module->begin_load (NULL, prepared_notify, NULL, &pixbuf, error);
782         
783                 if (!context)
784                         goto out;
785                 
786                 while (!feof (f) && !ferror (f)) {
787                         length = fread (buffer, 1, sizeof (buffer), f);
788                         if (length > 0)
789                                 if (!module->load_increment (context, buffer, length, error)) {
790                                         module->stop_load (context, NULL);
791                                         if (pixbuf != NULL) {
792                                                 g_object_unref (pixbuf);
793                                                 pixbuf = NULL;
794                                         }
795                                         goto out;
796                                 }
797                 }
798                 
799                 if (!module->stop_load (context, error)) {
800                         if (pixbuf != NULL) {
801                                 g_object_unref (pixbuf);
802                                 pixbuf = NULL;
803                         }
804                 }
805         } else if (module->load_animation != NULL) {
806                 animation = (* module->load_animation) (f, error);
807                 if (animation != NULL) {
808                         pixbuf = gdk_pixbuf_animation_get_static_image (animation);
809
810                         g_object_ref (pixbuf);
811                         g_object_unref (animation);
812                 }
813         }
814
815  out:
816         if (locked)
817                 _gdk_pixbuf_unlock (module);
818         return pixbuf;
819 }
820
821 /**
822  * gdk_pixbuf_new_from_file:
823  * @filename: Name of file to load, in the GLib file name encoding
824  * @error: Return location for an error
825  *
826  * Creates a new pixbuf by loading an image from a file.  The file format is
827  * detected automatically. If %NULL is returned, then @error will be set.
828  * Possible errors are in the #GDK_PIXBUF_ERROR and #G_FILE_ERROR domains.
829  *
830  * Return value: A newly-created pixbuf with a reference count of 1, or %NULL if
831  * any of several error conditions occurred:  the file could not be opened,
832  * there was no loader for the file's format, there was not enough memory to
833  * allocate the image buffer, or the image file contained invalid data.
834  **/
835 GdkPixbuf *
836 gdk_pixbuf_new_from_file (const char *filename,
837                           GError    **error)
838 {
839         GdkPixbuf *pixbuf;
840         int size;
841         FILE *f;
842         guchar buffer[256];
843         GdkPixbufModule *image_module;
844         gchar *display_name;
845
846         g_return_val_if_fail (filename != NULL, NULL);
847         g_return_val_if_fail (error == NULL || *error == NULL, NULL);
848         
849         display_name = g_filename_display_name (filename);      
850
851         f = g_fopen (filename, "rb");
852         if (!f) {
853                 g_set_error (error,
854                              G_FILE_ERROR,
855                              g_file_error_from_errno (errno),
856                              _("Failed to open file '%s': %s"),
857                              display_name,
858                              g_strerror (errno));
859                 g_free (display_name);
860                 return NULL;
861         }
862
863         size = fread (&buffer, 1, sizeof (buffer), f);
864         if (size == 0) {
865                 g_set_error (error,
866                              GDK_PIXBUF_ERROR,
867                              GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
868                              _("Image file '%s' contains no data"),
869                              display_name);
870                 g_free (display_name);
871                 fclose (f);
872                 return NULL;
873         }
874
875         image_module = _gdk_pixbuf_get_module (buffer, size, filename, error);
876         if (image_module == NULL) {
877                 g_free (display_name);
878                 fclose (f);
879                 return NULL;
880         }
881
882         if (image_module->module == NULL)
883                 if (!_gdk_pixbuf_load_module (image_module, error)) {
884                         g_free (display_name);
885                         fclose (f);
886                         return NULL;
887                 }
888
889         fseek (f, 0, SEEK_SET);
890         pixbuf = _gdk_pixbuf_generic_image_load (image_module, f, error);
891         fclose (f);
892
893         if (pixbuf == NULL && error != NULL && *error == NULL) {
894
895                 /* I don't trust these crufty longjmp()'ing image libs
896                  * to maintain proper error invariants, and I don't
897                  * want user code to segfault as a result. We need to maintain
898                  * the invariant that error gets set if NULL is returned.
899                  */
900
901                 g_warning ("Bug! gdk-pixbuf loader '%s' didn't set an error on failure.", image_module->module_name);
902                 g_set_error (error,
903                              GDK_PIXBUF_ERROR,
904                              GDK_PIXBUF_ERROR_FAILED,
905                              _("Failed to load image '%s': reason not known, probably a corrupt image file"),
906                              display_name);
907         } else if (error != NULL && *error != NULL) {
908
909           /* Add the filename to the error message */
910           GError *e = *error;
911           gchar  *old;
912
913           old = e->message;
914           e->message = g_strdup_printf (_("Failed to load image '%s': %s"),
915                                         display_name,
916                                         old);
917           g_free (old);
918         }
919
920         g_free (display_name);
921         return pixbuf;
922 }
923
924 #ifdef G_OS_WIN32
925
926 #undef gdk_pixbuf_new_from_file
927 GdkPixbuf *
928 gdk_pixbuf_new_from_file (const char *filename,
929                           GError    **error)
930 {
931         gchar *utf8_filename =
932                 g_locale_to_utf8 (filename, -1, NULL, NULL, error);
933         GdkPixbuf *retval;
934
935         if (utf8_filename == NULL)
936                 return NULL;
937
938         retval = gdk_pixbuf_new_from_file_utf8 (utf8_filename, error);
939
940         g_free (utf8_filename);
941
942         return retval;
943 }
944 #endif
945
946 static void
947 size_prepared_cb (GdkPixbufLoader *loader, 
948                   int              width,
949                   int              height,
950                   gpointer         data)
951 {
952         struct {
953                 gint width;
954                 gint height;
955                 gboolean preserve_aspect_ratio;
956         } *info = data;
957
958         g_return_if_fail (width > 0 && height > 0);
959
960         if (info->preserve_aspect_ratio && 
961             (info->width > 0 || info->height > 0)) {
962                 if (info->width < 0)
963                 {
964                         width = width * (double)info->height/(double)height;
965                         height = info->height;
966                 }
967                 else if (info->height < 0)
968                 {
969                         height = height * (double)info->width/(double)width;
970                         width = info->width;
971                 }
972                 else if ((double)height * (double)info->width >
973                          (double)width * (double)info->height) {
974                         width = 0.5 + (double)width * (double)info->height / (double)height;
975                         height = info->height;
976                 } else {
977                         height = 0.5 + (double)height * (double)info->width / (double)width;
978                         width = info->width;
979                 }
980         } else {
981                 if (info->width > 0)
982                         width = info->width;
983                 if (info->height > 0)
984                         height = info->height;
985         }
986         
987         gdk_pixbuf_loader_set_size (loader, width, height);
988 }
989
990 /**
991  * gdk_pixbuf_new_from_file_at_size:
992  * @filename: Name of file to load, in the GLib file name encoding
993  * @width: The width the image should have or -1 to not constrain the width
994  * @height: The height the image should have or -1 to not constrain the height
995  * @error: Return location for an error
996  *
997  * Creates a new pixbuf by loading an image from a file.  The file format is
998  * detected automatically. If %NULL is returned, then @error will be set.
999  * Possible errors are in the #GDK_PIXBUF_ERROR and #G_FILE_ERROR domains.
1000  * The image will be scaled to fit in the requested size, preserving
1001  * the image's aspect ratio.
1002  *
1003  * Return value: A newly-created pixbuf with a reference count of 1, or 
1004  * %NULL if any of several error conditions occurred:  the file could not 
1005  * be opened, there was no loader for the file's format, there was not 
1006  * enough memory to allocate the image buffer, or the image file contained 
1007  * invalid data.
1008  *
1009  * Since: 2.4
1010  **/
1011 GdkPixbuf *
1012 gdk_pixbuf_new_from_file_at_size (const char *filename,
1013                                   int         width, 
1014                                   int         height,
1015                                   GError    **error)
1016 {
1017         return gdk_pixbuf_new_from_file_at_scale (filename, 
1018                                                   width, height, 
1019                                                   TRUE, error);
1020 }
1021
1022 #ifdef G_OS_WIN32
1023
1024 #undef gdk_pixbuf_new_from_file_at_size
1025
1026 GdkPixbuf *
1027 gdk_pixbuf_new_from_file_at_size (const char *filename,
1028                                   int         width, 
1029                                   int         height,
1030                                   GError    **error)
1031 {
1032         gchar *utf8_filename =
1033                 g_locale_to_utf8 (filename, -1, NULL, NULL, error);
1034         GdkPixbuf *retval;
1035
1036         if (utf8_filename == NULL)
1037                 return NULL;
1038
1039         retval = gdk_pixbuf_new_from_file_at_size_utf8 (utf8_filename,
1040                                                         width, height,
1041                                                         error);
1042
1043         g_free (utf8_filename);
1044
1045         return retval;
1046 }
1047 #endif
1048
1049 /**
1050  * gdk_pixbuf_new_from_file_at_scale:
1051  * @filename: Name of file to load, in the GLib file name encoding
1052  * @width: The width the image should have or -1 to not constrain the width
1053  * @height: The height the image should have or -1 to not constrain the height
1054  * @preserve_aspect_ratio: %TRUE to preserve the image's aspect ratio
1055  * @error: Return location for an error
1056  *
1057  * Creates a new pixbuf by loading an image from a file.  The file format is
1058  * detected automatically. If %NULL is returned, then @error will be set.
1059  * Possible errors are in the #GDK_PIXBUF_ERROR and #G_FILE_ERROR domains.
1060  * The image will be scaled to fit in the requested size, optionally preserving
1061  * the image's aspect ratio. 
1062  *
1063  * When preserving the aspect ratio, a @width of -1 will cause the image
1064  * to be scaled to the exact given height, and a @height of -1 will cause
1065  * the image to be scaled to the exact given width. When not preserving
1066  * aspect ratio, a @width or @height of -1 means to not scale the image 
1067  * at all in that dimension. Negative values for @width and @height are 
1068  * allowed since 2.8.
1069  *
1070  * Return value: A newly-created pixbuf with a reference count of 1, or %NULL 
1071  * if any of several error conditions occurred:  the file could not be opened,
1072  * there was no loader for the file's format, there was not enough memory to
1073  * allocate the image buffer, or the image file contained invalid data.
1074  *
1075  * Since: 2.6
1076  **/
1077 GdkPixbuf *
1078 gdk_pixbuf_new_from_file_at_scale (const char *filename,
1079                                    int         width, 
1080                                    int         height,
1081                                    gboolean    preserve_aspect_ratio,
1082                                    GError    **error)
1083 {
1084
1085         GdkPixbufLoader *loader;
1086         GdkPixbuf       *pixbuf;
1087
1088         guchar buffer [4096];
1089         int length;
1090         FILE *f;
1091         struct {
1092                 gint width;
1093                 gint height;
1094                 gboolean preserve_aspect_ratio;
1095         } info;
1096
1097         g_return_val_if_fail (filename != NULL, NULL);
1098         g_return_val_if_fail (width > 0 || width == -1, NULL);
1099         g_return_val_if_fail (height > 0 || height == -1, NULL);
1100
1101         f = g_fopen (filename, "rb");
1102         if (!f) {
1103                 gchar *display_name = g_filename_display_name (filename);
1104                 g_set_error (error,
1105                              G_FILE_ERROR,
1106                              g_file_error_from_errno (errno),
1107                              _("Failed to open file '%s': %s"),
1108                              display_name,
1109                              g_strerror (errno));
1110                 g_free (display_name);
1111                 return NULL;
1112         }
1113
1114         loader = gdk_pixbuf_loader_new ();
1115
1116         info.width = width;
1117         info.height = height;
1118         info.preserve_aspect_ratio = preserve_aspect_ratio;
1119
1120         g_signal_connect (loader, "size-prepared", G_CALLBACK (size_prepared_cb), &info);
1121
1122         while (!feof (f) && !ferror (f)) {
1123                 length = fread (buffer, 1, sizeof (buffer), f);
1124                 if (length > 0)
1125                         if (!gdk_pixbuf_loader_write (loader, buffer, length, error)) {
1126                                 gdk_pixbuf_loader_close (loader, NULL);
1127                                 fclose (f);
1128                                 g_object_unref (loader);
1129                                 return NULL;
1130                         }
1131         }
1132
1133         fclose (f);
1134
1135         if (!gdk_pixbuf_loader_close (loader, error)) {
1136                 g_object_unref (loader);
1137                 return NULL;
1138         }
1139
1140         pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1141
1142         if (!pixbuf) {
1143                 gchar *display_name = g_filename_display_name (filename);
1144                 g_object_unref (loader);
1145                 g_set_error (error,
1146                              GDK_PIXBUF_ERROR,
1147                              GDK_PIXBUF_ERROR_FAILED,
1148                              _("Failed to load image '%s': reason not known, probably a corrupt image file"),
1149                              display_name);
1150                 g_free (display_name);
1151                 return NULL;
1152         }
1153
1154         g_object_ref (pixbuf);
1155
1156         g_object_unref (loader);
1157
1158         return pixbuf;
1159 }
1160
1161 #ifdef G_OS_WIN32
1162
1163 #undef gdk_pixbuf_new_from_file_at_scale
1164
1165 GdkPixbuf *
1166 gdk_pixbuf_new_from_file_at_scale (const char *filename,
1167                                    int         width, 
1168                                    int         height,
1169                                    gboolean    preserve_aspect_ratio,
1170                                    GError    **error)
1171 {
1172         gchar *utf8_filename =
1173                 g_locale_to_utf8 (filename, -1, NULL, NULL, error);
1174         GdkPixbuf *retval;
1175
1176         if (utf8_filename == NULL)
1177                 return NULL;
1178
1179         retval = gdk_pixbuf_new_from_file_at_scale_utf8 (utf8_filename,
1180                                                          width, height,
1181                                                          preserve_aspect_ratio,
1182                                                          error);
1183
1184         g_free (utf8_filename);
1185
1186         return retval;
1187 }
1188 #endif
1189
1190
1191 static void
1192 info_cb (GdkPixbufLoader *loader, 
1193          int              width,
1194          int              height,
1195          gpointer         data)
1196 {
1197         struct {
1198                 GdkPixbufFormat *format;
1199                 int width;
1200                 int height;
1201         } *info = data;
1202
1203         g_return_if_fail (width > 0 && height > 0);
1204
1205         info->format = gdk_pixbuf_loader_get_format (loader);
1206         info->width = width;
1207         info->height = height;
1208
1209         gdk_pixbuf_loader_set_size (loader, 0, 0);
1210 }
1211
1212 /**
1213  * gdk_pixbuf_get_file_info:
1214  * @filename: The name of the file to identify.
1215  * @width: Return location for the width of the image, or %NULL
1216  * @height: Return location for the height of the image, or %NULL
1217  * 
1218  * Parses an image file far enough to determine its format and size.
1219  * 
1220  * Returns: A #GdkPixbufFormat describing the image format of the file 
1221  *    or %NULL if the image format wasn't recognized. The return value 
1222  *    is owned by GdkPixbuf and should not be freed.
1223  *
1224  * Since: 2.4
1225  **/
1226 GdkPixbufFormat *
1227 gdk_pixbuf_get_file_info (const gchar  *filename,
1228                           gint         *width, 
1229                           gint         *height)
1230 {
1231         GdkPixbufLoader *loader;
1232         guchar buffer [4096];
1233         int length;
1234         FILE *f;
1235         struct {
1236                 GdkPixbufFormat *format;
1237                 gint width;
1238                 gint height;
1239         } info;
1240
1241         g_return_val_if_fail (filename != NULL, NULL);
1242
1243         f = g_fopen (filename, "rb");
1244         if (!f)
1245                 return NULL;
1246
1247         loader = gdk_pixbuf_loader_new ();
1248
1249         info.format = NULL;
1250         info.width = -1;
1251         info.height = -1;
1252                 
1253         g_signal_connect (loader, "size-prepared", G_CALLBACK (info_cb), &info);
1254
1255         while (!feof (f) && !ferror (f)) {
1256                 length = fread (buffer, 1, sizeof (buffer), f);
1257                 if (length > 0) {
1258                         if (!gdk_pixbuf_loader_write (loader, buffer, length, NULL))
1259                                 break;
1260                 }
1261                 if (info.format != NULL)
1262                         break;
1263         }
1264
1265         fclose (f);
1266         gdk_pixbuf_loader_close (loader, NULL);
1267         g_object_unref (loader);
1268
1269         if (width) 
1270                 *width = info.width;
1271         if (height) 
1272                 *height = info.height;
1273
1274         return info.format;
1275 }
1276
1277 /**
1278  * gdk_pixbuf_new_from_xpm_data:
1279  * @data: Pointer to inline XPM data.
1280  *
1281  * Creates a new pixbuf by parsing XPM data in memory.  This data is commonly
1282  * the result of including an XPM file into a program's C source.
1283  *
1284  * Return value: A newly-created pixbuf with a reference count of 1.
1285  **/
1286 GdkPixbuf *
1287 gdk_pixbuf_new_from_xpm_data (const char **data)
1288 {
1289         GdkPixbuf *(* load_xpm_data) (const char **data);
1290         GdkPixbuf *pixbuf;
1291         GError *error = NULL;
1292         GdkPixbufModule *xpm_module;
1293         gboolean locked;
1294
1295         xpm_module = _gdk_pixbuf_get_named_module ("xpm", &error);
1296         if (xpm_module == NULL) {
1297                 g_warning ("Error loading XPM image loader: %s", error->message);
1298                 g_error_free (error);
1299                 return NULL;
1300         }
1301
1302         if (xpm_module->module == NULL) {
1303                 if (!_gdk_pixbuf_load_module (xpm_module, &error)) {
1304                         g_warning ("Error loading XPM image loader: %s", error->message);
1305                         g_error_free (error);
1306                         return NULL;
1307                 }
1308         }
1309
1310         locked = _gdk_pixbuf_lock (xpm_module);
1311
1312         if (xpm_module->load_xpm_data == NULL) {
1313                 g_warning ("gdk-pixbuf XPM module lacks XPM data capability");
1314                 pixbuf = NULL;
1315         } else {
1316                 load_xpm_data = xpm_module->load_xpm_data;
1317                 pixbuf = (* load_xpm_data) (data);
1318         }
1319         
1320         if (locked)
1321                 _gdk_pixbuf_unlock (xpm_module);
1322         return pixbuf;
1323 }
1324
1325 static void
1326 collect_save_options (va_list   opts,
1327                       gchar  ***keys,
1328                       gchar  ***vals)
1329 {
1330   gchar *key;
1331   gchar *val;
1332   gchar *next;
1333   gint count;
1334
1335   count = 0;
1336   *keys = NULL;
1337   *vals = NULL;
1338   
1339   next = va_arg (opts, gchar*);
1340   while (next)
1341     {
1342       key = next;
1343       val = va_arg (opts, gchar*);
1344
1345       ++count;
1346
1347       /* woo, slow */
1348       *keys = g_realloc (*keys, sizeof(gchar*) * (count + 1));
1349       *vals = g_realloc (*vals, sizeof(gchar*) * (count + 1));
1350       
1351       (*keys)[count-1] = g_strdup (key);
1352       (*vals)[count-1] = g_strdup (val);
1353
1354       (*keys)[count] = NULL;
1355       (*vals)[count] = NULL;
1356       
1357       next = va_arg (opts, gchar*);
1358     }
1359 }
1360
1361 static gboolean
1362 save_to_file_callback (const gchar *buf,
1363                        gsize        count,
1364                        GError     **error,
1365                        gpointer     data)
1366 {
1367         FILE *filehandle = data;
1368         gsize n;
1369
1370         n = fwrite (buf, 1, count, filehandle);
1371         if (n != count) {
1372                 g_set_error (error,
1373                              G_FILE_ERROR,
1374                              g_file_error_from_errno (errno),
1375                              _("Error writing to image file: %s"),
1376                              g_strerror (errno));
1377                 return FALSE;
1378         }
1379         return TRUE;
1380 }
1381
1382 static gboolean
1383 gdk_pixbuf_real_save (GdkPixbuf     *pixbuf, 
1384                       FILE          *filehandle, 
1385                       const char    *type, 
1386                       gchar        **keys,
1387                       gchar        **values,
1388                       GError       **error)
1389 {
1390         gboolean ret;
1391         GdkPixbufModule *image_module = NULL;       
1392         gboolean locked;
1393
1394         image_module = _gdk_pixbuf_get_named_module (type, error);
1395
1396         if (image_module == NULL)
1397                 return FALSE;
1398        
1399         if (image_module->module == NULL)
1400                 if (!_gdk_pixbuf_load_module (image_module, error))
1401                         return FALSE;
1402
1403         locked = _gdk_pixbuf_lock (image_module);
1404
1405         if (image_module->save) {
1406                 /* save normally */
1407                 ret = (* image_module->save) (filehandle, pixbuf,
1408                                               keys, values,
1409                                               error);
1410         } else if (image_module->save_to_callback) {
1411                 /* save with simple callback */
1412                 ret = (* image_module->save_to_callback) (save_to_file_callback,
1413                                                           filehandle, pixbuf,
1414                                                           keys, values,
1415                                                           error);
1416         } else {
1417                 /* can't save */
1418                 g_set_error (error,
1419                              GDK_PIXBUF_ERROR,
1420                              GDK_PIXBUF_ERROR_UNSUPPORTED_OPERATION,
1421                              _("This build of gdk-pixbuf does not support saving the image format: %s"),
1422                              type);
1423                 ret = FALSE;
1424         }
1425
1426         if (locked)
1427                 _gdk_pixbuf_unlock (image_module);
1428         return ret;
1429 }
1430
1431 #define TMP_FILE_BUF_SIZE 4096
1432
1433 static gboolean
1434 save_to_callback_with_tmp_file (GdkPixbufModule   *image_module,
1435                                 GdkPixbuf         *pixbuf,
1436                                 GdkPixbufSaveFunc  save_func,
1437                                 gpointer           user_data,
1438                                 gchar            **keys,
1439                                 gchar            **values,
1440                                 GError           **error)
1441 {
1442         int fd;
1443         FILE *f = NULL;
1444         gboolean retval = FALSE;
1445         gchar *buf = NULL;
1446         gsize n;
1447         gchar *filename = NULL;
1448         gboolean locked;
1449
1450         buf = g_try_malloc (TMP_FILE_BUF_SIZE);
1451         if (buf == NULL) {
1452                 g_set_error (error,
1453                              GDK_PIXBUF_ERROR,
1454                              GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
1455                              _("Insufficient memory to save image to callback"));
1456                 goto end;
1457         }
1458
1459         fd = g_file_open_tmp ("gdkpixbuf-save-tmp.XXXXXX", &filename, error);
1460         if (fd == -1)
1461                 goto end;
1462         f = fdopen (fd, "wb+");
1463         if (f == NULL) {
1464                 g_set_error (error,
1465                              G_FILE_ERROR,
1466                              g_file_error_from_errno (errno),
1467                              _("Failed to open temporary file"));
1468                 goto end;
1469         }
1470
1471         locked = _gdk_pixbuf_lock (image_module);
1472         retval = (image_module->save) (f, pixbuf, keys, values, error);
1473         if (locked)
1474                 _gdk_pixbuf_unlock (image_module);
1475         if (!retval)
1476                 goto end;
1477
1478         rewind (f);
1479         for (;;) {
1480                 n = fread (buf, 1, TMP_FILE_BUF_SIZE, f);
1481                 if (n > 0) {
1482                         if (!save_func (buf, n, error, user_data))
1483                                 goto end;
1484                 }
1485                 if (n != TMP_FILE_BUF_SIZE) 
1486                         break;
1487         }
1488         if (ferror (f)) {
1489                 g_set_error (error,
1490                              G_FILE_ERROR,
1491                              g_file_error_from_errno (errno),
1492                              _("Failed to read from temporary file"));
1493                 goto end;
1494         }
1495         retval = TRUE;
1496
1497  end:
1498         /* cleanup and return retval */
1499         if (f)
1500                 fclose (f);
1501         if (filename) {
1502                 g_unlink (filename);
1503                 g_free (filename);
1504         }
1505         g_free (buf);
1506
1507         return retval;
1508 }
1509
1510 static gboolean
1511 gdk_pixbuf_real_save_to_callback (GdkPixbuf         *pixbuf,
1512                                   GdkPixbufSaveFunc  save_func,
1513                                   gpointer           user_data,
1514                                   const char        *type, 
1515                                   gchar            **keys,
1516                                   gchar            **values,
1517                                   GError           **error)
1518 {
1519         gboolean ret;
1520         GdkPixbufModule *image_module = NULL;       
1521         gboolean locked;
1522
1523         image_module = _gdk_pixbuf_get_named_module (type, error);
1524
1525         if (image_module == NULL)
1526                 return FALSE;
1527        
1528         if (image_module->module == NULL)
1529                 if (!_gdk_pixbuf_load_module (image_module, error))
1530                         return FALSE;
1531
1532         locked = _gdk_pixbuf_lock (image_module);
1533
1534         if (image_module->save_to_callback) {
1535                 /* save normally */
1536                 ret = (* image_module->save_to_callback) (save_func, user_data, 
1537                                                           pixbuf, keys, values,
1538                                                           error);
1539         } else if (image_module->save) {
1540                 /* use a temporary file */
1541                 ret = save_to_callback_with_tmp_file (image_module, pixbuf,
1542                                                       save_func, user_data, 
1543                                                       keys, values,
1544                                                       error);
1545         } else {
1546                 /* can't save */
1547                 g_set_error (error,
1548                              GDK_PIXBUF_ERROR,
1549                              GDK_PIXBUF_ERROR_UNSUPPORTED_OPERATION,
1550                              _("This build of gdk-pixbuf does not support saving the image format: %s"),
1551                              type);
1552                 ret = FALSE;
1553         }
1554
1555         if (locked)
1556                 _gdk_pixbuf_unlock (image_module);
1557         return ret;
1558 }
1559
1560  
1561 /**
1562  * gdk_pixbuf_save:
1563  * @pixbuf: a #GdkPixbuf.
1564  * @filename: name of file to save.
1565  * @type: name of file format.
1566  * @error: return location for error, or %NULL
1567  * @Varargs: list of key-value save options
1568  *
1569  * Saves pixbuf to a file in format @type. By default, "jpeg", "png", "ico" 
1570  * and "bmp" are possible file formats to save in, but more formats may be
1571  * installed. The list of all writable formats can be determined in the 
1572  * following way:
1573  *
1574  * <informalexample><programlisting>
1575  * void add_if_writable (GdkPixbufFormat *data, GSList **list)
1576  * {
1577  *   if (gdk_pixbuf_format_is_writable (data))
1578  *     *list = g_slist_prepend (*list, data);
1579  * }
1580  * <!-- -->
1581  * GSList *formats = gdk_pixbuf_get_formats (<!-- -->);
1582  * GSList *writable_formats = NULL;
1583  * g_slist_foreach (formats, add_if_writable, &amp;writable_formats);
1584  * g_slist_free (formats);
1585  * </programlisting></informalexample>
1586  *
1587  * If @error is set, %FALSE will be returned. Possible errors include 
1588  * those in the #GDK_PIXBUF_ERROR domain and those in the #G_FILE_ERROR domain.
1589  *
1590  * The variable argument list should be %NULL-terminated; if not empty,
1591  * it should contain pairs of strings that modify the save
1592  * parameters. For example:
1593  * <informalexample><programlisting>
1594  * gdk_pixbuf_save (pixbuf, handle, "jpeg", &amp;error,
1595  *                  "quality", "100", NULL);
1596  * </programlisting></informalexample>
1597  *
1598  * Currently only few parameters exist. JPEG images can be saved with a
1599  * "quality" parameter; its value should be in the range [0,100].
1600  *
1601  * Text chunks can be attached to PNG images by specifying parameters of
1602  * the form "tEXt::key", where key is an ASCII string of length 1-79.
1603  * The values are UTF-8 encoded strings. The PNG compression level can
1604  * be specified using the "compression" parameter; it's value is in an
1605  * integer in the range of [0,9].
1606  *
1607  * ICO images can be saved in depth 16, 24, or 32, by using the "depth"
1608  * parameter. When the ICO saver is given "x_hot" and "y_hot" parameters,
1609  * it produces a CUR instead of an ICO.
1610  *
1611  * Return value: whether an error was set
1612  **/
1613
1614 gboolean
1615 gdk_pixbuf_save (GdkPixbuf  *pixbuf, 
1616                  const char *filename, 
1617                  const char *type, 
1618                  GError    **error,
1619                  ...)
1620 {
1621         gchar **keys = NULL;
1622         gchar **values = NULL;
1623         va_list args;
1624         gboolean result;
1625
1626         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1627         
1628         va_start (args, error);
1629         
1630         collect_save_options (args, &keys, &values);
1631         
1632         va_end (args);
1633
1634         result = gdk_pixbuf_savev (pixbuf, filename, type,
1635                                    keys, values,
1636                                    error);
1637
1638         g_strfreev (keys);
1639         g_strfreev (values);
1640
1641         return result;
1642 }
1643
1644 #ifdef G_OS_WIN32
1645
1646 #undef gdk_pixbuf_save
1647
1648 gboolean
1649 gdk_pixbuf_save (GdkPixbuf  *pixbuf, 
1650                  const char *filename, 
1651                  const char *type, 
1652                  GError    **error,
1653                  ...)
1654 {
1655         char *utf8_filename;
1656         gchar **keys = NULL;
1657         gchar **values = NULL;
1658         va_list args;
1659         gboolean result;
1660
1661         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1662         
1663         utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, error);
1664
1665         if (utf8_filename == NULL)
1666                 return FALSE;
1667
1668         va_start (args, error);
1669         
1670         collect_save_options (args, &keys, &values);
1671         
1672         va_end (args);
1673
1674         result = gdk_pixbuf_savev_utf8 (pixbuf, utf8_filename, type,
1675                                         keys, values,
1676                                         error);
1677
1678         g_free (utf8_filename);
1679
1680         g_strfreev (keys);
1681         g_strfreev (values);
1682
1683         return result;
1684 }
1685
1686 #endif
1687
1688 /**
1689  * gdk_pixbuf_savev:
1690  * @pixbuf: a #GdkPixbuf.
1691  * @filename: name of file to save.
1692  * @type: name of file format.
1693  * @option_keys: name of options to set, %NULL-terminated
1694  * @option_values: values for named options
1695  * @error: return location for error, or %NULL
1696  *
1697  * Saves pixbuf to a file in @type, which is currently "jpeg", "png", "ico" or "bmp".
1698  * If @error is set, %FALSE will be returned. 
1699  * See gdk_pixbuf_save () for more details.
1700  *
1701  * Return value: whether an error was set
1702  **/
1703
1704 gboolean
1705 gdk_pixbuf_savev (GdkPixbuf  *pixbuf, 
1706                   const char *filename, 
1707                   const char *type,
1708                   char      **option_keys,
1709                   char      **option_values,
1710                   GError    **error)
1711 {
1712         FILE *f = NULL;
1713         gboolean result;
1714        
1715         g_return_val_if_fail (filename != NULL, FALSE);
1716         g_return_val_if_fail (type != NULL, FALSE);
1717         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1718        
1719         f = g_fopen (filename, "wb");
1720         
1721         if (f == NULL) {
1722                 gchar *display_name = g_filename_display_name (filename);
1723                 g_set_error (error,
1724                              G_FILE_ERROR,
1725                              g_file_error_from_errno (errno),
1726                              _("Failed to open '%s' for writing: %s"),
1727                              display_name,
1728                              g_strerror (errno));
1729                 g_free (display_name);
1730                 return FALSE;
1731         }
1732
1733        
1734        result = gdk_pixbuf_real_save (pixbuf, f, type,
1735                                       option_keys, option_values,
1736                                       error);
1737        
1738        
1739        if (!result) {
1740                g_return_val_if_fail (error == NULL || *error != NULL, FALSE);
1741                fclose (f);
1742                return FALSE;
1743        }
1744
1745        if (fclose (f) < 0) {
1746                gchar *display_name = g_filename_display_name (filename);
1747                g_set_error (error,
1748                             G_FILE_ERROR,
1749                             g_file_error_from_errno (errno),
1750                             _("Failed to close '%s' while writing image, all data may not have been saved: %s"),
1751                             display_name,
1752                             g_strerror (errno));
1753                g_free (display_name);
1754                return FALSE;
1755        }
1756        
1757        return TRUE;
1758 }
1759
1760 #ifdef G_OS_WIN32
1761
1762 #undef gdk_pixbuf_savev
1763
1764 gboolean
1765 gdk_pixbuf_savev (GdkPixbuf  *pixbuf, 
1766                   const char *filename, 
1767                   const char *type,
1768                   char      **option_keys,
1769                   char      **option_values,
1770                   GError    **error)
1771 {
1772         char *utf8_filename;
1773         gboolean retval;
1774
1775         g_return_val_if_fail (filename != NULL, FALSE);
1776        
1777         utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, error);
1778
1779         if (utf8_filename == NULL)
1780                 return FALSE;
1781
1782         retval = gdk_pixbuf_savev_utf8 (pixbuf, utf8_filename, type,
1783                                         option_keys, option_values, error);
1784
1785         g_free (utf8_filename);
1786
1787         return retval;
1788 }
1789
1790 #endif
1791
1792 /**
1793  * gdk_pixbuf_save_to_callback:
1794  * @pixbuf: a #GdkPixbuf.
1795  * @save_func: a function that is called to save each block of data that
1796  *   the save routine generates.
1797  * @user_data: user data to pass to the save function.
1798  * @type: name of file format.
1799  * @error: return location for error, or %NULL
1800  * @Varargs: list of key-value save options
1801  *
1802  * Saves pixbuf in format @type by feeding the produced data to a 
1803  * callback. Can be used when you want to store the image to something 
1804  * other than a file, such as an in-memory buffer or a socket.  
1805  * If @error is set, %FALSE will be returned. Possible errors
1806  * include those in the #GDK_PIXBUF_ERROR domain and whatever the save
1807  * function generates.
1808  *
1809  * See gdk_pixbuf_save() for more details.
1810  *
1811  * Return value: whether an error was set
1812  *
1813  * Since: 2.4
1814  **/
1815 gboolean
1816 gdk_pixbuf_save_to_callback    (GdkPixbuf  *pixbuf,
1817                                 GdkPixbufSaveFunc save_func,
1818                                 gpointer user_data,
1819                                 const char *type, 
1820                                 GError    **error,
1821                                 ...)
1822 {
1823         gchar **keys = NULL;
1824         gchar **values = NULL;
1825         va_list args;
1826         gboolean result;
1827         
1828         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1829         
1830         va_start (args, error);
1831         
1832         collect_save_options (args, &keys, &values);
1833         
1834         va_end (args);
1835
1836         result = gdk_pixbuf_save_to_callbackv (pixbuf, save_func, user_data,
1837                                                type, keys, values,
1838                                                error);
1839
1840         g_strfreev (keys);
1841         g_strfreev (values);
1842
1843         return result;
1844 }
1845
1846 /**
1847  * gdk_pixbuf_save_to_callbackv:
1848  * @pixbuf: a #GdkPixbuf.
1849  * @save_func: a function that is called to save each block of data that
1850  *   the save routine generates.
1851  * @user_data: user data to pass to the save function.
1852  * @type: name of file format.
1853  * @option_keys: name of options to set, %NULL-terminated
1854  * @option_values: values for named options
1855  * @error: return location for error, or %NULL
1856  *
1857  * Saves pixbuf to a callback in format @type, which is currently "jpeg",
1858  * "png", "ico" or "bmp".  If @error is set, %FALSE will be returned. See
1859  * gdk_pixbuf_save_to_callback () for more details.
1860  *
1861  * Return value: whether an error was set
1862  *
1863  * Since: 2.4
1864  **/
1865 gboolean
1866 gdk_pixbuf_save_to_callbackv   (GdkPixbuf  *pixbuf, 
1867                                 GdkPixbufSaveFunc save_func,
1868                                 gpointer user_data,
1869                                 const char *type,
1870                                 char      **option_keys,
1871                                 char      **option_values,
1872                                 GError    **error)
1873 {
1874         gboolean result;
1875         
1876        
1877         g_return_val_if_fail (save_func != NULL, FALSE);
1878         g_return_val_if_fail (type != NULL, FALSE);
1879         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1880        
1881        result = gdk_pixbuf_real_save_to_callback (pixbuf,
1882                                                   save_func, user_data, type,
1883                                                   option_keys, option_values,
1884                                                   error);
1885        
1886        if (!result) {
1887                g_return_val_if_fail (error == NULL || *error != NULL, FALSE);
1888                return FALSE;
1889        }
1890
1891        return TRUE;
1892 }
1893
1894 /**
1895  * gdk_pixbuf_save_to_buffer:
1896  * @pixbuf: a #GdkPixbuf.
1897  * @buffer: location to receive a pointer to the new buffer.
1898  * @buffer_size: location to receive the size of the new buffer.
1899  * @type: name of file format.
1900  * @error: return location for error, or %NULL
1901  * @Varargs: list of key-value save options
1902  *
1903  * Saves pixbuf to a new buffer in format @type, which is currently "jpeg",
1904  * "png", "ico" or "bmp".  This is a convenience function that uses
1905  * gdk_pixbuf_save_to_callback() to do the real work. Note that the buffer 
1906  * is not nul-terminated and may contain embedded  nuls.
1907  * If @error is set, %FALSE will be returned and @string will be set to
1908  * %NULL. Possible errors include those in the #GDK_PIXBUF_ERROR
1909  * domain.
1910  *
1911  * See gdk_pixbuf_save() for more details.
1912  *
1913  * Return value: whether an error was set
1914  *
1915  * Since: 2.4
1916  **/
1917 gboolean
1918 gdk_pixbuf_save_to_buffer      (GdkPixbuf  *pixbuf,
1919                                 gchar     **buffer,
1920                                 gsize      *buffer_size,
1921                                 const char *type, 
1922                                 GError    **error,
1923                                 ...)
1924 {
1925         gchar **keys = NULL;
1926         gchar **values = NULL;
1927         va_list args;
1928         gboolean result;
1929         
1930         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1931         
1932         va_start (args, error);
1933         
1934         collect_save_options (args, &keys, &values);
1935         
1936         va_end (args);
1937
1938         result = gdk_pixbuf_save_to_bufferv (pixbuf, buffer, buffer_size,
1939                                              type, keys, values,
1940                                              error);
1941
1942         g_strfreev (keys);
1943         g_strfreev (values);
1944
1945         return result;
1946 }
1947
1948 struct SaveToBufferData {
1949         gchar *buffer;
1950         gsize len, max;
1951 };
1952
1953 static gboolean
1954 save_to_buffer_callback (const gchar *data,
1955                          gsize count,
1956                          GError **error,
1957                          gpointer user_data)
1958 {
1959         struct SaveToBufferData *sdata = user_data;
1960         gchar *new_buffer;
1961         gsize new_max;
1962
1963         if (sdata->len + count > sdata->max) {
1964                 new_max = MAX (sdata->max*2, sdata->len + count);
1965                 new_buffer = g_try_realloc (sdata->buffer, new_max);
1966                 if (!new_buffer) {
1967                         g_set_error (error,
1968                                      GDK_PIXBUF_ERROR,
1969                                      GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
1970                                      _("Insufficient memory to save image into a buffer"));
1971                         return FALSE;
1972                 }
1973                 sdata->buffer = new_buffer;
1974                 sdata->max = new_max;
1975         }
1976         memcpy (sdata->buffer + sdata->len, data, count);
1977         sdata->len += count;
1978         return TRUE;
1979 }
1980
1981 /**
1982  * gdk_pixbuf_save_to_bufferv:
1983  * @pixbuf: a #GdkPixbuf.
1984  * @buffer: location to receive a pointer to the new buffer.
1985  * @buffer_size: location to receive the size of the new buffer.
1986  * @type: name of file format.
1987  * @option_keys: name of options to set, %NULL-terminated
1988  * @option_values: values for named options
1989  * @error: return location for error, or %NULL
1990  *
1991  * Saves pixbuf to a new buffer in format @type, which is currently "jpeg",
1992  * "png", "ico" or "bmp".  See gdk_pixbuf_save_to_buffer() for more details.
1993  *
1994  * Return value: whether an error was set
1995  *
1996  * Since: 2.4
1997  **/
1998 gboolean
1999 gdk_pixbuf_save_to_bufferv     (GdkPixbuf  *pixbuf,
2000                                 gchar     **buffer,
2001                                 gsize      *buffer_size,
2002                                 const char *type, 
2003                                 char      **option_keys,
2004                                 char      **option_values,
2005                                 GError    **error)
2006 {
2007         static const gint initial_max = 1024;
2008         struct SaveToBufferData sdata;
2009
2010         *buffer = NULL;
2011         *buffer_size = 0;
2012
2013         sdata.buffer = g_try_malloc (initial_max);
2014         sdata.max = initial_max;
2015         sdata.len = 0;
2016         if (!sdata.buffer) {
2017                 g_set_error (error,
2018                              GDK_PIXBUF_ERROR,
2019                              GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
2020                              _("Insufficient memory to save image into a buffer"));
2021                 return FALSE;
2022         }
2023
2024         if (!gdk_pixbuf_save_to_callbackv (pixbuf,
2025                                            save_to_buffer_callback, &sdata,
2026                                            type, option_keys, option_values,
2027                                            error)) {
2028                 g_free (sdata.buffer);
2029                 return FALSE;
2030         }
2031
2032         *buffer = sdata.buffer;
2033         *buffer_size = sdata.len;
2034         return TRUE;
2035 }
2036
2037 /**
2038  * gdk_pixbuf_format_get_name:
2039  * @format: a #GdkPixbufFormat
2040  *
2041  * Returns the name of the format.
2042  * 
2043  * Return value: the name of the format. 
2044  *
2045  * Since: 2.2
2046  */
2047 gchar *
2048 gdk_pixbuf_format_get_name (GdkPixbufFormat *format)
2049 {
2050         g_return_val_if_fail (format != NULL, NULL);
2051
2052         return g_strdup (format->name);
2053 }
2054
2055 /**
2056  * gdk_pixbuf_format_get_description:
2057  * @format: a #GdkPixbufFormat
2058  *
2059  * Returns a description of the format.
2060  * 
2061  * Return value: a description of the format.
2062  *
2063  * Since: 2.2
2064  */
2065 gchar *
2066 gdk_pixbuf_format_get_description (GdkPixbufFormat *format)
2067 {
2068         gchar *domain;
2069         gchar *description;
2070         g_return_val_if_fail (format != NULL, NULL);
2071
2072         if (format->domain != NULL) 
2073                 domain = format->domain;
2074         else 
2075                 domain = GETTEXT_PACKAGE;
2076         description = dgettext (domain, format->description);
2077
2078         return g_strdup (description);
2079 }
2080
2081 /**
2082  * gdk_pixbuf_format_get_mime_types:
2083  * @format: a #GdkPixbufFormat
2084  *
2085  * Returns the mime types supported by the format.
2086  * 
2087  * Return value: a %NULL-terminated array of mime types which must be freed with 
2088  * g_strfreev() when it is no longer needed.
2089  *
2090  * Since: 2.2
2091  */
2092 gchar **
2093 gdk_pixbuf_format_get_mime_types (GdkPixbufFormat *format)
2094 {
2095         g_return_val_if_fail (format != NULL, NULL);
2096
2097         return g_strdupv (format->mime_types);
2098 }
2099
2100 /**
2101  * gdk_pixbuf_format_get_extensions:
2102  * @format: a #GdkPixbufFormat
2103  *
2104  * Returns the filename extensions typically used for files in the 
2105  * given format.
2106  * 
2107  * Return value: a %NULL-terminated array of filename extensions which must be
2108  * freed with g_strfreev() when it is no longer needed.
2109  *
2110  * Since: 2.2
2111  */
2112 gchar **
2113 gdk_pixbuf_format_get_extensions (GdkPixbufFormat *format)
2114 {
2115         g_return_val_if_fail (format != NULL, NULL);
2116
2117         return g_strdupv (format->extensions);
2118 }
2119
2120 /**
2121  * gdk_pixbuf_format_is_writable:
2122  * @format: a #GdkPixbufFormat
2123  *
2124  * Returns whether pixbufs can be saved in the given format.
2125  * 
2126  * Return value: whether pixbufs can be saved in the given format.
2127  *
2128  * Since: 2.2
2129  */
2130 gboolean
2131 gdk_pixbuf_format_is_writable (GdkPixbufFormat *format)
2132 {
2133         g_return_val_if_fail (format != NULL, FALSE);
2134
2135         return (format->flags & GDK_PIXBUF_FORMAT_WRITABLE) != 0;
2136 }
2137
2138 /**
2139  * gdk_pixbuf_format_is_scalable:
2140  * @format: a #GdkPixbufFormat
2141  *
2142  * Returns whether this image format is scalable. If a file is in a 
2143  * scalable format, it is preferable to load it at the desired size, 
2144  * rather than loading it at the default size and scaling the 
2145  * resulting pixbuf to the desired size.
2146  * 
2147  * Return value: whether this image format is scalable.
2148  *
2149  * Since: 2.6
2150  */
2151 gboolean
2152 gdk_pixbuf_format_is_scalable (GdkPixbufFormat *format)
2153 {
2154         g_return_val_if_fail (format != NULL, FALSE);
2155
2156         return (format->flags & GDK_PIXBUF_FORMAT_SCALABLE) != 0;
2157 }
2158
2159 /**
2160  * gdk_pixbuf_format_is_disabled:
2161  * @format: a #GdkPixbufFormat
2162  *
2163  * Returns whether this image format is disabled. See
2164  * gdk_pixbuf_format_set_disabled().
2165  * 
2166  * Return value: whether this image format is disabled.
2167  *
2168  * Since: 2.6
2169  */
2170 gboolean   
2171 gdk_pixbuf_format_is_disabled (GdkPixbufFormat *format)
2172 {
2173         g_return_val_if_fail (format != NULL, FALSE);
2174
2175         return format->disabled;        
2176 }
2177
2178 /**
2179  * gdk_pixbuf_format_set_disabled:
2180  * @format: a #GdkPixbufFormat
2181  * @disabled: %TRUE to disable the format @format
2182  *
2183  * Disables or enables an image format. If a format is disabled, 
2184  * gdk-pixbuf won't use the image loader for this format to load 
2185  * images. Applications can use this to avoid using image loaders 
2186  * with an inappropriate license, see gdk_pixbuf_format_get_license().
2187  *
2188  * Since: 2.6
2189  */
2190 void 
2191 gdk_pixbuf_format_set_disabled (GdkPixbufFormat *format,
2192                                 gboolean         disabled)
2193 {
2194         g_return_if_fail (format != NULL);
2195         
2196         format->disabled = disabled != FALSE;
2197 }
2198
2199 /**
2200  * gdk_pixbuf_format_get_license:
2201  * @format: a #GdkPixbufFormat
2202  *
2203  * Returns information about the license of the image loader
2204  * for the format. The returned string should be a shorthand for 
2205  * a wellknown license, e.g. "LGPL", "GPL", "QPL", "GPL/QPL",
2206  * or "other" to indicate some other license.  
2207  *
2208  * Returns: a string describing the license of @format. 
2209  *
2210  * Since: 2.6
2211  */
2212 gchar*
2213 gdk_pixbuf_format_get_license (GdkPixbufFormat *format)
2214 {
2215         g_return_val_if_fail (format != NULL, NULL);
2216
2217         return g_strdup (format->license);
2218 }
2219
2220 GdkPixbufFormat *
2221 _gdk_pixbuf_get_format (GdkPixbufModule *module)
2222 {
2223         g_return_val_if_fail (module != NULL, NULL);
2224
2225         return module->info;
2226 }
2227
2228 /**
2229  * gdk_pixbuf_get_formats:
2230  *
2231  * Obtains the available information about the image formats supported
2232  * by GdkPixbuf.
2233  *
2234  * Returns: A list of #GdkPixbufFormat<!-- -->s describing the supported 
2235  * image formats.  The list should be freed when it is no longer needed, 
2236  * but the structures themselves are owned by #GdkPixbuf and should not be 
2237  * freed.  
2238  *
2239  * Since: 2.2
2240  */
2241 GSList *
2242 gdk_pixbuf_get_formats (void)
2243 {
2244         GSList *result = NULL;
2245         GSList *modules;
2246
2247         for (modules = get_file_formats (); modules; modules = g_slist_next (modules)) {
2248                 GdkPixbufModule *module = (GdkPixbufModule *)modules->data;
2249                 GdkPixbufFormat *info = _gdk_pixbuf_get_format (module);
2250                 result = g_slist_prepend (result, info);
2251         }
2252
2253         return result;
2254 }
2255
2256
2257 #define __GDK_PIXBUF_IO_C__
2258 #include "gdk-pixbuf-aliasdef.c"
2259
2260
2261
2262