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    ComplexClip2GM(bool doPaths, bool antiAlias)
19    : fDoPaths(doPaths)
20    , fAntiAlias(antiAlias) {
21        this->setBGColor(SkColorSetRGB(0xDD,0xA0,0xDD));
22
23        // offset the rects a bit so we get antialiasing even in the rect case
24        SkScalar xA = SkFloatToScalar(0.65f);
25        SkScalar xB = SkFloatToScalar(10.65f);
26        SkScalar xC = SkFloatToScalar(20.65f);
27        SkScalar xD = SkFloatToScalar(30.65f);
28        SkScalar xE = SkFloatToScalar(40.65f);
29        SkScalar xF = SkFloatToScalar(50.65f);
30
31        SkScalar yA = SkFloatToScalar(0.65f);
32        SkScalar yB = SkFloatToScalar(10.65f);
33        SkScalar yC = SkFloatToScalar(20.65f);
34        SkScalar yD = SkFloatToScalar(30.65f);
35        SkScalar yE = SkFloatToScalar(40.65f);
36        SkScalar yF = SkFloatToScalar(50.65f);
37
38        fWidth = xF - xA;
39        fHeight = yF - yA;
40
41        fRects[0].set(xB, yB, xE, yE);
42        fPaths[0].addRoundRect(fRects[0], SkIntToScalar(5), SkIntToScalar(5));
43        fRectColors[0] = SK_ColorRED;
44
45        fRects[1].set(xA, yA, xD, yD);
46        fPaths[1].addRoundRect(fRects[1], SkIntToScalar(5), SkIntToScalar(5));
47        fRectColors[1] = SK_ColorGREEN;
48
49        fRects[2].set(xC, yA, xF, yD);
50        fPaths[2].addRoundRect(fRects[2], SkIntToScalar(5), SkIntToScalar(5));
51        fRectColors[2] = SK_ColorBLUE;
52
53        fRects[3].set(xA, yC, xD, yF);
54        fPaths[3].addRoundRect(fRects[3], SkIntToScalar(5), SkIntToScalar(5));
55        fRectColors[3] = SK_ColorYELLOW;
56
57        fRects[4].set(xC, yC, xF, yF);
58        fPaths[4].addRoundRect(fRects[4], SkIntToScalar(5), SkIntToScalar(5));
59        fRectColors[4] = SK_ColorCYAN;
60
61        fTotalWidth = kCols * fWidth + SK_Scalar1 * (kCols + 1) * kPadX;
62        fTotalHeight = kRows * fHeight + SK_Scalar1 * (kRows + 1) * kPadY;
63
64        SkRegion::Op ops[] = {
65            SkRegion::kDifference_Op,
66            SkRegion::kIntersect_Op,
67            SkRegion::kUnion_Op,
68            SkRegion::kXOR_Op,
69            SkRegion::kReverseDifference_Op,
70            SkRegion::kReplace_Op,
71        };
72
73        SkRandom r;
74        for (int i = 0; i < kRows; ++i) {
75            for (int j = 0; j < kCols; ++j) {
76                for (int k = 0; k < 5; ++k) {
77                    fOps[j*kRows+i][k] = ops[r.nextU() % SK_ARRAY_COUNT(ops)];
78                }
79            }
80        }
81    }
82
83protected:
84
85    static const int kRows = 5;
86    static const int kCols = 5;
87    static const int kPadX = 20;
88    static const int kPadY = 20;
89
90    virtual SkString onShortName() {
91        if (!fDoPaths && !fAntiAlias) {
92            return SkString("complexclip2");
93        }
94
95        SkString str;
96        str.printf("complexclip2_%s_%s",
97                    fDoPaths ? "path" : "rect",
98                    fAntiAlias ? "aa" : "bw");
99        return str;
100    }
101
102    virtual SkISize onISize() {
103        return make_isize(SkScalarRoundToInt(fTotalWidth),
104                          SkScalarRoundToInt(fTotalHeight));
105    }
106
107    virtual void onDraw(SkCanvas* canvas) {
108        SkPaint rectPaint;
109        rectPaint.setStyle(SkPaint::kStroke_Style);
110        rectPaint.setStrokeWidth(-1);
111
112        SkPaint fillPaint;
113        fillPaint.setColor(SkColorSetRGB(0xA0,0xDD,0xA0));
114
115        for (int i = 0; i < kRows; ++i) {
116            for (int j = 0; j < kCols; ++j) {
117                canvas->save();
118
119                canvas->translate(kPadX * SK_Scalar1 + (fWidth + kPadX * SK_Scalar1)*j,
120                                  kPadY * SK_Scalar1 + (fHeight + kPadY * SK_Scalar1)*i);
121
122                // draw the original shapes first so we can see the
123                // antialiasing on the clipped draw
124                for (int k = 0; k < 5; ++k) {
125                    rectPaint.setColor(fRectColors[k]);
126                    if (fDoPaths) {
127                        canvas->drawPath(fPaths[k], rectPaint);
128                    } else {
129                        canvas->drawRect(fRects[k], rectPaint);
130                    }
131                }
132
133                for (int k = 0; k < 5; ++k) {
134                    if (fDoPaths) {
135                        canvas->clipPath(fPaths[k],
136                                         fOps[j*kRows+i][k],
137                                         fAntiAlias);
138                    } else {
139                        canvas->clipRect(fRects[k],
140                                         fOps[j*kRows+i][k],
141                                         fAntiAlias);
142                    }
143                }
144                canvas->drawRect(SkRect::MakeWH(fWidth, fHeight), fillPaint);
145                canvas->restore();
146            }
147        }
148    }
149private:
150    bool fDoPaths;
151    bool fAntiAlias;
152    SkRect fRects[5];
153    SkPath fPaths[5];
154    SkColor fRectColors[5];
155    SkRegion::Op fOps[kRows * kCols][5];
156    SkScalar fWidth;
157    SkScalar fHeight;
158    SkScalar fTotalWidth;
159    SkScalar fTotalHeight;
160
161    typedef GM INHERITED;
162};
163
164//////////////////////////////////////////////////////////////////////////////
165
166// bw rects
167static GM* MyFactory(void*) { return new ComplexClip2GM(false, false); }
168static GMRegistry reg(MyFactory);
169
170// bw paths
171static GM* MyFactory2(void*) { return new ComplexClip2GM(true, false); }
172static GMRegistry reg2(MyFactory2);
173
174// aa rects
175static GM* MyFactory3(void*) { return new ComplexClip2GM(false, true); }
176static GMRegistry reg3(MyFactory3);
177
178// aa paths
179static GM* MyFactory4(void*) { return new ComplexClip2GM(true, true); }
180static GMRegistry reg4(MyFactory4);
181
182}
183