• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.h"
9 #include "sk_tool_utils.h"
10 #include "SkTArray.h"
11 #include "SkRandom.h"
12 #include "SkMatrix.h"
13 #include "SkBlurMaskFilter.h"
14 #include "SkColorFilter.h"
15 #include "SkGradientShader.h"
16 #include "SkBlurDrawLooper.h"
17 #include "SkRect.h"
18 #include "SkRRect.h"
19 
20 namespace skiagm {
21 
gen_color(SkRandom * rand)22 static SkColor gen_color(SkRandom* rand) {
23     SkScalar hsv[3];
24     hsv[0] = rand->nextRangeF(0.0f, 360.0f);
25     hsv[1] = rand->nextRangeF(0.75f, 1.0f);
26     hsv[2] = rand->nextRangeF(0.75f, 1.0f);
27 
28     return sk_tool_utils::color_to_565(SkHSVToColor(hsv));
29 }
30 
31 class RoundRectGM : public GM {
32 public:
RoundRectGM()33     RoundRectGM() {
34         this->setBGColor(0xFF000000);
35         this->makePaints();
36         this->makeMatrices();
37     }
38 
39 protected:
40 
onShortName()41     SkString onShortName() override {
42         return SkString("roundrects");
43     }
44 
onISize()45     SkISize onISize() override {
46         return SkISize::Make(1200, 900);
47     }
48 
makePaints()49     void makePaints() {
50         {
51             // no AA
52             SkPaint p;
53             fPaints.push_back(p);
54         }
55 
56         {
57             // AA
58             SkPaint p;
59             p.setAntiAlias(true);
60             fPaints.push_back(p);
61         }
62 
63         {
64             // AA with stroke style
65             SkPaint p;
66             p.setAntiAlias(true);
67             p.setStyle(SkPaint::kStroke_Style);
68             p.setStrokeWidth(SkIntToScalar(5));
69             fPaints.push_back(p);
70         }
71 
72         {
73             // AA with stroke style, width = 0
74             SkPaint p;
75             p.setAntiAlias(true);
76             p.setStyle(SkPaint::kStroke_Style);
77             fPaints.push_back(p);
78         }
79 
80         {
81             // AA with stroke and fill style
82             SkPaint p;
83             p.setAntiAlias(true);
84             p.setStyle(SkPaint::kStrokeAndFill_Style);
85             p.setStrokeWidth(SkIntToScalar(3));
86             fPaints.push_back(p);
87         }
88     }
89 
makeMatrices()90     void makeMatrices() {
91         {
92             SkMatrix m;
93             m.setIdentity();
94             fMatrices.push_back(m);
95         }
96 
97         {
98             SkMatrix m;
99             m.setScale(SkIntToScalar(3), SkIntToScalar(2));
100             fMatrices.push_back(m);
101         }
102 
103         {
104             SkMatrix m;
105             m.setScale(SkIntToScalar(2), SkIntToScalar(2));
106             fMatrices.push_back(m);
107         }
108 
109         {
110             SkMatrix m;
111             m.setScale(SkIntToScalar(1), SkIntToScalar(2));
112             fMatrices.push_back(m);
113         }
114 
115         {
116             SkMatrix m;
117             m.setScale(SkIntToScalar(4), SkIntToScalar(1));
118             fMatrices.push_back(m);
119         }
120 
121         {
122             SkMatrix m;
123             m.setRotate(SkIntToScalar(90));
124             fMatrices.push_back(m);
125         }
126 
127         {
128             SkMatrix m;
129             m.setSkew(SkIntToScalar(2), SkIntToScalar(3));
130             fMatrices.push_back(m);
131         }
132 
133         {
134             SkMatrix m;
135             m.setRotate(SkIntToScalar(60));
136             fMatrices.push_back(m);
137         }
138     }
139 
onDraw(SkCanvas * canvas)140     void onDraw(SkCanvas* canvas) override {
141         SkRandom rand(1);
142         canvas->translate(20 * SK_Scalar1, 20 * SK_Scalar1);
143         const SkRect rect = SkRect::MakeLTRB(-20, -30, 20, 30);
144         SkRRect circleRect;
145         circleRect.setRectXY(rect, 5, 5);
146 
147         const SkScalar kXStart = 60.0f;
148         const SkScalar kYStart = 80.0f;
149         const int kXStep = 150;
150         const int kYStep = 160;
151         int maxX = fMatrices.count();
152 
153         SkPaint rectPaint;
154         rectPaint.setAntiAlias(true);
155         rectPaint.setStyle(SkPaint::kStroke_Style);
156         rectPaint.setStrokeWidth(SkIntToScalar(0));
157         rectPaint.setColor(SK_ColorLTGRAY);
158 
159         int testCount = 0;
160         for (int i = 0; i < fPaints.count(); ++i) {
161             for (int j = 0; j < fMatrices.count(); ++j) {
162                 canvas->save();
163                 SkMatrix mat = fMatrices[j];
164                 // position the roundrect, and make it at off-integer coords.
165                 mat.postTranslate(kXStart + SK_Scalar1 * kXStep * (testCount % maxX) +
166                                   SK_Scalar1 / 4,
167                                   kYStart + SK_Scalar1 * kYStep * (testCount / maxX) +
168                                   3 * SK_Scalar1 / 4);
169                 canvas->concat(mat);
170 
171                 SkColor color = gen_color(&rand);
172                 fPaints[i].setColor(color);
173 
174                 canvas->drawRect(rect, rectPaint);
175                 canvas->drawRRect(circleRect, fPaints[i]);
176 
177                 canvas->restore();
178 
179                 ++testCount;
180             }
181         }
182 
183         // special cases
184 
185         // non-scaled tall and skinny roundrect
186         for (int i = 0; i < fPaints.count(); ++i) {
187             SkRect rect = SkRect::MakeLTRB(-20, -60, 20, 60);
188             SkRRect ellipseRect;
189             ellipseRect.setRectXY(rect, 5, 10);
190 
191             canvas->save();
192             // position the roundrect, and make it at off-integer coords.
193             canvas->translate(kXStart + SK_Scalar1 * kXStep * 2.55f + SK_Scalar1 / 4,
194                               kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4);
195 
196             SkColor color = gen_color(&rand);
197             fPaints[i].setColor(color);
198 
199             canvas->drawRect(rect, rectPaint);
200             canvas->drawRRect(ellipseRect, fPaints[i]);
201             canvas->restore();
202         }
203 
204         // non-scaled wide and short roundrect
205         for (int i = 0; i < fPaints.count(); ++i) {
206             SkRect rect = SkRect::MakeLTRB(-80, -30, 80, 30);
207             SkRRect ellipseRect;
208             ellipseRect.setRectXY(rect, 20, 5);
209 
210             canvas->save();
211             // position the roundrect, and make it at off-integer coords.
212             canvas->translate(kXStart + SK_Scalar1 * kXStep * 4 + SK_Scalar1 / 4,
213                               kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4 +
214                               SK_ScalarHalf * kYStep);
215 
216             SkColor color = gen_color(&rand);
217             fPaints[i].setColor(color);
218 
219             canvas->drawRect(rect, rectPaint);
220             canvas->drawRRect(ellipseRect, fPaints[i]);
221             canvas->restore();
222         }
223 
224         // super skinny roundrect
225         for (int i = 0; i < fPaints.count(); ++i) {
226             SkRect rect = SkRect::MakeLTRB(0, -60, 1, 60);
227             SkRRect circleRect;
228             circleRect.setRectXY(rect, 5, 5);
229 
230             canvas->save();
231             // position the roundrect, and make it at off-integer coords.
232             canvas->translate(kXStart + SK_Scalar1 * kXStep * 3.25f + SK_Scalar1 / 4,
233                               kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4);
234 
235             SkColor color = gen_color(&rand);
236             fPaints[i].setColor(color);
237 
238             canvas->drawRRect(circleRect, fPaints[i]);
239             canvas->restore();
240         }
241 
242         // super short roundrect
243         for (int i = 0; i < fPaints.count(); ++i) {
244             SkRect rect = SkRect::MakeLTRB(-80, -1, 80, 0);
245             SkRRect circleRect;
246             circleRect.setRectXY(rect, 5, 5);
247 
248             canvas->save();
249             // position the roundrect, and make it at off-integer coords.
250             canvas->translate(kXStart + SK_Scalar1 * kXStep * 2.5f + SK_Scalar1 / 4,
251                               kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4 +
252                               SK_ScalarHalf * kYStep);
253 
254             SkColor color = gen_color(&rand);
255             fPaints[i].setColor(color);
256 
257             canvas->drawRRect(circleRect, fPaints[i]);
258             canvas->restore();
259         }
260 
261         // radial gradient
262         SkPoint center = SkPoint::Make(SkIntToScalar(0), SkIntToScalar(0));
263         SkColor colors[] = { SK_ColorBLUE, SK_ColorRED, SK_ColorGREEN };
264         SkScalar pos[] = { 0, SK_ScalarHalf, SK_Scalar1 };
265         auto shader = SkGradientShader::MakeRadial(center, 20, colors, pos, SK_ARRAY_COUNT(colors),
266                                                    SkShader::kClamp_TileMode);
267 
268         for (int i = 0; i < fPaints.count(); ++i) {
269             canvas->save();
270             // position the path, and make it at off-integer coords.
271             canvas->translate(kXStart + SK_Scalar1 * kXStep * 0 + SK_Scalar1 / 4,
272                               kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4 +
273                               SK_ScalarHalf * kYStep);
274 
275             SkColor color = gen_color(&rand);
276             fPaints[i].setColor(color);
277             fPaints[i].setShader(shader);
278 
279             canvas->drawRect(rect, rectPaint);
280             canvas->drawRRect(circleRect, fPaints[i]);
281 
282             fPaints[i].setShader(nullptr);
283 
284             canvas->restore();
285         }
286 
287         // strokes and radii
288         {
289             SkScalar radii[][2] = {
290                 {10,10},
291                 {5,15},
292                 {5,15},
293                 {5,15}
294             };
295 
296             SkScalar strokeWidths[] = {
297                 20, 10, 20, 40
298             };
299 
300             for (int i = 0; i < 4; ++i) {
301                 SkRRect circleRect;
302                 circleRect.setRectXY(rect, radii[i][0], radii[i][1]);
303 
304                 canvas->save();
305                 // position the roundrect, and make it at off-integer coords.
306                 canvas->translate(kXStart + SK_Scalar1 * kXStep * 5 + SK_Scalar1 / 4,
307                                   kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4 +
308                                   SK_ScalarHalf * kYStep);
309 
310                 SkColor color = gen_color(&rand);
311 
312                 SkPaint p;
313                 p.setAntiAlias(true);
314                 p.setStyle(SkPaint::kStroke_Style);
315                 p.setStrokeWidth(strokeWidths[i]);
316                 p.setColor(color);
317 
318                 canvas->drawRRect(circleRect, p);
319                 canvas->restore();
320             }
321         }
322 
323         // test old entry point ( https://bug.skia.org/3786 )
324         {
325             canvas->save();
326 
327             canvas->translate(kXStart + SK_Scalar1 * kXStep * 5 + SK_Scalar1 / 4,
328                               kYStart + SK_Scalar1 * kYStep * 4 + SK_Scalar1 / 4 +
329                               SK_ScalarHalf * kYStep);
330 
331             const SkColor color = gen_color(&rand);
332 
333             SkPaint p;
334             p.setColor(color);
335 
336             const SkRect oooRect = { 20, 30, -20, -30 };     // intentionally out of order
337             canvas->drawRoundRect(oooRect, 10, 10, p);
338 
339             canvas->restore();
340         }
341 
342         // rrect with stroke > radius/2
343         {
344             SkRect smallRect = { -30, -20, 30, 20 };
345             SkRRect circleRect;
346             circleRect.setRectXY(smallRect, 5, 5);
347 
348             canvas->save();
349             // position the roundrect, and make it at off-integer coords.
350             canvas->translate(kXStart + SK_Scalar1 * kXStep * 5 + SK_Scalar1 / 4,
351                               kYStart - SK_Scalar1 * kYStep + 73 * SK_Scalar1 / 4 +
352                               SK_ScalarHalf * kYStep);
353 
354             SkColor color = gen_color(&rand);
355 
356             SkPaint p;
357             p.setAntiAlias(true);
358             p.setStyle(SkPaint::kStroke_Style);
359             p.setStrokeWidth(25);
360             p.setColor(color);
361 
362             canvas->drawRRect(circleRect, p);
363             canvas->restore();
364         }
365     }
366 
367 private:
368     SkTArray<SkPaint> fPaints;
369     SkTArray<SkMatrix> fMatrices;
370 
371     typedef GM INHERITED;
372 };
373 
374 //////////////////////////////////////////////////////////////////////////////
375 
376 DEF_GM( return new RoundRectGM; )
377 
378 }
379