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
14namespace skiagm {
15
16class ComplexClip2GM : public GM {
17public:
18    enum Clip {
19        kRect_Clip,
20        kRRect_Clip,
21        kPath_Clip
22    };
23
24    ComplexClip2GM(Clip clip, bool antiAlias)
25    : fClip(clip)
26    , fAntiAlias(antiAlias) {
27        this->setBGColor(SkColorSetRGB(0xDD,0xA0,0xDD));
28
29        // offset the rects a bit so we get antialiasing even in the rect case
30        SkScalar xA = 0.65f;
31        SkScalar xB = 10.65f;
32        SkScalar xC = 20.65f;
33        SkScalar xD = 30.65f;
34        SkScalar xE = 40.65f;
35        SkScalar xF = 50.65f;
36
37        SkScalar yA = 0.65f;
38        SkScalar yB = 10.65f;
39        SkScalar yC = 20.65f;
40        SkScalar yD = 30.65f;
41        SkScalar yE = 40.65f;
42        SkScalar yF = 50.65f;
43
44        fWidth = xF - xA;
45        fHeight = yF - yA;
46
47        fRects[0].set(xB, yB, xE, yE);
48        fRRects[0].setRectXY(fRects[0], 7, 7);
49        fPaths[0].addRoundRect(fRects[0], 5, 5);
50        fRectColors[0] = SK_ColorRED;
51
52        fRects[1].set(xA, yA, xD, yD);
53        fRRects[1].setRectXY(fRects[1], 7, 7);
54        fPaths[1].addRoundRect(fRects[1], 5, 5);
55        fRectColors[1] = SK_ColorGREEN;
56
57        fRects[2].set(xC, yA, xF, yD);
58        fRRects[2].setRectXY(fRects[2], 7, 7);
59        fPaths[2].addRoundRect(fRects[2], 5, 5);
60        fRectColors[2] = SK_ColorBLUE;
61
62        fRects[3].set(xA, yC, xD, yF);
63        fRRects[3].setRectXY(fRects[3], 7, 7);
64        fPaths[3].addRoundRect(fRects[3], 5, 5);
65        fRectColors[3] = SK_ColorYELLOW;
66
67        fRects[4].set(xC, yC, xF, yF);
68        fRRects[4].setRectXY(fRects[4], 7, 7);
69        fPaths[4].addRoundRect(fRects[4], 5, 5);
70        fRectColors[4] = SK_ColorCYAN;
71
72        fTotalWidth = kCols * fWidth + SK_Scalar1 * (kCols + 1) * kPadX;
73        fTotalHeight = kRows * fHeight + SK_Scalar1 * (kRows + 1) * kPadY;
74
75        SkRegion::Op ops[] = {
76            SkRegion::kDifference_Op,
77            SkRegion::kIntersect_Op,
78            SkRegion::kUnion_Op,
79            SkRegion::kXOR_Op,
80            SkRegion::kReverseDifference_Op,
81            SkRegion::kReplace_Op,
82        };
83
84        SkLCGRandom r;
85        for (int i = 0; i < kRows; ++i) {
86            for (int j = 0; j < kCols; ++j) {
87                for (int k = 0; k < 5; ++k) {
88                    fOps[j*kRows+i][k] = ops[r.nextU() % SK_ARRAY_COUNT(ops)];
89                }
90            }
91        }
92    }
93
94protected:
95
96    static const int kRows = 5;
97    static const int kCols = 5;
98    static const int kPadX = 20;
99    static const int kPadY = 20;
100
101    static const char* ClipStr(Clip clip) {
102        switch (clip) {
103        case kRect_Clip:
104            return "rect";
105        case kRRect_Clip:
106            return "rrect";
107        case kPath_Clip:
108            return "path";
109        }
110        SkDEBUGFAIL("Unknown clip type.");
111        return "";
112    }
113
114    virtual uint32_t onGetFlags() const SK_OVERRIDE {
115        if (kRect_Clip != fClip) {
116            return kSkipTiled_Flag;
117        }
118        return 0;
119    }
120
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
133    virtual SkISize onISize() {
134        return SkISize::Make(SkScalarRoundToInt(fTotalWidth),
135                             SkScalarRoundToInt(fTotalHeight));
136    }
137
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    }
194private:
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
213DEF_GM( return new ComplexClip2GM(ComplexClip2GM::kRect_Clip, false); )
214DEF_GM( return new ComplexClip2GM(ComplexClip2GM::kRRect_Clip, false); )
215DEF_GM( return new ComplexClip2GM(ComplexClip2GM::kPath_Clip, false); )
216
217// aa
218DEF_GM( return new ComplexClip2GM(ComplexClip2GM::kRect_Clip, true); )
219DEF_GM( return new ComplexClip2GM(ComplexClip2GM::kRRect_Clip, true); )
220DEF_GM( return new ComplexClip2GM(ComplexClip2GM::kPath_Clip, true); )
221
222}
223