• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 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 #include "SampleCode.h"
8 #include "SkView.h"
9 #include "SkCanvas.h"
10 #include "SkPath.h"
11 
12 #include <iostream>
13 #include <cmath>
14 
15 #define PI SK_ScalarPI
16 
17 #define LIN_SEGMENTS 10
18 
19 class OverstrokeView : public SampleView {
20    public:
21     SkScalar fStroke;
22     int fPathType;  // super lazy enum
23     bool fClosePath;
24     bool fDrawFillPath;
25     bool fDumpHex;
OverstrokeView()26     OverstrokeView() {
27         fStroke = 5;
28         fPathType = 0;
29         fClosePath = false;
30         fDrawFillPath = false;
31         fDumpHex = false;
32         this->setBGColor(0xFFFFFFFF);
33     }
34 
35    protected:
onQuery(SkEvent * evt)36     bool onQuery(SkEvent* evt) override {
37         if (SampleCode::TitleQ(*evt)) {
38             SampleCode::TitleR(evt, "PathOverstroke");
39             return true;
40         }
41         SkUnichar uni;
42         if (SampleCode::CharQ(*evt, &uni)) {
43             switch (uni) {
44                 case ',':
45                     fStroke += 1.0;
46                     this->inval(nullptr);
47                     return true;
48                 case '.':
49                     fStroke -= 1.0;
50                     this->inval(nullptr);
51                     return true;
52                 case 'x':
53                     fPathType = (fPathType + 1) % 4;
54                     this->inval(nullptr);
55                     return true;
56                 case 'c':
57                     fClosePath = !fClosePath;
58                     this->inval(nullptr);
59                     return true;
60                 case 'f':
61                     fDrawFillPath = !fDrawFillPath;
62                     this->inval(nullptr);
63                     return true;
64                 case 'D':
65                     fDumpHex = !fDumpHex;
66                     this->inval(nullptr);
67                     return true;
68                 default:
69                     break;
70             }
71         }
72         return this->INHERITED::onQuery(evt);
73     }
74 
quadPath(SkPoint p1,SkPoint p2)75     SkPath quadPath(SkPoint p1, SkPoint p2) {
76         SkASSERT(p1.y() == p2.y());
77 
78         SkPath path;
79         path.moveTo(p1);
80         path.lineTo(p2);
81 
82         SkPoint p3 = SkPoint::Make((p1.x() + p2.x()) / 2.0f, p1.y() * 0.7f);
83 
84         path.quadTo(p3, p1);
85 
86         return path;
87     }
88 
cubicPath(SkPoint p1,SkPoint p2)89     SkPath cubicPath(SkPoint p1, SkPoint p2) {
90         SkASSERT(p1.y() == p2.y());
91 
92         SkPath path;
93         path.moveTo(p1);
94 
95         SkPoint p3 = SkPoint::Make((p1.x() + p2.x()) / 3.0f, p1.y() * 0.7f);
96         SkPoint p4 = SkPoint::Make(2.0f*(p1.x() + p2.x()) / 3.0f, p1.y() * 1.5f);
97 
98         path.cubicTo(p3, p4, p2);
99 
100         return path;
101     }
102 
linSemicirclePath(SkPoint p1,SkPoint p2)103     SkPath linSemicirclePath(SkPoint p1, SkPoint p2) {
104         SkASSERT(p1.y() == p2.y());
105 
106         SkPath path;
107         path.moveTo(p1);
108         path.lineTo(p2);
109 
110         SkPoint pt;
111 
112         for (int i = 0; i < LIN_SEGMENTS; i++) {
113             float theta = i * PI / (LIN_SEGMENTS);
114             SkScalar x = 65 + 15 * cos(theta);
115             SkScalar y = 50 - 15 * sin(theta);
116             pt = SkPoint::Make(x, y);
117             path.lineTo(pt);
118         }
119         path.lineTo(p1);
120 
121         return path;
122     }
123 
rectPath(SkPoint p1)124     SkPath rectPath(SkPoint p1) {
125         SkRect r = SkRect::MakeXYWH(p1.fX, p1.fY, 20, 20);
126         SkPath path;
127         path.addRect(r);
128 
129         return path;
130     }
131 
onDrawContent(SkCanvas * canvas)132     void onDrawContent(SkCanvas* canvas) override {
133         const float SCALE = 1;
134 
135         canvas->translate(30, 40);
136         canvas->scale(SCALE, SCALE);
137 
138         SkPoint p1 = SkPoint::Make(50, 50);
139         SkPoint p2 = SkPoint::Make(80, 50);
140 
141         SkPath path;
142         switch (fPathType) {
143             case 0:
144                 path = quadPath(p1, p2);
145                 break;
146             case 1:
147                 path = cubicPath(p1, p2);
148                 break;
149             case 2:
150                 path = rectPath(p1);
151                 break;
152             case 3:
153                 path = linSemicirclePath(p1, p2);
154                 break;
155             default:
156                 path = quadPath(p1, p2);
157                 break;
158         }
159 
160         if (fClosePath) {
161             path.close();
162         }
163 
164         SkPaint p;
165         p.setColor(SK_ColorRED);
166         p.setAntiAlias(true);
167         p.setStyle(SkPaint::kStroke_Style);
168         p.setStrokeWidth(fStroke);
169 
170         canvas->drawPath(path, p);
171 
172         if (fDumpHex) {
173             std::cerr << "path dumpHex" << std::endl;
174             path.dumpHex();
175         }
176 
177         SkPaint hairp;
178         hairp.setColor(SK_ColorBLACK);
179         hairp.setAntiAlias(true);
180         hairp.setStyle(SkPaint::kStroke_Style);
181 
182         if (fDrawFillPath) {
183             SkPath fillpath;
184             p.getFillPath(path, &fillpath);
185 
186             canvas->drawPath(fillpath, hairp);
187 
188             if (fDumpHex) {
189                 std::cerr << "fillpath dumpHex" << std::endl;
190                 fillpath.dumpHex();
191             }
192         }
193 
194         if (fDumpHex) {
195             std::cerr << std::endl;
196 
197             fDumpHex = false;
198         }
199 
200         // draw original path with green hairline
201         hairp.setColor(SK_ColorGREEN);
202         canvas->drawPath(path, hairp);
203     }
204 
205    private:
206     typedef SampleView INHERITED;
207 };
208 
209 ///////////////////////////////////////////////////////////////////////////////
210 
MyFactory()211 static SkView* MyFactory() { return new OverstrokeView; }
212 static SkViewRegister reg(MyFactory);
213