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) 2009 Dirk Schulze <krit@webkit.org>
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) Research In Motion Limited 2010. 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/rendering/svg/RenderSVGResourceFilter.h"
2753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
28197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "core/dom/ElementTraversal.h"
2909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "core/frame/Settings.h"
30e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch#include "core/rendering/svg/RenderSVGResourceFilterPrimitive.h"
3153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/SVGRenderingContext.h"
3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/svg/SVGFilterPrimitiveStandardAttributes.h"
33a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/UnacceleratedImageBufferSurface.h"
3409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "platform/graphics/filters/SkiaImageFilterBuilder.h"
35a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/filters/SourceAlpha.h"
36a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/filters/SourceGraphic.h"
375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
38c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
40f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)const RenderSVGResourceType RenderSVGResourceFilter::s_resourceType = FilterResourceType;
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)RenderSVGResourceFilter::RenderSVGResourceFilter(SVGFilterElement* node)
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : RenderSVGResourceContainer(node)
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)RenderSVGResourceFilter::~RenderSVGResourceFilter()
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
49e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)}
50e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)
51e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)void RenderSVGResourceFilter::destroy()
52e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles){
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_filter.clear();
54e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    RenderSVGResourceContainer::destroy();
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)bool RenderSVGResourceFilter::isChildAllowed(RenderObject* child, RenderStyle*) const
5809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
5909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return child->isSVGResourceFilterPrimitive();
6009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
6109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderSVGResourceFilter::removeAllClientsFromCache(bool markForInvalidation)
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
641e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    m_filter.clear();
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    markAllClientsForInvalidation(markForInvalidation ? LayoutAndBoundariesInvalidation : ParentOnlyInvalidation);
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderSVGResourceFilter::removeClientFromCache(RenderObject* client, bool markForInvalidation)
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(client);
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
727242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    m_filter.remove(client);
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    markClientForInvalidation(client, markForInvalidation ? BoundariesInvalidation : ParentOnlyInvalidation);
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<SVGFilterBuilder> RenderSVGResourceFilter::buildPrimitives(SVGFilter* filter)
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
798abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    SVGFilterElement* filterElement = toSVGFilterElement(element());
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatRect targetBoundingBox = filter->targetBoundingBox();
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Add effects to the builder
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<SVGFilterBuilder> builder = SVGFilterBuilder::create(SourceGraphic::create(filter), SourceAlpha::create(filter));
84d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    for (SVGElement* element = Traversal<SVGElement>::firstChild(*filterElement); element; element = Traversal<SVGElement>::nextSibling(*element)) {
855267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        if (!element->isFilterEffect() || !element->renderer())
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            continue;
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        SVGFilterPrimitiveStandardAttributes* effectElement = static_cast<SVGFilterPrimitiveStandardAttributes*>(element);
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RefPtr<FilterEffect> effect = effectElement->build(builder.get(), filter);
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!effect) {
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            builder->clearEffects();
92d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            return nullptr;
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        builder->appendEffectToEffectReferences(effect, effectElement->renderer());
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        effectElement->setStandardAttributes(effect.get());
96d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        effect->setEffectBoundaries(SVGLengthContext::resolveRectangle<SVGFilterPrimitiveStandardAttributes>(effectElement, filterElement->primitiveUnits()->currentValue()->enumValue(), targetBoundingBox));
97926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        effect->setOperatingColorSpace(
98197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            effectElement->renderer()->style()->svgStyle().colorInterpolationFilters() == CI_LINEARRGB ? ColorSpaceLinearRGB : ColorSpaceDeviceRGB);
9909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        builder->add(AtomicString(effectElement->result()->currentValue()->value()), effect);
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return builder.release();
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
104c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)static void beginDeferredFilter(GraphicsContext* context, FilterData* filterData)
105c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){
106c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    context->beginRecording(filterData->boundaries);
107697ef0c10ac944be8499480c025020e4c282c980Ben Murdoch    context->setShouldSmoothFonts(false);
108c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    // We pass the boundaries to SkPictureImageFilter so it knows the
109c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    // world-space position of the filter primitives. It gets them
110c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    // from the DisplayList, which also applies the inverse translate
111c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    // to the origin. So we apply the forward translate here to avoid
112c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    // it being applied twice.
113c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    // FIXME: we should fix SkPicture to handle this offset itself, or
114c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    // make the translate optional on SkPictureImageFilter.
115c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    // See https://code.google.com/p/skia/issues/detail?id=2801
116c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    context->translate(filterData->boundaries.x(), filterData->boundaries.y());
117c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}
118c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
119c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)static void endDeferredFilter(GraphicsContext* context, FilterData* filterData)
120c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){
121c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    // FIXME: maybe filterData should just hold onto SourceGraphic after creation?
122c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    SourceGraphic* sourceGraphic = static_cast<SourceGraphic*>(filterData->builder->getEffectById(SourceGraphic::effectName()));
123c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    ASSERT(sourceGraphic);
124c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    sourceGraphic->setDisplayList(context->endRecording());
125c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}
126c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
127c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)static void drawDeferredFilter(GraphicsContext* context, FilterData* filterData, SVGFilterElement* filterElement)
128f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu{
129f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    SkiaImageFilterBuilder builder(context);
130c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    SourceGraphic* sourceGraphic = static_cast<SourceGraphic*>(filterData->builder->getEffectById(SourceGraphic::effectName()));
131c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    ASSERT(sourceGraphic);
132c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    builder.setSourceGraphic(sourceGraphic);
133f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    RefPtr<ImageFilter> imageFilter = builder.build(filterData->builder->lastEffect(), ColorSpaceDeviceRGB);
1347242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    FloatRect boundaries = filterData->boundaries;
135f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    context->save();
136c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
137c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    FloatSize deviceSize = context->getCTM().mapSize(boundaries.size());
138c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    float scaledArea = deviceSize.width() * deviceSize.height();
13976c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)
14076c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)    // If area of scaled size is bigger than the upper limit, adjust the scale
141c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    // to fit. Note that this only really matters in the non-impl-side painting
142c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    // case, since the impl-side case never allocates a full-sized backing
143c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    // store, only tile-sized.
144c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    // FIXME: remove this once all platforms are using impl-side painting.
145c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    // crbug.com/169282.
14676c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)    if (scaledArea > FilterEffect::maxFilterArea()) {
14776c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)        float scale = sqrtf(FilterEffect::maxFilterArea() / scaledArea);
14876c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)        context->scale(scale, scale);
14976c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)    }
1507242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // Clip drawing of filtered image to the minimum required paint rect.
1517242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    FilterEffect* lastEffect = filterData->builder->lastEffect();
1527242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    context->clipRect(lastEffect->determineAbsolutePaintRect(lastEffect->maxEffectRect()));
153f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    if (filterElement->hasAttribute(SVGNames::filterResAttr)) {
154f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        // Get boundaries in device coords.
1555d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        // FIXME: See crbug.com/382491. Is the use of getCTM OK here, given it does not include device
1565d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        // zoom or High DPI adjustments?
157f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        FloatSize size = context->getCTM().mapSize(boundaries.size());
158f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        // Compute the scale amount required so that the resulting offscreen is exactly filterResX by filterResY pixels.
1595d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        float filterResScaleX = filterElement->filterResX()->currentValue()->value() / size.width();
1605d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        float filterResScaleY = filterElement->filterResY()->currentValue()->value() / size.height();
161f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        // Scale the CTM so the primitive is drawn to filterRes.
1625d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        context->scale(filterResScaleX, filterResScaleY);
163f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        // Create a resize filter with the inverse scale.
164f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        AffineTransform resizeMatrix;
1655d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        resizeMatrix.scale(1 / filterResScaleX, 1 / filterResScaleY);
166f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        imageFilter = builder.buildTransform(resizeMatrix, imageFilter.get());
167f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    }
168f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    // If the CTM contains rotation or shearing, apply the filter to
169f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    // the unsheared/unrotated matrix, and do the shearing/rotation
170f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    // as a final pass.
171f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    AffineTransform ctm = context->getCTM();
172f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    if (ctm.b() || ctm.c()) {
173f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        AffineTransform scaleAndTranslate;
174f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        scaleAndTranslate.translate(ctm.e(), ctm.f());
175f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        scaleAndTranslate.scale(ctm.xScale(), ctm.yScale());
176f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        ASSERT(scaleAndTranslate.isInvertible());
177f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        AffineTransform shearAndRotate = scaleAndTranslate.inverse();
178f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        shearAndRotate.multiply(ctm);
179f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        context->setCTM(scaleAndTranslate);
180f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        imageFilter = builder.buildTransform(shearAndRotate, imageFilter.get());
181f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    }
182f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    context->beginLayer(1, CompositeSourceOver, &boundaries, ColorFilterNone, imageFilter.get());
183f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    context->endLayer();
184f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    context->restore();
185f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu}
186f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool RenderSVGResourceFilter::applyResource(RenderObject* object, RenderStyle*, GraphicsContext*& context, unsigned short resourceMode)
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(object);
1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(context);
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT_UNUSED(resourceMode, resourceMode == ApplyToDefaultMode);
1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
19351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    clearInvalidationMask();
19451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
195f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    if (m_filter.contains(object)) {
1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        FilterData* filterData = m_filter.get(object);
1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (filterData->state == FilterData::PaintingSource || filterData->state == FilterData::Applying)
1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            filterData->state = FilterData::CycleDetected;
1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false; // Already built, or we're in a cycle, or we're marked for removal. Regardless, just do nothing more now.
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OwnPtr<FilterData> filterData(adoptPtr(new FilterData));
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatRect targetBoundingBox = object->objectBoundingBox();
2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2058abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    SVGFilterElement* filterElement = toSVGFilterElement(element());
206d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    filterData->boundaries = SVGLengthContext::resolveRectangle<SVGFilterElement>(filterElement, filterElement->filterUnits()->currentValue()->enumValue(), targetBoundingBox);
2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (filterData->boundaries.isEmpty())
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
210926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    filterData->drawingRegion = object->strokeBoundingBox();
211926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    filterData->drawingRegion.intersect(filterData->boundaries);
2127242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    IntRect intDrawingRegion = enclosingIntRect(filterData->drawingRegion);
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Create the SVGFilter object.
215d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    bool primitiveBoundingBoxMode = filterElement->primitiveUnits()->currentValue()->enumValue() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX;
2167242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    filterData->filter = SVGFilter::create(intDrawingRegion, targetBoundingBox, filterData->boundaries, primitiveBoundingBoxMode);
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Create all relevant filter primitives.
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    filterData->builder = buildPrimitives(filterData->filter.get());
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!filterData->builder)
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FilterEffect* lastEffect = filterData->builder->lastEffect();
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!lastEffect)
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
227a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    lastEffect->determineFilterPrimitiveSubregion(ClipToFilterRegion);
22809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
2297242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    FilterData* data = filterData.get();
2301e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    m_filter.set(object, filterData.release());
2317242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    beginDeferredFilter(context, data);
2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2357242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccivoid RenderSVGResourceFilter::postApplyResource(RenderObject* object, GraphicsContext*& context)
2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(object);
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(context);
2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FilterData* filterData = m_filter.get(object);
2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!filterData)
2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch (filterData->state) {
2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case FilterData::CycleDetected:
2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case FilterData::Applying:
2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // We have a cycle if we are already applying the data.
2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // This can occur due to FeImage referencing a source that makes use of the FEImage itself.
2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // This is the first place we've hit the cycle, so set the state back to PaintingSource so the return stack
2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // will continue correctly.
2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        filterData->state = FilterData::PaintingSource;
2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case FilterData::PaintingSource:
2557242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        endDeferredFilter(context, filterData);
2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case FilterData::Built: { } // Empty
2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2617242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    drawDeferredFilter(context, filterData, toSVGFilterElement(element()));
2627242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    filterData->state = FilterData::Built;
2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
26509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)FloatRect RenderSVGResourceFilter::resourceBoundingBox(const RenderObject* object)
2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2678abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    if (SVGFilterElement* element = toSVGFilterElement(this->element()))
268d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return SVGLengthContext::resolveRectangle<SVGFilterElement>(element, element->filterUnits()->currentValue()->enumValue(), object->objectBoundingBox());
2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return FloatRect();
2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderSVGResourceFilter::primitiveAttributeChanged(RenderObject* object, const QualifiedName& attribute)
2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2751e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    FilterMap::iterator it = m_filter.begin();
2761e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    FilterMap::iterator end = m_filter.end();
2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SVGFilterPrimitiveStandardAttributes* primitve = static_cast<SVGFilterPrimitiveStandardAttributes*>(object->node());
2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (; it != end; ++it) {
2801e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        FilterData* filterData = it->value.get();
2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (filterData->state != FilterData::Built)
2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            continue;
2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        SVGFilterBuilder* builder = filterData->builder.get();
2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        FilterEffect* effect = builder->effectByRenderer(object);
2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!effect)
2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            continue;
2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Since all effects shares the same attribute value, all
2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // or none of them will be changed.
2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!primitve->setFilterEffectAttribute(effect, attribute))
2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return;
2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        builder->clearResultsRecursive(effect);
2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
294e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        // Issue paint invalidations for the image on the screen.
295e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        markClientForInvalidation(it->key, PaintInvalidation);
2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
297926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    markAllClientLayersForInvalidation();
298926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
299926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
300926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)FloatRect RenderSVGResourceFilter::drawingRegion(RenderObject* object) const
301926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
302926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    FilterData* filterData = m_filter.get(object);
303926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return filterData ? filterData->drawingRegion : FloatRect();
3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
307