15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2005 Eric Seidel <eric@webkit.org>
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2010 Dirk Schulze <krit@webkit.org>
653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * Copyright (C) 2013 Google Inc. All rights reserved.
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is free software; you can redistribute it and/or
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modify it under the terms of the GNU Library General Public
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * License as published by the Free Software Foundation; either
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * version 2 of the License, or (at your option) any later version.
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is distributed in the hope that it will be useful,
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * but WITHOUT ANY WARRANTY; without even the implied warranty of
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Library General Public License for more details.
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * You should have received a copy of the GNU Library General Public License
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * along with this library; see the file COPYING.LIB.  If not, write to
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Boston, MA 02110-1301, USA.
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/svg/graphics/filters/SVGFEImage.h"
2753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
2893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#include "SkBitmapSource.h"
2909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "SkPictureImageFilter.h"
3053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderObject.h"
3153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/SVGRenderingContext.h"
32f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)#include "core/svg/SVGElement.h"
3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/svg/SVGURIReference.h"
3409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "platform/graphics/DisplayList.h"
35a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/GraphicsContext.h"
36a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/filters/Filter.h"
3709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "platform/graphics/filters/SkiaImageFilterBuilder.h"
381e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/text/TextStream.h"
391e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/transforms/AffineTransform.h"
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
41c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)FEImage::FEImage(Filter* filter, PassRefPtr<Image> image, PassRefPtr<SVGPreserveAspectRatio> preserveAspectRatio)
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : FilterEffect(filter)
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_image(image)
4610f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    , m_treeScope(0)
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_preserveAspectRatio(preserveAspectRatio)
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5110f88d5669dbd969c059d61ba09fa37dd72ac559Ben MurdochFEImage::FEImage(Filter* filter, TreeScope& treeScope, const String& href, PassRefPtr<SVGPreserveAspectRatio> preserveAspectRatio)
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : FilterEffect(filter)
5310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    , m_treeScope(&treeScope)
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_href(href)
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_preserveAspectRatio(preserveAspectRatio)
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)PassRefPtr<FEImage> FEImage::createWithImage(Filter* filter, PassRefPtr<Image> image, PassRefPtr<SVGPreserveAspectRatio> preserveAspectRatio)
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return adoptRef(new FEImage(filter, image, preserveAspectRatio));
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6410f88d5669dbd969c059d61ba09fa37dd72ac559Ben MurdochPassRefPtr<FEImage> FEImage::createWithIRIReference(Filter* filter, TreeScope& treeScope, const String& href, PassRefPtr<SVGPreserveAspectRatio> preserveAspectRatio)
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6610f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    return adoptRef(new FEImage(filter, treeScope, href, preserveAspectRatio));
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)static FloatRect getRendererRepaintRect(RenderObject* renderer)
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
7109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return renderer->localToParentTransform().mapRect(
725d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        renderer->paintInvalidationRectInLocalCoordinates());
7309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
757242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano TucciAffineTransform makeMapBetweenRects(const FloatRect& source, const FloatRect& dest)
767242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{
777242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    AffineTransform transform;
787242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    transform.translate(dest.x() - source.x(), dest.y() - source.y());
797242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    transform.scale(dest.width() / source.width(), dest.height() / source.height());
807242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    return transform;
817242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci}
827242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
8309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)FloatRect FEImage::determineAbsolutePaintRect(const FloatRect& originalRequestedRect)
8409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
8509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    RenderObject* renderer = referencedRenderer();
8609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (!m_image && !renderer)
8709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return FloatRect();
8809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
8909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    FloatRect requestedRect = originalRequestedRect;
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (clipsToBounds())
9109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        requestedRect.intersect(maxEffectRect());
9209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
9309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    FloatRect destRect = filter()->mapLocalRectToAbsoluteRect(filterPrimitiveSubregion());
9409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    FloatRect srcRect;
9509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (renderer) {
9609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        srcRect = getRendererRepaintRect(renderer);
9709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        SVGElement* contextNode = toSVGElement(renderer->node());
9809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
9909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        if (contextNode->hasRelativeLengths()) {
10009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            // FIXME: This fixes relative lengths but breaks non-relative ones (see crbug/260709).
10109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            SVGLengthContext lengthContext(contextNode);
10209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            FloatSize viewportSize;
10309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            if (lengthContext.determineViewport(viewportSize)) {
10409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)                srcRect = makeMapBetweenRects(FloatRect(FloatPoint(), viewportSize), destRect).mapRect(srcRect);
10509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            }
10609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        } else {
10709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            srcRect = filter()->mapLocalRectToAbsoluteRect(srcRect);
10809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            srcRect.move(destRect.x(), destRect.y());
10909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        }
11009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        destRect.intersect(srcRect);
11109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    } else {
11209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        srcRect = FloatRect(FloatPoint(), m_image->size());
11309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        m_preserveAspectRatio->transformRect(destRect, srcRect);
11409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
11509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
11609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    destRect.intersect(requestedRect);
11709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    addAbsolutePaintRect(destRect);
11809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return destRect;
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)RenderObject* FEImage::referencedRenderer() const
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
12310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    if (!m_treeScope)
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
12510f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    Element* hrefElement = SVGURIReference::targetElementFromIRIString(m_href, *m_treeScope);
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!hrefElement || !hrefElement->isSVGElement())
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return hrefElement->renderer();
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void FEImage::applySoftware()
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderObject* renderer = referencedRenderer();
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!m_image && !renderer)
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ImageBuffer* resultImage = createImageBufferResult();
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!resultImage)
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    IntPoint paintLocation = absolutePaintRect().location();
14109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    resultImage->context()->translate(-paintLocation.x(), -paintLocation.y());
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
143926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // FEImage results are always in ColorSpaceDeviceRGB
144926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    setResultColorSpace(ColorSpaceDeviceRGB);
145926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
14609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    FloatRect destRect = filter()->mapLocalRectToAbsoluteRect(filterPrimitiveSubregion());
14709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    FloatRect srcRect;
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (!renderer) {
15009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        srcRect = FloatRect(FloatPoint(), m_image->size());
15109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        m_preserveAspectRatio->transformRect(destRect, srcRect);
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        resultImage->context()->drawImage(m_image.get(), destRect, srcRect);
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    SVGElement* contextNode = toSVGElement(renderer->node());
15809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (contextNode->hasRelativeLengths()) {
15909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        // FIXME: This fixes relative lengths but breaks non-relative ones (see crbug/260709).
16009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        SVGLengthContext lengthContext(contextNode);
16109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        FloatSize viewportSize;
16209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
16309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        // If we're referencing an element with percentage units, eg. <rect with="30%"> those values were resolved against the viewport.
16409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        // Build up a transformation that maps from the viewport space to the filter primitive subregion.
16509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        if (lengthContext.determineViewport(viewportSize))
16609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            resultImage->context()->concatCTM(makeMapBetweenRects(FloatRect(FloatPoint(), viewportSize), destRect));
16709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    } else {
16809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        resultImage->context()->translate(destRect.x(), destRect.y());
16909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        resultImage->context()->concatCTM(filter()->absoluteTransform());
17009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
17109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
17209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    AffineTransform contentTransformation;
17309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    SVGRenderingContext::renderSubtree(resultImage->context(), renderer, contentTransformation);
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)TextStream& FEImage::externalRepresentation(TextStream& ts, int indent) const
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    IntSize imageSize;
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_image)
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        imageSize = m_image->size();
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (RenderObject* renderer = referencedRenderer())
18209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        imageSize = enclosingIntRect(getRendererRepaintRect(renderer)).size();
1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    writeIndent(ts, indent);
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ts << "[feImage";
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FilterEffect::externalRepresentation(ts);
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ts << " image-size=\"" << imageSize.width() << "x" << imageSize.height() << "\"]\n";
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // FIXME: should this dump also object returned by SVGFEImage::image() ?
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return ts;
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
19109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)PassRefPtr<SkImageFilter> FEImage::createImageFilterForRenderer(RenderObject* renderer, SkiaImageFilterBuilder* builder)
19209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
19309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    FloatRect dstRect = filterPrimitiveSubregion();
19409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
19509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    AffineTransform transform;
19609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    SVGElement* contextNode = toSVGElement(renderer->node());
19709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
19809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (contextNode->hasRelativeLengths()) {
19909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        SVGLengthContext lengthContext(contextNode);
20009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        FloatSize viewportSize;
20109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
20209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        // If we're referencing an element with percentage units, eg. <rect with="30%"> those values were resolved against the viewport.
20309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        // Build up a transformation that maps from the viewport space to the filter primitive subregion.
20409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        if (lengthContext.determineViewport(viewportSize))
20509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            transform = makeMapBetweenRects(FloatRect(FloatPoint(), viewportSize), dstRect);
20609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    } else {
20709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        transform.translate(dstRect.x(), dstRect.y());
20809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
20909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
21009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    GraphicsContext* context = builder->context();
21109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (!context)
21210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch        return adoptRef(SkBitmapSource::Create(SkBitmap()));
21309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    AffineTransform contentTransformation;
2147242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    FloatRect bounds(FloatPoint(), dstRect.size());
21509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    context->save();
2167242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    context->beginRecording(bounds);
21709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    context->concatCTM(transform);
21809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    SVGRenderingContext::renderSubtree(context, renderer, contentTransformation);
21909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    RefPtr<DisplayList> displayList = context->endRecording();
22009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    context->restore();
22110f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    RefPtr<SkImageFilter> result = adoptRef(SkPictureImageFilter::Create(displayList->picture(), dstRect));
22209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return result.release();
22309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
22409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
2253c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben MurdochPassRefPtr<SkImageFilter> FEImage::createImageFilter(SkiaImageFilterBuilder* builder)
22693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles){
22709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    RenderObject* renderer = referencedRenderer();
22809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (!m_image && !renderer)
22910f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch        return adoptRef(SkBitmapSource::Create(SkBitmap()));
23009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
23109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    setOperatingColorSpace(ColorSpaceDeviceRGB);
23209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
23309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (renderer)
23409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return createImageFilterForRenderer(renderer, builder);
23509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
23609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    FloatRect srcRect = FloatRect(FloatPoint(), m_image->size());
23709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    FloatRect dstRect = filterPrimitiveSubregion();
23809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
23909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // FIXME: CSS image filters currently do not seem to set filter primitive
24009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // subregion correctly if unspecified. So default to srcRect size if so.
24109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (dstRect.isEmpty())
24209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        dstRect = srcRect;
24309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
24409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    m_preserveAspectRatio->transformRect(dstRect, srcRect);
24593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
24693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    if (!m_image->nativeImageForCurrentFrame())
24710f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch        return adoptRef(SkBitmapSource::Create(SkBitmap()));
24893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
24910f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    RefPtr<SkImageFilter> result = adoptRef(SkBitmapSource::Create(m_image->nativeImageForCurrentFrame()->bitmap(), srcRect, dstRect));
25009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return result.release();
25193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)}
2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
253c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink
254