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