tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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