123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274 |
- /*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #include "gm/gm.h"
- #include "include/core/SkCanvas.h"
- #include "include/core/SkColor.h"
- #include "include/core/SkMatrix.h"
- #include "include/core/SkPaint.h"
- #include "include/core/SkPath.h"
- #include "include/core/SkPathEffect.h"
- #include "include/core/SkRect.h"
- #include "include/core/SkRefCnt.h"
- #include "include/core/SkScalar.h"
- #include "include/core/SkSize.h"
- #include "include/core/SkString.h"
- #include "include/core/SkTypes.h"
- #include "include/effects/SkDashPathEffect.h"
- #include "tools/timer/TimeUtils.h"
- int dash1[] = { 1, 1 };
- int dash2[] = { 1, 3 };
- int dash3[] = { 1, 1, 3, 3 };
- int dash4[] = { 1, 3, 2, 4 };
- struct DashExample {
- int* pattern;
- int length;
- } dashExamples[] = {
- { dash1, SK_ARRAY_COUNT(dash1) },
- { dash2, SK_ARRAY_COUNT(dash2) },
- { dash3, SK_ARRAY_COUNT(dash3) },
- { dash4, SK_ARRAY_COUNT(dash4) }
- };
- class DashCircleGM : public skiagm::GM {
- public:
- DashCircleGM() : fRotation(0) { }
- protected:
- SkString onShortName() override { return SkString("dashcircle"); }
- SkISize onISize() override { return SkISize::Make(900, 1200); }
- void onDraw(SkCanvas* canvas) override {
- SkPaint refPaint;
- refPaint.setAntiAlias(true);
- refPaint.setColor(0xFFbf3f7f);
- refPaint.setStyle(SkPaint::kStroke_Style);
- refPaint.setStrokeWidth(1);
- const SkScalar radius = 125;
- SkRect oval = SkRect::MakeLTRB(-radius - 20, -radius - 20, radius + 20, radius + 20);
- SkPath circle;
- circle.addCircle(0, 0, radius);
- SkScalar circumference = radius * SK_ScalarPI * 2;
- int wedges[] = { 6, 12, 36 };
- canvas->translate(radius+20, radius+20);
- for (int wedge : wedges) {
- SkScalar arcLength = 360.f / wedge;
- canvas->save();
- for (const DashExample& dashExample : dashExamples) {
- SkPath refPath;
- int dashUnits = 0;
- for (int index = 0; index < dashExample.length; ++index) {
- dashUnits += dashExample.pattern[index];
- }
- SkScalar unitLength = arcLength / dashUnits;
- SkScalar angle = 0;
- for (int index = 0; index < wedge; ++index) {
- for (int i2 = 0; i2 < dashExample.length; i2 += 2) {
- SkScalar span = dashExample.pattern[i2] * unitLength;
- refPath.moveTo(0, 0);
- refPath.arcTo(oval, angle, span, false);
- refPath.close();
- angle += span + (dashExample.pattern[i2 + 1]) * unitLength;
- }
- }
- canvas->save();
- canvas->rotate(fRotation);
- canvas->drawPath(refPath, refPaint);
- canvas->restore();
- SkPaint p;
- p.setAntiAlias(true);
- p.setStyle(SkPaint::kStroke_Style);
- p.setStrokeWidth(10);
- SkScalar intervals[4];
- int intervalCount = dashExample.length;
- SkScalar dashLength = circumference / wedge / dashUnits;
- for (int index = 0; index < dashExample.length; ++index) {
- intervals[index] = dashExample.pattern[index] * dashLength;
- }
- p.setPathEffect(SkDashPathEffect::Make(intervals, intervalCount, 0));
- canvas->save();
- canvas->rotate(fRotation);
- canvas->drawPath(circle, p);
- canvas->restore();
- canvas->translate(0, radius * 2 + 50);
- }
- canvas->restore();
- canvas->translate(radius * 2 + 50, 0);
- }
- }
- bool onAnimate(double nanos) override {
- constexpr SkScalar kDesiredDurationSecs = 100.0f;
- fRotation = TimeUtils::Scaled(1e-9 * nanos, 360.0f/kDesiredDurationSecs, 360.0f);
- return true;
- }
- private:
- SkScalar fRotation;
- typedef GM INHERITED;
- };
- DEF_GM(return new DashCircleGM; )
- class DashCircle2GM : public skiagm::GM {
- public:
- DashCircle2GM() {}
- protected:
- SkString onShortName() override { return SkString("dashcircle2"); }
- SkISize onISize() override { return SkISize::Make(635, 900); }
- void onDraw(SkCanvas* canvas) override {
- // These intervals are defined relative to tau.
- static constexpr SkScalar kIntervals[][2]{
- {0.333f, 0.333f},
- {0.015f, 0.015f},
- {0.01f , 0.09f },
- {0.097f, 0.003f},
- {0.02f , 0.04f },
- {0.1f , 0.2f },
- {0.25f , 0.25f },
- {0.6f , 0.7f }, // adds to > 1
- {1.2f , 0.8f }, // on is > 1
- {0.1f , 1.1f }, // off is > 1*/
- };
- static constexpr int kN = SK_ARRAY_COUNT(kIntervals);
- static constexpr SkScalar kRadius = 20.f;
- static constexpr SkScalar kStrokeWidth = 15.f;
- static constexpr SkScalar kPad = 5.f;
- static constexpr SkRect kCircle = {-kRadius, -kRadius, kRadius, kRadius};
- static constexpr SkScalar kThinRadius = kRadius * 1.5;
- static constexpr SkRect kThinCircle = {-kThinRadius, -kThinRadius,
- kThinRadius, kThinRadius};
- static constexpr SkScalar kThinStrokeWidth = 0.4f;
- sk_sp<SkPathEffect> deffects[SK_ARRAY_COUNT(kIntervals)];
- sk_sp<SkPathEffect> thinDEffects[SK_ARRAY_COUNT(kIntervals)];
- for (int i = 0; i < kN; ++i) {
- static constexpr SkScalar kTau = 2 * SK_ScalarPI;
- static constexpr SkScalar kCircumference = kRadius * kTau;
- SkScalar scaledIntervals[2] = {kCircumference * kIntervals[i][0],
- kCircumference * kIntervals[i][1]};
- deffects[i] = SkDashPathEffect::Make(
- scaledIntervals, 2, kCircumference * fPhaseDegrees * kTau / 360.f);
- static constexpr SkScalar kThinCircumference = kThinRadius * kTau;
- scaledIntervals[0] = kThinCircumference * kIntervals[i][0];
- scaledIntervals[1] = kThinCircumference * kIntervals[i][1];
- thinDEffects[i] = SkDashPathEffect::Make(
- scaledIntervals, 2, kThinCircumference * fPhaseDegrees * kTau / 360.f);
- }
- SkMatrix rotate;
- rotate.setRotate(25.f);
- static const SkMatrix kMatrices[]{
- SkMatrix::I(),
- SkMatrix::MakeScale(1.2f),
- SkMatrix::MakeAll(1, 0, 0, 0, -1, 0, 0, 0, 1), // y flipper
- SkMatrix::MakeAll(-1, 0, 0, 0, 1, 0, 0, 0, 1), // x flipper
- SkMatrix::MakeScale(0.7f),
- rotate,
- SkMatrix::Concat(
- SkMatrix::Concat(SkMatrix::MakeAll(-1, 0, 0, 0, 1, 0, 0, 0, 1), rotate),
- rotate)
- };
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setStrokeWidth(kStrokeWidth);
- paint.setStyle(SkPaint::kStroke_Style);
- // Compute the union of bounds of all of our test cases.
- SkRect bounds = SkRect::MakeEmpty();
- static const SkRect kBounds = kThinCircle.makeOutset(kThinStrokeWidth / 2.f,
- kThinStrokeWidth / 2.f);
- for (const auto& m : kMatrices) {
- SkRect devBounds;
- m.mapRect(&devBounds, kBounds);
- bounds.join(devBounds);
- }
- canvas->save();
- canvas->translate(-bounds.fLeft + kPad, -bounds.fTop + kPad);
- for (size_t i = 0; i < SK_ARRAY_COUNT(deffects); ++i) {
- canvas->save();
- for (const auto& m : kMatrices) {
- canvas->save();
- canvas->concat(m);
- paint.setPathEffect(deffects[i]);
- paint.setStrokeWidth(kStrokeWidth);
- canvas->drawOval(kCircle, paint);
- paint.setPathEffect(thinDEffects[i]);
- paint.setStrokeWidth(kThinStrokeWidth);
- canvas->drawOval(kThinCircle, paint);
- canvas->restore();
- canvas->translate(bounds.width() + kPad, 0);
- }
- canvas->restore();
- canvas->translate(0, bounds.height() + kPad);
- }
- canvas->restore();
- }
- protected:
- bool onAnimate(double nanos) override {
- fPhaseDegrees = 1e-9 * nanos;
- return true;
- }
- // Init with a non-zero phase for when run as a non-animating GM.
- SkScalar fPhaseDegrees = 12.f;
- };
- DEF_GM(return new DashCircle2GM;)
- DEF_SIMPLE_GM(maddash, canvas, 1600, 1600) {
- canvas->drawRect({0, 0, 1600, 1600}, SkPaint());
- SkPaint p;
- p.setColor(SK_ColorRED);
- p.setAntiAlias(true);
- p.setStyle(SkPaint::kStroke_Style);
- p.setStrokeWidth(380);
- SkScalar intvls[] = { 2.5, 10 /* 1200 */ };
- p.setPathEffect(SkDashPathEffect::Make(intvls, 2, 0));
- canvas->drawCircle(400, 400, 200, p);
- SkPath path;
- path.moveTo(800, 400);
- path.quadTo(1000, 400, 1000, 600);
- path.quadTo(1000, 800, 800, 800);
- path.quadTo(600, 800, 600, 600);
- path.quadTo(600, 400, 800, 400);
- path.close();
- canvas->translate(350, 150);
- p.setStrokeWidth(320);
- canvas->drawPath(path, p);
- path.reset();
- path.moveTo(800, 400);
- path.cubicTo(900, 400, 1000, 500, 1000, 600);
- path.cubicTo(1000, 700, 900, 800, 800, 800);
- path.cubicTo(700, 800, 600, 700, 600, 600);
- path.cubicTo(600, 500, 700, 400, 800, 400);
- path.close();
- canvas->translate(-550, 500);
- p.setStrokeWidth(300);
- canvas->drawPath(path, p);
- }
|