blob: a718cdeac6c1e3997f039eaaed0afd02534e9b7c [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
Hal Canaryfdcfb8b2018-06-13 09:42:32 -04008#include "gm.h"
humper@google.com7c7292c2013-01-04 20:29:03 +00009#include "SkBlurMask.h"
reed@google.comdb87c962012-11-02 21:11:12 +000010#include "SkCanvas.h"
Mike Reed1be1f8d2018-03-14 13:01:17 -040011#include "SkMaskFilter.h"
reed@google.comdb87c962012-11-02 21:11:12 +000012#include "SkPath.h"
13
14#define STROKE_WIDTH SkIntToScalar(10)
15
16typedef void (*Proc)(SkCanvas*, const SkRect&, const SkPaint&);
17
18static void fill_rect(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
19 canvas->drawRect(r, p);
20}
21
reed@google.comdb87c962012-11-02 21:11:12 +000022static void draw_donut(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
23 SkRect rect;
24 SkPath path;
skia.committer@gmail.com34587162012-11-20 02:01:23 +000025
reed@google.comdb87c962012-11-02 21:11:12 +000026 rect = r;
27 rect.outset(STROKE_WIDTH/2, STROKE_WIDTH/2);
28 path.addRect(rect);
29 rect = r;
30 rect.inset(STROKE_WIDTH/2, STROKE_WIDTH/2);
skia.committer@gmail.com34587162012-11-20 02:01:23 +000031
reed@google.comdb87c962012-11-02 21:11:12 +000032 path.addRect(rect);
33 path.setFillType(SkPath::kEvenOdd_FillType);
skia.committer@gmail.com34587162012-11-20 02:01:23 +000034
reed@google.com808b70f2012-11-19 16:14:02 +000035 canvas->drawPath(path, p);
36}
reed@google.comdb87c962012-11-02 21:11:12 +000037
reed@google.com808b70f2012-11-19 16:14:02 +000038static void draw_donut_skewed(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
39 SkRect rect;
40 SkPath path;
skia.committer@gmail.com34587162012-11-20 02:01:23 +000041
reed@google.com808b70f2012-11-19 16:14:02 +000042 rect = r;
43 rect.outset(STROKE_WIDTH/2, STROKE_WIDTH/2);
44 path.addRect(rect);
45 rect = r;
46 rect.inset(STROKE_WIDTH/2, STROKE_WIDTH/2);
skia.committer@gmail.com34587162012-11-20 02:01:23 +000047
reed@google.com808b70f2012-11-19 16:14:02 +000048 rect.offset(7, -7);
skia.committer@gmail.com34587162012-11-20 02:01:23 +000049
reed@google.com808b70f2012-11-19 16:14:02 +000050 path.addRect(rect);
51 path.setFillType(SkPath::kEvenOdd_FillType);
skia.committer@gmail.com34587162012-11-20 02:01:23 +000052
reed@google.comdb87c962012-11-02 21:11:12 +000053 canvas->drawPath(path, p);
54}
55
reed@google.com53007a22012-11-26 14:39:50 +000056#include "SkGradientShader.h"
57
joshualitt341400e2014-12-18 11:54:13 -080058/*
59 * Spits out a dummy gradient to test blur with shader on paint
60 */
Robert Phillips09dfc472017-09-13 15:25:47 -040061static sk_sp<SkShader> make_radial() {
joshualitt341400e2014-12-18 11:54:13 -080062 SkPoint pts[2] = {
63 { 0, 0 },
64 { SkIntToScalar(100), SkIntToScalar(100) }
65 };
66 SkShader::TileMode tm = SkShader::kClamp_TileMode;
67 const SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, };
68 const SkScalar pos[] = { SK_Scalar1/4, SK_Scalar1*3/4 };
69 SkMatrix scale;
70 scale.setScale(0.5f, 0.5f);
71 scale.postTranslate(25.f, 25.f);
72 SkPoint center0, center1;
73 center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
74 SkScalarAve(pts[0].fY, pts[1].fY));
75 center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
76 SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
reed2ad1aa62016-03-09 09:50:50 -080077 return SkGradientShader::MakeTwoPointConical(center1, (pts[1].fX - pts[0].fX) / 7,
78 center0, (pts[1].fX - pts[0].fX) / 2,
79 colors, pos, SK_ARRAY_COUNT(colors), tm,
80 0, &scale);
joshualitt341400e2014-12-18 11:54:13 -080081}
82
reed@google.com53007a22012-11-26 14:39:50 +000083typedef void (*PaintProc)(SkPaint*, SkScalar width);
84
reed@google.comdb87c962012-11-02 21:11:12 +000085class BlurRectGM : public skiagm::GM {
reedefdfd512016-04-04 10:02:58 -070086 sk_sp<SkMaskFilter> fMaskFilters[kLastEnum_SkBlurStyle + 1];
humper@google.coma99a92c2013-02-20 16:42:06 +000087 SkString fName;
humper@google.coma99a92c2013-02-20 16:42:06 +000088 SkAlpha fAlpha;
reed@google.comdb87c962012-11-02 21:11:12 +000089public:
commit-bot@chromium.org7cced562014-01-10 23:10:13 +000090 BlurRectGM(const char name[], U8CPU alpha)
91 : fName(name)
92 , fAlpha(SkToU8(alpha)) {
reed@google.com57850b92012-12-17 21:20:53 +000093 }
reed@google.comdb87c962012-11-02 21:11:12 +000094
95protected:
mtklein36352bf2015-03-25 18:17:31 -070096 void onOnceBeforeDraw() override {
commit-bot@chromium.orge3964552014-04-28 16:25:35 +000097 for (int i = 0; i <= kLastEnum_SkBlurStyle; ++i) {
Mike Reed1be1f8d2018-03-14 13:01:17 -040098 fMaskFilters[i] = SkMaskFilter::MakeBlur((SkBlurStyle)i,
99 SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(STROKE_WIDTH/2)));
commit-bot@chromium.org7cced562014-01-10 23:10:13 +0000100 }
101 }
102
mtklein36352bf2015-03-25 18:17:31 -0700103 SkString onShortName() override {
reed@google.com53007a22012-11-26 14:39:50 +0000104 return fName;
reed@google.comdb87c962012-11-02 21:11:12 +0000105 }
106
mtklein36352bf2015-03-25 18:17:31 -0700107 SkISize onISize() override {
joshualitt341400e2014-12-18 11:54:13 -0800108 return SkISize::Make(860, 820);
reed@google.comdb87c962012-11-02 21:11:12 +0000109 }
110
mtklein36352bf2015-03-25 18:17:31 -0700111 void onDraw(SkCanvas* canvas) override {
reed@google.comdb87c962012-11-02 21:11:12 +0000112 canvas->translate(STROKE_WIDTH*3/2, STROKE_WIDTH*3/2);
113
commit-bot@chromium.org7cced562014-01-10 23:10:13 +0000114 SkRect r = { 0, 0, 100, 50 };
115 SkScalar scales[] = { SK_Scalar1, 0.6f };
skia.committer@gmail.com8ccf5902012-11-27 02:01:19 +0000116
commit-bot@chromium.org7cced562014-01-10 23:10:13 +0000117 for (size_t s = 0; s < SK_ARRAY_COUNT(scales); ++s) {
118 canvas->save();
119 for (size_t f = 0; f < SK_ARRAY_COUNT(fMaskFilters); ++f) {
120 SkPaint paint;
121 paint.setMaskFilter(fMaskFilters[f]);
122 paint.setAlpha(fAlpha);
123
joshualitt341400e2014-12-18 11:54:13 -0800124 SkPaint paintWithRadial = paint;
Robert Phillips09dfc472017-09-13 15:25:47 -0400125 paintWithRadial.setShader(make_radial());
joshualitt341400e2014-12-18 11:54:13 -0800126
mtkleindbfd7ab2016-09-01 11:24:54 -0700127 constexpr Proc procs[] = {
commit-bot@chromium.org7cced562014-01-10 23:10:13 +0000128 fill_rect, draw_donut, draw_donut_skewed
129 };
130
131 canvas->save();
132 canvas->scale(scales[s], scales[s]);
133 this->drawProcs(canvas, r, paint, false, procs, SK_ARRAY_COUNT(procs));
134 canvas->translate(r.width() * 4/3, 0);
joshualitt341400e2014-12-18 11:54:13 -0800135 this->drawProcs(canvas, r, paintWithRadial, false, procs, SK_ARRAY_COUNT(procs));
136 canvas->translate(r.width() * 4/3, 0);
commit-bot@chromium.org7cced562014-01-10 23:10:13 +0000137 this->drawProcs(canvas, r, paint, true, procs, SK_ARRAY_COUNT(procs));
joshualitt341400e2014-12-18 11:54:13 -0800138 canvas->translate(r.width() * 4/3, 0);
139 this->drawProcs(canvas, r, paintWithRadial, true, procs, SK_ARRAY_COUNT(procs));
commit-bot@chromium.org7cced562014-01-10 23:10:13 +0000140 canvas->restore();
141
142 canvas->translate(0, SK_ARRAY_COUNT(procs) * r.height() * 4/3 * scales[s]);
143 }
144 canvas->restore();
joshualitt341400e2014-12-18 11:54:13 -0800145 canvas->translate(4 * r.width() * 4/3 * scales[s], 0);
reed@google.com53007a22012-11-26 14:39:50 +0000146 }
reed@google.comdb87c962012-11-02 21:11:12 +0000147 }
148
reed@google.comdb87c962012-11-02 21:11:12 +0000149private:
150 void drawProcs(SkCanvas* canvas, const SkRect& r, const SkPaint& paint,
151 bool doClip, const Proc procs[], size_t procsCount) {
152 SkAutoCanvasRestore acr(canvas, true);
153 for (size_t i = 0; i < procsCount; ++i) {
154 if (doClip) {
155 SkRect clipRect(r);
156 clipRect.inset(STROKE_WIDTH/2, STROKE_WIDTH/2);
157 canvas->save();
158 canvas->clipRect(r);
159 }
160 procs[i](canvas, r, paint);
161 if (doClip) {
162 canvas->restore();
163 }
164 canvas->translate(0, r.height() * 4/3);
165 }
166 }
humper@google.coma99a92c2013-02-20 16:42:06 +0000167private:
reed@google.comdb87c962012-11-02 21:11:12 +0000168 typedef GM INHERITED;
169};
170
halcanary2a243382015-09-09 08:16:41 -0700171DEF_SIMPLE_GM(blurrect_gallery, canvas, 1200, 1024) {
172 const int fGMWidth = 1200;
173 const int fPadding = 10;
174 const int fMargin = 100;
commit-bot@chromium.org3c1594a2014-05-28 21:52:12 +0000175
commit-bot@chromium.org3c1594a2014-05-28 21:52:12 +0000176 const int widths[] = {25, 5, 5, 100, 150, 25};
177 const int heights[] = {100, 100, 5, 25, 150, 25};
178 const SkBlurStyle styles[] = {kNormal_SkBlurStyle, kInner_SkBlurStyle, kOuter_SkBlurStyle};
179 const float radii[] = {20, 5, 10};
180
181 canvas->translate(50,20);
182
183 int cur_x = 0;
184 int cur_y = 0;
185
186 int max_height = 0;
187
188 for (size_t i = 0 ; i < SK_ARRAY_COUNT(widths) ; i++) {
189 int width = widths[i];
190 int height = heights[i];
191 SkRect r;
192 r.setWH(SkIntToScalar(width), SkIntToScalar(height));
193 SkAutoCanvasRestore autoRestore(canvas, true);
194
195 for (size_t j = 0 ; j < SK_ARRAY_COUNT(radii) ; j++) {
196 float radius = radii[j];
197 for (size_t k = 0 ; k < SK_ARRAY_COUNT(styles) ; k++) {
198 SkBlurStyle style = styles[k];
199
200 SkMask mask;
robertphillipse80eb922015-12-17 11:33:12 -0800201 if (!SkBlurMask::BlurRect(SkBlurMask::ConvertRadiusToSigma(radius),
202 &mask, r, style)) {
203 continue;
204 }
commit-bot@chromium.org3c1594a2014-05-28 21:52:12 +0000205
206 SkAutoMaskFreeImage amfi(mask.fImage);
207
208 SkBitmap bm;
209 bm.installMaskPixels(mask);
210
211 if (cur_x + bm.width() >= fGMWidth - fMargin) {
212 cur_x = 0;
213 cur_y += max_height + fPadding;
214 max_height = 0;
215 }
216
217 canvas->save();
commit-bot@chromium.org793ddd92014-05-28 22:42:31 +0000218 canvas->translate((SkScalar)cur_x, (SkScalar)cur_y);
commit-bot@chromium.org3c1594a2014-05-28 21:52:12 +0000219 canvas->translate(-(bm.width() - r.width())/2, -(bm.height()-r.height())/2);
halcanary96fcdcc2015-08-27 07:41:13 -0700220 canvas->drawBitmap(bm, 0.f, 0.f, nullptr);
commit-bot@chromium.org3c1594a2014-05-28 21:52:12 +0000221 canvas->restore();
222
223 cur_x += bm.width() + fPadding;
224 if (bm.height() > max_height)
225 max_height = bm.height();
226 }
227 }
228 }
halcanary2a243382015-09-09 08:16:41 -0700229}
humper@google.com7c7292c2013-01-04 20:29:03 +0000230
reed@google.comdb87c962012-11-02 21:11:12 +0000231//////////////////////////////////////////////////////////////////////////////
232
commit-bot@chromium.org7cced562014-01-10 23:10:13 +0000233DEF_GM(return new BlurRectGM("blurrects", 0xFF);)