From 817ad6d3f81db85ce8be1f9ec5453dc992904b6d Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 20 Oct 2002 22:16:58 +0000 Subject: [PATCH] Support the Netscape application extension for gif animations (#95060): --- gdk-pixbuf/ChangeLog | 13 +++++++++++ gdk-pixbuf/io-gif-animation.c | 12 +++++++--- gdk-pixbuf/io-gif-animation.h | 2 ++ gdk-pixbuf/io-gif.c | 43 +++++++++++++++++++++++++++++++---- 4 files changed, 62 insertions(+), 8 deletions(-) diff --git a/gdk-pixbuf/ChangeLog b/gdk-pixbuf/ChangeLog index 6eb6be3816..4cdb33ab4f 100644 --- a/gdk-pixbuf/ChangeLog +++ b/gdk-pixbuf/ChangeLog @@ -1,3 +1,16 @@ +2002-10-21 Matthias Clasen + + Support the Netscape application extension for gif animations + (#95060): + + * io-gif-animation.h: + * io-gif-animation.c (gdk_pixbuf_gif_anim_iter_advance): + Add loop count to GdkPixbufGifAnim and use it in the advance + method of GdkPixbufGifAnimIter. + + * io-gif.c (gif_get_extension): Parse Netscape application + extension block and set the animation loop count. + 2002-10-11 Matthias Clasen * gdk-pixbuf-loader.c (gdk_pixbuf_loader_get_format): Remove diff --git a/gdk-pixbuf/io-gif-animation.c b/gdk-pixbuf/io-gif-animation.c index b797f04812..2b4fe90aef 100644 --- a/gdk-pixbuf/io-gif-animation.c +++ b/gdk-pixbuf/io-gif-animation.c @@ -260,6 +260,7 @@ gdk_pixbuf_gif_anim_iter_advance (GdkPixbufAnimationIter *anim_iter, { GdkPixbufGifAnimIter *iter; gint elapsed; + gint loop; GList *tmp; GList *old; @@ -285,12 +286,17 @@ gdk_pixbuf_gif_anim_iter_advance (GdkPixbufAnimationIter *anim_iter, /* See how many times we've already played the full animation, * and subtract time for that. */ + + loop = elapsed / iter->gif_anim->total_time; elapsed = elapsed % iter->gif_anim->total_time; iter->position = elapsed; - + /* Now move to the proper frame */ - tmp = iter->gif_anim->frames; + if (iter->gif_anim->loop == 0 || loop < iter->gif_anim->loop) + tmp = iter->gif_anim->frames; + else + tmp = NULL; while (tmp != NULL) { GdkPixbufFrame *frame = tmp->data; @@ -525,7 +531,7 @@ gdk_pixbuf_gif_anim_iter_get_pixbuf (GdkPixbufAnimationIter *anim_iter) iter = GDK_PIXBUF_GIF_ANIM_ITER (anim_iter); - frame = iter->current_frame ? iter->current_frame->data : NULL; + frame = iter->current_frame ? iter->current_frame->data : g_list_last (iter->gif_anim->frames)->data; #if 0 if (FALSE && frame) diff --git a/gdk-pixbuf/io-gif-animation.h b/gdk-pixbuf/io-gif-animation.h index 0d61114381..00172cc474 100644 --- a/gdk-pixbuf/io-gif-animation.h +++ b/gdk-pixbuf/io-gif-animation.h @@ -76,6 +76,8 @@ struct _GdkPixbufGifAnim { guchar bg_red; guchar bg_green; guchar bg_blue; + + int loop; }; struct _GdkPixbufGifAnimClass { diff --git a/gdk-pixbuf/io-gif.c b/gdk-pixbuf/io-gif.c index b91e78af22..7342c3ef9c 100644 --- a/gdk-pixbuf/io-gif.c +++ b/gdk-pixbuf/io-gif.c @@ -83,7 +83,7 @@ enum { GIF_GET_COLORMAP, GIF_GET_NEXT_STEP, GIF_GET_FRAME_INFO, - GIF_GET_EXTENTION, + GIF_GET_EXTENSION, GIF_GET_COLORMAP2, GIF_PREPARE_LZW, GIF_LZW_FILL_BUFFER, @@ -149,6 +149,7 @@ struct _GifContext /* extension context */ guchar extension_label; guchar extension_flag; + gboolean in_loop_extension; /* get block context */ guchar block_count; @@ -353,7 +354,7 @@ get_data_block (GifContext *context, static void gif_set_get_extension (GifContext *context) { - context->state = GIF_GET_EXTENTION; + context->state = GIF_GET_EXTENSION; context->extension_flag = TRUE; context->extension_label = 0; context->block_count = 0; @@ -376,8 +377,8 @@ gif_get_extension (GifContext *context) } switch (context->extension_label) { - case 0xf9: /* Graphic Control Extension */ - retval = get_data_block (context, (unsigned char *) context->block_buf, NULL); + case 0xf9: /* Graphic Control Extension */ + retval = get_data_block (context, (unsigned char *) context->block_buf, NULL); if (retval != 0) return retval; @@ -399,6 +400,36 @@ gif_get_extension (GifContext *context) /* Now we've successfully loaded this one, we continue on our way */ context->block_count = 0; context->extension_flag = FALSE; + break; + case 0xff: /* application extension */ + if (!context->in_loop_extension) { + retval = get_data_block (context, (unsigned char *) context->block_buf, NULL); + if (retval != 0) + return retval; + if (!strncmp (context->block_buf, "NETSCAPE2.0", 11) || + !strncmp (context->block_buf, "ANIMEXTS1.0", 11)) { + context->in_loop_extension = TRUE; + context->block_count = 0; + } + } + if (context->in_loop_extension) { + do { + retval = get_data_block (context, (unsigned char *) context->block_buf, &empty_block); + if (retval != 0) + return retval; + if (context->block_buf[0] == 0x01) { + context->animation->loop = context->block_buf[1] + (context->block_buf[2] << 8); + if (context->animation->loop != 0) + context->animation->loop++; + } + context->block_count = 0; + } + while (!empty_block); + context->in_loop_extension = FALSE; + context->extension_flag = FALSE; + return 0; + } + break; default: /* Unhandled extension */ break; @@ -1280,7 +1311,7 @@ gif_main_loop (GifContext *context) retval = gif_get_frame_info (context); break; - case GIF_GET_EXTENTION: + case GIF_GET_EXTENSION: LOG("get_extension\n"); retval = gif_get_extension (context); if (retval == 0) @@ -1349,6 +1380,8 @@ new_context (void) context->gif89.delay_time = -1; context->gif89.input_flag = -1; context->gif89.disposal = -1; + context->animation->loop = 1; + context->in_loop_extension = FALSE; return context; }