nsGIFDecoder2.h (6164B)
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 #include "mozilla/gfx/Swizzle.h" 15 16 namespace mozilla { 17 namespace image { 18 class RasterImage; 19 20 ////////////////////////////////////////////////////////////////////// 21 // nsGIFDecoder2 Definition 22 23 class nsGIFDecoder2 final : public Decoder { 24 public: 25 ~nsGIFDecoder2(); 26 27 DecoderType GetType() const override { return DecoderType::GIF; } 28 29 protected: 30 LexerResult DoDecode(SourceBufferIterator& aIterator, 31 IResumable* aOnResume) override; 32 nsresult FinishWithErrorInternal() override; 33 nsresult FinishInternal() override; 34 35 Maybe<glean::impl::MemoryDistributionMetric> SpeedMetric() const override; 36 37 private: 38 friend class DecoderFactory; 39 40 // Decoders should only be instantiated via DecoderFactory. 41 explicit nsGIFDecoder2(RasterImage* aImage); 42 43 /// Called when we begin decoding the image. 44 void BeginGIF(); 45 46 /** 47 * Called when we begin decoding a frame. 48 * 49 * @param aFrameRect The region of the image that contains data. The region 50 * outside this rect is transparent. 51 * @param aDepth The palette depth of this frame. 52 * @param aIsInterlaced If true, this frame is an interlaced frame. 53 */ 54 nsresult BeginImageFrame(const OrientedIntRect& aFrameRect, 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 /// Convert color map to BGRA, applying any necessary CMS transforms. 64 void ConvertColormap(uint32_t* aColormap, uint32_t aColors); 65 66 /// Transforms a palette index into a pixel. 67 template <typename PixelSize> 68 PixelSize ColormapIndexToPixel(uint8_t aIndex); 69 70 /// A generator function that performs LZW decompression and yields pixels. 71 template <typename PixelSize> 72 std::tuple<int32_t, Maybe<WriteState>> YieldPixels(const uint8_t* aData, 73 size_t aLength, 74 size_t* aBytesReadOut, 75 PixelSize* aPixelBlock, 76 int32_t aBlockSize); 77 78 /// Checks if we have transparency, either because the header indicates that 79 /// there's alpha, or because the frame rect doesn't cover the entire image. 80 bool CheckForTransparency(const OrientedIntRect& aFrameRect); 81 82 // @return the clear code used for LZW decompression. 83 int ClearCode() const { 84 MOZ_ASSERT(mGIFStruct.datasize <= MAX_LZW_BITS); 85 return 1 << mGIFStruct.datasize; 86 } 87 88 enum class State { 89 FAILURE, 90 SUCCESS, 91 GIF_HEADER, 92 SCREEN_DESCRIPTOR, 93 GLOBAL_COLOR_TABLE, 94 FINISHED_GLOBAL_COLOR_TABLE, 95 BLOCK_HEADER, 96 EXTENSION_HEADER, 97 GRAPHIC_CONTROL_EXTENSION, 98 APPLICATION_IDENTIFIER, 99 NETSCAPE_EXTENSION_SUB_BLOCK, 100 NETSCAPE_EXTENSION_DATA, 101 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 FINISH_END_IMAGE_FRAME, 110 SKIP_SUB_BLOCKS, 111 SKIP_DATA_THEN_SKIP_SUB_BLOCKS, 112 FINISHED_SKIPPING_DATA 113 }; 114 115 LexerTransition<State> ReadGIFHeader(const char* aData); 116 LexerTransition<State> ReadScreenDescriptor(const char* aData); 117 LexerTransition<State> ReadGlobalColorTable(const char* aData, 118 size_t aLength); 119 LexerTransition<State> FinishedGlobalColorTable(); 120 LexerTransition<State> ReadBlockHeader(const char* aData); 121 LexerTransition<State> ReadExtensionHeader(const char* aData); 122 LexerTransition<State> ReadGraphicControlExtension(const char* aData); 123 LexerTransition<State> ReadApplicationIdentifier(const char* aData); 124 LexerTransition<State> ReadNetscapeExtensionSubBlock(const char* aData); 125 LexerTransition<State> ReadNetscapeExtensionData(const char* aData); 126 LexerTransition<State> ReadImageDescriptor(const char* aData); 127 LexerTransition<State> FinishImageDescriptor(const char* aData); 128 LexerTransition<State> ReadLocalColorTable(const char* aData, size_t aLength); 129 LexerTransition<State> FinishedLocalColorTable(); 130 LexerTransition<State> ReadImageDataBlock(const char* aData); 131 LexerTransition<State> ReadImageDataSubBlock(const char* aData); 132 LexerTransition<State> ReadLZWData(const char* aData, size_t aLength); 133 LexerTransition<State> SkipSubBlocks(const char* aData); 134 135 // The StreamingLexer used to manage input. The initial size of the buffer is 136 // chosen as a little larger than the maximum size of any fixed-length data we 137 // have to read for a state. We read variable-length data in unbuffered mode 138 // so the buffer shouldn't have to be resized during decoding. 139 StreamingLexer<State, 16> mLexer; 140 141 uint32_t mOldColor; // The old value of the transparent pixel 142 143 // The frame number of the currently-decoding frame when we're in the middle 144 // of decoding it, and -1 otherwise. 145 int32_t mCurrentFrameIndex; 146 147 // When we're reading in the global or local color table, this records our 148 // current position - i.e., the offset into which the next byte should be 149 // written. 150 size_t mColorTablePos; 151 uint32_t* mColormap; // Current colormap to be used in Cairo format 152 uint32_t mColormapSize; 153 154 uint8_t mColorMask; // Apply this to the pixel to keep within colormap 155 bool mGIFOpen; 156 bool mSawTransparency; 157 158 gif_struct mGIFStruct; 159 160 gfx::SwizzleRowFn mSwizzleFn; /// Method to unpack color tables from RGB. 161 SurfacePipe mPipe; /// The SurfacePipe used to write to the output surface. 162 }; 163 164 } // namespace image 165 } // namespace mozilla 166 167 #endif // mozilla_image_decoders_nsGIFDecoder2_h