1/* 2 * Copyright (C) 2005 Oliver Hunt <ojh16@student.canterbury.ac.nz> 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Library General Public 6 * License as published by the Free Software Foundation; either 7 * version 2 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Library General Public License for more details. 13 * 14 * You should have received a copy of the GNU Library General Public License 15 * along with this library; see the file COPYING.LIB. If not, write to 16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 * Boston, MA 02110-1301, USA. 18 */ 19 20#include "config.h" 21 22#include "core/svg/SVGFEDiffuseLightingElement.h" 23 24#include "core/rendering/style/RenderStyle.h" 25#include "core/svg/SVGElementInstance.h" 26#include "core/svg/SVGParserUtilities.h" 27#include "core/svg/graphics/filters/SVGFilterBuilder.h" 28#include "platform/graphics/filters/FEDiffuseLighting.h" 29#include "platform/graphics/filters/FilterEffect.h" 30 31namespace WebCore { 32 33// Animated property definitions 34DEFINE_ANIMATED_STRING(SVGFEDiffuseLightingElement, SVGNames::inAttr, In1, in1) 35DEFINE_ANIMATED_NUMBER(SVGFEDiffuseLightingElement, SVGNames::diffuseConstantAttr, DiffuseConstant, diffuseConstant) 36DEFINE_ANIMATED_NUMBER(SVGFEDiffuseLightingElement, SVGNames::surfaceScaleAttr, SurfaceScale, surfaceScale) 37DEFINE_ANIMATED_NUMBER_MULTIPLE_WRAPPERS(SVGFEDiffuseLightingElement, SVGNames::kernelUnitLengthAttr, kernelUnitLengthXIdentifier(), KernelUnitLengthX, kernelUnitLengthX) 38DEFINE_ANIMATED_NUMBER_MULTIPLE_WRAPPERS(SVGFEDiffuseLightingElement, SVGNames::kernelUnitLengthAttr, kernelUnitLengthYIdentifier(), KernelUnitLengthY, kernelUnitLengthY) 39 40BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGFEDiffuseLightingElement) 41 REGISTER_LOCAL_ANIMATED_PROPERTY(in1) 42 REGISTER_LOCAL_ANIMATED_PROPERTY(diffuseConstant) 43 REGISTER_LOCAL_ANIMATED_PROPERTY(surfaceScale) 44 REGISTER_LOCAL_ANIMATED_PROPERTY(kernelUnitLengthX) 45 REGISTER_LOCAL_ANIMATED_PROPERTY(kernelUnitLengthY) 46 REGISTER_PARENT_ANIMATED_PROPERTIES(SVGFilterPrimitiveStandardAttributes) 47END_REGISTER_ANIMATED_PROPERTIES 48 49inline SVGFEDiffuseLightingElement::SVGFEDiffuseLightingElement(Document& document) 50 : SVGFilterPrimitiveStandardAttributes(SVGNames::feDiffuseLightingTag, document) 51 , m_diffuseConstant(1) 52 , m_surfaceScale(1) 53{ 54 ScriptWrappable::init(this); 55 registerAnimatedPropertiesForSVGFEDiffuseLightingElement(); 56} 57 58PassRefPtr<SVGFEDiffuseLightingElement> SVGFEDiffuseLightingElement::create(Document& document) 59{ 60 return adoptRef(new SVGFEDiffuseLightingElement(document)); 61} 62 63const AtomicString& SVGFEDiffuseLightingElement::kernelUnitLengthXIdentifier() 64{ 65 DEFINE_STATIC_LOCAL(AtomicString, s_identifier, ("SVGKernelUnitLengthX", AtomicString::ConstructFromLiteral)); 66 return s_identifier; 67} 68 69const AtomicString& SVGFEDiffuseLightingElement::kernelUnitLengthYIdentifier() 70{ 71 DEFINE_STATIC_LOCAL(AtomicString, s_identifier, ("SVGKernelUnitLengthY", AtomicString::ConstructFromLiteral)); 72 return s_identifier; 73} 74 75bool SVGFEDiffuseLightingElement::isSupportedAttribute(const QualifiedName& attrName) 76{ 77 DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ()); 78 if (supportedAttributes.isEmpty()) { 79 supportedAttributes.add(SVGNames::inAttr); 80 supportedAttributes.add(SVGNames::diffuseConstantAttr); 81 supportedAttributes.add(SVGNames::surfaceScaleAttr); 82 supportedAttributes.add(SVGNames::kernelUnitLengthAttr); 83 supportedAttributes.add(SVGNames::lighting_colorAttr); // Even though it's a SVG-CSS property, we override its handling here. 84 } 85 return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName); 86} 87 88void SVGFEDiffuseLightingElement::parseAttribute(const QualifiedName& name, const AtomicString& value) 89{ 90 if (!isSupportedAttribute(name) || name == SVGNames::lighting_colorAttr) { 91 SVGFilterPrimitiveStandardAttributes::parseAttribute(name, value); 92 return; 93 } 94 95 if (name == SVGNames::inAttr) { 96 setIn1BaseValue(value); 97 return; 98 } 99 100 if (name == SVGNames::surfaceScaleAttr) { 101 setSurfaceScaleBaseValue(value.toFloat()); 102 return; 103 } 104 105 if (name == SVGNames::diffuseConstantAttr) { 106 setDiffuseConstantBaseValue(value.toFloat()); 107 return; 108 } 109 110 if (name == SVGNames::kernelUnitLengthAttr) { 111 float x, y; 112 if (parseNumberOptionalNumber(value, x, y)) { 113 setKernelUnitLengthXBaseValue(x); 114 setKernelUnitLengthYBaseValue(y); 115 } 116 return; 117 } 118 119 ASSERT_NOT_REACHED(); 120} 121 122bool SVGFEDiffuseLightingElement::setFilterEffectAttribute(FilterEffect* effect, const QualifiedName& attrName) 123{ 124 FEDiffuseLighting* diffuseLighting = static_cast<FEDiffuseLighting*>(effect); 125 126 if (attrName == SVGNames::lighting_colorAttr) { 127 RenderObject* renderer = this->renderer(); 128 ASSERT(renderer); 129 ASSERT(renderer->style()); 130 return diffuseLighting->setLightingColor(renderer->style()->svgStyle()->lightingColor()); 131 } 132 if (attrName == SVGNames::surfaceScaleAttr) 133 return diffuseLighting->setSurfaceScale(surfaceScaleCurrentValue()); 134 if (attrName == SVGNames::diffuseConstantAttr) 135 return diffuseLighting->setDiffuseConstant(diffuseConstantCurrentValue()); 136 137 LightSource* lightSource = const_cast<LightSource*>(diffuseLighting->lightSource()); 138 const SVGFELightElement* lightElement = SVGFELightElement::findLightElement(this); 139 ASSERT(lightSource); 140 ASSERT(lightElement); 141 142 if (attrName == SVGNames::azimuthAttr) 143 return lightSource->setAzimuth(lightElement->azimuthCurrentValue()); 144 if (attrName == SVGNames::elevationAttr) 145 return lightSource->setElevation(lightElement->elevationCurrentValue()); 146 if (attrName == SVGNames::xAttr) 147 return lightSource->setX(lightElement->xCurrentValue()); 148 if (attrName == SVGNames::yAttr) 149 return lightSource->setY(lightElement->yCurrentValue()); 150 if (attrName == SVGNames::zAttr) 151 return lightSource->setZ(lightElement->zCurrentValue()); 152 if (attrName == SVGNames::pointsAtXAttr) 153 return lightSource->setPointsAtX(lightElement->pointsAtXCurrentValue()); 154 if (attrName == SVGNames::pointsAtYAttr) 155 return lightSource->setPointsAtY(lightElement->pointsAtYCurrentValue()); 156 if (attrName == SVGNames::pointsAtZAttr) 157 return lightSource->setPointsAtZ(lightElement->pointsAtZCurrentValue()); 158 if (attrName == SVGNames::specularExponentAttr) 159 return lightSource->setSpecularExponent(lightElement->specularExponentCurrentValue()); 160 if (attrName == SVGNames::limitingConeAngleAttr) 161 return lightSource->setLimitingConeAngle(lightElement->limitingConeAngleCurrentValue()); 162 163 ASSERT_NOT_REACHED(); 164 return false; 165} 166 167void SVGFEDiffuseLightingElement::svgAttributeChanged(const QualifiedName& attrName) 168{ 169 if (!isSupportedAttribute(attrName)) { 170 SVGFilterPrimitiveStandardAttributes::svgAttributeChanged(attrName); 171 return; 172 } 173 174 SVGElementInstance::InvalidationGuard invalidationGuard(this); 175 176 if (attrName == SVGNames::surfaceScaleAttr 177 || attrName == SVGNames::diffuseConstantAttr 178 || attrName == SVGNames::kernelUnitLengthAttr 179 || attrName == SVGNames::lighting_colorAttr) { 180 primitiveAttributeChanged(attrName); 181 return; 182 } 183 184 if (attrName == SVGNames::inAttr) { 185 invalidate(); 186 return; 187 } 188 189 ASSERT_NOT_REACHED(); 190} 191 192void SVGFEDiffuseLightingElement::lightElementAttributeChanged(const SVGFELightElement* lightElement, const QualifiedName& attrName) 193{ 194 if (SVGFELightElement::findLightElement(this) != lightElement) 195 return; 196 197 // The light element has different attribute names. 198 primitiveAttributeChanged(attrName); 199} 200 201PassRefPtr<FilterEffect> SVGFEDiffuseLightingElement::build(SVGFilterBuilder* filterBuilder, Filter* filter) 202{ 203 FilterEffect* input1 = filterBuilder->getEffectById(in1CurrentValue()); 204 205 if (!input1) 206 return 0; 207 208 RefPtr<LightSource> lightSource = SVGFELightElement::findLightSource(this); 209 if (!lightSource) 210 return 0; 211 212 RenderObject* renderer = this->renderer(); 213 if (!renderer) 214 return 0; 215 216 ASSERT(renderer->style()); 217 Color color = renderer->style()->svgStyle()->lightingColor(); 218 219 RefPtr<FilterEffect> effect = FEDiffuseLighting::create(filter, color, surfaceScaleCurrentValue(), diffuseConstantCurrentValue(), 220 kernelUnitLengthXCurrentValue(), kernelUnitLengthYCurrentValue(), lightSource.release()); 221 effect->inputEffects().append(input1); 222 return effect.release(); 223} 224 225} 226