Chromium Code Reviews| 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..bbdeb13dda2b9e565c3d3828c072e8ce4a96b158 100644 |
| --- a/third_party/WebKit/Source/platform/image-decoders/png/PNGImageReader.h |
| +++ b/third_party/WebKit/Source/platform/image-decoders/png/PNGImageReader.h |
| @@ -29,6 +29,10 @@ |
| #include "platform/image-decoders/png/PNGImageDecoder.h" |
| #include "png.h" |
| +namespace blink { |
| + |
| +class SegmentReader; |
| + |
| #if !defined(PNG_LIBPNG_VER_MAJOR) || !defined(PNG_LIBPNG_VER_MINOR) |
| #error version error: compile against a versioned libpng. |
| #endif |
| @@ -40,45 +44,119 @@ |
| #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; |
| + }; |
| + |
| + // 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&, PNGImageDecoder::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(bool completed) { m_parseCompleted = completed; }; |
|
scroggo_chromium
2016/12/08 13:59:09
nit: this is only called with true, and I think it
joostouwerling
2016/12/08 16:28:39
Done.
|
| + |
| + // 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(SegmentReader&, size_t offset, size_t length); |
| + bool parseSize(SegmentReader&); |
| + void parseFrameInfo(const png_byte* data); |
| + void resetPNGStruct(); |
| + void startFrameDecoding(SegmentReader&, size_t); |
| + // @return true if the complete frame has been decoded |
| + // false otherwise |
| + bool progressivelyDecodeFirstFrame(SegmentReader&); |
| + void decodeFrame(SegmentReader&, size_t); |
| + void endFrameDecoding(); |
| +}; |
| +}; |
| #endif |