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