1 /*
2  * Copyright 2019 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.h"
9 #include "SkBlurImageFilter.h"
10 #include "SkGradientShader.h"
11 #include "SkLiteDL.h"
12 #include "SkLiteRecorder.h"
13 #include "SkPictureRecorder.h"
14 
15 // Make a noisy (with hard-edges) background, so we can see the effect of the blur
16 //
make_shader(SkScalar cx,SkScalar cy,SkScalar rad)17 static sk_sp<SkShader> make_shader(SkScalar cx, SkScalar cy, SkScalar rad) {
18     const SkColor colors[] = {
19         SK_ColorRED, SK_ColorRED, SK_ColorBLUE, SK_ColorBLUE, SK_ColorGREEN, SK_ColorGREEN,
20         SK_ColorRED, SK_ColorRED, SK_ColorBLUE, SK_ColorBLUE, SK_ColorGREEN, SK_ColorGREEN,
21     };
22     constexpr int count = SK_ARRAY_COUNT(colors);
23     SkScalar pos[count] = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6 };
24     for (int i = 0; i < count; ++i) {
25         pos[i] *= 1.0f/6;
26     }
27     return SkGradientShader::MakeSweep(cx, cy, colors, pos, count);
28 }
29 
do_draw(SkCanvas * canvas,bool useClip,bool useHintRect)30 static void do_draw(SkCanvas* canvas, bool useClip, bool useHintRect) {
31     SkAutoCanvasRestore acr(canvas, true);
32     canvas->clipRect({0, 0, 256, 256});
33 
34     const SkScalar cx = 128, cy = 128, rad = 100;
35     SkPaint p;
36     p.setShader(make_shader(cx, cy, rad));
37     p.setAntiAlias(true);
38     canvas->drawCircle(cx, cy, rad, p);
39 
40     // now setup a saveLayer that will pull in the backdrop and blur it
41     //
42     const SkRect r = {cx-50, cy-50, cx+50, cy+50};
43     const SkRect* drawrptr = useHintRect ? &r : nullptr;
44     const SkScalar sigma = 10;
45     if (useClip) {
46         canvas->clipRect(r);
47     }
48     auto blur = SkBlurImageFilter::Make(sigma, sigma, nullptr);
49     auto rec = SkCanvas::SaveLayerRec(drawrptr, nullptr, blur.get(), 0);
50     canvas->saveLayer(rec);
51         // draw something inside, just to demonstrate that we don't blur the new contents,
52         // just the backdrop.
53         p.setColor(SK_ColorYELLOW);
54         p.setShader(nullptr);
55         canvas->drawCircle(cx, cy, 30, p);
56     canvas->restore();
57 }
58 
59 /*
60  *  Draws a 3x4 grid of sweep circles.
61  *  - for a given row, each col should be identical (canvas, picture, litedl)
62  *  - row:0     no-hint-rect    no-clip-rect        expect big blur (except inner circle)
63  *  - row:1     no-hint-rect    clip-rect           expect small blur (except inner circle)
64  *  - row:2     hint-rect       no-clip-rect        expect big blur (except inner circle)
65  *  - row:3     hint-rect       clip-rect           expect small blur (except inner circle)
66  *
67  *  The test is that backdrop effects should be independent of the hint-rect, but should
68  *  respect the clip-rect.
69  */
70 DEF_SIMPLE_GM(backdrop_hintrect_clipping, canvas, 768, 1024) {
71     for (bool useHintRect : {false, true}) {
72         for (bool useClip : {false, true}) {
73             SkAutoCanvasRestore acr(canvas, true);
74 
75             do_draw(canvas, useClip, useHintRect);
76 
77             SkPictureRecorder rec;
78             do_draw(rec.beginRecording(256, 256), useClip, useHintRect);
79             canvas->translate(256, 0);
80             canvas->drawPicture(rec.finishRecordingAsPicture());
81 
82             SkLiteDL dl;
83             SkLiteRecorder lite;
84             lite.reset(&dl, {0, 0, 256, 256});
85             do_draw(&lite, useClip, useHintRect);
86             canvas->translate(256, 0);
87             dl.draw(canvas);
88 
89             acr.restore();
90             canvas->translate(0, 256);
91         }
92     }
93 }
94