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