This source file includes following definitions.
- m_repetitionCount
- create
- createForTesting
- isLazyDecoded
- setEnabled
- filenameExtension
- frameBufferAtIndex
- setData
- isSizeAvailable
- size
- frameSizeAtIndex
- frameCount
- repetitionCount
- clearCacheExceptFrame
- frameHasAlphaAtIndex
- frameIsCompleteAtIndex
- frameDurationAtIndex
- frameBytesAtIndex
- orientation
- activateLazyDecoding
- prepareLazyDecodedFrames
- createBitmap
- createSkiaDiscardableBitmap
- createLazyDecodingBitmap
- hotSpot
#include "config.h"
#include "platform/graphics/DeferredImageDecoder.h"
#include "platform/graphics/DecodingImageGenerator.h"
#include "platform/graphics/ImageDecodingStore.h"
#include "platform/graphics/LazyDecodingPixelRef.h"
#include "third_party/skia/include/core/SkImageInfo.h"
#include "wtf/PassOwnPtr.h"
namespace WebCore {
namespace {
const char labelLazyDecoded[] = "lazy";
const char labelDiscardable[] = "discardable";
}
bool DeferredImageDecoder::s_enabled = false;
bool DeferredImageDecoder::s_skiaDiscardableMemoryEnabled = false;
DeferredImageDecoder::DeferredImageDecoder(PassOwnPtr<ImageDecoder> actualDecoder)
: m_allDataReceived(false)
, m_lastDataSize(0)
, m_dataChanged(false)
, m_actualDecoder(actualDecoder)
, m_orientation(DefaultImageOrientation)
, m_repetitionCount(cAnimationNone)
{
}
DeferredImageDecoder::~DeferredImageDecoder()
{
}
PassOwnPtr<DeferredImageDecoder> DeferredImageDecoder::create(const SharedBuffer& data, ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorOption)
{
OwnPtr<ImageDecoder> actualDecoder = ImageDecoder::create(data, alphaOption, gammaAndColorOption);
return actualDecoder ? adoptPtr(new DeferredImageDecoder(actualDecoder.release())) : nullptr;
}
PassOwnPtr<DeferredImageDecoder> DeferredImageDecoder::createForTesting(PassOwnPtr<ImageDecoder> decoder)
{
return adoptPtr(new DeferredImageDecoder(decoder));
}
bool DeferredImageDecoder::isLazyDecoded(const SkBitmap& bitmap)
{
return bitmap.pixelRef()
&& bitmap.pixelRef()->getURI()
&& (!memcmp(bitmap.pixelRef()->getURI(), labelLazyDecoded, sizeof(labelLazyDecoded))
|| !memcmp(bitmap.pixelRef()->getURI(), labelDiscardable, sizeof(labelDiscardable)));
}
void DeferredImageDecoder::setEnabled(bool enabled)
{
s_enabled = enabled;
#if !OS(ANDROID)
s_skiaDiscardableMemoryEnabled = enabled;
if (enabled)
ImageDecodingStore::setImageCachingEnabled(false);
#endif
}
String DeferredImageDecoder::filenameExtension() const
{
return m_actualDecoder ? m_actualDecoder->filenameExtension() : m_filenameExtension;
}
ImageFrame* DeferredImageDecoder::frameBufferAtIndex(size_t index)
{
prepareLazyDecodedFrames();
if (index < m_lazyDecodedFrames.size()) {
m_lazyDecodedFrames[index]->setHasAlpha(m_frameGenerator->hasAlpha(index));
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) {
const bool firstData = !m_data && data;
const bool moreData = data && data->size() > m_lastDataSize;
m_dataChanged = firstData || moreData;
m_data = data;
m_lastDataSize = data->size();
m_allDataReceived = allDataReceived;
m_actualDecoder->setData(data, allDataReceived);
prepareLazyDecodedFrames();
}
if (m_frameGenerator)
m_frameGenerator->setData(data, allDataReceived);
}
bool DeferredImageDecoder::isSizeAvailable()
{
return m_actualDecoder ? m_actualDecoder->isSizeAvailable() : true;
}
IntSize DeferredImageDecoder::size() const
{
return m_actualDecoder ? m_actualDecoder->size() : m_size;
}
IntSize DeferredImageDecoder::frameSizeAtIndex(size_t index) const
{
return m_actualDecoder ? m_actualDecoder->frameSizeAtIndex(index) : m_size;
}
size_t DeferredImageDecoder::frameCount()
{
return m_actualDecoder ? m_actualDecoder->frameCount() : m_lazyDecodedFrames.size();
}
int DeferredImageDecoder::repetitionCount() const
{
return m_actualDecoder ? m_actualDecoder->repetitionCount() : m_repetitionCount;
}
size_t DeferredImageDecoder::clearCacheExceptFrame(size_t clearExceptFrame)
{
return m_actualDecoder ? m_actualDecoder->clearCacheExceptFrame(clearExceptFrame) : 0;
}
bool DeferredImageDecoder::frameHasAlphaAtIndex(size_t index) const
{
if (m_actualDecoder)
return m_actualDecoder->frameHasAlphaAtIndex(index);
if (!m_frameGenerator->isMultiFrame())
return m_frameGenerator->hasAlpha(index);
return true;
}
bool DeferredImageDecoder::frameIsCompleteAtIndex(size_t index) const
{
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
{
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
{
return m_frameGenerator ? 0 : m_actualDecoder->frameBytesAtIndex(index);
}
ImageOrientation DeferredImageDecoder::orientation() const
{
return m_actualDecoder ? m_actualDecoder->orientation() : m_orientation;
}
void DeferredImageDecoder::activateLazyDecoding()
{
if (m_frameGenerator)
return;
m_size = m_actualDecoder->size();
m_orientation = m_actualDecoder->orientation();
m_filenameExtension = m_actualDecoder->filenameExtension();
const bool isSingleFrame = m_actualDecoder->repetitionCount() == cAnimationNone || (m_allDataReceived && m_actualDecoder->frameCount() == 1u);
m_frameGenerator = ImageFrameGenerator::create(SkISize::Make(m_actualDecoder->decodedSize().width(), m_actualDecoder->decodedSize().height()), m_data, m_allDataReceived, !isSingleFrame);
}
void DeferredImageDecoder::prepareLazyDecodedFrames()
{
if (!s_enabled
|| !m_actualDecoder
|| !m_actualDecoder->isSizeAvailable()
|| m_actualDecoder->filenameExtension() == "ico")
return;
activateLazyDecoding();
const size_t previousSize = m_lazyDecodedFrames.size();
m_lazyDecodedFrames.resize(m_actualDecoder->frameCount());
if (m_lazyDecodedFrames.size() < previousSize)
return;
for (size_t i = previousSize; i < m_lazyDecodedFrames.size(); ++i) {
OwnPtr<ImageFrame> frame(adoptPtr(new ImageFrame()));
frame->setSkBitmap(createBitmap(i));
frame->setDuration(m_actualDecoder->frameDurationAtIndex(i));
frame->setStatus(m_actualDecoder->frameIsCompleteAtIndex(i) ? ImageFrame::FrameComplete : ImageFrame::FramePartial);
m_lazyDecodedFrames[i] = frame.release();
}
if (previousSize) {
const size_t lastFrame = previousSize - 1;
m_lazyDecodedFrames[lastFrame]->setStatus(m_actualDecoder->frameIsCompleteAtIndex(lastFrame) ? ImageFrame::FrameComplete : ImageFrame::FramePartial);
if (m_dataChanged) {
m_dataChanged = false;
m_lazyDecodedFrames[lastFrame]->setSkBitmap(createBitmap(lastFrame));
}
}
if (m_allDataReceived) {
m_repetitionCount = m_actualDecoder->repetitionCount();
m_actualDecoder.clear();
m_data = nullptr;
}
}
SkBitmap DeferredImageDecoder::createBitmap(size_t index)
{
if (s_skiaDiscardableMemoryEnabled)
return createSkiaDiscardableBitmap(index);
return createLazyDecodingBitmap(index);
}
SkBitmap DeferredImageDecoder::createSkiaDiscardableBitmap(size_t index)
{
IntSize decodedSize = m_actualDecoder->decodedSize();
ASSERT(decodedSize.width() > 0);
ASSERT(decodedSize.height() > 0);
SkImageInfo info;
info.fWidth = decodedSize.width();
info.fHeight = decodedSize.height();
info.fColorType = kBGRA_8888_SkColorType;
info.fAlphaType = kPremul_SkAlphaType;
SkBitmap bitmap;
DecodingImageGenerator* generator = new DecodingImageGenerator(m_frameGenerator, info, index);
bool installed = SkInstallDiscardablePixelRef(generator, &bitmap);
ASSERT_UNUSED(installed, installed);
bitmap.pixelRef()->setURI(labelDiscardable);
generator->setGenerationId(bitmap.getGenerationID());
return bitmap;
}
SkBitmap DeferredImageDecoder::createLazyDecodingBitmap(size_t index)
{
IntSize decodedSize = m_actualDecoder->decodedSize();
ASSERT(decodedSize.width() > 0);
ASSERT(decodedSize.height() > 0);
SkImageInfo info;
info.fWidth = decodedSize.width();
info.fHeight = decodedSize.height();
info.fColorType = kPMColor_SkColorType;
info.fAlphaType = kPremul_SkAlphaType;
SkBitmap bitmap;
bitmap.setConfig(info);
bitmap.setPixelRef(new LazyDecodingPixelRef(info, m_frameGenerator, index))->unref();
bitmap.pixelRef()->setURI(labelLazyDecoded);
bitmap.setImmutable();
return bitmap;
}
bool DeferredImageDecoder::hotSpot(IntPoint& hotSpot) const
{
return m_actualDecoder ? m_actualDecoder->hotSpot(hotSpot) : false;
}
}