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 "core/svg/SVGFESpecularLightingElement.h" 24 25#include "core/rendering/RenderObject.h" 26#include "core/rendering/style/RenderStyle.h" 27#include "core/svg/SVGParserUtilities.h" 28#include "core/svg/graphics/filters/SVGFilterBuilder.h" 29#include "platform/graphics/filters/FilterEffect.h" 30 31namespace blink { 32 33inline SVGFESpecularLightingElement::SVGFESpecularLightingElement(Document& document) 34 : SVGFilterPrimitiveStandardAttributes(SVGNames::feSpecularLightingTag, document) 35 , m_specularConstant(SVGAnimatedNumber::create(this, SVGNames::specularConstantAttr, SVGNumber::create(1))) 36 , m_specularExponent(SVGAnimatedNumber::create(this, SVGNames::specularExponentAttr, SVGNumber::create(1))) 37 , m_surfaceScale(SVGAnimatedNumber::create(this, SVGNames::surfaceScaleAttr, SVGNumber::create(1))) 38 , m_kernelUnitLength(SVGAnimatedNumberOptionalNumber::create(this, SVGNames::surfaceScaleAttr)) 39 , m_in1(SVGAnimatedString::create(this, SVGNames::inAttr, SVGString::create())) 40{ 41 addToPropertyMap(m_specularConstant); 42 addToPropertyMap(m_specularExponent); 43 addToPropertyMap(m_surfaceScale); 44 addToPropertyMap(m_kernelUnitLength); 45 addToPropertyMap(m_in1); 46} 47 48DEFINE_NODE_FACTORY(SVGFESpecularLightingElement) 49 50bool SVGFESpecularLightingElement::isSupportedAttribute(const QualifiedName& attrName) 51{ 52 DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ()); 53 if (supportedAttributes.isEmpty()) { 54 supportedAttributes.add(SVGNames::inAttr); 55 supportedAttributes.add(SVGNames::specularConstantAttr); 56 supportedAttributes.add(SVGNames::specularExponentAttr); 57 supportedAttributes.add(SVGNames::surfaceScaleAttr); 58 supportedAttributes.add(SVGNames::kernelUnitLengthAttr); 59 } 60 return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName); 61} 62 63void SVGFESpecularLightingElement::parseAttribute(const QualifiedName& name, const AtomicString& value) 64{ 65 if (!isSupportedAttribute(name)) { 66 SVGFilterPrimitiveStandardAttributes::parseAttribute(name, value); 67 return; 68 } 69 70 SVGParsingError parseError = NoError; 71 72 if (name == SVGNames::inAttr) 73 m_in1->setBaseValueAsString(value, parseError); 74 else if (name == SVGNames::surfaceScaleAttr) 75 m_surfaceScale->setBaseValueAsString(value, parseError); 76 else if (name == SVGNames::specularConstantAttr) 77 m_specularConstant->setBaseValueAsString(value, parseError); 78 else if (name == SVGNames::specularExponentAttr) 79 m_specularExponent->setBaseValueAsString(value, parseError); 80 else if (name == SVGNames::kernelUnitLengthAttr) 81 m_kernelUnitLength->setBaseValueAsString(value, parseError); 82 else 83 ASSERT_NOT_REACHED(); 84 85 reportAttributeParsingError(parseError, name, value); 86} 87 88bool SVGFESpecularLightingElement::setFilterEffectAttribute(FilterEffect* effect, const QualifiedName& attrName) 89{ 90 FESpecularLighting* specularLighting = static_cast<FESpecularLighting*>(effect); 91 92 if (attrName == SVGNames::lighting_colorAttr) { 93 RenderObject* renderer = this->renderer(); 94 ASSERT(renderer); 95 ASSERT(renderer->style()); 96 return specularLighting->setLightingColor(renderer->style()->svgStyle().lightingColor()); 97 } 98 if (attrName == SVGNames::surfaceScaleAttr) 99 return specularLighting->setSurfaceScale(m_surfaceScale->currentValue()->value()); 100 if (attrName == SVGNames::specularConstantAttr) 101 return specularLighting->setSpecularConstant(m_specularConstant->currentValue()->value()); 102 if (attrName == SVGNames::specularExponentAttr) 103 return specularLighting->setSpecularExponent(m_specularExponent->currentValue()->value()); 104 105 LightSource* lightSource = const_cast<LightSource*>(specularLighting->lightSource()); 106 SVGFELightElement* lightElement = SVGFELightElement::findLightElement(*this); 107 ASSERT(lightSource); 108 ASSERT(lightElement); 109 ASSERT(effect->filter()); 110 111 if (attrName == SVGNames::azimuthAttr) 112 return lightSource->setAzimuth(lightElement->azimuth()->currentValue()->value()); 113 if (attrName == SVGNames::elevationAttr) 114 return lightSource->setElevation(lightElement->elevation()->currentValue()->value()); 115 if (attrName == SVGNames::xAttr || attrName == SVGNames::yAttr || attrName == SVGNames::zAttr) 116 return lightSource->setPosition(effect->filter()->resolve3dPoint(lightElement->position())); 117 if (attrName == SVGNames::pointsAtXAttr || attrName == SVGNames::pointsAtYAttr || attrName == SVGNames::pointsAtZAttr) 118 return lightSource->setPointsAt(effect->filter()->resolve3dPoint(lightElement->pointsAt())); 119 if (attrName == SVGNames::specularExponentAttr) 120 return lightSource->setSpecularExponent(lightElement->specularExponent()->currentValue()->value()); 121 if (attrName == SVGNames::limitingConeAngleAttr) 122 return lightSource->setLimitingConeAngle(lightElement->limitingConeAngle()->currentValue()->value()); 123 124 ASSERT_NOT_REACHED(); 125 return false; 126} 127 128void SVGFESpecularLightingElement::svgAttributeChanged(const QualifiedName& attrName) 129{ 130 if (!isSupportedAttribute(attrName)) { 131 SVGFilterPrimitiveStandardAttributes::svgAttributeChanged(attrName); 132 return; 133 } 134 135 SVGElement::InvalidationGuard invalidationGuard(this); 136 137 if (attrName == SVGNames::surfaceScaleAttr 138 || attrName == SVGNames::specularConstantAttr 139 || attrName == SVGNames::specularExponentAttr 140 || attrName == SVGNames::kernelUnitLengthAttr) { 141 primitiveAttributeChanged(attrName); 142 return; 143 } 144 145 if (attrName == SVGNames::inAttr) { 146 invalidate(); 147 return; 148 } 149 150 ASSERT_NOT_REACHED(); 151} 152 153void 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 162PassRefPtr<FilterEffect> SVGFESpecularLightingElement::build(SVGFilterBuilder* filterBuilder, Filter* filter) 163{ 164 FilterEffect* input1 = filterBuilder->getEffectById(AtomicString(m_in1->currentValue()->value())); 165 166 if (!input1) 167 return nullptr; 168 169 SVGFELightElement* lightNode = SVGFELightElement::findLightElement(*this); 170 if (!lightNode) 171 return nullptr; 172 173 RenderObject* renderer = this->renderer(); 174 if (!renderer) 175 return nullptr; 176 177 ASSERT(renderer->style()); 178 Color color = renderer->style()->svgStyle().lightingColor(); 179 180 RefPtr<LightSource> lightSource = lightNode->lightSource(filter); 181 RefPtr<FilterEffect> effect = FESpecularLighting::create(filter, color, m_surfaceScale->currentValue()->value(), m_specularConstant->currentValue()->value(), 182 m_specularExponent->currentValue()->value(), kernelUnitLengthX()->currentValue()->value(), kernelUnitLengthY()->currentValue()->value(), lightSource.release()); 183 effect->inputEffects().append(input1); 184 return effect.release(); 185} 186 187} // namespace blink 188