1 /*
2  * Copyright 2013 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/SkDrawLooper.h"
13 #include "include/core/SkMaskFilter.h"
14 #include "include/core/SkMatrix.h"
15 #include "include/core/SkPaint.h"
16 #include "include/core/SkPoint.h"
17 #include "include/core/SkRect.h"
18 #include "include/core/SkScalar.h"
19 #include "include/core/SkShader.h"
20 #include "include/core/SkSize.h"
21 #include "include/core/SkString.h"
22 #include "include/core/SkTileMode.h"
23 #include "include/core/SkTypes.h"
24 #include "include/effects/SkBlurDrawLooper.h"
25 #include "include/effects/SkGradientShader.h"
26 #include "include/private/SkTArray.h"
27 #include "src/core/SkBlurMask.h"
28 
29 namespace skiagm {
30 
31 class RectsGM : public GM {
32     sk_sp<SkDrawLooper> fLooper;
33     enum {
34         kLooperColorSentinel = 0x01020304
35     };
36 
37 protected:
onOnceBeforeDraw()38     void onOnceBeforeDraw() override {
39         this->setBGColor(0xFF000000);
40         this->makePaints();
41         this->makeMatrices();
42         this->makeRects();
43     }
44 
onShortName()45     SkString onShortName() override {
46         return SkString("rects");
47     }
48 
onISize()49     SkISize onISize() override {
50         return SkISize::Make(1200, 900);
51     }
52 
makePaints()53     void makePaints() {
54         {
55             // no AA
56             SkPaint p;
57             p.setColor(SK_ColorWHITE);
58             fPaints.push_back(p);
59         }
60 
61         {
62             // AA
63             SkPaint p;
64             p.setColor(SK_ColorWHITE);
65             p.setAntiAlias(true);
66             fPaints.push_back(p);
67         }
68 
69         {
70             // AA with translucent
71             SkPaint p;
72             p.setColor(SK_ColorWHITE);
73             p.setAntiAlias(true);
74             p.setAlpha(0x66);
75             fPaints.push_back(p);
76         }
77 
78         {
79             // AA with mask filter
80             SkPaint p;
81             p.setColor(SK_ColorWHITE);
82             p.setAntiAlias(true);
83             p.setMaskFilter(SkMaskFilter::MakeBlur(
84                                    kNormal_SkBlurStyle,
85                                    SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(5))));
86             fPaints.push_back(p);
87         }
88 
89         {
90             // AA with radial shader
91             SkPaint p;
92             p.setColor(SK_ColorWHITE);
93             p.setAntiAlias(true);
94             SkPoint center = SkPoint::Make(SkIntToScalar(-5), SkIntToScalar(30));
95             SkColor colors[] = { SK_ColorBLUE, SK_ColorRED, SK_ColorGREEN };
96             SkScalar pos[] = { 0, SK_ScalarHalf, SK_Scalar1 };
97             p.setShader(SkGradientShader::MakeRadial(center, 20, colors, pos,
98                                                      SK_ARRAY_COUNT(colors),
99                                                      SkTileMode::kClamp));
100             fPaints.push_back(p);
101         }
102 
103         fLooper = SkBlurDrawLooper::Make(SK_ColorWHITE, SkBlurMask::ConvertRadiusToSigma(10),5,10);
104         {
105             SkPaint p;
106             p.setColor(kLooperColorSentinel);
107             p.setAntiAlias(true);
108             fPaints.push_back(p);
109         }
110         {
111             // AA with stroke style
112             SkPaint p;
113             p.setColor(SK_ColorWHITE);
114             p.setAntiAlias(true);
115             p.setStyle(SkPaint::kStroke_Style);
116             p.setStrokeWidth(SkIntToScalar(3));
117             fPaints.push_back(p);
118         }
119 
120         {
121             // AA with bevel-stroke style
122             SkPaint p;
123             p.setColor(SK_ColorWHITE);
124             p.setAntiAlias(true);
125             p.setStyle(SkPaint::kStroke_Style);
126             p.setStrokeJoin(SkPaint::kBevel_Join);
127             p.setStrokeWidth(SkIntToScalar(3));
128             fPaints.push_back(p);
129         }
130 
131         {
132             // AA with round-stroke style
133             SkPaint p;
134             p.setColor(SK_ColorWHITE);
135             p.setAntiAlias(true);
136             p.setStyle(SkPaint::kStroke_Style);
137             p.setStrokeJoin(SkPaint::kRound_Join);
138             p.setStrokeWidth(SkIntToScalar(3));
139             fPaints.push_back(p);
140         }
141 
142         {
143             // AA with stroke style, width = 0
144             SkPaint p;
145             p.setColor(SK_ColorWHITE);
146             p.setAntiAlias(true);
147             p.setStyle(SkPaint::kStroke_Style);
148             fPaints.push_back(p);
149         }
150 
151         {
152             // AA with stroke style, width wider than rect width and/or height
153             SkPaint p;
154             p.setColor(SK_ColorWHITE);
155             p.setAntiAlias(true);
156             p.setStyle(SkPaint::kStroke_Style);
157             p.setStrokeWidth(SkIntToScalar(40));
158             fPaints.push_back(p);
159         }
160 
161         {
162             // AA with stroke and fill style
163             SkPaint p;
164             p.setColor(SK_ColorWHITE);
165             p.setAntiAlias(true);
166             p.setStyle(SkPaint::kStrokeAndFill_Style);
167             p.setStrokeWidth(SkIntToScalar(2));
168             fPaints.push_back(p);
169         }
170     }
171 
makeMatrices()172     void makeMatrices() {
173         {
174             // 1x1.5 scale
175             SkMatrix m;
176             m.setScale(1, 1.5f);
177             fMatrices.push_back(m);
178         }
179 
180         {
181             // 1.5x1.5 scale
182             SkMatrix m;
183             m.setScale(1.5f, 1.5f);
184             fMatrices.push_back(m);
185         }
186 
187         {
188             // 1x1.5 skew
189             SkMatrix m;
190             m.setSkew(1, 1.5f);
191             fMatrices.push_back(m);
192         }
193 
194         {
195             // 1.5x1.5 skew
196             SkMatrix m;
197             m.setSkew(1.5f, 1.5f);
198             fMatrices.push_back(m);
199         }
200 
201         {
202             // 30 degree rotation
203             SkMatrix m;
204             m.setRotate(SkIntToScalar(30));
205             fMatrices.push_back(m);
206         }
207 
208         {
209             // 90 degree rotation
210             SkMatrix m;
211             m.setRotate(SkIntToScalar(90));
212             fMatrices.push_back(m);
213         }
214     }
215 
makeRects()216     void makeRects() {
217         {
218             // small square
219             SkRect r = SkRect::MakeLTRB(0, 0, 30, 30);
220             fRects.push_back(r);
221         }
222 
223         {
224             // thin vertical
225             SkRect r = SkRect::MakeLTRB(0, 0, 2, 40);
226             fRects.push_back(r);
227         }
228 
229         {
230             // thin horizontal
231             SkRect r = SkRect::MakeLTRB(0, 0, 40, 2);
232             fRects.push_back(r);
233         }
234 
235         {
236             // very thin
237             SkRect r = SkRect::MakeLTRB(0, 0, 0.25f, 10);
238             fRects.push_back(r);
239         }
240 
241         {
242             // zaftig
243             SkRect r = SkRect::MakeLTRB(0, 0, 60, 60);
244             fRects.push_back(r);
245         }
246     }
247 
248     // position the current test on the canvas
Position(SkCanvas * canvas,int testCount)249     static void Position(SkCanvas* canvas, int testCount) {
250         canvas->translate(SK_Scalar1 * 100 * (testCount % 10) + SK_Scalar1 / 4,
251                           SK_Scalar1 * 100 * (testCount / 10) + 3 * SK_Scalar1 / 4);
252     }
253 
onDraw(SkCanvas * canvas)254     void onDraw(SkCanvas* canvas) override {
255         canvas->translate(20 * SK_Scalar1, 20 * SK_Scalar1);
256 
257         int testCount = 0;
258 
259         for (int i = 0; i < fPaints.count(); ++i) {
260             for (int j = 0; j < fRects.count(); ++j, ++testCount) {
261                 canvas->save();
262                 Position(canvas, testCount);
263                 SkPaint p = fPaints[i];
264                 if (p.getColor() == kLooperColorSentinel) {
265                     p.setColor(SK_ColorWHITE);
266                     SkRect r = fRects[j];
267                     fLooper->apply(canvas, p, [r](SkCanvas* c, const SkPaint& p) {
268                         c->drawRect(r, p);
269                     });
270                 } else {
271                     canvas->drawRect(fRects[j], p);
272                 }
273                 canvas->restore();
274             }
275         }
276 
277         SkPaint paint;
278         paint.setColor(SK_ColorWHITE);
279         paint.setAntiAlias(true);
280 
281         for (int i = 0; i < fMatrices.count(); ++i) {
282             for (int j = 0; j < fRects.count(); ++j, ++testCount) {
283                 canvas->save();
284                 Position(canvas, testCount);
285                 canvas->concat(fMatrices[i]);
286                 canvas->drawRect(fRects[j], paint);
287                 canvas->restore();
288             }
289         }
290     }
291 
292 private:
293     SkTArray<SkPaint>  fPaints;
294     SkTArray<SkMatrix> fMatrices;
295     SkTArray<SkRect>   fRects;
296 
297     using INHERITED = GM;
298 };
299 
300 //////////////////////////////////////////////////////////////////////////////
301 
302 DEF_GM( return new RectsGM; )
303 
304 }  // namespace skiagm
305