зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1204392 - Use StreamingLexer in the GIF decoder. r=njn,seth
This commit is contained in:
Родитель
59240878a5
Коммит
112f55ea0c
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче