Element's renderer factory should return RenderPtrs.
[WebKit-https.git] / Source / WebCore / svg / SVGFESpecularLightingElement.cpp
1 /*
2  * Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
3  * Copyright (C) 2004, 2005, 2006 Rob Buis <buis@kde.org>
4  * Copyright (C) 2005 Oliver Hunt <oliver@nerget.com>
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 "SVGFESpecularLightingElement.h"
26
27 #include "Attribute.h"
28 #include "FilterEffect.h"
29 #include "RenderStyle.h"
30 #include "SVGColor.h"
31 #include "SVGElementInstance.h"
32 #include "SVGFELightElement.h"
33 #include "SVGFilterBuilder.h"
34 #include "SVGNames.h"
35 #include "SVGParserUtilities.h"
36
37 namespace WebCore {
38
39 // Animated property definitions
40 DEFINE_ANIMATED_STRING(SVGFESpecularLightingElement, SVGNames::inAttr, In1, in1)
41 DEFINE_ANIMATED_NUMBER(SVGFESpecularLightingElement, SVGNames::specularConstantAttr, SpecularConstant, specularConstant)
42 DEFINE_ANIMATED_NUMBER(SVGFESpecularLightingElement, SVGNames::specularExponentAttr, SpecularExponent, specularExponent)
43 DEFINE_ANIMATED_NUMBER(SVGFESpecularLightingElement, SVGNames::surfaceScaleAttr, SurfaceScale, surfaceScale)
44 DEFINE_ANIMATED_NUMBER_MULTIPLE_WRAPPERS(SVGFESpecularLightingElement, SVGNames::kernelUnitLengthAttr, kernelUnitLengthXIdentifier(), KernelUnitLengthX, kernelUnitLengthX)
45 DEFINE_ANIMATED_NUMBER_MULTIPLE_WRAPPERS(SVGFESpecularLightingElement, SVGNames::kernelUnitLengthAttr, kernelUnitLengthYIdentifier(), KernelUnitLengthY, kernelUnitLengthY)
46
47 BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGFESpecularLightingElement)
48     REGISTER_LOCAL_ANIMATED_PROPERTY(in1)
49     REGISTER_LOCAL_ANIMATED_PROPERTY(specularConstant)
50     REGISTER_LOCAL_ANIMATED_PROPERTY(specularExponent)
51     REGISTER_LOCAL_ANIMATED_PROPERTY(surfaceScale)
52     REGISTER_LOCAL_ANIMATED_PROPERTY(kernelUnitLengthX)
53     REGISTER_LOCAL_ANIMATED_PROPERTY(kernelUnitLengthY)
54     REGISTER_PARENT_ANIMATED_PROPERTIES(SVGFilterPrimitiveStandardAttributes)
55 END_REGISTER_ANIMATED_PROPERTIES
56
57 inline SVGFESpecularLightingElement::SVGFESpecularLightingElement(const QualifiedName& tagName, Document& document)
58     : SVGFilterPrimitiveStandardAttributes(tagName, document)
59     , m_specularConstant(1)
60     , m_specularExponent(1)
61     , m_surfaceScale(1)
62 {
63     ASSERT(hasTagName(SVGNames::feSpecularLightingTag));
64     registerAnimatedPropertiesForSVGFESpecularLightingElement();
65 }
66
67 PassRefPtr<SVGFESpecularLightingElement> SVGFESpecularLightingElement::create(const QualifiedName& tagName, Document& document)
68 {
69     return adoptRef(new SVGFESpecularLightingElement(tagName, document));
70 }
71
72 const AtomicString& SVGFESpecularLightingElement::kernelUnitLengthXIdentifier()
73 {
74     DEFINE_STATIC_LOCAL(AtomicString, s_identifier, ("SVGKernelUnitLengthX", AtomicString::ConstructFromLiteral));
75     return s_identifier;
76 }
77
78 const AtomicString& SVGFESpecularLightingElement::kernelUnitLengthYIdentifier()
79 {
80     DEFINE_STATIC_LOCAL(AtomicString, s_identifier, ("SVGKernelUnitLengthY", AtomicString::ConstructFromLiteral));
81     return s_identifier;
82 }
83
84 bool SVGFESpecularLightingElement::isSupportedAttribute(const QualifiedName& attrName)
85 {
86     DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
87     if (supportedAttributes.isEmpty()) {
88         supportedAttributes.add(SVGNames::inAttr);
89         supportedAttributes.add(SVGNames::specularConstantAttr);
90         supportedAttributes.add(SVGNames::specularExponentAttr);
91         supportedAttributes.add(SVGNames::surfaceScaleAttr);
92         supportedAttributes.add(SVGNames::kernelUnitLengthAttr);
93     }
94     return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
95 }
96
97 void SVGFESpecularLightingElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
98 {
99     if (!isSupportedAttribute(name)) {
100         SVGFilterPrimitiveStandardAttributes::parseAttribute(name, value);
101         return;
102     }
103
104     if (name == SVGNames::inAttr) {
105         setIn1BaseValue(value);
106         return;
107     }
108
109     if (name == SVGNames::surfaceScaleAttr) {
110         setSurfaceScaleBaseValue(value.toFloat());
111         return;
112     }
113
114     if (name == SVGNames::specularConstantAttr) {
115         setSpecularConstantBaseValue(value.toFloat());
116         return;
117     }
118
119     if (name == SVGNames::specularExponentAttr) {
120         setSpecularExponentBaseValue(value.toFloat());
121         return;
122     }
123
124     if (name == SVGNames::kernelUnitLengthAttr) {
125         float x, y;
126         if (parseNumberOptionalNumber(value, x, y)) {
127             setKernelUnitLengthXBaseValue(x);
128             setKernelUnitLengthYBaseValue(y);
129         }
130         return;
131     }
132
133     ASSERT_NOT_REACHED();
134 }
135
136 bool SVGFESpecularLightingElement::setFilterEffectAttribute(FilterEffect* effect, const QualifiedName& attrName)
137 {
138     FESpecularLighting* specularLighting = static_cast<FESpecularLighting*>(effect);
139
140     if (attrName == SVGNames::lighting_colorAttr) {
141         RenderObject* renderer = this->renderer();
142         ASSERT(renderer);
143         return specularLighting->setLightingColor(renderer->style().svgStyle().lightingColor());
144     }
145     if (attrName == SVGNames::surfaceScaleAttr)
146         return specularLighting->setSurfaceScale(surfaceScale());
147     if (attrName == SVGNames::specularConstantAttr)
148         return specularLighting->setSpecularConstant(specularConstant());
149     if (attrName == SVGNames::specularExponentAttr)
150         return specularLighting->setSpecularExponent(specularExponent());
151
152     LightSource* lightSource = const_cast<LightSource*>(specularLighting->lightSource());
153     const SVGFELightElement* lightElement = SVGFELightElement::findLightElement(this);
154     ASSERT(lightSource);
155     ASSERT(lightElement);
156
157     if (attrName == SVGNames::azimuthAttr)
158         return lightSource->setAzimuth(lightElement->azimuth());
159     if (attrName == SVGNames::elevationAttr)
160         return lightSource->setElevation(lightElement->elevation());
161     if (attrName == SVGNames::xAttr)
162         return lightSource->setX(lightElement->x());
163     if (attrName == SVGNames::yAttr)
164         return lightSource->setY(lightElement->y());
165     if (attrName == SVGNames::zAttr)
166         return lightSource->setZ(lightElement->z());
167     if (attrName == SVGNames::pointsAtXAttr)
168         return lightSource->setPointsAtX(lightElement->pointsAtX());
169     if (attrName == SVGNames::pointsAtYAttr)
170         return lightSource->setPointsAtY(lightElement->pointsAtY());
171     if (attrName == SVGNames::pointsAtZAttr)
172         return lightSource->setPointsAtZ(lightElement->pointsAtZ());
173     if (attrName == SVGNames::specularExponentAttr)
174         return lightSource->setSpecularExponent(lightElement->specularExponent());
175     if (attrName == SVGNames::limitingConeAngleAttr)
176         return lightSource->setLimitingConeAngle(lightElement->limitingConeAngle());
177
178     ASSERT_NOT_REACHED();
179     return false;
180 }
181
182 void SVGFESpecularLightingElement::svgAttributeChanged(const QualifiedName& attrName)
183 {
184     if (!isSupportedAttribute(attrName)) {
185         SVGFilterPrimitiveStandardAttributes::svgAttributeChanged(attrName);
186         return;
187     }
188
189     SVGElementInstance::InvalidationGuard invalidationGuard(this);
190     
191     if (attrName == SVGNames::surfaceScaleAttr
192         || attrName == SVGNames::specularConstantAttr
193         || attrName == SVGNames::specularExponentAttr
194         || attrName == SVGNames::kernelUnitLengthAttr) {
195         primitiveAttributeChanged(attrName);
196         return;
197     }
198
199     if (attrName == SVGNames::inAttr) {
200         invalidate();
201         return;
202     }
203
204     ASSERT_NOT_REACHED();
205 }
206
207 void SVGFESpecularLightingElement::lightElementAttributeChanged(const SVGFELightElement* lightElement, const QualifiedName& attrName)
208 {
209     if (SVGFELightElement::findLightElement(this) != lightElement)
210         return;
211
212     // The light element has different attribute names so attrName can identify the requested attribute.
213     primitiveAttributeChanged(attrName);
214 }
215
216 PassRefPtr<FilterEffect> SVGFESpecularLightingElement::build(SVGFilterBuilder* filterBuilder, Filter* filter)
217 {
218     FilterEffect* input1 = filterBuilder->getEffectById(in1());
219
220     if (!input1)
221         return 0;
222
223     RefPtr<LightSource> lightSource = SVGFELightElement::findLightSource(this);
224     if (!lightSource)
225         return 0;
226
227     RenderObject* renderer = this->renderer();
228     if (!renderer)
229         return 0;
230     
231     Color color = renderer->style().svgStyle().lightingColor();
232
233     RefPtr<FilterEffect> effect = FESpecularLighting::create(filter, color, surfaceScale(), specularConstant(),
234                                           specularExponent(), kernelUnitLengthX(), kernelUnitLengthY(), lightSource.release());
235     effect->inputEffects().append(input1);
236     return effect.release();
237 }
238
239 }
240
241 #endif // ENABLE(SVG)