forked from AuroraMiddleware/gtk
Added progressive animation loading. Added progressive animation loading.
2000-01-07 Jonathan Blandford <jrb@redhat.com> * 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. I think progressive animation loading all works now. It's all documented too, if anyone wants to play with it.
This commit is contained in:
parent
0e86d28026
commit
84c85a1a11
@ -23,8 +23,11 @@ Rendering a pixbuf to a GDK drawable.
|
||||
<important>
|
||||
<para>
|
||||
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.
|
||||
|
||||
</para>
|
||||
</important>
|
||||
|
||||
|
@ -1,5 +1,15 @@
|
||||
2000-01-07 Jonathan Blandford <jrb@redhat.com>
|
||||
|
||||
* 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.
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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]);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
*
|
||||
* Authors: Mark Crichton <crichton@gimp.org>
|
||||
* Federico Mena-Quintero <federico@gimp.org>
|
||||
* Jonathan Blandford <jrb@redhat.com>
|
||||
*
|
||||
* 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;
|
||||
|
@ -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]);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user