blob: 821906565857dc9af99b3142fa839fe5a6164dcf [file] [log] [blame]
hstern9bd4c692016-06-15 09:13:34 -07001/*
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 <cmath>
13
14#define PI SK_ScalarPI
15
16#define LIN_SEGMENTS 10
17
18class OverstrokeView : public SampleView {
19 public:
20 SkScalar fStroke;
21 int fPathType; // super lazy enum
22 bool fClosePath;
23 bool fDrawFillPath;
24 OverstrokeView() {
25 fStroke = 5;
26 fPathType = 0;
27 fClosePath = false;
28 fDrawFillPath = false;
29 this->setBGColor(0xFFFFFFFF);
30 }
31
32 protected:
33 bool onQuery(SkEvent* evt) override {
34 if (SampleCode::TitleQ(*evt)) {
35 SampleCode::TitleR(evt, "PathOverstroke");
36 return true;
37 }
38 SkUnichar uni;
39 if (SampleCode::CharQ(*evt, &uni)) {
40 switch (uni) {
41 case ',':
42 fStroke += 1.0;
43 this->inval(nullptr);
44 return true;
45 case '.':
46 fStroke -= 1.0;
47 this->inval(nullptr);
48 return true;
49 case 'x':
50 fPathType = (fPathType + 1) % 3;
51 this->inval(nullptr);
52 return true;
53 case 'c':
54 fClosePath = !fClosePath;
55 this->inval(nullptr);
56 return true;
57 case 'f':
58 fDrawFillPath = !fDrawFillPath;
59 this->inval(nullptr);
60 return true;
61 default:
62 break;
63 }
64 }
65 return this->INHERITED::onQuery(evt);
66 }
67
68 SkPath quadPath(SkPoint p1, SkPoint p2) {
69 SkASSERT(p1.y() == p2.y());
70
71 SkPath path;
72 path.moveTo(p1);
73 path.lineTo(p2);
74
75 SkPoint p3 = SkPoint::Make((p1.x() + p2.x()) / 2.0f, p1.y() * 0.7f);
76
77 path.quadTo(p3, p1);
78
79 return path;
80 }
81
82 SkPath linSemicirclePath(SkPoint p1, SkPoint p2) {
83 SkASSERT(p1.y() == p2.y());
84
85 SkPath path;
86 path.moveTo(p1);
87 path.lineTo(p2);
88
89 SkPoint pt;
90
91 for (int i = 0; i < LIN_SEGMENTS; i++) {
92 float theta = i * PI / (LIN_SEGMENTS);
93 SkScalar x = 65 + 15 * cos(theta);
94 SkScalar y = 50 - 15 * sin(theta);
95 pt = SkPoint::Make(x, y);
96 path.lineTo(pt);
97 }
98 path.lineTo(p1);
99
100 return path;
101 }
102
103 SkPath rectPath(SkPoint p1) {
104 SkRect r = SkRect::MakeXYWH(p1.fX, p1.fY, 20, 20);
105 SkPath path;
106 path.addRect(r);
107
108 return path;
109 }
110
111 void onDrawContent(SkCanvas* canvas) override {
112 const float SCALE = 1;
113
114 canvas->translate(30, 40);
115 canvas->scale(SCALE, SCALE);
116
117 SkPoint p1 = SkPoint::Make(50, 50);
118 SkPoint p2 = SkPoint::Make(80, 50);
119
120 SkPath path;
121 switch (fPathType) {
122 case 0:
123 path = quadPath(p1, p2);
124 break;
125 case 1:
126 path = linSemicirclePath(p1, p2);
127 break;
128 case 2:
129 path = rectPath(p1);
130 break;
131 default:
132 path = quadPath(p1, p2);
133 break;
134 }
135
136 if (fClosePath) {
137 path.close();
138 }
139
140 SkPaint p;
141 p.setColor(SK_ColorRED);
142 p.setAntiAlias(true);
143 p.setStyle(SkPaint::kStroke_Style);
144 p.setStrokeWidth(fStroke);
145
146 canvas->drawPath(path, p);
147
148 if (fDrawFillPath) {
149 SkPath fillpath;
150 p.getFillPath(path, &fillpath);
151
152 SkPaint fillp;
153 fillp.setColor(SK_ColorBLACK);
154 fillp.setAntiAlias(true);
155 fillp.setStyle(SkPaint::kStroke_Style);
156
157 canvas->drawPath(fillpath, fillp);
158 }
159 }
160
161 private:
162 typedef SampleView INHERITED;
163};
164
165///////////////////////////////////////////////////////////////////////////////
166
167static SkView* MyFactory() { return new OverstrokeView; }
168static SkViewRegister reg(MyFactory);