diff options
Diffstat (limited to 'gdk-pixbuf/io-gif.c')
-rw-r--r-- | gdk-pixbuf/io-gif.c | 149 |
1 files changed, 80 insertions, 69 deletions
diff --git a/gdk-pixbuf/io-gif.c b/gdk-pixbuf/io-gif.c index e5e7657ec9..c37251eb4b 100644 --- a/gdk-pixbuf/io-gif.c +++ b/gdk-pixbuf/io-gif.c @@ -410,8 +410,8 @@ gif_get_extension (GifContext *context) if (!strncmp (context->block_buf, "NETSCAPE2.0", 11) || !strncmp (context->block_buf, "ANIMEXTS1.0", 11)) { context->in_loop_extension = TRUE; - context->block_count = 0; } + context->block_count = 0; } if (context->in_loop_extension) { do { @@ -777,6 +777,49 @@ set_need_recomposite (gpointer data, gpointer user_data) frame->need_recomposite = TRUE; } +/* Clips a rectancle to the base dimensions. Returns TRUE if the clipped rectangle is non-empty. */ +static gboolean +clip_frame (GifContext *context, + gint *x, + gint *y, + gint *width, + gint *height) +{ + gint orig_x, orig_y; + + orig_x = *x; + orig_y = *y; + *x = MAX (0, *x); + *y = MAX (0, *y); + *width = MIN (context->width, orig_x + *width) - *x; + *height = MIN (context->height, orig_y + *height) - *y; + + if (*width > 0 && *height > 0) + return TRUE; + + /* The frame is completely off-bounds */ + + *x = 0; + *y = 0; + *width = 0; + *height = 0; + + return FALSE; +} + +/* Call update_func on the given rectangle, unless it is completely off-bounds */ +static void +maybe_update (GifContext *context, + gint x, + gint y, + gint width, + gint height) +{ + if (clip_frame (context, &x, &y, &width, &height)) + (*context->update_func) (context->frame->pixbuf, + x, y, width, height, + context->user_data); +} static int gif_get_lzw (GifContext *context) @@ -863,25 +906,8 @@ gif_get_lzw (GifContext *context) context->frame->bg_transparent = (context->gif89.transparent == context->background_index); - { - /* Update animation size */ - int w, h; - - context->animation->n_frames ++; - context->animation->frames = g_list_append (context->animation->frames, context->frame); - - w = context->frame->x_offset + - gdk_pixbuf_get_width (context->frame->pixbuf); - h = context->frame->y_offset + - gdk_pixbuf_get_height (context->frame->pixbuf); - if (w > context->animation->width || h > context->animation->height) { - g_list_foreach (context->animation->frames, set_need_recomposite, NULL); - } - if (w > context->animation->width) - context->animation->width = w; - if (h > context->animation->height) - context->animation->height = h; - } + context->animation->n_frames ++; + context->animation->frames = g_list_append (context->animation->frames, context->frame); /* Only call prepare_func for the first frame */ if (context->animation->frames->next == NULL) { @@ -893,6 +919,7 @@ gif_get_lzw (GifContext *context) /* Otherwise init frame with last frame */ GList *link; GdkPixbufFrame *prev_frame; + gint x, y, w, h; link = g_list_find (context->animation->frames, context->frame); @@ -900,13 +927,15 @@ gif_get_lzw (GifContext *context) gdk_pixbuf_gif_anim_frame_composite (context->animation, prev_frame); - gdk_pixbuf_copy_area (prev_frame->composited, - context->frame->x_offset, - context->frame->y_offset, - gdk_pixbuf_get_width (context->frame->pixbuf), - gdk_pixbuf_get_height (context->frame->pixbuf), - context->frame->pixbuf, - 0, 0); + x = context->frame->x_offset; + y = context->frame->y_offset; + w = gdk_pixbuf_get_width (context->frame->pixbuf); + h = gdk_pixbuf_get_height (context->frame->pixbuf); + if (clip_frame (context, &x, &y, &w, &h)) + gdk_pixbuf_copy_area (prev_frame->composited, + x, y, w, h, + context->frame->pixbuf, + 0, 0); } } @@ -1005,37 +1034,29 @@ gif_get_lzw (GifContext *context) if (bound_flag && context->update_func) { if (lower_bound <= upper_bound && first_pass == context->draw_pass) { - (* context->update_func) - (context->frame->pixbuf, - context->frame->x_offset, - context->frame->y_offset + lower_bound, - gdk_pixbuf_get_width (context->frame->pixbuf), - upper_bound - lower_bound, - context->user_data); + maybe_update (context, + context->frame->x_offset, + context->frame->y_offset + lower_bound, + gdk_pixbuf_get_width (context->frame->pixbuf), + upper_bound - lower_bound); } else { if (lower_bound <= upper_bound) { - (* context->update_func) - (context->frame->pixbuf, - context->frame->x_offset, - context->frame->y_offset, - gdk_pixbuf_get_width (context->frame->pixbuf), - gdk_pixbuf_get_height (context->frame->pixbuf), - context->user_data); + maybe_update (context, + context->frame->x_offset, + context->frame->y_offset, + gdk_pixbuf_get_width (context->frame->pixbuf), + gdk_pixbuf_get_height (context->frame->pixbuf)); } else { - (* context->update_func) - (context->frame->pixbuf, - context->frame->x_offset, - context->frame->y_offset, - gdk_pixbuf_get_width (context->frame->pixbuf), - upper_bound, - context->user_data); - (* context->update_func) - (context->frame->pixbuf, - context->frame->x_offset, - context->frame->y_offset + lower_bound, - gdk_pixbuf_get_width (context->frame->pixbuf), - gdk_pixbuf_get_height (context->frame->pixbuf) - lower_bound, - context->user_data); + maybe_update (context, + context->frame->x_offset, + context->frame->y_offset, + gdk_pixbuf_get_width (context->frame->pixbuf), + upper_bound); + maybe_update (context, + context->frame->x_offset, + context->frame->y_offset + lower_bound, + gdk_pixbuf_get_width (context->frame->pixbuf), + gdk_pixbuf_get_height (context->frame->pixbuf) - lower_bound); } } } @@ -1164,7 +1185,10 @@ gif_init (GifContext *context) context->animation->bg_red = 0; context->animation->bg_green = 0; context->animation->bg_blue = 0; - + + context->animation->width = context->width; + context->animation->height = context->height; + if (context->has_global_cmap) { gif_set_get_colormap (context); } else { @@ -1200,19 +1224,6 @@ gif_get_frame_info (GifContext *context) context->x_offset = LM_to_uint (buf[0], buf[1]); context->y_offset = LM_to_uint (buf[2], buf[3]); - if (((context->frame_height + context->y_offset) > context->height) || - ((context->frame_len + context->x_offset) > context->width)) { - /* All frames must fit in the image bounds */ - context->state = GIF_DONE; - - g_set_error (context->error, - GDK_PIXBUF_ERROR, - GDK_PIXBUF_ERROR_CORRUPT_IMAGE, - _("GIF image contained a frame appearing outside the image bounds.")); - - return -2; - } - if (context->animation->frames == NULL && context->gif89.disposal == 3) { /* First frame can't have "revert to previous" as its |