• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #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
DEFINE_ANIMATED_STRING(SVGFEConvolveMatrixElement,SVGNames::inAttr,In1,in1)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 
create(const QualifiedName & tagName,Document * document)56 PassRefPtr<SVGFEConvolveMatrixElement> SVGFEConvolveMatrixElement::create(const QualifiedName& tagName, Document* document)
57 {
58     return adoptRef(new SVGFEConvolveMatrixElement(tagName, document));
59 }
60 
kernelUnitLengthXIdentifier()61 const AtomicString& SVGFEConvolveMatrixElement::kernelUnitLengthXIdentifier()
62 {
63     DEFINE_STATIC_LOCAL(AtomicString, s_identifier, ("SVGKernelUnitLengthX"));
64     return s_identifier;
65 }
66 
kernelUnitLengthYIdentifier()67 const AtomicString& SVGFEConvolveMatrixElement::kernelUnitLengthYIdentifier()
68 {
69     DEFINE_STATIC_LOCAL(AtomicString, s_identifier, ("SVGKernelUnitLengthY"));
70     return s_identifier;
71 }
72 
orderXIdentifier()73 const AtomicString& SVGFEConvolveMatrixElement::orderXIdentifier()
74 {
75     DEFINE_STATIC_LOCAL(AtomicString, s_identifier, ("SVGOrderX"));
76     return s_identifier;
77 }
78 
orderYIdentifier()79 const AtomicString& SVGFEConvolveMatrixElement::orderYIdentifier()
80 {
81     DEFINE_STATIC_LOCAL(AtomicString, s_identifier, ("SVGOrderY"));
82     return s_identifier;
83 }
84 
parseMappedAttribute(Attribute * attr)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 
setFilterEffectAttribute(FilterEffect * effect,const QualifiedName & attrName)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 
setOrder(float x,float y)153 void SVGFEConvolveMatrixElement::setOrder(float x, float y)
154 {
155     setOrderXBaseValue(x);
156     setOrderYBaseValue(y);
157     invalidate();
158 }
159 
setKernelUnitLength(float x,float y)160 void SVGFEConvolveMatrixElement::setKernelUnitLength(float x, float y)
161 {
162     setKernelUnitLengthXBaseValue(x);
163     setKernelUnitLengthYBaseValue(y);
164     invalidate();
165 }
166 
svgAttributeChanged(const QualifiedName & attrName)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 
attributeToPropertyTypeMap()186 AttributeToPropertyTypeMap& SVGFEConvolveMatrixElement::attributeToPropertyTypeMap()
187 {
188     DEFINE_STATIC_LOCAL(AttributeToPropertyTypeMap, s_attributeToPropertyTypeMap, ());
189     return s_attributeToPropertyTypeMap;
190 }
191 
fillAttributeToPropertyTypeMap()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 
build(SVGFilterBuilder * filterBuilder,Filter * filter)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