1
2/*
3 * Copyright 2014 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8#include "gm.h"
9#include "SkCanvas.h"
10#include "SkPath.h"
11
12namespace skiagm {
13
14static const SkColor gPathColor = SK_ColorYELLOW;
15
16class ComplexClip3GM : public GM {
17public:
18    ComplexClip3GM(bool doSimpleClipFirst)
19        : fDoSimpleClipFirst(doSimpleClipFirst) {
20        this->setBGColor(0xFFDDDDDD);
21    }
22
23protected:
24
25    SkString onShortName() {
26        SkString str;
27        str.printf("complexclip3_%s", fDoSimpleClipFirst ? "simple" : "complex");
28        return str;
29    }
30
31    SkISize onISize() { return SkISize::Make(1000, 950); }
32
33    virtual void onDraw(SkCanvas* canvas) {
34        SkPath clipSimple;
35        clipSimple.addCircle(SkIntToScalar(70), SkIntToScalar(50), SkIntToScalar(20));
36
37        SkRect r1 = { 10, 20, 70, 80 };
38        SkPath clipComplex;
39        clipComplex.moveTo(SkIntToScalar(40),  SkIntToScalar(50));
40        clipComplex.arcTo(r1, SkIntToScalar(30), SkIntToScalar(300), false);
41        clipComplex.close();
42
43        SkPath* firstClip = &clipSimple;
44        SkPath* secondClip = &clipComplex;
45
46        if (!fDoSimpleClipFirst) {
47            SkTSwap<SkPath*>(firstClip, secondClip);
48        }
49
50        SkPaint paint;
51        paint.setAntiAlias(true);
52        sk_tool_utils::set_portable_typeface(&paint);
53        paint.setTextSize(SkIntToScalar(20));
54
55        static const struct {
56            SkRegion::Op fOp;
57            const char*  fName;
58        } gOps[] = {
59            {SkRegion::kIntersect_Op,         "I"},
60            {SkRegion::kDifference_Op,        "D" },
61            {SkRegion::kUnion_Op,             "U"},
62            {SkRegion::kXOR_Op,               "X"  },
63            {SkRegion::kReverseDifference_Op, "R"}
64        };
65
66        canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
67        canvas->scale(3 * SK_Scalar1 / 4, 3 * SK_Scalar1 / 4);
68
69        SkPaint pathPaint;
70        pathPaint.setAntiAlias(true);
71        pathPaint.setColor(gPathColor);
72
73        for (int invA = 0; invA < 2; ++invA) {
74            for (int aaBits = 0; aaBits < 4; ++aaBits) {
75                canvas->save();
76                for (size_t op = 0; op < SK_ARRAY_COUNT(gOps); ++op) {
77                    for (int invB = 0; invB < 2; ++invB) {
78                        bool doAAA = SkToBool(aaBits & 1);
79                        bool doAAB = SkToBool(aaBits & 2);
80                        bool doInvA = SkToBool(invA);
81                        bool doInvB = SkToBool(invB);
82                        canvas->save();
83                        // set clip
84                        firstClip->setFillType(doInvA ? SkPath::kInverseEvenOdd_FillType :
85                                               SkPath::kEvenOdd_FillType);
86                        secondClip->setFillType(doInvB ? SkPath::kInverseEvenOdd_FillType :
87                                                SkPath::kEvenOdd_FillType);
88                        canvas->clipPath(*firstClip, SkRegion::kIntersect_Op, doAAA);
89                        canvas->clipPath(*secondClip, gOps[op].fOp, doAAB);
90
91                        // draw rect clipped
92                        SkRect r = { 0, 0, 100, 100 };
93                        canvas->drawRect(r, pathPaint);
94                        canvas->restore();
95
96
97                        SkScalar txtX = SkIntToScalar(10);
98                        paint.setColor(SK_ColorBLACK);
99                        SkString str;
100                        str.printf("%s%s %s %s%s", doAAA ? "A" : "B",
101                                                   doInvA ? "I" : "N",
102                                                   gOps[op].fName,
103                                                   doAAB ? "A" : "B",
104                                                   doInvB ? "I" : "N");
105
106                        canvas->drawText(str.c_str(), strlen(str.c_str()), txtX, SkIntToScalar(130),
107                                         paint);
108                        if (doInvB) {
109                            canvas->translate(SkIntToScalar(150),0);
110                        } else {
111                            canvas->translate(SkIntToScalar(120),0);
112                        }
113                    }
114                }
115                canvas->restore();
116                canvas->translate(0, SkIntToScalar(150));
117            }
118        }
119    }
120
121private:
122    bool fDoSimpleClipFirst;
123
124    typedef GM INHERITED;
125};
126
127//////////////////////////////////////////////////////////////////////////////
128
129// Simple clip first
130DEF_GM( return new ComplexClip3GM(true); )
131// Complex clip first
132DEF_GM( return new ComplexClip3GM(false); )
133}
134