• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
19 enum class VerbType {
20     kTriangles,
21     kQuadratics,
22     kCubics,
23     kConics
24 };
25 
verb_type_name(VerbType verbType)26 static 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  */
39 class StrokeVerbView : public Sample {
onOnceBeforeDraw()40     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;
name()46     SkString name() override { return SkString("StrokeVerb"); }
47 
48     class Click;
49 
updateAndInval()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 
onDrawContent(SkCanvas * canvas)67 void StrokeVerbView::onDrawContent(SkCanvas* canvas) {
68     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 
updatePath()107 void StrokeVerbView::updatePath() {
108     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 
128 class StrokeVerbView::Click : public Sample::Click {
129 public:
Click(int ptIdx)130     Click(int ptIdx) : fPtIdx(ptIdx) {}
131 
doClick(SkPoint points[])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 
142 private:
143     int fPtIdx;
144 };
145 
onFindClickHandler(SkScalar x,SkScalar y,skui::ModifierKey)146 Sample::Click* StrokeVerbView::onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey) {
147     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 
onClick(Sample::Click * click)158 bool StrokeVerbView::onClick(Sample::Click* click) {
159     Click* myClick = (Click*)click;
160     myClick->doClick(fPoints);
161     this->updateAndInval();
162     return true;
163 }
164 
onChar(SkUnichar unichar)165 bool StrokeVerbView::onChar(SkUnichar unichar) {
166         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 
221 DEF_SAMPLE(return new StrokeVerbView;)
222 
223 #endif  // SK_SUPPORT_GPU
224