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