1 /* GdkPixbuf library - Main header file
3 * Copyright (C) 1999 The Free Software Foundation
5 * Authors: Mark Crichton <crichton@gimp.org>
6 * Miguel de Icaza <miguel@gnu.org>
7 * Federico Mena-Quintero <federico@gimp.org>
8 * Jonathan Blandford <jrb@redhat.com>
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Library General Public License for more details.
20 * You should have received a copy of the GNU Library General Public
21 * License along with this library; if not, write to the
22 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 * Boston, MA 02111-1307, USA.
26 #include "gdk-pixbuf-loader.h"
27 #include "gdk-pixbuf-io.h"
28 #include <gtk/gtksignal.h>
39 static GtkObjectClass *parent_class;
41 static void gdk_pixbuf_loader_class_init (GdkPixbufLoaderClass *klass);
42 static void gdk_pixbuf_loader_init (GdkPixbufLoader *loader);
43 static void gdk_pixbuf_loader_destroy (GtkObject *loader);
44 static void gdk_pixbuf_loader_finalize (GtkObject *loader);
46 static guint pixbuf_loader_signals[LAST_SIGNAL] = { 0 };
56 GdkPixbufModule *image_module;
58 } GdkPixbufLoaderPrivate;
63 typedef void (* GtkSignal_NONE__INT_INT_INT_INT) (GtkObject *object,
64 gint arg1, gint arg2, gint arg3, gint arg4,
67 gtk_marshal_NONE__INT_INT_INT_INT (GtkObject *object, GtkSignalFunc func, gpointer func_data,
70 GtkSignal_NONE__INT_INT_INT_INT rfunc;
72 rfunc = (GtkSignal_NONE__INT_INT_INT_INT) func;
74 GTK_VALUE_INT (args[0]),
75 GTK_VALUE_INT (args[1]),
76 GTK_VALUE_INT (args[2]),
77 GTK_VALUE_INT (args[3]),
84 * gdk_pixbuf_loader_get_type:
87 * Registers the &GdkPixubfLoader class if necessary, and returns the type ID
90 * Return value: The type ID of the &GdkPixbufLoader class.
93 gdk_pixbuf_loader_get_type (void)
95 static GtkType loader_type = 0;
98 static const GtkTypeInfo loader_info = {
100 sizeof (GdkPixbufLoader),
101 sizeof (GdkPixbufLoaderClass),
102 (GtkClassInitFunc) gdk_pixbuf_loader_class_init,
103 (GtkObjectInitFunc) gdk_pixbuf_loader_init,
104 /* reserved_1 */ NULL,
105 /* reserved_2 */ NULL,
106 (GtkClassInitFunc) NULL,
109 loader_type = gtk_type_unique (GTK_TYPE_OBJECT, &loader_info);
116 gdk_pixbuf_loader_class_init (GdkPixbufLoaderClass *class)
118 GtkObjectClass *object_class;
120 object_class = (GtkObjectClass *) class;
122 parent_class = gtk_type_class (gtk_object_get_type ());
124 pixbuf_loader_signals[AREA_PREPARED] =
125 gtk_signal_new ("area_prepared",
128 GTK_SIGNAL_OFFSET (GdkPixbufLoaderClass, area_prepared),
129 gtk_marshal_NONE__NONE,
132 pixbuf_loader_signals[AREA_UPDATED] =
133 gtk_signal_new ("area_updated",
136 GTK_SIGNAL_OFFSET (GdkPixbufLoaderClass, area_updated),
137 gtk_marshal_NONE__INT_INT_INT_INT,
144 pixbuf_loader_signals[CLOSED] =
145 gtk_signal_new ("closed",
148 GTK_SIGNAL_OFFSET (GdkPixbufLoaderClass, closed),
149 gtk_marshal_NONE__NONE,
152 gtk_object_class_add_signals (object_class, pixbuf_loader_signals, LAST_SIGNAL);
154 object_class->destroy = gdk_pixbuf_loader_destroy;
155 object_class->finalize = gdk_pixbuf_loader_finalize;
159 gdk_pixbuf_loader_init (GdkPixbufLoader *loader)
161 GdkPixbufLoaderPrivate *priv;
163 priv = g_new0 (GdkPixbufLoaderPrivate, 1);
164 loader->private = priv;
168 gdk_pixbuf_loader_destroy (GtkObject *object)
170 GdkPixbufLoader *loader;
171 GdkPixbufLoaderPrivate *priv = NULL;
173 g_return_if_fail (object != NULL);
174 g_return_if_fail (GDK_IS_PIXBUF_LOADER (object));
176 loader = GDK_PIXBUF_LOADER (object);
177 priv = loader->private;
180 gdk_pixbuf_loader_close (loader);
183 gdk_pixbuf_unref (priv->pixbuf);
185 if (GTK_OBJECT_CLASS (parent_class)->destroy)
186 (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
190 gdk_pixbuf_loader_finalize (GtkObject *object)
192 GdkPixbufLoader *loader;
193 GdkPixbufLoaderPrivate *priv = NULL;
195 loader = GDK_PIXBUF_LOADER (object);
196 priv = loader->private;
200 if (GTK_OBJECT_CLASS (parent_class)->finalize)
201 (* GTK_OBJECT_CLASS (parent_class)->finalize) (object);
205 gdk_pixbuf_loader_prepare (GdkPixbuf *pixbuf, gpointer loader)
207 GdkPixbufLoaderPrivate *priv = NULL;
209 priv = GDK_PIXBUF_LOADER (loader)->private;
210 gdk_pixbuf_ref (pixbuf);
211 g_assert (priv->pixbuf == NULL);
213 priv->pixbuf = pixbuf;
214 gtk_signal_emit (GTK_OBJECT (loader), pixbuf_loader_signals[AREA_PREPARED]);
220 * gdk_pixbuf_loader_new:
223 * Creates a new pixbuf loader object.
225 * Return value: A newly-created pixbuf loader.
228 gdk_pixbuf_loader_new (void)
230 return gtk_type_new (gdk_pixbuf_loader_get_type ());
234 * gdk_pixbuf_loader_write:
235 * @loader: A pixbuf loader.
236 * @buf: The image data.
237 * @count: The length of @buf in bytes.
239 * This will load the next @size bytes of the image. It will return TRUE if the
240 * data was loaded successfully, and FALSE if an error occurred. In this case,
241 * the loader will be closed, and will not accept further writes.
243 * Return value: Returns TRUE if the write was successful -- FALSE if the loader
244 * cannot parse the buf.
247 gdk_pixbuf_loader_write (GdkPixbufLoader *loader, guchar *buf, size_t count)
249 GdkPixbufLoaderPrivate *priv;
251 g_return_val_if_fail (loader != NULL, FALSE);
252 g_return_val_if_fail (GDK_IS_PIXBUF_LOADER (loader), FALSE);
253 g_return_val_if_fail (buf != NULL, FALSE);
254 g_return_val_if_fail (count >= 0, FALSE);
256 priv = loader->private;
258 /* we expect it's not to be closed */
259 g_return_val_if_fail (priv->closed == FALSE, FALSE);
261 if (priv->image_module == NULL) {
262 gboolean retval = TRUE;
264 memcpy (priv->buf + priv->buf_offset,
266 (priv->buf_offset + count > 128) ? (128 - priv->buf_offset) : count);
268 if (priv->buf_offset + count >= 128) {
269 /* We have enough data to start doing something with the image */
270 priv->image_module = gdk_pixbuf_get_module (priv->buf, 128);
271 if (priv->image_module == NULL)
273 else if ((priv->image_module->begin_load == NULL) ||
274 (priv->image_module->stop_load == NULL) ||
275 (priv->image_module->load_increment == NULL)) {
276 g_warning ("module %s does not support incremental loading.\n",
277 priv->image_module->module_name);
280 priv->context = (*priv->image_module->begin_load) (
281 gdk_pixbuf_loader_prepare, loader);
283 if (priv->context == NULL) {
284 g_warning("Failed to begin progressive load");
288 retval = (* priv->image_module->load_increment) (
289 priv->context, priv->buf, 128);
291 /* if we had more then 128 bytes total, we want
292 * to send the rest of the buffer.
295 if (retval && (priv->buf_offset + count) > 128) {
296 retval = (* priv->image_module->load_increment) (
299 count + priv->buf_offset - 128);
303 priv->buf_offset += count;
308 if (priv->image_module->load_increment)
309 return (* priv->image_module->load_increment) (priv->context, buf, count);
315 * gdk_pixbuf_loader_get_pixbuf:
316 * @loader: A pixbuf loader.
318 * Gets the GdkPixbuf that the loader is currently loading. If the loader
319 * hasn't been enough data via gdk_pixbuf_loader_write, then NULL is returned.
320 * Any application using this function should check for this value when it is
321 * used. The pixbuf returned will be the same in all future calls to the
322 * loader, so simply calling a gdk_pixbuf_ref() should be sufficient to continue
325 * Return value: The GdkPixbuf that the loader is loading.
328 gdk_pixbuf_loader_get_pixbuf (GdkPixbufLoader *loader)
330 GdkPixbufLoaderPrivate *priv;
332 g_return_val_if_fail (loader != NULL, NULL);
333 g_return_val_if_fail (GDK_IS_PIXBUF_LOADER (loader), NULL);
335 priv = loader->private;
341 * gdk_pixbuf_loader_close:
342 * @loader: A pixbuf loader.
344 * Tells the loader to stop accepting writes.
347 gdk_pixbuf_loader_close (GdkPixbufLoader *loader)
349 GdkPixbufLoaderPrivate *priv;
351 g_return_if_fail (loader != NULL);
352 g_return_if_fail (GDK_IS_PIXBUF_LOADER (loader));
354 priv = loader->private;
356 /* we expect it's not closed */
357 g_return_if_fail (priv->closed == FALSE);
359 /* We have less the 128 bytes in the image. Flush it, and keep going. */
360 if (priv->image_module == NULL) {
361 priv->image_module = gdk_pixbuf_get_module (priv->buf, priv->buf_offset);
362 if (priv->image_module &&
363 ((priv->image_module->begin_load == NULL) ||
364 (priv->image_module->stop_load == NULL) ||
365 (priv->image_module->load_increment == NULL))) {
366 g_warning ("module %s does not support incremental loading.\n",
367 priv->image_module->module_name);
368 } else if (priv->image_module) {
369 g_print ("module loaded: name is %s\n", priv->image_module->module_name);
370 priv->context = (* priv->image_module->begin_load) (
371 gdk_pixbuf_loader_prepare, loader);
372 (* priv->image_module->load_increment) (priv->context,
373 priv->buf, priv->buf_offset);
377 if (priv->image_module && priv->image_module->stop_load)
378 (* priv->image_module->stop_load) (priv->context);