1 /* 2 * Copyright (C) 2009 Dirk Schulze <krit (at) 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 #if ENABLE(SVG) && ENABLE(FILTERS) 23 #include "SVGFEConvolveMatrixElement.h" 24 25 #include "Attr.h" 26 #include "FilterEffect.h" 27 #include "FloatPoint.h" 28 #include "IntPoint.h" 29 #include "IntSize.h" 30 #include "SVGFilterBuilder.h" 31 #include "SVGNames.h" 32 #include "SVGParserUtilities.h" 33 34 namespace WebCore { 35 36 // Animated property definitions 37 DEFINE_ANIMATED_STRING(SVGFEConvolveMatrixElement, SVGNames::inAttr, In1, in1) 38 DEFINE_ANIMATED_INTEGER_MULTIPLE_WRAPPERS(SVGFEConvolveMatrixElement, SVGNames::orderAttr, orderXIdentifier(), OrderX, orderX) 39 DEFINE_ANIMATED_INTEGER_MULTIPLE_WRAPPERS(SVGFEConvolveMatrixElement, SVGNames::orderAttr, orderYIdentifier(), OrderY, orderY) 40 DEFINE_ANIMATED_NUMBER_LIST(SVGFEConvolveMatrixElement, SVGNames::kernelMatrixAttr, KernelMatrix, kernelMatrix) 41 DEFINE_ANIMATED_NUMBER(SVGFEConvolveMatrixElement, SVGNames::divisorAttr, Divisor, divisor) 42 DEFINE_ANIMATED_NUMBER(SVGFEConvolveMatrixElement, SVGNames::biasAttr, Bias, bias) 43 DEFINE_ANIMATED_INTEGER(SVGFEConvolveMatrixElement, SVGNames::targetXAttr, TargetX, targetX) 44 DEFINE_ANIMATED_INTEGER(SVGFEConvolveMatrixElement, SVGNames::targetYAttr, TargetY, targetY) 45 DEFINE_ANIMATED_ENUMERATION(SVGFEConvolveMatrixElement, SVGNames::operatorAttr, EdgeMode, edgeMode) 46 DEFINE_ANIMATED_NUMBER_MULTIPLE_WRAPPERS(SVGFEConvolveMatrixElement, SVGNames::kernelUnitLengthAttr, kernelUnitLengthXIdentifier(), KernelUnitLengthX, kernelUnitLengthX) 47 DEFINE_ANIMATED_NUMBER_MULTIPLE_WRAPPERS(SVGFEConvolveMatrixElement, SVGNames::kernelUnitLengthAttr, kernelUnitLengthYIdentifier(), KernelUnitLengthY, kernelUnitLengthY) 48 DEFINE_ANIMATED_BOOLEAN(SVGFEConvolveMatrixElement, SVGNames::preserveAlphaAttr, PreserveAlpha, preserveAlpha) 49 50 inline SVGFEConvolveMatrixElement::SVGFEConvolveMatrixElement(const QualifiedName& tagName, Document* document) 51 : SVGFilterPrimitiveStandardAttributes(tagName, document) 52 , m_edgeMode(EDGEMODE_DUPLICATE) 53 { 54 } 55 56 PassRefPtr<SVGFEConvolveMatrixElement> SVGFEConvolveMatrixElement::create(const QualifiedName& tagName, Document* document) 57 { 58 return adoptRef(new SVGFEConvolveMatrixElement(tagName, document)); 59 } 60 61 const AtomicString& SVGFEConvolveMatrixElement::kernelUnitLengthXIdentifier() 62 { 63 DEFINE_STATIC_LOCAL(AtomicString, s_identifier, ("SVGKernelUnitLengthX")); 64 return s_identifier; 65 } 66 67 const AtomicString& SVGFEConvolveMatrixElement::kernelUnitLengthYIdentifier() 68 { 69 DEFINE_STATIC_LOCAL(AtomicString, s_identifier, ("SVGKernelUnitLengthY")); 70 return s_identifier; 71 } 72 73 const AtomicString& SVGFEConvolveMatrixElement::orderXIdentifier() 74 { 75 DEFINE_STATIC_LOCAL(AtomicString, s_identifier, ("SVGOrderX")); 76 return s_identifier; 77 } 78 79 const AtomicString& SVGFEConvolveMatrixElement::orderYIdentifier() 80 { 81 DEFINE_STATIC_LOCAL(AtomicString, s_identifier, ("SVGOrderY")); 82 return s_identifier; 83 } 84 85 void SVGFEConvolveMatrixElement::parseMappedAttribute(Attribute* attr) 86 { 87 const String& value = attr->value(); 88 if (attr->name() == SVGNames::inAttr) 89 setIn1BaseValue(value); 90 else if (attr->name() == SVGNames::orderAttr) { 91 float x, y; 92 if (parseNumberOptionalNumber(value, x, y)) { 93 setOrderXBaseValue(x); 94 setOrderYBaseValue(y); 95 } 96 } else if (attr->name() == SVGNames::edgeModeAttr) { 97 if (value == "duplicate") 98 setEdgeModeBaseValue(EDGEMODE_DUPLICATE); 99 else if (value == "wrap") 100 setEdgeModeBaseValue(EDGEMODE_WRAP); 101 else if (value == "none") 102 setEdgeModeBaseValue(EDGEMODE_NONE); 103 } else if (attr->name() == SVGNames::kernelMatrixAttr) { 104 SVGNumberList newList; 105 newList.parse(value); 106 detachAnimatedKernelMatrixListWrappers(newList.size()); 107 setKernelMatrixBaseValue(newList); 108 } else if (attr->name() == SVGNames::divisorAttr) 109 setDivisorBaseValue(value.toFloat()); 110 else if (attr->name() == SVGNames::biasAttr) 111 setBiasBaseValue(value.toFloat()); 112 else if (attr->name() == SVGNames::targetXAttr) 113 setTargetXBaseValue(value.toUIntStrict()); 114 else if (attr->name() == SVGNames::targetYAttr) 115 setTargetYBaseValue(value.toUIntStrict()); 116 else if (attr->name() == SVGNames::kernelUnitLengthAttr) { 117 float x, y; 118 if (parseNumberOptionalNumber(value, x, y)) { 119 setKernelUnitLengthXBaseValue(x); 120 setKernelUnitLengthYBaseValue(y); 121 } 122 } else if (attr->name() == SVGNames::preserveAlphaAttr) { 123 if (value == "true") 124 setPreserveAlphaBaseValue(true); 125 else if (value == "false") 126 setPreserveAlphaBaseValue(false); 127 } else 128 SVGFilterPrimitiveStandardAttributes::parseMappedAttribute(attr); 129 } 130 131 bool SVGFEConvolveMatrixElement::setFilterEffectAttribute(FilterEffect* effect, const QualifiedName& attrName) 132 { 133 FEConvolveMatrix* convolveMatrix = static_cast<FEConvolveMatrix*>(effect); 134 if (attrName == SVGNames::edgeModeAttr) 135 return convolveMatrix->setEdgeMode(static_cast<EdgeModeType>(edgeMode())); 136 if (attrName == SVGNames::divisorAttr) 137 return convolveMatrix->setDivisor(divisor()); 138 if (attrName == SVGNames::biasAttr) 139 return convolveMatrix->setBias(bias()); 140 if (attrName == SVGNames::targetXAttr) 141 return convolveMatrix->setTargetOffset(IntPoint(targetX(), targetY())); 142 if (attrName == SVGNames::targetYAttr) 143 return convolveMatrix->setTargetOffset(IntPoint(targetX(), targetY())); 144 if (attrName == SVGNames::kernelUnitLengthAttr) 145 return convolveMatrix->setKernelUnitLength(FloatPoint(kernelUnitLengthX(), kernelUnitLengthY())); 146 if (attrName == SVGNames::preserveAlphaAttr) 147 return convolveMatrix->setPreserveAlpha(preserveAlpha()); 148 149 ASSERT_NOT_REACHED(); 150 return false; 151 } 152 153 void SVGFEConvolveMatrixElement::setOrder(float x, float y) 154 { 155 setOrderXBaseValue(x); 156 setOrderYBaseValue(y); 157 invalidate(); 158 } 159 160 void SVGFEConvolveMatrixElement::setKernelUnitLength(float x, float y) 161 { 162 setKernelUnitLengthXBaseValue(x); 163 setKernelUnitLengthYBaseValue(y); 164 invalidate(); 165 } 166 167 void SVGFEConvolveMatrixElement::svgAttributeChanged(const QualifiedName& attrName) 168 { 169 SVGFilterPrimitiveStandardAttributes::svgAttributeChanged(attrName); 170 171 if (attrName == SVGNames::edgeModeAttr 172 || attrName == SVGNames::divisorAttr 173 || attrName == SVGNames::biasAttr 174 || attrName == SVGNames::targetXAttr 175 || attrName == SVGNames::targetYAttr 176 || attrName == SVGNames::kernelUnitLengthAttr 177 || attrName == SVGNames::preserveAlphaAttr) 178 primitiveAttributeChanged(attrName); 179 180 if (attrName == SVGNames::inAttr 181 || attrName == SVGNames::orderAttr 182 || attrName == SVGNames::kernelMatrixAttr) 183 invalidate(); 184 } 185 186 AttributeToPropertyTypeMap& SVGFEConvolveMatrixElement::attributeToPropertyTypeMap() 187 { 188 DEFINE_STATIC_LOCAL(AttributeToPropertyTypeMap, s_attributeToPropertyTypeMap, ()); 189 return s_attributeToPropertyTypeMap; 190 } 191 192 void SVGFEConvolveMatrixElement::fillAttributeToPropertyTypeMap() 193 { 194 AttributeToPropertyTypeMap& attributeToPropertyTypeMap = this->attributeToPropertyTypeMap(); 195 196 SVGFilterPrimitiveStandardAttributes::fillPassedAttributeToPropertyTypeMap(attributeToPropertyTypeMap); 197 attributeToPropertyTypeMap.set(SVGNames::inAttr, AnimatedString); 198 attributeToPropertyTypeMap.set(SVGNames::orderAttr, AnimatedNumberOptionalNumber); 199 attributeToPropertyTypeMap.set(SVGNames::kernelMatrixAttr, AnimatedNumberList); 200 attributeToPropertyTypeMap.set(SVGNames::divisorAttr, AnimatedNumber); 201 attributeToPropertyTypeMap.set(SVGNames::biasAttr, AnimatedNumber); 202 attributeToPropertyTypeMap.set(SVGNames::targetXAttr, AnimatedInteger); 203 attributeToPropertyTypeMap.set(SVGNames::targetYAttr, AnimatedInteger); 204 attributeToPropertyTypeMap.set(SVGNames::operatorAttr, AnimatedEnumeration); 205 attributeToPropertyTypeMap.set(SVGNames::kernelUnitLengthAttr, AnimatedNumberOptionalNumber); 206 attributeToPropertyTypeMap.set(SVGNames::preserveAlphaAttr, AnimatedBoolean); 207 } 208 209 PassRefPtr<FilterEffect> SVGFEConvolveMatrixElement::build(SVGFilterBuilder* filterBuilder, Filter* filter) 210 { 211 FilterEffect* input1 = filterBuilder->getEffectById(in1()); 212 213 if (!input1) 214 return 0; 215 216 int orderXValue = orderX(); 217 int orderYValue = orderY(); 218 if (!hasAttribute(SVGNames::orderAttr)) { 219 orderXValue = 3; 220 orderYValue = 3; 221 } 222 SVGNumberList& kernelMatrix = this->kernelMatrix(); 223 int kernelMatrixSize = kernelMatrix.size(); 224 // The spec says this is a requirement, and should bail out if fails 225 if (orderXValue * orderYValue != kernelMatrixSize) 226 return 0; 227 228 int targetXValue = targetX(); 229 int targetYValue = targetY(); 230 if (hasAttribute(SVGNames::targetXAttr) && (targetXValue < 0 || targetXValue >= orderXValue)) 231 return 0; 232 // The spec says the default value is: targetX = floor ( orderX / 2 )) 233 if (!hasAttribute(SVGNames::targetXAttr)) 234 targetXValue = static_cast<int>(floorf(orderXValue / 2)); 235 if (hasAttribute(SVGNames::targetYAttr) && (targetYValue < 0 || targetYValue >= orderYValue)) 236 return 0; 237 // The spec says the default value is: targetY = floor ( orderY / 2 )) 238 if (!hasAttribute(SVGNames::targetYAttr)) 239 targetYValue = static_cast<int>(floorf(orderYValue / 2)); 240 241 float divisorValue = divisor(); 242 if (hasAttribute(SVGNames::divisorAttr) && !divisorValue) 243 return 0; 244 if (!hasAttribute(SVGNames::divisorAttr)) { 245 for (int i = 0; i < kernelMatrixSize; ++i) 246 divisorValue += kernelMatrix.at(i); 247 if (!divisorValue) 248 divisorValue = 1; 249 } 250 251 RefPtr<FilterEffect> effect = FEConvolveMatrix::create(filter, 252 IntSize(orderXValue, orderYValue), divisorValue, 253 bias(), IntPoint(targetXValue, targetYValue), static_cast<EdgeModeType>(edgeMode()), 254 FloatPoint(kernelUnitLengthX(), kernelUnitLengthX()), preserveAlpha(), kernelMatrix); 255 effect->inputEffects().append(input1); 256 return effect.release(); 257 } 258 259 } // namespace WebCore 260 261 #endif // ENABLE(SVG) 262