#include "config.h"
#include "Image.h"
#include "FloatRect.h"
#include "GraphicsContext.h"
#include <cairo.h>
#include <math.h>
Vector<char> loadResourceIntoArray(const char*);
namespace WebCore {
void FrameData::clear()
{
if (m_frame) {
cairo_surface_destroy(m_frame);
m_frame = 0;
m_duration = 0.;
m_hasAlpha = true;
}
}
void Image::initNativeData()
{
}
void Image::destroyNativeData()
{
}
void Image::invalidateNativeData()
{
}
Image* Image::loadResource(const char *name)
{
Vector<char> arr = loadResourceIntoArray(name);
Image* img = new Image;
img->setNativeData(&arr, true);
return img;
}
bool Image::supportsType(const String& type)
{
return false;
}
static void setCompositingOperation(cairo_t* context, CompositeOperator op, bool hasAlpha)
{
if (op == CompositeSourceOver && !hasAlpha)
op = CompositeCopy;
if (op == CompositeCopy)
cairo_set_operator(context, CAIRO_OPERATOR_SOURCE);
else
cairo_set_operator(context, CAIRO_OPERATOR_OVER);
}
void Image::checkForSolidColor()
{
m_isSolidColor = false;
}
void Image::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatRect& src, CompositeOperator op)
{
cairo_t* context = ctxt->platformContext();
if (!m_source.initialized())
return;
cairo_surface_t* image = frameAtIndex(m_currentFrame);
if (!image) return;
IntSize selfSize = size();
FloatRect srcRect(src);
FloatRect dstRect(dst);
cairo_save(context);
setCompositingOperation(context, op, frameHasAlphaAtIndex(m_currentFrame));
cairo_pattern_t* pattern = cairo_pattern_create_for_surface(image);
float scaleX = srcRect.width() / dstRect.width();
float scaleY = srcRect.height() / dstRect.height();
cairo_matrix_t mat = { scaleX, 0, 0 , scaleY, srcRect.x(), srcRect.y() };
cairo_pattern_set_matrix(pattern, &mat);
cairo_translate(context, dstRect.x(), dstRect.y());
cairo_set_source(context, pattern);
cairo_rectangle(context, 0, 0, dstRect.width(), dstRect.height());
cairo_fill(context);
cairo_restore(context);
startAnimation();
}
void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& dstRect, const FloatPoint& srcPoint,
const FloatSize& tileSize, CompositeOperator op)
{
if (!m_source.initialized())
return;
cairo_surface_t* image = frameAtIndex(m_currentFrame);
if (!image) return;
IntSize intrinsicImageSize = size();
FloatRect srcRect(srcPoint, intrinsicImageSize);
FloatPoint point = srcPoint;
float tileWidth = size().width();
float tileHeight = size().height();
float scaleX = 1.0;
float scaleY = 1.0;
cairo_matrix_t mat;
cairo_matrix_init_identity(&mat);
if (tileSize.width() != intrinsicImageSize.width() || tileSize.height() != intrinsicImageSize.height()) {
scaleX = intrinsicImageSize.width() / tileSize.width();
scaleY = intrinsicImageSize.height() / tileSize.height();
cairo_matrix_init_scale(&mat, scaleX, scaleY);
tileWidth = tileSize.width();
tileHeight = tileSize.height();
}
float dstTileX = dstRect.x() + fmodf(fmodf(-point.x(), tileWidth) - tileWidth, tileWidth);
float dstTileY = dstRect.y() + fmodf(fmodf(-point.y(), tileHeight) - tileHeight, tileHeight);
FloatRect dstTileRect(dstTileX, dstTileY, tileWidth, tileHeight);
float srcX = dstRect.x() - dstTileRect.x();
float srcY = dstRect.y() - dstTileRect.y();
if (dstTileRect.contains(dstRect)) {
draw(ctxt, dstRect,
FloatRect(srcX * scaleX, srcY * scaleY, dstRect.width() * scaleX, dstRect.height() * scaleY), op);
return;
}
cairo_t* context = ctxt->platformContext();
cairo_save(context);
setCompositingOperation(context, op, frameHasAlphaAtIndex(m_currentFrame));
cairo_translate(context, dstTileRect.x(), dstTileRect.y());
cairo_pattern_t* pattern = cairo_pattern_create_for_surface(image);
cairo_pattern_set_matrix(pattern, &mat);
cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
cairo_set_source(context, pattern);
cairo_rectangle(context, srcX, srcY, dstRect.width(), dstRect.height());
cairo_fill(context);
cairo_restore(context);
startAnimation();
}
}