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