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.
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.
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.
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.
26 #include "core/svg/SVGFilterElement.h"
28 #include "XLinkNames.h"
29 #include "core/rendering/svg/RenderSVGResourceFilter.h"
30 #include "core/svg/SVGElementInstance.h"
31 #include "core/svg/SVGParserUtilities.h"
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))
46 ScriptWrappable::init(this);
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%");
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);
64 PassRefPtr<SVGFilterElement> SVGFilterElement::create(Document& document)
66 return adoptRef(new SVGFilterElement(document));
69 void SVGFilterElement::setFilterRes(unsigned x, unsigned y)
71 filterResX()->baseValue()->setValue(x);
72 filterResY()->baseValue()->setValue(y);
74 invalidateSVGAttributes();
75 svgAttributeChanged(SVGNames::filterResAttr);
78 bool SVGFilterElement::isSupportedAttribute(const QualifiedName& attrName)
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);
91 return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
94 void SVGFilterElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
96 SVGParsingError parseError = NoError;
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)) {
116 ASSERT_NOT_REACHED();
118 reportAttributeParsingError(parseError, name, value);
121 void SVGFilterElement::svgAttributeChanged(const QualifiedName& attrName)
123 if (!isSupportedAttribute(attrName)) {
124 SVGElement::svgAttributeChanged(attrName);
128 SVGElement::InvalidationGuard invalidationGuard(this);
130 if (attrName == SVGNames::xAttr
131 || attrName == SVGNames::yAttr
132 || attrName == SVGNames::widthAttr
133 || attrName == SVGNames::heightAttr)
134 updateRelativeLengthsInformation();
136 RenderSVGResourceContainer* renderer = toRenderSVGResourceContainer(this->renderer());
138 renderer->invalidateCacheAndMarkForLayout();
141 void SVGFilterElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
143 SVGElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
148 if (RenderObject* object = renderer())
149 object->setNeedsLayout();
152 RenderObject* SVGFilterElement::createRenderer(RenderStyle*)
154 RenderSVGResourceFilter* renderer = new RenderSVGResourceFilter(this);
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();
164 bool SVGFilterElement::selfHasRelativeLengths() const
166 return m_x->currentValue()->isRelative()
167 || m_y->currentValue()->isRelative()
168 || m_width->currentValue()->isRelative()
169 || m_height->currentValue()->isRelative();
172 void SVGFilterElement::addClient(Node* client)
175 m_clientsToAdd.add(client);
178 void SVGFilterElement::removeClient(Node* client)
181 m_clientsToAdd.remove(client);