xref: /aosp_15_r20/external/skia/gm/blurs.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
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  */
7 
8 #include "gm/gm.h"
9 #include "include/core/SkBlurTypes.h"
10 #include "include/core/SkCanvas.h"
11 #include "include/core/SkColor.h"
12 #include "include/core/SkColorFilter.h"
13 #include "include/core/SkFont.h"
14 #include "include/core/SkMaskFilter.h"
15 #include "include/core/SkPaint.h"
16 #include "include/core/SkPathBuilder.h"
17 #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"
22 #include "include/effects/SkImageFilters.h"
23 #include "src/core/SkBlurMask.h"
24 #include "tools/DecodeUtils.h"
25 #include "tools/Resources.h"
26 #include "tools/ToolUtils.h"
27 #include "tools/fonts/FontToolUtils.h"
28 
29 DEF_SIMPLE_GM_BG(blurs, canvas, 700, 500, 0xFFDDDDDD) {
30     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     };
41 
42     SkPaint paint;
43     paint.setAntiAlias(true);
44     paint.setColor(SK_ColorBLUE);
45 
46     canvas->translate(SkIntToScalar(-40), SkIntToScalar(0));
47 
48     for (size_t i = 0; i < std::size(gRecs); i++) {
49         if (gRecs[i].fStyle != NONE) {
50             paint.setMaskFilter(SkMaskFilter::MakeBlur(gRecs[i].fStyle,
51                                    SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(20))));
52         } else {
53             paint.setMaskFilter(nullptr);
54         }
55         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     {
62         SkFont font(ToolUtils::DefaultPortableTypeface(), 25);
63         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     }
77 }
78 
79 //////////////////////////////////////////////////////////////////////////////////////////////
80 
81 // 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 //
87 DEF_SIMPLE_GM(blur2rects, canvas, 700, 500) {
88     SkPaint paint;
89 
90     paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 2.3f));
91 
92     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();
97 
98     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);
104 }
105 
106 DEF_SIMPLE_GM(blur2rectsnonninepatch, canvas, 700, 500) {
107     SkPaint paint;
108     paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 4.3f));
109 
110     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);
116 
117     SkScalar dx = SkScalarRoundToScalar(path.getBounds().width()) + 40 + 0.25f;
118     canvas->translate(dx, 0);
119     canvas->drawPath(path, paint);
120 
121     // Translate to outside of clip bounds.
122     canvas->translate(-dx, 0);
123     canvas->translate(-30, -150);
124     canvas->drawPath(path, paint);
125 }
126 
127 DEF_SIMPLE_GM(BlurDrawImage, canvas, 256, 256) {
128     SkPaint paint;
129     paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 10));
130     canvas->clear(0xFF88FF88);
131     if (auto image = ToolUtils::GetResourceAsImage("images/mandrill_512_q075.jpg")) {
132         canvas->scale(0.25, 0.25);
133         canvas->drawImage(image, 256, 256, SkSamplingOptions(), &paint);
134     }
135 }
136 
137 DEF_SIMPLE_GM(BlurBigSigma, canvas, 1024, 1024) {
138     SkPaint layerPaint, p;
139 
140     p.setImageFilter(SkImageFilters::Blur(500, 500, nullptr));
141 
142     canvas->drawRect(SkRect::MakeWH(700, 800), p);
143 }
144 
145 DEF_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     }
153 
154     {
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     }
164 }
165 
166 // Modeled after crbug.com/1500021, incorporates manual tiling to emulate Chrome's raster tiles
167 // or the tiled rendering mode in Viewer.
168 DEF_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 }
203