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