15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.  All rights reserved.
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * are met:
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 1. Redistributions of source code must retain the above copyright
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    notice, this list of conditions and the following disclaimer.
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    notice, this list of conditions and the following disclaimer in the
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    documentation and/or other materials provided with the distribution.
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
245267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
2853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/platform/graphics/Image.h"
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/platform/Length.h"
3153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/platform/MIMETypeRegistry.h"
3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/platform/SharedBuffer.h"
33f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)#include "core/platform/chromium/TraceEvent.h"
3453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/platform/graphics/BitmapImage.h"
35f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)#include "core/platform/graphics/FloatPoint.h"
36f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)#include "core/platform/graphics/FloatRect.h"
37f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)#include "core/platform/graphics/FloatSize.h"
3853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/platform/graphics/GraphicsContext.h"
39e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch#include "core/platform/graphics/GraphicsContextStateSaver.h"
40e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch#include "core/platform/graphics/GraphicsTypes.h"
4153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/platform/graphics/IntRect.h"
42f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)#include "public/platform/Platform.h"
43f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)#include "public/platform/WebData.h"
445267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#include "wtf/MainThread.h"
455267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#include "wtf/StdLibExtras.h"
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
47f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)#include <math.h>
48f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore {
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Image::Image(ImageObserver* observer)
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : m_imageObserver(observer)
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Image::~Image()
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Image* Image::nullImage()
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(isMainThread());
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    DEFINE_STATIC_LOCAL(RefPtr<Image>, nullImage, (BitmapImage::create()));;
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return nullImage.get();
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
67f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)PassRefPtr<Image> Image::loadPlatformResource(const char *name)
68f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles){
69f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    const WebKit::WebData& resource = WebKit::Platform::current()->loadResource(name);
70f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    if (resource.isEmpty())
71f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        return Image::nullImage();
72f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)
73f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    RefPtr<Image> image = BitmapImage::create();
74f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    image->setData(resource, true);
75f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    return image.release();
76f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)}
77f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool Image::supportsType(const String& type)
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
805267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    return MIMETypeRegistry::isSupportedImageResourceMIMEType(type);
815267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)}
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool Image::setData(PassRefPtr<SharedBuffer> data, bool allDataReceived)
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
85926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    m_encodedImageData = data;
86926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!m_encodedImageData.get())
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
89926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    int length = m_encodedImageData->size();
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!length)
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
925267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return dataChanged(allDataReceived);
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
965267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)void Image::fillWithSolidColor(GraphicsContext* ctxt, const FloatRect& dstRect, const Color& color, CompositeOperator op)
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!color.alpha())
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1005267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    CompositeOperator previousOperator = ctxt->compositeOperation();
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ctxt->setCompositeOperation(!color.hasAlpha() && op == CompositeSourceOver ? CompositeCopy : op);
1035267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    ctxt->fillRect(dstRect, color);
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ctxt->setCompositeOperation(previousOperator);
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)FloatRect Image::adjustForNegativeSize(const FloatRect& rect)
10893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles){
10993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    FloatRect norm = rect;
11093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    if (norm.width() < 0) {
11193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        norm.setX(norm.x() + norm.width());
11293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        norm.setWidth(-norm.width());
11393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    }
11493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    if (norm.height() < 0) {
11593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        norm.setY(norm.y() + norm.height());
11693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        norm.setHeight(-norm.height());
11793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    }
11893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    return norm;
11993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)}
12093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
1215267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)void Image::draw(GraphicsContext* ctx, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator op, BlendMode blendMode, RespectImageOrientationEnum)
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1235267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    draw(ctx, dstRect, srcRect, op, blendMode);
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1265267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& destRect, const FloatPoint& srcPoint, const FloatSize& scaledTileSize, CompositeOperator op, BlendMode blendMode)
1275267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (mayFillWithSolidColor()) {
1295267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        fillWithSolidColor(ctxt, destRect, solidColor(), op);
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // See <https://webkit.org/b/59043>.
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(!isBitmapImage() || notSolidColor());
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatSize intrinsicTileSize = size();
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (hasRelativeWidth())
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        intrinsicTileSize.setWidth(scaledTileSize.width());
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (hasRelativeHeight())
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        intrinsicTileSize.setHeight(scaledTileSize.height());
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatSize scale(scaledTileSize.width() / intrinsicTileSize.width(),
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    scaledTileSize.height() / intrinsicTileSize.height());
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatRect oneTileRect;
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    oneTileRect.setX(destRect.x() + fmodf(fmodf(-srcPoint.x(), scaledTileSize.width()) - scaledTileSize.width(), scaledTileSize.width()));
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    oneTileRect.setY(destRect.y() + fmodf(fmodf(-srcPoint.y(), scaledTileSize.height()) - scaledTileSize.height(), scaledTileSize.height()));
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    oneTileRect.setSize(scaledTileSize);
1495267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
1505267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    // Check and see if a single draw of the image can cover the entire area we are supposed to tile.
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (oneTileRect.contains(destRect)) {
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        FloatRect visibleSrcRect;
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        visibleSrcRect.setX((destRect.x() - oneTileRect.x()) / scale.width());
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        visibleSrcRect.setY((destRect.y() - oneTileRect.y()) / scale.height());
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        visibleSrcRect.setWidth(destRect.width() / scale.width());
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        visibleSrcRect.setHeight(destRect.height() / scale.height());
1575267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        draw(ctxt, destRect, visibleSrcRect, op, blendMode);
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1615267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    FloatRect tileRect(FloatPoint(), intrinsicTileSize);
162521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    drawPattern(ctxt, tileRect, scale, oneTileRect.location(), op, destRect, blendMode);
1635267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    startAnimation();
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// FIXME: Merge with the other drawTiled eventually, since we need a combination of both for some things.
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& dstRect, const FloatRect& srcRect,
169e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    const FloatSize& providedTileScaleFactor, TileRule hRule, TileRule vRule, CompositeOperator op)
1705267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (mayFillWithSolidColor()) {
1725267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        fillWithSolidColor(ctxt, dstRect, solidColor(), op);
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1755267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
176e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    // FIXME: We do not support 'space' yet. For now just map it to 'repeat'.
177e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    if (hRule == SpaceTile)
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        hRule = RepeatTile;
179e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    if (vRule == SpaceTile)
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        vRule = RepeatTile;
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
182e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    // FIXME: if this code is used for background-repeat: round (in addition to
183e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    // border-image-repeat), then add logic to deal with the background-size: auto
184e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    // special case. The aspect ratio should be maintained in this case.
185e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    FloatSize tileScaleFactor = providedTileScaleFactor;
186e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    bool useLowInterpolationQuality = false;
187e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    if (hRule == RoundTile) {
188e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        float hRepetitions = std::max(1.0f, roundf(dstRect.width() / (tileScaleFactor.width() * srcRect.width())));
189e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        tileScaleFactor.setWidth(dstRect.width() / (srcRect.width() * hRepetitions));
190e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    }
191e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    if (vRule == RoundTile) {
192e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        float vRepetitions = std::max(1.0f, roundf(dstRect.height() / (tileScaleFactor.height() * srcRect.height())));
193e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        tileScaleFactor.setHeight(dstRect.height() / (srcRect.height() * vRepetitions));
194e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    }
195e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    if (hRule == RoundTile || vRule == RoundTile) {
196e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        // High interpolation quality rounds the scaled tile to an integer size (see Image::drawPattern).
197e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        // To avoid causing a visual problem, linear interpolation must be used instead.
198e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        // FIXME: Allow using high-quality interpolation in this case, too.
199e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        useLowInterpolationQuality = true;
200e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    }
201e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // We want to construct the phase such that the pattern is centered (when stretch is not
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // set for a particular rule).
2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float hPhase = tileScaleFactor.width() * srcRect.x();
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float vPhase = tileScaleFactor.height() * srcRect.y();
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float scaledTileWidth = tileScaleFactor.width() * srcRect.width();
2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float scaledTileHeight = tileScaleFactor.height() * srcRect.height();
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (hRule == Image::RepeatTile)
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        hPhase -= (dstRect.width() - scaledTileWidth) / 2;
2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (vRule == Image::RepeatTile)
2115267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        vPhase -= (dstRect.height() - scaledTileHeight) / 2;
2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatPoint patternPhase(dstRect.x() - hPhase, dstRect.y() - vPhase);
2135267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
214e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    if (useLowInterpolationQuality) {
215e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        InterpolationQuality previousInterpolationQuality = ctxt->imageInterpolationQuality();
216e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        ctxt->setImageInterpolationQuality(InterpolationLow);
217e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        drawPattern(ctxt, srcRect, tileScaleFactor, patternPhase, op, dstRect);
218e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        ctxt->setImageInterpolationQuality(previousInterpolationQuality);
219e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    } else {
220e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        drawPattern(ctxt, srcRect, tileScaleFactor, patternPhase, op, dstRect);
221e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    }
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    startAnimation();
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
226f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)void Image::drawPattern(GraphicsContext* context, const FloatRect& floatSrcRect, const FloatSize& scale,
227f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    const FloatPoint& phase, CompositeOperator compositeOp, const FloatRect& destRect, BlendMode blendMode)
228f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles){
229f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    TRACE_EVENT0("skia", "Image::drawPattern");
230f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    if (RefPtr<NativeImageSkia> bitmap = nativeImageForCurrentFrame())
231f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        bitmap->drawPattern(context, adjustForNegativeSize(floatSrcRect), scale, phase, compositeOp, destRect, blendMode);
232f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)}
233f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void Image::computeIntrinsicDimensions(Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio)
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    intrinsicRatio = size();
2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    intrinsicWidth = Length(intrinsicRatio.width(), Fixed);
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    intrinsicHeight = Length(intrinsicRatio.height(), Fixed);
2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
242