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 "SampleCode.h"
9 #include "SkCanvas.h"
10 #include "SkPath.h"
11 #include "SkView.h"
12 #include "SkClipOpPriv.h"
13 
14 class ComplexClipView : public SampleView {
15 public:
16     ComplexClipView() {
17         this->setBGColor(0xFFA0DDA0);
18     }
19 
20 protected:
21     // overrides from SkEventSink
22     virtual bool onQuery(SkEvent* evt) {
23         if (SampleCode::TitleQ(*evt)) {
24             SampleCode::TitleR(evt, "ComplexClip");
25             return true;
26         }
27         return this->INHERITED::onQuery(evt);
28     }
29 
30     virtual void onDrawContent(SkCanvas* canvas) {
31         SkPath path;
32         path.moveTo(SkIntToScalar(0),   SkIntToScalar(50));
33         path.quadTo(SkIntToScalar(0),   SkIntToScalar(0),   SkIntToScalar(50),  SkIntToScalar(0));
34         path.lineTo(SkIntToScalar(175), SkIntToScalar(0));
35         path.quadTo(SkIntToScalar(200), SkIntToScalar(0),   SkIntToScalar(200), SkIntToScalar(25));
36         path.lineTo(SkIntToScalar(200), SkIntToScalar(150));
37         path.quadTo(SkIntToScalar(200), SkIntToScalar(200), SkIntToScalar(150), SkIntToScalar(200));
38         path.lineTo(SkIntToScalar(0),   SkIntToScalar(200));
39         path.close();
40         path.moveTo(SkIntToScalar(50),  SkIntToScalar(50));
41         path.lineTo(SkIntToScalar(150), SkIntToScalar(50));
42         path.lineTo(SkIntToScalar(150), SkIntToScalar(125));
43         path.quadTo(SkIntToScalar(150), SkIntToScalar(150), SkIntToScalar(125), SkIntToScalar(150));
44         path.lineTo(SkIntToScalar(50),  SkIntToScalar(150));
45         path.close();
46         path.setFillType(SkPath::kEvenOdd_FillType);
47         SkColor pathColor = SK_ColorBLACK;
48         SkPaint pathPaint;
49         pathPaint.setAntiAlias(true);
50         pathPaint.setColor(pathColor);
51 
52         SkPath clipA;
53         clipA.moveTo(SkIntToScalar(10),  SkIntToScalar(20));
54         clipA.lineTo(SkIntToScalar(165), SkIntToScalar(22));
55         clipA.lineTo(SkIntToScalar(70),  SkIntToScalar(105));
56         clipA.lineTo(SkIntToScalar(165), SkIntToScalar(177));
57         clipA.lineTo(SkIntToScalar(-5),  SkIntToScalar(180));
58         clipA.close();
59         SkColor colorA = SK_ColorCYAN;
60 
61         SkPath clipB;
62         clipB.moveTo(SkIntToScalar(40),  SkIntToScalar(10));
63         clipB.lineTo(SkIntToScalar(190), SkIntToScalar(15));
64         clipB.lineTo(SkIntToScalar(195), SkIntToScalar(190));
65         clipB.lineTo(SkIntToScalar(40),  SkIntToScalar(185));
66         clipB.lineTo(SkIntToScalar(155), SkIntToScalar(100));
67         clipB.close();
68         SkColor colorB = SK_ColorRED;
69 
70         SkPaint paint;
71         paint.setAntiAlias(true);
72 
73         paint.setStyle(SkPaint::kStroke_Style);
74         paint.setStrokeWidth(0);
75 
76         canvas->translate(SkIntToScalar(10),SkIntToScalar(10));
77         canvas->drawPath(path, pathPaint);
78         paint.setColor(colorA);
79         canvas->drawPath(clipA, paint);
80         paint.setColor(colorB);
81         canvas->drawPath(clipB, paint);
82 
83         static const struct {
84             SkClipOp    fOp;
85             const char* fName;
86         } gOps[] = { //extra spaces in names for measureText
87             {kIntersect_SkClipOp,         "Isect "},
88             {kDifference_SkClipOp,        "Diff " },
89             {kUnion_SkClipOp,             "Union "},
90             {kXOR_SkClipOp,               "Xor "  },
91             {kReverseDifference_SkClipOp, "RDiff "}
92         };
93 
94         canvas->translate(0, SkIntToScalar(40));
95         canvas->scale(3 * SK_Scalar1 / 4, 3 * SK_Scalar1 / 4);
96         canvas->save();
97 
98         for (int invA = 0; invA < 2; ++invA) {
99             for (size_t op = 0; op < SK_ARRAY_COUNT(gOps); ++op) {
100                 size_t idx = invA * SK_ARRAY_COUNT(gOps) + op;
101                 if (!(idx % 3)) {
102                     canvas->restore();
103                     canvas->translate(0, SkIntToScalar(250));
104                     canvas->save();
105                 }
106                 canvas->save();
107                     // set clip
108                     clipA.setFillType(invA ? SkPath::kInverseEvenOdd_FillType :
109                                              SkPath::kEvenOdd_FillType);
110                     canvas->clipPath(clipA);
111                     canvas->clipPath(clipB, gOps[op].fOp);
112 
113                     // draw path clipped
114                     canvas->drawPath(path, pathPaint);
115                 canvas->restore();
116 
117                 // draw path in hairline
118                 paint.setColor(pathColor);
119                 canvas->drawPath(path, paint);
120 
121                 // draw clips in hair line
122                 paint.setColor(colorA);
123                 canvas->drawPath(clipA, paint);
124                 paint.setColor(colorB);
125                 canvas->drawPath(clipB, paint);
126 
127                 paint.setTextSize(SkIntToScalar(20));
128 
129                 SkScalar txtX = SkIntToScalar(55);
130                 paint.setColor(colorA);
131                 const char* aTxt = invA ? "InverseA " : "A ";
132                 canvas->drawString(aTxt, txtX, SkIntToScalar(220), paint);
133                 txtX += paint.measureText(aTxt, strlen(aTxt));
134                 paint.setColor(SK_ColorBLACK);
135                 canvas->drawString(gOps[op].fName,
136                                     txtX, SkIntToScalar(220), paint);
137                 txtX += paint.measureText(gOps[op].fName, strlen(gOps[op].fName));
138                 paint.setColor(colorB);
139                 canvas->drawString("B", txtX, SkIntToScalar(220), paint);
140 
141                 canvas->translate(SkIntToScalar(250),0);
142             }
143         }
144         canvas->restore();
145     }
146 
147 private:
148     typedef SampleView INHERITED;
149 };
150 
151 //////////////////////////////////////////////////////////////////////////////
152 
153 static SkView* MyFactory() { return new ComplexClipView; }
154 static SkViewRegister reg(MyFactory);
155