1 /* 2 * Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann (at) kde.org> 3 * Copyright (C) 2004, 2005, 2006 Rob Buis <buis (at) kde.org> 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Library General Public 7 * License as published by the Free Software Foundation; either 8 * version 2 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Library General Public License for more details. 14 * 15 * You should have received a copy of the GNU Library General Public License 16 * along with this library; see the file COPYING.LIB. If not, write to 17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 18 * Boston, MA 02110-1301, USA. 19 */ 20 21 #include "config.h" 22 23 #include "core/svg/SVGFECompositeElement.h" 24 25 #include "SVGNames.h" 26 #include "core/platform/graphics/filters/FilterEffect.h" 27 #include "core/svg/SVGElementInstance.h" 28 #include "core/svg/graphics/filters/SVGFilterBuilder.h" 29 30 namespace WebCore { 31 32 // Animated property definitions 33 DEFINE_ANIMATED_STRING(SVGFECompositeElement, SVGNames::inAttr, In1, in1) 34 DEFINE_ANIMATED_STRING(SVGFECompositeElement, SVGNames::in2Attr, In2, in2) 35 DEFINE_ANIMATED_ENUMERATION(SVGFECompositeElement, SVGNames::operatorAttr, SVGOperator, svgOperator, CompositeOperationType) 36 DEFINE_ANIMATED_NUMBER(SVGFECompositeElement, SVGNames::k1Attr, K1, k1) 37 DEFINE_ANIMATED_NUMBER(SVGFECompositeElement, SVGNames::k2Attr, K2, k2) 38 DEFINE_ANIMATED_NUMBER(SVGFECompositeElement, SVGNames::k3Attr, K3, k3) 39 DEFINE_ANIMATED_NUMBER(SVGFECompositeElement, SVGNames::k4Attr, K4, k4) 40 41 BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGFECompositeElement) 42 REGISTER_LOCAL_ANIMATED_PROPERTY(in1) 43 REGISTER_LOCAL_ANIMATED_PROPERTY(in2) 44 REGISTER_LOCAL_ANIMATED_PROPERTY(svgOperator) 45 REGISTER_LOCAL_ANIMATED_PROPERTY(k1) 46 REGISTER_LOCAL_ANIMATED_PROPERTY(k2) 47 REGISTER_LOCAL_ANIMATED_PROPERTY(k3) 48 REGISTER_LOCAL_ANIMATED_PROPERTY(k4) 49 REGISTER_PARENT_ANIMATED_PROPERTIES(SVGFilterPrimitiveStandardAttributes) 50 END_REGISTER_ANIMATED_PROPERTIES 51 52 inline SVGFECompositeElement::SVGFECompositeElement(const QualifiedName& tagName, Document* document) 53 : SVGFilterPrimitiveStandardAttributes(tagName, document) 54 , m_svgOperator(FECOMPOSITE_OPERATOR_OVER) 55 { 56 ASSERT(hasTagName(SVGNames::feCompositeTag)); 57 ScriptWrappable::init(this); 58 registerAnimatedPropertiesForSVGFECompositeElement(); 59 } 60 61 PassRefPtr<SVGFECompositeElement> SVGFECompositeElement::create(const QualifiedName& tagName, Document* document) 62 { 63 return adoptRef(new SVGFECompositeElement(tagName, document)); 64 } 65 66 bool SVGFECompositeElement::isSupportedAttribute(const QualifiedName& attrName) 67 { 68 DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ()); 69 if (supportedAttributes.isEmpty()) { 70 supportedAttributes.add(SVGNames::inAttr); 71 supportedAttributes.add(SVGNames::in2Attr); 72 supportedAttributes.add(SVGNames::operatorAttr); 73 supportedAttributes.add(SVGNames::k1Attr); 74 supportedAttributes.add(SVGNames::k2Attr); 75 supportedAttributes.add(SVGNames::k3Attr); 76 supportedAttributes.add(SVGNames::k4Attr); 77 } 78 return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName); 79 } 80 81 void SVGFECompositeElement::parseAttribute(const QualifiedName& name, const AtomicString& value) 82 { 83 if (!isSupportedAttribute(name)) { 84 SVGFilterPrimitiveStandardAttributes::parseAttribute(name, value); 85 return; 86 } 87 88 if (name == SVGNames::operatorAttr) { 89 CompositeOperationType propertyValue = SVGPropertyTraits<CompositeOperationType>::fromString(value); 90 if (propertyValue > 0) 91 setSVGOperatorBaseValue(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::k1Attr) { 106 setK1BaseValue(value.toFloat()); 107 return; 108 } 109 110 if (name == SVGNames::k2Attr) { 111 setK2BaseValue(value.toFloat()); 112 return; 113 } 114 115 if (name == SVGNames::k3Attr) { 116 setK3BaseValue(value.toFloat()); 117 return; 118 } 119 120 if (name == SVGNames::k4Attr) { 121 setK4BaseValue(value.toFloat()); 122 return; 123 } 124 125 ASSERT_NOT_REACHED(); 126 } 127 128 bool SVGFECompositeElement::setFilterEffectAttribute(FilterEffect* effect, const QualifiedName& attrName) 129 { 130 FEComposite* composite = static_cast<FEComposite*>(effect); 131 if (attrName == SVGNames::operatorAttr) 132 return composite->setOperation(svgOperatorCurrentValue()); 133 if (attrName == SVGNames::k1Attr) 134 return composite->setK1(k1CurrentValue()); 135 if (attrName == SVGNames::k2Attr) 136 return composite->setK2(k2CurrentValue()); 137 if (attrName == SVGNames::k3Attr) 138 return composite->setK3(k3CurrentValue()); 139 if (attrName == SVGNames::k4Attr) 140 return composite->setK4(k4CurrentValue()); 141 142 ASSERT_NOT_REACHED(); 143 return false; 144 } 145 146 147 void SVGFECompositeElement::svgAttributeChanged(const QualifiedName& attrName) 148 { 149 if (!isSupportedAttribute(attrName)) { 150 SVGFilterPrimitiveStandardAttributes::svgAttributeChanged(attrName); 151 return; 152 } 153 154 SVGElementInstance::InvalidationGuard invalidationGuard(this); 155 156 if (attrName == SVGNames::operatorAttr 157 || attrName == SVGNames::k1Attr 158 || attrName == SVGNames::k2Attr 159 || attrName == SVGNames::k3Attr 160 || attrName == SVGNames::k4Attr) { 161 primitiveAttributeChanged(attrName); 162 return; 163 } 164 165 if (attrName == SVGNames::inAttr || attrName == SVGNames::in2Attr) { 166 invalidate(); 167 return; 168 } 169 170 ASSERT_NOT_REACHED(); 171 } 172 173 PassRefPtr<FilterEffect> SVGFECompositeElement::build(SVGFilterBuilder* filterBuilder, Filter* filter) 174 { 175 FilterEffect* input1 = filterBuilder->getEffectById(in1CurrentValue()); 176 FilterEffect* input2 = filterBuilder->getEffectById(in2CurrentValue()); 177 178 if (!input1 || !input2) 179 return 0; 180 181 RefPtr<FilterEffect> effect = FEComposite::create(filter, svgOperatorCurrentValue(), k1CurrentValue(), k2CurrentValue(), k3CurrentValue(), k4CurrentValue()); 182 FilterEffectVector& inputEffects = effect->inputEffects(); 183 inputEffects.reserveCapacity(2); 184 inputEffects.append(input1); 185 inputEffects.append(input2); 186 return effect.release(); 187 } 188 189 } 190