Bug 1204392 - Use StreamingLexer in the GIF decoder. r=njn,seth

This commit is contained in:
Seth Fowler 2016-06-08 12:17:17 -07:00
Родитель 59240878a5
Коммит 112f55ea0c
3 изменённых файлов: 702 добавлений и 696 удалений

Просмотреть файл

@ -15,44 +15,10 @@ enum { GIF_TRAILER = 0x3B }; // ';'
enum { GIF_IMAGE_SEPARATOR = 0x2C }; // ','
enum { GIF_EXTENSION_INTRODUCER = 0x21 }; // '!'
enum { GIF_GRAPHIC_CONTROL_LABEL = 0xF9 };
enum { GIF_COMMENT_LABEL = 0xFE };
enum { GIF_PLAIN_TEXT_LABEL = 0x01 };
enum { GIF_APPLICATION_EXTENSION_LABEL = 0xFF };
// gif2.h
// The interface for the GIF87/89a decoder.
// List of possible parsing states
typedef enum {
gif_type,
gif_global_header,
gif_global_colormap,
gif_image_start,
gif_image_header,
gif_image_colormap,
gif_lzw_start,
gif_lzw,
gif_sub_block,
gif_extension,
gif_control_extension,
gif_consume_block,
gif_skip_block,
gif_done,
gif_error,
gif_comment_extension,
gif_application_extension,
gif_netscape_extension_block,
gif_consume_netscape_extension,
gif_consume_comment
} gstate;
// A GIF decoder's state
typedef struct gif_struct {
// Parsing state machine
gstate state; // Current decoder master state
uint32_t bytes_to_consume; // Number of bytes to accumulate
uint32_t bytes_in_hold; // bytes accumulated so far
// LZW decoder state machine
uint8_t* stackp; // Current stack pointer
int datasize;
@ -61,7 +27,6 @@ typedef struct gif_struct {
int avail; // Index of next available slot in dictionary
int oldcode;
uint8_t firstchar;
int count; // Remaining # bytes in sub-block
int bits; // Number of unread bits in "datum"
int32_t datum; // 32-bit input buffer
@ -80,7 +45,8 @@ typedef struct gif_struct {
int version; // Either 89 for GIF89 or 87 for GIF87
int32_t screen_width; // Logical screen width & height
int32_t screen_height;
uint32_t global_colormap_depth; // Depth of global colormap array
uint8_t global_colormap_depth; // Depth of global colormap array
uint16_t global_colormap_count; // Number of colors in global colormap
int images_decoded; // Counts images for multi-part GIFs
int loop_count; // Netscape specific extension block to control
// the number of animation loops a GIF
@ -89,7 +55,6 @@ typedef struct gif_struct {
bool is_transparent; // TRUE, if tpixel is valid
uint16_t prefix[MAX_BITS]; // LZW decoding tables
uint8_t* hold; // Accumulation buffer
uint32_t global_colormap[MAX_COLORS]; // Default colormap if local not
// supplied
uint8_t suffix[MAX_BITS]; // LZW decoding tables

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -9,6 +9,7 @@
#include "Decoder.h"
#include "GIF2.h"
#include "StreamingLexer.h"
#include "SurfacePipe.h"
namespace mozilla {
@ -54,25 +55,70 @@ private:
/// Called when we finish decoding the entire image.
void FlushImageData();
nsresult GifWrite(const uint8_t* buf, uint32_t numbytes);
/// Transforms a palette index into a pixel.
template <typename PixelSize> PixelSize
ColormapIndexToPixel(uint8_t aIndex);
/// A generator function that performs LZW decompression and yields pixels.
template <typename PixelSize> NextPixel<PixelSize>
YieldPixel(const uint8_t*& aCurrentByte);
YieldPixel(const uint8_t* aData, size_t aLength, size_t* aBytesReadOut);
/// The entry point for LZW decompression.
bool DoLzw(const uint8_t* aData);
/// Checks if we have transparency, either because the header indicates that
/// there's alpha, or because the frame rect doesn't cover the entire image.
bool CheckForTransparency(const gfx::IntRect& aFrameRect);
bool SetHold(const uint8_t* buf, uint32_t count,
const uint8_t* buf2 = nullptr, uint32_t count2 = 0);
bool CheckForTransparency(const gfx::IntRect& aFrameRect);
gfx::IntRect ClampToImageRect(const gfx::IntRect& aFrameRect);
// @return the clear code used for LZW decompression.
int ClearCode() const { return 1 << mGIFStruct.datasize; }
inline int ClearCode() const { return 1 << mGIFStruct.datasize; }
enum class State
{
FAILURE,
SUCCESS,
GIF_HEADER,
SCREEN_DESCRIPTOR,
GLOBAL_COLOR_TABLE,
FINISHED_GLOBAL_COLOR_TABLE,
BLOCK_HEADER,
EXTENSION_HEADER,
GRAPHIC_CONTROL_EXTENSION,
APPLICATION_IDENTIFIER,
NETSCAPE_EXTENSION_SUB_BLOCK,
NETSCAPE_EXTENSION_DATA,
IMAGE_DESCRIPTOR,
LOCAL_COLOR_TABLE,
FINISHED_LOCAL_COLOR_TABLE,
IMAGE_DATA_BLOCK,
IMAGE_DATA_SUB_BLOCK,
LZW_DATA,
FINISHED_LZW_DATA,
SKIP_SUB_BLOCKS,
SKIP_DATA_THEN_SKIP_SUB_BLOCKS,
FINISHED_SKIPPING_DATA
};
LexerTransition<State> ReadGIFHeader(const char* aData);
LexerTransition<State> ReadScreenDescriptor(const char* aData);
LexerTransition<State> ReadGlobalColorTable(const char* aData, size_t aLength);
LexerTransition<State> FinishedGlobalColorTable();
LexerTransition<State> ReadBlockHeader(const char* aData);
LexerTransition<State> ReadExtensionHeader(const char* aData);
LexerTransition<State> ReadGraphicControlExtension(const char* aData);
LexerTransition<State> ReadApplicationIdentifier(const char* aData);
LexerTransition<State> ReadNetscapeExtensionSubBlock(const char* aData);
LexerTransition<State> ReadNetscapeExtensionData(const char* aData);
LexerTransition<State> ReadImageDescriptor(const char* aData);
LexerTransition<State> ReadLocalColorTable(const char* aData, size_t aLength);
LexerTransition<State> FinishedLocalColorTable();
LexerTransition<State> ReadImageDataBlock(const char* aData);
LexerTransition<State> ReadImageDataSubBlock(const char* aData);
LexerTransition<State> ReadLZWData(const char* aData, size_t aLength);
LexerTransition<State> SkipSubBlocks(const char* aData);
// The StreamingLexer used to manage input. The initial size of the buffer is
// chosen as a little larger than the maximum size of any fixed-length data we
// have to read for a state. We read variable-length data in unbuffered mode
// so the buffer shouldn't have to be resized during decoding.
StreamingLexer<State, 16> mLexer;
uint32_t mOldColor; // The old value of the transparent pixel
@ -80,6 +126,11 @@ private:
// of decoding it, and -1 otherwise.
int32_t mCurrentFrameIndex;
// When we're reading in the global or local color table, this records our
// current position - i.e., the offset into which the next byte should be
// written.
size_t mColorTablePos;
uint8_t mColorMask; // Apply this to the pixel to keep within colormap
bool mGIFOpen;
bool mSawTransparency;