Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / 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 #include "core/svg/SVGFilterElement.h"
27
28 #include "XLinkNames.h"
29 #include "core/rendering/svg/RenderSVGResourceFilter.h"
30 #include "core/svg/SVGElementInstance.h"
31 #include "core/svg/SVGParserUtilities.h"
32
33 namespace WebCore {
34
35 // Animated property definitions
36 DEFINE_ANIMATED_ENUMERATION(SVGFilterElement, SVGNames::filterUnitsAttr, FilterUnits, filterUnits, SVGUnitTypes::SVGUnitType)
37 DEFINE_ANIMATED_ENUMERATION(SVGFilterElement, SVGNames::primitiveUnitsAttr, PrimitiveUnits, primitiveUnits, SVGUnitTypes::SVGUnitType)
38
39 BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGFilterElement)
40     REGISTER_LOCAL_ANIMATED_PROPERTY(filterUnits)
41     REGISTER_LOCAL_ANIMATED_PROPERTY(primitiveUnits)
42 END_REGISTER_ANIMATED_PROPERTIES
43
44 inline SVGFilterElement::SVGFilterElement(Document& document)
45     : SVGElement(SVGNames::filterTag, document)
46     , SVGURIReference(this)
47     , m_x(SVGAnimatedLength::create(this, SVGNames::xAttr, SVGLength::create(LengthModeWidth)))
48     , m_y(SVGAnimatedLength::create(this, SVGNames::yAttr, SVGLength::create(LengthModeHeight)))
49     , m_width(SVGAnimatedLength::create(this, SVGNames::widthAttr, SVGLength::create(LengthModeWidth)))
50     , m_height(SVGAnimatedLength::create(this, SVGNames::heightAttr, SVGLength::create(LengthModeHeight)))
51     , m_filterRes(SVGAnimatedIntegerOptionalInteger::create(this, SVGNames::filterResAttr))
52     , m_filterUnits(SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)
53     , m_primitiveUnits(SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE)
54 {
55     ScriptWrappable::init(this);
56
57     // Spec: If the x/y attribute is not specified, the effect is as if a value of "-10%" were specified.
58     // Spec: If the width/height attribute is not specified, the effect is as if a value of "120%" were specified.
59     m_x->setDefaultValueAsString("-10%");
60     m_y->setDefaultValueAsString("-10%");
61     m_width->setDefaultValueAsString("120%");
62     m_height->setDefaultValueAsString("120%");
63
64     addToPropertyMap(m_x);
65     addToPropertyMap(m_y);
66     addToPropertyMap(m_width);
67     addToPropertyMap(m_height);
68     addToPropertyMap(m_filterRes);
69     registerAnimatedPropertiesForSVGFilterElement();
70 }
71
72 PassRefPtr<SVGFilterElement> SVGFilterElement::create(Document& document)
73 {
74     return adoptRef(new SVGFilterElement(document));
75 }
76
77 void SVGFilterElement::setFilterRes(unsigned x, unsigned y)
78 {
79     filterResX()->baseValue()->setValue(x);
80     filterResY()->baseValue()->setValue(y);
81
82     invalidateSVGAttributes();
83     svgAttributeChanged(SVGNames::filterResAttr);
84 }
85
86 bool SVGFilterElement::isSupportedAttribute(const QualifiedName& attrName)
87 {
88     DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
89     if (supportedAttributes.isEmpty()) {
90         SVGURIReference::addSupportedAttributes(supportedAttributes);
91         supportedAttributes.add(SVGNames::filterUnitsAttr);
92         supportedAttributes.add(SVGNames::primitiveUnitsAttr);
93         supportedAttributes.add(SVGNames::xAttr);
94         supportedAttributes.add(SVGNames::yAttr);
95         supportedAttributes.add(SVGNames::widthAttr);
96         supportedAttributes.add(SVGNames::heightAttr);
97         supportedAttributes.add(SVGNames::filterResAttr);
98     }
99     return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
100 }
101
102 void SVGFilterElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
103 {
104     SVGParsingError parseError = NoError;
105
106     if (!isSupportedAttribute(name)) {
107         SVGElement::parseAttribute(name, value);
108     } else if (name == SVGNames::filterUnitsAttr) {
109         SVGUnitTypes::SVGUnitType propertyValue = SVGPropertyTraits<SVGUnitTypes::SVGUnitType>::fromString(value);
110         if (propertyValue > 0)
111             setFilterUnitsBaseValue(propertyValue);
112     } else if (name == SVGNames::primitiveUnitsAttr) {
113         SVGUnitTypes::SVGUnitType propertyValue = SVGPropertyTraits<SVGUnitTypes::SVGUnitType>::fromString(value);
114         if (propertyValue > 0)
115             setPrimitiveUnitsBaseValue(propertyValue);
116     } else if (name == SVGNames::xAttr) {
117         m_x->setBaseValueAsString(value, AllowNegativeLengths, parseError);
118     } else if (name == SVGNames::yAttr) {
119         m_y->setBaseValueAsString(value, AllowNegativeLengths, parseError);
120     } else if (name == SVGNames::widthAttr) {
121         m_width->setBaseValueAsString(value, ForbidNegativeLengths, parseError);
122     } else if (name == SVGNames::heightAttr) {
123         m_height->setBaseValueAsString(value, ForbidNegativeLengths, parseError);
124     } else if (name == SVGNames::filterResAttr) {
125         m_filterRes->setBaseValueAsString(value, parseError);
126     } else if (SVGURIReference::parseAttribute(name, value, parseError)) {
127     } else {
128         ASSERT_NOT_REACHED();
129     }
130
131     reportAttributeParsingError(parseError, name, value);
132 }
133
134 void SVGFilterElement::svgAttributeChanged(const QualifiedName& attrName)
135 {
136     if (!isSupportedAttribute(attrName)) {
137         SVGElement::svgAttributeChanged(attrName);
138         return;
139     }
140
141     SVGElementInstance::InvalidationGuard invalidationGuard(this);
142
143     if (attrName == SVGNames::xAttr
144         || attrName == SVGNames::yAttr
145         || attrName == SVGNames::widthAttr
146         || attrName == SVGNames::heightAttr)
147         updateRelativeLengthsInformation();
148
149     RenderSVGResourceContainer* renderer = toRenderSVGResourceContainer(this->renderer());
150     if (renderer)
151         renderer->invalidateCacheAndMarkForLayout();
152 }
153
154 void SVGFilterElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
155 {
156     SVGElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
157
158     if (changedByParser)
159         return;
160
161     if (RenderObject* object = renderer())
162         object->setNeedsLayout();
163 }
164
165 RenderObject* SVGFilterElement::createRenderer(RenderStyle*)
166 {
167     RenderSVGResourceFilter* renderer = new RenderSVGResourceFilter(this);
168
169     HashSet<RefPtr<Node> >::iterator layerEnd = m_clientsToAdd.end();
170     for (HashSet<RefPtr<Node> >::iterator it = m_clientsToAdd.begin(); it != layerEnd; ++it)
171         renderer->addClientRenderLayer((*it).get());
172     m_clientsToAdd.clear();
173
174     return renderer;
175 }
176
177 bool SVGFilterElement::selfHasRelativeLengths() const
178 {
179     return m_x->currentValue()->isRelative()
180         || m_y->currentValue()->isRelative()
181         || m_width->currentValue()->isRelative()
182         || m_height->currentValue()->isRelative();
183 }
184
185 void SVGFilterElement::addClient(Node* client)
186 {
187     ASSERT(client);
188     m_clientsToAdd.add(client);
189 }
190
191 void SVGFilterElement::removeClient(Node* client)
192 {
193     ASSERT(client);
194     m_clientsToAdd.remove(client);
195 }
196
197 }