Flutter Engine
The Flutter Engine
QuadStrokerSlide.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2012 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
11#include "include/core/SkFont.h"
15#include "include/core/SkPath.h"
20#include "include/core/SkRect.h"
30#include "src/core/SkGeometry.h"
31#include "src/core/SkPathPriv.h"
33#include "src/core/SkStroke.h"
34#include "tools/ToolUtils.h"
37
38#include <cfloat>
39
40using namespace skia_private;
41
42class SkEvent;
43
44static bool hittest(const SkPoint& target, SkScalar x, SkScalar y) {
45 const SkScalar TOL = 7;
46 return SkPoint::Distance(target, SkPoint::Make(x, y)) <= TOL;
47}
48
49static int getOnCurvePoints(const SkPath& path, SkPoint storage[]) {
50 int count = 0;
51 for (auto [verb, pts, w] : SkPathPriv::Iterate(path)) {
52 switch (verb) {
58 storage[count++] = pts[0];
59 break;
60 default:
61 break;
62 }
63 }
64 return count;
65}
66
67static void getContourCounts(const SkPath& path, TArray<int>* contourCounts) {
68 int count = 0;
69 for (auto [verb, pts, w] : SkPathPriv::Iterate(path)) {
70 switch (verb) {
73 count += 1;
74 break;
77 count += 2;
78 break;
80 count += 3;
81 break;
83 contourCounts->push_back(count);
84 count = 0;
85 break;
86 default:
87 break;
88 }
89 }
90 if (count > 0) {
91 contourCounts->push_back(count);
92 }
93}
94
95static void erase(const sk_sp<SkSurface>& surface) {
96 SkCanvas* canvas = surface->getCanvas();
97 if (canvas) {
99 }
100}
101
104 char fLabel;
106};
107
109 bool fFill;
110};
111
113 enum {
114 SKELETON_COLOR = 0xFF0000FF,
115 WIREFRAME_COLOR = 0x80FF0000
116 };
117
118 enum {
119 kCount = 18
120 };
121 SkPoint fPts[kCount];
122 SkRect fWeightControl;
123 SkRect fRadiusControl;
124 SkRect fErrorControl;
125 SkRect fWidthControl;
126 SkRect fBounds;
127 SkMatrix fMatrix, fInverse;
128 sk_sp<SkShader> fShader;
129 sk_sp<SkSurface> fMinSurface;
130 sk_sp<SkSurface> fMaxSurface;
131 StrokeTypeButton fCubicButton;
132 StrokeTypeButton fConicButton;
133 StrokeTypeButton fQuadButton;
134 StrokeTypeButton fArcButton;
135 StrokeTypeButton fRRectButton;
136 CircleTypeButton fCircleButton;
137 StrokeTypeButton fTextButton;
138 SkString fText;
139 SkScalar fTextSize;
140 SkScalar fWeight;
141 SkScalar fRadius;
142 SkScalar fWidth, fDWidth;
143 SkScalar fWidthScale;
144 int fW, fH, fZoom;
145 bool fAnimate;
146 bool fDrawRibs;
147 bool fDrawTangents;
148 bool fDrawTDivs;
149#ifdef SK_DEBUG
150 #define kStrokerErrorMin 0.001f
151 #define kStrokerErrorMax 5
152#endif
153 #define kWidthMin 1
154 #define kWidthMax 100
155public:
157 fPts[0].set(50, 200); // cubic
158 fPts[1].set(50, 100);
159 fPts[2].set(150, 50);
160 fPts[3].set(300, 50);
161
162 fPts[4].set(350, 200); // conic
163 fPts[5].set(350, 100);
164 fPts[6].set(450, 50);
165
166 fPts[7].set(150, 300); // quad
167 fPts[8].set(150, 200);
168 fPts[9].set(250, 150);
169
170 fPts[10].set(250, 200); // arc
171 fPts[11].set(250, 300);
172 fPts[12].set(150, 350);
173
174 fPts[13].set(200, 200); // rrect
175 fPts[14].set(400, 400);
176
177 fPts[15].set(250, 250); // oval
178 fPts[16].set(450, 450);
179
180 fText = "a";
181 fTextSize = 12;
182 fWidth = 50;
183 fDWidth = 0.25f;
184 fWeight = 1;
185 fRadius = 150;
186
187 fCubicButton.fLabel = 'C';
188 fCubicButton.fEnabled = false;
189 fConicButton.fLabel = 'K';
190 fConicButton.fEnabled = false;
191 fQuadButton.fLabel = 'Q';
192 fQuadButton.fEnabled = false;
193 fArcButton.fLabel = 'A';
194 fArcButton.fEnabled = true;
195 fRRectButton.fLabel = 'R';
196 fRRectButton.fEnabled = false;
197 fCircleButton.fLabel = 'O';
198 fCircleButton.fEnabled = true;
199 fCircleButton.fFill = true;
200 fTextButton.fLabel = 'T';
201 fTextButton.fEnabled = false;
202 fAnimate = false;
203 setAsNeeded();
204 fName = "QuadStroker";
205 }
206
207 bool onChar(SkUnichar uni) override {
208 if (fTextButton.fEnabled) {
209 switch (uni) {
210 case ' ':
211 fText = "";
212 break;
213 case '-':
214 fTextSize = std::max(1.0f, fTextSize - 1);
215 break;
216 case '+':
217 case '=':
218 fTextSize += 1;
219 break;
220 default:
221 fText.appendUnichar(uni);
222 }
223 return true;
224 }
225 return false;
226 }
227
228 void load(SkScalar w, SkScalar h) override { this->layout(w, h); }
229
230 void resize(SkScalar w, SkScalar h) override { this->layout(w, h); }
231
232 void draw(SkCanvas* canvas) override {
233 canvas->clear(SK_ColorLTGRAY);
234
235 SkPath path;
236 SkScalar width = fWidth;
237
238 if (fCubicButton.fEnabled) {
239 path.moveTo(fPts[0]);
240 path.cubicTo(fPts[1], fPts[2], fPts[3]);
241 setForSingles();
242 draw_stroke(canvas, path, width, 950, false);
243 }
244
245 if (fConicButton.fEnabled) {
246 path.reset();
247 path.moveTo(fPts[4]);
248 path.conicTo(fPts[5], fPts[6], fWeight);
249 setForSingles();
250 draw_stroke(canvas, path, width, 950, false);
251 }
252
253 if (fQuadButton.fEnabled) {
254 path.reset();
255 path.moveTo(fPts[7]);
256 path.quadTo(fPts[8], fPts[9]);
257 setForSingles();
258 draw_stroke(canvas, path, width, 950, false);
259 }
260
261 if (fArcButton.fEnabled) {
262 path.reset();
263 path.moveTo(fPts[10]);
264 path.arcTo(fPts[11], fPts[12], fRadius);
265 setForGeometry();
266 draw_stroke(canvas, path, width, 950, false);
267 SkPath pathPts;
268 pathPts.moveTo(fPts[10]);
269 pathPts.lineTo(fPts[11]);
270 pathPts.lineTo(fPts[12]);
271 draw_points(canvas, pathPts, SK_ColorDKGRAY, true);
272 }
273
274 if (fRRectButton.fEnabled) {
275 SkScalar rad = 32;
276 SkRect r;
277 r.setBounds(&fPts[13], 2);
278 path.reset();
279 SkRRect rr;
280 rr.setRectXY(r, rad, rad);
281 path.addRRect(rr);
282 setForGeometry();
283 draw_stroke(canvas, path, width, 950, false);
284
285 path.reset();
286 SkRRect rr2;
287 rr.inset(width/2, width/2, &rr2);
288 path.addRRect(rr2, SkPathDirection::kCCW);
289 rr.inset(-width/2, -width/2, &rr2);
290 path.addRRect(rr2, SkPathDirection::kCW);
292 paint.setAntiAlias(true);
293 paint.setColor(0x40FF8844);
294 canvas->drawPath(path, paint);
295 }
296
297 if (fCircleButton.fEnabled) {
298 path.reset();
299 SkRect r;
300 r.setBounds(&fPts[15], 2);
301 path.addOval(r);
302 setForGeometry();
303 if (fCircleButton.fFill) {
304 if (fArcButton.fEnabled) {
306 if (arcCenter(&center)) {
307 r.setLTRB(center.fX - fRadius, center.fY - fRadius,
308 center.fX + fRadius, center.fY + fRadius);
309 }
310 }
311 draw_fill(canvas, r, width);
312 } else {
313 draw_stroke(canvas, path, width, 950, false);
314 }
315 }
316
317 if (fTextButton.fEnabled) {
318 path.reset();
320 font.setSize(fTextSize);
321 SkTextUtils::GetPath(fText.c_str(), fText.size(), SkTextEncoding::kUTF8,
322 0, fTextSize, font, &path);
323 setForText();
324 draw_stroke(canvas, path, width * fWidthScale / fTextSize, fTextSize, true);
325 }
326
327 if (fAnimate) {
328 fWidth += fDWidth;
329 if (fDWidth > 0 && fWidth > kWidthMax) {
330 fDWidth = -fDWidth;
331 } else if (fDWidth < 0 && fWidth < kWidthMin) {
332 fDWidth = -fDWidth;
333 }
334 }
335 setAsNeeded();
336 if (fConicButton.fEnabled) {
337 draw_control(canvas, fWeightControl, fWeight, 0, 5, "weight");
338 }
339 if (fArcButton.fEnabled) {
340 draw_control(canvas, fRadiusControl, fRadius, 0, 500, "radius");
341 }
342#ifdef SK_DEBUG
343 draw_control(canvas, fErrorControl, gDebugStrokerError, kStrokerErrorMin, kStrokerErrorMax,
344 "error");
345#endif
346 draw_control(canvas, fWidthControl, fWidth * fWidthScale, kWidthMin * fWidthScale,
347 kWidthMax * fWidthScale, "width");
348 draw_button(canvas, fQuadButton);
349 draw_button(canvas, fCubicButton);
350 draw_button(canvas, fConicButton);
351 draw_button(canvas, fArcButton);
352 draw_button(canvas, fRRectButton);
353 draw_button(canvas, fCircleButton);
354 draw_button(canvas, fTextButton);
355 }
356protected:
357 class MyClick : public Click {
358 public:
360 MyClick(int index) : fIndex(index) {}
361 };
362
364 for (size_t i = 0; i < std::size(fPts); ++i) {
365 if (hittest(fPts[i], x, y)) {
366 return new MyClick((int)i);
367 }
368 }
369 const SkRect& rectPt = SkRect::MakeXYWH(x, y, 1, 1);
370 if (fWeightControl.contains(rectPt)) {
371 return new MyClick((int) std::size(fPts) + 1);
372 }
373 if (fRadiusControl.contains(rectPt)) {
374 return new MyClick((int) std::size(fPts) + 2);
375 }
376#ifdef SK_DEBUG
377 if (fErrorControl.contains(rectPt)) {
378 return new MyClick((int) std::size(fPts) + 3);
379 }
380#endif
381 if (fWidthControl.contains(rectPt)) {
382 return new MyClick((int) std::size(fPts) + 4);
383 }
384 if (fCubicButton.fBounds.contains(rectPt)) {
385 fCubicButton.fEnabled ^= true;
386 return new MyClick((int) std::size(fPts) + 5);
387 }
388 if (fConicButton.fBounds.contains(rectPt)) {
389 fConicButton.fEnabled ^= true;
390 return new MyClick((int) std::size(fPts) + 6);
391 }
392 if (fQuadButton.fBounds.contains(rectPt)) {
393 fQuadButton.fEnabled ^= true;
394 return new MyClick((int) std::size(fPts) + 7);
395 }
396 if (fArcButton.fBounds.contains(rectPt)) {
397 fArcButton.fEnabled ^= true;
398 return new MyClick((int) std::size(fPts) + 8);
399 }
400 if (fRRectButton.fBounds.contains(rectPt)) {
401 fRRectButton.fEnabled ^= true;
402 return new MyClick((int) std::size(fPts) + 9);
403 }
404 if (fCircleButton.fBounds.contains(rectPt)) {
405 bool wasEnabled = fCircleButton.fEnabled;
406 fCircleButton.fEnabled = !fCircleButton.fFill;
407 fCircleButton.fFill = wasEnabled && !fCircleButton.fFill;
408 return new MyClick((int) std::size(fPts) + 10);
409 }
410 if (fTextButton.fBounds.contains(rectPt)) {
411 fTextButton.fEnabled ^= true;
412 return new MyClick((int) std::size(fPts) + 11);
413 }
414 return nullptr;
415 }
416
417 bool onClick(Click* click) override {
418 int index = ((MyClick*)click)->fIndex;
419 if (index < (int) std::size(fPts)) {
420 fPts[index].offset(click->fCurr.fX - click->fPrev.fX,
421 click->fCurr.fY - click->fPrev.fY);
422 } else if (index == (int) std::size(fPts) + 1) {
423 fWeight = MapScreenYtoValue(click->fCurr.fY, fWeightControl, 0, 5);
424 } else if (index == (int) std::size(fPts) + 2) {
425 fRadius = MapScreenYtoValue(click->fCurr.fY, fRadiusControl, 0, 500);
426 }
427#ifdef SK_DEBUG
428 else if (index == (int) std::size(fPts) + 3) {
429 gDebugStrokerError = std::max(FLT_EPSILON, MapScreenYtoValue(click->fCurr.fY,
430 fErrorControl, kStrokerErrorMin, kStrokerErrorMax));
431 gDebugStrokerErrorSet = true;
432 }
433#endif
434 else if (index == (int) std::size(fPts) + 4) {
435 fWidth = std::max(FLT_EPSILON, MapScreenYtoValue(click->fCurr.fY, fWidthControl,
437 fAnimate = fWidth <= kWidthMin;
438 }
439 return true;
440 }
441
442private:
443 void layout(SkScalar w, SkScalar h) {
444 fRadiusControl.setXYWH(w - 200, 30, 30, 400);
445 fWeightControl.setXYWH(w - 150, 30, 30, 400);
446 fErrorControl.setXYWH(w - 100, 30, 30, 400);
447 fWidthControl.setXYWH(w - 50, 30, 30, 400);
448 int buttonOffset = 450;
449 fCubicButton.fBounds.setXYWH(w - 50, SkIntToScalar(buttonOffset), 30, 30);
450 buttonOffset += 50;
451 fConicButton.fBounds.setXYWH(w - 50, SkIntToScalar(buttonOffset), 30, 30);
452 buttonOffset += 50;
453 fQuadButton.fBounds.setXYWH(w - 50, SkIntToScalar(buttonOffset), 30, 30);
454 buttonOffset += 50;
455 fArcButton.fBounds.setXYWH(w - 50, SkIntToScalar(buttonOffset), 30, 30);
456 buttonOffset += 50;
457 fRRectButton.fBounds.setXYWH(w - 50, SkIntToScalar(buttonOffset), 30, 30);
458 buttonOffset += 50;
459 fCircleButton.fBounds.setXYWH(w - 50, SkIntToScalar(buttonOffset), 30, 30);
460 buttonOffset += 50;
461 fTextButton.fBounds.setXYWH(w - 50, SkIntToScalar(buttonOffset), 30, 30);
462 }
463
464 void copyMinToMax() {
465 erase(fMaxSurface);
466 SkCanvas* canvas = fMaxSurface->getCanvas();
467 canvas->save();
468 canvas->concat(fMatrix);
469 fMinSurface->draw(canvas, 0, 0);
470 canvas->restore();
471
473 paint.setBlendMode(SkBlendMode::kClear);
474 for (int iy = 1; iy < fH; ++iy) {
475 SkScalar y = SkIntToScalar(iy * fZoom);
476 canvas->drawLine(0, y - SK_ScalarHalf, 999, y - SK_ScalarHalf, paint);
477 }
478 for (int ix = 1; ix < fW; ++ix) {
479 SkScalar x = SkIntToScalar(ix * fZoom);
480 canvas->drawLine(x - SK_ScalarHalf, 0, x - SK_ScalarHalf, 999, paint);
481 }
482 }
483
484 void setWHZ(int width, int height, int zoom) {
485 fZoom = zoom;
486 fBounds.setIWH(width * zoom, height * zoom);
487 fMatrix.setScale(SkIntToScalar(zoom), SkIntToScalar(zoom));
488 fInverse.setScale(SK_Scalar1 / zoom, SK_Scalar1 / zoom);
489 fShader = ToolUtils::create_checkerboard_shader(0xFFCCCCCC, 0xFFFFFFFF, zoom);
490
492 fMinSurface = SkSurfaces::Raster(info);
493 info = info.makeWH(width * zoom, height * zoom);
494 fMaxSurface = SkSurfaces::Raster(info);
495 }
496
497 void draw_points(SkCanvas* canvas, const SkPath& path, SkColor color,
498 bool show_lines) {
500 paint.setColor(color);
501 paint.setAlpha(0x80);
502 paint.setAntiAlias(true);
503 int n = path.countPoints();
504 std::unique_ptr<SkPoint[]> pts{new SkPoint[n]};
505 if (show_lines && fDrawTangents) {
506 TArray<int> contourCounts;
507 getContourCounts(path, &contourCounts);
508 SkPoint* ptPtr = pts.get();
509 for (int i = 0; i < contourCounts.size(); ++i) {
510 int count = contourCounts[i];
511 path.getPoints(ptPtr, count);
513 ptPtr += count;
514 }
515 } else {
516 n = getOnCurvePoints(path, pts.get());
517 }
518 paint.setStrokeWidth(5);
519 canvas->drawPoints(SkCanvas::kPoints_PointMode, n, pts.get(), paint);
520 }
521
522 void draw_ribs(SkCanvas* canvas, const SkPath& path, SkScalar width,
523 SkColor color) {
524 const SkScalar radius = width / 2;
525
526 SkPathMeasure meas(path, false);
527 SkScalar total = meas.getLength();
528
529 SkScalar delta = 8;
530 SkPaint paint, labelP;
531 paint.setColor(color);
532 labelP.setColor(color & 0xff5f9f5f);
534 SkPoint pos, tan;
535 int index = 0;
536 for (SkScalar dist = 0; dist <= total; dist += delta) {
537 if (meas.getPosTan(dist, &pos, &tan)) {
538 tan.scale(radius);
540 canvas->drawLine(pos.x() + tan.x(), pos.y() + tan.y(),
541 pos.x() - tan.x(), pos.y() - tan.y(), paint);
542 if (0 == index % 10) {
543 SkString label;
544 label.appendS32(index);
545 SkRect dot = SkRect::MakeXYWH(pos.x() - 2, pos.y() - 2, 4, 4);
546 canvas->drawRect(dot, labelP);
547 canvas->drawString(label,
548 pos.x() - tan.x() * 1.25f, pos.y() - tan.y() * 1.25f, font, labelP);
549 }
550 }
551 ++index;
552 }
553 }
554
555 void draw_t_divs(SkCanvas* canvas, const SkPath& path, SkScalar width, SkColor color) {
556 const SkScalar radius = width / 2;
558 paint.setColor(color);
559 SkPathMeasure meas(path, false);
560 SkScalar total = meas.getLength();
561 SkScalar delta = 8;
562 int ribs = 0;
563 for (SkScalar dist = 0; dist <= total; dist += delta) {
564 ++ribs;
565 }
566 const uint8_t* verbs = SkPathPriv::VerbData(path);
567 if (path.countVerbs() < 2 || SkPath::kMove_Verb != verbs[0]) {
568 SkASSERT(0);
569 return;
570 }
571 auto verb = static_cast<SkPath::Verb>(verbs[1]);
573 const SkPoint* pts = SkPathPriv::PointData(path);
574 SkPoint pos, tan;
575 for (int index = 0; index < ribs; ++index) {
576 SkScalar t = (SkScalar) index / ribs;
577 switch (verb) {
579 tan = pts[1] - pts[0];
580 pos = pts[0];
581 pos.fX += tan.fX * t;
582 pos.fY += tan.fY * t;
583 break;
585 pos = SkEvalQuadAt(pts, t);
586 tan = SkEvalQuadTangentAt(pts, t);
587 break;
588 case SkPath::kConic_Verb: {
590 pos = conic.evalAt(t);
591 tan = conic.evalTangentAt(t);
592 } break;
594 SkEvalCubicAt(pts, t, &pos, &tan, nullptr);
595 break;
596 default:
597 SkASSERT(0);
598 return;
599 }
600 tan.setLength(radius);
602 canvas->drawLine(pos.x() + tan.x(), pos.y() + tan.y(),
603 pos.x() - tan.x(), pos.y() - tan.y(), paint);
604 if (0 == index % 10) {
605 SkString label;
606 label.appendS32(index);
607 canvas->drawString(label,
608 pos.x() + tan.x() * 1.25f,
609 pos.y() + tan.y() * 1.25f,
611 paint);
612 }
613 }
614 }
615
616 void draw_stroke(SkCanvas* canvas, const SkPath& path, SkScalar width, SkScalar scale,
617 bool drawText) {
618 if (path.isEmpty()) {
619 return;
620 }
621 SkRect bounds = path.getBounds();
622 this->setWHZ(SkScalarCeilToInt(bounds.right()), drawText
624 SkScalarRoundToInt(950.0f / scale));
625 erase(fMinSurface);
627 paint.setColor(0x1f1f0f0f);
629 paint.setStrokeWidth(width * scale * scale);
630 paint.setColor(0x3f0f1f3f);
631 if (drawText) {
632 fMinSurface->getCanvas()->drawPath(path, paint);
633 this->copyMinToMax();
634 fMaxSurface->draw(canvas, 0, 0);
635 }
636 paint.setAntiAlias(true);
638 paint.setStrokeWidth(1);
639
640 paint.setColor(SKELETON_COLOR);
641 SkPath scaled;
643 matrix.reset();
644 matrix.setScale(950 / scale, 950 / scale);
645 if (drawText) {
646 path.transform(matrix, &scaled);
647 } else {
648 scaled = path;
649 }
650 canvas->drawPath(scaled, paint);
651 draw_points(canvas, scaled, SKELETON_COLOR, true);
652
653 if (fDrawRibs) {
654 draw_ribs(canvas, scaled, width, 0xFF00FF00);
655 }
656
657 if (fDrawTDivs) {
658 draw_t_divs(canvas, scaled, width, 0xFF3F3F00);
659 }
660
661 SkPath fill;
662
663 SkPaint p;
664 p.setStyle(SkPaint::kStroke_Style);
665 if (drawText) {
666 p.setStrokeWidth(width * scale * scale);
667 } else {
668 p.setStrokeWidth(width);
669 }
671 SkPath scaledFill;
672 if (drawText) {
673 fill.transform(matrix, &scaledFill);
674 } else {
675 scaledFill = fill;
676 }
677 paint.setColor(WIREFRAME_COLOR);
678 canvas->drawPath(scaledFill, paint);
679 draw_points(canvas, scaledFill, WIREFRAME_COLOR, false);
680 }
681
682 void draw_fill(SkCanvas* canvas, const SkRect& rect, SkScalar width) {
683 if (rect.isEmpty()) {
684 return;
685 }
687 paint.setColor(0x1f1f0f0f);
689 paint.setStrokeWidth(width);
690 SkPath path;
691 SkScalar maxSide = std::max(rect.width(), rect.height()) / 2;
692 SkPoint center = { rect.fLeft + maxSide, rect.fTop + maxSide };
693 path.addCircle(center.fX, center.fY, maxSide);
694 canvas->drawPath(path, paint);
695 paint.setStyle(SkPaint::kFill_Style);
696 path.reset();
697 path.addCircle(center.fX, center.fY, maxSide - width / 2);
698 paint.setColor(0x3f0f1f3f);
699 canvas->drawPath(path, paint);
700 path.reset();
701 path.setFillType(SkPathFillType::kEvenOdd);
702 path.addCircle(center.fX, center.fY, maxSide + width / 2);
703 SkRect outside = SkRect::MakeXYWH(center.fX - maxSide - width, center.fY - maxSide - width,
704 (maxSide + width) * 2, (maxSide + width) * 2);
705 path.addRect(outside);
706 canvas->drawPath(path, paint);
707 }
708
709 void draw_button(SkCanvas* canvas, const StrokeTypeButton& button) {
711 paint.setAntiAlias(true);
713 paint.setColor(button.fEnabled ? 0xFF3F0000 : 0x6F3F0000);
714 canvas->drawRect(button.fBounds, paint);
715 paint.setColor(button.fEnabled ? 0xFF3F0000 : 0x6F3F0000);
716 paint.setStyle(SkPaint::kFill_Style);
718 font.setSize(25.0f);
720 button.fBounds.centerX(), button.fBounds.fBottom - 5,
722 }
723
724 void draw_control(SkCanvas* canvas, const SkRect& bounds, SkScalar value,
725 SkScalar min, SkScalar max, const char* name) {
727 paint.setAntiAlias(true);
729 canvas->drawRect(bounds, paint);
730 SkScalar scale = max - min;
731 SkScalar yPos = bounds.fTop + (value - min) * bounds.height() / scale;
732 paint.setColor(0xFFFF0000);
733 canvas->drawLine(bounds.fLeft - 5, yPos, bounds.fRight + 5, yPos, paint);
734 SkString label;
735 label.printf("%0.3g", value);
736 paint.setColor(0xFF000000);
737 paint.setStyle(SkPaint::kFill_Style);
739 canvas->drawString(label, bounds.fLeft + 5, yPos - 5, font, paint);
740 font.setSize(13.0f);
741 canvas->drawString(name, bounds.fLeft, bounds.bottom() + 11, font, paint);
742 }
743
744 void setForGeometry() {
745 fDrawRibs = true;
746 fDrawTangents = true;
747 fDrawTDivs = false;
748 fWidthScale = 1;
749 }
750
751 void setForText() {
752 fDrawRibs = fDrawTangents = fDrawTDivs = false;
753 fWidthScale = 0.002f;
754 }
755
756 void setForSingles() {
757 setForGeometry();
758 fDrawTDivs = true;
759 }
760
761 void setAsNeeded() {
762 if (fConicButton.fEnabled || fCubicButton.fEnabled || fQuadButton.fEnabled) {
763 setForSingles();
764 } else if (fRRectButton.fEnabled || fCircleButton.fEnabled || fArcButton.fEnabled) {
765 setForGeometry();
766 } else {
767 setForText();
768 }
769 }
770
771 bool arcCenter(SkPoint* center) {
772 SkPath path;
773 path.moveTo(fPts[10]);
774 path.arcTo(fPts[11], fPts[12], fRadius);
775 SkPath::Iter iter(path, false);
776 SkPoint pts[4];
777 iter.next(pts);
778 if (SkPath::kLine_Verb == iter.next(pts)) {
779 iter.next(pts);
780 }
781 SkVector before = pts[0] - pts[1];
782 SkVector after = pts[1] - pts[2];
783 before.setLength(fRadius);
784 after.setLength(fRadius);
785 SkVector beforeCCW, afterCCW;
786 SkPointPriv::RotateCCW(before, &beforeCCW);
787 SkPointPriv::RotateCCW(after, &afterCCW);
788 beforeCCW += pts[0];
789 afterCCW += pts[2];
790 *center = beforeCCW;
791 if (SkScalarNearlyEqual(beforeCCW.fX, afterCCW.fX)
792 && SkScalarNearlyEqual(beforeCCW.fY, afterCCW.fY)) {
793 return true;
794 }
795 SkVector beforeCW, afterCW;
796 SkPointPriv::RotateCW(before, &beforeCW);
797 SkPointPriv::RotateCW(after, &afterCW);
798 beforeCW += pts[0];
799 afterCW += pts[2];
800 *center = beforeCW;
801 return SkScalarNearlyEqual(beforeCW.fX, afterCW.fX)
802 && SkScalarNearlyEqual(beforeCCW.fY, afterCW.fY);
803 }
804
805 static SkScalar MapScreenYtoValue(SkScalar y, const SkRect& control, SkScalar min,
806 SkScalar max) {
807 return (y - control.fTop) / control.height() * (max - min) + min;
808 }
809};
810
811///////////////////////////////////////////////////////////////////////////////
812
813DEF_SLIDE( return new QuadStrokerSlide(); )
SkPoint fPts[2]
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
int count
Definition: FontMgrTest.cpp:50
SkPoint pos
const SkRect fBounds
static bool hittest(const SkPoint &target, SkScalar x, SkScalar y)
#define kWidthMax
static void getContourCounts(const SkPath &path, TArray< int > *contourCounts)
#define kWidthMin
static void erase(const sk_sp< SkSurface > &surface)
static int getOnCurvePoints(const SkPath &path, SkPoint storage[])
#define SkASSERT(cond)
Definition: SkAssert.h:116
@ kClear
r = 0
constexpr SkColor SK_ColorLTGRAY
Definition: SkColor.h:118
uint32_t SkColor
Definition: SkColor.h:37
constexpr SkColor SK_ColorTRANSPARENT
Definition: SkColor.h:99
constexpr SkColor SK_ColorDKGRAY
Definition: SkColor.h:108
@ kUTF8
uses bytes to represent UTF-8 or ASCII
void SkEvalCubicAt(const SkPoint src[4], SkScalar t, SkPoint *loc, SkVector *tangent, SkVector *curvature)
Definition: SkGeometry.cpp:418
SkVector SkEvalQuadTangentAt(const SkPoint src[3], SkScalar t)
Definition: SkGeometry.cpp:148
void SkEvalQuadAt(const SkPoint src[3], SkScalar t, SkPoint *pt, SkVector *tangent)
Definition: SkGeometry.cpp:132
@ kClose
SkPath::RawIter returns 0 points.
@ kCubic
SkPath::RawIter returns 4 points.
@ kConic
SkPath::RawIter returns 3 points + 1 weight.
@ kQuad
SkPath::RawIter returns 3 points.
@ kMove
SkPath::RawIter returns 1 point.
@ kLine
SkPath::RawIter returns 2 points.
static bool SkScalarNearlyEqual(SkScalar x, SkScalar y, SkScalar tolerance=SK_ScalarNearlyZero)
Definition: SkScalar.h:107
#define SK_Scalar1
Definition: SkScalar.h:18
#define SK_ScalarHalf
Definition: SkScalar.h:19
#define SkScalarRoundToInt(x)
Definition: SkScalar.h:37
#define SkScalarCeilToInt(x)
Definition: SkScalar.h:36
#define SkIntToScalar(x)
Definition: SkScalar.h:57
int32_t SkUnichar
Definition: SkTypes.h:175
#define DEF_SLIDE(code)
Definition: Slide.h:25
static SkScalar center(float pos0, float pos1)
void resize(SkScalar w, SkScalar h) override
void draw(SkCanvas *canvas) override
Click * onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey modi) override
bool onChar(SkUnichar uni) override
void load(SkScalar w, SkScalar h) override
bool onClick(Click *click) override
void drawRect(const SkRect &rect, const SkPaint &paint)
Definition: SkCanvas.cpp:1673
void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint &paint)
Definition: SkCanvas.cpp:1710
void restore()
Definition: SkCanvas.cpp:461
void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint &paint)
Definition: SkCanvas.cpp:2700
void clear(SkColor color)
Definition: SkCanvas.h:1199
int save()
Definition: SkCanvas.cpp:447
void drawPath(const SkPath &path, const SkPaint &paint)
Definition: SkCanvas.cpp:1747
void concat(const SkMatrix &matrix)
Definition: SkCanvas.cpp:1318
void drawString(const char str[], SkScalar x, SkScalar y, const SkFont &font, const SkPaint &paint)
Definition: SkCanvas.h:1803
@ kPolygon_PointMode
draw the array of points as a open polygon
Definition: SkCanvas.h:1243
@ kPoints_PointMode
draw each point separately
Definition: SkCanvas.h:1241
Definition: SkFont.h:35
SkMatrix & setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py)
Definition: SkMatrix.cpp:296
void setColor(SkColor color)
Definition: SkPaint.cpp:119
@ kStroke_Style
set to stroke geometry
Definition: SkPaint.h:194
@ kFill_Style
set to fill geometry
Definition: SkPaint.h:193
static const uint8_t * VerbData(const SkPath &path)
Definition: SkPathPriv.h:198
static const SkScalar * ConicWeightData(const SkPath &path)
Definition: SkPathPriv.h:213
static const SkPoint * PointData(const SkPath &path)
Definition: SkPathPriv.h:203
Definition: SkPath.h:59
SkPath & moveTo(SkScalar x, SkScalar y)
Definition: SkPath.cpp:688
SkPath & lineTo(SkScalar x, SkScalar y)
Definition: SkPath.cpp:728
@ kMove_Verb
Definition: SkPath.h:1466
@ kConic_Verb
Definition: SkPath.h:1469
@ kCubic_Verb
Definition: SkPath.h:1470
@ kQuad_Verb
Definition: SkPath.h:1468
@ kLine_Verb
Definition: SkPath.h:1467
void transform(const SkMatrix &matrix, SkPath *dst, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
Definition: SkPath.cpp:1711
static void RotateCCW(const SkPoint &src, SkPoint *dst)
Definition: SkPointPriv.h:72
static void RotateCW(const SkPoint &src, SkPoint *dst)
Definition: SkPointPriv.h:83
void inset(SkScalar dx, SkScalar dy, SkRRect *dst) const
Definition: SkRRect.cpp:562
void setRectXY(const SkRect &rect, SkScalar xRad, SkScalar yRad)
Definition: SkRRect.cpp:52
void printf(const char format[],...) SK_PRINTF_LIKE(2
Definition: SkString.cpp:534
void appendS32(int32_t value)
Definition: SkString.h:208
SkCanvas * getCanvas()
Definition: SkSurface.cpp:82
void draw(SkCanvas *canvas, SkScalar x, SkScalar y, const SkSamplingOptions &sampling, const SkPaint *paint)
Definition: SkSurface.cpp:116
static void GetPath(const void *text, size_t length, SkTextEncoding, SkScalar x, SkScalar y, const SkFont &, SkPath *)
Definition: SkTextUtils.cpp:38
static void Draw(SkCanvas *, const void *text, size_t size, SkTextEncoding, SkScalar x, SkScalar y, const SkFont &, const SkPaint &, Align=kLeft_Align)
Definition: SkTextUtils.cpp:24
SkString fName
Definition: Slide.h:54
int size() const
Definition: SkTArray.h:421
const Paint & paint
Definition: color_source.cc:38
DlColor color
VkSurfaceKHR surface
Definition: main.cc:49
float SkScalar
Definition: extension.cpp:12
uint8_t value
uint32_t * target
static float max(float r, float g, float b)
Definition: hsl.cpp:49
static float min(float r, float g, float b)
Definition: hsl.cpp:48
double y
double x
unsigned useCenter Optional< SkMatrix > matrix
Definition: SkRecords.h:258
Optional< SkRect > bounds
Definition: SkRecords.h:189
sk_sp< SkBlender > blender SkRect rect
Definition: SkRecords.h:350
SK_API sk_sp< SkSurface > Raster(const SkImageInfo &imageInfo, size_t rowBytes, const SkSurfaceProps *surfaceProps)
sk_sp< SkShader > create_checkerboard_shader(SkColor c1, SkColor c2, int size)
Definition: ToolUtils.cpp:150
SkFont DefaultFont()
sk_sp< SkTypeface > DefaultTypeface()
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
font
Font Metadata and Metrics.
AI float conic(float tolerance, const SkPoint pts[], float w, const VectorXform &vectorXform=VectorXform())
Definition: WangsFormula.h:287
SK_API bool FillPathWithPaint(const SkPath &src, const SkPaint &paint, SkPath *dst, const SkRect *cullRect, SkScalar resScale=1)
Definition: SkPathUtils.cpp:23
ModifierKey
Definition: ModifierKey.h:9
SINT T dot(const Vec< N, T > &a, const Vec< N, T > &b)
Definition: SkVx.h:964
SkScalar w
SkScalar h
int32_t height
int32_t width
const Scalar scale
static SkImageInfo MakeN32Premul(int width, int height)
bool setLength(float length)
Definition: SkPoint.cpp:30
float fX
x-axis value
Definition: SkPoint_impl.h:164
void offset(float dx, float dy)
Definition: SkPoint_impl.h:269
static constexpr SkPoint Make(float x, float y)
Definition: SkPoint_impl.h:173
void set(float x, float y)
Definition: SkPoint_impl.h:200
static float Distance(const SkPoint &a, const SkPoint &b)
Definition: SkPoint_impl.h:508
void scale(float scale, SkPoint *dst) const
Definition: SkPoint.cpp:17
float fY
y-axis value
Definition: SkPoint_impl.h:165
constexpr float y() const
Definition: SkPoint_impl.h:187
constexpr float x() const
Definition: SkPoint_impl.h:181
SkScalar fBottom
larger y-axis bounds
Definition: extension.cpp:17
void setXYWH(float x, float y, float width, float height)
Definition: SkRect.h:931
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
Definition: SkRect.h:659
bool contains(SkScalar x, SkScalar y) const
Definition: extension.cpp:19
constexpr float centerX() const
Definition: SkRect.h:776
constexpr float height() const
Definition: SkRect.h:769
void setIWH(int32_t width, int32_t height)
Definition: SkRect.h:950
void setLTRB(float left, float top, float right, float bottom)
Definition: SkRect.h:865
void setBounds(const SkPoint pts[], int count)
Definition: SkRect.h:881
SkScalar fTop
smaller y-axis bounds
Definition: extension.cpp:15