blob: b88132cf3b4fee7506e40bc287ae35be1b67847d [file] [log] [blame]
reed@google.comdb87c962012-11-02 21:11:12 +00001/*
humper@google.coma99a92c2013-02-20 16:42:06 +00002* Copyright 2012 Google Inc.
3*
4* Use of this source code is governed by a BSD-style license that can be
5* found in the LICENSE file.
6*/
reed@google.comdb87c962012-11-02 21:11:12 +00007
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "gm/gm.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -04009#include "include/core/SkBitmap.h"
10#include "include/core/SkBlurTypes.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "include/core/SkCanvas.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040012#include "include/core/SkColor.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050013#include "include/core/SkMaskFilter.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040014#include "include/core/SkMatrix.h"
15#include "include/core/SkPaint.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050016#include "include/core/SkPath.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040017#include "include/core/SkPoint.h"
18#include "include/core/SkRect.h"
19#include "include/core/SkRefCnt.h"
20#include "include/core/SkScalar.h"
21#include "include/core/SkShader.h"
22#include "include/core/SkSize.h"
23#include "include/core/SkString.h"
24#include "include/core/SkTileMode.h"
25#include "include/core/SkTypes.h"
26#include "include/effects/SkGradientShader.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050027#include "include/private/SkTo.h"
28#include "src/core/SkBlurMask.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040029#include "src/core/SkMask.h"
reed@google.comdb87c962012-11-02 21:11:12 +000030
31#define STROKE_WIDTH SkIntToScalar(10)
32
33typedef void (*Proc)(SkCanvas*, const SkRect&, const SkPaint&);
34
35static void fill_rect(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
36 canvas->drawRect(r, p);
37}
38
reed@google.comdb87c962012-11-02 21:11:12 +000039static void draw_donut(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
40 SkRect rect;
41 SkPath path;
skia.committer@gmail.com34587162012-11-20 02:01:23 +000042
reed@google.comdb87c962012-11-02 21:11:12 +000043 rect = r;
44 rect.outset(STROKE_WIDTH/2, STROKE_WIDTH/2);
45 path.addRect(rect);
46 rect = r;
47 rect.inset(STROKE_WIDTH/2, STROKE_WIDTH/2);
skia.committer@gmail.com34587162012-11-20 02:01:23 +000048
reed@google.comdb87c962012-11-02 21:11:12 +000049 path.addRect(rect);
50 path.setFillType(SkPath::kEvenOdd_FillType);
skia.committer@gmail.com34587162012-11-20 02:01:23 +000051
reed@google.com808b70f2012-11-19 16:14:02 +000052 canvas->drawPath(path, p);
53}
reed@google.comdb87c962012-11-02 21:11:12 +000054
reed@google.com808b70f2012-11-19 16:14:02 +000055static void draw_donut_skewed(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
56 SkRect rect;
57 SkPath path;
skia.committer@gmail.com34587162012-11-20 02:01:23 +000058
reed@google.com808b70f2012-11-19 16:14:02 +000059 rect = r;
60 rect.outset(STROKE_WIDTH/2, STROKE_WIDTH/2);
61 path.addRect(rect);
62 rect = r;
63 rect.inset(STROKE_WIDTH/2, STROKE_WIDTH/2);
skia.committer@gmail.com34587162012-11-20 02:01:23 +000064
reed@google.com808b70f2012-11-19 16:14:02 +000065 rect.offset(7, -7);
skia.committer@gmail.com34587162012-11-20 02:01:23 +000066
reed@google.com808b70f2012-11-19 16:14:02 +000067 path.addRect(rect);
68 path.setFillType(SkPath::kEvenOdd_FillType);
skia.committer@gmail.com34587162012-11-20 02:01:23 +000069
reed@google.comdb87c962012-11-02 21:11:12 +000070 canvas->drawPath(path, p);
71}
72
joshualitt341400e2014-12-18 11:54:13 -080073/*
74 * Spits out a dummy gradient to test blur with shader on paint
75 */
Robert Phillips09dfc472017-09-13 15:25:47 -040076static sk_sp<SkShader> make_radial() {
joshualitt341400e2014-12-18 11:54:13 -080077 SkPoint pts[2] = {
78 { 0, 0 },
79 { SkIntToScalar(100), SkIntToScalar(100) }
80 };
Mike Reedfae8fce2019-04-03 10:27:45 -040081 SkTileMode tm = SkTileMode::kClamp;
joshualitt341400e2014-12-18 11:54:13 -080082 const SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, };
83 const SkScalar pos[] = { SK_Scalar1/4, SK_Scalar1*3/4 };
84 SkMatrix scale;
85 scale.setScale(0.5f, 0.5f);
86 scale.postTranslate(25.f, 25.f);
87 SkPoint center0, center1;
88 center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
89 SkScalarAve(pts[0].fY, pts[1].fY));
90 center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
91 SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
reed2ad1aa62016-03-09 09:50:50 -080092 return SkGradientShader::MakeTwoPointConical(center1, (pts[1].fX - pts[0].fX) / 7,
93 center0, (pts[1].fX - pts[0].fX) / 2,
94 colors, pos, SK_ARRAY_COUNT(colors), tm,
95 0, &scale);
joshualitt341400e2014-12-18 11:54:13 -080096}
97
reed@google.com53007a22012-11-26 14:39:50 +000098typedef void (*PaintProc)(SkPaint*, SkScalar width);
99
reed@google.comdb87c962012-11-02 21:11:12 +0000100class BlurRectGM : public skiagm::GM {
reed@google.comdb87c962012-11-02 21:11:12 +0000101public:
Hal Canary594fe852019-07-18 13:35:49 -0400102 BlurRectGM(const char name[], U8CPU alpha) : fName(name), fAlpha(SkToU8(alpha)) {}
reed@google.comdb87c962012-11-02 21:11:12 +0000103
Hal Canary594fe852019-07-18 13:35:49 -0400104private:
105 sk_sp<SkMaskFilter> fMaskFilters[kLastEnum_SkBlurStyle + 1];
106 const char* fName;
107 SkAlpha fAlpha;
108
mtklein36352bf2015-03-25 18:17:31 -0700109 void onOnceBeforeDraw() override {
commit-bot@chromium.orge3964552014-04-28 16:25:35 +0000110 for (int i = 0; i <= kLastEnum_SkBlurStyle; ++i) {
Mike Reed1be1f8d2018-03-14 13:01:17 -0400111 fMaskFilters[i] = SkMaskFilter::MakeBlur((SkBlurStyle)i,
112 SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(STROKE_WIDTH/2)));
commit-bot@chromium.org7cced562014-01-10 23:10:13 +0000113 }
114 }
115
Hal Canary594fe852019-07-18 13:35:49 -0400116 SkString onShortName() override { return SkString(fName); }
reed@google.comdb87c962012-11-02 21:11:12 +0000117
Hal Canary594fe852019-07-18 13:35:49 -0400118 SkISize onISize() override { return {860, 820}; }
reed@google.comdb87c962012-11-02 21:11:12 +0000119
mtklein36352bf2015-03-25 18:17:31 -0700120 void onDraw(SkCanvas* canvas) override {
reed@google.comdb87c962012-11-02 21:11:12 +0000121 canvas->translate(STROKE_WIDTH*3/2, STROKE_WIDTH*3/2);
122
commit-bot@chromium.org7cced562014-01-10 23:10:13 +0000123 SkRect r = { 0, 0, 100, 50 };
124 SkScalar scales[] = { SK_Scalar1, 0.6f };
skia.committer@gmail.com8ccf5902012-11-27 02:01:19 +0000125
commit-bot@chromium.org7cced562014-01-10 23:10:13 +0000126 for (size_t s = 0; s < SK_ARRAY_COUNT(scales); ++s) {
127 canvas->save();
128 for (size_t f = 0; f < SK_ARRAY_COUNT(fMaskFilters); ++f) {
129 SkPaint paint;
130 paint.setMaskFilter(fMaskFilters[f]);
131 paint.setAlpha(fAlpha);
132
joshualitt341400e2014-12-18 11:54:13 -0800133 SkPaint paintWithRadial = paint;
Robert Phillips09dfc472017-09-13 15:25:47 -0400134 paintWithRadial.setShader(make_radial());
joshualitt341400e2014-12-18 11:54:13 -0800135
mtkleindbfd7ab2016-09-01 11:24:54 -0700136 constexpr Proc procs[] = {
commit-bot@chromium.org7cced562014-01-10 23:10:13 +0000137 fill_rect, draw_donut, draw_donut_skewed
138 };
139
140 canvas->save();
141 canvas->scale(scales[s], scales[s]);
142 this->drawProcs(canvas, r, paint, false, procs, SK_ARRAY_COUNT(procs));
143 canvas->translate(r.width() * 4/3, 0);
joshualitt341400e2014-12-18 11:54:13 -0800144 this->drawProcs(canvas, r, paintWithRadial, false, procs, SK_ARRAY_COUNT(procs));
145 canvas->translate(r.width() * 4/3, 0);
commit-bot@chromium.org7cced562014-01-10 23:10:13 +0000146 this->drawProcs(canvas, r, paint, true, procs, SK_ARRAY_COUNT(procs));
joshualitt341400e2014-12-18 11:54:13 -0800147 canvas->translate(r.width() * 4/3, 0);
148 this->drawProcs(canvas, r, paintWithRadial, true, procs, SK_ARRAY_COUNT(procs));
commit-bot@chromium.org7cced562014-01-10 23:10:13 +0000149 canvas->restore();
150
151 canvas->translate(0, SK_ARRAY_COUNT(procs) * r.height() * 4/3 * scales[s]);
152 }
153 canvas->restore();
joshualitt341400e2014-12-18 11:54:13 -0800154 canvas->translate(4 * r.width() * 4/3 * scales[s], 0);
reed@google.com53007a22012-11-26 14:39:50 +0000155 }
reed@google.comdb87c962012-11-02 21:11:12 +0000156 }
157
reed@google.comdb87c962012-11-02 21:11:12 +0000158 void drawProcs(SkCanvas* canvas, const SkRect& r, const SkPaint& paint,
159 bool doClip, const Proc procs[], size_t procsCount) {
160 SkAutoCanvasRestore acr(canvas, true);
161 for (size_t i = 0; i < procsCount; ++i) {
162 if (doClip) {
163 SkRect clipRect(r);
164 clipRect.inset(STROKE_WIDTH/2, STROKE_WIDTH/2);
165 canvas->save();
166 canvas->clipRect(r);
167 }
168 procs[i](canvas, r, paint);
169 if (doClip) {
170 canvas->restore();
171 }
172 canvas->translate(0, r.height() * 4/3);
173 }
174 }
reed@google.comdb87c962012-11-02 21:11:12 +0000175};
176
halcanary2a243382015-09-09 08:16:41 -0700177DEF_SIMPLE_GM(blurrect_gallery, canvas, 1200, 1024) {
178 const int fGMWidth = 1200;
179 const int fPadding = 10;
180 const int fMargin = 100;
commit-bot@chromium.org3c1594a2014-05-28 21:52:12 +0000181
commit-bot@chromium.org3c1594a2014-05-28 21:52:12 +0000182 const int widths[] = {25, 5, 5, 100, 150, 25};
183 const int heights[] = {100, 100, 5, 25, 150, 25};
184 const SkBlurStyle styles[] = {kNormal_SkBlurStyle, kInner_SkBlurStyle, kOuter_SkBlurStyle};
185 const float radii[] = {20, 5, 10};
186
187 canvas->translate(50,20);
188
189 int cur_x = 0;
190 int cur_y = 0;
191
192 int max_height = 0;
193
194 for (size_t i = 0 ; i < SK_ARRAY_COUNT(widths) ; i++) {
195 int width = widths[i];
196 int height = heights[i];
197 SkRect r;
198 r.setWH(SkIntToScalar(width), SkIntToScalar(height));
199 SkAutoCanvasRestore autoRestore(canvas, true);
200
201 for (size_t j = 0 ; j < SK_ARRAY_COUNT(radii) ; j++) {
202 float radius = radii[j];
203 for (size_t k = 0 ; k < SK_ARRAY_COUNT(styles) ; k++) {
204 SkBlurStyle style = styles[k];
205
206 SkMask mask;
robertphillipse80eb922015-12-17 11:33:12 -0800207 if (!SkBlurMask::BlurRect(SkBlurMask::ConvertRadiusToSigma(radius),
208 &mask, r, style)) {
209 continue;
210 }
commit-bot@chromium.org3c1594a2014-05-28 21:52:12 +0000211
212 SkAutoMaskFreeImage amfi(mask.fImage);
213
214 SkBitmap bm;
215 bm.installMaskPixels(mask);
216
217 if (cur_x + bm.width() >= fGMWidth - fMargin) {
218 cur_x = 0;
219 cur_y += max_height + fPadding;
220 max_height = 0;
221 }
222
223 canvas->save();
commit-bot@chromium.org793ddd92014-05-28 22:42:31 +0000224 canvas->translate((SkScalar)cur_x, (SkScalar)cur_y);
commit-bot@chromium.org3c1594a2014-05-28 21:52:12 +0000225 canvas->translate(-(bm.width() - r.width())/2, -(bm.height()-r.height())/2);
halcanary96fcdcc2015-08-27 07:41:13 -0700226 canvas->drawBitmap(bm, 0.f, 0.f, nullptr);
commit-bot@chromium.org3c1594a2014-05-28 21:52:12 +0000227 canvas->restore();
228
229 cur_x += bm.width() + fPadding;
230 if (bm.height() > max_height)
231 max_height = bm.height();
232 }
233 }
234 }
halcanary2a243382015-09-09 08:16:41 -0700235}
humper@google.com7c7292c2013-01-04 20:29:03 +0000236
reed@google.comdb87c962012-11-02 21:11:12 +0000237//////////////////////////////////////////////////////////////////////////////
238
commit-bot@chromium.org7cced562014-01-10 23:10:13 +0000239DEF_GM(return new BlurRectGM("blurrects", 0xFF);)