summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/platform/graphics/filters/fe_convolve_matrix.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/blink/renderer/platform/graphics/filters/fe_convolve_matrix.cc')
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/filters/fe_convolve_matrix.cc197
1 files changed, 197 insertions, 0 deletions
diff --git a/chromium/third_party/blink/renderer/platform/graphics/filters/fe_convolve_matrix.cc b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_convolve_matrix.cc
new file mode 100644
index 00000000000..d9ac47ac002
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_convolve_matrix.cc
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
+ * Copyright (C) 2005 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
+ * Copyright (C) 2010 Zoltan Herczeg <zherczeg@webkit.org>
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "third_party/blink/renderer/platform/graphics/filters/fe_convolve_matrix.h"
+
+#include <memory>
+#include "SkMatrixConvolutionImageFilter.h"
+#include "third_party/blink/renderer/platform/graphics/filters/paint_filter_builder.h"
+#include "third_party/blink/renderer/platform/text/text_stream.h"
+#include "third_party/blink/renderer/platform/wtf/checked_numeric.h"
+
+namespace blink {
+
+FEConvolveMatrix::FEConvolveMatrix(Filter* filter,
+ const IntSize& kernel_size,
+ float divisor,
+ float bias,
+ const IntPoint& target_offset,
+ EdgeModeType edge_mode,
+ bool preserve_alpha,
+ const Vector<float>& kernel_matrix)
+ : FilterEffect(filter),
+ kernel_size_(kernel_size),
+ divisor_(divisor),
+ bias_(bias),
+ target_offset_(target_offset),
+ edge_mode_(edge_mode),
+ preserve_alpha_(preserve_alpha),
+ kernel_matrix_(kernel_matrix) {}
+
+FEConvolveMatrix* FEConvolveMatrix::Create(Filter* filter,
+ const IntSize& kernel_size,
+ float divisor,
+ float bias,
+ const IntPoint& target_offset,
+ EdgeModeType edge_mode,
+ bool preserve_alpha,
+ const Vector<float>& kernel_matrix) {
+ return new FEConvolveMatrix(filter, kernel_size, divisor, bias, target_offset,
+ edge_mode, preserve_alpha, kernel_matrix);
+}
+
+FloatRect FEConvolveMatrix::MapEffect(const FloatRect& rect) const {
+ if (!ParametersValid())
+ return rect;
+ FloatRect result = rect;
+ result.MoveBy(-target_offset_);
+ result.Expand(FloatSize(kernel_size_));
+ return result;
+}
+
+bool FEConvolveMatrix::SetDivisor(float divisor) {
+ if (divisor_ == divisor)
+ return false;
+ divisor_ = divisor;
+ return true;
+}
+
+bool FEConvolveMatrix::SetBias(float bias) {
+ if (bias_ == bias)
+ return false;
+ bias_ = bias;
+ return true;
+}
+
+bool FEConvolveMatrix::SetTargetOffset(const IntPoint& target_offset) {
+ if (target_offset_ == target_offset)
+ return false;
+ target_offset_ = target_offset;
+ return true;
+}
+
+bool FEConvolveMatrix::SetEdgeMode(EdgeModeType edge_mode) {
+ if (edge_mode_ == edge_mode)
+ return false;
+ edge_mode_ = edge_mode;
+ return true;
+}
+
+bool FEConvolveMatrix::SetPreserveAlpha(bool preserve_alpha) {
+ if (preserve_alpha_ == preserve_alpha)
+ return false;
+ preserve_alpha_ = preserve_alpha;
+ return true;
+}
+
+SkMatrixConvolutionImageFilter::TileMode ToSkiaTileMode(
+ EdgeModeType edge_mode) {
+ switch (edge_mode) {
+ case EDGEMODE_DUPLICATE:
+ return SkMatrixConvolutionImageFilter::kClamp_TileMode;
+ case EDGEMODE_WRAP:
+ return SkMatrixConvolutionImageFilter::kRepeat_TileMode;
+ case EDGEMODE_NONE:
+ return SkMatrixConvolutionImageFilter::kClampToBlack_TileMode;
+ default:
+ return SkMatrixConvolutionImageFilter::kClamp_TileMode;
+ }
+}
+
+bool FEConvolveMatrix::ParametersValid() const {
+ if (kernel_size_.IsEmpty())
+ return false;
+ uint64_t kernel_area = kernel_size_.Area();
+ if (!CheckedNumeric<int>(kernel_area).IsValid())
+ return false;
+ if (SafeCast<size_t>(kernel_area) != kernel_matrix_.size())
+ return false;
+ if (target_offset_.X() < 0 || target_offset_.X() >= kernel_size_.Width())
+ return false;
+ if (target_offset_.Y() < 0 || target_offset_.Y() >= kernel_size_.Height())
+ return false;
+ if (!divisor_)
+ return false;
+ return true;
+}
+
+sk_sp<PaintFilter> FEConvolveMatrix::CreateImageFilter() {
+ if (!ParametersValid())
+ return CreateTransparentBlack();
+
+ sk_sp<PaintFilter> input(
+ PaintFilterBuilder::Build(InputEffect(0), OperatingInterpolationSpace()));
+ SkISize kernel_size(
+ SkISize::Make(kernel_size_.Width(), kernel_size_.Height()));
+ // parametersValid() above checks that the kernel area fits in int.
+ int num_elements = SafeCast<int>(kernel_size_.Area());
+ SkScalar gain = SkFloatToScalar(1.0f / divisor_);
+ SkScalar bias = SkFloatToScalar(bias_ * 255);
+ SkIPoint target = SkIPoint::Make(target_offset_.X(), target_offset_.Y());
+ MatrixConvolutionPaintFilter::TileMode tile_mode = ToSkiaTileMode(edge_mode_);
+ bool convolve_alpha = !preserve_alpha_;
+ auto kernel = std::make_unique<SkScalar[]>(num_elements);
+ for (int i = 0; i < num_elements; ++i)
+ kernel[i] = SkFloatToScalar(kernel_matrix_[num_elements - 1 - i]);
+ PaintFilter::CropRect crop_rect = GetCropRect();
+ return sk_make_sp<MatrixConvolutionPaintFilter>(
+ kernel_size, kernel.get(), gain, bias, target, tile_mode, convolve_alpha,
+ std::move(input), &crop_rect);
+}
+
+static TextStream& operator<<(TextStream& ts, const EdgeModeType& type) {
+ switch (type) {
+ case EDGEMODE_UNKNOWN:
+ ts << "UNKNOWN";
+ break;
+ case EDGEMODE_DUPLICATE:
+ ts << "DUPLICATE";
+ break;
+ case EDGEMODE_WRAP:
+ ts << "WRAP";
+ break;
+ case EDGEMODE_NONE:
+ ts << "NONE";
+ break;
+ }
+ return ts;
+}
+
+TextStream& FEConvolveMatrix::ExternalRepresentation(TextStream& ts,
+ int indent) const {
+ WriteIndent(ts, indent);
+ ts << "[feConvolveMatrix";
+ FilterEffect::ExternalRepresentation(ts);
+ ts << " order=\"" << FloatSize(kernel_size_) << "\" "
+ << "kernelMatrix=\"" << kernel_matrix_ << "\" "
+ << "divisor=\"" << divisor_ << "\" "
+ << "bias=\"" << bias_ << "\" "
+ << "target=\"" << target_offset_ << "\" "
+ << "edgeMode=\"" << edge_mode_ << "\" "
+ << "preserveAlpha=\"" << preserve_alpha_ << "\"]\n";
+ InputEffect(0)->ExternalRepresentation(ts, indent + 1);
+ return ts;
+}
+
+} // namespace blink