summaryrefslogtreecommitdiff
path: root/gdk-pixbuf/io-gif.c
diff options
context:
space:
mode:
authorMatthias Clasen <matthias@localhost.localdomain>2003-06-22 18:08:33 +0000
committerMatthias Clasen <matthiasc@src.gnome.org>2003-06-22 18:08:33 +0000
commita378391aaa4b7e422a96ae42477f080cc90989a8 (patch)
tree03b0530fac034f3fd0e504013e948f4aeaee752f /gdk-pixbuf/io-gif.c
parent1a3ba4fde060cc90cac32a6affce028cfdd672f9 (diff)
downloadgdk-pixbuf-a378391aaa4b7e422a96ae42477f080cc90989a8.tar.gz
Reset block_count to 0 for all application extensions, otherwise the data
2003-06-22 Matthias Clasen <matthias@localhost.localdomain> * io-gif.c (gif_get_extension): Reset block_count to 0 for all application extensions, otherwise the data blocks of unknown extensions are not propertly skipped. Second half of the fix for #106962, handle frames extending beyond the logical screen: * io-gif.c (clip_frame): New helper function to clip a rectangle to the logical screen size of the gif. (maybe_update): New helper function to call update_func only if the rectangle is not completely off-bounds. (gif_get_lzw): Read frames extending outside the logical screen size, but be careful clip to the logical screen size when operating on the composite pixbuf and when calling update_func. (gif_init): Set the animation size to the logical screen size. (gif_get_frame_info): Don't refuse to load images with frames extending beyond the logical screen size. * io-gif-animation.c (gdk_pixbuf_gif_anim_frame_composite): Be careful to clip all rectangles to the logical screen size, also handle the fact that frames may be completely off-bounds.
Diffstat (limited to 'gdk-pixbuf/io-gif.c')
-rw-r--r--gdk-pixbuf/io-gif.c149
1 files changed, 80 insertions, 69 deletions
diff --git a/gdk-pixbuf/io-gif.c b/gdk-pixbuf/io-gif.c
index e5e7657ec..c37251eb4 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