diff options
Diffstat (limited to 'gdk-pixbuf/gdk-pixbuf-animation.c')
-rw-r--r-- | gdk-pixbuf/gdk-pixbuf-animation.c | 655 |
1 files changed, 487 insertions, 168 deletions
diff --git a/gdk-pixbuf/gdk-pixbuf-animation.c b/gdk-pixbuf/gdk-pixbuf-animation.c index cc32559048..274813c503 100644 --- a/gdk-pixbuf/gdk-pixbuf-animation.c +++ b/gdk-pixbuf/gdk-pixbuf-animation.c @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ /* GdkPixbuf library - Simple animation support * * Copyright (C) 1999 The Free Software Foundation @@ -26,12 +27,59 @@ #include "gdk-pixbuf-io.h" #include "gdk-pixbuf-private.h" -static void gdk_pixbuf_animation_class_init (GdkPixbufAnimationClass *klass); -static void gdk_pixbuf_animation_finalize (GObject *object); +typedef struct _GdkPixbufNonAnim GdkPixbufNonAnim; +typedef struct _GdkPixbufNonAnimClass GdkPixbufNonAnimClass; + +#define GDK_TYPE_PIXBUF_NON_ANIM (gdk_pixbuf_non_anim_get_type ()) +#define GDK_PIXBUF_NON_ANIM(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_PIXBUF_NON_ANIM, GdkPixbufNonAnim)) +#define GDK_IS_PIXBUF_NON_ANIM(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_PIXBUF_NON_ANIM)) + +#define GDK_PIXBUF_NON_ANIM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_PIXBUF_NON_ANIM, GdkPixbufNonAnimClass)) +#define GDK_IS_PIXBUF_NON_ANIM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_PIXBUF_NON_ANIM)) +#define GDK_PIXBUF_NON_ANIM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_PIXBUF_NON_ANIM, GdkPixbufNonAnimClass)) + +/* Private part of the GdkPixbufNonAnim structure */ +struct _GdkPixbufNonAnim { + GdkPixbufAnimation parent_instance; + + GdkPixbuf *pixbuf; +}; + +struct _GdkPixbufNonAnimClass { + GdkPixbufAnimationClass parent_class; + +}; + +static GType gdk_pixbuf_non_anim_get_type (void) G_GNUC_CONST; -static gpointer parent_class; +typedef struct _GdkPixbufNonAnimIter GdkPixbufNonAnimIter; +typedef struct _GdkPixbufNonAnimIterClass GdkPixbufNonAnimIterClass; + + +#define GDK_TYPE_PIXBUF_NON_ANIM_ITER (gdk_pixbuf_non_anim_iter_get_type ()) +#define GDK_PIXBUF_NON_ANIM_ITER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_PIXBUF_NON_ANIM_ITER, GdkPixbufNonAnimIter)) +#define GDK_IS_PIXBUF_NON_ANIM_ITER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_PIXBUF_NON_ANIM_ITER)) + +#define GDK_PIXBUF_NON_ANIM_ITER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_PIXBUF_NON_ANIM_ITER, GdkPixbufNonAnimIterClass)) +#define GDK_IS_PIXBUF_NON_ANIM_ITER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_PIXBUF_NON_ANIM_ITER)) +#define GDK_PIXBUF_NON_ANIM_ITER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_PIXBUF_NON_ANIM_ITER, GdkPixbufNonAnimIterClass)) + +struct _GdkPixbufNonAnimIter { + GdkPixbufAnimationIter parent_instance; + + GdkPixbufNonAnim *non_anim; +}; + +struct _GdkPixbufNonAnimIterClass { + GdkPixbufAnimationIterClass parent_class; + +}; + +static GType gdk_pixbuf_non_anim_iter_get_type (void) G_GNUC_CONST; + + GType gdk_pixbuf_animation_get_type (void) @@ -43,7 +91,7 @@ gdk_pixbuf_animation_get_type (void) sizeof (GdkPixbufAnimationClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, - (GClassInitFunc) gdk_pixbuf_animation_class_init, + (GClassInitFunc) NULL, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (GdkPixbufAnimation), @@ -59,35 +107,6 @@ gdk_pixbuf_animation_get_type (void) return object_type; } -static void -gdk_pixbuf_animation_class_init (GdkPixbufAnimationClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - parent_class = g_type_class_peek_parent (klass); - - object_class->finalize = gdk_pixbuf_animation_finalize; -} - -static void -gdk_pixbuf_animation_finalize (GObject *object) -{ - GdkPixbufAnimation *animation = GDK_PIXBUF_ANIMATION (object); - - GList *l; - GdkPixbufFrame *frame; - - for (l = animation->frames; l; l = l->next) { - frame = l->data; - gdk_pixbuf_unref (frame->pixbuf); - g_free (frame); - } - - g_list_free (animation->frames); - - G_OBJECT_CLASS (parent_class)->finalize (object); -} - /** @@ -154,7 +173,6 @@ gdk_pixbuf_animation_new_from_file (const char *filename, if (image_module->load_animation == NULL) { GdkPixbuf *pixbuf; - GdkPixbufFrame *frame; /* Keep this logic in sync with gdk_pixbuf_new_from_file() */ @@ -191,20 +209,9 @@ gdk_pixbuf_animation_new_from_file (const char *filename, if (pixbuf == NULL) return NULL; - frame = g_new (GdkPixbufFrame, 1); - frame->pixbuf = pixbuf; - g_object_ref (G_OBJECT (frame->pixbuf)); - frame->x_offset = 0; - frame->y_offset = 0; - frame->delay_time = -1; - frame->action = GDK_PIXBUF_FRAME_RETAIN; + animation = gdk_pixbuf_non_anim_new (pixbuf); - animation = g_object_new (GDK_TYPE_PIXBUF_ANIMATION, NULL); - - animation->n_frames = 1; - animation->frames = g_list_prepend (NULL, frame); - animation->width = gdk_pixbuf_get_width (pixbuf); - animation->height = gdk_pixbuf_get_height (pixbuf); + g_object_unref (G_OBJECT (pixbuf)); } else { fseek (f, 0, SEEK_SET); animation = (* image_module->load_animation) (f, error); @@ -262,6 +269,46 @@ gdk_pixbuf_animation_unref (GdkPixbufAnimation *animation) } /** + * gdk_pixbuf_animation_is_static_image: + * @animation: a #GdkPixbufAnimation + * + * If you load a file with gdk_pixbuf_animation_new_from_file() and it turns + * out to be a plain, unanimated image, then this function will return + * %TRUE. Use gdk_pixbuf_animation_get_static_image() to retrieve + * the image. + * + * Return value: %TRUE if the "animation" was really just an image + **/ +gboolean +gdk_pixbuf_animation_is_static_image (GdkPixbufAnimation *animation) +{ + g_return_val_if_fail (GDK_IS_PIXBUF_ANIMATION (animation), FALSE); + + return GDK_PIXBUF_ANIMATION_GET_CLASS (animation)->is_static_image (animation); +} + +/** + * gdk_pixbuf_animation_get_static_image: + * @animation: a #GdkPixbufAnimation + * + * If an animation is really just a plain image (has only one frame), + * this function returns that image. If the animation is an animation, + * this function returns a reasonable thing to display as a static + * unanimated image, which might be the first frame, or something more + * sophisticated. If an animation hasn't loaded any frames yet, this + * function will return %NULL. + * + * Return value: unanimated image representing the animation + **/ +GdkPixbuf* +gdk_pixbuf_animation_get_static_image (GdkPixbufAnimation *animation) +{ + g_return_val_if_fail (GDK_IS_PIXBUF_ANIMATION (animation), NULL); + + return GDK_PIXBUF_ANIMATION_GET_CLASS (animation)->get_static_image (animation); +} + +/** * gdk_pixbuf_animation_get_width: * @animation: An animation. * @@ -272,9 +319,16 @@ gdk_pixbuf_animation_unref (GdkPixbufAnimation *animation) int gdk_pixbuf_animation_get_width (GdkPixbufAnimation *animation) { - g_return_val_if_fail (animation != NULL, -1); + int width; + + g_return_val_if_fail (GDK_IS_PIXBUF_ANIMATION (animation), 0); + + width = 0; + GDK_PIXBUF_ANIMATION_GET_CLASS (animation)->get_size (animation, + &width, NULL); + - return animation->width; + return width; } /** @@ -288,179 +342,444 @@ gdk_pixbuf_animation_get_width (GdkPixbufAnimation *animation) int gdk_pixbuf_animation_get_height (GdkPixbufAnimation *animation) { - g_return_val_if_fail (animation != NULL, -1); - - return animation->height; -} + int height; + + g_return_val_if_fail (GDK_IS_PIXBUF_ANIMATION (animation), 0); -/** - * gdk_pixbuf_animation_get_num_frames: - * @animation: An animation. - * - * Queries the number of frames in a pixbuf animation. - * - * Return value: Number of frames in the animation. - **/ -int -gdk_pixbuf_animation_get_num_frames (GdkPixbufAnimation *animation) -{ - g_return_val_if_fail (animation != NULL, -1); + height = 0; + GDK_PIXBUF_ANIMATION_GET_CLASS (animation)->get_size (animation, + NULL, &height); + - return animation->n_frames; + return height; } + /** - * gdk_pixbuf_animation_get_frames: - * @animation: An animation. + * gdk_pixbuf_animation_get_iter: + * @animation: a #GdkPixbufAnimation + * @start_time: time when the animation starts playing + * + * Get an iterator for displaying an animation. The iterator provides + * the frames that should be displayed at a given time. + * It should be freed after use with g_object_unref(). + * + * @start_time would normally come from g_get_current_time(), and + * marks the beginning of animation playback. After creating an + * iterator, you should immediately display the pixbuf returned by + * gdk_pixbuf_animation_iter_get_pixbuf(). Then, you should install a + * timeout (with g_timeout_add()) or by some other mechanism ensure + * that you'll update the image after + * gdk_pixbuf_animation_iter_get_delay_time() milliseconds. Each time + * the image is updated, you should reinstall the timeout with the new, + * possibly-changed delay time. + * + * As a shortcut, if @start_time is %NULL, the result of + * g_get_current_time() will be used automatically. * - * Queries the list of frames of an animation. + * To update the image (i.e. possibly change the result of + * gdk_pixbuf_animation_iter_get_pixbuf() to a new frame of the animation), + * call gdk_pixbuf_animation_iter_advance(). + * + * If you're using #GdkPixbufLoader, in addition to updating the image + * after the delay time, you should also update it whenever you + * receive the area_updated signal and + * gdk_pixbuf_animation_iter_on_currently_loading_frame() returns + * %TRUE. In this case, the frame currently being fed into the loader + * has received new data, so needs to be refreshed. The delay time for + * a frame may also be modified after an area_updated signal, for + * example if the delay time for a frame is encoded in the data after + * the frame itself. So your timeout should be reinstalled after any + * area_updated signal. + * + * A delay time of -1 is possible, indicating "infinite." * - * Return value: List of frames in the animation; this is a #GList of - * #GdkPixbufFrame structures. + * Return value: an iterator to move over the animation **/ -GList * -gdk_pixbuf_animation_get_frames (GdkPixbufAnimation *animation) +GdkPixbufAnimationIter* +gdk_pixbuf_animation_get_iter (GdkPixbufAnimation *animation, + const GTimeVal *start_time) { - g_return_val_if_fail (animation != NULL, NULL); + GTimeVal val; + + g_return_val_if_fail (GDK_IS_PIXBUF_ANIMATION (animation), NULL); + - return animation->frames; + if (start_time) + val = *start_time; + else + g_get_current_time (&val); + + return GDK_PIXBUF_ANIMATION_GET_CLASS (animation)->get_iter (animation, &val); } -/** - * gdk_pixbuf_frame_get_pixbuf: - * @frame: A pixbuf animation frame. - * - * Queries the pixbuf of an animation frame. - * - * Return value: A pixbuf. - **/ -GdkPixbuf * -gdk_pixbuf_frame_get_pixbuf (GdkPixbufFrame *frame) +GType +gdk_pixbuf_animation_iter_get_type (void) { - g_return_val_if_fail (frame != NULL, NULL); + static GType object_type = 0; - return frame->pixbuf; + if (!object_type) { + static const GTypeInfo object_info = { + sizeof (GdkPixbufAnimationIterClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) NULL, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GdkPixbufAnimationIter), + 0, /* n_preallocs */ + (GInstanceInitFunc) NULL, + }; + + object_type = g_type_register_static (G_TYPE_OBJECT, + "GdkPixbufAnimationIter", + &object_info, 0); + } + + return object_type; } /** - * gdk_pixbuf_frame_get_x_offset: - * @frame: A pixbuf animation frame. + * gdk_pixbuf_animation_iter_get_delay_time: + * @iter: an animation iterator * - * Queries the X offset of an animation frame. - * - * Return value: X offset from the top left corner of the animation. + * Gets the number of milliseconds the current pixbuf should be displayed, + * or -1 if the current pixbuf should be displayed forever. g_timeout_add() + * conveniently takes a timeout in milliseconds, so you can use a timeout + * to schedule the next update. + * + * Return value: delay time in milliseconds (thousandths of a second) **/ int -gdk_pixbuf_frame_get_x_offset (GdkPixbufFrame *frame) +gdk_pixbuf_animation_iter_get_delay_time (GdkPixbufAnimationIter *iter) { - g_return_val_if_fail (frame != NULL, -1); - - return frame->x_offset; + g_return_val_if_fail (GDK_IS_PIXBUF_ANIMATION_ITER (iter), -1); + + return GDK_PIXBUF_ANIMATION_ITER_GET_CLASS (iter)->get_delay_time (iter); } /** - * gdk_pixbuf_frame_get_y_offset: - * @frame: A pixbuf animation frame. + * gdk_pixbuf_animation_iter_get_pixbuf: + * @iter: an animation iterator * - * Queries the Y offset of an animation frame. - * - * Return value: Y offset from the top left corner of the animation. + * Gets the current pixbuf which should be displayed; the pixbuf will + * be the same size as the animation itself + * (gdk_pixbuf_animation_get_width(), + * gdk_pixbuf_animation_get_height()). This pixbuf should be displayed + * for gdk_pixbuf_animation_get_delay_time() milliseconds. The caller + * of this function does not own a reference to the returned pixbuf; + * the returned pixbuf will become invalid when the iterator advances + * to the next frame, which may happen anytime you call + * gdk_pixbuf_animation_iter_advance(). Copy the pixbuf to keep it + * (don't just add a reference), as it may get recycled as you advance + * the iterator. + * + * Return value: the pixbuf to be displayed **/ -int -gdk_pixbuf_frame_get_y_offset (GdkPixbufFrame *frame) +GdkPixbuf* +gdk_pixbuf_animation_iter_get_pixbuf (GdkPixbufAnimationIter *iter) { - g_return_val_if_fail (frame != NULL, -1); - - return frame->y_offset; + g_return_val_if_fail (GDK_IS_PIXBUF_ANIMATION_ITER (iter), NULL); + + return GDK_PIXBUF_ANIMATION_ITER_GET_CLASS (iter)->get_pixbuf (iter); } /** - * gdk_pixbuf_frame_get_delay_time: - * @frame: A pixbuf animation frame. - * - * Queries the delay time in milliseconds of an animation frame. + * gdk_pixbuf_animation_iter_on_currently_loading_frame: + * @iter: a #GdkPixbufAnimationIter + * + * Used to determine how to respond to the area_updated signal on + * #GdkPixbufLoader when loading an animation. area_updated is emitted + * for an area of the frame currently streaming in to the loader. So if + * you're on the currently loading frame, you need to redraw the screen for + * the updated area. * - * Return value: Delay time in milliseconds. + * Return value: %TRUE if the frame we're on is partially loaded, or the last frame **/ -int -gdk_pixbuf_frame_get_delay_time (GdkPixbufFrame *frame) +gboolean +gdk_pixbuf_animation_iter_on_currently_loading_frame (GdkPixbufAnimationIter *iter) { - g_return_val_if_fail (frame != NULL, -1); - - return frame->delay_time; + g_return_val_if_fail (GDK_IS_PIXBUF_ANIMATION_ITER (iter), FALSE); + + return GDK_PIXBUF_ANIMATION_ITER_GET_CLASS (iter)->on_currently_loading_frame (iter); } /** - * gdk_pixbuf_frame_get_action: - * @frame: A pixbuf animation frame. + * gdk_pixbuf_animation_iter_advance: + * @iter: a #GdkPixbufAnimationIter + * @current_time: current time + * + * Possibly advances an animation to a new frame. Chooses the frame based + * on the start time passed to gdk_pixbuf_animation_get_iter(). * - * Queries the overlay action of an animation frame. + * @current_time would normally come from g_get_current_time(), and + * must be greater than or equal to the time passed to + * gdk_pixbuf_animation_get_iter(), and must increase or remain + * unchanged each time gdk_pixbuf_animation_iter_get_pixbuf() is + * called. That is, you can't go backward in time; animations only + * play forward. + * + * As a shortcut, pass %NULL for the current time and g_get_current_time() + * will be invoked on your behalf. So you only need to explicitly pass + * @current_time if you're doing something odd like playing the animation + * at double speed. + * + * If this function returns %FALSE, there's no need to update the animation + * display, assuming the display had been rendered prior to advancing; + * if %TRUE, you need to call gdk_animation_iter_get_pixbuf() and update the + * display with the new pixbuf. + * + * Returns: %TRUE if the image may need updating * - * Return value: Overlay action for this frame. **/ -GdkPixbufFrameAction -gdk_pixbuf_frame_get_action (GdkPixbufFrame *frame) +gboolean +gdk_pixbuf_animation_iter_advance (GdkPixbufAnimationIter *iter, + const GTimeVal *current_time) { - g_return_val_if_fail (frame != NULL, GDK_PIXBUF_FRAME_RETAIN); + GTimeVal val; + + g_return_val_if_fail (GDK_IS_PIXBUF_ANIMATION_ITER (iter), FALSE); - return frame->action; + if (current_time) + val = *current_time; + else + g_get_current_time (&val); + + return GDK_PIXBUF_ANIMATION_ITER_GET_CLASS (iter)->advance (iter, &val); } -/** - * gdk_pixbuf_frame_copy: - * @src: a #GdkPixbufFrame to copy - * - * Copies a #GdkPixbufFrame. Free the result - * with gdk_pixbuf_frame_free(). - * - * Return value: a new #GdkPixbufFrame - **/ -GdkPixbufFrame* -gdk_pixbuf_frame_copy (GdkPixbufFrame *src) + + +static void gdk_pixbuf_non_anim_class_init (GdkPixbufNonAnimClass *klass); +static void gdk_pixbuf_non_anim_finalize (GObject *object); + +static gboolean gdk_pixbuf_non_anim_is_static_image (GdkPixbufAnimation *animation); +static GdkPixbuf* gdk_pixbuf_non_anim_get_static_image (GdkPixbufAnimation *animation); +static void gdk_pixbuf_non_anim_get_size (GdkPixbufAnimation *anim, + int *width, + int *height); +static GdkPixbufAnimationIter* gdk_pixbuf_non_anim_get_iter (GdkPixbufAnimation *anim, + const GTimeVal *start_time); + + + + + +static gpointer non_parent_class; + +GType +gdk_pixbuf_non_anim_get_type (void) { - GdkPixbufFrame *frame; - - frame = g_new (GdkPixbufFrame, 1); - frame->pixbuf = src->pixbuf; - g_object_ref (G_OBJECT (frame->pixbuf)); - frame->x_offset = src->x_offset; - frame->y_offset = src->y_offset; - frame->delay_time = src->delay_time; - frame->action = src->action; - - return frame; + static GType object_type = 0; + + if (!object_type) { + static const GTypeInfo object_info = { + sizeof (GdkPixbufNonAnimClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gdk_pixbuf_non_anim_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GdkPixbufNonAnim), + 0, /* n_preallocs */ + (GInstanceInitFunc) NULL, + }; + + object_type = g_type_register_static (GDK_TYPE_PIXBUF_ANIMATION, + "GdkPixbufNonAnim", + &object_info, 0); + } + + return object_type; } -/** - * gdk_pixbuf_frame_free: - * @frame: a #GdkPixbufFrame - * - * Frees a #GdkPixbufFrame. Don't do this with frames you got from - * #GdkPixbufAnimation, usually the animation owns those (it doesn't - * make a copy before returning the frame). - **/ -void -gdk_pixbuf_frame_free (GdkPixbufFrame *frame) +static void +gdk_pixbuf_non_anim_class_init (GdkPixbufNonAnimClass *klass) { - g_return_if_fail (frame != NULL); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GdkPixbufAnimationClass *anim_class = GDK_PIXBUF_ANIMATION_CLASS (klass); + + non_parent_class = g_type_class_peek_parent (klass); + + object_class->finalize = gdk_pixbuf_non_anim_finalize; + + anim_class->is_static_image = gdk_pixbuf_non_anim_is_static_image; + anim_class->get_static_image = gdk_pixbuf_non_anim_get_static_image; + anim_class->get_size = gdk_pixbuf_non_anim_get_size; + anim_class->get_iter = gdk_pixbuf_non_anim_get_iter; +} + +static void +gdk_pixbuf_non_anim_finalize (GObject *object) +{ + GdkPixbufNonAnim *non_anim = GDK_PIXBUF_NON_ANIM (object); + + if (non_anim->pixbuf) + g_object_unref (G_OBJECT (non_anim->pixbuf)); + + G_OBJECT_CLASS (non_parent_class)->finalize (object); +} + +GdkPixbufAnimation* +gdk_pixbuf_non_anim_new (GdkPixbuf *pixbuf) +{ + GdkPixbufNonAnim *non_anim; + + non_anim = g_object_new (GDK_TYPE_PIXBUF_NON_ANIM, NULL); + + non_anim->pixbuf = pixbuf; + + if (pixbuf) + g_object_ref (G_OBJECT (pixbuf)); - g_object_unref (G_OBJECT (frame->pixbuf)); - g_free (frame); + return GDK_PIXBUF_ANIMATION (non_anim); } +static gboolean +gdk_pixbuf_non_anim_is_static_image (GdkPixbufAnimation *animation) +{ + + return TRUE; +} + +static GdkPixbuf* +gdk_pixbuf_non_anim_get_static_image (GdkPixbufAnimation *animation) +{ + GdkPixbufNonAnim *non_anim; + + non_anim = GDK_PIXBUF_NON_ANIM (animation); + + return non_anim->pixbuf; +} + +static void +gdk_pixbuf_non_anim_get_size (GdkPixbufAnimation *anim, + int *width, + int *height) +{ + GdkPixbufNonAnim *non_anim; + + non_anim = GDK_PIXBUF_NON_ANIM (anim); + + if (width) + *width = gdk_pixbuf_get_width (non_anim->pixbuf); + + if (height) + *height = gdk_pixbuf_get_height (non_anim->pixbuf); +} + + +static GdkPixbufAnimationIter* +gdk_pixbuf_non_anim_get_iter (GdkPixbufAnimation *anim, + const GTimeVal *start_time) +{ + GdkPixbufNonAnimIter *iter; + + iter = g_object_new (GDK_TYPE_PIXBUF_NON_ANIM_ITER, NULL); + + iter->non_anim = GDK_PIXBUF_NON_ANIM (anim); + + g_object_ref (G_OBJECT (iter->non_anim)); + + return GDK_PIXBUF_ANIMATION_ITER (iter); +} + + + +static void gdk_pixbuf_non_anim_iter_class_init (GdkPixbufNonAnimIterClass *klass); +static void gdk_pixbuf_non_anim_iter_finalize (GObject *object); +static int gdk_pixbuf_non_anim_iter_get_delay_time (GdkPixbufAnimationIter *iter); +static GdkPixbuf* gdk_pixbuf_non_anim_iter_get_pixbuf (GdkPixbufAnimationIter *iter); +static gboolean gdk_pixbuf_non_anim_iter_on_currently_loading_frame (GdkPixbufAnimationIter *iter); +static gboolean gdk_pixbuf_non_anim_iter_advance (GdkPixbufAnimationIter *iter, + const GTimeVal *current_time); + + + + + +static gpointer non_iter_parent_class; + GType -gdk_pixbuf_frame_get_type (void) +gdk_pixbuf_non_anim_iter_get_type (void) +{ + static GType object_type = 0; + + if (!object_type) { + static const GTypeInfo object_info = { + sizeof (GdkPixbufNonAnimIterClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gdk_pixbuf_non_anim_iter_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GdkPixbufNonAnimIter), + 0, /* n_preallocs */ + (GInstanceInitFunc) NULL, + }; + + object_type = g_type_register_static (GDK_TYPE_PIXBUF_ANIMATION_ITER, + "GdkPixbufNonAnimIter", + &object_info, 0); + } + + return object_type; +} + +static void +gdk_pixbuf_non_anim_iter_class_init (GdkPixbufNonAnimIterClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GdkPixbufAnimationIterClass *anim_iter_class = + GDK_PIXBUF_ANIMATION_ITER_CLASS (klass); + + non_iter_parent_class = g_type_class_peek_parent (klass); + + object_class->finalize = gdk_pixbuf_non_anim_iter_finalize; + + anim_iter_class->get_delay_time = gdk_pixbuf_non_anim_iter_get_delay_time; + anim_iter_class->get_pixbuf = gdk_pixbuf_non_anim_iter_get_pixbuf; + anim_iter_class->on_currently_loading_frame = gdk_pixbuf_non_anim_iter_on_currently_loading_frame; + anim_iter_class->advance = gdk_pixbuf_non_anim_iter_advance; +} + +static void +gdk_pixbuf_non_anim_iter_finalize (GObject *object) { - static GType our_type = 0; + GdkPixbufNonAnimIter *iter = GDK_PIXBUF_NON_ANIM_ITER (object); - if (our_type == 0) - our_type = g_boxed_type_register_static ("GdkPixbufFrame", - NULL, - gdk_pixbuf_frame_copy, - gdk_pixbuf_frame_free, - FALSE); + g_object_unref (G_OBJECT (iter->non_anim)); + + G_OBJECT_CLASS (non_iter_parent_class)->finalize (object); +} + +static int +gdk_pixbuf_non_anim_iter_get_delay_time (GdkPixbufAnimationIter *iter) +{ + return -1; /* show only frame forever */ +} - return our_type; +static GdkPixbuf* +gdk_pixbuf_non_anim_iter_get_pixbuf (GdkPixbufAnimationIter *iter) +{ + return GDK_PIXBUF_NON_ANIM_ITER (iter)->non_anim->pixbuf; } + + +static gboolean +gdk_pixbuf_non_anim_iter_on_currently_loading_frame (GdkPixbufAnimationIter *iter) +{ + return TRUE; +} + +static gboolean +gdk_pixbuf_non_anim_iter_advance (GdkPixbufAnimationIter *iter, + const GTimeVal *current_time) +{ + + /* Advancing never requires a refresh */ + return FALSE; +} + |