| Index: Source/core/platform/graphics/chromium/DeferredImageDecoder.cpp
|
| diff --git a/Source/core/platform/graphics/chromium/DeferredImageDecoder.cpp b/Source/core/platform/graphics/chromium/DeferredImageDecoder.cpp
|
| index 1bd684cc979688e2136762adc0594ed8153477ed..717d38d38c62be01a4ef8d9cccfaa5964b0f8303 100644
|
| --- a/Source/core/platform/graphics/chromium/DeferredImageDecoder.cpp
|
| +++ b/Source/core/platform/graphics/chromium/DeferredImageDecoder.cpp
|
| @@ -46,6 +46,7 @@ DeferredImageDecoder::DeferredImageDecoder(PassOwnPtr<ImageDecoder> actualDecode
|
| : m_allDataReceived(false)
|
| , m_actualDecoder(actualDecoder)
|
| , m_orientation(DefaultImageOrientation)
|
| + , m_repetitionCount(cAnimationNone)
|
| {
|
| }
|
|
|
| @@ -84,7 +85,7 @@ SkBitmap DeferredImageDecoder::createResizedLazyDecodingBitmap(const SkBitmap& b
|
| // FIXME: This code has the potential problem that multiple
|
| // LazyDecodingPixelRefs are created even though they share the same
|
| // scaled size and ImageFrameGenerator.
|
| - resizedBitmap.setPixelRef(new LazyDecodingPixelRef(pixelRef->frameGenerator(), scaledSize, scaledSubset))->unref();
|
| + resizedBitmap.setPixelRef(new LazyDecodingPixelRef(pixelRef->frameGenerator(), scaledSize, pixelRef->frameIndex(), scaledSubset))->unref();
|
|
|
| // See comments in createLazyDecodingBitmap().
|
| resizedBitmap.setImmutable();
|
| @@ -98,44 +99,25 @@ void DeferredImageDecoder::setEnabled(bool enabled)
|
|
|
| ImageFrame* DeferredImageDecoder::frameBufferAtIndex(size_t index)
|
| {
|
| - // Only defer image decoding if this is a single frame image. The reason is
|
| - // because a multiframe is usually animated GIF. Animation is handled by
|
| - // BitmapImage which uses some metadata functions that do synchronous image
|
| - // decoding.
|
| - if (s_enabled
|
| - && m_actualDecoder
|
| - && m_actualDecoder->repetitionCount() == cAnimationNone
|
| - && m_actualDecoder->isSizeAvailable()
|
| - && m_actualDecoder->frameCount() == 1) {
|
| -
|
| - m_size = m_actualDecoder->size();
|
| - m_orientation = m_actualDecoder->orientation();
|
| -
|
| - SkBitmap lazyDecodedSkBitmap = createLazyDecodingBitmap();
|
| - m_lazyDecodedFrame.setSkBitmap(lazyDecodedSkBitmap);
|
| -
|
| - // Don't mark the frame as completely decoded until the underlying
|
| - // decoder has really decoded it. Until then, our data and metadata may
|
| - // be incorrect, so callers can't rely on them.
|
| - m_lazyDecodedFrame.setStatus(ImageFrame::FramePartial);
|
| - }
|
| -
|
| - return m_actualDecoder ? m_actualDecoder->frameBufferAtIndex(index) : &m_lazyDecodedFrame;
|
| + prepareLazyDecodedFrames();
|
| + if (index < m_lazyDecodedFrames.size())
|
| + return m_lazyDecodedFrames[index].get();
|
| + if (m_actualDecoder)
|
| + return m_actualDecoder->frameBufferAtIndex(index);
|
| + return 0;
|
| }
|
|
|
| void DeferredImageDecoder::setData(SharedBuffer* data, bool allDataReceived)
|
| {
|
| if (m_actualDecoder) {
|
| - // Keep a reference to data until image decoding is deferred.
|
| - // When image decoding is deferred then ownership of m_data is
|
| - // transferred to ImageDecodingStore.
|
| m_data = data;
|
| m_allDataReceived = allDataReceived;
|
| m_actualDecoder->setData(data, allDataReceived);
|
| - } else {
|
| - ASSERT(!m_data);
|
| - m_frameGenerator->setData(data, allDataReceived);
|
| + prepareLazyDecodedFrames();
|
| }
|
| +
|
| + if (m_frameGenerator)
|
| + m_frameGenerator->setData(data, allDataReceived);
|
| }
|
|
|
| bool DeferredImageDecoder::isSizeAvailable()
|
| @@ -152,17 +134,19 @@ IntSize DeferredImageDecoder::size() const
|
|
|
| IntSize DeferredImageDecoder::frameSizeAtIndex(size_t index) const
|
| {
|
| + // FIXME: Frame size is assumed to be uniform. This might not be true for
|
| + // future supported codecs.
|
| return m_actualDecoder ? m_actualDecoder->frameSizeAtIndex(index) : m_size;
|
| }
|
|
|
| size_t DeferredImageDecoder::frameCount()
|
| {
|
| - return m_actualDecoder ? m_actualDecoder->frameCount() : 1;
|
| + return m_actualDecoder ? m_actualDecoder->frameCount() : m_lazyDecodedFrames.size();
|
| }
|
|
|
| int DeferredImageDecoder::repetitionCount() const
|
| {
|
| - return m_actualDecoder ? m_actualDecoder->repetitionCount() : cAnimationNone;
|
| + return m_actualDecoder ? m_actualDecoder->repetitionCount() : m_repetitionCount;
|
| }
|
|
|
| size_t DeferredImageDecoder::clearCacheExceptFrame(size_t clearExceptFrame)
|
| @@ -174,26 +158,37 @@ size_t DeferredImageDecoder::clearCacheExceptFrame(size_t clearExceptFrame)
|
|
|
| bool DeferredImageDecoder::frameHasAlphaAtIndex(size_t index) const
|
| {
|
| - return m_actualDecoder ? m_actualDecoder->frameHasAlphaAtIndex(index) : m_frameGenerator->hasAlpha();
|
| + // FIXME: Report this for multi-frame image.
|
| + if (m_actualDecoder)
|
| + return m_actualDecoder->frameHasAlphaAtIndex(index);
|
| + if (!m_frameGenerator->isMultiFrame())
|
| + return m_frameGenerator->hasAlpha();
|
| + return true;
|
| }
|
|
|
| bool DeferredImageDecoder::frameIsCompleteAtIndex(size_t index) const
|
| {
|
| - // TODO: Implement this for deferred decoding.
|
| - return m_actualDecoder && m_actualDecoder->frameIsCompleteAtIndex(index);
|
| + if (m_actualDecoder)
|
| + return m_actualDecoder->frameIsCompleteAtIndex(index);
|
| + if (index < m_lazyDecodedFrames.size())
|
| + return m_lazyDecodedFrames[index]->status() == ImageFrame::FrameComplete;
|
| + return false;
|
| }
|
|
|
| float DeferredImageDecoder::frameDurationAtIndex(size_t index) const
|
| {
|
| - // TODO: Implement this for deferred decoding.
|
| - return m_actualDecoder ? m_actualDecoder->frameDurationAtIndex(index) : 0;
|
| + if (m_actualDecoder)
|
| + return m_actualDecoder->frameDurationAtIndex(index);
|
| + if (index < m_lazyDecodedFrames.size())
|
| + return m_lazyDecodedFrames[index]->duration();
|
| + return 0;
|
| }
|
|
|
| unsigned DeferredImageDecoder::frameBytesAtIndex(size_t index) const
|
| {
|
| // If frame decoding is deferred then it is not managed by MemoryCache
|
| // so return 0 here.
|
| - return m_actualDecoder ? m_actualDecoder->frameBytesAtIndex(index) : 0;
|
| + return m_frameGenerator ? 0 : m_actualDecoder->frameBytesAtIndex(index);
|
| }
|
|
|
| ImageOrientation DeferredImageDecoder::orientation() const
|
| @@ -201,7 +196,48 @@ ImageOrientation DeferredImageDecoder::orientation() const
|
| return m_actualDecoder ? m_actualDecoder->orientation() : m_orientation;
|
| }
|
|
|
| -SkBitmap DeferredImageDecoder::createLazyDecodingBitmap()
|
| +void DeferredImageDecoder::activateLazyDecoding()
|
| +{
|
| + if (m_frameGenerator)
|
| + return;
|
| + m_size = m_actualDecoder->size();
|
| + m_orientation = m_actualDecoder->orientation();
|
| + const bool isSingleFrame = m_actualDecoder->repetitionCount() == cAnimationNone || (m_allDataReceived && m_actualDecoder->frameCount() == 1u);
|
| + m_frameGenerator = ImageFrameGenerator::create(SkISize::Make(m_size.width(), m_size.height()), m_data, m_allDataReceived, !isSingleFrame);
|
| +}
|
| +
|
| +void DeferredImageDecoder::prepareLazyDecodedFrames()
|
| +{
|
| + if (!s_enabled
|
| + || !m_actualDecoder
|
| + || !m_actualDecoder->isSizeAvailable())
|
| + return;
|
| +
|
| + activateLazyDecoding();
|
| +
|
| + const size_t previousSize = m_lazyDecodedFrames.size();
|
| + m_lazyDecodedFrames.resize(m_actualDecoder->frameCount());
|
| + for (size_t i = previousSize; i < m_lazyDecodedFrames.size(); ++i) {
|
| + OwnPtr<ImageFrame> frame(adoptPtr(new ImageFrame()));
|
| + frame->setSkBitmap(createLazyDecodingBitmap(i));
|
| + frame->setDuration(m_actualDecoder->frameDurationAtIndex(i));
|
| + frame->setStatus(m_actualDecoder->frameIsCompleteAtIndex(i) ? ImageFrame::FrameComplete : ImageFrame::FramePartial);
|
| + m_lazyDecodedFrames[i] = frame.release();
|
| + }
|
| +
|
| + // The last lazy decoded frame created from previous call might be
|
| + // incomplete so update its state.
|
| + if (previousSize)
|
| + m_lazyDecodedFrames[previousSize - 1]->setStatus(m_actualDecoder->frameIsCompleteAtIndex(previousSize - 1) ? ImageFrame::FrameComplete : ImageFrame::FramePartial);
|
| +
|
| + if (m_allDataReceived) {
|
| + m_repetitionCount = m_actualDecoder->repetitionCount();
|
| + m_actualDecoder.clear();
|
| + m_data = nullptr;
|
| + }
|
| +}
|
| +
|
| +SkBitmap DeferredImageDecoder::createLazyDecodingBitmap(size_t index)
|
| {
|
| SkISize fullSize = SkISize::Make(m_actualDecoder->size().width(), m_actualDecoder->size().height());
|
| ASSERT(!fullSize.isEmpty());
|
| @@ -211,11 +247,7 @@ SkBitmap DeferredImageDecoder::createLazyDecodingBitmap()
|
| // Creates a lazily decoded SkPixelRef that references the entire image without scaling.
|
| SkBitmap bitmap;
|
| bitmap.setConfig(SkBitmap::kARGB_8888_Config, fullSize.width(), fullSize.height());
|
| -
|
| - m_frameGenerator = ImageFrameGenerator::create(fullSize, m_data.release(), m_allDataReceived);
|
| - m_actualDecoder.clear();
|
| -
|
| - bitmap.setPixelRef(new LazyDecodingPixelRef(m_frameGenerator, fullSize, fullRect))->unref();
|
| + bitmap.setPixelRef(new LazyDecodingPixelRef(m_frameGenerator, fullSize, index, fullRect))->unref();
|
|
|
| // Use the URI to identify this as a lazily decoded SkPixelRef of type LazyDecodingPixelRef.
|
| // FIXME: It would be more useful to give the actual image URI.
|
| @@ -234,6 +266,7 @@ SkBitmap DeferredImageDecoder::createLazyDecodingBitmap()
|
|
|
| bool DeferredImageDecoder::hotSpot(IntPoint& hotSpot) const
|
| {
|
| + // TODO: Implement.
|
| return m_actualDecoder ? m_actualDecoder->hotSpot(hotSpot) : false;
|
| }
|
|
|
|
|