693411e5fcafe0855ae58da59d5fbc249016a121
[WebKit-https.git] / WebCore / svg / SVGFEConvolveMatrixElement.cpp
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 "FloatPoint.h"
27 #include "FloatSize.h"
28 #include "IntPoint.h"
29 #include "IntSize.h"
30 #include "SVGNames.h"
31 #include "SVGNumberList.h"
32 #include "SVGParserUtilities.h"
33
34 #include <math.h>
35
36 namespace WebCore {
37
38 inline SVGFEConvolveMatrixElement::SVGFEConvolveMatrixElement(const QualifiedName& tagName, Document* document)
39     : SVGFilterPrimitiveStandardAttributes(tagName, document)
40     , m_edgeMode(EDGEMODE_DUPLICATE)
41 {
42 }
43
44 PassRefPtr<SVGFEConvolveMatrixElement> SVGFEConvolveMatrixElement::create(const QualifiedName& tagName, Document* document)
45 {
46     return adoptRef(new SVGFEConvolveMatrixElement(tagName, document));
47 }
48
49 const AtomicString& SVGFEConvolveMatrixElement::kernelUnitLengthXIdentifier()
50 {
51     DEFINE_STATIC_LOCAL(AtomicString, s_identifier, ("SVGKernelUnitLengthX"));
52     return s_identifier;
53 }
54
55 const AtomicString& SVGFEConvolveMatrixElement::kernelUnitLengthYIdentifier()
56 {
57     DEFINE_STATIC_LOCAL(AtomicString, s_identifier, ("SVGKernelUnitLengthY"));
58     return s_identifier;
59 }
60
61 void SVGFEConvolveMatrixElement::parseMappedAttribute(Attribute* attr)
62 {
63     const String& value = attr->value();
64     if (attr->name() == SVGNames::inAttr)
65         setIn1BaseValue(value);
66     else if (attr->name() == SVGNames::orderAttr) {
67         float x, y;
68         if (parseNumberOptionalNumber(value, x, y)) {
69             setOrderXBaseValue(x);
70             setOrderYBaseValue(y);
71         }
72     } else if (attr->name() == SVGNames::edgeModeAttr) {
73         if (value == "duplicate")
74             setEdgeModeBaseValue(EDGEMODE_DUPLICATE);
75         else if (value == "wrap")
76             setEdgeModeBaseValue(EDGEMODE_WRAP);
77         else if (value == "none")
78             setEdgeModeBaseValue(EDGEMODE_NONE);
79     } else if (attr->name() == SVGNames::kernelMatrixAttr) {
80         SVGNumberList newList;
81         newList.parse(value);
82         detachAnimatedKernelMatrixListWrappers(newList.size());
83         kernelMatrixBaseValue() = newList;
84     } else if (attr->name() == SVGNames::divisorAttr)
85         setDivisorBaseValue(value.toFloat());
86     else if (attr->name() == SVGNames::biasAttr)
87         setBiasBaseValue(value.toFloat());
88     else if (attr->name() == SVGNames::targetXAttr)
89         setTargetXBaseValue(value.toUIntStrict());
90     else if (attr->name() == SVGNames::targetYAttr)
91         setTargetYBaseValue(value.toUIntStrict());
92     else if (attr->name() == SVGNames::kernelUnitLengthAttr) {
93         float x, y;
94         if (parseNumberOptionalNumber(value, x, y)) {
95             setKernelUnitLengthXBaseValue(x);
96             setKernelUnitLengthYBaseValue(y);
97         }
98     } else if (attr->name() == SVGNames::preserveAlphaAttr) {
99         if (value == "true")
100             setPreserveAlphaBaseValue(true);
101         else if (value == "false")
102             setPreserveAlphaBaseValue(false);
103     } else
104         SVGFilterPrimitiveStandardAttributes::parseMappedAttribute(attr);
105 }
106
107 void SVGFEConvolveMatrixElement::setOrder(float x, float y)
108 {
109     setOrderXBaseValue(x);
110     setOrderYBaseValue(y);
111     invalidate();
112 }
113
114 void SVGFEConvolveMatrixElement::setKernelUnitLength(float x, float y)
115 {
116     setKernelUnitLengthXBaseValue(x);
117     setKernelUnitLengthYBaseValue(y);
118     invalidate();
119 }
120
121 void SVGFEConvolveMatrixElement::svgAttributeChanged(const QualifiedName& attrName)
122 {
123     SVGFilterPrimitiveStandardAttributes::svgAttributeChanged(attrName);
124
125     if (attrName == SVGNames::inAttr
126         || attrName == SVGNames::orderAttr
127         || attrName == SVGNames::edgeModeAttr
128         || attrName == SVGNames::kernelMatrixAttr
129         || attrName == SVGNames::divisorAttr
130         || attrName == SVGNames::biasAttr
131         || attrName == SVGNames::targetXAttr
132         || attrName == SVGNames::targetYAttr
133         || attrName == SVGNames::kernelUnitLengthAttr
134         || attrName == SVGNames::preserveAlphaAttr)
135         invalidate();
136 }
137
138 PassRefPtr<FilterEffect> SVGFEConvolveMatrixElement::build(SVGFilterBuilder* filterBuilder)
139 {
140     FilterEffect* input1 = filterBuilder->getEffectById(in1());
141
142     if (!input1)
143         return 0;
144
145     int orderXValue = orderX();
146     int orderYValue = orderY();
147     if (!hasAttribute(SVGNames::orderAttr)) {
148         orderXValue = 3;
149         orderYValue = 3;
150     }
151     SVGNumberList& kernelMatrix = this->kernelMatrix();
152     int kernelMatrixSize = kernelMatrix.size();
153     // The spec says this is a requirement, and should bail out if fails
154     if (orderXValue * orderYValue != kernelMatrixSize)
155         return 0;
156
157     int targetXValue = targetX();
158     int targetYValue = targetY();
159     if (hasAttribute(SVGNames::targetXAttr) && (targetXValue < 0 || targetXValue >= orderXValue))
160         return 0;
161     // The spec says the default value is: targetX = floor ( orderX / 2 ))
162     if (!hasAttribute(SVGNames::targetXAttr))
163         targetXValue = static_cast<int>(floorf(orderXValue / 2));
164     if (hasAttribute(SVGNames::targetYAttr) && (targetYValue < 0 || targetYValue >= orderYValue))
165         return 0;
166     // The spec says the default value is: targetY = floor ( orderY / 2 ))
167     if (!hasAttribute(SVGNames::targetYAttr))
168         targetYValue = static_cast<int>(floorf(orderYValue / 2));
169
170     float divisorValue = divisor();
171     if (hasAttribute(SVGNames::divisorAttr) && !divisorValue)
172         return 0;
173     if (!hasAttribute(SVGNames::divisorAttr)) {
174         for (int i = 0; i < kernelMatrixSize; ++i)
175             divisorValue += kernelMatrix.at(i);
176         if (!divisorValue)
177             divisorValue = 1;
178     }
179
180     RefPtr<FilterEffect> effect = FEConvolveMatrix::create(
181                     IntSize(orderXValue, orderYValue), divisorValue,
182                     bias(), IntPoint(targetXValue, targetYValue), static_cast<EdgeModeType>(edgeMode()),
183                     FloatPoint(kernelUnitLengthX(), kernelUnitLengthX()), preserveAlpha(), kernelMatrix);
184     effect->inputEffects().append(input1);
185     return effect.release();
186 }
187
188 } // namespace WebCore
189
190 #endif // ENABLE(SVG)