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