1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_image_decoders_nsGIFDecoder2_h
8 #define mozilla_image_decoders_nsGIFDecoder2_h
12 #include "StreamingLexer.h"
13 #include "SurfacePipe.h"
14 #include "mozilla/gfx/Swizzle.h"
20 //////////////////////////////////////////////////////////////////////
21 // nsGIFDecoder2 Definition
23 class nsGIFDecoder2
: public Decoder
{
27 DecoderType
GetType() const override
{ return DecoderType::GIF
; }
30 LexerResult
DoDecode(SourceBufferIterator
& aIterator
,
31 IResumable
* aOnResume
) override
;
32 nsresult
FinishInternal() override
;
34 Maybe
<Telemetry::HistogramID
> SpeedHistogram() const override
;
37 friend class DecoderFactory
;
39 // Decoders should only be instantiated via DecoderFactory.
40 explicit nsGIFDecoder2(RasterImage
* aImage
);
42 /// Called when we begin decoding the image.
46 * Called when we begin decoding a frame.
48 * @param aFrameRect The region of the image that contains data. The region
49 * outside this rect is transparent.
50 * @param aDepth The palette depth of this frame.
51 * @param aIsInterlaced If true, this frame is an interlaced frame.
53 nsresult
BeginImageFrame(const gfx::IntRect
& aFrameRect
, uint16_t aDepth
,
56 /// Called when we finish decoding a frame.
59 /// Called when we finish decoding the entire image.
60 void FlushImageData();
62 /// Convert color map to BGRA, applying any necessary CMS transforms.
63 void ConvertColormap(uint32_t* aColormap
, uint32_t aColors
);
65 /// Transforms a palette index into a pixel.
66 template <typename PixelSize
>
67 PixelSize
ColormapIndexToPixel(uint8_t aIndex
);
69 /// A generator function that performs LZW decompression and yields pixels.
70 template <typename PixelSize
>
71 Tuple
<int32_t, Maybe
<WriteState
>> YieldPixels(const uint8_t* aData
,
73 size_t* aBytesReadOut
,
74 PixelSize
* aPixelBlock
,
77 /// Checks if we have transparency, either because the header indicates that
78 /// there's alpha, or because the frame rect doesn't cover the entire image.
79 bool CheckForTransparency(const gfx::IntRect
& aFrameRect
);
81 // @return the clear code used for LZW decompression.
82 int ClearCode() const {
83 MOZ_ASSERT(mGIFStruct
.datasize
<= MAX_LZW_BITS
);
84 return 1 << mGIFStruct
.datasize
;
93 FINISHED_GLOBAL_COLOR_TABLE
,
96 GRAPHIC_CONTROL_EXTENSION
,
97 APPLICATION_IDENTIFIER
,
98 NETSCAPE_EXTENSION_SUB_BLOCK
,
99 NETSCAPE_EXTENSION_DATA
,
101 FINISH_IMAGE_DESCRIPTOR
,
103 FINISHED_LOCAL_COLOR_TABLE
,
105 IMAGE_DATA_SUB_BLOCK
,
110 SKIP_DATA_THEN_SKIP_SUB_BLOCKS
,
111 FINISHED_SKIPPING_DATA
114 LexerTransition
<State
> ReadGIFHeader(const char* aData
);
115 LexerTransition
<State
> ReadScreenDescriptor(const char* aData
);
116 LexerTransition
<State
> ReadGlobalColorTable(const char* aData
,
118 LexerTransition
<State
> FinishedGlobalColorTable();
119 LexerTransition
<State
> ReadBlockHeader(const char* aData
);
120 LexerTransition
<State
> ReadExtensionHeader(const char* aData
);
121 LexerTransition
<State
> ReadGraphicControlExtension(const char* aData
);
122 LexerTransition
<State
> ReadApplicationIdentifier(const char* aData
);
123 LexerTransition
<State
> ReadNetscapeExtensionSubBlock(const char* aData
);
124 LexerTransition
<State
> ReadNetscapeExtensionData(const char* aData
);
125 LexerTransition
<State
> ReadImageDescriptor(const char* aData
);
126 LexerTransition
<State
> FinishImageDescriptor(const char* aData
);
127 LexerTransition
<State
> ReadLocalColorTable(const char* aData
, size_t aLength
);
128 LexerTransition
<State
> FinishedLocalColorTable();
129 LexerTransition
<State
> ReadImageDataBlock(const char* aData
);
130 LexerTransition
<State
> ReadImageDataSubBlock(const char* aData
);
131 LexerTransition
<State
> ReadLZWData(const char* aData
, size_t aLength
);
132 LexerTransition
<State
> SkipSubBlocks(const char* aData
);
134 // The StreamingLexer used to manage input. The initial size of the buffer is
135 // chosen as a little larger than the maximum size of any fixed-length data we
136 // have to read for a state. We read variable-length data in unbuffered mode
137 // so the buffer shouldn't have to be resized during decoding.
138 StreamingLexer
<State
, 16> mLexer
;
140 uint32_t mOldColor
; // The old value of the transparent pixel
142 // The frame number of the currently-decoding frame when we're in the middle
143 // of decoding it, and -1 otherwise.
144 int32_t mCurrentFrameIndex
;
146 // When we're reading in the global or local color table, this records our
147 // current position - i.e., the offset into which the next byte should be
149 size_t mColorTablePos
;
150 uint32_t* mColormap
; // Current colormap to be used in Cairo format
151 uint32_t mColormapSize
;
153 uint8_t mColorMask
; // Apply this to the pixel to keep within colormap
155 bool mSawTransparency
;
157 gif_struct mGIFStruct
;
159 gfx::SwizzleRowFn mSwizzleFn
; /// Method to unpack color tables from RGB.
160 SurfacePipe mPipe
; /// The SurfacePipe used to write to the output surface.
164 } // namespace mozilla
166 #endif // mozilla_image_decoders_nsGIFDecoder2_h