blob: bb90ee3b783c4dd268c93481d9743b918365b2f7 [file] [log] [blame]
Chris Dalton9ff7eef2021-03-05 21:58:25 -07001/*
2 * Copyright 2017 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 "include/core/SkTypes.h"
9
10#if SK_SUPPORT_GPU
11
12#include "include/core/SkCanvas.h"
13#include "include/core/SkFont.h"
14#include "include/core/SkPaint.h"
15#include "include/core/SkPath.h"
16#include "samplecode/Sample.h"
17#include "src/core/SkGeometry.h"
18
19enum class VerbType {
20 kTriangles,
21 kQuadratics,
22 kCubics,
23 kConics
24};
25
26static const char* verb_type_name(VerbType verbType) {
27 switch (verbType) {
28 case VerbType::kTriangles: return "kTriangles";
29 case VerbType::kQuadratics: return "kQuadratics";
30 case VerbType::kCubics: return "kCubics";
31 case VerbType::kConics: return "kConics";
32 }
33 SkUNREACHABLE;
34};
35
36/**
37 * This sample visualizes simple strokes.
38 */
Chris Dalton685e09b2021-06-19 11:50:17 -060039class StrokeVerbView : public Sample {
Chris Dalton9ff7eef2021-03-05 21:58:25 -070040 void onOnceBeforeDraw() override { this->updatePath(); }
41 void onDrawContent(SkCanvas*) override;
42
43 Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey) override;
44 bool onClick(Sample::Click*) override;
45 bool onChar(SkUnichar) override;
46 SkString name() override { return SkString("StrokeVerb"); }
47
48 class Click;
49
50 void updateAndInval() { this->updatePath(); }
51
52 void updatePath();
53
54 VerbType fVerbType = VerbType::kCubics;
55
56 SkPoint fPoints[4] = {
57 {100.05f, 100.05f}, {400.75f, 100.05f}, {400.75f, 300.95f}, {100.05f, 300.95f}};
58
59 float fConicWeight = .5;
60 float fStrokeWidth = 40;
61 SkPaint::Join fStrokeJoin = SkPaint::kMiter_Join;
62 SkPaint::Cap fStrokeCap = SkPaint::kButt_Cap;
63
64 SkPath fPath;
65};
66
Chris Dalton685e09b2021-06-19 11:50:17 -060067void StrokeVerbView::onDrawContent(SkCanvas* canvas) {
Chris Dalton9ff7eef2021-03-05 21:58:25 -070068 canvas->clear(SK_ColorBLACK);
69
70 SkPaint outlinePaint;
71 outlinePaint.setColor(0xff808080);
72 outlinePaint.setStyle(SkPaint::kStroke_Style);
73 outlinePaint.setStrokeWidth(fStrokeWidth);
74 outlinePaint.setStrokeJoin(fStrokeJoin);
75 outlinePaint.setStrokeCap(fStrokeCap);
76 outlinePaint.setAntiAlias(true);
77 canvas->drawPath(fPath, outlinePaint);
78
79 SkString caption;
80 caption.appendf("VerbType_%s", verb_type_name(fVerbType));
81 if (VerbType::kCubics == fVerbType) {
82 caption.appendf(" (%s)", SkCubicTypeName(SkClassifyCubic(fPoints)));
83 } else if (VerbType::kConics == fVerbType) {
84 caption.appendf(" (w=%f)", fConicWeight);
85 }
86
87 caption.appendf(" (stroke_width=%f)", fStrokeWidth);
88
89 SkPaint pointsPaint;
90 pointsPaint.setColor(SK_ColorBLUE);
91 pointsPaint.setStrokeWidth(8);
92 pointsPaint.setAntiAlias(true);
93
94 if (VerbType::kCubics == fVerbType) {
95 canvas->drawPoints(SkCanvas::kPoints_PointMode, 4, fPoints, pointsPaint);
96 } else {
97 canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, fPoints, pointsPaint);
98 canvas->drawPoints(SkCanvas::kPoints_PointMode, 1, fPoints + 3, pointsPaint);
99 }
100
101 SkFont font(nullptr, 20);
102 SkPaint captionPaint;
103 captionPaint.setColor(SK_ColorWHITE);
104 canvas->drawString(caption, 10, 30, font, captionPaint);
105}
106
Chris Dalton685e09b2021-06-19 11:50:17 -0600107void StrokeVerbView::updatePath() {
Chris Dalton9ff7eef2021-03-05 21:58:25 -0700108 fPath.reset();
109 fPath.moveTo(fPoints[0]);
110 switch (fVerbType) {
111 case VerbType::kCubics:
112 fPath.cubicTo(fPoints[1], fPoints[2], fPoints[3]);
113 break;
114 case VerbType::kQuadratics:
115 fPath.quadTo(fPoints[1], fPoints[3]);
116 break;
117 case VerbType::kConics:
118 fPath.conicTo(fPoints[1], fPoints[3], fConicWeight);
119 break;
120 case VerbType::kTriangles:
121 fPath.lineTo(fPoints[1]);
122 fPath.lineTo(fPoints[3]);
123 fPath.close();
124 break;
125 }
126}
127
Chris Dalton685e09b2021-06-19 11:50:17 -0600128class StrokeVerbView::Click : public Sample::Click {
Chris Dalton9ff7eef2021-03-05 21:58:25 -0700129public:
130 Click(int ptIdx) : fPtIdx(ptIdx) {}
131
132 void doClick(SkPoint points[]) {
133 if (fPtIdx >= 0) {
134 points[fPtIdx] += fCurr - fPrev;
135 } else {
136 for (int i = 0; i < 4; ++i) {
137 points[i] += fCurr - fPrev;
138 }
139 }
140 }
141
142private:
143 int fPtIdx;
144};
145
Chris Dalton685e09b2021-06-19 11:50:17 -0600146Sample::Click* StrokeVerbView::onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey) {
Chris Dalton9ff7eef2021-03-05 21:58:25 -0700147 for (int i = 0; i < 4; ++i) {
148 if (VerbType::kCubics != fVerbType && 2 == i) {
149 continue;
150 }
151 if (fabs(x - fPoints[i].x()) < 20 && fabsf(y - fPoints[i].y()) < 20) {
152 return new Click(i);
153 }
154 }
155 return new Click(-1);
156}
157
Chris Dalton685e09b2021-06-19 11:50:17 -0600158bool StrokeVerbView::onClick(Sample::Click* click) {
Chris Dalton9ff7eef2021-03-05 21:58:25 -0700159 Click* myClick = (Click*)click;
160 myClick->doClick(fPoints);
161 this->updateAndInval();
162 return true;
163}
164
Chris Dalton685e09b2021-06-19 11:50:17 -0600165bool StrokeVerbView::onChar(SkUnichar unichar) {
Chris Dalton9ff7eef2021-03-05 21:58:25 -0700166 if (unichar >= '1' && unichar <= '4') {
167 fVerbType = VerbType(unichar - '1');
168 this->updateAndInval();
169 return true;
170 }
171 float* valueToScale = nullptr;
172 if (VerbType::kConics == fVerbType) {
173 valueToScale = &fConicWeight;
174 } else {
175 valueToScale = &fStrokeWidth;
176 }
177 if (valueToScale) {
178 if (unichar == '+') {
179 *valueToScale *= 2;
180 this->updateAndInval();
181 return true;
182 }
183 if (unichar == '+' || unichar == '=') {
184 *valueToScale *= 5/4.f;
185 this->updateAndInval();
186 return true;
187 }
188 if (unichar == '-') {
189 *valueToScale *= 4/5.f;
190 this->updateAndInval();
191 return true;
192 }
193 if (unichar == '_') {
194 *valueToScale *= .5f;
195 this->updateAndInval();
196 return true;
197 }
198 }
199 if (unichar == 'D') {
200 SkDebugf(" SkPoint fPoints[4] = {\n");
201 SkDebugf(" {%ff, %ff},\n", fPoints[0].x(), fPoints[0].y());
202 SkDebugf(" {%ff, %ff},\n", fPoints[1].x(), fPoints[1].y());
203 SkDebugf(" {%ff, %ff},\n", fPoints[2].x(), fPoints[2].y());
204 SkDebugf(" {%ff, %ff}\n", fPoints[3].x(), fPoints[3].y());
205 SkDebugf(" };\n");
206 return true;
207 }
208 if (unichar == 'J') {
209 fStrokeJoin = (SkPaint::Join)((fStrokeJoin + 1) % 3);
210 this->updateAndInval();
211 return true;
212 }
213 if (unichar == 'C') {
214 fStrokeCap = (SkPaint::Cap)((fStrokeCap + 1) % 3);
215 this->updateAndInval();
216 return true;
217 }
218 return false;
219}
220
Chris Dalton685e09b2021-06-19 11:50:17 -0600221DEF_SAMPLE(return new StrokeVerbView;)
Chris Dalton9ff7eef2021-03-05 21:58:25 -0700222
223#endif // SK_SUPPORT_GPU