diff --git a/docs/reference/gdk-pixbuf/tmpl/rendering.sgml b/docs/reference/gdk-pixbuf/tmpl/rendering.sgml index a3f86c3701..09afa8c659 100644 --- a/docs/reference/gdk-pixbuf/tmpl/rendering.sgml +++ b/docs/reference/gdk-pixbuf/tmpl/rendering.sgml @@ -23,8 +23,11 @@ Rendering a pixbuf to a GDK drawable. Since these functions use GdkRGB for rendering, you must - initialize GdkRGB before using any of them. You can do this by - calling gdk_rgb_init() near the beginning of your program. + initialize GdkRGB before using any of them. If you are using + GNOME, gnome_init() will do this for you automatically. + Otherwise, you can do this by calling gdk_rgb_init() near the + beginning of your program. + diff --git a/gdk-pixbuf/ChangeLog b/gdk-pixbuf/ChangeLog index 620cdf5210..5d525cce41 100644 --- a/gdk-pixbuf/ChangeLog +++ b/gdk-pixbuf/ChangeLog @@ -1,5 +1,15 @@ 2000-01-07 Jonathan Blandford + * gdk-pixbuf/gdk-pixbuf-io.c: Added progressive animation loading. + * gdk-pixbuf/gdk-pixbuf-io.h: Added progressive animation loading. + * gdk-pixbuf/gdk-pixbuf-loader.c: Added progressive animation + loading. + * gdk-pixbuf/gdk-pixbuf-loader.h: Added progressive animation + loading. + * gdk-pixbuf/io-gif.c (image_load_increment): I think the + ref-counting mess is finally fixed. Added progressive animation + loading. + * doc/tmpl/gdk-pixbuf-loader.sgml: much longer long description added. diff --git a/gdk-pixbuf/gdk-pixbuf-animation.c b/gdk-pixbuf/gdk-pixbuf-animation.c index 3a693cc968..5e9e0d17e9 100644 --- a/gdk-pixbuf/gdk-pixbuf-animation.c +++ b/gdk-pixbuf/gdk-pixbuf-animation.c @@ -98,7 +98,7 @@ gdk_pixbuf_animation_new_from_file (const char *filename) frame->delay_time = -1; frame->action = GDK_PIXBUF_FRAME_RETAIN; - animation = g_new (GdkPixbufAnimation, 1); + animation = g_new0 (GdkPixbufAnimation, 1); animation->ref_count = 1; animation->n_frames = 1; animation->frames = g_list_prepend (NULL, frame); diff --git a/gdk-pixbuf/gdk-pixbuf-io.h b/gdk-pixbuf/gdk-pixbuf-io.h index e6ba541c02..4e439ce9b6 100644 --- a/gdk-pixbuf/gdk-pixbuf-io.h +++ b/gdk-pixbuf/gdk-pixbuf-io.h @@ -44,8 +44,7 @@ typedef void (* ModuleUpdatedNotifyFunc) (GdkPixbuf *pixbuf, guint width, guint height, gpointer user_data); /* Needed only for animated images. */ -typedef void (* ModuleFrameDoneNotifyFunc) (GdkPixbuf *pixbuf, - gint frame, +typedef void (* ModuleFrameDoneNotifyFunc) (GdkPixbufFrame *frame, gpointer user_data); typedef void (* ModuleAnimationDoneNotifyFunc) (GdkPixbuf *pixbuf, gpointer user_data); diff --git a/gdk-pixbuf/gdk-pixbuf-loader.c b/gdk-pixbuf/gdk-pixbuf-loader.c index 69bb7f98ea..56637df75d 100644 --- a/gdk-pixbuf/gdk-pixbuf-loader.c +++ b/gdk-pixbuf/gdk-pixbuf-loader.c @@ -35,6 +35,8 @@ enum { AREA_UPDATED, AREA_PREPARED, + FRAME_DONE, + ANIMATION_DONE, CLOSED, LAST_SIGNAL }; @@ -89,11 +91,11 @@ gtk_marshal_NONE__INT_INT_INT_INT (GtkObject *object, GtkSignalFunc func, gpoint /** * gdk_pixbuf_loader_get_type: - * @void: - * + * @void: + * * Registers the #GdkPixubfLoader class if necessary, and returns the type ID * associated to it. - * + * * Return value: The type ID of the #GdkPixbufLoader class. **/ GtkType @@ -148,6 +150,22 @@ gdk_pixbuf_loader_class_init (GdkPixbufLoaderClass *class) GTK_TYPE_INT, GTK_TYPE_INT); + pixbuf_loader_signals[FRAME_DONE] = + gtk_signal_new ("frame_done", + GTK_RUN_LAST, + parent_class->type, + GTK_SIGNAL_OFFSET (GdkPixbufLoaderClass, frame_done), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); + + pixbuf_loader_signals[ANIMATION_DONE] = + gtk_signal_new ("animation_done", + GTK_RUN_LAST, + parent_class->type, + GTK_SIGNAL_OFFSET (GdkPixbufLoaderClass, animation_done), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); + pixbuf_loader_signals[CLOSED] = gtk_signal_new ("closed", GTK_RUN_LAST, @@ -186,6 +204,8 @@ gdk_pixbuf_loader_destroy (GtkObject *object) if (!priv->closed) gdk_pixbuf_loader_close (loader); + if (priv->animation) + gdk_pixbuf_animation_unref (priv->animation); if (priv->pixbuf) gdk_pixbuf_unref (priv->pixbuf); @@ -236,14 +256,40 @@ gdk_pixbuf_loader_update (GdkPixbuf *pixbuf, guint x, guint y, guint width, guin MIN (height, gdk_pixbuf_get_height (priv->pixbuf))); } +static void +gdk_pixbuf_loader_frame_done (GdkPixbufFrame *frame, gpointer loader) +{ + GdkPixbufLoaderPrivate *priv = NULL; + + priv = GDK_PIXBUF_LOADER (loader)->private; + + if (priv->animation == NULL) { + priv->animation = g_new0 (GdkPixbufAnimation, 1); + priv->animation->n_frames = 0; + priv->animation->ref_count = 1; + } + + priv->animation->frames = g_list_append (priv->animation->frames, frame); + priv->animation->n_frames ++; + gtk_signal_emit (GTK_OBJECT (loader), + pixbuf_loader_signals[FRAME_DONE], + frame); +} + +static void +gdk_pixbuf_loader_animation_done (GdkPixbuf *pixbuf, gpointer loader) +{ + gtk_signal_emit (GTK_OBJECT (loader), + pixbuf_loader_signals[ANIMATION_DONE]); +} + /** * gdk_pixbuf_loader_new: - * @void: - * + * * Creates a new pixbuf loader object. - * + * * Return value: A newly-created pixbuf loader. **/ GdkPixbufLoader * @@ -276,7 +322,11 @@ gdk_pixbuf_loader_load_module(GdkPixbufLoader *loader) return 0; } - priv->context = (*priv->image_module->begin_load) (gdk_pixbuf_loader_prepare, gdk_pixbuf_loader_update, NULL, NULL, loader); + priv->context = (*priv->image_module->begin_load) (gdk_pixbuf_loader_prepare, + gdk_pixbuf_loader_update, + gdk_pixbuf_loader_frame_done, + gdk_pixbuf_loader_animation_done, + loader); if (priv->context == NULL) { g_warning("Failed to begin progressive load"); @@ -285,7 +335,7 @@ gdk_pixbuf_loader_load_module(GdkPixbufLoader *loader) if( (* priv->image_module->load_increment) (priv->context, priv->header_buf, priv->header_buf_offset) ) return priv->header_buf_offset; - + return 0; } @@ -297,9 +347,9 @@ gdk_pixbuf_loader_eat_header_write (GdkPixbufLoader *loader, const guchar *buf, nbytes = MIN(LOADER_HEADER_SIZE - priv->header_buf_offset, count); memcpy (priv->header_buf + priv->header_buf_offset, buf, nbytes); - + priv->header_buf_offset += nbytes; - + if(priv->header_buf_offset >= LOADER_HEADER_SIZE) { if (gdk_pixbuf_loader_load_module(loader) == 0) return 0; @@ -385,11 +435,12 @@ gdk_pixbuf_loader_get_pixbuf (GdkPixbufLoader *loader) /** * gdk_pixbuf_loader_get_animation: * @loader: A pixbuf loader - * + * * Queries the GdkPixbufAnimation that a pixbuf loader is currently creating. * In general it only makes sense to call this function afer the "area_prepared" - * signal has been emitted by the loader. - * + * signal has been emitted by the loader. If the image is not an animation, + * then it will return NULL. + * * Return value: The GdkPixbufAnimation that the loader is loading, or NULL if not enough data has been read to determine the information. **/ @@ -438,3 +489,4 @@ gdk_pixbuf_loader_close (GdkPixbufLoader *loader) gtk_signal_emit (GTK_OBJECT (loader), pixbuf_loader_signals[CLOSED]); } + diff --git a/gdk-pixbuf/gdk-pixbuf-loader.h b/gdk-pixbuf/gdk-pixbuf-loader.h index bbab22e11e..9f9a79dc25 100644 --- a/gdk-pixbuf/gdk-pixbuf-loader.h +++ b/gdk-pixbuf/gdk-pixbuf-loader.h @@ -61,7 +61,7 @@ struct _GdkPixbufLoaderClass { void (* area_updated) (GdkPixbufLoader *loader, guint x, guint y, guint width, guint height); - void (* frame_done) (GdkPixbufLoader *loader, gint frame); + void (* frame_done) (GdkPixbufLoader *loader, GdkPixbufFrame *frame); void (* animation_done) (GdkPixbufLoader *loader); diff --git a/gdk-pixbuf/io-gif.c b/gdk-pixbuf/io-gif.c index 13a66cfba4..1ba894dda6 100644 --- a/gdk-pixbuf/io-gif.c +++ b/gdk-pixbuf/io-gif.c @@ -42,6 +42,7 @@ * -2 -> failure; abort the load * -3 -> control needs to be passed back to the main loop * \_ (most of the time returning 0 will get this, but not always) + * * >1 -> for functions that get a guchar, the char will be returned. * * -jrb (11/03/1999) @@ -129,6 +130,8 @@ struct _GifContext /* progressive read, only. */ ModulePreparedNotifyFunc prepare_func; ModuleUpdatedNotifyFunc update_func; + ModuleFrameDoneNotifyFunc frame_done_func; + ModuleAnimationDoneNotifyFunc anim_done_func; gpointer user_data; guchar *buf; guint ptr; @@ -670,7 +673,7 @@ gif_get_lzw (GifContext *context) if (context->prepare_func) (* context->prepare_func) (context->pixbuf, context->user_data); - if (context->animation) { + if (context->animation || context->frame_done_func) { context->frame = g_new (GdkPixbufFrame, 1); context->frame->x_offset = 0; context->frame->y_offset = 0; @@ -691,8 +694,10 @@ gif_get_lzw (GifContext *context) break; } context->frame->pixbuf = context->pixbuf; - context->animation->n_frames ++; - context->animation->frames = g_list_append (context->animation->frames, context->frame); + if (context->animation) { + context->animation->n_frames ++; + context->animation->frames = g_list_append (context->animation->frames, context->frame); + } } } dest = gdk_pixbuf_get_pixels (context->pixbuf); @@ -816,6 +821,10 @@ gif_get_lzw (GifContext *context) } if (context->animation && context->state == GIF_GET_NEXT_STEP) { + (* context->frame_done_func) (context->frame, + context->user_data); + + gdk_pixbuf_unref (context->pixbuf); context->pixbuf = NULL; context->frame = NULL; } @@ -1059,6 +1068,8 @@ new_context (void) context->state = GIF_START; context->prepare_func = NULL; context->update_func = NULL; + context->frame_done_func = NULL; + context->anim_done_func = NULL; context->user_data = NULL; context->buf = NULL; context->amount_needed = 0; @@ -1099,6 +1110,8 @@ image_begin_load (ModulePreparedNotifyFunc prepare_func, context = new_context (); context->prepare_func = prepare_func; context->update_func = update_func; + context->frame_done_func = frame_done_func; + context->anim_done_func = anim_done_func; context->user_data = user_data; return (gpointer) context; @@ -1113,7 +1126,9 @@ image_stop_load (gpointer data) if (context->pixbuf) gdk_pixbuf_unref (context->pixbuf); -/* g_free (context->buf); */ + if (context->animation) + gdk_pixbuf_animation_unref (context->animation); +/* g_free (context->buf);*/ g_free (context); } diff --git a/gdk-pixbuf/io-tiff.c b/gdk-pixbuf/io-tiff.c index 155a035778..a45a0b1149 100644 --- a/gdk-pixbuf/io-tiff.c +++ b/gdk-pixbuf/io-tiff.c @@ -5,6 +5,7 @@ * * Authors: Mark Crichton * Federico Mena-Quintero + * Jonathan Blandford * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -110,8 +111,8 @@ image_load_real (FILE *f, TiffData *context) TIFFClose (tiff); if (context) { - gdk_pixbuf_unref (pixbuf); (* context->update_func) (pixbuf, 0, 0, w, h, context->user_data); + gdk_pixbuf_unref (pixbuf); } return pixbuf; diff --git a/gtk/gdk-pixbuf-loader.c b/gtk/gdk-pixbuf-loader.c index 69bb7f98ea..56637df75d 100644 --- a/gtk/gdk-pixbuf-loader.c +++ b/gtk/gdk-pixbuf-loader.c @@ -35,6 +35,8 @@ enum { AREA_UPDATED, AREA_PREPARED, + FRAME_DONE, + ANIMATION_DONE, CLOSED, LAST_SIGNAL }; @@ -89,11 +91,11 @@ gtk_marshal_NONE__INT_INT_INT_INT (GtkObject *object, GtkSignalFunc func, gpoint /** * gdk_pixbuf_loader_get_type: - * @void: - * + * @void: + * * Registers the #GdkPixubfLoader class if necessary, and returns the type ID * associated to it. - * + * * Return value: The type ID of the #GdkPixbufLoader class. **/ GtkType @@ -148,6 +150,22 @@ gdk_pixbuf_loader_class_init (GdkPixbufLoaderClass *class) GTK_TYPE_INT, GTK_TYPE_INT); + pixbuf_loader_signals[FRAME_DONE] = + gtk_signal_new ("frame_done", + GTK_RUN_LAST, + parent_class->type, + GTK_SIGNAL_OFFSET (GdkPixbufLoaderClass, frame_done), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); + + pixbuf_loader_signals[ANIMATION_DONE] = + gtk_signal_new ("animation_done", + GTK_RUN_LAST, + parent_class->type, + GTK_SIGNAL_OFFSET (GdkPixbufLoaderClass, animation_done), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); + pixbuf_loader_signals[CLOSED] = gtk_signal_new ("closed", GTK_RUN_LAST, @@ -186,6 +204,8 @@ gdk_pixbuf_loader_destroy (GtkObject *object) if (!priv->closed) gdk_pixbuf_loader_close (loader); + if (priv->animation) + gdk_pixbuf_animation_unref (priv->animation); if (priv->pixbuf) gdk_pixbuf_unref (priv->pixbuf); @@ -236,14 +256,40 @@ gdk_pixbuf_loader_update (GdkPixbuf *pixbuf, guint x, guint y, guint width, guin MIN (height, gdk_pixbuf_get_height (priv->pixbuf))); } +static void +gdk_pixbuf_loader_frame_done (GdkPixbufFrame *frame, gpointer loader) +{ + GdkPixbufLoaderPrivate *priv = NULL; + + priv = GDK_PIXBUF_LOADER (loader)->private; + + if (priv->animation == NULL) { + priv->animation = g_new0 (GdkPixbufAnimation, 1); + priv->animation->n_frames = 0; + priv->animation->ref_count = 1; + } + + priv->animation->frames = g_list_append (priv->animation->frames, frame); + priv->animation->n_frames ++; + gtk_signal_emit (GTK_OBJECT (loader), + pixbuf_loader_signals[FRAME_DONE], + frame); +} + +static void +gdk_pixbuf_loader_animation_done (GdkPixbuf *pixbuf, gpointer loader) +{ + gtk_signal_emit (GTK_OBJECT (loader), + pixbuf_loader_signals[ANIMATION_DONE]); +} + /** * gdk_pixbuf_loader_new: - * @void: - * + * * Creates a new pixbuf loader object. - * + * * Return value: A newly-created pixbuf loader. **/ GdkPixbufLoader * @@ -276,7 +322,11 @@ gdk_pixbuf_loader_load_module(GdkPixbufLoader *loader) return 0; } - priv->context = (*priv->image_module->begin_load) (gdk_pixbuf_loader_prepare, gdk_pixbuf_loader_update, NULL, NULL, loader); + priv->context = (*priv->image_module->begin_load) (gdk_pixbuf_loader_prepare, + gdk_pixbuf_loader_update, + gdk_pixbuf_loader_frame_done, + gdk_pixbuf_loader_animation_done, + loader); if (priv->context == NULL) { g_warning("Failed to begin progressive load"); @@ -285,7 +335,7 @@ gdk_pixbuf_loader_load_module(GdkPixbufLoader *loader) if( (* priv->image_module->load_increment) (priv->context, priv->header_buf, priv->header_buf_offset) ) return priv->header_buf_offset; - + return 0; } @@ -297,9 +347,9 @@ gdk_pixbuf_loader_eat_header_write (GdkPixbufLoader *loader, const guchar *buf, nbytes = MIN(LOADER_HEADER_SIZE - priv->header_buf_offset, count); memcpy (priv->header_buf + priv->header_buf_offset, buf, nbytes); - + priv->header_buf_offset += nbytes; - + if(priv->header_buf_offset >= LOADER_HEADER_SIZE) { if (gdk_pixbuf_loader_load_module(loader) == 0) return 0; @@ -385,11 +435,12 @@ gdk_pixbuf_loader_get_pixbuf (GdkPixbufLoader *loader) /** * gdk_pixbuf_loader_get_animation: * @loader: A pixbuf loader - * + * * Queries the GdkPixbufAnimation that a pixbuf loader is currently creating. * In general it only makes sense to call this function afer the "area_prepared" - * signal has been emitted by the loader. - * + * signal has been emitted by the loader. If the image is not an animation, + * then it will return NULL. + * * Return value: The GdkPixbufAnimation that the loader is loading, or NULL if not enough data has been read to determine the information. **/ @@ -438,3 +489,4 @@ gdk_pixbuf_loader_close (GdkPixbufLoader *loader) gtk_signal_emit (GTK_OBJECT (loader), pixbuf_loader_signals[CLOSED]); } + diff --git a/gtk/gdk-pixbuf-loader.h b/gtk/gdk-pixbuf-loader.h index bbab22e11e..9f9a79dc25 100644 --- a/gtk/gdk-pixbuf-loader.h +++ b/gtk/gdk-pixbuf-loader.h @@ -61,7 +61,7 @@ struct _GdkPixbufLoaderClass { void (* area_updated) (GdkPixbufLoader *loader, guint x, guint y, guint width, guint height); - void (* frame_done) (GdkPixbufLoader *loader, gint frame); + void (* frame_done) (GdkPixbufLoader *loader, GdkPixbufFrame *frame); void (* animation_done) (GdkPixbufLoader *loader);