| Index: third_party/WebKit/Source/platform/image-decoders/png/PNGImageReader.h | 
| diff --git a/third_party/WebKit/Source/platform/image-decoders/png/PNGImageReader.h b/third_party/WebKit/Source/platform/image-decoders/png/PNGImageReader.h | 
| index 4144201a9b66088d12704bdf2d64feb9eac6c822..62d53542789b964011c5cd2c2b79cb9aa4458ad1 100644 | 
| --- a/third_party/WebKit/Source/platform/image-decoders/png/PNGImageReader.h | 
| +++ b/third_party/WebKit/Source/platform/image-decoders/png/PNGImageReader.h | 
| @@ -26,8 +26,28 @@ | 
| #ifndef PNGImageReader_h | 
| #define PNGImageReader_h | 
|  | 
| -#include "platform/image-decoders/png/PNGImageDecoder.h" | 
| +#include "platform/PlatformExport.h" | 
| +#include "platform/geometry/IntRect.h" | 
| #include "png.h" | 
| +#include "wtf/Allocator.h" | 
| +#include "wtf/Noncopyable.h" | 
| +#include "wtf/PtrUtil.h" | 
| +#include "wtf/Vector.h" | 
| + | 
| +namespace blink { | 
| + | 
| +// These constants map to the frame control parameters defined in fcTL chunks, | 
| +// as specified at https://wiki.mozilla.org/APNG_Specification. | 
| +const uint8_t kAPNGAlphaBlendBgcolor = 0; | 
| +const uint8_t kAPNGAlphaBlendPreviousFrame = 1; | 
| + | 
| +const uint8_t kAPNGDisposeKeep = 0; | 
| +const uint8_t kAPNGDisposeBgcolor = 1; | 
| +const uint8_t kAPNGDisposePrevious = 2; | 
| + | 
| +class SegmentReader; | 
| +class PNGImageDecoder; | 
| +class FastSharedBufferReader; | 
|  | 
| #if !defined(PNG_LIBPNG_VER_MAJOR) || !defined(PNG_LIBPNG_VER_MINOR) | 
| #error version error: compile against a versioned libpng. | 
| @@ -40,45 +60,123 @@ | 
| #define JMPBUF(png_ptr) png_ptr->jmpbuf | 
| #endif | 
|  | 
| -namespace blink { | 
| - | 
| -class SegmentReader; | 
| - | 
| class PLATFORM_EXPORT PNGImageReader final { | 
| USING_FAST_MALLOC(PNGImageReader); | 
| WTF_MAKE_NONCOPYABLE(PNGImageReader); | 
|  | 
| public: | 
| -  PNGImageReader(PNGImageDecoder*, size_t offset); | 
| +  PNGImageReader(PNGImageDecoder*, size_t initialOffset); | 
| ~PNGImageReader(); | 
|  | 
| -  bool decode(const SegmentReader&, bool sizeOnly); | 
| +  struct FrameInfo { | 
| +    // The offset where the frame data of this frame starts. | 
| +    size_t startOffset; | 
| +    // The number of bytes that contain frame data, starting at startOffset. | 
| +    size_t byteLength; | 
| +    size_t duration; | 
| +    IntRect frameRect; | 
| +    uint8_t disposalMethod; | 
| +    uint8_t alphaBlend; | 
| +  }; | 
| + | 
| +  enum class PNGParseQuery { PNGSizeQuery, PNGMetaDataQuery }; | 
| + | 
| +  // This method tries to parse the data stream in the SegmentReader, up to | 
| +  // the point where the PNGParseQuery can be answered. | 
| +  // @return true when the query is fulfilled. | 
| +  //         false when: | 
| +  //          A) not enough data provided | 
| +  //          B) the data processing by libpng fails. In this case, it also | 
| +  //             calls setFailed() on m_decoder. | 
| +  bool parse(SegmentReader&, PNGParseQuery); | 
| + | 
| +  void decode(SegmentReader&, size_t); | 
| +  const FrameInfo& frameInfo(size_t) const; | 
| + | 
| +  // This will return the number of frames that have been detected in the | 
| +  // stream so far. If an incomplete stream is provided, this number is not | 
| +  // final. However, all frame info for the frames up to this number is | 
| +  // available so it can be used by the client if it wants to. | 
| +  size_t frameCount() const; | 
| + | 
| +  // This is called by the the libpng callback that handles unknown chunks. | 
| +  void parseAnimationChunk(const char* tag, | 
| +                           const void* dataChunk, | 
| +                           size_t length); | 
| + | 
| +  // |m_parseCompleted| becomes true when | 
| +  //  a) the png is determined to be non-animated, if no acTL chunk is found | 
| +  //     before the IDAT chunk, or | 
| +  //  b) when the IEND chunk is seen for animated pngs. | 
| +  bool parseCompleted() const { return m_parseCompleted; }; | 
| +  void setParseCompleted() { m_parseCompleted = true; }; | 
| + | 
| +  // This method indicates for *animated* PNGs whether the first frame is fully | 
| +  // received. That is, when the fcTL chunk of the next frame has been received. | 
| +  bool firstFrameFullyReceived() const; | 
| + | 
| +  // This method is called when a frame with status ImageFrame::FramePartial | 
| +  // gets cleared in PNGImageDecoder. | 
| +  // | 
| +  // For |frameIndex| > 0, no action is necessary, since each decode call will | 
| +  // decode the frame completely from start to end. | 
| +  // | 
| +  // For |frameIndex| == 0, |m_progressiveDecodeOffset| will be set to 0, to | 
| +  // make sure progressive decoding is started from the beginning of the frame. | 
| +  void clearDecodeState(size_t frameIndex); | 
| + | 
| png_structp pngPtr() const { return m_png; } | 
| png_infop infoPtr() const { return m_info; } | 
|  | 
| -  size_t getReadOffset() const { return m_readOffset; } | 
| -  void setReadOffset(size_t offset) { m_readOffset = offset; } | 
| -  size_t currentBufferSize() const { return m_currentBufferSize; } | 
| -  bool decodingSizeOnly() const { return m_decodingSizeOnly; } | 
| -  void setHasAlpha(bool hasAlpha) { m_hasAlpha = hasAlpha; } | 
| -  bool hasAlpha() const { return m_hasAlpha; } | 
| - | 
| png_bytep interlaceBuffer() const { return m_interlaceBuffer.get(); } | 
| void createInterlaceBuffer(int size) { | 
| m_interlaceBuffer = wrapArrayUnique(new png_byte[size]); | 
| } | 
| +  void clearInterlaceBuffer() { m_interlaceBuffer.reset(); } | 
|  | 
| private: | 
| png_structp m_png; | 
| png_infop m_info; | 
| PNGImageDecoder* m_decoder; | 
| +  // This indicates at what offset in the stream the PNG image starts. | 
| +  const size_t m_initialOffset; | 
| +  // This is used to keep track of how many bytes we've read during parsing. | 
| size_t m_readOffset; | 
| -  size_t m_currentBufferSize; | 
| -  bool m_decodingSizeOnly; | 
| -  bool m_hasAlpha; | 
| + | 
| +  // This variable is used to do progressive decoding for the first frame. It | 
| +  // keeps track of how many bytes have been processed so far. | 
| +  size_t m_progressiveDecodeOffset; | 
| +  // The offset where IDAT starts. This is used to re-use the complete set of | 
| +  // info/header chunks when mimicking a png image for a frame. | 
| +  size_t m_idatOffset; | 
| +  // This flag is set to true when an fcTL chunk is encountered before the | 
| +  // IDAT chunk(s). In that case, the IDAT data is the first frame. Otherwise, | 
| +  // the IDAT is ignored for an animated image. | 
| +  bool m_idatIsPartOfAnimation; | 
| +  bool m_isAnimated; | 
| +  bool m_parsedSignature; | 
| +  bool m_parseCompleted; | 
| + | 
| std::unique_ptr<png_byte[]> m_interlaceBuffer; | 
| -}; | 
|  | 
| -}  // namespace blink | 
| +  Vector<FrameInfo, 1> m_frameInfo; | 
| +  // This is used to temporarily store frame information, until it is pushed to | 
| +  // |m_frameInfo|, when all frame data has been seen in the stream. | 
| +  FrameInfo m_newFrame; | 
| + | 
| +  size_t processData(const FastSharedBufferReader&, | 
| +                     size_t offset, | 
| +                     size_t length); | 
| +  bool parseSize(const FastSharedBufferReader&); | 
| +  void parseFrameInfo(const png_byte* data); | 
| +  void resetPNGStruct(); | 
| +  void startFrameDecoding(const FastSharedBufferReader&, size_t); | 
| +  // @return true if the complete frame has been decoded | 
| +  //         false  otherwise | 
| +  bool progressivelyDecodeFirstFrame(const FastSharedBufferReader&); | 
| +  void decodeFrame(const FastSharedBufferReader&, size_t); | 
| +  void endFrameDecoding(); | 
| +}; | 
| +}; | 
|  | 
| #endif | 
|  |