NativeImageSkia.cpp [plain text]
#include "config.h"
#include "skia/ext/image_operations.h"
#include "NativeImageSkia.h"
#include "GraphicsContext3D.h"
#include "SkiaUtils.h"
#if PLATFORM(CHROMIUM)
#include "TraceEvent.h"
#endif
namespace WebCore {
NativeImageSkia::NativeImageSkia()
: m_resizeRequests(0)
{
}
NativeImageSkia::NativeImageSkia(const SkBitmap& other)
: m_image(other),
m_resizeRequests(0)
{
}
NativeImageSkia::~NativeImageSkia()
{
}
int NativeImageSkia::decodedSize() const
{
return m_image.getSize() + m_resizedImage.getSize();
}
bool NativeImageSkia::hasResizedBitmap(const SkIRect& srcSubset, int destWidth, int destHeight) const
{
return m_cachedImageInfo.isEqual(srcSubset, destWidth, destHeight) && !m_resizedImage.empty();
}
SkBitmap NativeImageSkia::resizedBitmap(const SkIRect& srcSubset,
int destWidth,
int destHeight,
const SkIRect& destVisibleSubset) const
{
#if PLATFORM(CHROMIUM)
TRACE_EVENT("NativeImageSkia::resizedBitmap", const_cast<NativeImageSkia*>(this), 0);
#endif
if (!hasResizedBitmap(srcSubset, destWidth, destHeight)) {
bool shouldCache = isDataComplete()
&& shouldCacheResampling(srcSubset, destWidth, destHeight, destVisibleSubset);
SkBitmap subset;
m_image.extractSubset(&subset, srcSubset);
if (!shouldCache) {
#if PLATFORM(CHROMIUM)
TRACE_EVENT("nonCachedResize", const_cast<NativeImageSkia*>(this), 0);
#endif
SkBitmap resizedImage = skia::ImageOperations::Resize(subset, skia::ImageOperations::RESIZE_LANCZOS3, destWidth, destHeight, destVisibleSubset);
resizedImage.setImmutable();
return resizedImage;
} else {
#if PLATFORM(CHROMIUM)
TRACE_EVENT("cachedResize", const_cast<NativeImageSkia*>(this), 0);
#endif
m_resizedImage = skia::ImageOperations::Resize(subset, skia::ImageOperations::RESIZE_LANCZOS3, destWidth, destHeight);
}
m_resizedImage.setImmutable();
}
SkBitmap visibleBitmap;
m_resizedImage.extractSubset(&visibleBitmap, destVisibleSubset);
return visibleBitmap;
}
bool NativeImageSkia::shouldCacheResampling(const SkIRect& srcSubset,
int destWidth,
int destHeight,
const SkIRect& destVisibleSubset) const
{
bool matchesPreviousRequest = m_cachedImageInfo.isEqual(srcSubset, destWidth, destHeight);
if (matchesPreviousRequest)
++m_resizeRequests;
else {
m_cachedImageInfo.set(srcSubset, destWidth, destHeight);
m_resizeRequests = 0;
m_resizedImage.reset();
}
if (!isDataComplete())
return false;
static const unsigned long long kLargeBitmapSize = 4096ULL * 4096ULL;
if ((static_cast<unsigned long long>(destWidth) * static_cast<unsigned long long>(destHeight)) > kLargeBitmapSize)
return false;
static const int kSmallBitmapSize = 4096;
if (destWidth * destHeight <= kSmallBitmapSize)
return true;
static const int kManyRequestThreshold = 4;
if (m_resizeRequests >= kManyRequestThreshold)
return true;
int destVisibleSize = destVisibleSubset.width() * destVisibleSubset.height();
return (destVisibleSize > (destWidth * destHeight) / 4);
}
NativeImageSkia::CachedImageInfo::CachedImageInfo()
{
srcSubset.setEmpty();
}
bool NativeImageSkia::CachedImageInfo::isEqual(const SkIRect& otherSrcSubset, int width, int height) const
{
return srcSubset == otherSrcSubset
&& requestSize.width() == width
&& requestSize.height() == height;
}
void NativeImageSkia::CachedImageInfo::set(const SkIRect& otherSrcSubset, int width, int height)
{
srcSubset = otherSrcSubset;
requestSize.setWidth(width);
requestSize.setHeight(height);
}
}