Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
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/. */
6 :
7 : #ifndef mozilla_image_decoders_nsGIFDecoder2_h
8 : #define mozilla_image_decoders_nsGIFDecoder2_h
9 :
10 : #include "Decoder.h"
11 : #include "GIF2.h"
12 : #include "StreamingLexer.h"
13 : #include "SurfacePipe.h"
14 :
15 : namespace mozilla {
16 : namespace image {
17 : class RasterImage;
18 :
19 : //////////////////////////////////////////////////////////////////////
20 : // nsGIFDecoder2 Definition
21 :
22 : class nsGIFDecoder2 : public Decoder
23 : {
24 : public:
25 : ~nsGIFDecoder2();
26 :
27 : protected:
28 : LexerResult DoDecode(SourceBufferIterator& aIterator,
29 : IResumable* aOnResume) override;
30 : nsresult FinishInternal() override;
31 :
32 : Maybe<Telemetry::HistogramID> SpeedHistogram() const override;
33 :
34 : private:
35 : friend class DecoderFactory;
36 :
37 : // Decoders should only be instantiated via DecoderFactory.
38 : explicit nsGIFDecoder2(RasterImage* aImage);
39 :
40 : /// Called when we begin decoding the image.
41 : void BeginGIF();
42 :
43 : /**
44 : * Called when we begin decoding a frame.
45 : *
46 : * @param aFrameRect The region of the image that contains data. The region
47 : * outside this rect is transparent.
48 : * @param aDepth The palette depth of this frame.
49 : * @param aIsInterlaced If true, this frame is an interlaced frame.
50 : */
51 : nsresult BeginImageFrame(const gfx::IntRect& aFrameRect,
52 : uint16_t aDepth,
53 : bool aIsInterlaced);
54 :
55 : /// Called when we finish decoding a frame.
56 : void EndImageFrame();
57 :
58 : /// Called when we finish decoding the entire image.
59 : void FlushImageData();
60 :
61 : /// Transforms a palette index into a pixel.
62 : template <typename PixelSize> PixelSize
63 : ColormapIndexToPixel(uint8_t aIndex);
64 :
65 : /// A generator function that performs LZW decompression and yields pixels.
66 : template <typename PixelSize> NextPixel<PixelSize>
67 : YieldPixel(const uint8_t* aData, size_t aLength, size_t* aBytesReadOut);
68 :
69 : /// Checks if we have transparency, either because the header indicates that
70 : /// there's alpha, or because the frame rect doesn't cover the entire image.
71 : bool CheckForTransparency(const gfx::IntRect& aFrameRect);
72 :
73 : // @return the clear code used for LZW decompression.
74 18 : int ClearCode() const { return 1 << mGIFStruct.datasize; }
75 :
76 : enum class State
77 : {
78 : FAILURE,
79 : SUCCESS,
80 : GIF_HEADER,
81 : SCREEN_DESCRIPTOR,
82 : GLOBAL_COLOR_TABLE,
83 : FINISHED_GLOBAL_COLOR_TABLE,
84 : BLOCK_HEADER,
85 : EXTENSION_HEADER,
86 : GRAPHIC_CONTROL_EXTENSION,
87 : APPLICATION_IDENTIFIER,
88 : NETSCAPE_EXTENSION_SUB_BLOCK,
89 : NETSCAPE_EXTENSION_DATA,
90 : IMAGE_DESCRIPTOR,
91 : FINISH_IMAGE_DESCRIPTOR,
92 : LOCAL_COLOR_TABLE,
93 : FINISHED_LOCAL_COLOR_TABLE,
94 : IMAGE_DATA_BLOCK,
95 : IMAGE_DATA_SUB_BLOCK,
96 : LZW_DATA,
97 : SKIP_LZW_DATA,
98 : FINISHED_LZW_DATA,
99 : SKIP_SUB_BLOCKS,
100 : SKIP_DATA_THEN_SKIP_SUB_BLOCKS,
101 : FINISHED_SKIPPING_DATA
102 : };
103 :
104 : LexerTransition<State> ReadGIFHeader(const char* aData);
105 : LexerTransition<State> ReadScreenDescriptor(const char* aData);
106 : LexerTransition<State> ReadGlobalColorTable(const char* aData, size_t aLength);
107 : LexerTransition<State> FinishedGlobalColorTable();
108 : LexerTransition<State> ReadBlockHeader(const char* aData);
109 : LexerTransition<State> ReadExtensionHeader(const char* aData);
110 : LexerTransition<State> ReadGraphicControlExtension(const char* aData);
111 : LexerTransition<State> ReadApplicationIdentifier(const char* aData);
112 : LexerTransition<State> ReadNetscapeExtensionSubBlock(const char* aData);
113 : LexerTransition<State> ReadNetscapeExtensionData(const char* aData);
114 : LexerTransition<State> ReadImageDescriptor(const char* aData);
115 : LexerTransition<State> FinishImageDescriptor(const char* aData);
116 : LexerTransition<State> ReadLocalColorTable(const char* aData, size_t aLength);
117 : LexerTransition<State> FinishedLocalColorTable();
118 : LexerTransition<State> ReadImageDataBlock(const char* aData);
119 : LexerTransition<State> ReadImageDataSubBlock(const char* aData);
120 : LexerTransition<State> ReadLZWData(const char* aData, size_t aLength);
121 : LexerTransition<State> SkipSubBlocks(const char* aData);
122 :
123 : // The StreamingLexer used to manage input. The initial size of the buffer is
124 : // chosen as a little larger than the maximum size of any fixed-length data we
125 : // have to read for a state. We read variable-length data in unbuffered mode
126 : // so the buffer shouldn't have to be resized during decoding.
127 : StreamingLexer<State, 16> mLexer;
128 :
129 : uint32_t mOldColor; // The old value of the transparent pixel
130 :
131 : // The frame number of the currently-decoding frame when we're in the middle
132 : // of decoding it, and -1 otherwise.
133 : int32_t mCurrentFrameIndex;
134 :
135 : // When we're reading in the global or local color table, this records our
136 : // current position - i.e., the offset into which the next byte should be
137 : // written.
138 : size_t mColorTablePos;
139 :
140 : uint8_t mColorMask; // Apply this to the pixel to keep within colormap
141 : bool mGIFOpen;
142 : bool mSawTransparency;
143 :
144 : gif_struct mGIFStruct;
145 :
146 : SurfacePipe mPipe; /// The SurfacePipe used to write to the output surface.
147 : };
148 :
149 : } // namespace image
150 : } // namespace mozilla
151 :
152 : #endif // mozilla_image_decoders_nsGIFDecoder2_h
|