1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2017 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
9*c8dee2aaSAndroid Build Coastguard Worker
10*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_GANESH)
11*c8dee2aaSAndroid Build Coastguard Worker
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkFont.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPaint.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPath.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkGeometry.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "tools/fonts/FontToolUtils.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "tools/viewer/ClickHandlerSlide.h"
19*c8dee2aaSAndroid Build Coastguard Worker
20*c8dee2aaSAndroid Build Coastguard Worker enum class VerbType {
21*c8dee2aaSAndroid Build Coastguard Worker kTriangles,
22*c8dee2aaSAndroid Build Coastguard Worker kQuadratics,
23*c8dee2aaSAndroid Build Coastguard Worker kCubics,
24*c8dee2aaSAndroid Build Coastguard Worker kConics
25*c8dee2aaSAndroid Build Coastguard Worker };
26*c8dee2aaSAndroid Build Coastguard Worker
verb_type_name(VerbType verbType)27*c8dee2aaSAndroid Build Coastguard Worker static const char* verb_type_name(VerbType verbType) {
28*c8dee2aaSAndroid Build Coastguard Worker switch (verbType) {
29*c8dee2aaSAndroid Build Coastguard Worker case VerbType::kTriangles: return "kTriangles";
30*c8dee2aaSAndroid Build Coastguard Worker case VerbType::kQuadratics: return "kQuadratics";
31*c8dee2aaSAndroid Build Coastguard Worker case VerbType::kCubics: return "kCubics";
32*c8dee2aaSAndroid Build Coastguard Worker case VerbType::kConics: return "kConics";
33*c8dee2aaSAndroid Build Coastguard Worker }
34*c8dee2aaSAndroid Build Coastguard Worker SkUNREACHABLE;
35*c8dee2aaSAndroid Build Coastguard Worker };
36*c8dee2aaSAndroid Build Coastguard Worker
37*c8dee2aaSAndroid Build Coastguard Worker /**
38*c8dee2aaSAndroid Build Coastguard Worker * This sample visualizes simple strokes.
39*c8dee2aaSAndroid Build Coastguard Worker */
40*c8dee2aaSAndroid Build Coastguard Worker class StrokeVerbSlide : public ClickHandlerSlide {
41*c8dee2aaSAndroid Build Coastguard Worker public:
StrokeVerbSlide()42*c8dee2aaSAndroid Build Coastguard Worker StrokeVerbSlide() { fName = "StrokeVerb"; }
43*c8dee2aaSAndroid Build Coastguard Worker
load(SkScalar w,SkScalar h)44*c8dee2aaSAndroid Build Coastguard Worker void load(SkScalar w, SkScalar h) override { this->updatePath(); }
45*c8dee2aaSAndroid Build Coastguard Worker
46*c8dee2aaSAndroid Build Coastguard Worker void draw(SkCanvas*) override;
47*c8dee2aaSAndroid Build Coastguard Worker
48*c8dee2aaSAndroid Build Coastguard Worker bool onChar(SkUnichar) override;
49*c8dee2aaSAndroid Build Coastguard Worker
50*c8dee2aaSAndroid Build Coastguard Worker protected:
51*c8dee2aaSAndroid Build Coastguard Worker class Click;
52*c8dee2aaSAndroid Build Coastguard Worker
53*c8dee2aaSAndroid Build Coastguard Worker ClickHandlerSlide::Click* onFindClickHandler(SkScalar x, SkScalar y,
54*c8dee2aaSAndroid Build Coastguard Worker skui::ModifierKey) override;
55*c8dee2aaSAndroid Build Coastguard Worker bool onClick(ClickHandlerSlide::Click*) override;
56*c8dee2aaSAndroid Build Coastguard Worker
57*c8dee2aaSAndroid Build Coastguard Worker
58*c8dee2aaSAndroid Build Coastguard Worker private:
updateAndInval()59*c8dee2aaSAndroid Build Coastguard Worker void updateAndInval() { this->updatePath(); }
60*c8dee2aaSAndroid Build Coastguard Worker
61*c8dee2aaSAndroid Build Coastguard Worker void updatePath();
62*c8dee2aaSAndroid Build Coastguard Worker
63*c8dee2aaSAndroid Build Coastguard Worker VerbType fVerbType = VerbType::kCubics;
64*c8dee2aaSAndroid Build Coastguard Worker
65*c8dee2aaSAndroid Build Coastguard Worker SkPoint fPoints[4] = {
66*c8dee2aaSAndroid Build Coastguard Worker {100.05f, 100.05f}, {400.75f, 100.05f}, {400.75f, 300.95f}, {100.05f, 300.95f}};
67*c8dee2aaSAndroid Build Coastguard Worker
68*c8dee2aaSAndroid Build Coastguard Worker float fConicWeight = .5;
69*c8dee2aaSAndroid Build Coastguard Worker float fStrokeWidth = 40;
70*c8dee2aaSAndroid Build Coastguard Worker SkPaint::Join fStrokeJoin = SkPaint::kMiter_Join;
71*c8dee2aaSAndroid Build Coastguard Worker SkPaint::Cap fStrokeCap = SkPaint::kButt_Cap;
72*c8dee2aaSAndroid Build Coastguard Worker
73*c8dee2aaSAndroid Build Coastguard Worker SkPath fPath;
74*c8dee2aaSAndroid Build Coastguard Worker };
75*c8dee2aaSAndroid Build Coastguard Worker
draw(SkCanvas * canvas)76*c8dee2aaSAndroid Build Coastguard Worker void StrokeVerbSlide::draw(SkCanvas* canvas) {
77*c8dee2aaSAndroid Build Coastguard Worker canvas->clear(SK_ColorBLACK);
78*c8dee2aaSAndroid Build Coastguard Worker
79*c8dee2aaSAndroid Build Coastguard Worker SkPaint outlinePaint;
80*c8dee2aaSAndroid Build Coastguard Worker outlinePaint.setColor(0xff808080);
81*c8dee2aaSAndroid Build Coastguard Worker outlinePaint.setStyle(SkPaint::kStroke_Style);
82*c8dee2aaSAndroid Build Coastguard Worker outlinePaint.setStrokeWidth(fStrokeWidth);
83*c8dee2aaSAndroid Build Coastguard Worker outlinePaint.setStrokeJoin(fStrokeJoin);
84*c8dee2aaSAndroid Build Coastguard Worker outlinePaint.setStrokeCap(fStrokeCap);
85*c8dee2aaSAndroid Build Coastguard Worker outlinePaint.setAntiAlias(true);
86*c8dee2aaSAndroid Build Coastguard Worker canvas->drawPath(fPath, outlinePaint);
87*c8dee2aaSAndroid Build Coastguard Worker
88*c8dee2aaSAndroid Build Coastguard Worker SkString caption;
89*c8dee2aaSAndroid Build Coastguard Worker caption.appendf("VerbType_%s", verb_type_name(fVerbType));
90*c8dee2aaSAndroid Build Coastguard Worker if (VerbType::kCubics == fVerbType) {
91*c8dee2aaSAndroid Build Coastguard Worker caption.appendf(" (%s)", SkCubicTypeName(SkClassifyCubic(fPoints)));
92*c8dee2aaSAndroid Build Coastguard Worker } else if (VerbType::kConics == fVerbType) {
93*c8dee2aaSAndroid Build Coastguard Worker caption.appendf(" (w=%f)", fConicWeight);
94*c8dee2aaSAndroid Build Coastguard Worker }
95*c8dee2aaSAndroid Build Coastguard Worker
96*c8dee2aaSAndroid Build Coastguard Worker caption.appendf(" (stroke_width=%f)", fStrokeWidth);
97*c8dee2aaSAndroid Build Coastguard Worker
98*c8dee2aaSAndroid Build Coastguard Worker SkPaint pointsPaint;
99*c8dee2aaSAndroid Build Coastguard Worker pointsPaint.setColor(SK_ColorBLUE);
100*c8dee2aaSAndroid Build Coastguard Worker pointsPaint.setStrokeWidth(8);
101*c8dee2aaSAndroid Build Coastguard Worker pointsPaint.setAntiAlias(true);
102*c8dee2aaSAndroid Build Coastguard Worker
103*c8dee2aaSAndroid Build Coastguard Worker if (VerbType::kCubics == fVerbType) {
104*c8dee2aaSAndroid Build Coastguard Worker canvas->drawPoints(SkCanvas::kPoints_PointMode, 4, fPoints, pointsPaint);
105*c8dee2aaSAndroid Build Coastguard Worker } else {
106*c8dee2aaSAndroid Build Coastguard Worker canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, fPoints, pointsPaint);
107*c8dee2aaSAndroid Build Coastguard Worker canvas->drawPoints(SkCanvas::kPoints_PointMode, 1, fPoints + 3, pointsPaint);
108*c8dee2aaSAndroid Build Coastguard Worker }
109*c8dee2aaSAndroid Build Coastguard Worker
110*c8dee2aaSAndroid Build Coastguard Worker SkFont font(ToolUtils::DefaultTypeface(), 20);
111*c8dee2aaSAndroid Build Coastguard Worker SkPaint captionPaint;
112*c8dee2aaSAndroid Build Coastguard Worker captionPaint.setColor(SK_ColorWHITE);
113*c8dee2aaSAndroid Build Coastguard Worker canvas->drawString(caption, 10, 30, font, captionPaint);
114*c8dee2aaSAndroid Build Coastguard Worker }
115*c8dee2aaSAndroid Build Coastguard Worker
updatePath()116*c8dee2aaSAndroid Build Coastguard Worker void StrokeVerbSlide::updatePath() {
117*c8dee2aaSAndroid Build Coastguard Worker fPath.reset();
118*c8dee2aaSAndroid Build Coastguard Worker fPath.moveTo(fPoints[0]);
119*c8dee2aaSAndroid Build Coastguard Worker switch (fVerbType) {
120*c8dee2aaSAndroid Build Coastguard Worker case VerbType::kCubics:
121*c8dee2aaSAndroid Build Coastguard Worker fPath.cubicTo(fPoints[1], fPoints[2], fPoints[3]);
122*c8dee2aaSAndroid Build Coastguard Worker break;
123*c8dee2aaSAndroid Build Coastguard Worker case VerbType::kQuadratics:
124*c8dee2aaSAndroid Build Coastguard Worker fPath.quadTo(fPoints[1], fPoints[3]);
125*c8dee2aaSAndroid Build Coastguard Worker break;
126*c8dee2aaSAndroid Build Coastguard Worker case VerbType::kConics:
127*c8dee2aaSAndroid Build Coastguard Worker fPath.conicTo(fPoints[1], fPoints[3], fConicWeight);
128*c8dee2aaSAndroid Build Coastguard Worker break;
129*c8dee2aaSAndroid Build Coastguard Worker case VerbType::kTriangles:
130*c8dee2aaSAndroid Build Coastguard Worker fPath.lineTo(fPoints[1]);
131*c8dee2aaSAndroid Build Coastguard Worker fPath.lineTo(fPoints[3]);
132*c8dee2aaSAndroid Build Coastguard Worker fPath.close();
133*c8dee2aaSAndroid Build Coastguard Worker break;
134*c8dee2aaSAndroid Build Coastguard Worker }
135*c8dee2aaSAndroid Build Coastguard Worker }
136*c8dee2aaSAndroid Build Coastguard Worker
137*c8dee2aaSAndroid Build Coastguard Worker class StrokeVerbSlide::Click : public ClickHandlerSlide::Click {
138*c8dee2aaSAndroid Build Coastguard Worker public:
Click(int ptIdx)139*c8dee2aaSAndroid Build Coastguard Worker Click(int ptIdx) : fPtIdx(ptIdx) {}
140*c8dee2aaSAndroid Build Coastguard Worker
doClick(SkPoint points[])141*c8dee2aaSAndroid Build Coastguard Worker void doClick(SkPoint points[]) {
142*c8dee2aaSAndroid Build Coastguard Worker if (fPtIdx >= 0) {
143*c8dee2aaSAndroid Build Coastguard Worker points[fPtIdx] += fCurr - fPrev;
144*c8dee2aaSAndroid Build Coastguard Worker } else {
145*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < 4; ++i) {
146*c8dee2aaSAndroid Build Coastguard Worker points[i] += fCurr - fPrev;
147*c8dee2aaSAndroid Build Coastguard Worker }
148*c8dee2aaSAndroid Build Coastguard Worker }
149*c8dee2aaSAndroid Build Coastguard Worker }
150*c8dee2aaSAndroid Build Coastguard Worker
151*c8dee2aaSAndroid Build Coastguard Worker private:
152*c8dee2aaSAndroid Build Coastguard Worker int fPtIdx;
153*c8dee2aaSAndroid Build Coastguard Worker };
154*c8dee2aaSAndroid Build Coastguard Worker
onFindClickHandler(SkScalar x,SkScalar y,skui::ModifierKey)155*c8dee2aaSAndroid Build Coastguard Worker ClickHandlerSlide::Click* StrokeVerbSlide::onFindClickHandler(SkScalar x, SkScalar y,
156*c8dee2aaSAndroid Build Coastguard Worker skui::ModifierKey) {
157*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < 4; ++i) {
158*c8dee2aaSAndroid Build Coastguard Worker if (VerbType::kCubics != fVerbType && 2 == i) {
159*c8dee2aaSAndroid Build Coastguard Worker continue;
160*c8dee2aaSAndroid Build Coastguard Worker }
161*c8dee2aaSAndroid Build Coastguard Worker if (fabs(x - fPoints[i].x()) < 20 && fabsf(y - fPoints[i].y()) < 20) {
162*c8dee2aaSAndroid Build Coastguard Worker return new Click(i);
163*c8dee2aaSAndroid Build Coastguard Worker }
164*c8dee2aaSAndroid Build Coastguard Worker }
165*c8dee2aaSAndroid Build Coastguard Worker return new Click(-1);
166*c8dee2aaSAndroid Build Coastguard Worker }
167*c8dee2aaSAndroid Build Coastguard Worker
onClick(ClickHandlerSlide::Click * click)168*c8dee2aaSAndroid Build Coastguard Worker bool StrokeVerbSlide::onClick(ClickHandlerSlide::Click* click) {
169*c8dee2aaSAndroid Build Coastguard Worker Click* myClick = (Click*)click;
170*c8dee2aaSAndroid Build Coastguard Worker myClick->doClick(fPoints);
171*c8dee2aaSAndroid Build Coastguard Worker this->updateAndInval();
172*c8dee2aaSAndroid Build Coastguard Worker return true;
173*c8dee2aaSAndroid Build Coastguard Worker }
174*c8dee2aaSAndroid Build Coastguard Worker
onChar(SkUnichar unichar)175*c8dee2aaSAndroid Build Coastguard Worker bool StrokeVerbSlide::onChar(SkUnichar unichar) {
176*c8dee2aaSAndroid Build Coastguard Worker if (unichar >= '1' && unichar <= '4') {
177*c8dee2aaSAndroid Build Coastguard Worker fVerbType = VerbType(unichar - '1');
178*c8dee2aaSAndroid Build Coastguard Worker this->updateAndInval();
179*c8dee2aaSAndroid Build Coastguard Worker return true;
180*c8dee2aaSAndroid Build Coastguard Worker }
181*c8dee2aaSAndroid Build Coastguard Worker float* valueToScale = nullptr;
182*c8dee2aaSAndroid Build Coastguard Worker if (VerbType::kConics == fVerbType) {
183*c8dee2aaSAndroid Build Coastguard Worker valueToScale = &fConicWeight;
184*c8dee2aaSAndroid Build Coastguard Worker } else {
185*c8dee2aaSAndroid Build Coastguard Worker valueToScale = &fStrokeWidth;
186*c8dee2aaSAndroid Build Coastguard Worker }
187*c8dee2aaSAndroid Build Coastguard Worker if (valueToScale) {
188*c8dee2aaSAndroid Build Coastguard Worker if (unichar == '+') {
189*c8dee2aaSAndroid Build Coastguard Worker *valueToScale *= 2;
190*c8dee2aaSAndroid Build Coastguard Worker this->updateAndInval();
191*c8dee2aaSAndroid Build Coastguard Worker return true;
192*c8dee2aaSAndroid Build Coastguard Worker }
193*c8dee2aaSAndroid Build Coastguard Worker if (unichar == '=') {
194*c8dee2aaSAndroid Build Coastguard Worker *valueToScale *= 5/4.f;
195*c8dee2aaSAndroid Build Coastguard Worker this->updateAndInval();
196*c8dee2aaSAndroid Build Coastguard Worker return true;
197*c8dee2aaSAndroid Build Coastguard Worker }
198*c8dee2aaSAndroid Build Coastguard Worker if (unichar == '-') {
199*c8dee2aaSAndroid Build Coastguard Worker *valueToScale *= 4/5.f;
200*c8dee2aaSAndroid Build Coastguard Worker this->updateAndInval();
201*c8dee2aaSAndroid Build Coastguard Worker return true;
202*c8dee2aaSAndroid Build Coastguard Worker }
203*c8dee2aaSAndroid Build Coastguard Worker if (unichar == '_') {
204*c8dee2aaSAndroid Build Coastguard Worker *valueToScale *= .5f;
205*c8dee2aaSAndroid Build Coastguard Worker this->updateAndInval();
206*c8dee2aaSAndroid Build Coastguard Worker return true;
207*c8dee2aaSAndroid Build Coastguard Worker }
208*c8dee2aaSAndroid Build Coastguard Worker }
209*c8dee2aaSAndroid Build Coastguard Worker if (unichar == 'D') {
210*c8dee2aaSAndroid Build Coastguard Worker SkDebugf(" SkPoint fPoints[4] = {\n");
211*c8dee2aaSAndroid Build Coastguard Worker SkDebugf(" {%ff, %ff},\n", fPoints[0].x(), fPoints[0].y());
212*c8dee2aaSAndroid Build Coastguard Worker SkDebugf(" {%ff, %ff},\n", fPoints[1].x(), fPoints[1].y());
213*c8dee2aaSAndroid Build Coastguard Worker SkDebugf(" {%ff, %ff},\n", fPoints[2].x(), fPoints[2].y());
214*c8dee2aaSAndroid Build Coastguard Worker SkDebugf(" {%ff, %ff}\n", fPoints[3].x(), fPoints[3].y());
215*c8dee2aaSAndroid Build Coastguard Worker SkDebugf(" };\n");
216*c8dee2aaSAndroid Build Coastguard Worker return true;
217*c8dee2aaSAndroid Build Coastguard Worker }
218*c8dee2aaSAndroid Build Coastguard Worker if (unichar == 'J') {
219*c8dee2aaSAndroid Build Coastguard Worker fStrokeJoin = (SkPaint::Join)((fStrokeJoin + 1) % 3);
220*c8dee2aaSAndroid Build Coastguard Worker this->updateAndInval();
221*c8dee2aaSAndroid Build Coastguard Worker return true;
222*c8dee2aaSAndroid Build Coastguard Worker }
223*c8dee2aaSAndroid Build Coastguard Worker if (unichar == 'C') {
224*c8dee2aaSAndroid Build Coastguard Worker fStrokeCap = (SkPaint::Cap)((fStrokeCap + 1) % 3);
225*c8dee2aaSAndroid Build Coastguard Worker this->updateAndInval();
226*c8dee2aaSAndroid Build Coastguard Worker return true;
227*c8dee2aaSAndroid Build Coastguard Worker }
228*c8dee2aaSAndroid Build Coastguard Worker return false;
229*c8dee2aaSAndroid Build Coastguard Worker }
230*c8dee2aaSAndroid Build Coastguard Worker
231*c8dee2aaSAndroid Build Coastguard Worker DEF_SLIDE(return new StrokeVerbSlide;)
232*c8dee2aaSAndroid Build Coastguard Worker
233*c8dee2aaSAndroid Build Coastguard Worker #endif // defined(SK_GANESH)
234