blob: 313f5c4ce5593835d5eb7ab251a8160ac4916fdc [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001/*
2 * Copyright 2011 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 */
reed36e6e262014-11-14 08:27:40 -08007
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "gm/gm.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -04009#include "include/core/SkBlurTypes.h"
10#include "include/core/SkCanvas.h"
11#include "include/core/SkColor.h"
Michael Ludwige585bb62023-11-08 13:14:09 -050012#include "include/core/SkColorFilter.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040013#include "include/core/SkFont.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050014#include "include/core/SkMaskFilter.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040015#include "include/core/SkPaint.h"
Mike Reed06d7c9d2020-08-26 12:56:51 -040016#include "include/core/SkPathBuilder.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040017#include "include/core/SkRect.h"
18#include "include/core/SkRefCnt.h"
19#include "include/core/SkScalar.h"
20#include "include/core/SkTypeface.h"
21#include "include/core/SkTypes.h"
Michael Ludwige2674642020-10-21 13:01:34 -040022#include "include/effects/SkImageFilters.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050023#include "src/core/SkBlurMask.h"
Kevin Lubick8b741882023-10-06 11:41:38 -040024#include "tools/DecodeUtils.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050025#include "tools/Resources.h"
26#include "tools/ToolUtils.h"
Kevin Lubicke836c3a2023-10-20 06:55:35 -040027#include "tools/fonts/FontToolUtils.h"
reed@google.comc96e5c22011-02-16 21:50:04 +000028
Mike Kleind46dce32018-08-16 10:17:03 -040029DEF_SIMPLE_GM_BG(blurs, canvas, 700, 500, 0xFFDDDDDD) {
Mike Reed4de2f1f2019-01-05 16:35:13 -050030 SkBlurStyle NONE = SkBlurStyle(-999);
31 const struct {
32 SkBlurStyle fStyle;
33 int fCx, fCy;
34 } gRecs[] = {
35 { NONE, 0, 0 },
36 { kInner_SkBlurStyle, -1, 0 },
37 { kNormal_SkBlurStyle, 0, 1 },
38 { kSolid_SkBlurStyle, 0, -1 },
39 { kOuter_SkBlurStyle, 1, 0 },
40 };
reed@google.comc96e5c22011-02-16 21:50:04 +000041
Mike Reed4de2f1f2019-01-05 16:35:13 -050042 SkPaint paint;
43 paint.setAntiAlias(true);
44 paint.setColor(SK_ColorBLUE);
reed@google.comc96e5c22011-02-16 21:50:04 +000045
Mike Reed4de2f1f2019-01-05 16:35:13 -050046 canvas->translate(SkIntToScalar(-40), SkIntToScalar(0));
47
Herb Derbyc37b3862022-06-21 09:49:17 -040048 for (size_t i = 0; i < std::size(gRecs); i++) {
Mike Reed4de2f1f2019-01-05 16:35:13 -050049 if (gRecs[i].fStyle != NONE) {
50 paint.setMaskFilter(SkMaskFilter::MakeBlur(gRecs[i].fStyle,
51 SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(20))));
52 } else {
Mike Reed1be1f8d2018-03-14 13:01:17 -040053 paint.setMaskFilter(nullptr);
reed@google.comc96e5c22011-02-16 21:50:04 +000054 }
Mike Reed4de2f1f2019-01-05 16:35:13 -050055 canvas->drawCircle(SkIntToScalar(200 + gRecs[i].fCx*100),
56 SkIntToScalar(200 + gRecs[i].fCy*100),
57 SkIntToScalar(50),
58 paint);
59 }
60 // draw text
61 {
Kevin Lubicke836c3a2023-10-20 06:55:35 -040062 SkFont font(ToolUtils::DefaultPortableTypeface(), 25);
Mike Reed4de2f1f2019-01-05 16:35:13 -050063 paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle,
64 SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(4))));
65 SkScalar x = SkIntToScalar(70);
66 SkScalar y = SkIntToScalar(400);
67 paint.setColor(SK_ColorBLACK);
68 canvas->drawString("Hamburgefons Style", x, y, font, paint);
69 canvas->drawString("Hamburgefons Style",
70 x, y + SkIntToScalar(50), font, paint);
71 paint.setMaskFilter(nullptr);
72 paint.setColor(SK_ColorWHITE);
73 x -= SkIntToScalar(2);
74 y -= SkIntToScalar(2);
75 canvas->drawString("Hamburgefons Style", x, y, font, paint);
76 }
halcanary2a243382015-09-09 08:16:41 -070077}
reed@google.comc96e5c22011-02-16 21:50:04 +000078
reed36e6e262014-11-14 08:27:40 -080079//////////////////////////////////////////////////////////////////////////////////////////////
reed@google.comc96e5c22011-02-16 21:50:04 +000080
reed36e6e262014-11-14 08:27:40 -080081// exercise a special-case of blurs, which is two nested rects. These are drawn specially,
82// and possibly cached.
83//
84// in particular, we want to notice that the 2nd rect draws slightly differently, since it
85// is translated a fractional amount.
86//
halcanary2a243382015-09-09 08:16:41 -070087DEF_SIMPLE_GM(blur2rects, canvas, 700, 500) {
Mike Reed06d7c9d2020-08-26 12:56:51 -040088 SkPaint paint;
reed36e6e262014-11-14 08:27:40 -080089
Mike Reed06d7c9d2020-08-26 12:56:51 -040090 paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 2.3f));
reed36e6e262014-11-14 08:27:40 -080091
Mike Reed06d7c9d2020-08-26 12:56:51 -040092 SkRect outer = SkRect::MakeXYWH(10.125f, 10.125f, 100.125f, 100);
93 SkRect inner = SkRect::MakeXYWH(20.25f, 20.125f, 80, 80);
94 SkPath path = SkPathBuilder().addRect(outer, SkPathDirection::kCW)
95 .addRect(inner, SkPathDirection::kCCW)
96 .detach();
reed36e6e262014-11-14 08:27:40 -080097
Mike Reed06d7c9d2020-08-26 12:56:51 -040098 canvas->drawPath(path, paint);
99 // important to translate by a factional amount to exercise a different "phase"
100 // of the same path w.r.t. the pixel grid
101 SkScalar dx = SkScalarRoundToScalar(path.getBounds().width()) + 14 + 0.25f;
102 canvas->translate(dx, 0);
103 canvas->drawPath(path, paint);
halcanary2a243382015-09-09 08:16:41 -0700104}
qiankun.miao28828d02014-12-10 07:40:36 -0800105
halcanary2a243382015-09-09 08:16:41 -0700106DEF_SIMPLE_GM(blur2rectsnonninepatch, canvas, 700, 500) {
Mike Reed06d7c9d2020-08-26 12:56:51 -0400107 SkPaint paint;
108 paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 4.3f));
qiankun.miao28828d02014-12-10 07:40:36 -0800109
Mike Reed06d7c9d2020-08-26 12:56:51 -0400110 SkRect outer = SkRect::MakeXYWH(10, 110, 100, 100);
111 SkRect inner = SkRect::MakeXYWH(50, 150, 10, 10);
112 SkPath path = SkPathBuilder().addRect(outer, SkPathDirection::kCW)
113 .addRect(inner, SkPathDirection::kCW)
114 .detach();
115 canvas->drawPath(path, paint);
qiankun.miao28828d02014-12-10 07:40:36 -0800116
Mike Reed06d7c9d2020-08-26 12:56:51 -0400117 SkScalar dx = SkScalarRoundToScalar(path.getBounds().width()) + 40 + 0.25f;
118 canvas->translate(dx, 0);
119 canvas->drawPath(path, paint);
qiankun.miao28828d02014-12-10 07:40:36 -0800120
Mike Reed06d7c9d2020-08-26 12:56:51 -0400121 // Translate to outside of clip bounds.
122 canvas->translate(-dx, 0);
123 canvas->translate(-30, -150);
124 canvas->drawPath(path, paint);
halcanary2a243382015-09-09 08:16:41 -0700125}
Hal Canary9982c4e2017-06-07 15:23:49 -0400126
127DEF_SIMPLE_GM(BlurDrawImage, canvas, 256, 256) {
128 SkPaint paint;
Mike Reed1be1f8d2018-03-14 13:01:17 -0400129 paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 10));
Hal Canary9982c4e2017-06-07 15:23:49 -0400130 canvas->clear(0xFF88FF88);
Kevin Lubick8b741882023-10-06 11:41:38 -0400131 if (auto image = ToolUtils::GetResourceAsImage("images/mandrill_512_q075.jpg")) {
Hal Canary9982c4e2017-06-07 15:23:49 -0400132 canvas->scale(0.25, 0.25);
Mike Reed8d29ab62021-01-23 18:10:39 -0500133 canvas->drawImage(image, 256, 256, SkSamplingOptions(), &paint);
Hal Canary9982c4e2017-06-07 15:23:49 -0400134 }
135}
Herb Derbyf07a3632019-09-23 16:46:09 -0400136
137DEF_SIMPLE_GM(BlurBigSigma, canvas, 1024, 1024) {
138 SkPaint layerPaint, p;
139
Michael Ludwige2674642020-10-21 13:01:34 -0400140 p.setImageFilter(SkImageFilters::Blur(500, 500, nullptr));
Herb Derbyf07a3632019-09-23 16:46:09 -0400141
142 canvas->drawRect(SkRect::MakeWH(700, 800), p);
143}
Michael Ludwige2674642020-10-21 13:01:34 -0400144
Jim Van Verth2b3403a2021-01-27 15:18:14 -0500145DEF_SIMPLE_GM(BlurSmallSigma, canvas, 512, 256) {
146 {
147 // Normal sigma on x-axis, a small but non-zero sigma on y-axis that should
148 // be treated as identity.
149 SkPaint paint;
150 paint.setImageFilter(SkImageFilters::Blur(16.f, 1e-5f, nullptr));
151 canvas->drawRect(SkRect::MakeLTRB(64, 64, 192, 192), paint);
152 }
Michael Ludwige2674642020-10-21 13:01:34 -0400153
Jim Van Verth2b3403a2021-01-27 15:18:14 -0500154 {
155 // Small sigma on both axes, should be treated as identity and no red should show
156 SkPaint paint;
157 paint.setColor(SK_ColorRED);
158 SkRect rect = SkRect::MakeLTRB(320, 64, 448, 192);
159 canvas->drawRect(rect, paint);
160 paint.setColor(SK_ColorBLACK);
161 paint.setImageFilter(SkImageFilters::Blur(1e-5f, 1e-5f, nullptr));
162 canvas->drawRect(rect, paint);
163 }
Michael Ludwige2674642020-10-21 13:01:34 -0400164}
Michael Ludwige585bb62023-11-08 13:14:09 -0500165
166// Modeled after crbug.com/1500021, incorporates manual tiling to emulate Chrome's raster tiles
167// or the tiled rendering mode in Viewer.
168DEF_SIMPLE_GM(TiledBlurBigSigma, canvas, 1024, 768) {
169 static constexpr int kTileWidth = 342;
170 static constexpr int kTileHeight = 256;
171
172 SkM44 origCTM = canvas->getLocalToDevice();
173
174 for (int y = 0; y < 3; ++y) {
175 for (int x = 0; x < 3; ++x) {
176 // Define tiled grid in the canvas pixel space
177 canvas->save();
178 canvas->resetMatrix();
179
180 canvas->clipIRect(SkIRect::MakeXYWH(x*kTileWidth, y*kTileHeight,
181 kTileWidth, kTileHeight));
182 canvas->setMatrix(origCTM);
183
184 auto flood = SkImageFilters::ColorFilter(SkColorFilters::Blend(
185 SK_ColorBLACK, SkBlendMode::kSrc), nullptr);
186 auto blend = SkImageFilters::Blend(SkBlendMode::kSrcOver,
187 std::move(flood), nullptr);
188 auto blur = SkImageFilters::Blur(206.f, 206.f, std::move(blend));
189
190 SkPaint p;
191 p.setImageFilter(std::move(blur));
192
193 canvas->clipRect({0, 0, 1970, 1223});
194 canvas->saveLayer(nullptr, &p);
195 SkPaint fill;
196 fill.setColor(SK_ColorBLUE);
197 canvas->drawCircle(600, 150, 350, fill);
198 canvas->restore();
199 canvas->restore();
200 }
201 }
202}