OSDN Git Service

Merge WebKit at r78450: Initial merge by git.
[android-x86/external-webkit.git] / Source / WebCore / svg / SVGFilterElement.cpp
1 /*
2  * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
3  * Copyright (C) 2004, 2005, 2006 Rob Buis <buis@kde.org>
4  * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
5  * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
6  * Copyright (C) Research In Motion Limited 2010. All rights reserved.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public License
19  * along with this library; see the file COPYING.LIB.  If not, write to
20  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  */
23
24 #include "config.h"
25
26 #if ENABLE(SVG) && ENABLE(FILTERS)
27 #include "SVGFilterElement.h"
28
29 #include "Attr.h"
30 #include "RenderSVGResourceFilter.h"
31 #include "SVGFilterBuilder.h"
32 #include "SVGFilterPrimitiveStandardAttributes.h"
33 #include "SVGNames.h"
34 #include "SVGParserUtilities.h"
35 #include "SVGUnitTypes.h"
36
37 namespace WebCore {
38
39 // Animated property definitions
40 DEFINE_ANIMATED_ENUMERATION(SVGFilterElement, SVGNames::filterUnitsAttr, FilterUnits, filterUnits)
41 DEFINE_ANIMATED_ENUMERATION(SVGFilterElement, SVGNames::primitiveUnitsAttr, PrimitiveUnits, primitiveUnits)
42 DEFINE_ANIMATED_LENGTH(SVGFilterElement, SVGNames::xAttr, X, x)
43 DEFINE_ANIMATED_LENGTH(SVGFilterElement, SVGNames::yAttr, Y, y)
44 DEFINE_ANIMATED_LENGTH(SVGFilterElement, SVGNames::widthAttr, Width, width)
45 DEFINE_ANIMATED_LENGTH(SVGFilterElement, SVGNames::heightAttr, Height, height)
46 DEFINE_ANIMATED_INTEGER_MULTIPLE_WRAPPERS(SVGFilterElement, SVGNames::filterResAttr, filterResXIdentifier(), FilterResX, filterResX)
47 DEFINE_ANIMATED_INTEGER_MULTIPLE_WRAPPERS(SVGFilterElement, SVGNames::filterResAttr, filterResYIdentifier(), FilterResY, filterResY)
48 DEFINE_ANIMATED_STRING(SVGFilterElement, XLinkNames::hrefAttr, Href, href)
49 DEFINE_ANIMATED_BOOLEAN(SVGFilterElement, SVGNames::externalResourcesRequiredAttr, ExternalResourcesRequired, externalResourcesRequired)
50
51 inline SVGFilterElement::SVGFilterElement(const QualifiedName& tagName, Document* document)
52     : SVGStyledElement(tagName, document)
53     , SVGURIReference()
54     , SVGLangSpace()
55     , SVGExternalResourcesRequired()
56     , m_filterUnits(SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)
57     , m_primitiveUnits(SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE)
58     , m_x(LengthModeWidth, "-10%")
59     , m_y(LengthModeHeight, "-10%")
60     , m_width(LengthModeWidth, "120%")
61     , m_height(LengthModeHeight, "120%")
62 {
63     // Spec: If the x/y attribute is not specified, the effect is as if a value of "-10%" were specified.
64     // Spec: If the width/height attribute is not specified, the effect is as if a value of "120%" were specified.
65 }
66
67 PassRefPtr<SVGFilterElement> SVGFilterElement::create(const QualifiedName& tagName, Document* document)
68 {
69     return adoptRef(new SVGFilterElement(tagName, document));
70 }
71
72 const AtomicString& SVGFilterElement::filterResXIdentifier()
73 {
74     DEFINE_STATIC_LOCAL(AtomicString, s_identifier, ("SVGFilterResX"));
75     return s_identifier;
76 }
77
78 const AtomicString& SVGFilterElement::filterResYIdentifier()
79 {
80     DEFINE_STATIC_LOCAL(AtomicString, s_identifier, ("SVGFilterResY"));
81     return s_identifier;
82 }
83
84 void SVGFilterElement::setFilterRes(unsigned long filterResX, unsigned long filterResY)
85 {
86     setFilterResXBaseValue(filterResX);
87     setFilterResYBaseValue(filterResY);
88
89     if (RenderObject* object = renderer())
90         object->setNeedsLayout(true);
91 }
92
93 void SVGFilterElement::parseMappedAttribute(Attribute* attr)
94 {
95     const String& value = attr->value();
96     if (attr->name() == SVGNames::filterUnitsAttr) {
97         if (value == "userSpaceOnUse")
98             setFilterUnitsBaseValue(SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE);
99         else if (value == "objectBoundingBox")
100             setFilterUnitsBaseValue(SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
101     } else if (attr->name() == SVGNames::primitiveUnitsAttr) {
102         if (value == "userSpaceOnUse")
103             setPrimitiveUnitsBaseValue(SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE);
104         else if (value == "objectBoundingBox")
105             setPrimitiveUnitsBaseValue(SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
106     } else if (attr->name() == SVGNames::xAttr)
107         setXBaseValue(SVGLength(LengthModeWidth, value));
108     else if (attr->name() == SVGNames::yAttr)
109         setYBaseValue(SVGLength(LengthModeHeight, value));
110     else if (attr->name() == SVGNames::widthAttr)
111         setWidthBaseValue(SVGLength(LengthModeWidth, value));
112     else if (attr->name() == SVGNames::heightAttr)
113         setHeightBaseValue(SVGLength(LengthModeHeight, value));
114     else if (attr->name() == SVGNames::filterResAttr) {
115         float x, y;
116         if (parseNumberOptionalNumber(value, x, y)) {
117             setFilterResXBaseValue(x);
118             setFilterResYBaseValue(y);
119         }
120     } else {
121         if (SVGURIReference::parseMappedAttribute(attr))
122             return;
123         if (SVGLangSpace::parseMappedAttribute(attr))
124             return;
125         if (SVGExternalResourcesRequired::parseMappedAttribute(attr))
126             return;
127
128         SVGStyledElement::parseMappedAttribute(attr);
129     }
130 }
131
132 void SVGFilterElement::svgAttributeChanged(const QualifiedName& attrName)
133 {
134     SVGStyledElement::svgAttributeChanged(attrName);
135
136     bool invalidateClients = false;
137     if (attrName == SVGNames::xAttr
138         || attrName == SVGNames::yAttr
139         || attrName == SVGNames::widthAttr
140         || attrName == SVGNames::heightAttr) {
141         invalidateClients = true;
142         updateRelativeLengthsInformation();
143     }
144
145     RenderObject* object = renderer();
146     if (!object)
147         return;
148
149     if (invalidateClients
150         || attrName == SVGNames::filterUnitsAttr
151         || attrName == SVGNames::primitiveUnitsAttr
152         || attrName == SVGNames::filterResAttr
153         || SVGStyledElement::isKnownAttribute(attrName)
154         || SVGURIReference::isKnownAttribute(attrName)
155         || SVGLangSpace::isKnownAttribute(attrName)
156         || SVGExternalResourcesRequired::isKnownAttribute(attrName))
157         object->setNeedsLayout(true);
158 }
159
160 void SVGFilterElement::synchronizeProperty(const QualifiedName& attrName)
161 {
162     SVGStyledElement::synchronizeProperty(attrName);
163
164     if (attrName == anyQName()) {
165         synchronizeX();
166         synchronizeY();
167         synchronizeWidth();
168         synchronizeHeight();
169         synchronizeFilterUnits();
170         synchronizePrimitiveUnits();
171         synchronizeFilterResX();
172         synchronizeFilterResY();
173         synchronizeExternalResourcesRequired();
174         synchronizeHref();
175         return;
176     }
177
178     if (attrName == SVGNames::xAttr)
179         synchronizeX();
180     else if (attrName == SVGNames::yAttr)
181         synchronizeY();
182     else if (attrName == SVGNames::widthAttr)
183         synchronizeWidth();
184     else if (attrName == SVGNames::heightAttr)
185         synchronizeHeight();
186     else if (attrName == SVGNames::filterUnitsAttr)
187         synchronizeFilterUnits();
188     else if (attrName == SVGNames::primitiveUnitsAttr)
189         synchronizePrimitiveUnits();
190     else if (attrName == SVGNames::filterResAttr) {
191         synchronizeFilterResX();
192         synchronizeFilterResY();
193     } else if (SVGExternalResourcesRequired::isKnownAttribute(attrName))
194         synchronizeExternalResourcesRequired();
195     else if (SVGURIReference::isKnownAttribute(attrName))
196         synchronizeHref();
197 }
198
199 AttributeToPropertyTypeMap& SVGFilterElement::attributeToPropertyTypeMap()
200 {
201     DEFINE_STATIC_LOCAL(AttributeToPropertyTypeMap, s_attributeToPropertyTypeMap, ());
202     return s_attributeToPropertyTypeMap;
203 }
204
205 void SVGFilterElement::fillAttributeToPropertyTypeMap()
206 {
207     AttributeToPropertyTypeMap& attributeToPropertyTypeMap = this->attributeToPropertyTypeMap();
208
209     SVGStyledElement::fillPassedAttributeToPropertyTypeMap(attributeToPropertyTypeMap);
210     attributeToPropertyTypeMap.set(SVGNames::filterUnitsAttr, AnimatedEnumeration);
211     attributeToPropertyTypeMap.set(SVGNames::primitiveUnitsAttr, AnimatedEnumeration);
212     attributeToPropertyTypeMap.set(SVGNames::xAttr, AnimatedLength);
213     attributeToPropertyTypeMap.set(SVGNames::yAttr, AnimatedLength);
214     attributeToPropertyTypeMap.set(SVGNames::widthAttr, AnimatedLength);
215     attributeToPropertyTypeMap.set(SVGNames::heightAttr, AnimatedLength);
216     attributeToPropertyTypeMap.set(SVGNames::filterResAttr, AnimatedNumberOptionalNumber);
217     attributeToPropertyTypeMap.set(XLinkNames::hrefAttr, AnimatedEnumeration);
218 }
219
220 void SVGFilterElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
221 {
222     SVGStyledElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
223
224     if (changedByParser)
225         return;
226
227     if (RenderObject* object = renderer())
228         object->setNeedsLayout(true);
229 }
230
231 FloatRect SVGFilterElement::filterBoundingBox(const FloatRect& objectBoundingBox) const
232 {
233     FloatRect filterBBox;
234     if (filterUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)
235         filterBBox = FloatRect(x().valueAsPercentage() * objectBoundingBox.width() + objectBoundingBox.x(),
236                                y().valueAsPercentage() * objectBoundingBox.height() + objectBoundingBox.y(),
237                                width().valueAsPercentage() * objectBoundingBox.width(),
238                                height().valueAsPercentage() * objectBoundingBox.height());
239     else
240         filterBBox = FloatRect(x().value(this),
241                                y().value(this),
242                                width().value(this),
243                                height().value(this));
244
245     return filterBBox;
246 }
247
248 RenderObject* SVGFilterElement::createRenderer(RenderArena* arena, RenderStyle*)
249 {
250     return new (arena) RenderSVGResourceFilter(this);
251 }
252
253 bool SVGFilterElement::selfHasRelativeLengths() const
254 {
255     return x().isRelative()
256         || y().isRelative()
257         || width().isRelative()
258         || height().isRelative();
259 }
260
261 }
262
263 #endif