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.
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.
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.
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.
26 #include "platform/graphics/filters/FEConvolveMatrix.h"
28 #include "SkMatrixConvolutionImageFilter.h"
29 #include "platform/graphics/filters/SkiaImageFilterBuilder.h"
30 #include "platform/text/TextStream.h"
31 #include "wtf/OwnPtr.h"
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)
42 , m_targetOffset(targetOffset)
43 , m_edgeMode(edgeMode)
44 , m_kernelUnitLength(kernelUnitLength)
45 , m_preserveAlpha(preserveAlpha)
46 , m_kernelMatrix(kernelMatrix)
48 ASSERT(m_kernelSize.width() > 0);
49 ASSERT(m_kernelSize.height() > 0);
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)
56 return adoptRef(new FEConvolveMatrix(filter, kernelSize, divisor, bias, targetOffset, edgeMode, kernelUnitLength,
57 preserveAlpha, kernelMatrix));
60 FloatRect FEConvolveMatrix::mapPaintRect(const FloatRect& rect, bool forward)
62 FloatRect result = rect;
64 result.moveBy(forward ? -m_targetOffset : m_targetOffset - m_kernelSize);
65 result.expand(m_kernelSize);
69 IntSize FEConvolveMatrix::kernelSize() const
74 void FEConvolveMatrix::setKernelSize(const IntSize& kernelSize)
76 ASSERT(kernelSize.width() > 0);
77 ASSERT(kernelSize.height() > 0);
78 m_kernelSize = kernelSize;
81 const Vector<float>& FEConvolveMatrix::kernel() const
83 return m_kernelMatrix;
86 void FEConvolveMatrix::setKernel(const Vector<float>& kernel)
88 m_kernelMatrix = kernel;
91 float FEConvolveMatrix::divisor() const
96 bool FEConvolveMatrix::setDivisor(float divisor)
99 if (m_divisor == divisor)
105 float FEConvolveMatrix::bias() const
110 bool FEConvolveMatrix::setBias(float bias)
118 IntPoint FEConvolveMatrix::targetOffset() const
120 return m_targetOffset;
123 bool FEConvolveMatrix::setTargetOffset(const IntPoint& targetOffset)
125 if (m_targetOffset == targetOffset)
127 m_targetOffset = targetOffset;
131 EdgeModeType FEConvolveMatrix::edgeMode() const
136 bool FEConvolveMatrix::setEdgeMode(EdgeModeType edgeMode)
138 if (m_edgeMode == edgeMode)
140 m_edgeMode = edgeMode;
144 FloatPoint FEConvolveMatrix::kernelUnitLength() const
146 return m_kernelUnitLength;
149 bool FEConvolveMatrix::setKernelUnitLength(const FloatPoint& kernelUnitLength)
151 ASSERT(kernelUnitLength.x() > 0);
152 ASSERT(kernelUnitLength.y() > 0);
153 if (m_kernelUnitLength == kernelUnitLength)
155 m_kernelUnitLength = kernelUnitLength;
159 bool FEConvolveMatrix::preserveAlpha() const
161 return m_preserveAlpha;
164 bool FEConvolveMatrix::setPreserveAlpha(bool preserveAlpha)
166 if (m_preserveAlpha == preserveAlpha)
168 m_preserveAlpha = preserveAlpha;
172 SkMatrixConvolutionImageFilter::TileMode toSkiaTileMode(EdgeModeType edgeMode)
175 case EDGEMODE_DUPLICATE:
176 return SkMatrixConvolutionImageFilter::kClamp_TileMode;
178 return SkMatrixConvolutionImageFilter::kRepeat_TileMode;
180 return SkMatrixConvolutionImageFilter::kClampToBlack_TileMode;
182 return SkMatrixConvolutionImageFilter::kClamp_TileMode;
186 PassRefPtr<SkImageFilter> FEConvolveMatrix::createImageFilter(SkiaImageFilterBuilder* builder)
188 RefPtr<SkImageFilter> input(builder->build(inputEffect(0), operatingColorSpace()));
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));
204 static TextStream& operator<<(TextStream& ts, const EdgeModeType& type)
207 case EDGEMODE_UNKNOWN:
210 case EDGEMODE_DUPLICATE:
223 TextStream& FEConvolveMatrix::externalRepresentation(TextStream& ts, int indent) const
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);
240 }; // namespace blink