1dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block/*
2dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
368513a70bcd92384395513322f1b801e7bf9c729Steve Block * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
468513a70bcd92384395513322f1b801e7bf9c729Steve Block * Copyright (C) 2005 Eric Seidel <eric@webkit.org>
568513a70bcd92384395513322f1b801e7bf9c729Steve Block * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
6dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * Copyright (C) Research In Motion Limited 2010. All rights reserved.
7dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block *
8dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * This library is free software; you can redistribute it and/or
9dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * modify it under the terms of the GNU Library General Public
10dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * License as published by the Free Software Foundation; either
11dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * version 2 of the License, or (at your option) any later version.
12dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block *
13dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * This library is distributed in the hope that it will be useful,
14dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * but WITHOUT ANY WARRANTY; without even the implied warranty of
15dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * Library General Public License for more details.
17dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block *
18dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * You should have received a copy of the GNU Library General Public License
19dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * along with this library; see the file COPYING.LIB.  If not, write to
20dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * Boston, MA 02110-1301, USA.
22dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block */
23dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
24dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "config.h"
25dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
26dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#if ENABLE(SVG) && ENABLE(FILTERS)
27dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "RenderSVGResourceFilter.h"
28dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
29dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "AffineTransform.h"
3054cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block#include "FilterEffect.h"
31dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "FloatPoint.h"
32dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "FloatRect.h"
33dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "GraphicsContext.h"
34dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "Image.h"
35dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "ImageBuffer.h"
36dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "ImageData.h"
37dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "IntRect.h"
38dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "RenderSVGResource.h"
39e14391e94c850b8bd03680c23b38978db68687a8John Reck#include "RenderSVGResourceFilterPrimitive.h"
40dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "SVGElement.h"
41dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "SVGFilter.h"
42dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "SVGFilterElement.h"
43dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "SVGFilterPrimitiveStandardAttributes.h"
44a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "SVGImageBufferTools.h"
45f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include "SVGNames.h"
46dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "SVGStyledElement.h"
47dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "SVGUnitTypes.h"
4865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
4921939df44de1705786c545cd1bf519d47250322dBen Murdoch#include <wtf/UnusedParam.h>
5065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#include <wtf/Vector.h>
51dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
52dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockusing namespace std;
53dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
54dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocknamespace WebCore {
55dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
56dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockRenderSVGResourceType RenderSVGResourceFilter::s_resourceType = FilterResourceType;
57dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
5821939df44de1705786c545cd1bf519d47250322dBen MurdochRenderSVGResourceFilter::RenderSVGResourceFilter(SVGFilterElement* node)
5921939df44de1705786c545cd1bf519d47250322dBen Murdoch    : RenderSVGResourceContainer(node)
60dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
61dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
62dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
63dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockRenderSVGResourceFilter::~RenderSVGResourceFilter()
64dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
65db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    if (m_filter.isEmpty())
66db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block        return;
67db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block
68dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    deleteAllValues(m_filter);
69dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    m_filter.clear();
70dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
71dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
72f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrickvoid RenderSVGResourceFilter::removeAllClientsFromCache(bool markForInvalidation)
73dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
74db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    if (!m_filter.isEmpty()) {
75db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block        deleteAllValues(m_filter);
76db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block        m_filter.clear();
77db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    }
78967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch
79f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    markAllClientsForInvalidation(markForInvalidation ? LayoutAndBoundariesInvalidation : ParentOnlyInvalidation);
80dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
81dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
82f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrickvoid RenderSVGResourceFilter::removeClientFromCache(RenderObject* client, bool markForInvalidation)
83dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
84db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    ASSERT(client);
85db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block
8654cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block    if (FilterData* filterData = m_filter.get(client)) {
8754cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block        if (filterData->savedContext)
8854cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block            filterData->markedForRemoval = true;
8954cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block        else
9054cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block            delete m_filter.take(client);
9154cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block    }
92dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
93f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    markClientForInvalidation(client, markForInvalidation ? BoundariesInvalidation : ParentOnlyInvalidation);
94dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
95dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
964576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) WangPassRefPtr<SVGFilterBuilder> RenderSVGResourceFilter::buildPrimitives(Filter* filter)
97dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
98dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    SVGFilterElement* filterElement = static_cast<SVGFilterElement*>(node());
99dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    bool primitiveBoundingBoxMode = filterElement->primitiveUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX;
100dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
101dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    // Add effects to the builder
1024576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    RefPtr<SVGFilterBuilder> builder = SVGFilterBuilder::create(filter);
103dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    for (Node* node = filterElement->firstChild(); node; node = node->nextSibling()) {
104dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (!node->isSVGElement())
105dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            continue;
106dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
107dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        SVGElement* element = static_cast<SVGElement*>(node);
108dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (!element->isFilterEffect())
109dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            continue;
110dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
111dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        SVGFilterPrimitiveStandardAttributes* effectElement = static_cast<SVGFilterPrimitiveStandardAttributes*>(element);
1124576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        RefPtr<FilterEffect> effect = effectElement->build(builder.get(), filter);
113dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (!effect) {
114dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            builder->clearEffects();
115dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            return 0;
116dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
1172fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        builder->appendEffectToEffectReferences(effect, effectElement->renderer());
118dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        effectElement->setStandardAttributes(primitiveBoundingBoxMode, effect.get());
119dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        builder->add(effectElement->result(), effect);
120dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
121dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return builder.release();
122dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
123dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
124dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockbool RenderSVGResourceFilter::fitsInMaximumImageSize(const FloatSize& size, FloatSize& scale)
125dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
126dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    bool matchesFilterSize = true;
127dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (size.width() > kMaxFilterSize) {
128dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        scale.setWidth(scale.width() * kMaxFilterSize / size.width());
129dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        matchesFilterSize = false;
130dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
131dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (size.height() > kMaxFilterSize) {
132dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        scale.setHeight(scale.height() * kMaxFilterSize / size.height());
133dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        matchesFilterSize = false;
134dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
135dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
136dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return matchesFilterSize;
137dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
138dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
13921939df44de1705786c545cd1bf519d47250322dBen Murdochbool RenderSVGResourceFilter::applyResource(RenderObject* object, RenderStyle*, GraphicsContext*& context, unsigned short resourceMode)
140dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
141dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    ASSERT(object);
142dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    ASSERT(context);
14321939df44de1705786c545cd1bf519d47250322dBen Murdoch#ifndef NDEBUG
14421939df44de1705786c545cd1bf519d47250322dBen Murdoch    ASSERT(resourceMode == ApplyToDefaultMode);
14521939df44de1705786c545cd1bf519d47250322dBen Murdoch#else
14621939df44de1705786c545cd1bf519d47250322dBen Murdoch    UNUSED_PARAM(resourceMode);
14721939df44de1705786c545cd1bf519d47250322dBen Murdoch#endif
148dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
149dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    // Returning false here, to avoid drawings onto the context. We just want to
150dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    // draw the stored filter output, not the unfiltered object as well.
151dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (m_filter.contains(object)) {
152dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        FilterData* filterData = m_filter.get(object);
153dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (filterData->builded)
154dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            return false;
155dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
156dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        delete m_filter.take(object); // Oops, have to rebuild, go through normal code path
157dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
158dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
159dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    OwnPtr<FilterData> filterData(new FilterData);
160a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    FloatRect targetBoundingBox = object->objectBoundingBox();
161a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
162a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    SVGFilterElement* filterElement = static_cast<SVGFilterElement*>(node());
163a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    filterData->boundaries = filterElement->filterBoundingBox(targetBoundingBox);
164a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (filterData->boundaries.isEmpty())
165a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return false;
166a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
167a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // Determine absolute transformation matrix for filter.
168a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    AffineTransform absoluteTransform;
169a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    SVGImageBufferTools::calculateTransformationToOutermostSVGCoordinateSystem(object, absoluteTransform);
170a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (!absoluteTransform.isInvertible())
171a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return false;
172a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
173a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // Eliminate shear of the absolute transformation matrix, to be able to produce unsheared tile images for feTile.
174a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    filterData->shearFreeAbsoluteTransform = AffineTransform(absoluteTransform.xScale(), 0, 0, absoluteTransform.yScale(), absoluteTransform.e(), absoluteTransform.f());
175a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
176a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // Determine absolute boundaries of the filter and the drawing region.
177a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    FloatRect absoluteFilterBoundaries = filterData->shearFreeAbsoluteTransform.mapRect(filterData->boundaries);
178a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    FloatRect drawingRegion = object->strokeBoundingBox();
179a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    drawingRegion.intersect(filterData->boundaries);
180a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    FloatRect absoluteDrawingRegion = filterData->shearFreeAbsoluteTransform.mapRect(drawingRegion);
181a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
182a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // Create the SVGFilter object.
183a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    bool primitiveBoundingBoxMode = filterElement->primitiveUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX;
184a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    filterData->filter = SVGFilter::create(filterData->shearFreeAbsoluteTransform, absoluteDrawingRegion, targetBoundingBox, filterData->boundaries, primitiveBoundingBoxMode);
185a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
186a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // Create all relevant filter primitives.
1874576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    filterData->builder = buildPrimitives(filterData->filter.get());
188dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (!filterData->builder)
189dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return false;
190dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
191dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    // Calculate the scale factor for the use of filterRes.
192dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    // Also see http://www.w3.org/TR/SVG/filters.html#FilterEffectsRegion
193a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    FloatSize scale(1, 1);
194dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (filterElement->hasAttribute(SVGNames::filterResAttr)) {
195a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        scale.setWidth(filterElement->filterResX() / absoluteFilterBoundaries.width());
196a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        scale.setHeight(filterElement->filterResY() / absoluteFilterBoundaries.height());
197dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
198dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
199dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (scale.isEmpty())
200dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return false;
201dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
202a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // Determine scale factor for filter. The size of intermediate ImageBuffers shouldn't be bigger than kMaxFilterSize.
203a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    FloatRect tempSourceRect = absoluteDrawingRegion;
204dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    tempSourceRect.scale(scale.width(), scale.height());
205dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    fitsInMaximumImageSize(tempSourceRect.size(), scale);
206dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
207a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // Set the scale level in SVGFilter.
208dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    filterData->filter->setFilterResolution(scale);
209dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
210dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    FilterEffect* lastEffect = filterData->builder->lastEffect();
211dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (!lastEffect)
212dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return false;
213a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
2142fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    RenderSVGResourceFilterPrimitive::determineFilterPrimitiveSubregion(lastEffect);
215e14391e94c850b8bd03680c23b38978db68687a8John Reck    FloatRect subRegion = lastEffect->maxEffectRect();
216e14391e94c850b8bd03680c23b38978db68687a8John Reck    // At least one FilterEffect has a too big image size,
217e14391e94c850b8bd03680c23b38978db68687a8John Reck    // recalculate the effect sizes with new scale factors.
218e14391e94c850b8bd03680c23b38978db68687a8John Reck    if (!fitsInMaximumImageSize(subRegion.size(), scale)) {
219dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        filterData->filter->setFilterResolution(scale);
2202fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        RenderSVGResourceFilterPrimitive::determineFilterPrimitiveSubregion(lastEffect);
221dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
222dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
223a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // If the drawingRegion is empty, we have something like <g filter=".."/>.
224a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // Even if the target objectBoundingBox() is empty, we still have to draw the last effect result image in postApplyResource.
225a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (drawingRegion.isEmpty()) {
226a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ASSERT(!m_filter.contains(object));
227a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        filterData->savedContext = context;
228a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        m_filter.set(object, filterData.leakPtr());
229dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return false;
230a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
231dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
232a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    absoluteDrawingRegion.scale(scale.width(), scale.height());
233a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
234a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    OwnPtr<ImageBuffer> sourceGraphic;
2354576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    if (!SVGImageBufferTools::createImageBuffer(absoluteDrawingRegion, absoluteDrawingRegion, sourceGraphic, ColorSpaceLinearRGB)) {
2364576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        ASSERT(!m_filter.contains(object));
2374576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        filterData->savedContext = context;
2384576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        m_filter.set(object, filterData.leakPtr());
239a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return false;
2404576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    }
241a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
242dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    GraphicsContext* sourceGraphicContext = sourceGraphic->context();
243a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(sourceGraphicContext);
244a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
245a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    sourceGraphicContext->translate(-absoluteDrawingRegion.x(), -absoluteDrawingRegion.y());
246a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (scale.width() != 1 || scale.height() != 1)
247a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        sourceGraphicContext->scale(scale);
248a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
249a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    sourceGraphicContext->concatCTM(filterData->shearFreeAbsoluteTransform);
250a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    sourceGraphicContext->clearRect(FloatRect(FloatPoint(), absoluteDrawingRegion.size()));
251e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    filterData->sourceGraphicBuffer = sourceGraphic.release();
2525af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    filterData->savedContext = context;
253dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
254dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    context = sourceGraphicContext;
255e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
256e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    ASSERT(!m_filter.contains(object));
257e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    m_filter.set(object, filterData.leakPtr());
258dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
259dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return true;
260dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
261dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
262f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid RenderSVGResourceFilter::postApplyResource(RenderObject* object, GraphicsContext*& context, unsigned short resourceMode, const Path*)
263dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
264dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    ASSERT(object);
265dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    ASSERT(context);
26621939df44de1705786c545cd1bf519d47250322dBen Murdoch#ifndef NDEBUG
26721939df44de1705786c545cd1bf519d47250322dBen Murdoch    ASSERT(resourceMode == ApplyToDefaultMode);
26821939df44de1705786c545cd1bf519d47250322dBen Murdoch#else
26921939df44de1705786c545cd1bf519d47250322dBen Murdoch    UNUSED_PARAM(resourceMode);
27021939df44de1705786c545cd1bf519d47250322dBen Murdoch#endif
271dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
27254cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block    FilterData* filterData = m_filter.get(object);
27354cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block    if (!filterData)
274dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return;
275dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
27654cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block    if (filterData->markedForRemoval) {
27754cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block        delete m_filter.take(object);
27854cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block        return;
27954cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block    }
28054cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block
281dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (!filterData->builded) {
2825af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        if (!filterData->savedContext) {
283f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick            removeClientFromCache(object);
284dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            return;
285dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
286dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2875af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        context = filterData->savedContext;
2885af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        filterData->savedContext = 0;
2892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#if !USE(CG)
290a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (filterData->sourceGraphicBuffer)
291a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            filterData->sourceGraphicBuffer->transformColorSpace(ColorSpaceDeviceRGB, ColorSpaceLinearRGB);
292dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#endif
293dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
294dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
295dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    FilterEffect* lastEffect = filterData->builder->lastEffect();
296dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
29768513a70bcd92384395513322f1b801e7bf9c729Steve Block    if (lastEffect && !filterData->boundaries.isEmpty() && !lastEffect->filterPrimitiveSubregion().isEmpty()) {
298dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        // This is the real filtering of the object. It just needs to be called on the
299dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        // initial filtering process. We just take the stored filter result on a
300dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        // second drawing.
3012fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        if (!filterData->builded)
3025af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke            filterData->filter->setSourceImage(filterData->sourceGraphicBuffer.release());
3032fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3042fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        // Always true if filterData is just built (filterData->builded is false).
3052fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        if (!lastEffect->hasResult()) {
3064576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang            lastEffect->apply();
3072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#if !USE(CG)
308f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            ImageBuffer* resultImage = lastEffect->asImageBuffer();
3095ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            if (resultImage)
310a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                resultImage->transformColorSpace(ColorSpaceLinearRGB, ColorSpaceDeviceRGB);
3115ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen#endif
312dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
3132fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        filterData->builded = true;
314dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
315f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        ImageBuffer* resultImage = lastEffect->asImageBuffer();
316a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (resultImage) {
317a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            context->concatCTM(filterData->shearFreeAbsoluteTransform.inverse());
318dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
319a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            context->scale(FloatSize(1 / filterData->filter->filterResolution().width(), 1 / filterData->filter->filterResolution().height()));
320a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            context->clip(lastEffect->maxEffectRect());
321a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            context->drawImageBuffer(resultImage, object->style()->colorSpace(), lastEffect->absolutePaintRect());
322a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            context->scale(filterData->filter->filterResolution());
323a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
324a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            context->concatCTM(filterData->shearFreeAbsoluteTransform);
325a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        }
326a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
3275af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    filterData->sourceGraphicBuffer.clear();
328dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
329dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
330545e470e52f0ac6a3a072bf559c796b42c6066b6Ben MurdochFloatRect RenderSVGResourceFilter::resourceBoundingBox(RenderObject* object)
331dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
332dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (SVGFilterElement* element = static_cast<SVGFilterElement*>(node()))
333545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch        return element->filterBoundingBox(object->objectBoundingBox());
334dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
335dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return FloatRect();
336dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
337dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
3382fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockvoid RenderSVGResourceFilter::primitiveAttributeChanged(RenderObject* object, const QualifiedName& attribute)
3392fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
3402fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    HashMap<RenderObject*, FilterData*>::iterator it = m_filter.begin();
3412fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    HashMap<RenderObject*, FilterData*>::iterator end = m_filter.end();
3422fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    SVGFilterPrimitiveStandardAttributes* primitve = static_cast<SVGFilterPrimitiveStandardAttributes*>(object->node());
3432fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3442fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    for (; it != end; ++it) {
3452fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        FilterData* filterData = it->second;
3462fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        if (!filterData->builded)
3472fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            continue;
3482fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3492fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        SVGFilterBuilder* builder = filterData->builder.get();
3502fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        FilterEffect* effect = builder->effectByRenderer(object);
3512fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        if (!effect)
3522fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            continue;
3532fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        // Since all effects shares the same attribute value, all
3542fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        // or none of them will be changed.
3552fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        if (!primitve->setFilterEffectAttribute(effect, attribute))
3562fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            return;
3572fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        builder->clearResultsRecursive(effect);
3582fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3592fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        // Repaint the image on the screen.
3602fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        markClientForInvalidation(it->first, RepaintInvalidation);
3612fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    }
3622fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
3632fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
364dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
365dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#endif
366