1/* 2 * Copyright (C) 2006 Oliver Hunt <oliver@nerget.com> 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/SVGFEDisplacementMapElement.h" 23 24#include "SVGNames.h" 25#include "platform/graphics/filters/FilterEffect.h" 26#include "core/svg/SVGElementInstance.h" 27#include "core/svg/graphics/filters/SVGFilterBuilder.h" 28 29namespace WebCore { 30 31// Animated property definitions 32DEFINE_ANIMATED_STRING(SVGFEDisplacementMapElement, SVGNames::inAttr, In1, in1) 33DEFINE_ANIMATED_STRING(SVGFEDisplacementMapElement, SVGNames::in2Attr, In2, in2) 34DEFINE_ANIMATED_ENUMERATION(SVGFEDisplacementMapElement, SVGNames::xChannelSelectorAttr, XChannelSelector, xChannelSelector, ChannelSelectorType) 35DEFINE_ANIMATED_ENUMERATION(SVGFEDisplacementMapElement, SVGNames::yChannelSelectorAttr, YChannelSelector, yChannelSelector, ChannelSelectorType) 36DEFINE_ANIMATED_NUMBER(SVGFEDisplacementMapElement, SVGNames::scaleAttr, Scale, scale) 37 38BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGFEDisplacementMapElement) 39 REGISTER_LOCAL_ANIMATED_PROPERTY(in1) 40 REGISTER_LOCAL_ANIMATED_PROPERTY(in2) 41 REGISTER_LOCAL_ANIMATED_PROPERTY(xChannelSelector) 42 REGISTER_LOCAL_ANIMATED_PROPERTY(yChannelSelector) 43 REGISTER_LOCAL_ANIMATED_PROPERTY(scale) 44 REGISTER_PARENT_ANIMATED_PROPERTIES(SVGFilterPrimitiveStandardAttributes) 45END_REGISTER_ANIMATED_PROPERTIES 46 47inline SVGFEDisplacementMapElement::SVGFEDisplacementMapElement(Document& document) 48 : SVGFilterPrimitiveStandardAttributes(SVGNames::feDisplacementMapTag, document) 49 , m_xChannelSelector(CHANNEL_A) 50 , m_yChannelSelector(CHANNEL_A) 51{ 52 ScriptWrappable::init(this); 53 registerAnimatedPropertiesForSVGFEDisplacementMapElement(); 54} 55 56PassRefPtr<SVGFEDisplacementMapElement> SVGFEDisplacementMapElement::create(Document& document) 57{ 58 return adoptRef(new SVGFEDisplacementMapElement(document)); 59} 60 61bool SVGFEDisplacementMapElement::isSupportedAttribute(const QualifiedName& attrName) 62{ 63 DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ()); 64 if (supportedAttributes.isEmpty()) { 65 supportedAttributes.add(SVGNames::inAttr); 66 supportedAttributes.add(SVGNames::in2Attr); 67 supportedAttributes.add(SVGNames::xChannelSelectorAttr); 68 supportedAttributes.add(SVGNames::yChannelSelectorAttr); 69 supportedAttributes.add(SVGNames::scaleAttr); 70 } 71 return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName); 72} 73 74void SVGFEDisplacementMapElement::parseAttribute(const QualifiedName& name, const AtomicString& value) 75{ 76 if (!isSupportedAttribute(name)) { 77 SVGFilterPrimitiveStandardAttributes::parseAttribute(name, value); 78 return; 79 } 80 81 if (name == SVGNames::xChannelSelectorAttr) { 82 ChannelSelectorType propertyValue = SVGPropertyTraits<ChannelSelectorType>::fromString(value); 83 if (propertyValue > 0) 84 setXChannelSelectorBaseValue(propertyValue); 85 return; 86 } 87 88 if (name == SVGNames::yChannelSelectorAttr) { 89 ChannelSelectorType propertyValue = SVGPropertyTraits<ChannelSelectorType>::fromString(value); 90 if (propertyValue > 0) 91 setYChannelSelectorBaseValue(propertyValue); 92 return; 93 } 94 95 if (name == SVGNames::inAttr) { 96 setIn1BaseValue(value); 97 return; 98 } 99 100 if (name == SVGNames::in2Attr) { 101 setIn2BaseValue(value); 102 return; 103 } 104 105 if (name == SVGNames::scaleAttr) { 106 setScaleBaseValue(value.toFloat()); 107 return; 108 } 109 110 ASSERT_NOT_REACHED(); 111} 112 113bool SVGFEDisplacementMapElement::setFilterEffectAttribute(FilterEffect* effect, const QualifiedName& attrName) 114{ 115 FEDisplacementMap* displacementMap = static_cast<FEDisplacementMap*>(effect); 116 if (attrName == SVGNames::xChannelSelectorAttr) 117 return displacementMap->setXChannelSelector(xChannelSelectorCurrentValue()); 118 if (attrName == SVGNames::yChannelSelectorAttr) 119 return displacementMap->setYChannelSelector(yChannelSelectorCurrentValue()); 120 if (attrName == SVGNames::scaleAttr) 121 return displacementMap->setScale(scaleCurrentValue()); 122 123 ASSERT_NOT_REACHED(); 124 return false; 125} 126 127void SVGFEDisplacementMapElement::svgAttributeChanged(const QualifiedName& attrName) 128{ 129 if (!isSupportedAttribute(attrName)) { 130 SVGFilterPrimitiveStandardAttributes::svgAttributeChanged(attrName); 131 return; 132 } 133 134 SVGElementInstance::InvalidationGuard invalidationGuard(this); 135 136 if (attrName == SVGNames::xChannelSelectorAttr || attrName == SVGNames::yChannelSelectorAttr || attrName == SVGNames::scaleAttr) { 137 primitiveAttributeChanged(attrName); 138 return; 139 } 140 141 if (attrName == SVGNames::inAttr || attrName == SVGNames::in2Attr) { 142 invalidate(); 143 return; 144 } 145 146 ASSERT_NOT_REACHED(); 147} 148 149PassRefPtr<FilterEffect> SVGFEDisplacementMapElement::build(SVGFilterBuilder* filterBuilder, Filter* filter) 150{ 151 FilterEffect* input1 = filterBuilder->getEffectById(in1CurrentValue()); 152 FilterEffect* input2 = filterBuilder->getEffectById(in2CurrentValue()); 153 154 if (!input1 || !input2) 155 return 0; 156 157 RefPtr<FilterEffect> effect = FEDisplacementMap::create(filter, xChannelSelectorCurrentValue(), yChannelSelectorCurrentValue(), scaleCurrentValue()); 158 FilterEffectVector& inputEffects = effect->inputEffects(); 159 inputEffects.reserveCapacity(2); 160 inputEffects.append(input1); 161 inputEffects.append(input2); 162 return effect.release(); 163} 164 165} 166