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#include "core/svg/SVGFELightElement.h"
25
26#include "SVGNames.h"
27#include "core/rendering/RenderObject.h"
28#include "core/rendering/svg/RenderSVGResource.h"
29#include "core/svg/SVGElementInstance.h"
30#include "core/svg/SVGFEDiffuseLightingElement.h"
31#include "core/svg/SVGFESpecularLightingElement.h"
32
33namespace WebCore {
34
35// Animated property definitions
36DEFINE_ANIMATED_NUMBER(SVGFELightElement, SVGNames::azimuthAttr, Azimuth, azimuth)
37DEFINE_ANIMATED_NUMBER(SVGFELightElement, SVGNames::elevationAttr, Elevation, elevation)
38DEFINE_ANIMATED_NUMBER(SVGFELightElement, SVGNames::xAttr, X, x)
39DEFINE_ANIMATED_NUMBER(SVGFELightElement, SVGNames::yAttr, Y, y)
40DEFINE_ANIMATED_NUMBER(SVGFELightElement, SVGNames::zAttr, Z, z)
41DEFINE_ANIMATED_NUMBER(SVGFELightElement, SVGNames::pointsAtXAttr, PointsAtX, pointsAtX)
42DEFINE_ANIMATED_NUMBER(SVGFELightElement, SVGNames::pointsAtYAttr, PointsAtY, pointsAtY)
43DEFINE_ANIMATED_NUMBER(SVGFELightElement, SVGNames::pointsAtZAttr, PointsAtZ, pointsAtZ)
44DEFINE_ANIMATED_NUMBER(SVGFELightElement, SVGNames::specularExponentAttr, SpecularExponent, specularExponent)
45DEFINE_ANIMATED_NUMBER(SVGFELightElement, SVGNames::limitingConeAngleAttr, LimitingConeAngle, limitingConeAngle)
46
47BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGFELightElement)
48    REGISTER_LOCAL_ANIMATED_PROPERTY(azimuth)
49    REGISTER_LOCAL_ANIMATED_PROPERTY(elevation)
50    REGISTER_LOCAL_ANIMATED_PROPERTY(x)
51    REGISTER_LOCAL_ANIMATED_PROPERTY(y)
52    REGISTER_LOCAL_ANIMATED_PROPERTY(z)
53    REGISTER_LOCAL_ANIMATED_PROPERTY(pointsAtX)
54    REGISTER_LOCAL_ANIMATED_PROPERTY(pointsAtY)
55    REGISTER_LOCAL_ANIMATED_PROPERTY(pointsAtZ)
56    REGISTER_LOCAL_ANIMATED_PROPERTY(specularExponent)
57    REGISTER_LOCAL_ANIMATED_PROPERTY(limitingConeAngle)
58END_REGISTER_ANIMATED_PROPERTIES
59
60SVGFELightElement::SVGFELightElement(const QualifiedName& tagName, Document& document)
61    : SVGElement(tagName, document)
62    , m_specularExponent(1)
63{
64    registerAnimatedPropertiesForSVGFELightElement();
65}
66
67SVGFELightElement* SVGFELightElement::findLightElement(const SVGElement* svgElement)
68{
69    for (Node* node = svgElement->firstChild(); node; node = node->nextSibling()) {
70        if (node->hasTagName(SVGNames::feDistantLightTag)
71            || node->hasTagName(SVGNames::fePointLightTag)
72            || node->hasTagName(SVGNames::feSpotLightTag)) {
73            return static_cast<SVGFELightElement*>(node);
74        }
75    }
76    return 0;
77}
78
79PassRefPtr<LightSource> SVGFELightElement::findLightSource(const SVGElement* svgElement)
80{
81    SVGFELightElement* lightNode = findLightElement(svgElement);
82    if (!lightNode)
83        return 0;
84    return lightNode->lightSource();
85}
86
87bool SVGFELightElement::isSupportedAttribute(const QualifiedName& attrName)
88{
89    DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
90    if (supportedAttributes.isEmpty()) {
91        supportedAttributes.add(SVGNames::azimuthAttr);
92        supportedAttributes.add(SVGNames::elevationAttr);
93        supportedAttributes.add(SVGNames::xAttr);
94        supportedAttributes.add(SVGNames::yAttr);
95        supportedAttributes.add(SVGNames::zAttr);
96        supportedAttributes.add(SVGNames::pointsAtXAttr);
97        supportedAttributes.add(SVGNames::pointsAtYAttr);
98        supportedAttributes.add(SVGNames::pointsAtZAttr);
99        supportedAttributes.add(SVGNames::specularExponentAttr);
100        supportedAttributes.add(SVGNames::limitingConeAngleAttr);
101    }
102    return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
103}
104
105void SVGFELightElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
106{
107    if (!isSupportedAttribute(name)) {
108        SVGElement::parseAttribute(name, value);
109        return;
110    }
111
112    if (name == SVGNames::azimuthAttr) {
113        setAzimuthBaseValue(value.toFloat());
114        return;
115    }
116
117    if (name == SVGNames::elevationAttr) {
118        setElevationBaseValue(value.toFloat());
119        return;
120    }
121
122    if (name == SVGNames::xAttr) {
123        setXBaseValue(value.toFloat());
124        return;
125    }
126
127    if (name == SVGNames::yAttr) {
128        setYBaseValue(value.toFloat());
129        return;
130    }
131
132    if (name == SVGNames::zAttr) {
133        setZBaseValue(value.toFloat());
134        return;
135    }
136
137    if (name == SVGNames::pointsAtXAttr) {
138        setPointsAtXBaseValue(value.toFloat());
139        return;
140    }
141
142    if (name == SVGNames::pointsAtYAttr) {
143        setPointsAtYBaseValue(value.toFloat());
144        return;
145    }
146
147    if (name == SVGNames::pointsAtZAttr) {
148        setPointsAtZBaseValue(value.toFloat());
149        return;
150    }
151
152    if (name == SVGNames::specularExponentAttr) {
153        setSpecularExponentBaseValue(value.toFloat());
154        return;
155    }
156
157    if (name == SVGNames::limitingConeAngleAttr) {
158        setLimitingConeAngleBaseValue(value.toFloat());
159        return;
160    }
161
162    ASSERT_NOT_REACHED();
163}
164
165void SVGFELightElement::svgAttributeChanged(const QualifiedName& attrName)
166{
167    if (!isSupportedAttribute(attrName)) {
168        SVGElement::svgAttributeChanged(attrName);
169        return;
170    }
171
172    SVGElementInstance::InvalidationGuard invalidationGuard(this);
173
174    if (attrName == SVGNames::azimuthAttr
175        || attrName == SVGNames::elevationAttr
176        || attrName == SVGNames::xAttr
177        || attrName == SVGNames::yAttr
178        || attrName == SVGNames::zAttr
179        || attrName == SVGNames::pointsAtXAttr
180        || attrName == SVGNames::pointsAtYAttr
181        || attrName == SVGNames::pointsAtZAttr
182        || attrName == SVGNames::specularExponentAttr
183        || attrName == SVGNames::limitingConeAngleAttr) {
184        ContainerNode* parent = parentNode();
185        if (!parent)
186            return;
187
188        RenderObject* renderer = parent->renderer();
189        if (!renderer || !renderer->isSVGResourceFilterPrimitive())
190            return;
191
192        if (parent->hasTagName(SVGNames::feDiffuseLightingTag)) {
193            toSVGFEDiffuseLightingElement(parent)->lightElementAttributeChanged(this, attrName);
194            return;
195        } else if (parent->hasTagName(SVGNames::feSpecularLightingTag)) {
196            toSVGFESpecularLightingElement(parent)->lightElementAttributeChanged(this, attrName);
197            return;
198        }
199    }
200
201    ASSERT_NOT_REACHED();
202}
203
204void SVGFELightElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
205{
206    SVGElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
207
208    if (!changedByParser) {
209        if (ContainerNode* parent = parentNode()) {
210            RenderObject* renderer = parent->renderer();
211            if (renderer && renderer->isSVGResourceFilterPrimitive())
212                RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
213        }
214    }
215}
216
217}
218