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