1/* 2 * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> 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/SVGFEMorphologyElement.h" 23 24#include "SVGNames.h" 25#include "platform/graphics/filters/FilterEffect.h" 26#include "core/svg/SVGElementInstance.h" 27#include "core/svg/SVGParserUtilities.h" 28#include "core/svg/graphics/filters/SVGFilterBuilder.h" 29 30namespace WebCore { 31 32// Animated property definitions 33DEFINE_ANIMATED_STRING(SVGFEMorphologyElement, SVGNames::inAttr, In1, in1) 34DEFINE_ANIMATED_ENUMERATION(SVGFEMorphologyElement, SVGNames::operatorAttr, SVGOperator, svgOperator, MorphologyOperatorType) 35DEFINE_ANIMATED_NUMBER_MULTIPLE_WRAPPERS(SVGFEMorphologyElement, SVGNames::radiusAttr, radiusXIdentifier(), RadiusX, radiusX) 36DEFINE_ANIMATED_NUMBER_MULTIPLE_WRAPPERS(SVGFEMorphologyElement, SVGNames::radiusAttr, radiusYIdentifier(), RadiusY, radiusY) 37 38BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGFEMorphologyElement) 39 REGISTER_LOCAL_ANIMATED_PROPERTY(in1) 40 REGISTER_LOCAL_ANIMATED_PROPERTY(svgOperator) 41 REGISTER_LOCAL_ANIMATED_PROPERTY(radiusX) 42 REGISTER_LOCAL_ANIMATED_PROPERTY(radiusY) 43 REGISTER_PARENT_ANIMATED_PROPERTIES(SVGFilterPrimitiveStandardAttributes) 44END_REGISTER_ANIMATED_PROPERTIES 45 46inline SVGFEMorphologyElement::SVGFEMorphologyElement(Document& document) 47 : SVGFilterPrimitiveStandardAttributes(SVGNames::feMorphologyTag, document) 48 , m_svgOperator(FEMORPHOLOGY_OPERATOR_ERODE) 49{ 50 ScriptWrappable::init(this); 51 registerAnimatedPropertiesForSVGFEMorphologyElement(); 52} 53 54PassRefPtr<SVGFEMorphologyElement> SVGFEMorphologyElement::create(Document& document) 55{ 56 return adoptRef(new SVGFEMorphologyElement(document)); 57} 58 59const AtomicString& SVGFEMorphologyElement::radiusXIdentifier() 60{ 61 DEFINE_STATIC_LOCAL(AtomicString, s_identifier, ("SVGRadiusX", AtomicString::ConstructFromLiteral)); 62 return s_identifier; 63} 64 65const AtomicString& SVGFEMorphologyElement::radiusYIdentifier() 66{ 67 DEFINE_STATIC_LOCAL(AtomicString, s_identifier, ("SVGRadiusY", AtomicString::ConstructFromLiteral)); 68 return s_identifier; 69} 70 71void SVGFEMorphologyElement::setRadius(float x, float y) 72{ 73 setRadiusXBaseValue(x); 74 setRadiusYBaseValue(y); 75 invalidate(); 76} 77 78bool SVGFEMorphologyElement::isSupportedAttribute(const QualifiedName& attrName) 79{ 80 DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ()); 81 if (supportedAttributes.isEmpty()) { 82 supportedAttributes.add(SVGNames::inAttr); 83 supportedAttributes.add(SVGNames::operatorAttr); 84 supportedAttributes.add(SVGNames::radiusAttr); 85 } 86 return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName); 87} 88 89void SVGFEMorphologyElement::parseAttribute(const QualifiedName& name, const AtomicString& value) 90{ 91 if (!isSupportedAttribute(name)) { 92 SVGFilterPrimitiveStandardAttributes::parseAttribute(name, value); 93 return; 94 } 95 96 if (name == SVGNames::operatorAttr) { 97 MorphologyOperatorType propertyValue = SVGPropertyTraits<MorphologyOperatorType>::fromString(value); 98 if (propertyValue > 0) 99 setSVGOperatorBaseValue(propertyValue); 100 return; 101 } 102 103 if (name == SVGNames::inAttr) { 104 setIn1BaseValue(value); 105 return; 106 } 107 108 if (name == SVGNames::radiusAttr) { 109 float x, y; 110 if (parseNumberOptionalNumber(value, x, y)) { 111 setRadiusXBaseValue(x); 112 setRadiusYBaseValue(y); 113 } 114 return; 115 } 116 117 ASSERT_NOT_REACHED(); 118} 119 120bool SVGFEMorphologyElement::setFilterEffectAttribute(FilterEffect* effect, const QualifiedName& attrName) 121{ 122 FEMorphology* morphology = static_cast<FEMorphology*>(effect); 123 if (attrName == SVGNames::operatorAttr) 124 return morphology->setMorphologyOperator(svgOperatorCurrentValue()); 125 if (attrName == SVGNames::radiusAttr) { 126 // Both setRadius functions should be evaluated separately. 127 bool isRadiusXChanged = morphology->setRadiusX(radiusXCurrentValue()); 128 bool isRadiusYChanged = morphology->setRadiusY(radiusYCurrentValue()); 129 return isRadiusXChanged || isRadiusYChanged; 130 } 131 132 ASSERT_NOT_REACHED(); 133 return false; 134} 135 136void SVGFEMorphologyElement::svgAttributeChanged(const QualifiedName& attrName) 137{ 138 if (!isSupportedAttribute(attrName)) { 139 SVGFilterPrimitiveStandardAttributes::svgAttributeChanged(attrName); 140 return; 141 } 142 143 SVGElementInstance::InvalidationGuard invalidationGuard(this); 144 145 if (attrName == SVGNames::operatorAttr || attrName == SVGNames::radiusAttr) { 146 primitiveAttributeChanged(attrName); 147 return; 148 } 149 150 if (attrName == SVGNames::inAttr) { 151 invalidate(); 152 return; 153 } 154 155 ASSERT_NOT_REACHED(); 156} 157 158PassRefPtr<FilterEffect> SVGFEMorphologyElement::build(SVGFilterBuilder* filterBuilder, Filter* filter) 159{ 160 FilterEffect* input1 = filterBuilder->getEffectById(in1CurrentValue()); 161 float xRadius = radiusXCurrentValue(); 162 float yRadius = radiusYCurrentValue(); 163 164 if (!input1) 165 return 0; 166 167 if (xRadius < 0 || yRadius < 0) 168 return 0; 169 170 RefPtr<FilterEffect> effect = FEMorphology::create(filter, svgOperatorCurrentValue(), xRadius, yRadius); 171 effect->inputEffects().append(input1); 172 return effect.release(); 173} 174 175} // namespace WebCore 176