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 Igalia, S.L.
7 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
8 * Copyright (C) 2013 Google Inc. All rights reserved.
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Library General Public License for more details.
19 *
20 * You should have received a copy of the GNU Library General Public License
21 * along with this library; see the file COPYING.LIB. If not, write to
22 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23 * Boston, MA 02110-1301, USA.
24 */
25
26 #include "third_party/blink/renderer/platform/graphics/filters/fe_gaussian_blur.h"
27
28 #include "third_party/blink/renderer/platform/graphics/filters/filter.h"
29 #include "third_party/blink/renderer/platform/graphics/filters/paint_filter_builder.h"
30 #include "third_party/blink/renderer/platform/wtf/text/text_stream.h"
31 #include "third_party/skia/include/effects/SkBlurImageFilter.h"
32
33 namespace blink {
34
35 namespace {
36
ApproximateBoxWidth(float s)37 inline unsigned ApproximateBoxWidth(float s) {
38 return static_cast<unsigned>(
39 floorf(s * (3 / 4.f * sqrtf(kTwoPiFloat)) + 0.5f));
40 }
41
CalculateKernelSize(const FloatSize & std)42 IntSize CalculateKernelSize(const FloatSize& std) {
43 DCHECK(std.Width() >= 0 && std.Height() >= 0);
44 IntSize kernel_size;
45 if (std.Width()) {
46 int size = std::max<unsigned>(2, ApproximateBoxWidth(std.Width()));
47 kernel_size.SetWidth(size);
48 }
49 if (std.Height()) {
50 int size = std::max<unsigned>(2, ApproximateBoxWidth(std.Height()));
51 kernel_size.SetHeight(size);
52 }
53 return kernel_size;
54 }
55
56 }
57
FEGaussianBlur(Filter * filter,float x,float y)58 FEGaussianBlur::FEGaussianBlur(Filter* filter, float x, float y)
59 : FilterEffect(filter), std_x_(x), std_y_(y) {}
60
MapEffect(const FloatSize & std_deviation,const FloatRect & rect)61 FloatRect FEGaussianBlur::MapEffect(const FloatSize& std_deviation,
62 const FloatRect& rect) {
63 IntSize kernel_size = CalculateKernelSize(std_deviation);
64 // We take the half kernel size and multiply it by three, because we run box
65 // blur three times.
66 FloatRect result = rect;
67 result.InflateX(3.0f * kernel_size.Width() * 0.5f);
68 result.InflateY(3.0f * kernel_size.Height() * 0.5f);
69 return result;
70 }
71
MapEffect(const FloatRect & rect) const72 FloatRect FEGaussianBlur::MapEffect(const FloatRect& rect) const {
73 FloatSize std_error(GetFilter()->ApplyHorizontalScale(std_x_),
74 GetFilter()->ApplyVerticalScale(std_y_));
75 return MapEffect(std_error, rect);
76 }
77
CreateImageFilter()78 sk_sp<PaintFilter> FEGaussianBlur::CreateImageFilter() {
79 sk_sp<PaintFilter> input(paint_filter_builder::Build(
80 InputEffect(0), OperatingInterpolationSpace()));
81 float std_x = GetFilter()->ApplyHorizontalScale(std_x_);
82 float std_y = GetFilter()->ApplyVerticalScale(std_y_);
83 PaintFilter::CropRect rect = GetCropRect();
84 return sk_make_sp<BlurPaintFilter>(
85 SkFloatToScalar(std_x), SkFloatToScalar(std_y),
86 BlurPaintFilter::TileMode::kClampToBlack_TileMode, std::move(input),
87 &rect);
88 }
89
ExternalRepresentation(WTF::TextStream & ts,int indent) const90 WTF::TextStream& FEGaussianBlur::ExternalRepresentation(WTF::TextStream& ts,
91 int indent) const {
92 WriteIndent(ts, indent);
93 ts << "[feGaussianBlur";
94 FilterEffect::ExternalRepresentation(ts);
95 ts << " stdDeviation=\"" << std_x_ << ", " << std_y_ << "\"]\n";
96 InputEffect(0)->ExternalRepresentation(ts, indent + 1);
97 return ts;
98 }
99
100 } // namespace blink
101