1 /*
2  * Copyright 2011 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 
9 #include "gm.h"
10 #include "SkCanvas.h"
11 #include "SkPath.h"
12 #include "SkRandom.h"
13 
14 namespace skiagm {
15 
16 class ComplexClip2GM : public GM {
17 public:
18     enum Clip {
19         kRect_Clip,
20         kRRect_Clip,
21         kPath_Clip
22     };
23 
ComplexClip2GM(Clip clip,bool antiAlias)24     ComplexClip2GM(Clip clip, bool antiAlias)
25     : fClip(clip)
26     , fAntiAlias(antiAlias) {
27         SkScalar xA = 0.65f;
28         SkScalar xF = 50.65f;
29 
30         SkScalar yA = 0.65f;
31         SkScalar yF = 50.65f;
32 
33         fWidth = xF - xA;
34         fHeight = yF - yA;
35 
36         fTotalWidth = kCols * fWidth + SK_Scalar1 * (kCols + 1) * kPadX;
37         fTotalHeight = kRows * fHeight + SK_Scalar1 * (kRows + 1) * kPadY;
38     }
39 
40 protected:
onOnceBeforeDraw()41     void onOnceBeforeDraw() override {
42         this->setBGColor(SkColorSetRGB(0xDD,0xA0,0xDD));
43 
44         // offset the rects a bit so we get antialiasing even in the rect case
45         SkScalar xA = 0.65f;
46         SkScalar xB = 10.65f;
47         SkScalar xC = 20.65f;
48         SkScalar xD = 30.65f;
49         SkScalar xE = 40.65f;
50         SkScalar xF = 50.65f;
51 
52         SkScalar yA = 0.65f;
53         SkScalar yB = 10.65f;
54         SkScalar yC = 20.65f;
55         SkScalar yD = 30.65f;
56         SkScalar yE = 40.65f;
57         SkScalar yF = 50.65f;
58 
59         fRects[0].set(xB, yB, xE, yE);
60         fRRects[0].setRectXY(fRects[0], 7, 7);
61         fPaths[0].addRoundRect(fRects[0], 5, 5);
62         fRectColors[0] = SK_ColorRED;
63 
64         fRects[1].set(xA, yA, xD, yD);
65         fRRects[1].setRectXY(fRects[1], 7, 7);
66         fPaths[1].addRoundRect(fRects[1], 5, 5);
67         fRectColors[1] = SK_ColorGREEN;
68 
69         fRects[2].set(xC, yA, xF, yD);
70         fRRects[2].setRectXY(fRects[2], 7, 7);
71         fPaths[2].addRoundRect(fRects[2], 5, 5);
72         fRectColors[2] = SK_ColorBLUE;
73 
74         fRects[3].set(xA, yC, xD, yF);
75         fRRects[3].setRectXY(fRects[3], 7, 7);
76         fPaths[3].addRoundRect(fRects[3], 5, 5);
77         fRectColors[3] = SK_ColorYELLOW;
78 
79         fRects[4].set(xC, yC, xF, yF);
80         fRRects[4].setRectXY(fRects[4], 7, 7);
81         fPaths[4].addRoundRect(fRects[4], 5, 5);
82         fRectColors[4] = SK_ColorCYAN;
83 
84         SkRegion::Op ops[] = {
85             SkRegion::kDifference_Op,
86             SkRegion::kIntersect_Op,
87             SkRegion::kUnion_Op,
88             SkRegion::kXOR_Op,
89             SkRegion::kReverseDifference_Op,
90             SkRegion::kReplace_Op,
91         };
92 
93         SkRandom r;
94         for (int i = 0; i < kRows; ++i) {
95             for (int j = 0; j < kCols; ++j) {
96                 for (int k = 0; k < 5; ++k) {
97                     fOps[j*kRows+i][k] = ops[r.nextU() % SK_ARRAY_COUNT(ops)];
98                 }
99             }
100         }
101     }
102 
103     static const int kRows = 5;
104     static const int kCols = 5;
105     static const int kPadX = 20;
106     static const int kPadY = 20;
107 
ClipStr(Clip clip)108     static const char* ClipStr(Clip clip) {
109         switch (clip) {
110         case kRect_Clip:
111             return "rect";
112         case kRRect_Clip:
113             return "rrect";
114         case kPath_Clip:
115             return "path";
116         }
117         SkDEBUGFAIL("Unknown clip type.");
118         return "";
119     }
120 
onShortName()121     virtual SkString onShortName() {
122         if (kRect_Clip == fClip && !fAntiAlias) {
123             return SkString("complexclip2");
124         }
125 
126         SkString str;
127         str.printf("complexclip2_%s_%s",
128                     ClipStr(fClip),
129                     fAntiAlias ? "aa" : "bw");
130         return str;
131     }
132 
onISize()133     virtual SkISize onISize() {
134         return SkISize::Make(SkScalarRoundToInt(fTotalWidth),
135                              SkScalarRoundToInt(fTotalHeight));
136     }
137 
onDraw(SkCanvas * canvas)138     virtual void onDraw(SkCanvas* canvas) {
139         SkPaint rectPaint;
140         rectPaint.setStyle(SkPaint::kStroke_Style);
141         rectPaint.setStrokeWidth(-1);
142 
143         SkPaint fillPaint;
144         fillPaint.setColor(SkColorSetRGB(0xA0,0xDD,0xA0));
145 
146         for (int i = 0; i < kRows; ++i) {
147             for (int j = 0; j < kCols; ++j) {
148                 canvas->save();
149 
150                 canvas->translate(kPadX * SK_Scalar1 + (fWidth + kPadX * SK_Scalar1)*j,
151                                   kPadY * SK_Scalar1 + (fHeight + kPadY * SK_Scalar1)*i);
152 
153                 // draw the original shapes first so we can see the
154                 // antialiasing on the clipped draw
155                 for (int k = 0; k < 5; ++k) {
156                     rectPaint.setColor(fRectColors[k]);
157                     switch (fClip) {
158                         case kRect_Clip:
159                             canvas->drawRect(fRects[k], rectPaint);
160                             break;
161                         case kRRect_Clip:
162                             canvas->drawRRect(fRRects[k], rectPaint);
163                             break;
164                         case kPath_Clip:
165                             canvas->drawPath(fPaths[k], rectPaint);
166                             break;
167                     }
168                 }
169 
170                 for (int k = 0; k < 5; ++k) {
171                     switch (fClip) {
172                         case kRect_Clip:
173                             canvas->clipRect(fRects[k],
174                                              fOps[j*kRows+i][k],
175                                              fAntiAlias);
176                             break;
177                         case kRRect_Clip:
178                             canvas->clipRRect(fRRects[k],
179                                               fOps[j*kRows+i][k],
180                                               fAntiAlias);
181                             break;
182                         case kPath_Clip:
183                             canvas->clipPath(fPaths[k],
184                                              fOps[j*kRows+i][k],
185                                              fAntiAlias);
186                             break;
187                     }
188                 }
189                 canvas->drawRect(SkRect::MakeWH(fWidth, fHeight), fillPaint);
190                 canvas->restore();
191             }
192         }
193     }
194 private:
195     Clip fClip;
196     bool fAntiAlias;
197     SkRect fRects[5];
198     SkRRect fRRects[5];
199     SkPath fPaths[5];
200     SkColor fRectColors[5];
201     SkRegion::Op fOps[kRows * kCols][5];
202     SkScalar fWidth;
203     SkScalar fHeight;
204     SkScalar fTotalWidth;
205     SkScalar fTotalHeight;
206 
207     typedef GM INHERITED;
208 };
209 
210 //////////////////////////////////////////////////////////////////////////////
211 
212 // bw
213 DEF_GM( return new ComplexClip2GM(ComplexClip2GM::kRect_Clip, false); )
214 DEF_GM( return new ComplexClip2GM(ComplexClip2GM::kRRect_Clip, false); )
215 DEF_GM( return new ComplexClip2GM(ComplexClip2GM::kPath_Clip, false); )
216 
217 // aa
218 DEF_GM( return new ComplexClip2GM(ComplexClip2GM::kRect_Clip, true); )
219 DEF_GM( return new ComplexClip2GM(ComplexClip2GM::kRRect_Clip, true); )
220 DEF_GM( return new ComplexClip2GM(ComplexClip2GM::kPath_Clip, true); )
221 
222 }
223