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