• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "gm.h"
9 #include "sk_tool_utils.h"
10 #include "SkCanvas.h"
11 #include "SkPath.h"
12 
13 namespace skiagm {
14 
15 constexpr SkColor gPathColor = SK_ColorBLACK;
16 constexpr SkColor gClipAColor = SK_ColorBLUE;
17 constexpr SkColor gClipBColor = SK_ColorRED;
18 
19 class ComplexClipGM : public GM {
20 public:
ComplexClipGM(bool aaclip,bool saveLayer,bool invertDraw)21     ComplexClipGM(bool aaclip, bool saveLayer, bool invertDraw)
22     : fDoAAClip(aaclip)
23     , fDoSaveLayer(saveLayer)
24     , fInvertDraw(invertDraw) {
25         this->setBGColor(0xFFDEDFDE);
26     }
27 
28 protected:
29 
30 
onShortName()31     SkString onShortName() {
32         SkString str;
33         str.printf("complexclip_%s%s%s",
34                    fDoAAClip ? "aa" : "bw",
35                    fDoSaveLayer ? "_layer" : "",
36                    fInvertDraw ? "_invert" : "");
37         return str;
38     }
39 
onISize()40     SkISize onISize() { return SkISize::Make(970, 780); }
41 
onDraw(SkCanvas * canvas)42     virtual void onDraw(SkCanvas* canvas) {
43         SkPath path;
44         path.moveTo(SkIntToScalar(0),   SkIntToScalar(50));
45         path.quadTo(SkIntToScalar(0),   SkIntToScalar(0),   SkIntToScalar(50),  SkIntToScalar(0));
46         path.lineTo(SkIntToScalar(175), SkIntToScalar(0));
47         path.quadTo(SkIntToScalar(200), SkIntToScalar(0),   SkIntToScalar(200), SkIntToScalar(25));
48         path.lineTo(SkIntToScalar(200), SkIntToScalar(150));
49         path.quadTo(SkIntToScalar(200), SkIntToScalar(200), SkIntToScalar(150), SkIntToScalar(200));
50         path.lineTo(SkIntToScalar(0),   SkIntToScalar(200));
51         path.close();
52         path.moveTo(SkIntToScalar(50),  SkIntToScalar(50));
53         path.lineTo(SkIntToScalar(150), SkIntToScalar(50));
54         path.lineTo(SkIntToScalar(150), SkIntToScalar(125));
55         path.quadTo(SkIntToScalar(150), SkIntToScalar(150), SkIntToScalar(125), SkIntToScalar(150));
56         path.lineTo(SkIntToScalar(50),  SkIntToScalar(150));
57         path.close();
58         if (fInvertDraw) {
59             path.setFillType(SkPath::kInverseEvenOdd_FillType);
60         } else {
61             path.setFillType(SkPath::kEvenOdd_FillType);
62         }
63         SkPaint pathPaint;
64         pathPaint.setAntiAlias(true);
65         pathPaint.setColor(gPathColor);
66 
67         SkPath clipA;
68         clipA.moveTo(SkIntToScalar(10),  SkIntToScalar(20));
69         clipA.lineTo(SkIntToScalar(165), SkIntToScalar(22));
70         clipA.lineTo(SkIntToScalar(70),  SkIntToScalar(105));
71         clipA.lineTo(SkIntToScalar(165), SkIntToScalar(177));
72         clipA.lineTo(SkIntToScalar(-5),  SkIntToScalar(180));
73         clipA.close();
74 
75         SkPath clipB;
76         clipB.moveTo(SkIntToScalar(40),  SkIntToScalar(10));
77         clipB.lineTo(SkIntToScalar(190), SkIntToScalar(15));
78         clipB.lineTo(SkIntToScalar(195), SkIntToScalar(190));
79         clipB.lineTo(SkIntToScalar(40),  SkIntToScalar(185));
80         clipB.lineTo(SkIntToScalar(155), SkIntToScalar(100));
81         clipB.close();
82 
83         SkPaint paint;
84         paint.setAntiAlias(true);
85         sk_tool_utils::set_portable_typeface(&paint);
86         paint.setTextSize(SkIntToScalar(20));
87 
88         constexpr struct {
89             SkClipOp fOp;
90             const char*      fName;
91         } gOps[] = { //extra spaces in names for measureText
92             {kIntersect_SkClipOp,         "Isect "},
93             {kDifference_SkClipOp,        "Diff " },
94             {kUnion_SkClipOp,             "Union "},
95             {kXOR_SkClipOp,               "Xor "  },
96             {kReverseDifference_SkClipOp, "RDiff "}
97         };
98 
99         canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
100         canvas->scale(3 * SK_Scalar1 / 4, 3 * SK_Scalar1 / 4);
101 
102         if (fDoSaveLayer) {
103             // We want the layer to appear symmetric relative to actual
104             // device boundaries so we need to "undo" the effect of the
105             // scale and translate
106             SkRect bounds = SkRect::MakeLTRB(
107               4.0f/3.0f * -20,
108               4.0f/3.0f * -20,
109               4.0f/3.0f * (this->getISize().fWidth - 20),
110               4.0f/3.0f * (this->getISize().fHeight - 20));
111 
112             bounds.inset(SkIntToScalar(100), SkIntToScalar(100));
113             SkPaint boundPaint;
114             boundPaint.setColor(SK_ColorRED);
115             boundPaint.setStyle(SkPaint::kStroke_Style);
116             canvas->drawRect(bounds, boundPaint);
117             canvas->saveLayer(&bounds, nullptr);
118         }
119 
120         for (int invBits = 0; invBits < 4; ++invBits) {
121             canvas->save();
122             for (size_t op = 0; op < SK_ARRAY_COUNT(gOps); ++op) {
123                 this->drawHairlines(canvas, path, clipA, clipB);
124 
125                 bool doInvA = SkToBool(invBits & 1);
126                 bool doInvB = SkToBool(invBits & 2);
127                 canvas->save();
128                     // set clip
129                     clipA.setFillType(doInvA ? SkPath::kInverseEvenOdd_FillType :
130                                       SkPath::kEvenOdd_FillType);
131                     clipB.setFillType(doInvB ? SkPath::kInverseEvenOdd_FillType :
132                                       SkPath::kEvenOdd_FillType);
133                     canvas->clipPath(clipA, fDoAAClip);
134                     canvas->clipPath(clipB, gOps[op].fOp, fDoAAClip);
135 
136                     // In the inverse case we need to prevent the draw from covering the whole
137                     // canvas.
138                     if (fInvertDraw) {
139                         SkRect rectClip = clipA.getBounds();
140                         rectClip.join(path.getBounds());
141                         rectClip.join(path.getBounds());
142                         rectClip.outset(5, 5);
143                         canvas->clipRect(rectClip);
144                     }
145 
146                     // draw path clipped
147                     canvas->drawPath(path, pathPaint);
148                 canvas->restore();
149 
150 
151                 SkScalar txtX = SkIntToScalar(45);
152                 paint.setColor(gClipAColor);
153                 const char* aTxt = doInvA ? "InvA " : "A ";
154                 canvas->drawString(aTxt, txtX, SkIntToScalar(220), paint);
155                 txtX += paint.measureText(aTxt, strlen(aTxt));
156                 paint.setColor(SK_ColorBLACK);
157                 canvas->drawString(gOps[op].fName, txtX, SkIntToScalar(220), paint);
158                 txtX += paint.measureText(gOps[op].fName, strlen(gOps[op].fName));
159                 paint.setColor(gClipBColor);
160                 const char* bTxt = doInvB ? "InvB " : "B ";
161                 canvas->drawString(bTxt, txtX, SkIntToScalar(220), paint);
162 
163                 canvas->translate(SkIntToScalar(250),0);
164             }
165             canvas->restore();
166             canvas->translate(0, SkIntToScalar(250));
167         }
168 
169         if (fDoSaveLayer) {
170             canvas->restore();
171         }
172     }
173 private:
drawHairlines(SkCanvas * canvas,const SkPath & path,const SkPath & clipA,const SkPath & clipB)174     void drawHairlines(SkCanvas* canvas, const SkPath& path,
175                        const SkPath& clipA, const SkPath& clipB) {
176         SkPaint paint;
177         paint.setAntiAlias(true);
178         paint.setStyle(SkPaint::kStroke_Style);
179         const SkAlpha fade = 0x33;
180 
181         // draw path in hairline
182         paint.setColor(gPathColor); paint.setAlpha(fade);
183         canvas->drawPath(path, paint);
184 
185         // draw clips in hair line
186         paint.setColor(gClipAColor); paint.setAlpha(fade);
187         canvas->drawPath(clipA, paint);
188         paint.setColor(gClipBColor); paint.setAlpha(fade);
189         canvas->drawPath(clipB, paint);
190     }
191 
192     bool fDoAAClip;
193     bool fDoSaveLayer;
194     bool fInvertDraw;
195 
196     typedef GM INHERITED;
197 };
198 
199 //////////////////////////////////////////////////////////////////////////////
200 
201 DEF_GM(return new ComplexClipGM(false, false, false);)
202 DEF_GM(return new ComplexClipGM(false, false, true);)
203 DEF_GM(return new ComplexClipGM(false, true, false);)
204 DEF_GM(return new ComplexClipGM(false, true, true);)
205 DEF_GM(return new ComplexClipGM(true, false, false);)
206 DEF_GM(return new ComplexClipGM(true, false, true);)
207 DEF_GM(return new ComplexClipGM(true, true, false);)
208 DEF_GM(return new ComplexClipGM(true, true, true);)
209 }
210