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