• 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     bool fDoAAClip;
22     bool fDoSaveLayer;
23 public:
ComplexClipGM(bool aaclip,bool saveLayer)24     ComplexClipGM(bool aaclip, bool saveLayer)
25     : fDoAAClip(aaclip)
26     , fDoSaveLayer(saveLayer) {
27         this->setBGColor(0xFFDDDDDD);
28 //        this->setBGColor(SkColorSetRGB(0xB0,0xDD,0xB0));
29     }
30 
31 protected:
32 
onShortName()33     SkString onShortName() {
34         SkString str;
35         str.printf("complexclip_%s%s",
36                    fDoAAClip ? "aa" : "bw",
37                    fDoSaveLayer ? "_layer" : "");
38         return str;
39     }
40 
onISize()41     SkISize onISize() { return make_isize(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         path.setFillType(SkPath::kEvenOdd_FillType);
60         SkPaint pathPaint;
61         pathPaint.setAntiAlias(true);
62         pathPaint.setColor(gPathColor);
63 
64         SkPath clipA;
65         clipA.moveTo(SkIntToScalar(10),  SkIntToScalar(20));
66         clipA.lineTo(SkIntToScalar(165), SkIntToScalar(22));
67         clipA.lineTo(SkIntToScalar(70),  SkIntToScalar(105));
68         clipA.lineTo(SkIntToScalar(165), SkIntToScalar(177));
69         clipA.lineTo(SkIntToScalar(-5),  SkIntToScalar(180));
70         clipA.close();
71 
72         SkPath clipB;
73         clipB.moveTo(SkIntToScalar(40),  SkIntToScalar(10));
74         clipB.lineTo(SkIntToScalar(190), SkIntToScalar(15));
75         clipB.lineTo(SkIntToScalar(195), SkIntToScalar(190));
76         clipB.lineTo(SkIntToScalar(40),  SkIntToScalar(185));
77         clipB.lineTo(SkIntToScalar(155), SkIntToScalar(100));
78         clipB.close();
79 
80         SkPaint paint;
81         paint.setAntiAlias(true);
82         paint.setTextSize(SkIntToScalar(20));
83 
84         static const struct {
85             SkRegion::Op fOp;
86             const char*  fName;
87         } gOps[] = { //extra spaces in names for measureText
88             {SkRegion::kIntersect_Op,         "Isect "},
89             {SkRegion::kDifference_Op,        "Diff " },
90             {SkRegion::kUnion_Op,             "Union "},
91             {SkRegion::kXOR_Op,               "Xor "  },
92             {SkRegion::kReverseDifference_Op, "RDiff "}
93         };
94 
95         canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
96         canvas->scale(3 * SK_Scalar1 / 4, 3 * SK_Scalar1 / 4);
97 
98         if (fDoSaveLayer) {
99             // We want the layer to appear symmetric relative to actual
100             // device boundaries so we need to "undo" the effect of the
101             // scale and translate
102             SkRect bounds = SkRect::MakeLTRB(
103               4.0f/3.0f * -20,
104               4.0f/3.0f * -20,
105               4.0f/3.0f * (this->getISize().fWidth - 20),
106               4.0f/3.0f * (this->getISize().fHeight - 20));
107 
108             bounds.inset(SkIntToScalar(100), SkIntToScalar(100));
109             SkPaint boundPaint;
110             boundPaint.setColor(SK_ColorRED);
111             boundPaint.setStyle(SkPaint::kStroke_Style);
112             canvas->drawRect(bounds, boundPaint);
113             canvas->saveLayer(&bounds, NULL);
114         }
115 
116         for (int invBits = 0; invBits < 4; ++invBits) {
117             canvas->save();
118             for (size_t op = 0; op < SK_ARRAY_COUNT(gOps); ++op) {
119                 this->drawHairlines(canvas, path, clipA, clipB);
120 
121                 bool doInvA = SkToBool(invBits & 1);
122                 bool doInvB = SkToBool(invBits & 2);
123                 canvas->save();
124                     // set clip
125                     clipA.setFillType(doInvA ? SkPath::kInverseEvenOdd_FillType :
126                                       SkPath::kEvenOdd_FillType);
127                     clipB.setFillType(doInvB ? SkPath::kInverseEvenOdd_FillType :
128                                       SkPath::kEvenOdd_FillType);
129                     canvas->clipPath(clipA, SkRegion::kIntersect_Op, fDoAAClip);
130                     canvas->clipPath(clipB, gOps[op].fOp, fDoAAClip);
131 
132                     // draw path clipped
133                     canvas->drawPath(path, pathPaint);
134                 canvas->restore();
135 
136 
137                 SkScalar txtX = SkIntToScalar(45);
138                 paint.setColor(gClipAColor);
139                 const char* aTxt = doInvA ? "InvA " : "A ";
140                 canvas->drawText(aTxt, strlen(aTxt), txtX, SkIntToScalar(220), paint);
141                 txtX += paint.measureText(aTxt, strlen(aTxt));
142                 paint.setColor(SK_ColorBLACK);
143                 canvas->drawText(gOps[op].fName, strlen(gOps[op].fName),
144                                     txtX, SkIntToScalar(220), paint);
145                 txtX += paint.measureText(gOps[op].fName, strlen(gOps[op].fName));
146                 paint.setColor(gClipBColor);
147                 const char* bTxt = doInvB ? "InvB " : "B ";
148                 canvas->drawText(bTxt, strlen(bTxt), txtX, SkIntToScalar(220), paint);
149 
150                 canvas->translate(SkIntToScalar(250),0);
151             }
152             canvas->restore();
153             canvas->translate(0, SkIntToScalar(250));
154         }
155 
156         if (fDoSaveLayer) {
157             canvas->restore();
158         }
159     }
160 private:
drawHairlines(SkCanvas * canvas,const SkPath & path,const SkPath & clipA,const SkPath & clipB)161     void drawHairlines(SkCanvas* canvas, const SkPath& path,
162                        const SkPath& clipA, const SkPath& clipB) {
163         SkPaint paint;
164         paint.setAntiAlias(true);
165         paint.setStyle(SkPaint::kStroke_Style);
166         const SkAlpha fade = 0x33;
167 
168         // draw path in hairline
169         paint.setColor(gPathColor); paint.setAlpha(fade);
170         canvas->drawPath(path, paint);
171 
172         // draw clips in hair line
173         paint.setColor(gClipAColor); paint.setAlpha(fade);
174         canvas->drawPath(clipA, paint);
175         paint.setColor(gClipBColor); paint.setAlpha(fade);
176         canvas->drawPath(clipB, paint);
177     }
178 
179     typedef GM INHERITED;
180 };
181 
182 //////////////////////////////////////////////////////////////////////////////
183 
184 // aliased and anti-aliased w/o a layer
gFact0(void *)185 static GM* gFact0(void*) { return new ComplexClipGM(false, false); }
gFact1(void *)186 static GM* gFact1(void*) { return new ComplexClipGM(true, false); }
187 
188 // aliased and anti-aliased w/ a layer
gFact2(void *)189 static GM* gFact2(void*) { return new ComplexClipGM(false, true); }
gFact3(void *)190 static GM* gFact3(void*) { return new ComplexClipGM(true, true); }
191 
192 static GMRegistry gReg0(gFact0);
193 static GMRegistry gReg1(gFact1);
194 static GMRegistry gReg2(gFact2);
195 static GMRegistry gReg3(gFact3);
196 
197 }
198