1 /*
2  * Copyright 2014 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/SkFont.h"
13 #include "include/core/SkPaint.h"
14 #include "include/core/SkPathBuilder.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/SkTypeface.h"
20 #include "include/core/SkTypes.h"
21 #include "src/core/SkClipOpPriv.h"
22 #include "tools/ToolUtils.h"
23 
24 #include <utility>
25 
26 namespace skiagm {
27 
28 constexpr SkColor gPathColor = SK_ColorYELLOW;
29 
30 class ComplexClip3GM : public GM {
31 public:
ComplexClip3GM(bool doSimpleClipFirst)32     ComplexClip3GM(bool doSimpleClipFirst)
33         : fDoSimpleClipFirst(doSimpleClipFirst) {
34         this->setBGColor(0xFFDDDDDD);
35     }
36 
37 protected:
38 
onShortName()39     SkString onShortName() override {
40         SkString str;
41         str.printf("complexclip3_%s", fDoSimpleClipFirst ? "simple" : "complex");
42         return str;
43     }
44 
onISize()45     SkISize onISize() override { return SkISize::Make(400, 950); }
46 
onDraw(SkCanvas * canvas)47     void onDraw(SkCanvas* canvas) override {
48         SkPath clipSimple = SkPath::Circle(70, 50, 20);
49 
50         SkRect r1 = { 10, 20, 70, 80 };
51         SkPath clipComplex = SkPathBuilder().moveTo(40,  50)
52                                             .arcTo(r1, 30, 300, false)
53                                             .close()
54                                             .detach();
55 
56         SkPath* firstClip = &clipSimple;
57         SkPath* secondClip = &clipComplex;
58         if (!fDoSimpleClipFirst) {
59             std::swap(firstClip, secondClip);
60         }
61 
62         SkPaint paint;
63         paint.setAntiAlias(true);
64 
65         SkFont font(ToolUtils::create_portable_typeface(), 20);
66 
67         constexpr struct {
68             SkClipOp    fOp;
69             const char* fName;
70         } gOps[] = {
71             {kIntersect_SkClipOp,         "I"},
72             {kDifference_SkClipOp,        "D" },
73         };
74 
75         canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
76         canvas->scale(3 * SK_Scalar1 / 4, 3 * SK_Scalar1 / 4);
77 
78         SkPaint pathPaint;
79         pathPaint.setAntiAlias(true);
80         pathPaint.setColor(gPathColor);
81 
82         for (int invA = 0; invA < 2; ++invA) {
83             for (int aaBits = 0; aaBits < 4; ++aaBits) {
84                 canvas->save();
85                 for (size_t op = 0; op < SK_ARRAY_COUNT(gOps); ++op) {
86                     for (int invB = 0; invB < 2; ++invB) {
87                         bool doAAA = SkToBool(aaBits & 1);
88                         bool doAAB = SkToBool(aaBits & 2);
89                         bool doInvA = SkToBool(invA);
90                         bool doInvB = SkToBool(invB);
91                         canvas->save();
92                         // set clip
93                         firstClip->setFillType(doInvA ? SkPathFillType::kInverseEvenOdd :
94                                                SkPathFillType::kEvenOdd);
95                         secondClip->setFillType(doInvB ? SkPathFillType::kInverseEvenOdd :
96                                                 SkPathFillType::kEvenOdd);
97                         canvas->clipPath(*firstClip, doAAA);
98                         canvas->clipPath(*secondClip, gOps[op].fOp, doAAB);
99 
100                         // draw rect clipped
101                         SkRect r = { 0, 0, 100, 100 };
102                         canvas->drawRect(r, pathPaint);
103                         canvas->restore();
104 
105 
106                         SkScalar txtX = SkIntToScalar(10);
107                         paint.setColor(SK_ColorBLACK);
108                         SkString str;
109                         str.printf("%s%s %s %s%s", doAAA ? "A" : "B",
110                                                    doInvA ? "I" : "N",
111                                                    gOps[op].fName,
112                                                    doAAB ? "A" : "B",
113                                                    doInvB ? "I" : "N");
114 
115                         canvas->drawString(str.c_str(), txtX, SkIntToScalar(130), font, paint);
116                         if (doInvB) {
117                             canvas->translate(SkIntToScalar(150),0);
118                         } else {
119                             canvas->translate(SkIntToScalar(120),0);
120                         }
121                     }
122                 }
123                 canvas->restore();
124                 canvas->translate(0, SkIntToScalar(150));
125             }
126         }
127     }
128 
129 private:
130     bool fDoSimpleClipFirst;
131 
132     using INHERITED = GM;
133 };
134 
135 //////////////////////////////////////////////////////////////////////////////
136 
137 // Simple clip first
138 DEF_GM( return new ComplexClip3GM(true); )
139 // Complex clip first
140 DEF_GM( return new ComplexClip3GM(false); )
141 }  // namespace skiagm
142