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