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