• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * Copyright 2016 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 "SkRandom.h"
11 #include "SkRRect.h"
12 
13 namespace skiagm {
14 
15 /*
16  * This is the base class for two GMs that cover various corner cases with primitive Skia shapes
17  * (zero radius, near-zero radius, inner shape overlap, etc.) It uses an xfermode of darken to help
18  * double-blended and/or dropped pixels stand out.
19  */
20 class ShapesGM : public GM {
21 protected:
ShapesGM(const char * name,bool antialias)22     ShapesGM(const char* name, bool antialias) : fName(name), fAntialias(antialias) {
23         fShapes.push_back().setOval(SkRect::MakeXYWH(-5, 25, 200, 100));
24         fRotations.push_back(21);
25 
26         fShapes.push_back().setRect(SkRect::MakeXYWH(95, 75, 125, 100));
27         fRotations.push_back(94);
28 
29         fShapes.push_back().setRectXY(SkRect::MakeXYWH(0, 75, 150, 100), 1e-5f, 1e-5f);
30         fRotations.push_back(132);
31 
32         fShapes.push_back().setRectXY(SkRect::MakeXYWH(15, -20, 100, 100), 20, 15);
33         fRotations.push_back(282);
34 
35         fSimpleShapeCount = fShapes.count();
36 
37         fShapes.push_back().setNinePatch(SkRect::MakeXYWH(140, -50, 90, 110), 10, 5, 25, 35);
38         fRotations.push_back(0);
39 
40         fShapes.push_back().setNinePatch(SkRect::MakeXYWH(160, -60, 60, 90), 10, 60, 50, 30);
41         fRotations.push_back(-35);
42 
43         fShapes.push_back().setNinePatch(SkRect::MakeXYWH(220, -120, 60, 90), 1, 89, 59, 1);
44         fRotations.push_back(65);
45 
46         SkVector radii[4] = {{4, 6}, {12, 8}, {24, 16}, {32, 48}};
47         fShapes.push_back().setRectRadii(SkRect::MakeXYWH(150, -129, 80, 160), radii);
48         fRotations.push_back(265);
49 
50         SkVector radii2[4] = {{0, 0}, {80, 60}, {0, 0}, {80, 60}};
51         fShapes.push_back().setRectRadii(SkRect::MakeXYWH(180, -30, 80, 60), radii2);
52         fRotations.push_back(295);
53 
54         if (!antialias) {
55             fName.append("_bw");
56         }
57     }
58 
onShortName()59     SkString onShortName() override final { return fName; }
onISize()60     SkISize onISize() override { return SkISize::Make(500, 500); }
61 
onOnceBeforeDraw()62     void onOnceBeforeDraw() override {
63         fPaint.setXfermodeMode(SkXfermode::kDarken_Mode);
64         fPaint.setAntiAlias(fAntialias);
65     }
66 
onDraw(SkCanvas * canvas)67     void onDraw(SkCanvas* canvas) override {
68         canvas->clear(SK_ColorWHITE);
69 
70         canvas->save();
71         canvas->translate(canvas->imageInfo().width() / 2.f, canvas->imageInfo().height() / 2.f);
72         this->drawShapes(canvas);
73         canvas->restore();
74     }
75 
76     virtual void drawShapes(SkCanvas* canvas) const = 0;
77 
78 protected:
79     SkString             fName;
80     bool                 fAntialias;
81     SkPaint              fPaint;
82     SkTArray<SkRRect>    fShapes;
83     SkTArray<SkScalar>   fRotations;
84     int                  fSimpleShapeCount;
85 
86 private:
87     typedef GM INHERITED;
88 };
89 
90 class SimpleShapesGM : public ShapesGM {
91 public:
SimpleShapesGM(bool antialias)92     SimpleShapesGM(bool antialias) : INHERITED("simpleshapes", antialias) {}
93 
94 private:
drawShapes(SkCanvas * canvas) const95     void drawShapes(SkCanvas* canvas) const override {
96         SkRandom rand(2);
97         for (int i = 0; i < fShapes.count(); i++) {
98             SkPaint paint(fPaint);
99             paint.setColor(rand.nextU() & ~0x808080);
100             paint.setAlpha(128);  // Use alpha to detect double blends.
101             const SkRRect& shape = fShapes[i];
102             canvas->save();
103             canvas->rotate(fRotations[i]);
104             switch (shape.getType()) {
105                 case SkRRect::kRect_Type:
106                     canvas->drawRect(shape.rect(), paint);
107                     break;
108                 case SkRRect::kOval_Type:
109                     canvas->drawOval(shape.rect(), paint);
110                     break;
111                 default:
112                     canvas->drawRRect(shape, paint);
113                     break;
114             }
115             canvas->restore();
116         }
117     }
118 
119     typedef ShapesGM INHERITED;
120 };
121 
122 class InnerShapesGM : public ShapesGM {
123 public:
InnerShapesGM(bool antialias)124     InnerShapesGM(bool antialias) : INHERITED("innershapes", antialias) {}
125 
126 private:
drawShapes(SkCanvas * canvas) const127     void drawShapes(SkCanvas* canvas) const override {
128         SkRandom rand;
129         for (int i = 0; i < fShapes.count(); i++) {
130             const SkRRect& outer = fShapes[i];
131             const SkRRect& inner = fShapes[(i * 7 + 11) % fSimpleShapeCount];
132             float s = 0.95f * SkTMin(outer.rect().width() / inner.rect().width(),
133                                      outer.rect().height() / inner.rect().height());
134             SkMatrix innerXform;
135             float dx = (rand.nextF() - 0.5f) * (outer.rect().width() - s * inner.rect().width());
136             float dy = (rand.nextF() - 0.5f) * (outer.rect().height() - s * inner.rect().height());
137             innerXform.setTranslate(outer.rect().centerX() + dx, outer.rect().centerY() + dy);
138             if (s < 1) {
139                 innerXform.preScale(s, s);
140             }
141             innerXform.preTranslate(-inner.rect().centerX(), -inner.rect().centerY());
142             SkRRect xformedInner;
143             inner.transform(innerXform, &xformedInner);
144             SkPaint paint(fPaint);
145             paint.setColor(rand.nextU() & ~0x808080);
146             paint.setAlpha(128);  // Use alpha to detect double blends.
147             canvas->save();
148             canvas->rotate(fRotations[i]);
149             canvas->drawDRRect(outer, xformedInner, paint);
150             canvas->restore();
151         }
152     }
153 
154     typedef ShapesGM INHERITED;
155 };
156 
157 //////////////////////////////////////////////////////////////////////////////
158 
159 DEF_GM( return new SimpleShapesGM(true); )
160 DEF_GM( return new SimpleShapesGM(false); )
161 DEF_GM( return new InnerShapesGM(true); )
162 DEF_GM( return new InnerShapesGM(false); )
163 
164 }
165