BitmapImageCairo.cpp [plain text]
#include "config.h"
#include "BitmapImage.h"
#if USE(CAIRO)
#include "CairoUtilities.h"
#include "ImageObserver.h"
#include "PlatformContextCairo.h"
#include "Timer.h"
#include <cairo.h>
namespace WebCore {
namespace NativeImage {
IntSize size(const RefPtr<cairo_surface_t>& image)
{
return cairoSurfaceSize(image.get());
}
bool hasAlpha(const RefPtr<cairo_surface_t>& image)
{
return cairo_surface_get_content(image.get()) != CAIRO_CONTENT_COLOR;
}
Color singlePixelSolidColor(const RefPtr<cairo_surface_t>& image)
{
ASSERT(image);
if (NativeImage::size(image) != IntSize(1, 1))
return Color();
if (cairo_surface_get_type(image.get()) != CAIRO_SURFACE_TYPE_IMAGE)
return Color();
RGBA32* pixel = reinterpret_cast_ptr<RGBA32*>(cairo_image_surface_get_data(image.get()));
return colorFromPremultipliedARGB(*pixel);
}
}
void BitmapImage::draw(GraphicsContext& context, const FloatRect& dst, const FloatRect& src, CompositeOperator op,
BlendMode blendMode, ImageOrientationDescription description)
{
if (!dst.width() || !dst.height() || !src.width() || !src.height())
return;
startAnimation();
auto surface = frameImageAtIndex(m_currentFrame);
if (!surface) return;
Color color = singlePixelSolidColor();
if (color.isValid()) {
fillWithSolidColor(context, dst, color, op);
return;
}
context.save();
if (op == CompositeSourceOver && blendMode == BlendModeNormal && !frameHasAlphaAtIndex(m_currentFrame))
context.setCompositeOperation(CompositeCopy);
else
context.setCompositeOperation(op, blendMode);
#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
IntSize scaledSize = cairoSurfaceSize(surface.get());
FloatRect adjustedSrcRect = adjustSourceRectForDownSampling(src, scaledSize);
#else
FloatRect adjustedSrcRect(src);
#endif
ImageOrientation frameOrientation(description.imageOrientation());
if (description.respectImageOrientation() == RespectImageOrientation)
frameOrientation = frameOrientationAtIndex(m_currentFrame);
FloatRect dstRect = dst;
if (frameOrientation != DefaultImageOrientation) {
context.translate(dstRect.x(), dstRect.y());
dstRect.setLocation(FloatPoint());
context.concatCTM(frameOrientation.transformFromDefault(dstRect.size()));
if (frameOrientation.usesWidthAsHeight()) {
dstRect = FloatRect(dstRect.x(), dstRect.y(), dstRect.height(), dstRect.width());
}
}
context.platformContext()->drawSurfaceToContext(surface.get(), dstRect, adjustedSrcRect, context);
context.restore();
if (imageObserver())
imageObserver()->didDraw(this);
}
bool FrameData::clear(bool clearMetadata)
{
if (clearMetadata)
m_haveMetadata = false;
if (m_image) {
m_image = nullptr;
return true;
}
return false;
}
}
#endif // USE(CAIRO)