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::ID> 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. ClearCode()74 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 153