Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
MotionMarkSlide.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2013 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#include <vector>
8
10#include "include/core/SkPath.h"
12#include "src/base/SkRandom.h"
13#include "tools/viewer/Slide.h"
14
15// Implementation in C++ of some WebKit MotionMark tests
16// Tests implemented so far:
17// * Canvas Lines
18// * Canvas Arcs
19// * Paths
20// Based on https://github.com/WebKit/MotionMark/blob/main/MotionMark/
21
22class MMObject {
23public:
24 virtual ~MMObject() = default;
25
26 virtual void draw(SkCanvas* canvas) = 0;
27
28 virtual void animate(double /*nanos*/) = 0;
29};
30
31class Stage {
32public:
33 Stage(SkSize size, int startingObjectCount, int objectIncrement)
34 : fSize(size)
35 , fStartingObjectCount(startingObjectCount)
36 , fObjectIncrement(objectIncrement) {}
37 virtual ~Stage() = default;
38
39 // The default impls of draw() and animate() simply iterate over fObjects and call the
40 // MMObject function.
41 virtual void draw(SkCanvas* canvas) {
42 for (size_t i = 0; i < fObjects.size(); ++i) {
43 fObjects[i]->draw(canvas);
44 }
45 }
46
47 virtual bool animate(double nanos) {
48 for (size_t i = 0; i < fObjects.size(); ++i) {
49 fObjects[i]->animate(nanos);
50 }
51 return true;
52 }
53
54 // The default impl handles +/- to add or remove N objects from the scene
55 virtual bool onChar(SkUnichar uni) {
56 bool handled = false;
57 switch (uni) {
58 case '+':
59 case '=':
60 for (int i = 0; i < fObjectIncrement; ++i) {
61 fObjects.push_back(this->createObject());
62 }
63 handled = true;
64 break;
65 case '-':
66 case '_':
67 if (fObjects.size() > (size_t) fObjectIncrement) {
68 fObjects.resize(fObjects.size() - (size_t) fObjectIncrement);
69 }
70 handled = true;
71 break;
72 default:
73 break;
74 }
75
76 return handled;
77 }
78
79protected:
80 virtual std::unique_ptr<MMObject> createObject() = 0;
81
83 for (int i = 0; i < fStartingObjectCount; ++i) {
84 fObjects.push_back(this->createObject());
85 }
86 }
87
88 [[maybe_unused]] SkSize fSize;
89
92
93 std::vector<std::unique_ptr<MMObject>> fObjects;
95};
96
97class MotionMarkSlide : public Slide {
98public:
99 MotionMarkSlide() = default;
100
101 bool onChar(SkUnichar uni) override {
102 return fStage->onChar(uni);
103 }
104
105 void draw(SkCanvas* canvas) override {
106 fStage->draw(canvas);
107 }
108
109 bool animate(double nanos) override {
110 return fStage->animate(nanos);
111 }
112
113protected:
114 std::unique_ptr<Stage> fStage;
115};
116
117
118namespace {
119
120float time_counter_value(double nanos, float factor) {
121 constexpr double kMillisPerNano = 0.0000001;
122 return static_cast<float>(nanos*kMillisPerNano)/factor;
123}
124
125float time_fractional_value(double nanos, float cycleLengthMs) {
126 return SkScalarFraction(time_counter_value(nanos, cycleLengthMs));
127}
128
129// The following functions match the input processing that Chrome's canvas2d layer performs before
130// calling into Skia.
131
132// See https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/modules/canvas/canvas2d/canvas_path.cc;drc=572074cb06425797e7e110511db405134cf67e2f;l=299
133void canonicalize_angle(float* startAngle, float* endAngle) {
134 float newStartAngle = SkScalarMod(*startAngle, 360.f);
135 float delta = newStartAngle - *startAngle;
136 *startAngle = newStartAngle;
137 *endAngle = *endAngle + delta;
138}
139
140// See https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/modules/canvas/canvas2d/canvas_path.cc;drc=572074cb06425797e7e110511db405134cf67e2f;l=245
141float adjust_end_angle(float startAngle, float endAngle, bool ccw) {
142 float newEndAngle = endAngle;
143 if (!ccw && endAngle - startAngle >= 360.f) {
144 newEndAngle = startAngle + 360.f;
145 } else if (ccw && startAngle - endAngle >= 360.f) {
146 newEndAngle = startAngle - 360.f;
147 } else if (!ccw && startAngle > endAngle) {
148 newEndAngle = startAngle + (360.f - SkScalarMod(startAngle - endAngle, 360.f));
149 } else if (ccw && startAngle < endAngle) {
150 newEndAngle = startAngle - (360.f - SkScalarMod(endAngle - startAngle, 360.f));
151 }
152
153 return newEndAngle;
154}
155
156} // namespace
157
158///////////////////////////////////////////////////////////////////////////////////////////////////
159// Canvas Lines
160///////////////////////////////////////////////////////////////////////////////////////////////////
167
169public:
171 int circle = random->nextRangeU(0, 3);
172
173 static constexpr SkColor kColors[] = {
174 0xffe01040, 0xff10c030, 0xff744cba, 0xffe05010
175 };
176 fColor = kColors[circle];
177 fLineWidth = std::pow(random->nextF(), 12) * 20 + 3;
178 fOmega = random->nextF() * 3 + 0.2f;
179 float theta = random->nextRangeF(0, 2*SK_ScalarPI);
180 fCosTheta = std::cos(theta);
181 fSinTheta = std::sin(theta);
182 fStart = params.fCircleCenters[circle] + SkPoint::Make(params.fCircleRadius * fCosTheta,
183 params.fCircleRadius * fSinTheta);
184 fLength = params.fLineMinimum;
185 fLength += std::pow(random->nextF(), 8) * params.fLineLengthMaximum;
186 fSegmentDirection = random->nextF() > 0.5 ? -1 : 1;
187 }
188
189 ~CanvasLineSegment() override = default;
190
191 void draw(SkCanvas* canvas) override {
193 paint.setAntiAlias(true);
194 paint.setColor(fColor);
195 paint.setStrokeWidth(fLineWidth);
197
198 SkPoint end = {
199 fStart.fX + fSegmentDirection * fLength * fCosTheta,
200 fStart.fY + fSegmentDirection * fLength * fSinTheta
201 };
202 canvas->drawLine(fStart, end, paint);
203 }
204
205 void animate(double nanos) override {
206 fLength += std::sin(time_counter_value(nanos, 100) * fOmega);
207 }
208
209private:
210 SkColor fColor;
211 float fLineWidth;
212 float fOmega;
213 float fCosTheta;
214 float fSinTheta;
215 SkPoint fStart;
216 float fLength;
217 float fSegmentDirection;
218};
219
221public:
223 : Stage(size, /*startingObjectCount=*/5000, /*objectIncrement*/1000) {
224 fParams.fLineMinimum = 20;
225 fParams.fLineLengthMaximum = 40;
226 fParams.fCircleRadius = fSize.fWidth/8 - .4 * (fParams.fLineMinimum +
227 fParams.fLineLengthMaximum);
228 fParams.fCircleCenters[0] = SkPoint::Make(5.5 / 32 * fSize.fWidth, 2.1 / 3*fSize.fHeight);
229 fParams.fCircleCenters[1] = SkPoint::Make(12.5 / 32 * fSize.fWidth, .9 / 3*fSize.fHeight);
230 fParams.fCircleCenters[2] = SkPoint::Make(19.5 / 32 * fSize.fWidth, 2.1 / 3*fSize.fHeight);
231 fParams.fCircleCenters[3] = SkPoint::Make(26.5 / 32 * fSize.fWidth, .9 / 3*fSize.fHeight);
232 fHalfSize = SkSize::Make(fSize.fWidth * 0.5f, fSize.fHeight * 0.5f);
233 fTwoFifthsSizeX = fSize.fWidth * .4;
234
235 this->initializeObjects();
236 }
237
238 ~CanvasLineSegmentStage() override = default;
239
240 void draw(SkCanvas* canvas) override {
241 canvas->clear(SK_ColorWHITE);
242
243 float dx = fTwoFifthsSizeX * std::cos(fCurrentAngle);
244 float dy = fTwoFifthsSizeX * std::sin(fCurrentAngle);
245
246 float colorStopStep = SkScalarInterp(-.1f, .1f, fCurrentGradientStep);
247 int brightnessStep = SkScalarRoundToInt(SkScalarInterp(32, 64, fCurrentGradientStep));
248
249 SkColor color1Step = SkColorSetARGB(brightnessStep,
250 brightnessStep,
251 (brightnessStep << 1),
252 102);
253 SkColor color2Step = SkColorSetARGB((brightnessStep << 1),
254 (brightnessStep << 1),
255 brightnessStep,
256 102);
257 SkPoint pts[2] = {
258 {fHalfSize.fWidth + dx, fHalfSize.fHeight + dy},
259 {fHalfSize.fWidth - dx, fHalfSize.fHeight - dy}
260 };
261 SkColor colors[] = {
262 color1Step,
263 color1Step,
264 color2Step,
265 color2Step
266 };
267 float pos[] = {
268 0,
269 0.2f + colorStopStep,
270 0.8f - colorStopStep,
271 1
272 };
273 sk_sp<SkShader> gradientShader = SkGradientShader::MakeLinear(pts, colors, pos, 4,
275
277 paint.setAntiAlias(true);
278 paint.setStrokeWidth(15);
279 for (int i = 0; i < 4; i++) {
280 const SkColor strokeColors[] = {
281 0xffe01040, 0xff10c030, 0xff744cba, 0xffe05010
282 };
283 const SkColor fillColors[] = {
284 0xff70051d, 0xff016112, 0xff2F0C6E, 0xff702701
285 };
286 paint.setColor(strokeColors[i]);
288 SkRect arcRect = SkRect::MakeXYWH(fParams.fCircleCenters[i].fX - fParams.fCircleRadius,
289 fParams.fCircleCenters[i].fY- fParams.fCircleRadius,
290 2*fParams.fCircleRadius,
291 2*fParams.fCircleRadius);
292 canvas->drawArc(arcRect, 0, 360, false, paint);
293 paint.setColor(fillColors[i]);
294 paint.setStyle(SkPaint::kFill_Style);
295 canvas->drawArc(arcRect, 0, 360, false, paint);
296 paint.setShader(gradientShader);
297 canvas->drawArc(arcRect, 0, 360, false, paint);
298 paint.setShader(nullptr);
299 }
300
301 this->Stage::draw(canvas);
302 }
303
304 bool animate(double nanos) override {
305 fCurrentAngle = time_fractional_value(nanos, 3000) * SK_ScalarPI * 2;
306 fCurrentGradientStep = 0.5f + 0.5f * std::sin(
307 time_fractional_value(nanos, 5000) * SK_ScalarPI * 2);
308
309 this->Stage::animate(nanos);
310 return true;
311 }
312
313 std::unique_ptr<MMObject> createObject() override {
314 return std::make_unique<CanvasLineSegment>(&fRandom,fParams);
315 }
316private:
317 LineSegmentParams fParams;
318 SkSize fHalfSize;
319 float fTwoFifthsSizeX;
320 float fCurrentAngle = 0;
321 float fCurrentGradientStep = 0.5f;
322};
323
324///////////////////////////////////////////////////////////////////////////////////////////////////
325// Canvas Arcs
326///////////////////////////////////////////////////////////////////////////////////////////////////
327
328class CanvasArc : public MMObject {
329public:
330 CanvasArc(SkRandom* random, SkSize size) {
331 constexpr float kMaxX = 6;
332 constexpr float kMaxY = 3;
333
334 const SkColor baseColors[3] = {
335 0xff101010, 0xff808080, 0xffc0c0c0
336 };
337 const SkColor bonusColors[3] = {
338 0xffe01040, 0xff10c030, 0xffe05010
339 };
340 float distanceX = size.fWidth / kMaxX;
341 float distanceY = size.fHeight / (kMaxY + 1);
342 int randY = random->nextRangeU(0, kMaxY);
343 int randX = random->nextRangeU(0, kMaxX - 1 * (randY % 2));
344
345 fPoint = SkPoint::Make(distanceX * (randX + (randY % 2) / 2), distanceY * (randY + 0.5f));
346
347 fRadius = 20 + std::pow(random->nextF(), 5) * (std::min(distanceX, distanceY) / 1.8f);
348 fStartAngle = random->nextRangeF(0, 2*SK_ScalarPI);
349 fEndAngle = random->nextRangeF(0, 2*SK_ScalarPI);
350 fOmega = (random->nextF() - 0.5f) * 0.3f;
351 fCounterclockwise = random->nextBool();
352 // The MotionMark code appends a random element from an array and appends it to the color
353 // array, then randomly picks from that. We'll just pick that random element and use it
354 // if the index is out of bounds for the base color array.
355 SkColor bonusColor = bonusColors[(randX + sk_float_ceil2int(randY * 0.5f)) % 3];
356 int colorIndex = random->nextRangeU(0, 3);
357 fColor = colorIndex == 3 ? bonusColor : baseColors[colorIndex];
358 fLineWidth = 1 + std::pow(random->nextF(), 5) * 30;
359 fDoStroke = random->nextRangeU(0, 3) != 0;
360 }
361
362 ~CanvasArc() override = default;
363
364 void draw(SkCanvas* canvas) override {
366 paint.setAntiAlias(true);
367 paint.setColor(fColor);
368 SkRect arcRect = SkRect::MakeXYWH(fPoint.fX - fRadius, fPoint.fY - fRadius,
369 2*fRadius, 2*fRadius);
370
371 float startAngleDeg = fStartAngle * 180.f / SK_ScalarPI;
372 float endAngleDeg = fEndAngle * 180.f / SK_ScalarPI;
373 canonicalize_angle(&startAngleDeg, &endAngleDeg);
374 endAngleDeg = adjust_end_angle(startAngleDeg, endAngleDeg, fCounterclockwise);
375
376 float sweepAngle = startAngleDeg - endAngleDeg;
377
378 if (fDoStroke) {
379 paint.setStrokeWidth(fLineWidth);
381 canvas->drawArc(arcRect, startAngleDeg, sweepAngle, false, paint);
382 } else {
383 paint.setStyle(SkPaint::kFill_Style);
384 // The MotionMark code creates a path for fills via lineTo(point), arc(), lineTo(point).
385 // For now we'll just use drawArc for both but might need to revisit.
386 canvas->drawArc(arcRect, startAngleDeg, sweepAngle, true, paint);
387 }
388 }
389
390 void animate(double /*nanos*/) override {
391 fStartAngle += fOmega;
392 fEndAngle += fOmega / 2;
393 }
394
395private:
396 SkPoint fPoint;
397 float fRadius;
398 float fStartAngle; // in radians
399 float fEndAngle; // in radians
400 SkColor fColor;
401 float fOmega; // in radians
402 bool fDoStroke;
403 bool fCounterclockwise;
404 float fLineWidth;
405};
406
407class CanvasArcStage : public Stage {
408public:
410 : Stage(size, /*startingObjectCount=*/1000, /*objectIncrement=*/200) {
411 this->initializeObjects();
412 }
413
414 ~CanvasArcStage() override = default;
415
416 void draw(SkCanvas* canvas) override {
417 canvas->clear(SK_ColorWHITE);
418 this->Stage::draw(canvas);
419 }
420
421 std::unique_ptr<MMObject> createObject() override {
422 return std::make_unique<CanvasArc>(&fRandom, fSize);
423 }
424};
425
426///////////////////////////////////////////////////////////////////////////////////////////////////
427// Paths
428///////////////////////////////////////////////////////////////////////////////////////////////////
429
430class CanvasLinePoint : public MMObject {
431protected:
432 void setEndPoint(SkRandom* random, SkSize size, SkPoint* prevCoord) {
433 const SkSize kGridSize = { 80, 40 };
434 const SkPoint kGridCenter = { 40, 20 };
435 const SkPoint kOffsets[4] = {
436 {-4, 0},
437 {2, 0},
438 {1, -2},
439 {1, 2}
440 };
441
442 SkPoint coordinate = prevCoord ? *prevCoord : kGridCenter;
443 if (prevCoord) {
444 SkPoint offset = kOffsets[random->nextRangeU(0, 3)];
445 coordinate += offset;
446 if (coordinate.fX < 0 || coordinate.fX > kGridSize.width())
447 coordinate.fX -= offset.fX * 2;
448 if (coordinate.fY < 0 || coordinate.fY > kGridSize.height())
449 coordinate.fY -= offset.fY * 2;
450 }
451
452 fPoint = SkPoint::Make((coordinate.fX + 0.5f) * size.width() / (kGridSize.width() + 1),
453 (coordinate.fY + 0.5f) * size.height() / (kGridSize.height() + 1));
454 fCoordinate = coordinate;
455 }
456
457public:
459 const SkColor kColors[7] = {
460 0xff101010, 0xff808080, 0xffc0c0c0, 0xff101010, 0xff808080, 0xffc0c0c0, 0xffe01040
461 };
462 fColor = kColors[random->nextRangeU(0, 6)];
463
464 fWidth = std::pow(random->nextF(), 5) * 20 + 1;
465 fIsSplit = random->nextBool();
466
467 this->setEndPoint(random, size, prev);
468 }
469
470 ~CanvasLinePoint() override = default;
471
472 virtual void append(SkPath* path) {
473 path->lineTo(fPoint);
474 }
475
476 // unused, all the work is done by append
477 void draw(SkCanvas*) override {}
478 void animate(double) override {}
479
480 SkColor getColor() { return fColor; }
481 float getWidth() { return fWidth; }
482 SkPoint getPoint() { return fPoint; }
483 SkPoint getCoord() { return fCoordinate; }
484 bool isSplit() { return fIsSplit; }
485 void toggleIsSplit() { fIsSplit = !fIsSplit; }
486
487private:
488 SkPoint fPoint;
489 SkPoint fCoordinate;
490 SkColor fColor;
491 float fWidth;
492 bool fIsSplit;
493};
494
496public:
498 : CanvasLinePoint(random, size, prev) {
499 // Note: The construction of these points is odd but mirrors the Javascript code.
500
501 // The chosen point from the base constructor is instead the control point.
502 fPoint2 = this->getPoint();
503
504 // Get another random point for the actual end point of the segment.
505 this->setEndPoint(random, size, prev);
506 }
507
508 void append(SkPath* path) override {
509 path->quadTo(fPoint2, this->getPoint());
510 }
511
512private:
513 SkPoint fPoint2;
514};
515
517public:
519 : CanvasLinePoint(random, size, prev) {
520 // Note: The construction of these points is odd but mirrors the Javascript code.
521
522 // The chosen point from the base constructor is instead the control point.
523 fPoint2 = this->getPoint();
524
525 // Get the second control point.
526 this->setEndPoint(random, size, prev);
527 fPoint3 = this->getPoint();
528
529 // Get third random point for the actual end point of the segment.
530 this->setEndPoint(random, size, prev);
531 }
532
533 void append(SkPath* path) override {
534 path->cubicTo(fPoint2, fPoint3, this->getPoint());
535 }
536
537private:
538 SkPoint fPoint2;
539 SkPoint fPoint3;
540};
541
542
543std::unique_ptr<CanvasLinePoint> make_line_path(SkRandom* random, SkSize size, SkPoint* prev) {
544 int choice = random->nextRangeU(0, 3);
545 switch (choice) {
546 case 0:
547 return std::make_unique<CanvasQuadraticSegment>(random, size, prev);
548 break;
549 case 1:
550 return std::make_unique<CanvasBezierSegment>(random, size, prev);
551 break;
552 case 2:
553 case 3:
554 default:
555 return std::make_unique<CanvasLinePoint>(random, size, prev);
556 break;
557 }
558}
559
561public:
563 : Stage(size, /*startingObjectCount=*/5000, /*objectIncrement=*/1000) {
564 this->initializeObjects();
565 }
566
567 ~CanvasLinePathStage() override = default;
568
569 void draw(SkCanvas* canvas) override {
570 canvas->clear(SK_ColorWHITE);
571
572 SkPath currentPath;
574 paint.setAntiAlias(true);
576 for (size_t i = 0; i < fObjects.size(); ++i) {
577 CanvasLinePoint* object = reinterpret_cast<CanvasLinePoint*>(fObjects[i].get());
578 if (i == 0) {
579 paint.setStrokeWidth(object->getWidth());
580 paint.setColor(object->getColor());
581 currentPath.moveTo(object->getPoint());
582 } else {
583 object->append(&currentPath);
584
585 if (object->isSplit()) {
586 canvas->drawPath(currentPath, paint);
587
588 paint.setStrokeWidth(object->getWidth());
589 paint.setColor(object->getColor());
590 currentPath.reset();
591 currentPath.moveTo(object->getPoint());
592 }
593
594 if (fRandom.nextF() > 0.995) {
595 object->toggleIsSplit();
596 }
597 }
598 }
599 canvas->drawPath(currentPath, paint);
600 }
601
602 bool animate(double /*nanos*/) override {
603 // Nothing to do, but return true so we redraw.
604 return true;
605 }
606
607 std::unique_ptr<MMObject> createObject() override {
608 if (fObjects.empty()) {
609 return make_line_path(&fRandom, fSize, nullptr);
610 } else {
611 CanvasLinePoint* prevObject = reinterpret_cast<CanvasLinePoint*>(fObjects.back().get());
612 SkPoint coord = prevObject->getCoord();
613 return make_line_path(&fRandom, fSize, &coord);
614 }
615 }
616};
617
618///////////////////////////////////////////////////////////////////////////////////////////////////
619
621public:
622 CanvasLinesSlide() {fName = "MotionMarkCanvasLines"; }
623
624 void load(SkScalar w, SkScalar h) override {
625 fStage = std::make_unique<CanvasLineSegmentStage>(SkSize::Make(w, h));
626 }
627};
628
630public:
631 CanvasArcsSlide() {fName = "MotionMarkCanvasArcs"; }
632
633 void load(SkScalar w, SkScalar h) override {
634 fStage = std::make_unique<CanvasArcStage>(SkSize::Make(w, h));
635 }
636};
637
639public:
640 PathsSlide() {fName = "MotionMarkPaths"; }
641
642 void load(SkScalar w, SkScalar h) override {
643 fStage = std::make_unique<CanvasLinePathStage>(SkSize::Make(w, h));
644 }
645};
646
647DEF_SLIDE( return new CanvasLinesSlide(); )
648DEF_SLIDE( return new CanvasArcsSlide(); )
649DEF_SLIDE( return new PathsSlide(); )
static const int kMaxY
static const int kMaxX
SkPoint pos
std::unique_ptr< CanvasLinePoint > make_line_path(SkRandom *random, SkSize size, SkPoint *prev)
static float prev(float f)
uint32_t SkColor
Definition SkColor.h:37
static constexpr SkColor SkColorSetARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
Definition SkColor.h:49
constexpr SkColor SK_ColorWHITE
Definition SkColor.h:122
#define sk_float_ceil2int(x)
#define SkScalarMod(x, y)
Definition SkScalar.h:41
#define SkScalarRoundToInt(x)
Definition SkScalar.h:37
static SkScalar SkScalarInterp(SkScalar A, SkScalar B, SkScalar t)
Definition SkScalar.h:131
static SkScalar SkScalarFraction(SkScalar x)
Definition SkScalar.h:67
#define SK_ScalarPI
Definition SkScalar.h:21
int32_t SkUnichar
Definition SkTypes.h:175
#define DEF_SLIDE(code)
Definition Slide.h:25
std::unique_ptr< MMObject > createObject() override
CanvasArcStage(SkSize size)
~CanvasArcStage() override=default
void draw(SkCanvas *canvas) override
void animate(double) override
CanvasArc(SkRandom *random, SkSize size)
void draw(SkCanvas *canvas) override
~CanvasArc() override=default
void load(SkScalar w, SkScalar h) override
CanvasBezierSegment(SkRandom *random, SkSize size, SkPoint *prev)
void append(SkPath *path) override
bool animate(double) override
std::unique_ptr< MMObject > createObject() override
CanvasLinePathStage(SkSize size)
~CanvasLinePathStage() override=default
void draw(SkCanvas *canvas) override
virtual void append(SkPath *path)
CanvasLinePoint(SkRandom *random, SkSize size, SkPoint *prev)
~CanvasLinePoint() override=default
void animate(double) override
void draw(SkCanvas *) override
void setEndPoint(SkRandom *random, SkSize size, SkPoint *prevCoord)
bool animate(double nanos) override
void draw(SkCanvas *canvas) override
CanvasLineSegmentStage(SkSize size)
std::unique_ptr< MMObject > createObject() override
~CanvasLineSegmentStage() override=default
~CanvasLineSegment() override=default
void draw(SkCanvas *canvas) override
void animate(double nanos) override
CanvasLineSegment(SkRandom *random, const LineSegmentParams &params)
void load(SkScalar w, SkScalar h) override
void append(SkPath *path) override
CanvasQuadraticSegment(SkRandom *random, SkSize size, SkPoint *prev)
virtual void animate(double)=0
virtual void draw(SkCanvas *canvas)=0
virtual ~MMObject()=default
std::unique_ptr< Stage > fStage
bool onChar(SkUnichar uni) override
MotionMarkSlide()=default
void draw(SkCanvas *canvas) override
bool animate(double nanos) override
void load(SkScalar w, SkScalar h) override
void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint &paint)
void clear(SkColor color)
Definition SkCanvas.h:1199
void drawArc(const SkRect &oval, SkScalar startAngle, SkScalar sweepAngle, bool useCenter, const SkPaint &paint)
void drawPath(const SkPath &path, const SkPaint &paint)
static sk_sp< SkShader > MakeLinear(const SkPoint pts[2], const SkColor colors[], const SkScalar pos[], int count, SkTileMode mode, uint32_t flags=0, const SkMatrix *localMatrix=nullptr)
@ kStroke_Style
set to stroke geometry
Definition SkPaint.h:194
@ kFill_Style
set to fill geometry
Definition SkPaint.h:193
SkPath & moveTo(SkScalar x, SkScalar y)
Definition SkPath.cpp:678
SkPath & reset()
Definition SkPath.cpp:360
float nextF()
Definition SkRandom.h:55
bool nextBool()
Definition SkRandom.h:117
float nextRangeF(float min, float max)
Definition SkRandom.h:64
uint32_t nextRangeU(uint32_t min, uint32_t max)
Definition SkRandom.h:80
Definition Slide.h:29
SkString fName
Definition Slide.h:54
virtual void draw(SkCanvas *canvas)
SkSize fSize
virtual ~Stage()=default
virtual bool animate(double nanos)
int fStartingObjectCount
int fObjectIncrement
SkRandom fRandom
void initializeObjects()
std::vector< std::unique_ptr< MMObject > > fObjects
virtual bool onChar(SkUnichar uni)
virtual std::unique_ptr< MMObject > createObject()=0
Stage(SkSize size, int startingObjectCount, int objectIncrement)
const Paint & paint
const EmbeddedViewParams * params
float SkScalar
Definition extension.cpp:12
glong glong end
SkScalar startAngle
Definition SkRecords.h:250
SkScalar w
SkScalar h
Point offset
float fX
x-axis value
static constexpr SkPoint Make(float x, float y)
float fY
y-axis value
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
Definition SkRect.h:659
static constexpr SkSize Make(SkScalar w, SkScalar h)
Definition SkSize.h:56
SkScalar fHeight
Definition SkSize.h:54
SkScalar width() const
Definition SkSize.h:76
SkScalar fWidth
Definition SkSize.h:53
SkScalar height() const
Definition SkSize.h:77