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