diff options
Diffstat (limited to '')
-rw-r--r-- | image/decoders/nsGIFDecoder2.h | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/image/decoders/nsGIFDecoder2.h b/image/decoders/nsGIFDecoder2.h new file mode 100644 index 0000000000..5a6c501778 --- /dev/null +++ b/image/decoders/nsGIFDecoder2.h @@ -0,0 +1,166 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_image_decoders_nsGIFDecoder2_h +#define mozilla_image_decoders_nsGIFDecoder2_h + +#include "Decoder.h" +#include "GIF2.h" +#include "StreamingLexer.h" +#include "SurfacePipe.h" +#include "mozilla/gfx/Swizzle.h" + +namespace mozilla { +namespace image { +class RasterImage; + +////////////////////////////////////////////////////////////////////// +// nsGIFDecoder2 Definition + +class nsGIFDecoder2 : public Decoder { + public: + ~nsGIFDecoder2(); + + DecoderType GetType() const override { return DecoderType::GIF; } + + protected: + LexerResult DoDecode(SourceBufferIterator& aIterator, + IResumable* aOnResume) override; + nsresult FinishInternal() override; + + Maybe<Telemetry::HistogramID> SpeedHistogram() const override; + + private: + friend class DecoderFactory; + + // Decoders should only be instantiated via DecoderFactory. + explicit nsGIFDecoder2(RasterImage* aImage); + + /// Called when we begin decoding the image. + void BeginGIF(); + + /** + * Called when we begin decoding a frame. + * + * @param aFrameRect The region of the image that contains data. The region + * outside this rect is transparent. + * @param aDepth The palette depth of this frame. + * @param aIsInterlaced If true, this frame is an interlaced frame. + */ + nsresult BeginImageFrame(const OrientedIntRect& aFrameRect, uint16_t aDepth, + bool aIsInterlaced); + + /// Called when we finish decoding a frame. + void EndImageFrame(); + + /// Called when we finish decoding the entire image. + void FlushImageData(); + + /// Convert color map to BGRA, applying any necessary CMS transforms. + void ConvertColormap(uint32_t* aColormap, uint32_t aColors); + + /// Transforms a palette index into a pixel. + template <typename PixelSize> + PixelSize ColormapIndexToPixel(uint8_t aIndex); + + /// A generator function that performs LZW decompression and yields pixels. + template <typename PixelSize> + std::tuple<int32_t, Maybe<WriteState>> YieldPixels(const uint8_t* aData, + size_t aLength, + size_t* aBytesReadOut, + PixelSize* aPixelBlock, + int32_t aBlockSize); + + /// Checks if we have transparency, either because the header indicates that + /// there's alpha, or because the frame rect doesn't cover the entire image. + bool CheckForTransparency(const OrientedIntRect& aFrameRect); + + // @return the clear code used for LZW decompression. + int ClearCode() const { + MOZ_ASSERT(mGIFStruct.datasize <= MAX_LZW_BITS); + return 1 << mGIFStruct.datasize; + } + + enum class State { + FAILURE, + SUCCESS, + GIF_HEADER, + SCREEN_DESCRIPTOR, + GLOBAL_COLOR_TABLE, + FINISHED_GLOBAL_COLOR_TABLE, + BLOCK_HEADER, + EXTENSION_HEADER, + GRAPHIC_CONTROL_EXTENSION, + APPLICATION_IDENTIFIER, + NETSCAPE_EXTENSION_SUB_BLOCK, + NETSCAPE_EXTENSION_DATA, + IMAGE_DESCRIPTOR, + FINISH_IMAGE_DESCRIPTOR, + LOCAL_COLOR_TABLE, + FINISHED_LOCAL_COLOR_TABLE, + IMAGE_DATA_BLOCK, + IMAGE_DATA_SUB_BLOCK, + LZW_DATA, + SKIP_LZW_DATA, + FINISHED_LZW_DATA, + SKIP_SUB_BLOCKS, + SKIP_DATA_THEN_SKIP_SUB_BLOCKS, + FINISHED_SKIPPING_DATA + }; + + LexerTransition<State> ReadGIFHeader(const char* aData); + LexerTransition<State> ReadScreenDescriptor(const char* aData); + LexerTransition<State> ReadGlobalColorTable(const char* aData, + size_t aLength); + LexerTransition<State> FinishedGlobalColorTable(); + LexerTransition<State> ReadBlockHeader(const char* aData); + LexerTransition<State> ReadExtensionHeader(const char* aData); + LexerTransition<State> ReadGraphicControlExtension(const char* aData); + LexerTransition<State> ReadApplicationIdentifier(const char* aData); + LexerTransition<State> ReadNetscapeExtensionSubBlock(const char* aData); + LexerTransition<State> ReadNetscapeExtensionData(const char* aData); + LexerTransition<State> ReadImageDescriptor(const char* aData); + LexerTransition<State> FinishImageDescriptor(const char* aData); + LexerTransition<State> ReadLocalColorTable(const char* aData, size_t aLength); + LexerTransition<State> FinishedLocalColorTable(); + LexerTransition<State> ReadImageDataBlock(const char* aData); + LexerTransition<State> ReadImageDataSubBlock(const char* aData); + LexerTransition<State> ReadLZWData(const char* aData, size_t aLength); + LexerTransition<State> SkipSubBlocks(const char* aData); + + // The StreamingLexer used to manage input. The initial size of the buffer is + // chosen as a little larger than the maximum size of any fixed-length data we + // have to read for a state. We read variable-length data in unbuffered mode + // so the buffer shouldn't have to be resized during decoding. + StreamingLexer<State, 16> mLexer; + + uint32_t mOldColor; // The old value of the transparent pixel + + // The frame number of the currently-decoding frame when we're in the middle + // of decoding it, and -1 otherwise. + int32_t mCurrentFrameIndex; + + // When we're reading in the global or local color table, this records our + // current position - i.e., the offset into which the next byte should be + // written. + size_t mColorTablePos; + uint32_t* mColormap; // Current colormap to be used in Cairo format + uint32_t mColormapSize; + + uint8_t mColorMask; // Apply this to the pixel to keep within colormap + bool mGIFOpen; + bool mSawTransparency; + + gif_struct mGIFStruct; + + gfx::SwizzleRowFn mSwizzleFn; /// Method to unpack color tables from RGB. + SurfacePipe mPipe; /// The SurfacePipe used to write to the output surface. +}; + +} // namespace image +} // namespace mozilla + +#endif // mozilla_image_decoders_nsGIFDecoder2_h |