Bug 1815313 - Add test for invalid schemes in onLoadRequest. r=jonalmeida
[gecko.git] / image / decoders / nsGIFDecoder2.h
blobfb444fba7e4d6c1c78f084ef9d406610f203308b
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
10 #include "Decoder.h"
11 #include "GIF2.h"
12 #include "StreamingLexer.h"
13 #include "SurfacePipe.h"
14 #include "mozilla/gfx/Swizzle.h"
16 namespace mozilla {
17 namespace image {
18 class RasterImage;
20 //////////////////////////////////////////////////////////////////////
21 // nsGIFDecoder2 Definition
23 class nsGIFDecoder2 : public Decoder {
24 public:
25 ~nsGIFDecoder2();
27 DecoderType GetType() const override { return DecoderType::GIF; }
29 protected:
30 LexerResult DoDecode(SourceBufferIterator& aIterator,
31 IResumable* aOnResume) override;
32 nsresult FinishInternal() override;
34 Maybe<Telemetry::HistogramID> SpeedHistogram() const override;
36 private:
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.
43 void BeginGIF();
45 /**
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 OrientedIntRect& aFrameRect, uint16_t aDepth,
54 bool aIsInterlaced);
56 /// Called when we finish decoding a frame.
57 void EndImageFrame();
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,
72 size_t aLength,
73 size_t* aBytesReadOut,
74 PixelSize* aPixelBlock,
75 int32_t aBlockSize);
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 OrientedIntRect& 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;
87 enum class State {
88 FAILURE,
89 SUCCESS,
90 GIF_HEADER,
91 SCREEN_DESCRIPTOR,
92 GLOBAL_COLOR_TABLE,
93 FINISHED_GLOBAL_COLOR_TABLE,
94 BLOCK_HEADER,
95 EXTENSION_HEADER,
96 GRAPHIC_CONTROL_EXTENSION,
97 APPLICATION_IDENTIFIER,
98 NETSCAPE_EXTENSION_SUB_BLOCK,
99 NETSCAPE_EXTENSION_DATA,
100 IMAGE_DESCRIPTOR,
101 FINISH_IMAGE_DESCRIPTOR,
102 LOCAL_COLOR_TABLE,
103 FINISHED_LOCAL_COLOR_TABLE,
104 IMAGE_DATA_BLOCK,
105 IMAGE_DATA_SUB_BLOCK,
106 LZW_DATA,
107 SKIP_LZW_DATA,
108 FINISHED_LZW_DATA,
109 SKIP_SUB_BLOCKS,
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,
117 size_t aLength);
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
148 // written.
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
154 bool mGIFOpen;
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.
163 } // namespace image
164 } // namespace mozilla
166 #endif // mozilla_image_decoders_nsGIFDecoder2_h