Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / platform / graphics / filters / FEConvolveMatrix.cpp
1 /*
2  * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
3  * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
4  * Copyright (C) 2005 Eric Seidel <eric@webkit.org>
5  * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
6  * Copyright (C) 2010 Zoltan Herczeg <zherczeg@webkit.org>
7  * Copyright (C) 2013 Google Inc. All rights reserved.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public License
20  * along with this library; see the file COPYING.LIB.  If not, write to
21  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22  * Boston, MA 02110-1301, USA.
23  */
24
25 #include "config.h"
26 #include "platform/graphics/filters/FEConvolveMatrix.h"
27
28 #include "SkMatrixConvolutionImageFilter.h"
29 #include "platform/graphics/filters/SkiaImageFilterBuilder.h"
30 #include "platform/text/TextStream.h"
31 #include "wtf/OwnPtr.h"
32
33 namespace blink {
34
35 FEConvolveMatrix::FEConvolveMatrix(Filter* filter, const IntSize& kernelSize,
36     float divisor, float bias, const IntPoint& targetOffset, EdgeModeType edgeMode,
37     const FloatPoint& kernelUnitLength, bool preserveAlpha, const Vector<float>& kernelMatrix)
38     : FilterEffect(filter)
39     , m_kernelSize(kernelSize)
40     , m_divisor(divisor)
41     , m_bias(bias)
42     , m_targetOffset(targetOffset)
43     , m_edgeMode(edgeMode)
44     , m_kernelUnitLength(kernelUnitLength)
45     , m_preserveAlpha(preserveAlpha)
46     , m_kernelMatrix(kernelMatrix)
47 {
48     ASSERT(m_kernelSize.width() > 0);
49     ASSERT(m_kernelSize.height() > 0);
50 }
51
52 PassRefPtr<FEConvolveMatrix> FEConvolveMatrix::create(Filter* filter, const IntSize& kernelSize,
53     float divisor, float bias, const IntPoint& targetOffset, EdgeModeType edgeMode,
54     const FloatPoint& kernelUnitLength, bool preserveAlpha, const Vector<float>& kernelMatrix)
55 {
56     return adoptRef(new FEConvolveMatrix(filter, kernelSize, divisor, bias, targetOffset, edgeMode, kernelUnitLength,
57         preserveAlpha, kernelMatrix));
58 }
59
60 FloatRect FEConvolveMatrix::mapPaintRect(const FloatRect& rect, bool forward)
61 {
62     FloatRect result = rect;
63
64     result.moveBy(forward ? -m_targetOffset : m_targetOffset - m_kernelSize);
65     result.expand(m_kernelSize);
66     return result;
67 }
68
69 IntSize FEConvolveMatrix::kernelSize() const
70 {
71     return m_kernelSize;
72 }
73
74 void FEConvolveMatrix::setKernelSize(const IntSize& kernelSize)
75 {
76     ASSERT(kernelSize.width() > 0);
77     ASSERT(kernelSize.height() > 0);
78     m_kernelSize = kernelSize;
79 }
80
81 const Vector<float>& FEConvolveMatrix::kernel() const
82 {
83     return m_kernelMatrix;
84 }
85
86 void FEConvolveMatrix::setKernel(const Vector<float>& kernel)
87 {
88     m_kernelMatrix = kernel;
89 }
90
91 float FEConvolveMatrix::divisor() const
92 {
93     return m_divisor;
94 }
95
96 bool FEConvolveMatrix::setDivisor(float divisor)
97 {
98     ASSERT(divisor);
99     if (m_divisor == divisor)
100         return false;
101     m_divisor = divisor;
102     return true;
103 }
104
105 float FEConvolveMatrix::bias() const
106 {
107     return m_bias;
108 }
109
110 bool FEConvolveMatrix::setBias(float bias)
111 {
112     if (m_bias == bias)
113         return false;
114     m_bias = bias;
115     return true;
116 }
117
118 IntPoint FEConvolveMatrix::targetOffset() const
119 {
120     return m_targetOffset;
121 }
122
123 bool FEConvolveMatrix::setTargetOffset(const IntPoint& targetOffset)
124 {
125     if (m_targetOffset == targetOffset)
126         return false;
127     m_targetOffset = targetOffset;
128     return true;
129 }
130
131 EdgeModeType FEConvolveMatrix::edgeMode() const
132 {
133     return m_edgeMode;
134 }
135
136 bool FEConvolveMatrix::setEdgeMode(EdgeModeType edgeMode)
137 {
138     if (m_edgeMode == edgeMode)
139         return false;
140     m_edgeMode = edgeMode;
141     return true;
142 }
143
144 FloatPoint FEConvolveMatrix::kernelUnitLength() const
145 {
146     return m_kernelUnitLength;
147 }
148
149 bool FEConvolveMatrix::setKernelUnitLength(const FloatPoint& kernelUnitLength)
150 {
151     ASSERT(kernelUnitLength.x() > 0);
152     ASSERT(kernelUnitLength.y() > 0);
153     if (m_kernelUnitLength == kernelUnitLength)
154         return false;
155     m_kernelUnitLength = kernelUnitLength;
156     return true;
157 }
158
159 bool FEConvolveMatrix::preserveAlpha() const
160 {
161     return m_preserveAlpha;
162 }
163
164 bool FEConvolveMatrix::setPreserveAlpha(bool preserveAlpha)
165 {
166     if (m_preserveAlpha == preserveAlpha)
167         return false;
168     m_preserveAlpha = preserveAlpha;
169     return true;
170 }
171
172 SkMatrixConvolutionImageFilter::TileMode toSkiaTileMode(EdgeModeType edgeMode)
173 {
174     switch (edgeMode) {
175     case EDGEMODE_DUPLICATE:
176         return SkMatrixConvolutionImageFilter::kClamp_TileMode;
177     case EDGEMODE_WRAP:
178         return SkMatrixConvolutionImageFilter::kRepeat_TileMode;
179     case EDGEMODE_NONE:
180         return SkMatrixConvolutionImageFilter::kClampToBlack_TileMode;
181     default:
182         return SkMatrixConvolutionImageFilter::kClamp_TileMode;
183     }
184 }
185
186 PassRefPtr<SkImageFilter> FEConvolveMatrix::createImageFilter(SkiaImageFilterBuilder* builder)
187 {
188     RefPtr<SkImageFilter> input(builder->build(inputEffect(0), operatingColorSpace()));
189
190     SkISize kernelSize(SkISize::Make(m_kernelSize.width(), m_kernelSize.height()));
191     int numElements = kernelSize.width() * kernelSize.height();
192     SkScalar gain = SkFloatToScalar(1.0f / m_divisor);
193     SkScalar bias = SkFloatToScalar(m_bias * 255);
194     SkIPoint target = SkIPoint::Make(m_targetOffset.x(), m_targetOffset.y());
195     SkMatrixConvolutionImageFilter::TileMode tileMode = toSkiaTileMode(m_edgeMode);
196     bool convolveAlpha = !m_preserveAlpha;
197     OwnPtr<SkScalar[]> kernel = adoptArrayPtr(new SkScalar[numElements]);
198     for (int i = 0; i < numElements; ++i)
199         kernel[i] = SkFloatToScalar(m_kernelMatrix[numElements - 1 - i]);
200     SkImageFilter::CropRect cropRect = getCropRect(builder->cropOffset());
201     return adoptRef(SkMatrixConvolutionImageFilter::Create(kernelSize, kernel.get(), gain, bias, target, tileMode, convolveAlpha, input.get(), &cropRect));
202 }
203
204 static TextStream& operator<<(TextStream& ts, const EdgeModeType& type)
205 {
206     switch (type) {
207     case EDGEMODE_UNKNOWN:
208         ts << "UNKNOWN";
209         break;
210     case EDGEMODE_DUPLICATE:
211         ts << "DUPLICATE";
212         break;
213     case EDGEMODE_WRAP:
214         ts << "WRAP";
215         break;
216     case EDGEMODE_NONE:
217         ts << "NONE";
218         break;
219     }
220     return ts;
221 }
222
223 TextStream& FEConvolveMatrix::externalRepresentation(TextStream& ts, int indent) const
224 {
225     writeIndent(ts, indent);
226     ts << "[feConvolveMatrix";
227     FilterEffect::externalRepresentation(ts);
228     ts << " order=\"" << m_kernelSize << "\" "
229        << "kernelMatrix=\"" << m_kernelMatrix  << "\" "
230        << "divisor=\"" << m_divisor << "\" "
231        << "bias=\"" << m_bias << "\" "
232        << "target=\"" << m_targetOffset << "\" "
233        << "edgeMode=\"" << m_edgeMode << "\" "
234        << "kernelUnitLength=\"" << m_kernelUnitLength << "\" "
235        << "preserveAlpha=\"" << m_preserveAlpha << "\"]\n";
236     inputEffect(0)->externalRepresentation(ts, indent + 1);
237     return ts;
238 }
239
240 }; // namespace blink