diff options
author | Richard Wilson <rjw@netsurf-browser.org> | 2004-04-17 20:50:33 +0000 |
---|---|---|
committer | Richard Wilson <rjw@netsurf-browser.org> | 2004-04-17 20:50:33 +0000 |
commit | dc510627d9044edb7b1f10cd7b1ac6fb491924b1 (patch) | |
tree | d4293716c7980dbe35a11b72ac7b7fe89d51d459 | |
parent | 6f5dd247adc24da5000672d71cf5ad4abd9fe84c (diff) | |
download | netsurf-dc510627d9044edb7b1f10cd7b1ac6fb491924b1.tar.gz netsurf-dc510627d9044edb7b1f10cd7b1ac6fb491924b1.tar.bz2 |
[project @ 2004-04-17 20:50:33 by rjw]
Fixed animation disposal handling.
svn path=/import/netsurf/; revision=790
-rw-r--r-- | riscos/gifread.c | 178 | ||||
-rw-r--r-- | riscos/gifread.h | 7 |
2 files changed, 94 insertions, 91 deletions
diff --git a/riscos/gifread.c b/riscos/gifread.c index 77406afd3..5d56245c7 100644 --- a/riscos/gifread.c +++ b/riscos/gifread.c @@ -84,6 +84,9 @@ static int curbit, lastbit, get_done, last_byte; static int return_clear; static int zero_data_block = FALSE; +/* Whether to clear the decoded image rather than plot +*/ +static int clear_image = FALSE; /* Initialises any workspace held by the animation and attempts to decode @@ -153,12 +156,12 @@ int gif_initialise(struct gif_animation *gif) { */ gif->width = 0; // Can't trust the supplied value gif->height = 0; // Can't trust the supplied value -// gif->width = (gif_data[0] | (gif_data[1] << 8)); -// gif->height = (gif_data[2] | (gif_data[3] << 8)); gif->global_colours = (gif_data[4] & 0x80); gif->colour_table_size = (2 << (gif_data[4] & 0x07)); gif->background_colour = gif_data[5]; gif->aspect_ratio = gif_data[6]; + gif->dirty_frame = -1; + gif->dirty_plot = 0; gif_data += 7; /* Allocate some data irrespective of whether we've got any colour tables. We @@ -513,21 +516,34 @@ int gif_decode_frame(struct gif_animation *gif, unsigned int frame) { unsigned int *frame_data = 0; // Set to 0 for no warnings unsigned int *frame_scanline; unsigned int extension_size; + unsigned int background_action; int transparency_index = -1; - unsigned int transparent_colour = 0; // Set to 0 for no warnings unsigned int save_buffer_position; - unsigned int frame_data_size; unsigned int return_value = 0; unsigned int x, y, decode_y; + unsigned int block_size; int colour; - unsigned int more_images; /* Ensure we have a frame to decode */ if (frame > gif->frame_count_partial) return GIF_INSUFFICIENT_DATA; - if (frame == gif->decoded_frame) return 0; - + if ((!clear_image) && (frame == gif->decoded_frame)) return 0; + + /* If the previous frame was dirty, remove it + */ + if (!clear_image) { + if (gif->decoded_frame == gif->dirty_frame) { + clear_image = TRUE; + if (frame != 0) gif_decode_frame(gif, gif->dirty_frame); + clear_image = FALSE; + gif->dirty_plot = 1; + } else { + gif->dirty_plot = 0; + } + gif->dirty_frame = -1; + } + /* Get the start of our frame data and the end of the GIF data */ gif_data = gif->gif_data + gif->frame_pointers[frame]; @@ -543,10 +559,12 @@ int gif_decode_frame(struct gif_animation *gif, unsigned int frame) { produce errors. */ frame_data = (unsigned int*)((char *)gif->frame_image + sizeof(osspriteop_header)); - if ((frame == 0) || (gif->decoded_frame == 0xffffffff)) { - memset((char*)frame_data, 0x00, gif->width * gif->height * sizeof(int)); + if (!clear_image) { + if ((frame == 0) || (gif->decoded_frame == 0xffffffff)) { + memset((char*)frame_data, 0x00, gif->width * gif->height * sizeof(int)); + } + gif->decoded_frame = frame; } - gif->decoded_frame = frame; /* Save the buffer position */ @@ -555,7 +573,7 @@ int gif_decode_frame(struct gif_animation *gif, unsigned int frame) { /* We've got to do this more than one time if we've got multiple images */ - gif->background_action = 0; + background_action = 0; more_images = 1; while (more_images != 0) { @@ -575,12 +593,13 @@ int gif_decode_frame(struct gif_animation *gif, unsigned int frame) { /* Check we've enough data for the extension then header */ if ((gif_end - gif_data) < (int)(extension_size + 13)) return GIF_INSUFFICIENT_FRAME_DATA; + /* Graphic control extension - store the frame delay. */ if (gif_data[1] == 0xf9) { flags = gif_data[3]; if (flags & 0x01) transparency_index = gif_data[6]; - gif->background_action = ((flags & 0x1c) >> 2); + background_action = ((flags & 0x1c) >> 2); more_images = ((gif_data[4] | (gif_data[5] << 8)) == 0); } /* Move to the first sub-block @@ -603,7 +622,6 @@ int gif_decode_frame(struct gif_animation *gif, unsigned int frame) { offset_y = gif_data[3] | (gif_data[4] << 8); width = gif_data[5] | (gif_data[6] << 8); height = gif_data[7] | (gif_data[8] << 8); -// LOG(("Decoding %ix%i at offset (%i,%i)", width, height, offset_x, offset_y)); /* Boundary checking - shouldn't ever happen except unless the data has been modified since initialisation. @@ -623,76 +641,54 @@ int gif_decode_frame(struct gif_animation *gif, unsigned int frame) { gif_data += 10; gif_bytes = (int)(gif_end - gif_data); - /* Initialise our sprite to be totally transparent if we should - */ -// gif->frame_offset_x = offset_x; -// gif->frame_offset_y = offset_y; -// gif->frame_image->width = width; -// gif->frame_image->height = height; - /* Set up the colour table */ if (flags & 0x80) { -// LOG(("Found local colour table")); if (gif_bytes < (int)(3 * colour_table_size)) return GIF_INSUFFICIENT_FRAME_DATA; colour_table = gif->local_colour_table; - for (index = 0; index < colour_table_size; index++) { - colour_table[index] = gif_data[0] | (gif_data[1] << 8) | - (gif_data[2] << 16) | 0xff000000; - gif_data += 3; + if (!clear_image) { + for (index = 0; index < colour_table_size; index++) { + colour_table[index] = gif_data[0] | (gif_data[1] << 8) | + (gif_data[2] << 16) | 0xff000000; + gif_data += 3; + } + } else { + gif_data += 3 * colour_table_size; } gif_bytes = (int)(gif_end - gif_data); } else { colour_table = gif->global_colour_table; } - /* Initialise the LZW decoding - */ - set_code_size = gif_data[0]; - gif->buffer_position = (gif_data - gif->gif_data) + 1; - /* Set our code variables + /* If we are clearing the image we just clear, if not decode */ - code_size = set_code_size + 1; - clear_code = (1 << set_code_size); - end_code = clear_code + 1; - max_code_size = 2 * clear_code; - max_code = clear_code + 2; - curbit = lastbit = 0; - last_byte = 2; - get_done = 0; - return_clear = 1; - stack_pointer = stack; + if (!clear_image) { + /* Set our dirty status + */ + if ((background_action == 2) || (background_action == 3)) { + gif->dirty_frame = frame; + } + + /* Initialise the LZW decoding + */ + set_code_size = gif_data[0]; + gif->buffer_position = (gif_data - gif->gif_data) + 1; - /* Set the transparent colour as transparent - */ - if (transparency_index >= 0) { - transparent_colour = colour_table[transparency_index]; - colour_table[transparency_index] = 0x00000000; - } + /* Set our code variables + */ + code_size = set_code_size + 1; + clear_code = (1 << set_code_size); + end_code = clear_code + 1; + max_code_size = 2 * clear_code; + max_code = clear_code + 2; + curbit = lastbit = 0; + last_byte = 2; + get_done = 0; + return_clear = 1; + stack_pointer = stack; - /* Decompress the data - */ - if ((gif->background_action == 2) || (gif->background_action == 3)) { - frame_data_size = width * height; - for (y = 0; y < height; y++) { - if (interlace) { - decode_y = gif_interlaced_line(height, y) + offset_y; - } else { - decode_y = y + offset_y; - } - frame_scanline = frame_data + offset_x + (decode_y * gif->width); - for (x = 0; x < width; x++) { - if ((colour = gif_read_LZW(gif)) >= 0) { - *frame_scanline++ = colour_table[colour]; - } else { - LOG(("%i bytes of %i read", index, frame_data_size)); - return_value = GIF_INSUFFICIENT_FRAME_DATA; - goto gif_decode_frame_exit; - } - } - } - } else { - frame_data_size = width * height; + /* Decompress the data + */ for (y = 0; y < height; y++) { if (interlace) { decode_y = gif_interlaced_line(height, y) + offset_y; @@ -708,20 +704,38 @@ int gif_decode_frame(struct gif_animation *gif, unsigned int frame) { *frame_scanline++ = colour_table[colour]; } } else { - LOG(("%i bytes of %i read", index, frame_data_size)); return_value = GIF_INSUFFICIENT_FRAME_DATA; goto gif_decode_frame_exit; } } - } - } -gif_decode_frame_exit: - - /* Unset the transparent colour - */ - if (transparency_index >= 0) { - colour_table[transparency_index] = transparent_colour; + } + } else { + /* Clear our frame + */ + if ((background_action == 2) || (background_action == 3)) { + for (y = 0; y < height; y++) { + frame_scanline = frame_data + offset_x + ((offset_y + y) * gif->width); + memset(frame_scanline, 0x00, width * 4); + } + } + + /* Repeatedly skip blocks until we get a zero block or run out of data + */ + gif_bytes = gif->buffer_size - gif->buffer_position; + gif_data = gif->gif_data + gif->buffer_size; + block_size = 0; + while (block_size != 1) { + /* Skip the block data + */ + block_size = gif_data[0] + 1; + if ((gif_bytes -= block_size) < 0) { + return_value = GIF_INSUFFICIENT_FRAME_DATA; + goto gif_decode_frame_exit; + } + gif_data += block_size; + } } +gif_decode_frame_exit: /* Check for end of data */ @@ -748,14 +762,6 @@ static unsigned int gif_interlaced_line(unsigned int height, unsigned int y) { if ((y << 2) < (height - 2)) return (y << 2) + 2; y -= ((height + 1) >> 2); return (y << 1) + 1; - -/* if ((y & 7) == 0) return (y >> 3); - offset = (height + 7) >> 3; - if ((y & 7) == 4) return offset + ((y - 4) >> 3); - offset += (height + 3) >> 3; - if ((y & 3) == 2) return offset + ((y - 2) >> 2); - return offset + ((height + 1) >> 2) + ((y - 1) >> 1); -*/ } /* Releases any workspace held by the animation diff --git a/riscos/gifread.h b/riscos/gifread.h index e1d11017e..391946b01 100644 --- a/riscos/gifread.h +++ b/riscos/gifread.h @@ -63,11 +63,8 @@ typedef struct gif_animation { /* Decoded frame data */ -// unsigned int frame_offset_x; -// unsigned int frame_offset_y; -// unsigned int frame_width; -// unsigned int frame_height; - unsigned int background_action; + unsigned int dirty_plot; // Frame needs background erasing + unsigned int dirty_frame; // Frame needs erasing before next osspriteop_header *frame_image; } gif_animation; |