1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2012 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/SkBlendMode.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColor.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkFont.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImageInfo.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkMatrix.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 "include/core/SkPathMeasure.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPathUtils.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPoint.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRRect.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkScalar.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkShader.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSurface.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTArray.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTemplates.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "include/utils/SkTextUtils.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkGeometry.h"
31*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkPathPriv.h"
32*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkPointPriv.h"
33*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkStroke.h"
34*c8dee2aaSAndroid Build Coastguard Worker #include "tools/ToolUtils.h"
35*c8dee2aaSAndroid Build Coastguard Worker #include "tools/fonts/FontToolUtils.h"
36*c8dee2aaSAndroid Build Coastguard Worker #include "tools/viewer/ClickHandlerSlide.h"
37*c8dee2aaSAndroid Build Coastguard Worker
38*c8dee2aaSAndroid Build Coastguard Worker #include <cfloat>
39*c8dee2aaSAndroid Build Coastguard Worker
40*c8dee2aaSAndroid Build Coastguard Worker using namespace skia_private;
41*c8dee2aaSAndroid Build Coastguard Worker
42*c8dee2aaSAndroid Build Coastguard Worker class SkEvent;
43*c8dee2aaSAndroid Build Coastguard Worker
hittest(const SkPoint & target,SkScalar x,SkScalar y)44*c8dee2aaSAndroid Build Coastguard Worker static bool hittest(const SkPoint& target, SkScalar x, SkScalar y) {
45*c8dee2aaSAndroid Build Coastguard Worker const SkScalar TOL = 7;
46*c8dee2aaSAndroid Build Coastguard Worker return SkPoint::Distance(target, SkPoint::Make(x, y)) <= TOL;
47*c8dee2aaSAndroid Build Coastguard Worker }
48*c8dee2aaSAndroid Build Coastguard Worker
getOnCurvePoints(const SkPath & path,SkPoint storage[])49*c8dee2aaSAndroid Build Coastguard Worker static int getOnCurvePoints(const SkPath& path, SkPoint storage[]) {
50*c8dee2aaSAndroid Build Coastguard Worker int count = 0;
51*c8dee2aaSAndroid Build Coastguard Worker for (auto [verb, pts, w] : SkPathPriv::Iterate(path)) {
52*c8dee2aaSAndroid Build Coastguard Worker switch (verb) {
53*c8dee2aaSAndroid Build Coastguard Worker case SkPathVerb::kMove:
54*c8dee2aaSAndroid Build Coastguard Worker case SkPathVerb::kLine:
55*c8dee2aaSAndroid Build Coastguard Worker case SkPathVerb::kQuad:
56*c8dee2aaSAndroid Build Coastguard Worker case SkPathVerb::kConic:
57*c8dee2aaSAndroid Build Coastguard Worker case SkPathVerb::kCubic:
58*c8dee2aaSAndroid Build Coastguard Worker storage[count++] = pts[0];
59*c8dee2aaSAndroid Build Coastguard Worker break;
60*c8dee2aaSAndroid Build Coastguard Worker default:
61*c8dee2aaSAndroid Build Coastguard Worker break;
62*c8dee2aaSAndroid Build Coastguard Worker }
63*c8dee2aaSAndroid Build Coastguard Worker }
64*c8dee2aaSAndroid Build Coastguard Worker return count;
65*c8dee2aaSAndroid Build Coastguard Worker }
66*c8dee2aaSAndroid Build Coastguard Worker
getContourCounts(const SkPath & path,TArray<int> * contourCounts)67*c8dee2aaSAndroid Build Coastguard Worker static void getContourCounts(const SkPath& path, TArray<int>* contourCounts) {
68*c8dee2aaSAndroid Build Coastguard Worker int count = 0;
69*c8dee2aaSAndroid Build Coastguard Worker for (auto [verb, pts, w] : SkPathPriv::Iterate(path)) {
70*c8dee2aaSAndroid Build Coastguard Worker switch (verb) {
71*c8dee2aaSAndroid Build Coastguard Worker case SkPathVerb::kMove:
72*c8dee2aaSAndroid Build Coastguard Worker case SkPathVerb::kLine:
73*c8dee2aaSAndroid Build Coastguard Worker count += 1;
74*c8dee2aaSAndroid Build Coastguard Worker break;
75*c8dee2aaSAndroid Build Coastguard Worker case SkPathVerb::kQuad:
76*c8dee2aaSAndroid Build Coastguard Worker case SkPathVerb::kConic:
77*c8dee2aaSAndroid Build Coastguard Worker count += 2;
78*c8dee2aaSAndroid Build Coastguard Worker break;
79*c8dee2aaSAndroid Build Coastguard Worker case SkPathVerb::kCubic:
80*c8dee2aaSAndroid Build Coastguard Worker count += 3;
81*c8dee2aaSAndroid Build Coastguard Worker break;
82*c8dee2aaSAndroid Build Coastguard Worker case SkPathVerb::kClose:
83*c8dee2aaSAndroid Build Coastguard Worker contourCounts->push_back(count);
84*c8dee2aaSAndroid Build Coastguard Worker count = 0;
85*c8dee2aaSAndroid Build Coastguard Worker break;
86*c8dee2aaSAndroid Build Coastguard Worker default:
87*c8dee2aaSAndroid Build Coastguard Worker break;
88*c8dee2aaSAndroid Build Coastguard Worker }
89*c8dee2aaSAndroid Build Coastguard Worker }
90*c8dee2aaSAndroid Build Coastguard Worker if (count > 0) {
91*c8dee2aaSAndroid Build Coastguard Worker contourCounts->push_back(count);
92*c8dee2aaSAndroid Build Coastguard Worker }
93*c8dee2aaSAndroid Build Coastguard Worker }
94*c8dee2aaSAndroid Build Coastguard Worker
erase(const sk_sp<SkSurface> & surface)95*c8dee2aaSAndroid Build Coastguard Worker static void erase(const sk_sp<SkSurface>& surface) {
96*c8dee2aaSAndroid Build Coastguard Worker SkCanvas* canvas = surface->getCanvas();
97*c8dee2aaSAndroid Build Coastguard Worker if (canvas) {
98*c8dee2aaSAndroid Build Coastguard Worker canvas->clear(SK_ColorTRANSPARENT);
99*c8dee2aaSAndroid Build Coastguard Worker }
100*c8dee2aaSAndroid Build Coastguard Worker }
101*c8dee2aaSAndroid Build Coastguard Worker
102*c8dee2aaSAndroid Build Coastguard Worker struct StrokeTypeButton {
103*c8dee2aaSAndroid Build Coastguard Worker SkRect fBounds;
104*c8dee2aaSAndroid Build Coastguard Worker char fLabel;
105*c8dee2aaSAndroid Build Coastguard Worker bool fEnabled;
106*c8dee2aaSAndroid Build Coastguard Worker };
107*c8dee2aaSAndroid Build Coastguard Worker
108*c8dee2aaSAndroid Build Coastguard Worker struct CircleTypeButton : public StrokeTypeButton {
109*c8dee2aaSAndroid Build Coastguard Worker bool fFill;
110*c8dee2aaSAndroid Build Coastguard Worker };
111*c8dee2aaSAndroid Build Coastguard Worker
112*c8dee2aaSAndroid Build Coastguard Worker class QuadStrokerSlide : public ClickHandlerSlide {
113*c8dee2aaSAndroid Build Coastguard Worker enum {
114*c8dee2aaSAndroid Build Coastguard Worker SKELETON_COLOR = 0xFF0000FF,
115*c8dee2aaSAndroid Build Coastguard Worker WIREFRAME_COLOR = 0x80FF0000
116*c8dee2aaSAndroid Build Coastguard Worker };
117*c8dee2aaSAndroid Build Coastguard Worker
118*c8dee2aaSAndroid Build Coastguard Worker enum {
119*c8dee2aaSAndroid Build Coastguard Worker kCount = 18
120*c8dee2aaSAndroid Build Coastguard Worker };
121*c8dee2aaSAndroid Build Coastguard Worker SkPoint fPts[kCount];
122*c8dee2aaSAndroid Build Coastguard Worker SkRect fWeightControl;
123*c8dee2aaSAndroid Build Coastguard Worker SkRect fRadiusControl;
124*c8dee2aaSAndroid Build Coastguard Worker SkRect fErrorControl;
125*c8dee2aaSAndroid Build Coastguard Worker SkRect fWidthControl;
126*c8dee2aaSAndroid Build Coastguard Worker SkRect fBounds;
127*c8dee2aaSAndroid Build Coastguard Worker SkMatrix fMatrix, fInverse;
128*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkShader> fShader;
129*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSurface> fMinSurface;
130*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSurface> fMaxSurface;
131*c8dee2aaSAndroid Build Coastguard Worker StrokeTypeButton fCubicButton;
132*c8dee2aaSAndroid Build Coastguard Worker StrokeTypeButton fConicButton;
133*c8dee2aaSAndroid Build Coastguard Worker StrokeTypeButton fQuadButton;
134*c8dee2aaSAndroid Build Coastguard Worker StrokeTypeButton fArcButton;
135*c8dee2aaSAndroid Build Coastguard Worker StrokeTypeButton fRRectButton;
136*c8dee2aaSAndroid Build Coastguard Worker CircleTypeButton fCircleButton;
137*c8dee2aaSAndroid Build Coastguard Worker StrokeTypeButton fTextButton;
138*c8dee2aaSAndroid Build Coastguard Worker SkString fText;
139*c8dee2aaSAndroid Build Coastguard Worker SkScalar fTextSize;
140*c8dee2aaSAndroid Build Coastguard Worker SkScalar fWeight;
141*c8dee2aaSAndroid Build Coastguard Worker SkScalar fRadius;
142*c8dee2aaSAndroid Build Coastguard Worker SkScalar fWidth, fDWidth;
143*c8dee2aaSAndroid Build Coastguard Worker SkScalar fWidthScale;
144*c8dee2aaSAndroid Build Coastguard Worker int fW, fH, fZoom;
145*c8dee2aaSAndroid Build Coastguard Worker bool fAnimate;
146*c8dee2aaSAndroid Build Coastguard Worker bool fDrawRibs;
147*c8dee2aaSAndroid Build Coastguard Worker bool fDrawTangents;
148*c8dee2aaSAndroid Build Coastguard Worker bool fDrawTDivs;
149*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
150*c8dee2aaSAndroid Build Coastguard Worker #define kStrokerErrorMin 0.001f
151*c8dee2aaSAndroid Build Coastguard Worker #define kStrokerErrorMax 5
152*c8dee2aaSAndroid Build Coastguard Worker #endif
153*c8dee2aaSAndroid Build Coastguard Worker #define kWidthMin 1
154*c8dee2aaSAndroid Build Coastguard Worker #define kWidthMax 100
155*c8dee2aaSAndroid Build Coastguard Worker public:
QuadStrokerSlide()156*c8dee2aaSAndroid Build Coastguard Worker QuadStrokerSlide() {
157*c8dee2aaSAndroid Build Coastguard Worker fPts[0].set(50, 200); // cubic
158*c8dee2aaSAndroid Build Coastguard Worker fPts[1].set(50, 100);
159*c8dee2aaSAndroid Build Coastguard Worker fPts[2].set(150, 50);
160*c8dee2aaSAndroid Build Coastguard Worker fPts[3].set(300, 50);
161*c8dee2aaSAndroid Build Coastguard Worker
162*c8dee2aaSAndroid Build Coastguard Worker fPts[4].set(350, 200); // conic
163*c8dee2aaSAndroid Build Coastguard Worker fPts[5].set(350, 100);
164*c8dee2aaSAndroid Build Coastguard Worker fPts[6].set(450, 50);
165*c8dee2aaSAndroid Build Coastguard Worker
166*c8dee2aaSAndroid Build Coastguard Worker fPts[7].set(150, 300); // quad
167*c8dee2aaSAndroid Build Coastguard Worker fPts[8].set(150, 200);
168*c8dee2aaSAndroid Build Coastguard Worker fPts[9].set(250, 150);
169*c8dee2aaSAndroid Build Coastguard Worker
170*c8dee2aaSAndroid Build Coastguard Worker fPts[10].set(250, 200); // arc
171*c8dee2aaSAndroid Build Coastguard Worker fPts[11].set(250, 300);
172*c8dee2aaSAndroid Build Coastguard Worker fPts[12].set(150, 350);
173*c8dee2aaSAndroid Build Coastguard Worker
174*c8dee2aaSAndroid Build Coastguard Worker fPts[13].set(200, 200); // rrect
175*c8dee2aaSAndroid Build Coastguard Worker fPts[14].set(400, 400);
176*c8dee2aaSAndroid Build Coastguard Worker
177*c8dee2aaSAndroid Build Coastguard Worker fPts[15].set(250, 250); // oval
178*c8dee2aaSAndroid Build Coastguard Worker fPts[16].set(450, 450);
179*c8dee2aaSAndroid Build Coastguard Worker
180*c8dee2aaSAndroid Build Coastguard Worker fText = "a";
181*c8dee2aaSAndroid Build Coastguard Worker fTextSize = 12;
182*c8dee2aaSAndroid Build Coastguard Worker fWidth = 50;
183*c8dee2aaSAndroid Build Coastguard Worker fDWidth = 0.25f;
184*c8dee2aaSAndroid Build Coastguard Worker fWeight = 1;
185*c8dee2aaSAndroid Build Coastguard Worker fRadius = 150;
186*c8dee2aaSAndroid Build Coastguard Worker
187*c8dee2aaSAndroid Build Coastguard Worker fCubicButton.fLabel = 'C';
188*c8dee2aaSAndroid Build Coastguard Worker fCubicButton.fEnabled = false;
189*c8dee2aaSAndroid Build Coastguard Worker fConicButton.fLabel = 'K';
190*c8dee2aaSAndroid Build Coastguard Worker fConicButton.fEnabled = false;
191*c8dee2aaSAndroid Build Coastguard Worker fQuadButton.fLabel = 'Q';
192*c8dee2aaSAndroid Build Coastguard Worker fQuadButton.fEnabled = false;
193*c8dee2aaSAndroid Build Coastguard Worker fArcButton.fLabel = 'A';
194*c8dee2aaSAndroid Build Coastguard Worker fArcButton.fEnabled = true;
195*c8dee2aaSAndroid Build Coastguard Worker fRRectButton.fLabel = 'R';
196*c8dee2aaSAndroid Build Coastguard Worker fRRectButton.fEnabled = false;
197*c8dee2aaSAndroid Build Coastguard Worker fCircleButton.fLabel = 'O';
198*c8dee2aaSAndroid Build Coastguard Worker fCircleButton.fEnabled = true;
199*c8dee2aaSAndroid Build Coastguard Worker fCircleButton.fFill = true;
200*c8dee2aaSAndroid Build Coastguard Worker fTextButton.fLabel = 'T';
201*c8dee2aaSAndroid Build Coastguard Worker fTextButton.fEnabled = false;
202*c8dee2aaSAndroid Build Coastguard Worker fAnimate = false;
203*c8dee2aaSAndroid Build Coastguard Worker setAsNeeded();
204*c8dee2aaSAndroid Build Coastguard Worker fName = "QuadStroker";
205*c8dee2aaSAndroid Build Coastguard Worker }
206*c8dee2aaSAndroid Build Coastguard Worker
onChar(SkUnichar uni)207*c8dee2aaSAndroid Build Coastguard Worker bool onChar(SkUnichar uni) override {
208*c8dee2aaSAndroid Build Coastguard Worker if (fTextButton.fEnabled) {
209*c8dee2aaSAndroid Build Coastguard Worker switch (uni) {
210*c8dee2aaSAndroid Build Coastguard Worker case ' ':
211*c8dee2aaSAndroid Build Coastguard Worker fText = "";
212*c8dee2aaSAndroid Build Coastguard Worker break;
213*c8dee2aaSAndroid Build Coastguard Worker case '-':
214*c8dee2aaSAndroid Build Coastguard Worker fTextSize = std::max(1.0f, fTextSize - 1);
215*c8dee2aaSAndroid Build Coastguard Worker break;
216*c8dee2aaSAndroid Build Coastguard Worker case '+':
217*c8dee2aaSAndroid Build Coastguard Worker case '=':
218*c8dee2aaSAndroid Build Coastguard Worker fTextSize += 1;
219*c8dee2aaSAndroid Build Coastguard Worker break;
220*c8dee2aaSAndroid Build Coastguard Worker default:
221*c8dee2aaSAndroid Build Coastguard Worker fText.appendUnichar(uni);
222*c8dee2aaSAndroid Build Coastguard Worker }
223*c8dee2aaSAndroid Build Coastguard Worker return true;
224*c8dee2aaSAndroid Build Coastguard Worker }
225*c8dee2aaSAndroid Build Coastguard Worker return false;
226*c8dee2aaSAndroid Build Coastguard Worker }
227*c8dee2aaSAndroid Build Coastguard Worker
load(SkScalar w,SkScalar h)228*c8dee2aaSAndroid Build Coastguard Worker void load(SkScalar w, SkScalar h) override { this->layout(w, h); }
229*c8dee2aaSAndroid Build Coastguard Worker
resize(SkScalar w,SkScalar h)230*c8dee2aaSAndroid Build Coastguard Worker void resize(SkScalar w, SkScalar h) override { this->layout(w, h); }
231*c8dee2aaSAndroid Build Coastguard Worker
draw(SkCanvas * canvas)232*c8dee2aaSAndroid Build Coastguard Worker void draw(SkCanvas* canvas) override {
233*c8dee2aaSAndroid Build Coastguard Worker canvas->clear(SK_ColorLTGRAY);
234*c8dee2aaSAndroid Build Coastguard Worker
235*c8dee2aaSAndroid Build Coastguard Worker SkPath path;
236*c8dee2aaSAndroid Build Coastguard Worker SkScalar width = fWidth;
237*c8dee2aaSAndroid Build Coastguard Worker
238*c8dee2aaSAndroid Build Coastguard Worker if (fCubicButton.fEnabled) {
239*c8dee2aaSAndroid Build Coastguard Worker path.moveTo(fPts[0]);
240*c8dee2aaSAndroid Build Coastguard Worker path.cubicTo(fPts[1], fPts[2], fPts[3]);
241*c8dee2aaSAndroid Build Coastguard Worker setForSingles();
242*c8dee2aaSAndroid Build Coastguard Worker draw_stroke(canvas, path, width, 950, false);
243*c8dee2aaSAndroid Build Coastguard Worker }
244*c8dee2aaSAndroid Build Coastguard Worker
245*c8dee2aaSAndroid Build Coastguard Worker if (fConicButton.fEnabled) {
246*c8dee2aaSAndroid Build Coastguard Worker path.reset();
247*c8dee2aaSAndroid Build Coastguard Worker path.moveTo(fPts[4]);
248*c8dee2aaSAndroid Build Coastguard Worker path.conicTo(fPts[5], fPts[6], fWeight);
249*c8dee2aaSAndroid Build Coastguard Worker setForSingles();
250*c8dee2aaSAndroid Build Coastguard Worker draw_stroke(canvas, path, width, 950, false);
251*c8dee2aaSAndroid Build Coastguard Worker }
252*c8dee2aaSAndroid Build Coastguard Worker
253*c8dee2aaSAndroid Build Coastguard Worker if (fQuadButton.fEnabled) {
254*c8dee2aaSAndroid Build Coastguard Worker path.reset();
255*c8dee2aaSAndroid Build Coastguard Worker path.moveTo(fPts[7]);
256*c8dee2aaSAndroid Build Coastguard Worker path.quadTo(fPts[8], fPts[9]);
257*c8dee2aaSAndroid Build Coastguard Worker setForSingles();
258*c8dee2aaSAndroid Build Coastguard Worker draw_stroke(canvas, path, width, 950, false);
259*c8dee2aaSAndroid Build Coastguard Worker }
260*c8dee2aaSAndroid Build Coastguard Worker
261*c8dee2aaSAndroid Build Coastguard Worker if (fArcButton.fEnabled) {
262*c8dee2aaSAndroid Build Coastguard Worker path.reset();
263*c8dee2aaSAndroid Build Coastguard Worker path.moveTo(fPts[10]);
264*c8dee2aaSAndroid Build Coastguard Worker path.arcTo(fPts[11], fPts[12], fRadius);
265*c8dee2aaSAndroid Build Coastguard Worker setForGeometry();
266*c8dee2aaSAndroid Build Coastguard Worker draw_stroke(canvas, path, width, 950, false);
267*c8dee2aaSAndroid Build Coastguard Worker SkPath pathPts;
268*c8dee2aaSAndroid Build Coastguard Worker pathPts.moveTo(fPts[10]);
269*c8dee2aaSAndroid Build Coastguard Worker pathPts.lineTo(fPts[11]);
270*c8dee2aaSAndroid Build Coastguard Worker pathPts.lineTo(fPts[12]);
271*c8dee2aaSAndroid Build Coastguard Worker draw_points(canvas, pathPts, SK_ColorDKGRAY, true);
272*c8dee2aaSAndroid Build Coastguard Worker }
273*c8dee2aaSAndroid Build Coastguard Worker
274*c8dee2aaSAndroid Build Coastguard Worker if (fRRectButton.fEnabled) {
275*c8dee2aaSAndroid Build Coastguard Worker SkScalar rad = 32;
276*c8dee2aaSAndroid Build Coastguard Worker SkRect r;
277*c8dee2aaSAndroid Build Coastguard Worker r.setBounds(&fPts[13], 2);
278*c8dee2aaSAndroid Build Coastguard Worker path.reset();
279*c8dee2aaSAndroid Build Coastguard Worker SkRRect rr;
280*c8dee2aaSAndroid Build Coastguard Worker rr.setRectXY(r, rad, rad);
281*c8dee2aaSAndroid Build Coastguard Worker path.addRRect(rr);
282*c8dee2aaSAndroid Build Coastguard Worker setForGeometry();
283*c8dee2aaSAndroid Build Coastguard Worker draw_stroke(canvas, path, width, 950, false);
284*c8dee2aaSAndroid Build Coastguard Worker
285*c8dee2aaSAndroid Build Coastguard Worker path.reset();
286*c8dee2aaSAndroid Build Coastguard Worker SkRRect rr2;
287*c8dee2aaSAndroid Build Coastguard Worker rr.inset(width/2, width/2, &rr2);
288*c8dee2aaSAndroid Build Coastguard Worker path.addRRect(rr2, SkPathDirection::kCCW);
289*c8dee2aaSAndroid Build Coastguard Worker rr.inset(-width/2, -width/2, &rr2);
290*c8dee2aaSAndroid Build Coastguard Worker path.addRRect(rr2, SkPathDirection::kCW);
291*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
292*c8dee2aaSAndroid Build Coastguard Worker paint.setAntiAlias(true);
293*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(0x40FF8844);
294*c8dee2aaSAndroid Build Coastguard Worker canvas->drawPath(path, paint);
295*c8dee2aaSAndroid Build Coastguard Worker }
296*c8dee2aaSAndroid Build Coastguard Worker
297*c8dee2aaSAndroid Build Coastguard Worker if (fCircleButton.fEnabled) {
298*c8dee2aaSAndroid Build Coastguard Worker path.reset();
299*c8dee2aaSAndroid Build Coastguard Worker SkRect r;
300*c8dee2aaSAndroid Build Coastguard Worker r.setBounds(&fPts[15], 2);
301*c8dee2aaSAndroid Build Coastguard Worker path.addOval(r);
302*c8dee2aaSAndroid Build Coastguard Worker setForGeometry();
303*c8dee2aaSAndroid Build Coastguard Worker if (fCircleButton.fFill) {
304*c8dee2aaSAndroid Build Coastguard Worker if (fArcButton.fEnabled) {
305*c8dee2aaSAndroid Build Coastguard Worker SkPoint center;
306*c8dee2aaSAndroid Build Coastguard Worker if (arcCenter(¢er)) {
307*c8dee2aaSAndroid Build Coastguard Worker r.setLTRB(center.fX - fRadius, center.fY - fRadius,
308*c8dee2aaSAndroid Build Coastguard Worker center.fX + fRadius, center.fY + fRadius);
309*c8dee2aaSAndroid Build Coastguard Worker }
310*c8dee2aaSAndroid Build Coastguard Worker }
311*c8dee2aaSAndroid Build Coastguard Worker draw_fill(canvas, r, width);
312*c8dee2aaSAndroid Build Coastguard Worker } else {
313*c8dee2aaSAndroid Build Coastguard Worker draw_stroke(canvas, path, width, 950, false);
314*c8dee2aaSAndroid Build Coastguard Worker }
315*c8dee2aaSAndroid Build Coastguard Worker }
316*c8dee2aaSAndroid Build Coastguard Worker
317*c8dee2aaSAndroid Build Coastguard Worker if (fTextButton.fEnabled) {
318*c8dee2aaSAndroid Build Coastguard Worker path.reset();
319*c8dee2aaSAndroid Build Coastguard Worker SkFont font = ToolUtils::DefaultFont();
320*c8dee2aaSAndroid Build Coastguard Worker font.setSize(fTextSize);
321*c8dee2aaSAndroid Build Coastguard Worker SkTextUtils::GetPath(fText.c_str(), fText.size(), SkTextEncoding::kUTF8,
322*c8dee2aaSAndroid Build Coastguard Worker 0, fTextSize, font, &path);
323*c8dee2aaSAndroid Build Coastguard Worker setForText();
324*c8dee2aaSAndroid Build Coastguard Worker draw_stroke(canvas, path, width * fWidthScale / fTextSize, fTextSize, true);
325*c8dee2aaSAndroid Build Coastguard Worker }
326*c8dee2aaSAndroid Build Coastguard Worker
327*c8dee2aaSAndroid Build Coastguard Worker if (fAnimate) {
328*c8dee2aaSAndroid Build Coastguard Worker fWidth += fDWidth;
329*c8dee2aaSAndroid Build Coastguard Worker if (fDWidth > 0 && fWidth > kWidthMax) {
330*c8dee2aaSAndroid Build Coastguard Worker fDWidth = -fDWidth;
331*c8dee2aaSAndroid Build Coastguard Worker } else if (fDWidth < 0 && fWidth < kWidthMin) {
332*c8dee2aaSAndroid Build Coastguard Worker fDWidth = -fDWidth;
333*c8dee2aaSAndroid Build Coastguard Worker }
334*c8dee2aaSAndroid Build Coastguard Worker }
335*c8dee2aaSAndroid Build Coastguard Worker setAsNeeded();
336*c8dee2aaSAndroid Build Coastguard Worker if (fConicButton.fEnabled) {
337*c8dee2aaSAndroid Build Coastguard Worker draw_control(canvas, fWeightControl, fWeight, 0, 5, "weight");
338*c8dee2aaSAndroid Build Coastguard Worker }
339*c8dee2aaSAndroid Build Coastguard Worker if (fArcButton.fEnabled) {
340*c8dee2aaSAndroid Build Coastguard Worker draw_control(canvas, fRadiusControl, fRadius, 0, 500, "radius");
341*c8dee2aaSAndroid Build Coastguard Worker }
342*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
343*c8dee2aaSAndroid Build Coastguard Worker draw_control(canvas, fErrorControl, gDebugStrokerError, kStrokerErrorMin, kStrokerErrorMax,
344*c8dee2aaSAndroid Build Coastguard Worker "error");
345*c8dee2aaSAndroid Build Coastguard Worker #endif
346*c8dee2aaSAndroid Build Coastguard Worker draw_control(canvas, fWidthControl, fWidth * fWidthScale, kWidthMin * fWidthScale,
347*c8dee2aaSAndroid Build Coastguard Worker kWidthMax * fWidthScale, "width");
348*c8dee2aaSAndroid Build Coastguard Worker draw_button(canvas, fQuadButton);
349*c8dee2aaSAndroid Build Coastguard Worker draw_button(canvas, fCubicButton);
350*c8dee2aaSAndroid Build Coastguard Worker draw_button(canvas, fConicButton);
351*c8dee2aaSAndroid Build Coastguard Worker draw_button(canvas, fArcButton);
352*c8dee2aaSAndroid Build Coastguard Worker draw_button(canvas, fRRectButton);
353*c8dee2aaSAndroid Build Coastguard Worker draw_button(canvas, fCircleButton);
354*c8dee2aaSAndroid Build Coastguard Worker draw_button(canvas, fTextButton);
355*c8dee2aaSAndroid Build Coastguard Worker }
356*c8dee2aaSAndroid Build Coastguard Worker protected:
357*c8dee2aaSAndroid Build Coastguard Worker class MyClick : public Click {
358*c8dee2aaSAndroid Build Coastguard Worker public:
359*c8dee2aaSAndroid Build Coastguard Worker int fIndex;
MyClick(int index)360*c8dee2aaSAndroid Build Coastguard Worker MyClick(int index) : fIndex(index) {}
361*c8dee2aaSAndroid Build Coastguard Worker };
362*c8dee2aaSAndroid Build Coastguard Worker
onFindClickHandler(SkScalar x,SkScalar y,skui::ModifierKey modi)363*c8dee2aaSAndroid Build Coastguard Worker Click* onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey modi) override {
364*c8dee2aaSAndroid Build Coastguard Worker for (size_t i = 0; i < std::size(fPts); ++i) {
365*c8dee2aaSAndroid Build Coastguard Worker if (hittest(fPts[i], x, y)) {
366*c8dee2aaSAndroid Build Coastguard Worker return new MyClick((int)i);
367*c8dee2aaSAndroid Build Coastguard Worker }
368*c8dee2aaSAndroid Build Coastguard Worker }
369*c8dee2aaSAndroid Build Coastguard Worker const SkRect& rectPt = SkRect::MakeXYWH(x, y, 1, 1);
370*c8dee2aaSAndroid Build Coastguard Worker if (fWeightControl.contains(rectPt)) {
371*c8dee2aaSAndroid Build Coastguard Worker return new MyClick((int) std::size(fPts) + 1);
372*c8dee2aaSAndroid Build Coastguard Worker }
373*c8dee2aaSAndroid Build Coastguard Worker if (fRadiusControl.contains(rectPt)) {
374*c8dee2aaSAndroid Build Coastguard Worker return new MyClick((int) std::size(fPts) + 2);
375*c8dee2aaSAndroid Build Coastguard Worker }
376*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
377*c8dee2aaSAndroid Build Coastguard Worker if (fErrorControl.contains(rectPt)) {
378*c8dee2aaSAndroid Build Coastguard Worker return new MyClick((int) std::size(fPts) + 3);
379*c8dee2aaSAndroid Build Coastguard Worker }
380*c8dee2aaSAndroid Build Coastguard Worker #endif
381*c8dee2aaSAndroid Build Coastguard Worker if (fWidthControl.contains(rectPt)) {
382*c8dee2aaSAndroid Build Coastguard Worker return new MyClick((int) std::size(fPts) + 4);
383*c8dee2aaSAndroid Build Coastguard Worker }
384*c8dee2aaSAndroid Build Coastguard Worker if (fCubicButton.fBounds.contains(rectPt)) {
385*c8dee2aaSAndroid Build Coastguard Worker fCubicButton.fEnabled ^= true;
386*c8dee2aaSAndroid Build Coastguard Worker return new MyClick((int) std::size(fPts) + 5);
387*c8dee2aaSAndroid Build Coastguard Worker }
388*c8dee2aaSAndroid Build Coastguard Worker if (fConicButton.fBounds.contains(rectPt)) {
389*c8dee2aaSAndroid Build Coastguard Worker fConicButton.fEnabled ^= true;
390*c8dee2aaSAndroid Build Coastguard Worker return new MyClick((int) std::size(fPts) + 6);
391*c8dee2aaSAndroid Build Coastguard Worker }
392*c8dee2aaSAndroid Build Coastguard Worker if (fQuadButton.fBounds.contains(rectPt)) {
393*c8dee2aaSAndroid Build Coastguard Worker fQuadButton.fEnabled ^= true;
394*c8dee2aaSAndroid Build Coastguard Worker return new MyClick((int) std::size(fPts) + 7);
395*c8dee2aaSAndroid Build Coastguard Worker }
396*c8dee2aaSAndroid Build Coastguard Worker if (fArcButton.fBounds.contains(rectPt)) {
397*c8dee2aaSAndroid Build Coastguard Worker fArcButton.fEnabled ^= true;
398*c8dee2aaSAndroid Build Coastguard Worker return new MyClick((int) std::size(fPts) + 8);
399*c8dee2aaSAndroid Build Coastguard Worker }
400*c8dee2aaSAndroid Build Coastguard Worker if (fRRectButton.fBounds.contains(rectPt)) {
401*c8dee2aaSAndroid Build Coastguard Worker fRRectButton.fEnabled ^= true;
402*c8dee2aaSAndroid Build Coastguard Worker return new MyClick((int) std::size(fPts) + 9);
403*c8dee2aaSAndroid Build Coastguard Worker }
404*c8dee2aaSAndroid Build Coastguard Worker if (fCircleButton.fBounds.contains(rectPt)) {
405*c8dee2aaSAndroid Build Coastguard Worker bool wasEnabled = fCircleButton.fEnabled;
406*c8dee2aaSAndroid Build Coastguard Worker fCircleButton.fEnabled = !fCircleButton.fFill;
407*c8dee2aaSAndroid Build Coastguard Worker fCircleButton.fFill = wasEnabled && !fCircleButton.fFill;
408*c8dee2aaSAndroid Build Coastguard Worker return new MyClick((int) std::size(fPts) + 10);
409*c8dee2aaSAndroid Build Coastguard Worker }
410*c8dee2aaSAndroid Build Coastguard Worker if (fTextButton.fBounds.contains(rectPt)) {
411*c8dee2aaSAndroid Build Coastguard Worker fTextButton.fEnabled ^= true;
412*c8dee2aaSAndroid Build Coastguard Worker return new MyClick((int) std::size(fPts) + 11);
413*c8dee2aaSAndroid Build Coastguard Worker }
414*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
415*c8dee2aaSAndroid Build Coastguard Worker }
416*c8dee2aaSAndroid Build Coastguard Worker
onClick(Click * click)417*c8dee2aaSAndroid Build Coastguard Worker bool onClick(Click* click) override {
418*c8dee2aaSAndroid Build Coastguard Worker int index = ((MyClick*)click)->fIndex;
419*c8dee2aaSAndroid Build Coastguard Worker if (index < (int) std::size(fPts)) {
420*c8dee2aaSAndroid Build Coastguard Worker fPts[index].offset(click->fCurr.fX - click->fPrev.fX,
421*c8dee2aaSAndroid Build Coastguard Worker click->fCurr.fY - click->fPrev.fY);
422*c8dee2aaSAndroid Build Coastguard Worker } else if (index == (int) std::size(fPts) + 1) {
423*c8dee2aaSAndroid Build Coastguard Worker fWeight = MapScreenYtoValue(click->fCurr.fY, fWeightControl, 0, 5);
424*c8dee2aaSAndroid Build Coastguard Worker } else if (index == (int) std::size(fPts) + 2) {
425*c8dee2aaSAndroid Build Coastguard Worker fRadius = MapScreenYtoValue(click->fCurr.fY, fRadiusControl, 0, 500);
426*c8dee2aaSAndroid Build Coastguard Worker }
427*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
428*c8dee2aaSAndroid Build Coastguard Worker else if (index == (int) std::size(fPts) + 3) {
429*c8dee2aaSAndroid Build Coastguard Worker gDebugStrokerError = std::max(FLT_EPSILON, MapScreenYtoValue(click->fCurr.fY,
430*c8dee2aaSAndroid Build Coastguard Worker fErrorControl, kStrokerErrorMin, kStrokerErrorMax));
431*c8dee2aaSAndroid Build Coastguard Worker gDebugStrokerErrorSet = true;
432*c8dee2aaSAndroid Build Coastguard Worker }
433*c8dee2aaSAndroid Build Coastguard Worker #endif
434*c8dee2aaSAndroid Build Coastguard Worker else if (index == (int) std::size(fPts) + 4) {
435*c8dee2aaSAndroid Build Coastguard Worker fWidth = std::max(FLT_EPSILON, MapScreenYtoValue(click->fCurr.fY, fWidthControl,
436*c8dee2aaSAndroid Build Coastguard Worker kWidthMin, kWidthMax));
437*c8dee2aaSAndroid Build Coastguard Worker fAnimate = fWidth <= kWidthMin;
438*c8dee2aaSAndroid Build Coastguard Worker }
439*c8dee2aaSAndroid Build Coastguard Worker return true;
440*c8dee2aaSAndroid Build Coastguard Worker }
441*c8dee2aaSAndroid Build Coastguard Worker
442*c8dee2aaSAndroid Build Coastguard Worker private:
layout(SkScalar w,SkScalar h)443*c8dee2aaSAndroid Build Coastguard Worker void layout(SkScalar w, SkScalar h) {
444*c8dee2aaSAndroid Build Coastguard Worker fRadiusControl.setXYWH(w - 200, 30, 30, 400);
445*c8dee2aaSAndroid Build Coastguard Worker fWeightControl.setXYWH(w - 150, 30, 30, 400);
446*c8dee2aaSAndroid Build Coastguard Worker fErrorControl.setXYWH(w - 100, 30, 30, 400);
447*c8dee2aaSAndroid Build Coastguard Worker fWidthControl.setXYWH(w - 50, 30, 30, 400);
448*c8dee2aaSAndroid Build Coastguard Worker int buttonOffset = 450;
449*c8dee2aaSAndroid Build Coastguard Worker fCubicButton.fBounds.setXYWH(w - 50, SkIntToScalar(buttonOffset), 30, 30);
450*c8dee2aaSAndroid Build Coastguard Worker buttonOffset += 50;
451*c8dee2aaSAndroid Build Coastguard Worker fConicButton.fBounds.setXYWH(w - 50, SkIntToScalar(buttonOffset), 30, 30);
452*c8dee2aaSAndroid Build Coastguard Worker buttonOffset += 50;
453*c8dee2aaSAndroid Build Coastguard Worker fQuadButton.fBounds.setXYWH(w - 50, SkIntToScalar(buttonOffset), 30, 30);
454*c8dee2aaSAndroid Build Coastguard Worker buttonOffset += 50;
455*c8dee2aaSAndroid Build Coastguard Worker fArcButton.fBounds.setXYWH(w - 50, SkIntToScalar(buttonOffset), 30, 30);
456*c8dee2aaSAndroid Build Coastguard Worker buttonOffset += 50;
457*c8dee2aaSAndroid Build Coastguard Worker fRRectButton.fBounds.setXYWH(w - 50, SkIntToScalar(buttonOffset), 30, 30);
458*c8dee2aaSAndroid Build Coastguard Worker buttonOffset += 50;
459*c8dee2aaSAndroid Build Coastguard Worker fCircleButton.fBounds.setXYWH(w - 50, SkIntToScalar(buttonOffset), 30, 30);
460*c8dee2aaSAndroid Build Coastguard Worker buttonOffset += 50;
461*c8dee2aaSAndroid Build Coastguard Worker fTextButton.fBounds.setXYWH(w - 50, SkIntToScalar(buttonOffset), 30, 30);
462*c8dee2aaSAndroid Build Coastguard Worker }
463*c8dee2aaSAndroid Build Coastguard Worker
copyMinToMax()464*c8dee2aaSAndroid Build Coastguard Worker void copyMinToMax() {
465*c8dee2aaSAndroid Build Coastguard Worker erase(fMaxSurface);
466*c8dee2aaSAndroid Build Coastguard Worker SkCanvas* canvas = fMaxSurface->getCanvas();
467*c8dee2aaSAndroid Build Coastguard Worker canvas->save();
468*c8dee2aaSAndroid Build Coastguard Worker canvas->concat(fMatrix);
469*c8dee2aaSAndroid Build Coastguard Worker fMinSurface->draw(canvas, 0, 0);
470*c8dee2aaSAndroid Build Coastguard Worker canvas->restore();
471*c8dee2aaSAndroid Build Coastguard Worker
472*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
473*c8dee2aaSAndroid Build Coastguard Worker paint.setBlendMode(SkBlendMode::kClear);
474*c8dee2aaSAndroid Build Coastguard Worker for (int iy = 1; iy < fH; ++iy) {
475*c8dee2aaSAndroid Build Coastguard Worker SkScalar y = SkIntToScalar(iy * fZoom);
476*c8dee2aaSAndroid Build Coastguard Worker canvas->drawLine(0, y - SK_ScalarHalf, 999, y - SK_ScalarHalf, paint);
477*c8dee2aaSAndroid Build Coastguard Worker }
478*c8dee2aaSAndroid Build Coastguard Worker for (int ix = 1; ix < fW; ++ix) {
479*c8dee2aaSAndroid Build Coastguard Worker SkScalar x = SkIntToScalar(ix * fZoom);
480*c8dee2aaSAndroid Build Coastguard Worker canvas->drawLine(x - SK_ScalarHalf, 0, x - SK_ScalarHalf, 999, paint);
481*c8dee2aaSAndroid Build Coastguard Worker }
482*c8dee2aaSAndroid Build Coastguard Worker }
483*c8dee2aaSAndroid Build Coastguard Worker
setWHZ(int width,int height,int zoom)484*c8dee2aaSAndroid Build Coastguard Worker void setWHZ(int width, int height, int zoom) {
485*c8dee2aaSAndroid Build Coastguard Worker fZoom = zoom;
486*c8dee2aaSAndroid Build Coastguard Worker fBounds.setIWH(width * zoom, height * zoom);
487*c8dee2aaSAndroid Build Coastguard Worker fMatrix.setScale(SkIntToScalar(zoom), SkIntToScalar(zoom));
488*c8dee2aaSAndroid Build Coastguard Worker fInverse.setScale(SK_Scalar1 / zoom, SK_Scalar1 / zoom);
489*c8dee2aaSAndroid Build Coastguard Worker fShader = ToolUtils::create_checkerboard_shader(0xFFCCCCCC, 0xFFFFFFFF, zoom);
490*c8dee2aaSAndroid Build Coastguard Worker
491*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
492*c8dee2aaSAndroid Build Coastguard Worker fMinSurface = SkSurfaces::Raster(info);
493*c8dee2aaSAndroid Build Coastguard Worker info = info.makeWH(width * zoom, height * zoom);
494*c8dee2aaSAndroid Build Coastguard Worker fMaxSurface = SkSurfaces::Raster(info);
495*c8dee2aaSAndroid Build Coastguard Worker }
496*c8dee2aaSAndroid Build Coastguard Worker
draw_points(SkCanvas * canvas,const SkPath & path,SkColor color,bool show_lines)497*c8dee2aaSAndroid Build Coastguard Worker void draw_points(SkCanvas* canvas, const SkPath& path, SkColor color,
498*c8dee2aaSAndroid Build Coastguard Worker bool show_lines) {
499*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
500*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(color);
501*c8dee2aaSAndroid Build Coastguard Worker paint.setAlpha(0x80);
502*c8dee2aaSAndroid Build Coastguard Worker paint.setAntiAlias(true);
503*c8dee2aaSAndroid Build Coastguard Worker int n = path.countPoints();
504*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkPoint[]> pts{new SkPoint[n]};
505*c8dee2aaSAndroid Build Coastguard Worker if (show_lines && fDrawTangents) {
506*c8dee2aaSAndroid Build Coastguard Worker TArray<int> contourCounts;
507*c8dee2aaSAndroid Build Coastguard Worker getContourCounts(path, &contourCounts);
508*c8dee2aaSAndroid Build Coastguard Worker SkPoint* ptPtr = pts.get();
509*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < contourCounts.size(); ++i) {
510*c8dee2aaSAndroid Build Coastguard Worker int count = contourCounts[i];
511*c8dee2aaSAndroid Build Coastguard Worker path.getPoints(ptPtr, count);
512*c8dee2aaSAndroid Build Coastguard Worker canvas->drawPoints(SkCanvas::kPolygon_PointMode, count, ptPtr, paint);
513*c8dee2aaSAndroid Build Coastguard Worker ptPtr += count;
514*c8dee2aaSAndroid Build Coastguard Worker }
515*c8dee2aaSAndroid Build Coastguard Worker } else {
516*c8dee2aaSAndroid Build Coastguard Worker n = getOnCurvePoints(path, pts.get());
517*c8dee2aaSAndroid Build Coastguard Worker }
518*c8dee2aaSAndroid Build Coastguard Worker paint.setStrokeWidth(5);
519*c8dee2aaSAndroid Build Coastguard Worker canvas->drawPoints(SkCanvas::kPoints_PointMode, n, pts.get(), paint);
520*c8dee2aaSAndroid Build Coastguard Worker }
521*c8dee2aaSAndroid Build Coastguard Worker
draw_ribs(SkCanvas * canvas,const SkPath & path,SkScalar width,SkColor color)522*c8dee2aaSAndroid Build Coastguard Worker void draw_ribs(SkCanvas* canvas, const SkPath& path, SkScalar width,
523*c8dee2aaSAndroid Build Coastguard Worker SkColor color) {
524*c8dee2aaSAndroid Build Coastguard Worker const SkScalar radius = width / 2;
525*c8dee2aaSAndroid Build Coastguard Worker
526*c8dee2aaSAndroid Build Coastguard Worker SkPathMeasure meas(path, false);
527*c8dee2aaSAndroid Build Coastguard Worker SkScalar total = meas.getLength();
528*c8dee2aaSAndroid Build Coastguard Worker
529*c8dee2aaSAndroid Build Coastguard Worker SkScalar delta = 8;
530*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint, labelP;
531*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(color);
532*c8dee2aaSAndroid Build Coastguard Worker labelP.setColor(color & 0xff5f9f5f);
533*c8dee2aaSAndroid Build Coastguard Worker SkFont font = ToolUtils::DefaultFont();
534*c8dee2aaSAndroid Build Coastguard Worker SkPoint pos, tan;
535*c8dee2aaSAndroid Build Coastguard Worker int index = 0;
536*c8dee2aaSAndroid Build Coastguard Worker for (SkScalar dist = 0; dist <= total; dist += delta) {
537*c8dee2aaSAndroid Build Coastguard Worker if (meas.getPosTan(dist, &pos, &tan)) {
538*c8dee2aaSAndroid Build Coastguard Worker tan.scale(radius);
539*c8dee2aaSAndroid Build Coastguard Worker SkPointPriv::RotateCCW(&tan);
540*c8dee2aaSAndroid Build Coastguard Worker canvas->drawLine(pos.x() + tan.x(), pos.y() + tan.y(),
541*c8dee2aaSAndroid Build Coastguard Worker pos.x() - tan.x(), pos.y() - tan.y(), paint);
542*c8dee2aaSAndroid Build Coastguard Worker if (0 == index % 10) {
543*c8dee2aaSAndroid Build Coastguard Worker SkString label;
544*c8dee2aaSAndroid Build Coastguard Worker label.appendS32(index);
545*c8dee2aaSAndroid Build Coastguard Worker SkRect dot = SkRect::MakeXYWH(pos.x() - 2, pos.y() - 2, 4, 4);
546*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(dot, labelP);
547*c8dee2aaSAndroid Build Coastguard Worker canvas->drawString(label,
548*c8dee2aaSAndroid Build Coastguard Worker pos.x() - tan.x() * 1.25f, pos.y() - tan.y() * 1.25f, font, labelP);
549*c8dee2aaSAndroid Build Coastguard Worker }
550*c8dee2aaSAndroid Build Coastguard Worker }
551*c8dee2aaSAndroid Build Coastguard Worker ++index;
552*c8dee2aaSAndroid Build Coastguard Worker }
553*c8dee2aaSAndroid Build Coastguard Worker }
554*c8dee2aaSAndroid Build Coastguard Worker
draw_t_divs(SkCanvas * canvas,const SkPath & path,SkScalar width,SkColor color)555*c8dee2aaSAndroid Build Coastguard Worker void draw_t_divs(SkCanvas* canvas, const SkPath& path, SkScalar width, SkColor color) {
556*c8dee2aaSAndroid Build Coastguard Worker const SkScalar radius = width / 2;
557*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
558*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(color);
559*c8dee2aaSAndroid Build Coastguard Worker SkPathMeasure meas(path, false);
560*c8dee2aaSAndroid Build Coastguard Worker SkScalar total = meas.getLength();
561*c8dee2aaSAndroid Build Coastguard Worker SkScalar delta = 8;
562*c8dee2aaSAndroid Build Coastguard Worker int ribs = 0;
563*c8dee2aaSAndroid Build Coastguard Worker for (SkScalar dist = 0; dist <= total; dist += delta) {
564*c8dee2aaSAndroid Build Coastguard Worker ++ribs;
565*c8dee2aaSAndroid Build Coastguard Worker }
566*c8dee2aaSAndroid Build Coastguard Worker const uint8_t* verbs = SkPathPriv::VerbData(path);
567*c8dee2aaSAndroid Build Coastguard Worker if (path.countVerbs() < 2 || SkPath::kMove_Verb != verbs[0]) {
568*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(0);
569*c8dee2aaSAndroid Build Coastguard Worker return;
570*c8dee2aaSAndroid Build Coastguard Worker }
571*c8dee2aaSAndroid Build Coastguard Worker auto verb = static_cast<SkPath::Verb>(verbs[1]);
572*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(SkPath::kLine_Verb <= verb && verb <= SkPath::kCubic_Verb);
573*c8dee2aaSAndroid Build Coastguard Worker const SkPoint* pts = SkPathPriv::PointData(path);
574*c8dee2aaSAndroid Build Coastguard Worker SkPoint pos, tan;
575*c8dee2aaSAndroid Build Coastguard Worker for (int index = 0; index < ribs; ++index) {
576*c8dee2aaSAndroid Build Coastguard Worker SkScalar t = (SkScalar) index / ribs;
577*c8dee2aaSAndroid Build Coastguard Worker switch (verb) {
578*c8dee2aaSAndroid Build Coastguard Worker case SkPath::kLine_Verb:
579*c8dee2aaSAndroid Build Coastguard Worker tan = pts[1] - pts[0];
580*c8dee2aaSAndroid Build Coastguard Worker pos = pts[0];
581*c8dee2aaSAndroid Build Coastguard Worker pos.fX += tan.fX * t;
582*c8dee2aaSAndroid Build Coastguard Worker pos.fY += tan.fY * t;
583*c8dee2aaSAndroid Build Coastguard Worker break;
584*c8dee2aaSAndroid Build Coastguard Worker case SkPath::kQuad_Verb:
585*c8dee2aaSAndroid Build Coastguard Worker pos = SkEvalQuadAt(pts, t);
586*c8dee2aaSAndroid Build Coastguard Worker tan = SkEvalQuadTangentAt(pts, t);
587*c8dee2aaSAndroid Build Coastguard Worker break;
588*c8dee2aaSAndroid Build Coastguard Worker case SkPath::kConic_Verb: {
589*c8dee2aaSAndroid Build Coastguard Worker SkConic conic(pts, SkPathPriv::ConicWeightData(path)[0]);
590*c8dee2aaSAndroid Build Coastguard Worker pos = conic.evalAt(t);
591*c8dee2aaSAndroid Build Coastguard Worker tan = conic.evalTangentAt(t);
592*c8dee2aaSAndroid Build Coastguard Worker } break;
593*c8dee2aaSAndroid Build Coastguard Worker case SkPath::kCubic_Verb:
594*c8dee2aaSAndroid Build Coastguard Worker SkEvalCubicAt(pts, t, &pos, &tan, nullptr);
595*c8dee2aaSAndroid Build Coastguard Worker break;
596*c8dee2aaSAndroid Build Coastguard Worker default:
597*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(0);
598*c8dee2aaSAndroid Build Coastguard Worker return;
599*c8dee2aaSAndroid Build Coastguard Worker }
600*c8dee2aaSAndroid Build Coastguard Worker tan.setLength(radius);
601*c8dee2aaSAndroid Build Coastguard Worker SkPointPriv::RotateCCW(&tan);
602*c8dee2aaSAndroid Build Coastguard Worker canvas->drawLine(pos.x() + tan.x(), pos.y() + tan.y(),
603*c8dee2aaSAndroid Build Coastguard Worker pos.x() - tan.x(), pos.y() - tan.y(), paint);
604*c8dee2aaSAndroid Build Coastguard Worker if (0 == index % 10) {
605*c8dee2aaSAndroid Build Coastguard Worker SkString label;
606*c8dee2aaSAndroid Build Coastguard Worker label.appendS32(index);
607*c8dee2aaSAndroid Build Coastguard Worker canvas->drawString(label,
608*c8dee2aaSAndroid Build Coastguard Worker pos.x() + tan.x() * 1.25f,
609*c8dee2aaSAndroid Build Coastguard Worker pos.y() + tan.y() * 1.25f,
610*c8dee2aaSAndroid Build Coastguard Worker ToolUtils::DefaultFont(),
611*c8dee2aaSAndroid Build Coastguard Worker paint);
612*c8dee2aaSAndroid Build Coastguard Worker }
613*c8dee2aaSAndroid Build Coastguard Worker }
614*c8dee2aaSAndroid Build Coastguard Worker }
615*c8dee2aaSAndroid Build Coastguard Worker
draw_stroke(SkCanvas * canvas,const SkPath & path,SkScalar width,SkScalar scale,bool drawText)616*c8dee2aaSAndroid Build Coastguard Worker void draw_stroke(SkCanvas* canvas, const SkPath& path, SkScalar width, SkScalar scale,
617*c8dee2aaSAndroid Build Coastguard Worker bool drawText) {
618*c8dee2aaSAndroid Build Coastguard Worker if (path.isEmpty()) {
619*c8dee2aaSAndroid Build Coastguard Worker return;
620*c8dee2aaSAndroid Build Coastguard Worker }
621*c8dee2aaSAndroid Build Coastguard Worker SkRect bounds = path.getBounds();
622*c8dee2aaSAndroid Build Coastguard Worker this->setWHZ(SkScalarCeilToInt(bounds.right()), drawText
623*c8dee2aaSAndroid Build Coastguard Worker ? SkScalarRoundToInt(scale * 3 / 2) : SkScalarRoundToInt(scale),
624*c8dee2aaSAndroid Build Coastguard Worker SkScalarRoundToInt(950.0f / scale));
625*c8dee2aaSAndroid Build Coastguard Worker erase(fMinSurface);
626*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
627*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(0x1f1f0f0f);
628*c8dee2aaSAndroid Build Coastguard Worker paint.setStyle(SkPaint::kStroke_Style);
629*c8dee2aaSAndroid Build Coastguard Worker paint.setStrokeWidth(width * scale * scale);
630*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(0x3f0f1f3f);
631*c8dee2aaSAndroid Build Coastguard Worker if (drawText) {
632*c8dee2aaSAndroid Build Coastguard Worker fMinSurface->getCanvas()->drawPath(path, paint);
633*c8dee2aaSAndroid Build Coastguard Worker this->copyMinToMax();
634*c8dee2aaSAndroid Build Coastguard Worker fMaxSurface->draw(canvas, 0, 0);
635*c8dee2aaSAndroid Build Coastguard Worker }
636*c8dee2aaSAndroid Build Coastguard Worker paint.setAntiAlias(true);
637*c8dee2aaSAndroid Build Coastguard Worker paint.setStyle(SkPaint::kStroke_Style);
638*c8dee2aaSAndroid Build Coastguard Worker paint.setStrokeWidth(1);
639*c8dee2aaSAndroid Build Coastguard Worker
640*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(SKELETON_COLOR);
641*c8dee2aaSAndroid Build Coastguard Worker SkPath scaled;
642*c8dee2aaSAndroid Build Coastguard Worker SkMatrix matrix;
643*c8dee2aaSAndroid Build Coastguard Worker matrix.reset();
644*c8dee2aaSAndroid Build Coastguard Worker matrix.setScale(950 / scale, 950 / scale);
645*c8dee2aaSAndroid Build Coastguard Worker if (drawText) {
646*c8dee2aaSAndroid Build Coastguard Worker path.transform(matrix, &scaled);
647*c8dee2aaSAndroid Build Coastguard Worker } else {
648*c8dee2aaSAndroid Build Coastguard Worker scaled = path;
649*c8dee2aaSAndroid Build Coastguard Worker }
650*c8dee2aaSAndroid Build Coastguard Worker canvas->drawPath(scaled, paint);
651*c8dee2aaSAndroid Build Coastguard Worker draw_points(canvas, scaled, SKELETON_COLOR, true);
652*c8dee2aaSAndroid Build Coastguard Worker
653*c8dee2aaSAndroid Build Coastguard Worker if (fDrawRibs) {
654*c8dee2aaSAndroid Build Coastguard Worker draw_ribs(canvas, scaled, width, 0xFF00FF00);
655*c8dee2aaSAndroid Build Coastguard Worker }
656*c8dee2aaSAndroid Build Coastguard Worker
657*c8dee2aaSAndroid Build Coastguard Worker if (fDrawTDivs) {
658*c8dee2aaSAndroid Build Coastguard Worker draw_t_divs(canvas, scaled, width, 0xFF3F3F00);
659*c8dee2aaSAndroid Build Coastguard Worker }
660*c8dee2aaSAndroid Build Coastguard Worker
661*c8dee2aaSAndroid Build Coastguard Worker SkPath fill;
662*c8dee2aaSAndroid Build Coastguard Worker
663*c8dee2aaSAndroid Build Coastguard Worker SkPaint p;
664*c8dee2aaSAndroid Build Coastguard Worker p.setStyle(SkPaint::kStroke_Style);
665*c8dee2aaSAndroid Build Coastguard Worker if (drawText) {
666*c8dee2aaSAndroid Build Coastguard Worker p.setStrokeWidth(width * scale * scale);
667*c8dee2aaSAndroid Build Coastguard Worker } else {
668*c8dee2aaSAndroid Build Coastguard Worker p.setStrokeWidth(width);
669*c8dee2aaSAndroid Build Coastguard Worker }
670*c8dee2aaSAndroid Build Coastguard Worker skpathutils::FillPathWithPaint(path, p, &fill);
671*c8dee2aaSAndroid Build Coastguard Worker SkPath scaledFill;
672*c8dee2aaSAndroid Build Coastguard Worker if (drawText) {
673*c8dee2aaSAndroid Build Coastguard Worker fill.transform(matrix, &scaledFill);
674*c8dee2aaSAndroid Build Coastguard Worker } else {
675*c8dee2aaSAndroid Build Coastguard Worker scaledFill = fill;
676*c8dee2aaSAndroid Build Coastguard Worker }
677*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(WIREFRAME_COLOR);
678*c8dee2aaSAndroid Build Coastguard Worker canvas->drawPath(scaledFill, paint);
679*c8dee2aaSAndroid Build Coastguard Worker draw_points(canvas, scaledFill, WIREFRAME_COLOR, false);
680*c8dee2aaSAndroid Build Coastguard Worker }
681*c8dee2aaSAndroid Build Coastguard Worker
draw_fill(SkCanvas * canvas,const SkRect & rect,SkScalar width)682*c8dee2aaSAndroid Build Coastguard Worker void draw_fill(SkCanvas* canvas, const SkRect& rect, SkScalar width) {
683*c8dee2aaSAndroid Build Coastguard Worker if (rect.isEmpty()) {
684*c8dee2aaSAndroid Build Coastguard Worker return;
685*c8dee2aaSAndroid Build Coastguard Worker }
686*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
687*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(0x1f1f0f0f);
688*c8dee2aaSAndroid Build Coastguard Worker paint.setStyle(SkPaint::kStroke_Style);
689*c8dee2aaSAndroid Build Coastguard Worker paint.setStrokeWidth(width);
690*c8dee2aaSAndroid Build Coastguard Worker SkPath path;
691*c8dee2aaSAndroid Build Coastguard Worker SkScalar maxSide = std::max(rect.width(), rect.height()) / 2;
692*c8dee2aaSAndroid Build Coastguard Worker SkPoint center = { rect.fLeft + maxSide, rect.fTop + maxSide };
693*c8dee2aaSAndroid Build Coastguard Worker path.addCircle(center.fX, center.fY, maxSide);
694*c8dee2aaSAndroid Build Coastguard Worker canvas->drawPath(path, paint);
695*c8dee2aaSAndroid Build Coastguard Worker paint.setStyle(SkPaint::kFill_Style);
696*c8dee2aaSAndroid Build Coastguard Worker path.reset();
697*c8dee2aaSAndroid Build Coastguard Worker path.addCircle(center.fX, center.fY, maxSide - width / 2);
698*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(0x3f0f1f3f);
699*c8dee2aaSAndroid Build Coastguard Worker canvas->drawPath(path, paint);
700*c8dee2aaSAndroid Build Coastguard Worker path.reset();
701*c8dee2aaSAndroid Build Coastguard Worker path.setFillType(SkPathFillType::kEvenOdd);
702*c8dee2aaSAndroid Build Coastguard Worker path.addCircle(center.fX, center.fY, maxSide + width / 2);
703*c8dee2aaSAndroid Build Coastguard Worker SkRect outside = SkRect::MakeXYWH(center.fX - maxSide - width, center.fY - maxSide - width,
704*c8dee2aaSAndroid Build Coastguard Worker (maxSide + width) * 2, (maxSide + width) * 2);
705*c8dee2aaSAndroid Build Coastguard Worker path.addRect(outside);
706*c8dee2aaSAndroid Build Coastguard Worker canvas->drawPath(path, paint);
707*c8dee2aaSAndroid Build Coastguard Worker }
708*c8dee2aaSAndroid Build Coastguard Worker
draw_button(SkCanvas * canvas,const StrokeTypeButton & button)709*c8dee2aaSAndroid Build Coastguard Worker void draw_button(SkCanvas* canvas, const StrokeTypeButton& button) {
710*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
711*c8dee2aaSAndroid Build Coastguard Worker paint.setAntiAlias(true);
712*c8dee2aaSAndroid Build Coastguard Worker paint.setStyle(SkPaint::kStroke_Style);
713*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(button.fEnabled ? 0xFF3F0000 : 0x6F3F0000);
714*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(button.fBounds, paint);
715*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(button.fEnabled ? 0xFF3F0000 : 0x6F3F0000);
716*c8dee2aaSAndroid Build Coastguard Worker paint.setStyle(SkPaint::kFill_Style);
717*c8dee2aaSAndroid Build Coastguard Worker SkFont font = ToolUtils::DefaultFont();
718*c8dee2aaSAndroid Build Coastguard Worker font.setSize(25.0f);
719*c8dee2aaSAndroid Build Coastguard Worker SkTextUtils::Draw(canvas, &button.fLabel, 1, SkTextEncoding::kUTF8,
720*c8dee2aaSAndroid Build Coastguard Worker button.fBounds.centerX(), button.fBounds.fBottom - 5,
721*c8dee2aaSAndroid Build Coastguard Worker font, paint, SkTextUtils::kCenter_Align);
722*c8dee2aaSAndroid Build Coastguard Worker }
723*c8dee2aaSAndroid Build Coastguard Worker
draw_control(SkCanvas * canvas,const SkRect & bounds,SkScalar value,SkScalar min,SkScalar max,const char * name)724*c8dee2aaSAndroid Build Coastguard Worker void draw_control(SkCanvas* canvas, const SkRect& bounds, SkScalar value,
725*c8dee2aaSAndroid Build Coastguard Worker SkScalar min, SkScalar max, const char* name) {
726*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
727*c8dee2aaSAndroid Build Coastguard Worker paint.setAntiAlias(true);
728*c8dee2aaSAndroid Build Coastguard Worker paint.setStyle(SkPaint::kStroke_Style);
729*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(bounds, paint);
730*c8dee2aaSAndroid Build Coastguard Worker SkScalar scale = max - min;
731*c8dee2aaSAndroid Build Coastguard Worker SkScalar yPos = bounds.fTop + (value - min) * bounds.height() / scale;
732*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(0xFFFF0000);
733*c8dee2aaSAndroid Build Coastguard Worker canvas->drawLine(bounds.fLeft - 5, yPos, bounds.fRight + 5, yPos, paint);
734*c8dee2aaSAndroid Build Coastguard Worker SkString label;
735*c8dee2aaSAndroid Build Coastguard Worker label.printf("%0.3g", value);
736*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(0xFF000000);
737*c8dee2aaSAndroid Build Coastguard Worker paint.setStyle(SkPaint::kFill_Style);
738*c8dee2aaSAndroid Build Coastguard Worker SkFont font(ToolUtils::DefaultTypeface(), 11.0f);
739*c8dee2aaSAndroid Build Coastguard Worker canvas->drawString(label, bounds.fLeft + 5, yPos - 5, font, paint);
740*c8dee2aaSAndroid Build Coastguard Worker font.setSize(13.0f);
741*c8dee2aaSAndroid Build Coastguard Worker canvas->drawString(name, bounds.fLeft, bounds.bottom() + 11, font, paint);
742*c8dee2aaSAndroid Build Coastguard Worker }
743*c8dee2aaSAndroid Build Coastguard Worker
setForGeometry()744*c8dee2aaSAndroid Build Coastguard Worker void setForGeometry() {
745*c8dee2aaSAndroid Build Coastguard Worker fDrawRibs = true;
746*c8dee2aaSAndroid Build Coastguard Worker fDrawTangents = true;
747*c8dee2aaSAndroid Build Coastguard Worker fDrawTDivs = false;
748*c8dee2aaSAndroid Build Coastguard Worker fWidthScale = 1;
749*c8dee2aaSAndroid Build Coastguard Worker }
750*c8dee2aaSAndroid Build Coastguard Worker
setForText()751*c8dee2aaSAndroid Build Coastguard Worker void setForText() {
752*c8dee2aaSAndroid Build Coastguard Worker fDrawRibs = fDrawTangents = fDrawTDivs = false;
753*c8dee2aaSAndroid Build Coastguard Worker fWidthScale = 0.002f;
754*c8dee2aaSAndroid Build Coastguard Worker }
755*c8dee2aaSAndroid Build Coastguard Worker
setForSingles()756*c8dee2aaSAndroid Build Coastguard Worker void setForSingles() {
757*c8dee2aaSAndroid Build Coastguard Worker setForGeometry();
758*c8dee2aaSAndroid Build Coastguard Worker fDrawTDivs = true;
759*c8dee2aaSAndroid Build Coastguard Worker }
760*c8dee2aaSAndroid Build Coastguard Worker
setAsNeeded()761*c8dee2aaSAndroid Build Coastguard Worker void setAsNeeded() {
762*c8dee2aaSAndroid Build Coastguard Worker if (fConicButton.fEnabled || fCubicButton.fEnabled || fQuadButton.fEnabled) {
763*c8dee2aaSAndroid Build Coastguard Worker setForSingles();
764*c8dee2aaSAndroid Build Coastguard Worker } else if (fRRectButton.fEnabled || fCircleButton.fEnabled || fArcButton.fEnabled) {
765*c8dee2aaSAndroid Build Coastguard Worker setForGeometry();
766*c8dee2aaSAndroid Build Coastguard Worker } else {
767*c8dee2aaSAndroid Build Coastguard Worker setForText();
768*c8dee2aaSAndroid Build Coastguard Worker }
769*c8dee2aaSAndroid Build Coastguard Worker }
770*c8dee2aaSAndroid Build Coastguard Worker
arcCenter(SkPoint * center)771*c8dee2aaSAndroid Build Coastguard Worker bool arcCenter(SkPoint* center) {
772*c8dee2aaSAndroid Build Coastguard Worker SkPath path;
773*c8dee2aaSAndroid Build Coastguard Worker path.moveTo(fPts[10]);
774*c8dee2aaSAndroid Build Coastguard Worker path.arcTo(fPts[11], fPts[12], fRadius);
775*c8dee2aaSAndroid Build Coastguard Worker SkPath::Iter iter(path, false);
776*c8dee2aaSAndroid Build Coastguard Worker SkPoint pts[4];
777*c8dee2aaSAndroid Build Coastguard Worker iter.next(pts);
778*c8dee2aaSAndroid Build Coastguard Worker if (SkPath::kLine_Verb == iter.next(pts)) {
779*c8dee2aaSAndroid Build Coastguard Worker iter.next(pts);
780*c8dee2aaSAndroid Build Coastguard Worker }
781*c8dee2aaSAndroid Build Coastguard Worker SkVector before = pts[0] - pts[1];
782*c8dee2aaSAndroid Build Coastguard Worker SkVector after = pts[1] - pts[2];
783*c8dee2aaSAndroid Build Coastguard Worker before.setLength(fRadius);
784*c8dee2aaSAndroid Build Coastguard Worker after.setLength(fRadius);
785*c8dee2aaSAndroid Build Coastguard Worker SkVector beforeCCW, afterCCW;
786*c8dee2aaSAndroid Build Coastguard Worker SkPointPriv::RotateCCW(before, &beforeCCW);
787*c8dee2aaSAndroid Build Coastguard Worker SkPointPriv::RotateCCW(after, &afterCCW);
788*c8dee2aaSAndroid Build Coastguard Worker beforeCCW += pts[0];
789*c8dee2aaSAndroid Build Coastguard Worker afterCCW += pts[2];
790*c8dee2aaSAndroid Build Coastguard Worker *center = beforeCCW;
791*c8dee2aaSAndroid Build Coastguard Worker if (SkScalarNearlyEqual(beforeCCW.fX, afterCCW.fX)
792*c8dee2aaSAndroid Build Coastguard Worker && SkScalarNearlyEqual(beforeCCW.fY, afterCCW.fY)) {
793*c8dee2aaSAndroid Build Coastguard Worker return true;
794*c8dee2aaSAndroid Build Coastguard Worker }
795*c8dee2aaSAndroid Build Coastguard Worker SkVector beforeCW, afterCW;
796*c8dee2aaSAndroid Build Coastguard Worker SkPointPriv::RotateCW(before, &beforeCW);
797*c8dee2aaSAndroid Build Coastguard Worker SkPointPriv::RotateCW(after, &afterCW);
798*c8dee2aaSAndroid Build Coastguard Worker beforeCW += pts[0];
799*c8dee2aaSAndroid Build Coastguard Worker afterCW += pts[2];
800*c8dee2aaSAndroid Build Coastguard Worker *center = beforeCW;
801*c8dee2aaSAndroid Build Coastguard Worker return SkScalarNearlyEqual(beforeCW.fX, afterCW.fX)
802*c8dee2aaSAndroid Build Coastguard Worker && SkScalarNearlyEqual(beforeCCW.fY, afterCW.fY);
803*c8dee2aaSAndroid Build Coastguard Worker }
804*c8dee2aaSAndroid Build Coastguard Worker
MapScreenYtoValue(SkScalar y,const SkRect & control,SkScalar min,SkScalar max)805*c8dee2aaSAndroid Build Coastguard Worker static SkScalar MapScreenYtoValue(SkScalar y, const SkRect& control, SkScalar min,
806*c8dee2aaSAndroid Build Coastguard Worker SkScalar max) {
807*c8dee2aaSAndroid Build Coastguard Worker return (y - control.fTop) / control.height() * (max - min) + min;
808*c8dee2aaSAndroid Build Coastguard Worker }
809*c8dee2aaSAndroid Build Coastguard Worker };
810*c8dee2aaSAndroid Build Coastguard Worker
811*c8dee2aaSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
812*c8dee2aaSAndroid Build Coastguard Worker
813*c8dee2aaSAndroid Build Coastguard Worker DEF_SLIDE( return new QuadStrokerSlide(); )
814