]> Pileus Git - ~andy/gtk/blob - gdk-pixbuf/gdk-pixbuf-loader.c
Remove GLIB_DIVERT_BEFORE_HELP() on initialization of gdktarget, that was
[~andy/gtk] / gdk-pixbuf / gdk-pixbuf-loader.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
2 /* GdkPixbuf library - Progressive loader object
3  *
4  * Copyright (C) 1999 The Free Software Foundation
5  *
6  * Authors: Mark Crichton <crichton@gimp.org>
7  *          Miguel de Icaza <miguel@gnu.org>
8  *          Federico Mena-Quintero <federico@gimp.org>
9  *          Jonathan Blandford <jrb@redhat.com>
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation; either
14  * version 2 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with this library; if not, write to the
23  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24  * Boston, MA 02111-1307, USA.
25  */
26
27 #include <config.h>
28 #include <string.h>
29
30 #include "gdk-pixbuf-alias.h"
31 #include "gdk-pixbuf-private.h"
32 #include "gdk-pixbuf-animation.h"
33 #include "gdk-pixbuf-io.h"
34 #include "gdk-pixbuf-loader.h"
35 #include "gdk-pixbuf-marshal.h"
36
37 enum {
38         SIZE_PREPARED,
39         AREA_PREPARED,
40         AREA_UPDATED,
41         CLOSED,
42         LAST_SIGNAL
43 };
44
45
46 static void gdk_pixbuf_loader_class_init    (GdkPixbufLoaderClass   *klass);
47 static void gdk_pixbuf_loader_init          (GdkPixbufLoader        *loader);
48 static void gdk_pixbuf_loader_finalize      (GObject                *loader);
49
50 static gpointer parent_class = NULL;
51 static guint    pixbuf_loader_signals[LAST_SIGNAL] = { 0 };
52
53 /* Internal data */
54
55 #define LOADER_HEADER_SIZE 128
56
57 typedef struct
58 {
59         GdkPixbufAnimation *animation;
60         gboolean closed;
61         gboolean holds_threadlock;
62         guchar header_buf[LOADER_HEADER_SIZE];
63         gint header_buf_offset;
64         GdkPixbufModule *image_module;
65         gpointer context;
66         gint width;
67         gint height;
68         gboolean size_fixed;
69         gboolean needs_scale;
70 } GdkPixbufLoaderPrivate;
71
72
73 /**
74  * gdk_pixbuf_loader_get_type:
75  *
76  * Registers the #GdkPixbufLoader class if necessary, and returns the type ID
77  * associated to it.
78  *
79  * Return value: The type ID of the #GdkPixbufLoader class.
80  **/
81 GType
82 gdk_pixbuf_loader_get_type (void)
83 {
84         static GType loader_type = 0;
85   
86         if (!loader_type)
87                 {
88                         static const GTypeInfo loader_info = {
89                                 sizeof (GdkPixbufLoaderClass),
90                                 (GBaseInitFunc) NULL,
91                                 (GBaseFinalizeFunc) NULL,
92                                 (GClassInitFunc) gdk_pixbuf_loader_class_init,
93                                 NULL,           /* class_finalize */
94                                 NULL,           /* class_data */
95                                 sizeof (GdkPixbufLoader),
96                                 0,              /* n_preallocs */
97                                 (GInstanceInitFunc) gdk_pixbuf_loader_init
98                         };
99       
100                         loader_type = g_type_register_static (G_TYPE_OBJECT,
101                                                               "GdkPixbufLoader",
102                                                               &loader_info,
103                                                               0);
104                 }
105   
106         return loader_type;
107 }
108
109 static void
110 gdk_pixbuf_loader_class_init (GdkPixbufLoaderClass *class)
111 {
112         GObjectClass *object_class;
113   
114         object_class = (GObjectClass *) class;
115   
116         parent_class = g_type_class_peek_parent (class);
117   
118         object_class->finalize = gdk_pixbuf_loader_finalize;
119
120         /**
121          * GdkPixbufLoader::size-prepared:
122          * @loader: the object which received the signal.
123          * @width: the original width of the image
124          * @height: the original height of the image
125          *
126          * This signal is emitted when the pixbuf loader has been fed the
127          * initial amount of data that is required to figure out the size
128          * of the image that it will create.  Applications can call  
129          * gdk_pixbuf_loader_set_size() in response to this signal to set
130          * the desired size to which the image should be scaled.
131          */
132         pixbuf_loader_signals[SIZE_PREPARED] =
133                 g_signal_new ("size_prepared",
134                               G_TYPE_FROM_CLASS (object_class),
135                               G_SIGNAL_RUN_LAST,
136                               G_STRUCT_OFFSET (GdkPixbufLoaderClass, size_prepared),
137                               NULL, NULL,
138                               _gdk_pixbuf_marshal_VOID__INT_INT,
139                               G_TYPE_NONE, 2, 
140                               G_TYPE_INT,
141                               G_TYPE_INT);
142   
143         /**
144          * GdkPixbufLoader::area-prepared:
145          * @loader: the object which received the signal.
146          *
147          * This signal is emitted when the pixbuf loader has allocated the 
148          * pixbuf in the desired size.  After this signal is emitted, 
149          * applications can call gdk_pixbuf_loader_get_pixbuf() to fetch 
150          * the partially-loaded pixbuf.
151          */
152         pixbuf_loader_signals[AREA_PREPARED] =
153                 g_signal_new ("area_prepared",
154                               G_TYPE_FROM_CLASS (object_class),
155                               G_SIGNAL_RUN_LAST,
156                               G_STRUCT_OFFSET (GdkPixbufLoaderClass, area_prepared),
157                               NULL, NULL,
158                               _gdk_pixbuf_marshal_VOID__VOID,
159                               G_TYPE_NONE, 0);
160
161         /**
162          * GdkPixbufLoader::area-updated:
163          * @loader: the object which received the signal.
164          * @x: X offset of upper-left corner of the updated area.
165          * @y: Y offset of upper-left corner of the updated area.
166          * @width: Width of updated area.
167          * @height: Height of updated area.
168          *
169          * This signal is emitted when a significant area of the image being
170          * loaded has been updated.  Normally it means that a complete
171          * scanline has been read in, but it could be a different area as
172          * well.  Applications can use this signal to know when to repaint
173          * areas of an image that is being loaded.
174          */
175         pixbuf_loader_signals[AREA_UPDATED] =
176                 g_signal_new ("area_updated",
177                               G_TYPE_FROM_CLASS (object_class),
178                               G_SIGNAL_RUN_LAST,
179                               G_STRUCT_OFFSET (GdkPixbufLoaderClass, area_updated),
180                               NULL, NULL,
181                               _gdk_pixbuf_marshal_VOID__INT_INT_INT_INT,
182                               G_TYPE_NONE, 4,
183                               G_TYPE_INT,
184                               G_TYPE_INT,
185                               G_TYPE_INT,
186                               G_TYPE_INT);
187   
188         /**
189          * GdkPixbufLoader::closed:
190          * @loader: the object which received the signal.
191          *
192          * This signal is emitted when gdk_pixbuf_loader_close() is called.
193          * It can be used by different parts of an application to receive
194          * notification when an image loader is closed by the code that
195          * drives it.
196          */
197         pixbuf_loader_signals[CLOSED] =
198                 g_signal_new ("closed",
199                               G_TYPE_FROM_CLASS (object_class),
200                               G_SIGNAL_RUN_LAST,
201                               G_STRUCT_OFFSET (GdkPixbufLoaderClass, closed),
202                               NULL, NULL,
203                               _gdk_pixbuf_marshal_VOID__VOID,
204                               G_TYPE_NONE, 0);
205 }
206
207 static void
208 gdk_pixbuf_loader_init (GdkPixbufLoader *loader)
209 {
210         GdkPixbufLoaderPrivate *priv;
211   
212         priv = g_new0 (GdkPixbufLoaderPrivate, 1);
213         priv->width = -1;
214         priv->height = -1;
215
216         loader->priv = priv;
217 }
218
219 static void
220 gdk_pixbuf_loader_finalize (GObject *object)
221 {
222         GdkPixbufLoader *loader;
223         GdkPixbufLoaderPrivate *priv = NULL;
224   
225         loader = GDK_PIXBUF_LOADER (object);
226         priv = loader->priv;
227
228         if (!priv->closed) {
229                 g_warning ("GdkPixbufLoader finalized without calling gdk_pixbuf_loader_close() - this is not allowed. You must explicitly end the data stream to the loader before dropping the last reference.");
230                 if (priv->holds_threadlock) {
231                         _gdk_pixbuf_unlock (priv->image_module);
232                 }
233         }
234         if (priv->animation)
235                 g_object_unref (priv->animation);
236   
237         g_free (priv);
238   
239         G_OBJECT_CLASS (parent_class)->finalize (object);
240 }
241
242 /**
243  * gdk_pixbuf_loader_set_size:
244  * @loader: A pixbuf loader.
245  * @width: The desired width of the image being loaded.
246  * @height: The desired height of the image being loaded.
247  *
248  * Causes the image to be scaled while it is loaded. The desired
249  * image size can be determined relative to the original size of
250  * the image by calling gdk_pixbuf_loader_set_size() from a
251  * signal handler for the ::size_prepared signal.
252  *
253  * Attempts to set the desired image size  are ignored after the 
254  * emission of the ::size_prepared signal.
255  *
256  * Since: 2.2
257  */
258 void 
259 gdk_pixbuf_loader_set_size (GdkPixbufLoader *loader,
260                             gint             width,
261                             gint             height)
262 {
263         GdkPixbufLoaderPrivate *priv = GDK_PIXBUF_LOADER (loader)->priv;
264         g_return_if_fail (width >= 0 && height >= 0);
265
266         if (!priv->size_fixed) 
267                 {
268                         priv->width = width;
269                         priv->height = height;
270                 }
271 }
272
273 static void
274 gdk_pixbuf_loader_size_func (gint *width, gint *height, gpointer loader)
275 {
276         GdkPixbufLoaderPrivate *priv = GDK_PIXBUF_LOADER (loader)->priv;
277
278         /* allow calling gdk_pixbuf_loader_set_size() before the signal */
279         if (priv->width == -1 && priv->height == -1) 
280                 {
281                         priv->width = *width;
282                         priv->height = *height;
283                 }
284
285         g_signal_emit (loader, pixbuf_loader_signals[SIZE_PREPARED], 0, *width, *height);
286         priv->size_fixed = TRUE;
287
288         *width = priv->width;
289         *height = priv->height;
290 }
291
292 static void
293 gdk_pixbuf_loader_prepare (GdkPixbuf          *pixbuf,
294                            GdkPixbufAnimation *anim,
295                            gpointer            loader)
296 {
297         GdkPixbufLoaderPrivate *priv = GDK_PIXBUF_LOADER (loader)->priv;
298         g_return_if_fail (pixbuf != NULL);
299
300         if (!priv->size_fixed) 
301                 {
302                         /* Defend against lazy loaders which don't call size_func */
303                         gint width = gdk_pixbuf_get_width (pixbuf);
304                         gint height = gdk_pixbuf_get_height (pixbuf);
305                         
306                         gdk_pixbuf_loader_size_func (&width, &height, loader);
307                 }
308
309         priv->needs_scale = FALSE;
310         if (priv->width > 0 && priv->height > 0 &&
311             (priv->width != gdk_pixbuf_get_width (pixbuf) ||
312              priv->height != gdk_pixbuf_get_height (pixbuf)))
313                 priv->needs_scale = TRUE;
314
315         if (anim)
316                 g_object_ref (anim);
317         else
318                 anim = gdk_pixbuf_non_anim_new (pixbuf);
319   
320         priv->animation = anim;
321   
322         if (!priv->needs_scale)
323                 g_signal_emit (loader, pixbuf_loader_signals[AREA_PREPARED], 0);
324 }
325
326 static void
327 gdk_pixbuf_loader_update (GdkPixbuf *pixbuf,
328                           gint       x,
329                           gint       y,
330                           gint       width,
331                           gint       height,
332                           gpointer   loader)
333 {
334         GdkPixbufLoaderPrivate *priv = GDK_PIXBUF_LOADER (loader)->priv;
335   
336         if (!priv->needs_scale)
337                 g_signal_emit (loader,
338                                pixbuf_loader_signals[AREA_UPDATED],
339                                0,
340                                x, y,
341                                /* sanity check in here.  Defend against an errant loader */
342                                MIN (width, gdk_pixbuf_animation_get_width (priv->animation)),
343                                MIN (height, gdk_pixbuf_animation_get_height (priv->animation)));
344 }
345
346 static gint
347 gdk_pixbuf_loader_load_module (GdkPixbufLoader *loader,
348                                const char      *image_type,
349                                GError         **error)
350 {
351         GdkPixbufLoaderPrivate *priv = loader->priv;
352
353         if (image_type)
354                 {
355                         priv->image_module = _gdk_pixbuf_get_named_module (image_type,
356                                                                            error);
357                 }
358         else
359                 {
360                         priv->image_module = _gdk_pixbuf_get_module (priv->header_buf,
361                                                                      priv->header_buf_offset,
362                                                                      NULL,
363                                                                      error);
364                 }
365   
366         if (priv->image_module == NULL)
367                 return 0;
368   
369         if (priv->image_module->module == NULL)
370                 if (!_gdk_pixbuf_load_module (priv->image_module, error))
371                         return 0;
372   
373         if (priv->image_module->module == NULL)
374                 return 0;
375   
376         if ((priv->image_module->begin_load == NULL) ||
377             (priv->image_module->stop_load == NULL) ||
378             (priv->image_module->load_increment == NULL))
379                 {
380                         g_set_error (error,
381                                      GDK_PIXBUF_ERROR,
382                                      GDK_PIXBUF_ERROR_UNSUPPORTED_OPERATION,
383                                      _("Incremental loading of image type '%s' is not supported"),
384                                      priv->image_module->module_name);
385
386                         return 0;
387                 }
388
389         if (!priv->holds_threadlock) {
390                 priv->holds_threadlock = _gdk_pixbuf_lock (priv->image_module);
391         }
392
393         priv->context = priv->image_module->begin_load (gdk_pixbuf_loader_size_func,
394                                                         gdk_pixbuf_loader_prepare,
395                                                         gdk_pixbuf_loader_update,
396                                                         loader,
397                                                         error);
398   
399         if (priv->context == NULL)
400                 {
401                         /* Defense against broken loaders; DO NOT take this as a GError
402                          * example
403                          */
404                         if (error && *error == NULL)
405                                 {
406                                         g_warning ("Bug! loader '%s' didn't set an error on failure",
407                                                    priv->image_module->module_name);
408                                         g_set_error (error,
409                                                      GDK_PIXBUF_ERROR,
410                                                      GDK_PIXBUF_ERROR_FAILED,
411                                                      _("Internal error: Image loader module '%s'"
412                                                        " failed to begin loading an image, but didn't"
413                                                        " give a reason for the failure"),
414                                                      priv->image_module->module_name);
415
416                                 }
417       
418                         return 0;
419                 }
420   
421         if (priv->header_buf_offset
422             && priv->image_module->load_increment (priv->context, priv->header_buf, priv->header_buf_offset, error))
423                 return priv->header_buf_offset;
424   
425         return 0;
426 }
427
428 static int
429 gdk_pixbuf_loader_eat_header_write (GdkPixbufLoader *loader,
430                                     const guchar    *buf,
431                                     gsize            count,
432                                     GError         **error)
433 {
434         gint n_bytes;
435         GdkPixbufLoaderPrivate *priv = loader->priv;
436   
437         n_bytes = MIN(LOADER_HEADER_SIZE - priv->header_buf_offset, count);
438         memcpy (priv->header_buf + priv->header_buf_offset, buf, n_bytes);
439   
440         priv->header_buf_offset += n_bytes;
441   
442         if (priv->header_buf_offset >= LOADER_HEADER_SIZE)
443                 {
444                         if (gdk_pixbuf_loader_load_module (loader, NULL, error) == 0)
445                                 return 0;
446                 }
447   
448         return n_bytes;
449 }
450
451 /**
452  * gdk_pixbuf_loader_write:
453  * @loader: A pixbuf loader.
454  * @buf: Pointer to image data.
455  * @count: Length of the @buf buffer in bytes.
456  * @error: return location for errors
457  *
458  * This will cause a pixbuf loader to parse the next @count bytes of
459  * an image.  It will return %TRUE if the data was loaded successfully,
460  * and %FALSE if an error occurred.  In the latter case, the loader
461  * will be closed, and will not accept further writes. If %FALSE is
462  * returned, @error will be set to an error from the #GDK_PIXBUF_ERROR
463  * or #G_FILE_ERROR domains.
464  *
465  * Return value: %TRUE if the write was successful, or %FALSE if the loader
466  * cannot parse the buffer.
467  **/
468 gboolean
469 gdk_pixbuf_loader_write (GdkPixbufLoader *loader,
470                          const guchar    *buf,
471                          gsize            count,
472                          GError         **error)
473 {
474         GdkPixbufLoaderPrivate *priv;
475   
476         g_return_val_if_fail (loader != NULL, FALSE);
477         g_return_val_if_fail (GDK_IS_PIXBUF_LOADER (loader), FALSE);
478   
479         g_return_val_if_fail (buf != NULL, FALSE);
480         g_return_val_if_fail (count >= 0, FALSE);
481         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
482   
483         priv = loader->priv;
484
485         /* we expect it's not to be closed */
486         g_return_val_if_fail (priv->closed == FALSE, FALSE);
487   
488         if (priv->image_module == NULL)
489                 {
490                         gint eaten;
491       
492                         eaten = gdk_pixbuf_loader_eat_header_write (loader, buf, count, error);
493                         if (eaten <= 0)
494                                 return FALSE;
495       
496                         count -= eaten;
497                         buf += eaten;
498                 }
499   
500         if (count > 0 && priv->image_module->load_increment)
501                 {
502                         gboolean retval;
503                         retval = priv->image_module->load_increment (priv->context, buf, count,
504                                                                      error);
505                         if (!retval && error && *error == NULL)
506                                 {
507                                         /* Fix up busted image loader */
508                                         g_warning ("Bug! loader '%s' didn't set an error on failure",
509                                                    priv->image_module->module_name);
510                                         g_set_error (error,
511                                                      GDK_PIXBUF_ERROR,
512                                                      GDK_PIXBUF_ERROR_FAILED,
513                                                      _("Internal error: Image loader module '%s'"
514                                                        " failed to begin loading an image, but didn't"
515                                                        " give a reason for the failure"),
516                                                      priv->image_module->module_name);
517                                 }
518
519                         return retval;
520                 }
521       
522         return TRUE;
523 }
524
525 /**
526  * gdk_pixbuf_loader_new:
527  *
528  * Creates a new pixbuf loader object.
529  *
530  * Return value: A newly-created pixbuf loader.
531  **/
532 GdkPixbufLoader *
533 gdk_pixbuf_loader_new (void)
534 {
535         return g_object_new (GDK_TYPE_PIXBUF_LOADER, NULL);
536 }
537
538 /**
539  * gdk_pixbuf_loader_new_with_type:
540  * @image_type: name of the image format to be loaded with the image
541  * @error: return location for an allocated #GError, or %NULL to ignore errors
542  *
543  * Creates a new pixbuf loader object that always attempts to parse
544  * image data as if it were an image of type @image_type, instead of
545  * identifying the type automatically. Useful if you want an error if
546  * the image isn't the expected type, for loading image formats
547  * that can't be reliably identified by looking at the data, or if
548  * the user manually forces a specific type.
549  *
550  * Return value: A newly-created pixbuf loader.
551  **/
552 GdkPixbufLoader *
553 gdk_pixbuf_loader_new_with_type (const char *image_type,
554                                  GError    **error)
555 {
556         GdkPixbufLoader *retval;
557         GError *tmp;
558         g_return_val_if_fail (error == NULL || *error == NULL, NULL);
559   
560         retval = g_object_new (GDK_TYPE_PIXBUF_LOADER, NULL);
561
562         tmp = NULL;
563         gdk_pixbuf_loader_load_module (retval, image_type, &tmp);
564         if (tmp != NULL)
565                 {
566                         g_propagate_error (error, tmp);
567                         g_object_unref (retval);
568                         return NULL;
569                 }
570
571         return retval;
572 }
573
574 /**
575  * gdk_pixbuf_loader_new_with_mime_type:
576  * @mime_type: the mime type to be loaded 
577  * @error: return location for an allocated #GError, or %NULL to ignore errors
578  *
579  * Creates a new pixbuf loader object that always attempts to parse
580  * image data as if it were an image of mime type @mime_type, instead of
581  * identifying the type automatically. Useful if you want an error if
582  * the image isn't the expected mime type, for loading image formats
583  * that can't be reliably identified by looking at the data, or if
584  * the user manually forces a specific mime type.
585  *
586  * Return value: A newly-created pixbuf loader.
587  * Since: 2.4
588  **/
589 GdkPixbufLoader *
590 gdk_pixbuf_loader_new_with_mime_type (const char *mime_type,
591                                       GError    **error)
592 {
593         const char * image_type = NULL;
594         char ** mimes;
595
596         GdkPixbufLoader *retval;
597         GError *tmp;
598   
599         GSList * formats;
600         GdkPixbufFormat *info;
601         int i, j, length;
602
603         formats = gdk_pixbuf_get_formats ();
604         length = g_slist_length (formats);
605
606         for (i = 0; i < length && image_type == NULL; i++) {
607                 info = (GdkPixbufFormat *)g_slist_nth_data (formats, i);
608                 mimes = info->mime_types;
609                 
610                 for (j = 0; mimes[j] != NULL; j++)
611                         if (g_ascii_strcasecmp (mimes[j], mime_type) == 0) {
612                                 image_type = info->name;
613                                 break;
614                         }
615         }
616
617         g_slist_free (formats);
618
619         retval = g_object_new (GDK_TYPE_PIXBUF_LOADER, NULL);
620
621         tmp = NULL;
622         gdk_pixbuf_loader_load_module(retval, image_type, &tmp);
623         if (tmp != NULL)
624                 {
625                         g_propagate_error (error, tmp);
626                         g_object_unref (retval);
627                         return NULL;
628                 }
629
630         return retval;
631 }
632
633 /**
634  * gdk_pixbuf_loader_get_pixbuf:
635  * @loader: A pixbuf loader.
636  *
637  * Queries the #GdkPixbuf that a pixbuf loader is currently creating.
638  * In general it only makes sense to call this function after the
639  * "area_prepared" signal has been emitted by the loader; this means
640  * that enough data has been read to know the size of the image that
641  * will be allocated.  If the loader has not received enough data via
642  * gdk_pixbuf_loader_write(), then this function returns %NULL.  The
643  * returned pixbuf will be the same in all future calls to the loader,
644  * so simply calling g_object_ref() should be sufficient to continue
645  * using it.  Additionally, if the loader is an animation, it will
646  * return the "static image" of the animation
647  * (see gdk_pixbuf_animation_get_static_image()).
648  * 
649  * Return value: The #GdkPixbuf that the loader is creating, or %NULL if not
650  * enough data has been read to determine how to create the image buffer.
651  **/
652 GdkPixbuf *
653 gdk_pixbuf_loader_get_pixbuf (GdkPixbufLoader *loader)
654 {
655         GdkPixbufLoaderPrivate *priv;
656   
657         g_return_val_if_fail (loader != NULL, NULL);
658         g_return_val_if_fail (GDK_IS_PIXBUF_LOADER (loader), NULL);
659   
660         priv = loader->priv;
661
662         if (priv->animation)
663                 return gdk_pixbuf_animation_get_static_image (priv->animation);
664         else
665                 return NULL;
666 }
667
668 /**
669  * gdk_pixbuf_loader_get_animation:
670  * @loader: A pixbuf loader
671  *
672  * Queries the #GdkPixbufAnimation that a pixbuf loader is currently creating.
673  * In general it only makes sense to call this function after the "area_prepared"
674  * signal has been emitted by the loader. If the loader doesn't have enough
675  * bytes yet (hasn't emitted the "area_prepared" signal) this function will 
676  * return %NULL.
677  *
678  * Return value: The #GdkPixbufAnimation that the loader is loading, or %NULL if
679  not enough data has been read to determine the information.
680 **/
681 GdkPixbufAnimation *
682 gdk_pixbuf_loader_get_animation (GdkPixbufLoader *loader)
683 {
684         GdkPixbufLoaderPrivate *priv;
685   
686         g_return_val_if_fail (loader != NULL, NULL);
687         g_return_val_if_fail (GDK_IS_PIXBUF_LOADER (loader), NULL);
688   
689         priv = loader->priv;
690   
691         return priv->animation;
692 }
693
694 /**
695  * gdk_pixbuf_loader_close:
696  * @loader: A pixbuf loader.
697  * @error: return location for a #GError, or %NULL to ignore errors
698  *
699  * Informs a pixbuf loader that no further writes with
700  * gdk_pixbuf_loader_write() will occur, so that it can free its
701  * internal loading structures. Also, tries to parse any data that
702  * hasn't yet been parsed; if the remaining data is partial or
703  * corrupt, an error will be returned.  If %FALSE is returned, @error
704  * will be set to an error from the #GDK_PIXBUF_ERROR or #G_FILE_ERROR
705  * domains. If you're just cancelling a load rather than expecting it
706  * to be finished, passing %NULL for @error to ignore it is
707  * reasonable.
708  *
709  * Returns: %TRUE if all image data written so far was successfully
710             passed out via the update_area signal
711  **/
712 gboolean
713 gdk_pixbuf_loader_close (GdkPixbufLoader *loader,
714                          GError         **error)
715 {
716         GdkPixbufLoaderPrivate *priv;
717         gboolean retval = TRUE;
718   
719         g_return_val_if_fail (loader != NULL, TRUE);
720         g_return_val_if_fail (GDK_IS_PIXBUF_LOADER (loader), TRUE);
721         g_return_val_if_fail (error == NULL || *error == NULL, TRUE);
722   
723         priv = loader->priv;
724   
725         /* we expect it's not closed */
726         g_return_val_if_fail (priv->closed == FALSE, TRUE);
727   
728         /* We have less the 128 bytes in the image.  Flush it, and keep going. */
729         if (priv->image_module == NULL)
730                 {
731                         GError *tmp = NULL;
732                         gdk_pixbuf_loader_load_module (loader, NULL, &tmp);
733                         if (tmp != NULL)
734                                 {
735                                         g_propagate_error (error, tmp);
736                                         retval = FALSE;
737                                 }
738                 }  
739
740         if (priv->image_module && priv->image_module->stop_load && priv->context) 
741                 {
742                         if (!priv->image_module->stop_load (priv->context, error))
743                                 retval = FALSE;
744                 }
745   
746         priv->closed = TRUE;
747         if (priv->image_module && priv->holds_threadlock) {
748                 _gdk_pixbuf_unlock (priv->image_module);
749                 priv->holds_threadlock = FALSE;
750         }
751
752         if (priv->needs_scale) 
753                 {
754                         GdkPixbuf *tmp, *pixbuf;
755                         
756                         tmp = gdk_pixbuf_animation_get_static_image (priv->animation);
757                         g_object_ref (tmp);
758                         pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, tmp->has_alpha, 8, priv->width, priv->height);
759                         g_object_unref (priv->animation);
760                         priv->animation = gdk_pixbuf_non_anim_new (pixbuf);
761                         g_object_unref (pixbuf);
762                         g_signal_emit (loader, pixbuf_loader_signals[AREA_PREPARED], 0);
763                         gdk_pixbuf_scale (tmp, pixbuf, 0, 0, priv->width, priv->height, 0, 0,
764                                           (double) priv->width / tmp->width,
765                                           (double) priv->height / tmp->height,
766                                           GDK_INTERP_BILINEAR); 
767                         g_object_unref (tmp);
768                         
769                         g_signal_emit (loader, pixbuf_loader_signals[AREA_UPDATED], 0, 
770                                        0, 0, priv->width, priv->height);
771                 }
772
773         
774         g_signal_emit (loader, pixbuf_loader_signals[CLOSED], 0);
775
776         return retval;
777 }
778
779 /**
780  * gdk_pixbuf_loader_get_format:
781  * @loader: A pixbuf loader.
782  *
783  * Obtains the available information about the format of the 
784  * currently loading image file.
785  *
786  * Returns: A #GdkPixbufFormat or %NULL. The return value is owned 
787  * by GdkPixbuf and should not be freed.
788  * 
789  * Since: 2.2
790  */
791 GdkPixbufFormat *
792 gdk_pixbuf_loader_get_format (GdkPixbufLoader *loader)
793 {
794         GdkPixbufLoaderPrivate *priv;
795   
796         g_return_val_if_fail (loader != NULL, NULL);
797         g_return_val_if_fail (GDK_IS_PIXBUF_LOADER (loader), NULL);
798   
799         priv = loader->priv;
800
801         if (priv->image_module)
802                 return _gdk_pixbuf_get_format (priv->image_module);
803         else
804                 return NULL;
805 }
806
807
808
809