Chromium Code Reviews| Index: Source/core/platform/image-decoders/ImageDecoder.cpp |
| diff --git a/Source/core/platform/image-decoders/ImageDecoder.cpp b/Source/core/platform/image-decoders/ImageDecoder.cpp |
| index 37cd9327dd39379d68debb4ab690c28d772a5dd3..bd987851b2727084aa78fddc572c4fb5a14acf97 100644 |
| --- a/Source/core/platform/image-decoders/ImageDecoder.cpp |
| +++ b/Source/core/platform/image-decoders/ImageDecoder.cpp |
| @@ -227,4 +227,85 @@ int ImageDecoder::scaledY(int origY, int searchStart) |
| return getScaledValue<Exact>(m_scaledRows, origY, searchStart); |
| } |
| +void ImageDecoder::clearFrameBufferCache(size_t clearExceptFrame) |
| +{ |
| + // Don't clear if there is no or only one frame. |
| + if (m_frameBufferCache.size() <= 1) |
| + return; |
| + |
| + // 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; |
| + // 3. We don't clear empty frames. |
|
Peter Kasting
2013/05/24 03:15:22
Why not clear empty frames? Shouldn't that just b
Xianzhu
2013/05/28 22:54:21
Done.
|
| + // All other frames can be cleared. |
| + size_t frameToBeRequired; |
|
Peter Kasting
2013/05/24 03:15:22
Nit: Init this to notFound; this allows eliminatin
Xianzhu
2013/05/28 22:54:21
Done.
|
| + if (clearExceptFrame < m_frameBufferCache.size() && m_frameBufferCache[clearExceptFrame].status() == ImageFrame::FrameEmpty) { |
| + frameToBeRequired = clearExceptFrame; |
| + do { |
| + frameToBeRequired = m_frameBufferCache[frameToBeRequired].requiredPreviousFrameIndex(); |
| + } while (frameToBeRequired != notFound && m_frameBufferCache[frameToBeRequired].status() == ImageFrame::FrameEmpty); |
|
Peter Kasting
2013/05/24 03:15:22
This loop tries to preserve the frame we'll need t
Xianzhu
2013/05/28 22:54:21
Done.
|
| + } else { |
| + // initFrameBuffer() has already been called for this frame. |
| + frameToBeRequired = notFound; |
| + } |
| + |
| + for (size_t i = 0; i < m_frameBufferCache.size(); ++i) { |
| + if (i != clearExceptFrame && i != frameToBeRequired && m_frameBufferCache[i].status() != ImageFrame::FrameEmpty) |
| + clearFrameBuffer(i); |
| + } |
| +} |
| + |
| +void ImageDecoder::clearFrameBuffer(size_t frameIndex) |
| +{ |
| + m_frameBufferCache[frameIndex].clearPixelData(); |
| +} |
| + |
| +size_t ImageDecoder::findRequiredPreviousFrame(size_t frameIndex) |
|
Peter Kasting
2013/05/24 03:15:22
By the way, the algorithm in this function can be
|
| +{ |
| + if (!frameIndex) { |
| + // The first frame doesn't rely on any previous data. |
| + return notFound; |
| + } |
| + |
| + // The starting state for this frame depends on the previous frame's |
| + // disposal method. |
| + // |
| + // Frames that use the DisposeOverwritePrevious method are effectively |
| + // no-ops in terms of changing the starting state of a frame compared to |
| + // the starting state of the previous frame, so skip over them. (If the |
| + // first frame specifies this method, it will get treated like |
| + // DisposeOverwriteBgcolor below and reset to a completely empty image.) |
| + size_t prevFrame = frameIndex - 1; |
| + const ImageFrame* prevBuffer = &m_frameBufferCache[prevFrame]; |
|
Peter Kasting
2013/05/24 03:15:22
If we're going to do this we should either check o
Xianzhu
2013/05/28 22:54:21
Done.
|
| + ImageFrame::FrameDisposalMethod prevMethod = prevBuffer->disposalMethod(); |
| + while (prevFrame && (prevMethod == ImageFrame::DisposeOverwritePrevious)) { |
| + prevBuffer = &m_frameBufferCache[--prevFrame]; |
| + prevMethod = prevBuffer->disposalMethod(); |
| + } |
| + |
| + if (prevMethod == ImageFrame::DisposeNotSpecified || prevMethod == ImageFrame::DisposeKeep) { |
| + // prevFrame will be used as the starting state for this frame. |
|
Peter Kasting
2013/05/24 03:15:22
Nit: Might want to add a note or FIXME about being
Xianzhu
2013/05/28 22:54:21
Done.
|
| + return prevFrame; |
| + } |
| + |
| + if (!prevFrame) { |
| + // The first frame whose disposal method is DisposeOverwriteBgColor or |
| + // DisposeOverritePrevious will be reset to background despite its size. |
|
Peter Kasting
2013/05/24 03:15:22
Nit: Comment could be clearer; how about:
This fr
Xianzhu
2013/05/28 22:54:21
Done.
|
| + return notFound; |
| + } |
| + |
| + ASSERT(prevMethod == ImageFrame::DisposeOverwriteBgcolor); |
| + const IntRect& prevRect = prevBuffer->originalFrameRect(); |
| + const IntSize& bufferSize = scaledSize(); |
|
Peter Kasting
2013/05/24 03:15:22
I think scaledSize() got nuked (or is getting nuke
Xianzhu
2013/05/28 22:54:21
Done.
|
| + if (prevRect.contains(IntRect(IntPoint(), scaledSize()))) { |
| + // prevFrame covering the whole image will be reset to background, |
|
Peter Kasting
2013/05/24 03:15:22
Nit: A slightly shorter way of doing this:
//
Xianzhu
2013/05/28 22:54:21
Done.
|
| + return notFound; |
| + } |
| + |
| + // prevFrame only clears part of the image to background, so it contributes |
| + // to the starting state of this frame. |
| + return prevFrame; |
| +} |
| + |
| } // namespace WebCore |