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"
29 #include "XLinkNames.h"
30 #include "core/rendering/svg/RenderSVGResourceFilter.h"
31 #include "core/svg/SVGElementInstance.h"
32 #include "core/svg/SVGParserUtilities.h"
36 // Animated property definitions
37 DEFINE_ANIMATED_ENUMERATION(SVGFilterElement, SVGNames::filterUnitsAttr, FilterUnits, filterUnits, SVGUnitTypes::SVGUnitType)
38 DEFINE_ANIMATED_ENUMERATION(SVGFilterElement, SVGNames::primitiveUnitsAttr, PrimitiveUnits, primitiveUnits, SVGUnitTypes::SVGUnitType)
39 DEFINE_ANIMATED_LENGTH(SVGFilterElement, SVGNames::xAttr, X, x)
40 DEFINE_ANIMATED_LENGTH(SVGFilterElement, SVGNames::yAttr, Y, y)
41 DEFINE_ANIMATED_LENGTH(SVGFilterElement, SVGNames::widthAttr, Width, width)
42 DEFINE_ANIMATED_LENGTH(SVGFilterElement, SVGNames::heightAttr, Height, height)
43 DEFINE_ANIMATED_INTEGER_MULTIPLE_WRAPPERS(SVGFilterElement, SVGNames::filterResAttr, filterResXIdentifier(), FilterResX, filterResX)
44 DEFINE_ANIMATED_INTEGER_MULTIPLE_WRAPPERS(SVGFilterElement, SVGNames::filterResAttr, filterResYIdentifier(), FilterResY, filterResY)
45 DEFINE_ANIMATED_STRING(SVGFilterElement, XLinkNames::hrefAttr, Href, href)
46 DEFINE_ANIMATED_BOOLEAN(SVGFilterElement, SVGNames::externalResourcesRequiredAttr, ExternalResourcesRequired, externalResourcesRequired)
48 BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGFilterElement)
49 REGISTER_LOCAL_ANIMATED_PROPERTY(filterUnits)
50 REGISTER_LOCAL_ANIMATED_PROPERTY(primitiveUnits)
51 REGISTER_LOCAL_ANIMATED_PROPERTY(x)
52 REGISTER_LOCAL_ANIMATED_PROPERTY(y)
53 REGISTER_LOCAL_ANIMATED_PROPERTY(width)
54 REGISTER_LOCAL_ANIMATED_PROPERTY(height)
55 REGISTER_LOCAL_ANIMATED_PROPERTY(filterResX)
56 REGISTER_LOCAL_ANIMATED_PROPERTY(filterResY)
57 REGISTER_LOCAL_ANIMATED_PROPERTY(href)
58 REGISTER_LOCAL_ANIMATED_PROPERTY(externalResourcesRequired)
59 END_REGISTER_ANIMATED_PROPERTIES
61 inline SVGFilterElement::SVGFilterElement(const QualifiedName& tagName, Document& document)
62 : SVGElement(tagName, document)
63 , m_filterUnits(SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)
64 , m_primitiveUnits(SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE)
65 , m_x(LengthModeWidth, "-10%")
66 , m_y(LengthModeHeight, "-10%")
67 , m_width(LengthModeWidth, "120%")
68 , m_height(LengthModeHeight, "120%")
70 // Spec: If the x/y attribute is not specified, the effect is as if a value of "-10%" were specified.
71 // Spec: If the width/height attribute is not specified, the effect is as if a value of "120%" were specified.
72 ASSERT(hasTagName(SVGNames::filterTag));
73 ScriptWrappable::init(this);
74 registerAnimatedPropertiesForSVGFilterElement();
77 PassRefPtr<SVGFilterElement> SVGFilterElement::create(const QualifiedName& tagName, Document& document)
79 return adoptRef(new SVGFilterElement(tagName, document));
82 const AtomicString& SVGFilterElement::filterResXIdentifier()
84 DEFINE_STATIC_LOCAL(AtomicString, s_identifier, ("SVGFilterResX", AtomicString::ConstructFromLiteral));
88 const AtomicString& SVGFilterElement::filterResYIdentifier()
90 DEFINE_STATIC_LOCAL(AtomicString, s_identifier, ("SVGFilterResY", AtomicString::ConstructFromLiteral));
94 void SVGFilterElement::setFilterRes(unsigned filterResX, unsigned filterResY)
96 setFilterResXBaseValue(filterResX);
97 setFilterResYBaseValue(filterResY);
99 RenderSVGResourceContainer* renderer = toRenderSVGResourceContainer(this->renderer());
101 renderer->invalidateCacheAndMarkForLayout();
104 bool SVGFilterElement::isSupportedAttribute(const QualifiedName& attrName)
106 DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
107 if (supportedAttributes.isEmpty()) {
108 SVGURIReference::addSupportedAttributes(supportedAttributes);
109 SVGExternalResourcesRequired::addSupportedAttributes(supportedAttributes);
110 supportedAttributes.add(SVGNames::filterUnitsAttr);
111 supportedAttributes.add(SVGNames::primitiveUnitsAttr);
112 supportedAttributes.add(SVGNames::xAttr);
113 supportedAttributes.add(SVGNames::yAttr);
114 supportedAttributes.add(SVGNames::widthAttr);
115 supportedAttributes.add(SVGNames::heightAttr);
116 supportedAttributes.add(SVGNames::filterResAttr);
118 return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
121 void SVGFilterElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
123 SVGParsingError parseError = NoError;
125 if (!isSupportedAttribute(name))
126 SVGElement::parseAttribute(name, value);
127 else if (name == SVGNames::filterUnitsAttr) {
128 SVGUnitTypes::SVGUnitType propertyValue = SVGPropertyTraits<SVGUnitTypes::SVGUnitType>::fromString(value);
129 if (propertyValue > 0)
130 setFilterUnitsBaseValue(propertyValue);
131 } else if (name == SVGNames::primitiveUnitsAttr) {
132 SVGUnitTypes::SVGUnitType propertyValue = SVGPropertyTraits<SVGUnitTypes::SVGUnitType>::fromString(value);
133 if (propertyValue > 0)
134 setPrimitiveUnitsBaseValue(propertyValue);
135 } else if (name == SVGNames::xAttr)
136 setXBaseValue(SVGLength::construct(LengthModeWidth, value, parseError));
137 else if (name == SVGNames::yAttr)
138 setYBaseValue(SVGLength::construct(LengthModeHeight, value, parseError));
139 else if (name == SVGNames::widthAttr)
140 setWidthBaseValue(SVGLength::construct(LengthModeWidth, value, parseError));
141 else if (name == SVGNames::heightAttr)
142 setHeightBaseValue(SVGLength::construct(LengthModeHeight, value, parseError));
143 else if (name == SVGNames::filterResAttr) {
145 if (parseNumberOptionalNumber(value, x, y)) {
146 setFilterResXBaseValue(x);
147 setFilterResYBaseValue(y);
149 } else if (SVGURIReference::parseAttribute(name, value)
150 || SVGExternalResourcesRequired::parseAttribute(name, value)) {
152 ASSERT_NOT_REACHED();
154 reportAttributeParsingError(parseError, name, value);
157 void SVGFilterElement::svgAttributeChanged(const QualifiedName& attrName)
159 if (!isSupportedAttribute(attrName)) {
160 SVGElement::svgAttributeChanged(attrName);
164 SVGElementInstance::InvalidationGuard invalidationGuard(this);
166 if (attrName == SVGNames::xAttr
167 || attrName == SVGNames::yAttr
168 || attrName == SVGNames::widthAttr
169 || attrName == SVGNames::heightAttr)
170 updateRelativeLengthsInformation();
172 RenderSVGResourceContainer* renderer = toRenderSVGResourceContainer(this->renderer());
174 renderer->invalidateCacheAndMarkForLayout();
177 void SVGFilterElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
179 SVGElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
184 if (RenderObject* object = renderer())
185 object->setNeedsLayout();
188 RenderObject* SVGFilterElement::createRenderer(RenderStyle*)
190 RenderSVGResourceFilter* renderer = new RenderSVGResourceFilter(this);
192 HashSet<RefPtr<Node> >::iterator layerEnd = m_clientsToAdd.end();
193 for (HashSet<RefPtr<Node> >::iterator it = m_clientsToAdd.begin(); it != layerEnd; ++it)
194 renderer->addClientRenderLayer((*it).get());
195 m_clientsToAdd.clear();
200 bool SVGFilterElement::childShouldCreateRenderer(const Node& child) const
202 if (!child.isSVGElement())
205 const SVGElement* svgElement = toSVGElement(&child);
207 DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, allowedChildElementTags, ());
208 if (allowedChildElementTags.isEmpty()) {
209 allowedChildElementTags.add(SVGNames::feBlendTag);
210 allowedChildElementTags.add(SVGNames::feColorMatrixTag);
211 allowedChildElementTags.add(SVGNames::feComponentTransferTag);
212 allowedChildElementTags.add(SVGNames::feCompositeTag);
213 allowedChildElementTags.add(SVGNames::feConvolveMatrixTag);
214 allowedChildElementTags.add(SVGNames::feDiffuseLightingTag);
215 allowedChildElementTags.add(SVGNames::feDisplacementMapTag);
216 allowedChildElementTags.add(SVGNames::feDistantLightTag);
217 allowedChildElementTags.add(SVGNames::feDropShadowTag);
218 allowedChildElementTags.add(SVGNames::feFloodTag);
219 allowedChildElementTags.add(SVGNames::feFuncATag);
220 allowedChildElementTags.add(SVGNames::feFuncBTag);
221 allowedChildElementTags.add(SVGNames::feFuncGTag);
222 allowedChildElementTags.add(SVGNames::feFuncRTag);
223 allowedChildElementTags.add(SVGNames::feGaussianBlurTag);
224 allowedChildElementTags.add(SVGNames::feImageTag);
225 allowedChildElementTags.add(SVGNames::feMergeTag);
226 allowedChildElementTags.add(SVGNames::feMergeNodeTag);
227 allowedChildElementTags.add(SVGNames::feMorphologyTag);
228 allowedChildElementTags.add(SVGNames::feOffsetTag);
229 allowedChildElementTags.add(SVGNames::fePointLightTag);
230 allowedChildElementTags.add(SVGNames::feSpecularLightingTag);
231 allowedChildElementTags.add(SVGNames::feSpotLightTag);
232 allowedChildElementTags.add(SVGNames::feTileTag);
233 allowedChildElementTags.add(SVGNames::feTurbulenceTag);
236 return allowedChildElementTags.contains<SVGAttributeHashTranslator>(svgElement->tagQName());
239 bool SVGFilterElement::selfHasRelativeLengths() const
241 return xCurrentValue().isRelative()
242 || yCurrentValue().isRelative()
243 || widthCurrentValue().isRelative()
244 || heightCurrentValue().isRelative();
247 void SVGFilterElement::addClient(Node* client)
250 m_clientsToAdd.add(client);
253 void SVGFilterElement::removeClient(Node* client)
256 m_clientsToAdd.remove(client);