• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2012 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 "SkRRect.h"
10 
11 namespace skiagm {
12 
13 ///////////////////////////////////////////////////////////////////////////////
14 
15 class RRectGM : public GM {
16 public:
RRectGM(bool doAA,bool doClip)17     RRectGM(bool doAA, bool doClip) : fDoAA(doAA), fDoClip(doClip) {
18         this->setBGColor(0xFFDDDDDD);
19         this->setUpRRects();
20     }
21 
22 protected:
onShortName()23     SkString onShortName() {
24         SkString name("rrect");
25         if (fDoClip) {
26             name.append("_clip");
27         }
28         if (fDoAA) {
29             name.append("_aa");
30         } else {
31             name.append("_bw");
32         }
33 
34         return name;
35     }
36 
onISize()37     virtual SkISize onISize() { return make_isize(kImageWidth, kImageHeight); }
38 
onDraw(SkCanvas * canvas)39     virtual void onDraw(SkCanvas* canvas) {
40 
41         SkPaint paint;
42         // when clipping the AA is pushed into the clip operation
43         paint.setAntiAlias(fDoClip ? false : fDoAA);
44 
45         static const SkRect kMaxTileBound = SkRect::MakeWH(SkIntToScalar(kTileX), SkIntToScalar(kTileY));
46 
47         int curRRect = 0;
48         for (int y = 1; y < kImageHeight; y += kTileY) {
49             for (int x = 1; x < kImageWidth; x += kTileX) {
50                 if (curRRect >= kNumRRects) {
51                     break;
52                 }
53                 SkASSERT(kMaxTileBound.contains(fRRects[curRRect].getBounds()));
54 
55                 canvas->save();
56                     canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
57                     if (fDoClip) {
58                         canvas->clipRRect(fRRects[curRRect], SkRegion::kReplace_Op, fDoAA);
59                         canvas->drawRect(kMaxTileBound, paint);
60                     } else {
61                         canvas->drawRRect(fRRects[curRRect], paint);
62                     }
63                     ++curRRect;
64                 canvas->restore();
65             }
66         }
67     }
68 
setUpRRects()69     void setUpRRects() {
70         // each RRect must fit in a 0x0 -> (kTileX-2)x(kTileY-2) block. These will be tiled across
71         // the screen in kTileX x kTileY tiles. The extra empty pixels on each side are for AA.
72 
73         // simple cases
74         fRRects[0].setRect(SkRect::MakeWH(kTileX-2, kTileY-2));
75         fRRects[1].setOval(SkRect::MakeWH(kTileX-2, kTileY-2));
76         fRRects[2].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 10, 10);
77 
78         // The first complex case needs special handling since it is a square
79         fRRects[kNumSimpleCases].setRectRadii(SkRect::MakeWH(kTileY-2, kTileY-2), gRadii[0]);
80         for (size_t i = 1; i < SK_ARRAY_COUNT(gRadii); ++i) {
81             fRRects[kNumSimpleCases+i].setRectRadii(SkRect::MakeWH(kTileX-2, kTileY-2), gRadii[i]);
82         }
83     }
84 
85 private:
86     bool fDoAA;
87     bool fDoClip;   // use clipRRect & drawRect instead of drawRRect
88 
89     static const int kImageWidth = 640;
90     static const int kImageHeight = 480;
91 
92     static const int kTileX = 80;
93     static const int kTileY = 40;
94 
95     static const int kNumSimpleCases = 3;
96     static const int kNumComplexCases = 19;
97     static const SkVector gRadii[kNumComplexCases][4];
98 
99     static const int kNumRRects = kNumSimpleCases + kNumComplexCases;
100     SkRRect fRRects[kNumRRects];
101 
102     typedef GM INHERITED;
103 };
104 
105 // Radii for the various test cases. Order is UL, UR, LR, LL
106 const SkVector RRectGM::gRadii[kNumComplexCases][4] = {
107     // a circle
108     { { kTileY, kTileY }, { kTileY, kTileY }, { kTileY, kTileY }, { kTileY, kTileY } },
109 
110     // odd ball cases
111     { { 8, 8 }, { 32, 32 }, { 8, 8 }, { 32, 32 } },
112     { { 16, 8 }, { 8, 16 }, { 16, 8 }, { 8, 16 } },
113     { { 0, 0 }, { 16, 16 }, { 8, 8 }, { 32, 32 } },
114 
115     // UL
116     { { 30, 30 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
117     { { 30, 15 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
118     { { 15, 30 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
119 
120     // UR
121     { { 0, 0 }, { 30, 30 }, { 0, 0 }, { 0, 0 } },
122     { { 0, 0 }, { 30, 15 }, { 0, 0 }, { 0, 0 } },
123     { { 0, 0 }, { 15, 30 }, { 0, 0 }, { 0, 0 } },
124 
125     // LR
126     { { 0, 0 }, { 0, 0 }, { 30, 30 }, { 0, 0 } },
127     { { 0, 0 }, { 0, 0 }, { 30, 15 }, { 0, 0 } },
128     { { 0, 0 }, { 0, 0 }, { 15, 30 }, { 0, 0 } },
129 
130     // LL
131     { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 30, 30 } },
132     { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 30, 15 } },
133     { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 15, 30 } },
134 
135     // over-sized radii
136     { { 0, 0 }, { 100, 400 }, { 0, 0 }, { 0, 0 } },
137     { { 0, 0 }, { 400, 400 }, { 0, 0 }, { 0, 0 } },
138     { { 400, 400 }, { 400, 400 }, { 400, 400 }, { 400, 400 } },
139 };
140 
141 ///////////////////////////////////////////////////////////////////////////////
142 
143 DEF_GM( return new RRectGM(false, false); )
144 DEF_GM( return new RRectGM(true, false); )
145 DEF_GM( return new RRectGM(false, true); )
146 DEF_GM( return new RRectGM(true, true); )
147 
148 }
149