• 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                     return true;
47                 case '.':
48                     fStroke -= 1.0;
49                     return true;
50                 case 'x':
51                     fPathType = (fPathType + 1) % 4;
52                     return true;
53                 case 'c':
54                     fClosePath = !fClosePath;
55                     return true;
56                 case 'f':
57                     fDrawFillPath = !fDrawFillPath;
58                     return true;
59                 case 'D':
60                     fDumpHex = !fDumpHex;
61                     return true;
62                 default:
63                     break;
64             }
65         }
66         return this->INHERITED::onQuery(evt);
67     }
68 
quadPath(SkPoint p1,SkPoint p2)69     SkPath quadPath(SkPoint p1, SkPoint p2) {
70         SkASSERT(p1.y() == p2.y());
71 
72         SkPath path;
73         path.moveTo(p1);
74         path.lineTo(p2);
75 
76         SkPoint p3 = SkPoint::Make((p1.x() + p2.x()) / 2.0f, p1.y() * 0.7f);
77 
78         path.quadTo(p3, p1);
79 
80         return path;
81     }
82 
cubicPath(SkPoint p1,SkPoint p2)83     SkPath cubicPath(SkPoint p1, SkPoint p2) {
84         SkASSERT(p1.y() == p2.y());
85 
86         SkPath path;
87         path.moveTo(p1);
88 
89         SkPoint p3 = SkPoint::Make((p1.x() + p2.x()) / 3.0f, p1.y() * 0.7f);
90         SkPoint p4 = SkPoint::Make(2.0f*(p1.x() + p2.x()) / 3.0f, p1.y() * 1.5f);
91 
92         path.cubicTo(p3, p4, p2);
93 
94         return path;
95     }
96 
linSemicirclePath(SkPoint p1,SkPoint p2)97     SkPath linSemicirclePath(SkPoint p1, SkPoint p2) {
98         SkASSERT(p1.y() == p2.y());
99 
100         SkPath path;
101         path.moveTo(p1);
102         path.lineTo(p2);
103 
104         SkPoint pt;
105 
106         for (int i = 0; i < LIN_SEGMENTS; i++) {
107             float theta = i * PI / (LIN_SEGMENTS);
108             SkScalar x = 65 + 15 * cos(theta);
109             SkScalar y = 50 - 15 * sin(theta);
110             pt = SkPoint::Make(x, y);
111             path.lineTo(pt);
112         }
113         path.lineTo(p1);
114 
115         return path;
116     }
117 
rectPath(SkPoint p1)118     SkPath rectPath(SkPoint p1) {
119         SkRect r = SkRect::MakeXYWH(p1.fX, p1.fY, 20, 20);
120         SkPath path;
121         path.addRect(r);
122 
123         return path;
124     }
125 
onDrawContent(SkCanvas * canvas)126     void onDrawContent(SkCanvas* canvas) override {
127         const float SCALE = 1;
128 
129         canvas->translate(30, 40);
130         canvas->scale(SCALE, SCALE);
131 
132         SkPoint p1 = SkPoint::Make(50, 50);
133         SkPoint p2 = SkPoint::Make(80, 50);
134 
135         SkPath path;
136         switch (fPathType) {
137             case 0:
138                 path = quadPath(p1, p2);
139                 break;
140             case 1:
141                 path = cubicPath(p1, p2);
142                 break;
143             case 2:
144                 path = rectPath(p1);
145                 break;
146             case 3:
147                 path = linSemicirclePath(p1, p2);
148                 break;
149             default:
150                 path = quadPath(p1, p2);
151                 break;
152         }
153 
154         if (fClosePath) {
155             path.close();
156         }
157 
158         SkPaint p;
159         p.setColor(SK_ColorRED);
160         p.setAntiAlias(true);
161         p.setStyle(SkPaint::kStroke_Style);
162         p.setStrokeWidth(fStroke);
163 
164         canvas->drawPath(path, p);
165 
166         if (fDumpHex) {
167             std::cerr << "path dumpHex" << std::endl;
168             path.dumpHex();
169         }
170 
171         SkPaint hairp;
172         hairp.setColor(SK_ColorBLACK);
173         hairp.setAntiAlias(true);
174         hairp.setStyle(SkPaint::kStroke_Style);
175 
176         if (fDrawFillPath) {
177             SkPath fillpath;
178             p.getFillPath(path, &fillpath);
179 
180             canvas->drawPath(fillpath, hairp);
181 
182             if (fDumpHex) {
183                 std::cerr << "fillpath dumpHex" << std::endl;
184                 fillpath.dumpHex();
185             }
186         }
187 
188         if (fDumpHex) {
189             std::cerr << std::endl;
190 
191             fDumpHex = false;
192         }
193 
194         // draw original path with green hairline
195         hairp.setColor(SK_ColorGREEN);
196         canvas->drawPath(path, hairp);
197     }
198 
199    private:
200     typedef SampleView INHERITED;
201 };
202 
203 ///////////////////////////////////////////////////////////////////////////////
204 
MyFactory()205 static SkView* MyFactory() { return new OverstrokeView; }
206 static SkViewRegister reg(MyFactory);
207