35fa32bdff71e9556b0f773aabeb864e1a0d6a9f
[WebKit-https.git] / Source / WebCore / svg / SVGFilterPrimitiveStandardAttributes.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) 2009 Dirk Schulze <krit@webkit.org>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public License
17  * along with this library; see the file COPYING.LIB.  If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21
22 #include "config.h"
23
24 #if ENABLE(SVG) && ENABLE(FILTERS)
25 #include "SVGFilterPrimitiveStandardAttributes.h"
26
27 #include "Attribute.h"
28 #include "FilterEffect.h"
29 #include "RenderSVGResourceFilterPrimitive.h"
30 #include "SVGElementInstance.h"
31 #include "SVGFilterBuilder.h"
32 #include "SVGLength.h"
33 #include "SVGNames.h"
34 #include "SVGStyledElement.h"
35 #include "SVGUnitTypes.h"
36
37 namespace WebCore {
38
39 // Animated property definitions
40 DEFINE_ANIMATED_LENGTH(SVGFilterPrimitiveStandardAttributes, SVGNames::xAttr, X, x)
41 DEFINE_ANIMATED_LENGTH(SVGFilterPrimitiveStandardAttributes, SVGNames::yAttr, Y, y)
42 DEFINE_ANIMATED_LENGTH(SVGFilterPrimitiveStandardAttributes, SVGNames::widthAttr, Width, width)
43 DEFINE_ANIMATED_LENGTH(SVGFilterPrimitiveStandardAttributes, SVGNames::heightAttr, Height, height)
44 DEFINE_ANIMATED_STRING(SVGFilterPrimitiveStandardAttributes, SVGNames::resultAttr, Result, result)
45
46 BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGFilterPrimitiveStandardAttributes)
47     REGISTER_LOCAL_ANIMATED_PROPERTY(x)
48     REGISTER_LOCAL_ANIMATED_PROPERTY(y)
49     REGISTER_LOCAL_ANIMATED_PROPERTY(width)
50     REGISTER_LOCAL_ANIMATED_PROPERTY(height)
51     REGISTER_LOCAL_ANIMATED_PROPERTY(result)
52     REGISTER_PARENT_ANIMATED_PROPERTIES(SVGStyledElement)
53 END_REGISTER_ANIMATED_PROPERTIES
54
55 SVGFilterPrimitiveStandardAttributes::SVGFilterPrimitiveStandardAttributes(const QualifiedName& tagName, Document* document)
56     : SVGStyledElement(tagName, document)
57     , m_x(LengthModeWidth, "0%")
58     , m_y(LengthModeHeight, "0%")
59     , m_width(LengthModeWidth, "100%")
60     , m_height(LengthModeHeight, "100%")
61 {
62     // Spec: If the x/y attribute is not specified, the effect is as if a value of "0%" were specified.
63     // Spec: If the width/height attribute is not specified, the effect is as if a value of "100%" were specified.
64     registerAnimatedPropertiesForSVGFilterPrimitiveStandardAttributes();
65 }
66
67 bool SVGFilterPrimitiveStandardAttributes::isSupportedAttribute(const QualifiedName& attrName)
68 {
69     DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
70     if (supportedAttributes.isEmpty()) {
71         supportedAttributes.add(SVGNames::xAttr);
72         supportedAttributes.add(SVGNames::yAttr);
73         supportedAttributes.add(SVGNames::widthAttr);
74         supportedAttributes.add(SVGNames::heightAttr);
75         supportedAttributes.add(SVGNames::resultAttr);
76     }
77     return supportedAttributes.contains<QualifiedName, SVGAttributeHashTranslator>(attrName);
78 }
79
80 void SVGFilterPrimitiveStandardAttributes::parseMappedAttribute(Attribute* attr)
81 {
82     SVGParsingError parseError = NoError;
83     const AtomicString& value = attr->value();
84
85     if (!isSupportedAttribute(attr->name()))
86         SVGStyledElement::parseMappedAttribute(attr);
87     else if (attr->name() == SVGNames::xAttr)
88         setXBaseValue(SVGLength::construct(LengthModeWidth, value, parseError));
89     else if (attr->name() == SVGNames::yAttr)
90         setYBaseValue(SVGLength::construct(LengthModeHeight, value, parseError));
91     else if (attr->name() == SVGNames::widthAttr)
92         setWidthBaseValue(SVGLength::construct(LengthModeWidth, value, parseError));
93     else if (attr->name() == SVGNames::heightAttr)
94         setHeightBaseValue(SVGLength::construct(LengthModeHeight, value, parseError));
95     else if (attr->name() == SVGNames::resultAttr)
96         setResultBaseValue(value);
97     else
98         ASSERT_NOT_REACHED();
99
100     reportAttributeParsingError(parseError, attr);
101 }
102
103 bool SVGFilterPrimitiveStandardAttributes::setFilterEffectAttribute(FilterEffect*, const QualifiedName&)
104 {
105     // When all filters support this method, it will be changed to a pure virtual method.
106     ASSERT_NOT_REACHED();
107     return false;
108 }
109
110 void SVGFilterPrimitiveStandardAttributes::svgAttributeChanged(const QualifiedName& attrName)
111 {
112     if (!isSupportedAttribute(attrName)) {
113         SVGStyledElement::svgAttributeChanged(attrName);
114         return;
115     }
116
117     SVGElementInstance::InvalidationGuard invalidationGuard(this);    
118     invalidate();
119 }
120
121 void SVGFilterPrimitiveStandardAttributes::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
122 {
123     SVGStyledElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
124
125     if (!changedByParser)
126         invalidate();
127 }
128
129 void SVGFilterPrimitiveStandardAttributes::setStandardAttributes(bool primitiveBoundingBoxMode, FilterEffect* filterEffect) const
130 {
131     ASSERT(filterEffect);
132     if (!filterEffect)
133         return;
134
135     if (this->hasAttribute(SVGNames::xAttr))
136         filterEffect->setHasX(true);
137     if (this->hasAttribute(SVGNames::yAttr))
138         filterEffect->setHasY(true);
139     if (this->hasAttribute(SVGNames::widthAttr))
140         filterEffect->setHasWidth(true);
141     if (this->hasAttribute(SVGNames::heightAttr))
142         filterEffect->setHasHeight(true);
143
144     FloatRect effectBBox;
145     if (primitiveBoundingBoxMode)
146         effectBBox = FloatRect(x().valueAsPercentage(),
147                                y().valueAsPercentage(),
148                                width().valueAsPercentage(),
149                                height().valueAsPercentage());
150     else
151         effectBBox = FloatRect(x().value(this),
152                                y().value(this),
153                                width().value(this),
154                                height().value(this));
155
156     filterEffect->setEffectBoundaries(effectBBox);
157 }
158
159 RenderObject* SVGFilterPrimitiveStandardAttributes::createRenderer(RenderArena* arena, RenderStyle*)
160 {
161     return new (arena) RenderSVGResourceFilterPrimitive(this);
162 }
163
164 bool SVGFilterPrimitiveStandardAttributes::rendererIsNeeded(const NodeRenderingContext& context)
165 {
166     if (parentNode() && (parentNode()->hasTagName(SVGNames::filterTag)))
167         return SVGStyledElement::rendererIsNeeded(context);
168
169     return false;
170 }
171
172 void invalidateFilterPrimitiveParent(SVGElement* element)
173 {
174     if (!element)
175         return;
176
177     ContainerNode* parent = element->parentNode();
178
179     if (!parent)
180         return;
181
182     RenderObject* renderer = parent->renderer();
183     if (!renderer || !renderer->isSVGResourceFilterPrimitive())
184         return;
185
186     RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer, false);
187 }
188
189 }
190
191 #endif // ENABLE(SVG)