diff options
author | Matthias Clasen <matthiasc@src.gnome.org> | 2002-09-06 21:14:15 +0000 |
---|---|---|
committer | Matthias Clasen <matthiasc@src.gnome.org> | 2002-09-06 21:14:15 +0000 |
commit | 8a1a091f87b279ad36d6ec09f49d686fe3341807 (patch) | |
tree | c3fd8dd6807003a62524d289a1f2cb9b43811eab /gdk-pixbuf/io-ani-animation.c | |
parent | ab971600673024805d9906b791a1a54043a12855 (diff) | |
download | gtk+-8a1a091f87b279ad36d6ec09f49d686fe3341807.tar.gz |
New loader, for .ANI animations.
* io-ani.c, io-ani-animation.h, io-ani-animation.c,
pixbufloader_ani.def, Makefile.am, gdk-pixbuf-io.c: New loader,
for .ANI animations.
Diffstat (limited to 'gdk-pixbuf/io-ani-animation.c')
-rw-r--r-- | gdk-pixbuf/io-ani-animation.c | 347 |
1 files changed, 347 insertions, 0 deletions
diff --git a/gdk-pixbuf/io-ani-animation.c b/gdk-pixbuf/io-ani-animation.c new file mode 100644 index 0000000000..07e70368a5 --- /dev/null +++ b/gdk-pixbuf/io-ani-animation.c @@ -0,0 +1,347 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ +/* GdkPixbuf library - ani support + * + * Copyright (C) 2002 The Free Software Foundation + * + * Author: Matthias Clasen <maclas@gmx.de> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <config.h> +#include <errno.h> +#include "gdk-pixbuf-io.h" +#include "gdk-pixbuf-private.h" +#include "io-ani-animation.h" + +static void gdk_pixbuf_ani_anim_class_init (GdkPixbufAniAnimClass *klass); +static void gdk_pixbuf_ani_anim_finalize (GObject *object); + +static gboolean gdk_pixbuf_ani_anim_is_static_image (GdkPixbufAnimation *animation); +static GdkPixbuf* gdk_pixbuf_ani_anim_get_static_image (GdkPixbufAnimation *animation); +static void gdk_pixbuf_ani_anim_get_size (GdkPixbufAnimation *anim, + int *width, + int *height); +static GdkPixbufAnimationIter* gdk_pixbuf_ani_anim_get_iter (GdkPixbufAnimation *anim, + const GTimeVal *start_time); + + + + +static gpointer parent_class; + +GType +gdk_pixbuf_ani_anim_get_type (void) +{ + static GType object_type = 0; + + if (!object_type) { + static const GTypeInfo object_info = { + sizeof (GdkPixbufAniAnimClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gdk_pixbuf_ani_anim_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GdkPixbufAniAnim), + 0, /* n_preallocs */ + (GInstanceInitFunc) NULL, + }; + + object_type = g_type_register_static (GDK_TYPE_PIXBUF_ANIMATION, + "GdkPixbufAniAnim", + &object_info, 0); + } + + return object_type; +} + +static void +gdk_pixbuf_ani_anim_class_init (GdkPixbufAniAnimClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GdkPixbufAnimationClass *anim_class = GDK_PIXBUF_ANIMATION_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + object_class->finalize = gdk_pixbuf_ani_anim_finalize; + + anim_class->is_static_image = gdk_pixbuf_ani_anim_is_static_image; + anim_class->get_static_image = gdk_pixbuf_ani_anim_get_static_image; + anim_class->get_size = gdk_pixbuf_ani_anim_get_size; + anim_class->get_iter = gdk_pixbuf_ani_anim_get_iter; +} + +static void +gdk_pixbuf_ani_anim_finalize (GObject *object) +{ + GdkPixbufAniAnim *ani_anim = GDK_PIXBUF_ANI_ANIM (object); + gint i; + + for (i = 0; i < ani_anim->n_pixbufs; i++) { + if (ani_anim->pixbufs[i]) + g_object_unref (ani_anim->pixbufs[i]); + } + g_free (ani_anim->pixbufs); + g_free (ani_anim->sequence); + g_free (ani_anim->delay); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static gboolean +gdk_pixbuf_ani_anim_is_static_image (GdkPixbufAnimation *animation) +{ + GdkPixbufAniAnim *ani_anim; + + ani_anim = GDK_PIXBUF_ANI_ANIM (animation); + + return ani_anim->n_frames == 1; +} + +static GdkPixbuf* +gdk_pixbuf_ani_anim_get_static_image (GdkPixbufAnimation *animation) +{ + GdkPixbufAniAnim *ani_anim; + + ani_anim = GDK_PIXBUF_ANI_ANIM (animation); + + if (ani_anim->pixbufs == NULL) + return NULL; + else + return ani_anim->pixbufs[0]; +} + +static void +gdk_pixbuf_ani_anim_get_size (GdkPixbufAnimation *anim, + int *width, + int *height) +{ + GdkPixbufAniAnim *ani_anim; + + ani_anim = GDK_PIXBUF_ANI_ANIM (anim); + + if (width) + *width = ani_anim->width; + + if (height) + *height = ani_anim->height; +} + + +static void +iter_restart (GdkPixbufAniAnimIter *iter) +{ + iter->current_frame = 0; + iter->position = 0; + iter->elapsed = 0; +} + +static GdkPixbufAnimationIter* +gdk_pixbuf_ani_anim_get_iter (GdkPixbufAnimation *anim, + const GTimeVal *start_time) +{ + GdkPixbufAniAnimIter *iter; + + iter = g_object_new (GDK_TYPE_PIXBUF_ANI_ANIM_ITER, NULL); + + iter->ani_anim = GDK_PIXBUF_ANI_ANIM (anim); + + g_object_ref (iter->ani_anim); + + iter_restart (iter); + + iter->start_time = *start_time; + iter->current_time = *start_time; + + return GDK_PIXBUF_ANIMATION_ITER (iter); +} + + + +static void gdk_pixbuf_ani_anim_iter_class_init (GdkPixbufAniAnimIterClass *klass); +static void gdk_pixbuf_ani_anim_iter_finalize (GObject *object); + +static int gdk_pixbuf_ani_anim_iter_get_delay_time (GdkPixbufAnimationIter *iter); +static GdkPixbuf* gdk_pixbuf_ani_anim_iter_get_pixbuf (GdkPixbufAnimationIter *iter); +static gboolean gdk_pixbuf_ani_anim_iter_on_currently_loading_frame (GdkPixbufAnimationIter *iter); +static gboolean gdk_pixbuf_ani_anim_iter_advance (GdkPixbufAnimationIter *iter, + const GTimeVal *current_time); + + + +static gpointer iter_parent_class; + +GType +gdk_pixbuf_ani_anim_iter_get_type (void) +{ + static GType object_type = 0; + + if (!object_type) { + static const GTypeInfo object_info = { + sizeof (GdkPixbufAniAnimIterClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gdk_pixbuf_ani_anim_iter_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GdkPixbufAniAnimIter), + 0, /* n_preallocs */ + (GInstanceInitFunc) NULL, + }; + + object_type = g_type_register_static (GDK_TYPE_PIXBUF_ANIMATION_ITER, + "GdkPixbufAniAnimIter", + &object_info, 0); + } + + return object_type; +} + +static void +gdk_pixbuf_ani_anim_iter_class_init (GdkPixbufAniAnimIterClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GdkPixbufAnimationIterClass *anim_iter_class = + GDK_PIXBUF_ANIMATION_ITER_CLASS (klass); + + iter_parent_class = g_type_class_peek_parent (klass); + + object_class->finalize = gdk_pixbuf_ani_anim_iter_finalize; + + anim_iter_class->get_delay_time = gdk_pixbuf_ani_anim_iter_get_delay_time; + anim_iter_class->get_pixbuf = gdk_pixbuf_ani_anim_iter_get_pixbuf; + anim_iter_class->on_currently_loading_frame = gdk_pixbuf_ani_anim_iter_on_currently_loading_frame; + anim_iter_class->advance = gdk_pixbuf_ani_anim_iter_advance; +} + +static void +gdk_pixbuf_ani_anim_iter_finalize (GObject *object) +{ + GdkPixbufAniAnimIter *iter = GDK_PIXBUF_ANI_ANIM_ITER (object); + + g_object_unref (iter->ani_anim); + + G_OBJECT_CLASS (iter_parent_class)->finalize (object); +} + +static gboolean +gdk_pixbuf_ani_anim_iter_advance (GdkPixbufAnimationIter *anim_iter, + const GTimeVal *current_time) +{ + GdkPixbufAniAnimIter *iter; + gint elapsed; + gint tmp; + gint old; + + iter = GDK_PIXBUF_ANI_ANIM_ITER (anim_iter); + + iter->current_time = *current_time; + + /* We use milliseconds for all times */ + elapsed = + (((iter->current_time.tv_sec - iter->start_time.tv_sec) * G_USEC_PER_SEC + + iter->current_time.tv_usec - iter->start_time.tv_usec)) / 1000; + + if (elapsed < 0) { + /* Try to compensate; probably the system clock + * was set backwards + */ + iter->start_time = iter->current_time; + elapsed = 0; + } + + g_assert (iter->ani_anim->total_time > 0); + + /* See how many times we've already played the full animation, + * and subtract time for that. + */ + elapsed = elapsed % iter->ani_anim->total_time; + + iter->position = elapsed; + + /* Now move to the proper frame */ + + iter->elapsed = 0; + for (tmp = 0; tmp < iter->ani_anim->n_frames; tmp++) { + if (iter->position >= iter->elapsed && + iter->position < (iter->elapsed + iter->ani_anim->delay[tmp])) + break; + iter->elapsed += iter->ani_anim->delay[tmp]; + } + + old = iter->current_frame; + + iter->current_frame = tmp; + + return iter->current_frame != old; +} + +int +gdk_pixbuf_ani_anim_iter_get_delay_time (GdkPixbufAnimationIter *anim_iter) +{ + GdkPixbufAniAnimIter *iter; + + iter = GDK_PIXBUF_ANI_ANIM_ITER (anim_iter); + + return iter->ani_anim->delay[iter->current_frame] - (iter->position - iter->elapsed); +} + +GdkPixbuf* +gdk_pixbuf_ani_anim_iter_get_pixbuf (GdkPixbufAnimationIter *anim_iter) +{ + GdkPixbufAniAnimIter *iter; + gint frame; + + iter = GDK_PIXBUF_ANI_ANIM_ITER (anim_iter); + + frame = iter->ani_anim->sequence[iter->current_frame]; + + /* this is necessary if the animation is displayed while loading */ + while (frame > 0 && !iter->ani_anim->pixbufs[frame]) + frame--; + + return iter->ani_anim->pixbufs[frame]; +} + +static gboolean +gdk_pixbuf_ani_anim_iter_on_currently_loading_frame (GdkPixbufAnimationIter *anim_iter) +{ + GdkPixbufAniAnimIter *iter; + gint frame; + + iter = GDK_PIXBUF_ANI_ANIM_ITER (anim_iter); + + if (iter->current_frame >= iter->ani_anim->n_frames - 1) + return TRUE; + + frame = iter->ani_anim->sequence[iter->current_frame + 1]; + + if (!iter->ani_anim->pixbufs[frame]) + return TRUE; + + return FALSE; +} + + + + + + + + + + |