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].addRoundRect(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].addRoundRect(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].addRoundRect(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].addRoundRect(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].addRoundRect(fRects[4], 5, 5);
91         fRectColors[4] = SK_ColorCYAN;
92 
93         const SkClipOp ops[] = {
94             kDifference_SkClipOp,
95             kIntersect_SkClipOp,
96             kUnion_SkClipOp,
97             kXOR_SkClipOp,
98             kReverseDifference_SkClipOp,
99             kReplace_SkClipOp,
100         };
101 
102         SkRandom r;
103         for (int i = 0; i < kRows; ++i) {
104             for (int j = 0; j < kCols; ++j) {
105                 for (int k = 0; k < 5; ++k) {
106                     fOps[j*kRows+i][k] = ops[r.nextU() % SK_ARRAY_COUNT(ops)];
107                 }
108             }
109         }
110     }
111 
112     static constexpr int kRows = 5;
113     static constexpr int kCols = 5;
114     static constexpr int kPadX = 20;
115     static constexpr int kPadY = 20;
116 
ClipStr(Clip clip)117     static const char* ClipStr(Clip clip) {
118         switch (clip) {
119         case kRect_Clip:
120             return "rect";
121         case kRRect_Clip:
122             return "rrect";
123         case kPath_Clip:
124             return "path";
125         }
126         SkDEBUGFAIL("Unknown clip type.");
127         return "";
128     }
129 
onShortName()130     SkString onShortName() override {
131         if (kRect_Clip == fClip && !fAntiAlias) {
132             return SkString("complexclip2");
133         }
134 
135         SkString str;
136         str.printf("complexclip2_%s_%s",
137                     ClipStr(fClip),
138                     fAntiAlias ? "aa" : "bw");
139         return str;
140     }
141 
onISize()142     SkISize onISize() override {
143         return SkISize::Make(SkScalarRoundToInt(fTotalWidth),
144                              SkScalarRoundToInt(fTotalHeight));
145     }
146 
onDraw(SkCanvas * canvas)147     void onDraw(SkCanvas* canvas) override {
148         SkPaint rectPaint;
149         rectPaint.setStyle(SkPaint::kStroke_Style);
150         rectPaint.setStrokeWidth(-1);
151 
152         SkPaint fillPaint;
153         fillPaint.setColor(SkColorSetRGB(0xA0,0xDD,0xA0));
154 
155         for (int i = 0; i < kRows; ++i) {
156             for (int j = 0; j < kCols; ++j) {
157                 canvas->save();
158 
159                 canvas->translate(kPadX * SK_Scalar1 + (fWidth + kPadX * SK_Scalar1)*j,
160                                   kPadY * SK_Scalar1 + (fHeight + kPadY * SK_Scalar1)*i);
161 
162                 // draw the original shapes first so we can see the
163                 // antialiasing on the clipped draw
164                 for (int k = 0; k < 5; ++k) {
165                     rectPaint.setColor(fRectColors[k]);
166                     switch (fClip) {
167                         case kRect_Clip:
168                             canvas->drawRect(fRects[k], rectPaint);
169                             break;
170                         case kRRect_Clip:
171                             canvas->drawRRect(fRRects[k], rectPaint);
172                             break;
173                         case kPath_Clip:
174                             canvas->drawPath(fPaths[k], rectPaint);
175                             break;
176                     }
177                 }
178 
179                 for (int k = 0; k < 5; ++k) {
180                     switch (fClip) {
181                         case kRect_Clip:
182                             canvas->clipRect(fRects[k],
183                                              fOps[j*kRows+i][k],
184                                              fAntiAlias);
185                             break;
186                         case kRRect_Clip:
187                             canvas->clipRRect(fRRects[k],
188                                               fOps[j*kRows+i][k],
189                                               fAntiAlias);
190                             break;
191                         case kPath_Clip:
192                             canvas->clipPath(fPaths[k],
193                                              fOps[j*kRows+i][k],
194                                              fAntiAlias);
195                             break;
196                     }
197                 }
198                 canvas->drawRect(SkRect::MakeWH(fWidth, fHeight), fillPaint);
199                 canvas->restore();
200             }
201         }
202     }
203 private:
204     Clip fClip;
205     bool fAntiAlias;
206     SkRect fRects[5];
207     SkRRect fRRects[5];
208     SkPath fPaths[5];
209     SkColor fRectColors[5];
210     SkClipOp fOps[kRows * kCols][5];
211     SkScalar fWidth;
212     SkScalar fHeight;
213     SkScalar fTotalWidth;
214     SkScalar fTotalHeight;
215 
216     typedef GM INHERITED;
217 };
218 
219 //////////////////////////////////////////////////////////////////////////////
220 
221 // bw
222 DEF_GM( return new ComplexClip2GM(ComplexClip2GM::kRect_Clip, false); )
223 DEF_GM( return new ComplexClip2GM(ComplexClip2GM::kRRect_Clip, false); )
224 DEF_GM( return new ComplexClip2GM(ComplexClip2GM::kPath_Clip, false); )
225 
226 // aa
227 DEF_GM( return new ComplexClip2GM(ComplexClip2GM::kRect_Clip, true); )
228 DEF_GM( return new ComplexClip2GM(ComplexClip2GM::kRRect_Clip, true); )
229 DEF_GM( return new ComplexClip2GM(ComplexClip2GM::kPath_Clip, true); )
230 
231 }
232