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"
28a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/Image.h"
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
30bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)#include "platform/Length.h"
3151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#include "platform/MIMETypeRegistry.h"
321e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/SharedBuffer.h"
331e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/TraceEvent.h"
341e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/geometry/FloatPoint.h"
351e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/geometry/FloatRect.h"
361e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/geometry/FloatSize.h"
37a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/BitmapImage.h"
38a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/GraphicsContext.h"
39a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/GraphicsContextStateSaver.h"
40f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)#include "public/platform/Platform.h"
41f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)#include "public/platform/WebData.h"
425267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#include "wtf/MainThread.h"
435267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#include "wtf/StdLibExtras.h"
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
45f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)#include <math.h>
46f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore {
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Image::Image(ImageObserver* observer)
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : m_imageObserver(observer)
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Image::~Image()
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Image* Image::nullImage()
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(isMainThread());
6151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    DEFINE_STATIC_REF(Image, nullImage, (BitmapImage::create()));
6251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    return nullImage;
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
65f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)PassRefPtr<Image> Image::loadPlatformResource(const char *name)
66f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles){
6751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    const blink::WebData& resource = blink::Platform::current()->loadResource(name);
68f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    if (resource.isEmpty())
69f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        return Image::nullImage();
70f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)
71f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    RefPtr<Image> image = BitmapImage::create();
72f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    image->setData(resource, true);
73f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    return image.release();
74f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)}
75f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool Image::supportsType(const String& type)
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
785267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    return MIMETypeRegistry::isSupportedImageResourceMIMEType(type);
795267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)}
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool Image::setData(PassRefPtr<SharedBuffer> data, bool allDataReceived)
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
83926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    m_encodedImageData = data;
84926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!m_encodedImageData.get())
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
87926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    int length = m_encodedImageData->size();
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!length)
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
905267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return dataChanged(allDataReceived);
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
945267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)void Image::fillWithSolidColor(GraphicsContext* ctxt, const FloatRect& dstRect, const Color& color, CompositeOperator op)
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!color.alpha())
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
985267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    CompositeOperator previousOperator = ctxt->compositeOperation();
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ctxt->setCompositeOperation(!color.hasAlpha() && op == CompositeSourceOver ? CompositeCopy : op);
1015267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    ctxt->fillRect(dstRect, color);
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ctxt->setCompositeOperation(previousOperator);
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)FloatRect Image::adjustForNegativeSize(const FloatRect& rect)
10693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles){
10793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    FloatRect norm = rect;
10893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    if (norm.width() < 0) {
10993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        norm.setX(norm.x() + norm.width());
11093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        norm.setWidth(-norm.width());
11193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    }
11293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    if (norm.height() < 0) {
11393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        norm.setY(norm.y() + norm.height());
11493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        norm.setHeight(-norm.height());
11593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    }
11693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    return norm;
11793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)}
11893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
119a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)void Image::draw(GraphicsContext* ctx, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator op, blink::WebBlendMode blendMode, RespectImageOrientationEnum)
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1215267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    draw(ctx, dstRect, srcRect, op, blendMode);
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
124a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& destRect, const FloatPoint& srcPoint, const FloatSize& scaledTileSize, CompositeOperator op, blink::WebBlendMode blendMode, const IntSize& repeatSpacing)
1255267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (mayFillWithSolidColor()) {
1275267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        fillWithSolidColor(ctxt, destRect, solidColor(), op);
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // See <https://webkit.org/b/59043>.
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(!isBitmapImage() || notSolidColor());
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatSize intrinsicTileSize = size();
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (hasRelativeWidth())
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        intrinsicTileSize.setWidth(scaledTileSize.width());
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (hasRelativeHeight())
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        intrinsicTileSize.setHeight(scaledTileSize.height());
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatSize scale(scaledTileSize.width() / intrinsicTileSize.width(),
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    scaledTileSize.height() / intrinsicTileSize.height());
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1431e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    FloatSize actualTileSize(scaledTileSize.width() + repeatSpacing.width(), scaledTileSize.height() + repeatSpacing.height());
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatRect oneTileRect;
1451e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    oneTileRect.setX(destRect.x() + fmodf(fmodf(-srcPoint.x(), actualTileSize.width()) - actualTileSize.width(), actualTileSize.width()));
1461e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    oneTileRect.setY(destRect.y() + fmodf(fmodf(-srcPoint.y(), actualTileSize.height()) - actualTileSize.height(), actualTileSize.height()));
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    oneTileRect.setSize(scaledTileSize);
1485267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
1495267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    // Check and see if a single draw of the image can cover the entire area we are supposed to tile.
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (oneTileRect.contains(destRect)) {
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        FloatRect visibleSrcRect;
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        visibleSrcRect.setX((destRect.x() - oneTileRect.x()) / scale.width());
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        visibleSrcRect.setY((destRect.y() - oneTileRect.y()) / scale.height());
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        visibleSrcRect.setWidth(destRect.width() / scale.width());
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        visibleSrcRect.setHeight(destRect.height() / scale.height());
1565267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        draw(ctxt, destRect, visibleSrcRect, op, blendMode);
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1605267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    FloatRect tileRect(FloatPoint(), intrinsicTileSize);
1611e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    drawPattern(ctxt, tileRect, scale, oneTileRect.location(), op, destRect, blendMode, repeatSpacing);
1625267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    startAnimation();
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// FIXME: Merge with the other drawTiled eventually, since we need a combination of both for some things.
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& dstRect, const FloatRect& srcRect,
168e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    const FloatSize& providedTileScaleFactor, TileRule hRule, TileRule vRule, CompositeOperator op)
1695267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (mayFillWithSolidColor()) {
1715267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        fillWithSolidColor(ctxt, dstRect, solidColor(), op);
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1745267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
175e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    // FIXME: We do not support 'space' yet. For now just map it to 'repeat'.
176e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    if (hRule == SpaceTile)
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        hRule = RepeatTile;
178e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    if (vRule == SpaceTile)
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        vRule = RepeatTile;
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
181e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    // FIXME: if this code is used for background-repeat: round (in addition to
182e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    // border-image-repeat), then add logic to deal with the background-size: auto
183e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    // special case. The aspect ratio should be maintained in this case.
184e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    FloatSize tileScaleFactor = providedTileScaleFactor;
185e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    bool useLowInterpolationQuality = false;
186e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    if (hRule == RoundTile) {
187e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        float hRepetitions = std::max(1.0f, roundf(dstRect.width() / (tileScaleFactor.width() * srcRect.width())));
188e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        tileScaleFactor.setWidth(dstRect.width() / (srcRect.width() * hRepetitions));
189e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    }
190e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    if (vRule == RoundTile) {
191e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        float vRepetitions = std::max(1.0f, roundf(dstRect.height() / (tileScaleFactor.height() * srcRect.height())));
192e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        tileScaleFactor.setHeight(dstRect.height() / (srcRect.height() * vRepetitions));
193e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    }
194e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    if (hRule == RoundTile || vRule == RoundTile) {
195e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        // High interpolation quality rounds the scaled tile to an integer size (see Image::drawPattern).
196e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        // To avoid causing a visual problem, linear interpolation must be used instead.
197e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        // FIXME: Allow using high-quality interpolation in this case, too.
198e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        useLowInterpolationQuality = true;
199e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    }
200e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // We want to construct the phase such that the pattern is centered (when stretch is not
2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // set for a particular rule).
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float hPhase = tileScaleFactor.width() * srcRect.x();
2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float vPhase = tileScaleFactor.height() * srcRect.y();
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float scaledTileWidth = tileScaleFactor.width() * srcRect.width();
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float scaledTileHeight = tileScaleFactor.height() * srcRect.height();
2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (hRule == Image::RepeatTile)
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        hPhase -= (dstRect.width() - scaledTileWidth) / 2;
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (vRule == Image::RepeatTile)
2105267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        vPhase -= (dstRect.height() - scaledTileHeight) / 2;
2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatPoint patternPhase(dstRect.x() - hPhase, dstRect.y() - vPhase);
2125267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
213e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    if (useLowInterpolationQuality) {
214e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        InterpolationQuality previousInterpolationQuality = ctxt->imageInterpolationQuality();
215e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        ctxt->setImageInterpolationQuality(InterpolationLow);
216e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        drawPattern(ctxt, srcRect, tileScaleFactor, patternPhase, op, dstRect);
217e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        ctxt->setImageInterpolationQuality(previousInterpolationQuality);
218e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    } else {
219e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        drawPattern(ctxt, srcRect, tileScaleFactor, patternPhase, op, dstRect);
220e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    }
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    startAnimation();
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
225f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)void Image::drawPattern(GraphicsContext* context, const FloatRect& floatSrcRect, const FloatSize& scale,
226a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    const FloatPoint& phase, CompositeOperator compositeOp, const FloatRect& destRect, blink::WebBlendMode blendMode, const IntSize& repeatSpacing)
227f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles){
228f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    TRACE_EVENT0("skia", "Image::drawPattern");
229f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    if (RefPtr<NativeImageSkia> bitmap = nativeImageForCurrentFrame())
2301e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        bitmap->drawPattern(context, adjustForNegativeSize(floatSrcRect), scale, phase, compositeOp, destRect, blendMode, repeatSpacing);
231f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)}
232f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void Image::computeIntrinsicDimensions(Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio)
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    intrinsicRatio = size();
2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    intrinsicWidth = Length(intrinsicRatio.width(), Fixed);
2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    intrinsicHeight = Length(intrinsicRatio.height(), Fixed);
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
241