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, see <http://www.gnu.org/licenses/>.
23  */
24 
25 #include "config.h"
26 #include <string.h>
27 
28 #include "gdk-pixbuf-private.h"
29 #include "gdk-pixbuf-animation.h"
30 #include "gdk-pixbuf-scaled-anim.h"
31 #include "gdk-pixbuf-loader.h"
32 #include "gdk-pixbuf-marshal.h"
33 
34 /**
35  * SECTION:gdk-pixbuf-loader
36  * @Short_description: Application-driven progressive image loading.
37  * @Title: GdkPixbufLoader
38  * @See_also: gdk_pixbuf_new_from_file(), gdk_pixbuf_animation_new_from_file()
39  *
40  * #GdkPixbufLoader provides a way for applications to drive the
41  * process of loading an image, by letting them send the image data
42  * directly to the loader instead of having the loader read the data
43  * from a file.  Applications can use this functionality instead of
44  * gdk_pixbuf_new_from_file() or gdk_pixbuf_animation_new_from_file()
45  * when they need to parse image data in
46  * small chunks.  For example, it should be used when reading an
47  * image from a (potentially) slow network connection, or when
48  * loading an extremely large file.
49  *
50  *
51  * To use #GdkPixbufLoader to load an image, just create a new one, and
52  * call gdk_pixbuf_loader_write() to send the data to it.  When done,
53  * gdk_pixbuf_loader_close() should be called to end the stream and
54  * finalize everything. The loader will emit three important signals
55  * throughout the process. The first, #GdkPixbufLoader::size-prepared,
56  * will be emitted as soon as the image has enough information to
57  * determine the size of the image to be used. If you want to scale
58  * the image while loading it, you can call gdk_pixbuf_loader_set_size()
59  * in response to this signal.
60  *
61  *
62  * The second signal, #GdkPixbufLoader::area-prepared, will be emitted as
63  * soon as the pixbuf of the desired has been allocated. You can obtain it
64  * by calling gdk_pixbuf_loader_get_pixbuf(). If you want to use it, simply
65  * ref it. You can also call gdk_pixbuf_loader_get_pixbuf() later and get
66  * the same pixbuf.
67  *
68  * The last signal, #GdkPixbufLoader::area-updated, gets emitted every time
69  * a region is updated. This way you can update a partially completed image.
70  * Note that you do not know anything about the completeness of an image
71  * from the updated area. For example, in an interlaced image, you need to
72  * make several passes before the image is done loading.
73  *
74  * # Loading an animation
75  *
76  * Loading an animation is almost as easy as loading an image. Once the first
77  * #GdkPixbufLoader::area-prepared signal has been emitted, you can call
78  * gdk_pixbuf_loader_get_animation() to get the #GdkPixbufAnimation struct
79  * and gdk_pixbuf_animation_get_iter() to get a #GdkPixbufAnimationIter for
80  * displaying it.
81  */
82 
83 
84 enum {
85         SIZE_PREPARED,
86         AREA_PREPARED,
87         AREA_UPDATED,
88         CLOSED,
89         LAST_SIGNAL
90 };
91 
92 
93 static void gdk_pixbuf_loader_finalize (GObject *loader);
94 
95 static guint    pixbuf_loader_signals[LAST_SIGNAL] = { 0 };
96 
97 /* Internal data */
98 
99 typedef struct
100 {
101         GdkPixbufAnimation *animation;
102         gboolean closed;
103         guchar header_buf[SNIFF_BUFFER_SIZE];
104         gint header_buf_offset;
105         GdkPixbufModule *image_module;
106         gpointer context;
107         gint original_width;
108         gint original_height;
109         gint width;
110         gint height;
111         gboolean size_fixed;
112         gboolean needs_scale;
113 	gchar *filename;
114 } GdkPixbufLoaderPrivate;
115 
G_DEFINE_TYPE(GdkPixbufLoader,gdk_pixbuf_loader,G_TYPE_OBJECT)116 G_DEFINE_TYPE (GdkPixbufLoader, gdk_pixbuf_loader, G_TYPE_OBJECT)
117 
118 
119 static void
120 gdk_pixbuf_loader_class_init (GdkPixbufLoaderClass *class)
121 {
122         GObjectClass *object_class;
123 
124         object_class = (GObjectClass *) class;
125 
126         object_class->finalize = gdk_pixbuf_loader_finalize;
127 
128         /**
129          * GdkPixbufLoader::size-prepared:
130          * @loader: the object which received the signal.
131          * @width: the original width of the image
132          * @height: the original height of the image
133          *
134          * This signal is emitted when the pixbuf loader has been fed the
135          * initial amount of data that is required to figure out the size
136          * of the image that it will create.  Applications can call
137          * gdk_pixbuf_loader_set_size() in response to this signal to set
138          * the desired size to which the image should be scaled.
139          */
140         pixbuf_loader_signals[SIZE_PREPARED] =
141                 g_signal_new ("size-prepared",
142                               G_TYPE_FROM_CLASS (object_class),
143                               G_SIGNAL_RUN_LAST,
144                               G_STRUCT_OFFSET (GdkPixbufLoaderClass, size_prepared),
145                               NULL, NULL,
146                               _gdk_pixbuf_marshal_VOID__INT_INT,
147                               G_TYPE_NONE, 2,
148                               G_TYPE_INT,
149                               G_TYPE_INT);
150 
151         /**
152          * GdkPixbufLoader::area-prepared:
153          * @loader: the object which received the signal.
154          *
155          * This signal is emitted when the pixbuf loader has allocated the
156          * pixbuf in the desired size.  After this signal is emitted,
157          * applications can call gdk_pixbuf_loader_get_pixbuf() to fetch
158          * the partially-loaded pixbuf.
159          */
160         pixbuf_loader_signals[AREA_PREPARED] =
161                 g_signal_new ("area-prepared",
162                               G_TYPE_FROM_CLASS (object_class),
163                               G_SIGNAL_RUN_LAST,
164                               G_STRUCT_OFFSET (GdkPixbufLoaderClass, area_prepared),
165                               NULL, NULL,
166                               _gdk_pixbuf_marshal_VOID__VOID,
167                               G_TYPE_NONE, 0);
168 
169         /**
170          * GdkPixbufLoader::area-updated:
171          * @loader: the object which received the signal.
172          * @x: X offset of upper-left corner of the updated area.
173          * @y: Y offset of upper-left corner of the updated area.
174          * @width: Width of updated area.
175          * @height: Height of updated area.
176          *
177          * This signal is emitted when a significant area of the image being
178          * loaded has been updated.  Normally it means that a complete
179          * scanline has been read in, but it could be a different area as
180          * well.  Applications can use this signal to know when to repaint
181          * areas of an image that is being loaded.
182          */
183         pixbuf_loader_signals[AREA_UPDATED] =
184                 g_signal_new ("area-updated",
185                               G_TYPE_FROM_CLASS (object_class),
186                               G_SIGNAL_RUN_LAST,
187                               G_STRUCT_OFFSET (GdkPixbufLoaderClass, area_updated),
188                               NULL, NULL,
189                               _gdk_pixbuf_marshal_VOID__INT_INT_INT_INT,
190                               G_TYPE_NONE, 4,
191                               G_TYPE_INT,
192                               G_TYPE_INT,
193                               G_TYPE_INT,
194                               G_TYPE_INT);
195 
196         /**
197          * GdkPixbufLoader::closed:
198          * @loader: the object which received the signal.
199          *
200          * This signal is emitted when gdk_pixbuf_loader_close() is called.
201          * It can be used by different parts of an application to receive
202          * notification when an image loader is closed by the code that
203          * drives it.
204          */
205         pixbuf_loader_signals[CLOSED] =
206                 g_signal_new ("closed",
207                               G_TYPE_FROM_CLASS (object_class),
208                               G_SIGNAL_RUN_LAST,
209                               G_STRUCT_OFFSET (GdkPixbufLoaderClass, closed),
210                               NULL, NULL,
211                               _gdk_pixbuf_marshal_VOID__VOID,
212                               G_TYPE_NONE, 0);
213 }
214 
215 static void
gdk_pixbuf_loader_init(GdkPixbufLoader * loader)216 gdk_pixbuf_loader_init (GdkPixbufLoader *loader)
217 {
218         GdkPixbufLoaderPrivate *priv;
219 
220         priv = g_new0 (GdkPixbufLoaderPrivate, 1);
221         priv->original_width = -1;
222         priv->original_height = -1;
223         priv->width = -1;
224         priv->height = -1;
225 
226         loader->priv = priv;
227 }
228 
229 static void
gdk_pixbuf_loader_finalize(GObject * object)230 gdk_pixbuf_loader_finalize (GObject *object)
231 {
232         GdkPixbufLoader *loader;
233         GdkPixbufLoaderPrivate *priv = NULL;
234 
235         loader = GDK_PIXBUF_LOADER (object);
236         priv = loader->priv;
237 
238         if (!priv->closed) {
239                 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.");
240         }
241         if (priv->animation)
242                 g_object_unref (priv->animation);
243 
244 	g_free (priv->filename);
245 
246         g_free (priv);
247 
248         G_OBJECT_CLASS (gdk_pixbuf_loader_parent_class)->finalize (object);
249 }
250 
251 /**
252  * gdk_pixbuf_loader_set_size:
253  * @loader: A pixbuf loader.
254  * @width: The desired width of the image being loaded.
255  * @height: The desired height of the image being loaded.
256  *
257  * Causes the image to be scaled while it is loaded. The desired
258  * image size can be determined relative to the original size of
259  * the image by calling gdk_pixbuf_loader_set_size() from a
260  * signal handler for the ::size-prepared signal.
261  *
262  * Attempts to set the desired image size  are ignored after the
263  * emission of the ::size-prepared signal.
264  *
265  * Since: 2.2
266  */
267 void
gdk_pixbuf_loader_set_size(GdkPixbufLoader * loader,gint width,gint height)268 gdk_pixbuf_loader_set_size (GdkPixbufLoader *loader,
269 			    gint             width,
270 			    gint             height)
271 {
272         GdkPixbufLoaderPrivate *priv;
273 
274         g_return_if_fail (GDK_IS_PIXBUF_LOADER (loader));
275         g_return_if_fail (width >= 0 && height >= 0);
276 
277         priv = GDK_PIXBUF_LOADER (loader)->priv;
278 
279         if (!priv->size_fixed)
280                 {
281                         priv->width = width;
282                         priv->height = height;
283                 }
284 }
285 
286 static void
gdk_pixbuf_loader_size_func(gint * width,gint * height,gpointer loader)287 gdk_pixbuf_loader_size_func (gint *width, gint *height, gpointer loader)
288 {
289         GdkPixbufLoaderPrivate *priv = GDK_PIXBUF_LOADER (loader)->priv;
290 
291         priv->original_width = *width;
292         priv->original_height = *height;
293 
294         /* allow calling gdk_pixbuf_loader_set_size() before the signal */
295         if (priv->width == -1 && priv->height == -1)
296                 {
297                         priv->width = *width;
298                         priv->height = *height;
299                 }
300 
301         g_signal_emit (loader, pixbuf_loader_signals[SIZE_PREPARED], 0, *width, *height);
302         priv->size_fixed = TRUE;
303 
304         *width = priv->width;
305         *height = priv->height;
306 }
307 
308 static void
gdk_pixbuf_loader_prepare(GdkPixbuf * pixbuf,GdkPixbufAnimation * anim,gpointer loader)309 gdk_pixbuf_loader_prepare (GdkPixbuf          *pixbuf,
310                            GdkPixbufAnimation *anim,
311 			   gpointer            loader)
312 {
313         GdkPixbufLoaderPrivate *priv = GDK_PIXBUF_LOADER (loader)->priv;
314         gint width, height;
315         g_return_if_fail (pixbuf != NULL);
316 
317         width = anim ? gdk_pixbuf_animation_get_width (anim) :
318                 gdk_pixbuf_get_width (pixbuf);
319         height = anim ? gdk_pixbuf_animation_get_height (anim) :
320                 gdk_pixbuf_get_height (pixbuf);
321 
322         if (!priv->size_fixed)
323                 {
324 			gint w = width;
325 			gint h = height;
326                         /* Defend against lazy loaders which don't call size_func */
327                         gdk_pixbuf_loader_size_func (&w, &h, loader);
328                 }
329 
330         priv->needs_scale = FALSE;
331         if (priv->width > 0 && priv->height > 0 &&
332             (priv->width != width || priv->height != height))
333                 priv->needs_scale = TRUE;
334 
335         if (anim)
336                 g_object_ref (anim);
337         else {
338                 if (priv->original_width > 0) {
339                         char *original_width_str = NULL;
340 
341                         original_width_str = g_strdup_printf ("%d", priv->original_width);
342                         gdk_pixbuf_set_option (pixbuf, "original-width", original_width_str);
343                         g_free (original_width_str);
344                 }
345 
346                 if (priv->original_height > 0) {
347                         char *original_height_str = NULL;
348 
349                         original_height_str = g_strdup_printf ("%d", priv->original_height);
350                         gdk_pixbuf_set_option (pixbuf, "original-height", original_height_str);
351                         g_free (original_height_str);
352                 }
353 
354                 anim = gdk_pixbuf_non_anim_new (pixbuf);
355         }
356 
357 	if (priv->needs_scale && width != 0 && height != 0) {
358 		priv->animation  = GDK_PIXBUF_ANIMATION (_gdk_pixbuf_scaled_anim_new (anim,
359                                          (double) priv->width / width,
360                                          (double) priv->height / height,
361 					  1.0));
362 			g_object_unref (anim);
363 	}
364 	else
365         	priv->animation = anim;
366 
367         if (!priv->needs_scale)
368                 g_signal_emit (loader, pixbuf_loader_signals[AREA_PREPARED], 0);
369 }
370 
371 static void
gdk_pixbuf_loader_update(GdkPixbuf * pixbuf,gint x,gint y,gint width,gint height,gpointer loader)372 gdk_pixbuf_loader_update (GdkPixbuf *pixbuf,
373 			  gint       x,
374 			  gint       y,
375 			  gint       width,
376 			  gint       height,
377 			  gpointer   loader)
378 {
379         GdkPixbufLoaderPrivate *priv = GDK_PIXBUF_LOADER (loader)->priv;
380 
381         if (!priv->needs_scale)
382                 g_signal_emit (loader,
383                                pixbuf_loader_signals[AREA_UPDATED],
384                                0,
385                                x, y,
386                                /* sanity check in here.  Defend against an errant loader */
387                                MIN (width, gdk_pixbuf_animation_get_width (priv->animation)),
388                                MIN (height, gdk_pixbuf_animation_get_height (priv->animation)));
389 }
390 
391 /* Defense against broken loaders; DO NOT take this as a GError example! */
392 static void
gdk_pixbuf_loader_ensure_error(GdkPixbufLoader * loader,GError ** error)393 gdk_pixbuf_loader_ensure_error (GdkPixbufLoader *loader,
394                                 GError         **error)
395 {
396         GdkPixbufLoaderPrivate *priv = loader->priv;
397 
398         if (error == NULL || *error != NULL)
399                 return;
400 
401         g_warning ("Bug! loader '%s' didn't set an error on failure",
402                    priv->image_module->module_name);
403         g_set_error (error,
404                      GDK_PIXBUF_ERROR,
405                      GDK_PIXBUF_ERROR_FAILED,
406                      _("Internal error: Image loader module “%s” failed to"
407                        " complete an operation, but didn’t give a reason for"
408                        " the failure"),
409                      priv->image_module->module_name);
410 }
411 
412 static gint
gdk_pixbuf_loader_load_module(GdkPixbufLoader * loader,const char * image_type,GError ** error)413 gdk_pixbuf_loader_load_module (GdkPixbufLoader *loader,
414                                const char      *image_type,
415                                GError         **error)
416 {
417         GdkPixbufLoaderPrivate *priv = loader->priv;
418 
419         if (image_type)
420                 {
421                         priv->image_module = _gdk_pixbuf_get_named_module (image_type,
422                                                                            error);
423                 }
424         else
425                 {
426                         priv->image_module = _gdk_pixbuf_get_module (priv->header_buf,
427                                                                      priv->header_buf_offset,
428                                                                      priv->filename,
429                                                                      error);
430                 }
431 
432         if (priv->image_module == NULL)
433                 return 0;
434 
435         if (!_gdk_pixbuf_load_module (priv->image_module, error))
436                 return 0;
437 
438         if (priv->image_module->module == NULL)
439                 return 0;
440 
441         if ((priv->image_module->begin_load == NULL) ||
442             (priv->image_module->stop_load == NULL) ||
443             (priv->image_module->load_increment == NULL))
444                 {
445                         g_set_error (error,
446                                      GDK_PIXBUF_ERROR,
447                                      GDK_PIXBUF_ERROR_UNSUPPORTED_OPERATION,
448                                      _("Incremental loading of image type “%s” is not supported"),
449                                      priv->image_module->module_name);
450 
451                         return 0;
452                 }
453 
454         priv->context = priv->image_module->begin_load (gdk_pixbuf_loader_size_func,
455                                                         gdk_pixbuf_loader_prepare,
456                                                         gdk_pixbuf_loader_update,
457                                                         loader,
458                                                         error);
459 
460         if (priv->context == NULL)
461                 {
462                         gdk_pixbuf_loader_ensure_error (loader, error);
463                         return 0;
464                 }
465 
466         if (priv->header_buf_offset
467             && priv->image_module->load_increment (priv->context, priv->header_buf, priv->header_buf_offset, error))
468                 return priv->header_buf_offset;
469 
470         return 0;
471 }
472 
473 static int
gdk_pixbuf_loader_eat_header_write(GdkPixbufLoader * loader,const guchar * buf,gsize count,GError ** error)474 gdk_pixbuf_loader_eat_header_write (GdkPixbufLoader *loader,
475 				    const guchar    *buf,
476 				    gsize            count,
477                                     GError         **error)
478 {
479         gint n_bytes;
480         GdkPixbufLoaderPrivate *priv = loader->priv;
481 
482         n_bytes = MIN(SNIFF_BUFFER_SIZE - priv->header_buf_offset, count);
483         memcpy (priv->header_buf + priv->header_buf_offset, buf, n_bytes);
484 
485         priv->header_buf_offset += n_bytes;
486 
487         if (priv->header_buf_offset >= SNIFF_BUFFER_SIZE)
488                 {
489                         if (gdk_pixbuf_loader_load_module (loader, NULL, error) == 0)
490                                 return 0;
491                 }
492 
493         return n_bytes;
494 }
495 
496 /**
497  * gdk_pixbuf_loader_write:
498  * @loader: A pixbuf loader.
499  * @buf: (array length=count): Pointer to image data.
500  * @count: Length of the @buf buffer in bytes.
501  * @error: return location for errors
502  *
503  * This will cause a pixbuf loader to parse the next @count bytes of
504  * an image.  It will return %TRUE if the data was loaded successfully,
505  * and %FALSE if an error occurred.  In the latter case, the loader
506  * will be closed, and will not accept further writes. If %FALSE is
507  * returned, @error will be set to an error from the #GDK_PIXBUF_ERROR
508  * or #G_FILE_ERROR domains.
509  *
510  * Return value: %TRUE if the write was successful, or %FALSE if the loader
511  * cannot parse the buffer.
512  **/
513 gboolean
gdk_pixbuf_loader_write(GdkPixbufLoader * loader,const guchar * buf,gsize count,GError ** error)514 gdk_pixbuf_loader_write (GdkPixbufLoader *loader,
515 			 const guchar    *buf,
516 			 gsize            count,
517                          GError         **error)
518 {
519         GdkPixbufLoaderPrivate *priv;
520 
521         g_return_val_if_fail (GDK_IS_PIXBUF_LOADER (loader), FALSE);
522 
523         g_return_val_if_fail (buf != NULL, FALSE);
524         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
525 
526         priv = loader->priv;
527 
528         /* we expect it's not to be closed */
529         g_return_val_if_fail (priv->closed == FALSE, FALSE);
530 
531         if (count > 0 && priv->image_module == NULL)
532                 {
533                         gint eaten;
534 
535                         eaten = gdk_pixbuf_loader_eat_header_write (loader, buf, count, error);
536                         if (eaten <= 0)
537                                goto fail;
538 
539                         count -= eaten;
540                         buf += eaten;
541                 }
542 
543         /* By this point, we expect the image_module to have been loaded. */
544         g_assert (count == 0 || priv->image_module != NULL);
545 
546         if (count > 0 && priv->image_module->load_increment != NULL)
547                 {
548                         if (!priv->image_module->load_increment (priv->context, buf, count,
549                                                                  error))
550 				goto fail;
551                 }
552 
553         return TRUE;
554 
555  fail:
556         gdk_pixbuf_loader_ensure_error (loader, error);
557         gdk_pixbuf_loader_close (loader, NULL);
558 
559         return FALSE;
560 }
561 
562 /**
563  * gdk_pixbuf_loader_write_bytes:
564  * @loader: A pixbuf loader.
565  * @buffer: The image data as a #GBytes
566  * @error: return location for errors
567  *
568  * This will cause a pixbuf loader to parse a buffer inside a #GBytes
569  * for an image.  It will return %TRUE if the data was loaded successfully,
570  * and %FALSE if an error occurred.  In the latter case, the loader
571  * will be closed, and will not accept further writes. If %FALSE is
572  * returned, @error will be set to an error from the #GDK_PIXBUF_ERROR
573  * or #G_FILE_ERROR domains.
574  *
575  * See also: gdk_pixbuf_loader_write()
576  *
577  * Return value: %TRUE if the write was successful, or %FALSE if the loader
578  * cannot parse the buffer.
579  *
580  * Since: 2.30
581  */
582 gboolean
gdk_pixbuf_loader_write_bytes(GdkPixbufLoader * loader,GBytes * buffer,GError ** error)583 gdk_pixbuf_loader_write_bytes (GdkPixbufLoader *loader,
584                                GBytes          *buffer,
585                                GError         **error)
586 {
587         g_return_val_if_fail (GDK_IS_PIXBUF_LOADER (loader), FALSE);
588 
589         g_return_val_if_fail (buffer != NULL, FALSE);
590         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
591 
592         return gdk_pixbuf_loader_write (loader,
593                                         g_bytes_get_data (buffer, NULL),
594                                         g_bytes_get_size (buffer),
595                                         error);
596 }
597 
598 /**
599  * gdk_pixbuf_loader_new:
600  *
601  * Creates a new pixbuf loader object.
602  *
603  * Return value: A newly-created pixbuf loader.
604  **/
605 GdkPixbufLoader *
gdk_pixbuf_loader_new(void)606 gdk_pixbuf_loader_new (void)
607 {
608         return g_object_new (GDK_TYPE_PIXBUF_LOADER, NULL);
609 }
610 
611 /**
612  * gdk_pixbuf_loader_new_with_type:
613  * @image_type: name of the image format to be loaded with the image
614  * @error: (allow-none): return location for an allocated #GError, or %NULL to ignore errors
615  *
616  * Creates a new pixbuf loader object that always attempts to parse
617  * image data as if it were an image of type @image_type, instead of
618  * identifying the type automatically. Useful if you want an error if
619  * the image isn't the expected type, for loading image formats
620  * that can't be reliably identified by looking at the data, or if
621  * the user manually forces a specific type.
622  *
623  * The list of supported image formats depends on what image loaders
624  * are installed, but typically "png", "jpeg", "gif", "tiff" and
625  * "xpm" are among the supported formats. To obtain the full list of
626  * supported image formats, call gdk_pixbuf_format_get_name() on each
627  * of the #GdkPixbufFormat structs returned by gdk_pixbuf_get_formats().
628  *
629  * Return value: A newly-created pixbuf loader.
630  **/
631 GdkPixbufLoader *
gdk_pixbuf_loader_new_with_type(const char * image_type,GError ** error)632 gdk_pixbuf_loader_new_with_type (const char *image_type,
633                                  GError    **error)
634 {
635         GdkPixbufLoader *retval;
636         GError *tmp;
637         g_return_val_if_fail (error == NULL || *error == NULL, NULL);
638 
639         retval = g_object_new (GDK_TYPE_PIXBUF_LOADER, NULL);
640 
641         tmp = NULL;
642         gdk_pixbuf_loader_load_module (retval, image_type, &tmp);
643         if (tmp != NULL)
644                 {
645                         g_propagate_error (error, tmp);
646                         gdk_pixbuf_loader_close (retval, NULL);
647                         g_object_unref (retval);
648                         return NULL;
649                 }
650 
651         return retval;
652 }
653 
654 /**
655  * gdk_pixbuf_loader_new_with_mime_type:
656  * @mime_type: the mime type to be loaded
657  * @error: (allow-none): return location for an allocated #GError, or %NULL to ignore errors
658  *
659  * Creates a new pixbuf loader object that always attempts to parse
660  * image data as if it were an image of mime type @mime_type, instead of
661  * identifying the type automatically. Useful if you want an error if
662  * the image isn't the expected mime type, for loading image formats
663  * that can't be reliably identified by looking at the data, or if
664  * the user manually forces a specific mime type.
665  *
666  * The list of supported mime types depends on what image loaders
667  * are installed, but typically "image/png", "image/jpeg", "image/gif",
668  * "image/tiff" and "image/x-xpixmap" are among the supported mime types.
669  * To obtain the full list of supported mime types, call
670  * gdk_pixbuf_format_get_mime_types() on each of the #GdkPixbufFormat
671  * structs returned by gdk_pixbuf_get_formats().
672  *
673  * Return value: A newly-created pixbuf loader.
674  * Since: 2.4
675  **/
676 GdkPixbufLoader *
gdk_pixbuf_loader_new_with_mime_type(const char * mime_type,GError ** error)677 gdk_pixbuf_loader_new_with_mime_type (const char *mime_type,
678                                       GError    **error)
679 {
680         const char * image_type = NULL;
681         char ** mimes;
682 
683         GdkPixbufLoader *retval;
684         GError *tmp;
685 
686         GSList * formats;
687         GdkPixbufFormat *info;
688         int i, j, length;
689 
690         formats = gdk_pixbuf_get_formats ();
691         length = g_slist_length (formats);
692 
693         for (i = 0; i < length && image_type == NULL; i++) {
694                 info = (GdkPixbufFormat *)g_slist_nth_data (formats, i);
695                 mimes = info->mime_types;
696 
697                 for (j = 0; mimes[j] != NULL; j++)
698                         if (g_ascii_strcasecmp (mimes[j], mime_type) == 0) {
699                                 image_type = info->name;
700                                 break;
701                         }
702         }
703 
704         g_slist_free (formats);
705 
706         retval = g_object_new (GDK_TYPE_PIXBUF_LOADER, NULL);
707 
708         tmp = NULL;
709         gdk_pixbuf_loader_load_module (retval, image_type, &tmp);
710         if (tmp != NULL)
711                 {
712                         g_propagate_error (error, tmp);
713                         gdk_pixbuf_loader_close (retval, NULL);
714                         g_object_unref (retval);
715                         return NULL;
716                 }
717 
718         return retval;
719 }
720 
721 GdkPixbufLoader *
_gdk_pixbuf_loader_new_with_filename(const char * filename)722 _gdk_pixbuf_loader_new_with_filename (const char *filename)
723 {
724 	GdkPixbufLoader *retval;
725         GdkPixbufLoaderPrivate *priv;
726 
727         retval = g_object_new (GDK_TYPE_PIXBUF_LOADER, NULL);
728 	priv = retval->priv;
729 	priv->filename = g_strdup (filename);
730 
731 	return retval;
732 }
733 
734 /**
735  * gdk_pixbuf_loader_get_pixbuf:
736  * @loader: A pixbuf loader.
737  *
738  * Queries the #GdkPixbuf that a pixbuf loader is currently creating.
739  * In general it only makes sense to call this function after the
740  * "area-prepared" signal has been emitted by the loader; this means
741  * that enough data has been read to know the size of the image that
742  * will be allocated.  If the loader has not received enough data via
743  * gdk_pixbuf_loader_write(), then this function returns %NULL.  The
744  * returned pixbuf will be the same in all future calls to the loader,
745  * so simply calling g_object_ref() should be sufficient to continue
746  * using it.  Additionally, if the loader is an animation, it will
747  * return the "static image" of the animation
748  * (see gdk_pixbuf_animation_get_static_image()).
749  *
750  * Return value: (transfer none): The #GdkPixbuf that the loader is creating, or %NULL if not
751  * enough data has been read to determine how to create the image buffer.
752  **/
753 GdkPixbuf *
gdk_pixbuf_loader_get_pixbuf(GdkPixbufLoader * loader)754 gdk_pixbuf_loader_get_pixbuf (GdkPixbufLoader *loader)
755 {
756         GdkPixbufLoaderPrivate *priv;
757 
758         g_return_val_if_fail (GDK_IS_PIXBUF_LOADER (loader), NULL);
759 
760         priv = loader->priv;
761 
762         if (priv->animation)
763                 return gdk_pixbuf_animation_get_static_image (priv->animation);
764         else
765                 return NULL;
766 }
767 
768 /**
769  * gdk_pixbuf_loader_get_animation:
770  * @loader: A pixbuf loader
771  *
772  * Queries the #GdkPixbufAnimation that a pixbuf loader is currently creating.
773  * In general it only makes sense to call this function after the "area-prepared"
774  * signal has been emitted by the loader. If the loader doesn't have enough
775  * bytes yet (hasn't emitted the "area-prepared" signal) this function will
776  * return %NULL.
777  *
778  * Return value: (transfer none): The #GdkPixbufAnimation that the loader is loading, or %NULL if
779  * not enough data has been read to determine the information.
780 **/
781 GdkPixbufAnimation *
gdk_pixbuf_loader_get_animation(GdkPixbufLoader * loader)782 gdk_pixbuf_loader_get_animation (GdkPixbufLoader *loader)
783 {
784         GdkPixbufLoaderPrivate *priv;
785 
786         g_return_val_if_fail (GDK_IS_PIXBUF_LOADER (loader), NULL);
787 
788         priv = loader->priv;
789 
790         return priv->animation;
791 }
792 
793 /**
794  * gdk_pixbuf_loader_close:
795  * @loader: A pixbuf loader.
796  * @error: (allow-none): return location for a #GError, or %NULL to ignore errors
797  *
798  * Informs a pixbuf loader that no further writes with
799  * gdk_pixbuf_loader_write() will occur, so that it can free its
800  * internal loading structures. Also, tries to parse any data that
801  * hasn't yet been parsed; if the remaining data is partial or
802  * corrupt, an error will be returned.  If %FALSE is returned, @error
803  * will be set to an error from the #GDK_PIXBUF_ERROR or #G_FILE_ERROR
804  * domains. If you're just cancelling a load rather than expecting it
805  * to be finished, passing %NULL for @error to ignore it is
806  * reasonable.
807  *
808  * Remember that this does not unref the loader, so if you plan not to
809  * use it anymore, please g_object_unref() it.
810  *
811  * Returns: %TRUE if all image data written so far was successfully
812             passed out via the update_area signal
813  **/
814 gboolean
gdk_pixbuf_loader_close(GdkPixbufLoader * loader,GError ** error)815 gdk_pixbuf_loader_close (GdkPixbufLoader *loader,
816                          GError         **error)
817 {
818         GdkPixbufLoaderPrivate *priv;
819         gboolean retval = TRUE;
820 
821         g_return_val_if_fail (GDK_IS_PIXBUF_LOADER (loader), TRUE);
822         g_return_val_if_fail (error == NULL || *error == NULL, TRUE);
823 
824         priv = loader->priv;
825 
826         if (priv->closed)
827                 return TRUE;
828 
829         /* We have less than SNIFF_BUFFER_SIZE bytes in the image.
830          * Flush it, and keep going.
831          */
832         if (priv->image_module == NULL)
833                 {
834                         GError *tmp = NULL;
835                         gdk_pixbuf_loader_load_module (loader, NULL, &tmp);
836                         if (tmp != NULL)
837                                 {
838                                         g_propagate_error (error, tmp);
839                                         retval = FALSE;
840                                 }
841                 }
842 
843         if (priv->image_module && priv->image_module->stop_load && priv->context)
844                 {
845                         GError *tmp = NULL;
846                         if (!priv->image_module->stop_load (priv->context, &tmp) || tmp)
847                                 {
848 					/* don't call gdk_pixbuf_loader_ensure_error()
849  					 * here, since we might not get an error in the
850  					 * gdk_pixbuf_get_file_info() case
851  					 */
852 					if (tmp) {
853 						if (error && *error == NULL)
854 							g_propagate_error (error, tmp);
855 						else
856 							g_error_free (tmp);
857 					}
858                                         retval = FALSE;
859                                 }
860                 }
861 
862         priv->closed = TRUE;
863 
864         if (priv->needs_scale)
865                 {
866 
867                         g_signal_emit (loader, pixbuf_loader_signals[AREA_PREPARED], 0);
868                         g_signal_emit (loader, pixbuf_loader_signals[AREA_UPDATED], 0,
869                                        0, 0, priv->width, priv->height);
870                 }
871 
872 
873         g_signal_emit (loader, pixbuf_loader_signals[CLOSED], 0);
874 
875         return retval;
876 }
877 
878 /**
879  * gdk_pixbuf_loader_get_format:
880  * @loader: A pixbuf loader.
881  *
882  * Obtains the available information about the format of the
883  * currently loading image file.
884  *
885  * Returns: (nullable) (transfer none): A #GdkPixbufFormat or
886  * %NULL. The return value is owned by GdkPixbuf and should not be
887  * freed.
888  *
889  * Since: 2.2
890  */
891 GdkPixbufFormat *
gdk_pixbuf_loader_get_format(GdkPixbufLoader * loader)892 gdk_pixbuf_loader_get_format (GdkPixbufLoader *loader)
893 {
894         GdkPixbufLoaderPrivate *priv;
895 
896         g_return_val_if_fail (GDK_IS_PIXBUF_LOADER (loader), NULL);
897 
898         priv = loader->priv;
899 
900         if (priv->image_module)
901                 return _gdk_pixbuf_get_format (priv->image_module);
902         else
903                 return NULL;
904 }
905