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