xref: /aosp_15_r20/external/skia/tools/viewer/StrokeVerbSlide.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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