#include "config.h"
#include "ImageSource.h"
#if USE(CG)
#include "ImageDecoderCG.h"
#else
#include "ImageDecoder.h"
#endif
#include "ImageOrientation.h"
namespace WebCore {
ImageSource::ImageSource(const NativeImagePtr&)
{
}
ImageSource::ImageSource(ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
: m_needsUpdateMetadata(true)
, m_maximumSubsamplingLevel(Nullopt)
, m_alphaOption(alphaOption)
, m_gammaAndColorProfileOption(gammaAndColorProfileOption)
{
}
ImageSource::~ImageSource()
{
}
void ImageSource::clearFrameBufferCache(size_t clearBeforeFrame)
{
if (!initialized())
return;
m_decoder->clearFrameBufferCache(clearBeforeFrame);
}
void ImageSource::clear(bool destroyAllFrames, size_t clearBeforeFrame, SharedBuffer* data, bool allDataReceived)
{
if (!destroyAllFrames) {
clearFrameBufferCache(clearBeforeFrame);
return;
}
m_decoder = nullptr;
if (data)
setData(data, allDataReceived);
}
void ImageSource::setData(SharedBuffer* data, bool allDataReceived)
{
if (!data)
return;
if (!initialized()) {
m_decoder = ImageDecoder::create(*data, m_alphaOption, m_gammaAndColorProfileOption);
if (!m_decoder)
return;
}
m_decoder->setData(*data, allDataReceived);
}
SubsamplingLevel ImageSource::calculateMaximumSubsamplingLevel() const
{
if (!m_allowSubsampling || !allowSubsamplingOfFrameAtIndex(0))
return 0;
const int maximumImageAreaBeforeSubsampling = 5 * 1024 * 1024;
const SubsamplingLevel maxSubsamplingLevel = 3;
for (SubsamplingLevel level = 0; level < maxSubsamplingLevel; ++level) {
if (frameSizeAtIndex(0, level).area() < maximumImageAreaBeforeSubsampling)
return level;
}
return maxSubsamplingLevel;
}
void ImageSource::updateMetadata()
{
if (!(m_needsUpdateMetadata && isSizeAvailable()))
return;
m_frameCount = m_decoder->frameCount();
if (!m_maximumSubsamplingLevel)
m_maximumSubsamplingLevel = calculateMaximumSubsamplingLevel();
m_needsUpdateMetadata = false;
}
SubsamplingLevel ImageSource::subsamplingLevelForScale(float scale)
{
if (!(scale > 0 && scale <= 1))
return 0;
updateMetadata();
if (!m_maximumSubsamplingLevel)
return 0;
SubsamplingLevel result = std::ceil(std::log2(1 / scale));
return std::min(result, m_maximumSubsamplingLevel.value());
}
size_t ImageSource::bytesDecodedToDetermineProperties()
{
return ImageDecoder::bytesDecodedToDetermineProperties();
}
bool ImageSource::isSizeAvailable() const
{
return initialized() && m_decoder->isSizeAvailable();
}
IntSize ImageSource::size() const
{
return frameSizeAtIndex(0, 0);
}
IntSize ImageSource::sizeRespectingOrientation() const
{
return frameSizeAtIndex(0, 0, RespectImageOrientation);
}
size_t ImageSource::frameCount()
{
updateMetadata();
return m_frameCount;
}
int ImageSource::repetitionCount()
{
return initialized() ? m_decoder->repetitionCount() : cAnimationNone;
}
String ImageSource::filenameExtension() const
{
return initialized() ? m_decoder->filenameExtension() : String();
}
Optional<IntPoint> ImageSource::hotSpot() const
{
return initialized() ? m_decoder->hotSpot() : Nullopt;
}
bool ImageSource::frameIsCompleteAtIndex(size_t index)
{
return initialized() && m_decoder->frameIsCompleteAtIndex(index);
}
bool ImageSource::frameHasAlphaAtIndex(size_t index)
{
return !initialized() || m_decoder->frameHasAlphaAtIndex(index);
}
bool ImageSource::allowSubsamplingOfFrameAtIndex(size_t index) const
{
return initialized() && m_decoder->allowSubsamplingOfFrameAtIndex(index);
}
IntSize ImageSource::frameSizeAtIndex(size_t index, SubsamplingLevel subsamplingLevel, RespectImageOrientationEnum shouldRespectImageOrientation) const
{
if (!initialized())
return { };
IntSize size = m_decoder->frameSizeAtIndex(index, subsamplingLevel);
if (shouldRespectImageOrientation != RespectImageOrientation)
return size;
return orientationAtIndex(index).usesWidthAsHeight() ? size.transposedSize() : size;
}
unsigned ImageSource::frameBytesAtIndex(size_t index, SubsamplingLevel subsamplingLevel) const
{
return frameSizeAtIndex(index, subsamplingLevel).area() * 4;
}
float ImageSource::frameDurationAtIndex(size_t index)
{
return initialized() ? m_decoder->frameDurationAtIndex(index) : 0;
}
ImageOrientation ImageSource::orientationAtIndex(size_t index) const
{
return initialized() ? m_decoder->orientationAtIndex(index) : ImageOrientation();
}
NativeImagePtr ImageSource::createFrameImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel)
{
return initialized() ? m_decoder->createFrameImageAtIndex(index, subsamplingLevel) : nullptr;
}
void ImageSource::dump(TextStream& ts) const
{
if (m_allowSubsampling)
ts.dumpProperty("allow-subsampling", m_allowSubsampling);
ImageOrientation orientation = orientationAtIndex(0);
if (orientation != OriginTopLeft)
ts.dumpProperty("orientation", orientation);
}
}