| Index: third_party/WebKit/Source/platform/image-decoders/gif/GIFImageDecoder.cpp
|
| diff --git a/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageDecoder.cpp b/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageDecoder.cpp
|
| index cc5954edf9de97a6391a4c904dc4826cc341741d..bf46ddc90833f8c0fe7fa1b33465bbf42a2a3daf 100644
|
| --- a/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageDecoder.cpp
|
| +++ b/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageDecoder.cpp
|
| @@ -220,15 +220,48 @@ bool GIFImageDecoder::frameComplete(size_t frameIndex)
|
|
|
| size_t GIFImageDecoder::clearCacheExceptFrame(size_t clearExceptFrame)
|
| {
|
| - // We need to preserve frames such that:
|
| - // 1. We don't clear |clearExceptFrame|;
|
| - // 2. We don't clear any frame from which a future initFrameBuffer() call
|
| - // will copy bitmap data.
|
| - // All other frames can be cleared.
|
| + // We expect that after this call, we'll be asked to decode frames after
|
| + // this one. So we want to avoid clearing frames such that those requests
|
| + // would force re-decoding from the beginning of the image.
|
| + //
|
| + // When |clearExceptFrame| is e.g. DisposeKeep, simply not clearing that
|
| + // frame is sufficient, as the next frame will be based on it, and in
|
| + // general future frames can't be based on anything previous.
|
| + //
|
| + // However, if this frame is DisposeOverwritePrevious, then subsequent
|
| + // frames will depend on this frame's required previous frame. In this
|
| + // case, we need to preserve both this frame and that one.
|
| + size_t clearExceptFrame2 = kNotFound;
|
| + if (clearExceptFrame < m_frameBufferCache.size()) {
|
| + const ImageFrame& frame = m_frameBufferCache[clearExceptFrame];
|
| + if ((frame.status() != ImageFrame::FrameEmpty) && (frame.disposalMethod() == ImageFrame::DisposeOverwritePrevious)) {
|
| + clearExceptFrame2 = clearExceptFrame;
|
| + clearExceptFrame = frame.requiredPreviousFrameIndex();
|
| + }
|
| + }
|
| +
|
| + // Now |clearExceptFrame| indicates the frame that future frames will
|
| + // depend on. But if decoding is skipping forward past intermediate frames,
|
| + // this frame may be FrameEmpty. So we need to keep traversing back through
|
| + // the required previous frames until we find the nearest non-empty
|
| + // ancestor. Preserving that will minimize the amount of future decoding
|
| + // needed.
|
| while ((clearExceptFrame < m_frameBufferCache.size()) && (m_frameBufferCache[clearExceptFrame].status() == ImageFrame::FrameEmpty))
|
| clearExceptFrame = m_frameBufferCache[clearExceptFrame].requiredPreviousFrameIndex();
|
| + return clearCacheExceptTwoFrames(clearExceptFrame, clearExceptFrame2);
|
| +}
|
| +
|
|
|
| - return ImageDecoder::clearCacheExceptFrame(clearExceptFrame);
|
| +size_t GIFImageDecoder::clearCacheExceptTwoFrames(size_t clearExceptFrame1, size_t clearExceptFrame2)
|
| +{
|
| + size_t frameBytesCleared = 0;
|
| + for (size_t i = 0; i < m_frameBufferCache.size(); ++i) {
|
| + if (m_frameBufferCache[i].status() != ImageFrame::FrameEmpty && i != clearExceptFrame1 && i != clearExceptFrame2) {
|
| + frameBytesCleared += frameBytesAtIndex(i);
|
| + clearFrameBuffer(i);
|
| + }
|
| + }
|
| + return frameBytesCleared;
|
| }
|
|
|
| void GIFImageDecoder::clearFrameBuffer(size_t frameIndex)
|
|
|