diff options
author | Brian Salomon <bsalomon@google.com> | 2018-04-20 13:54:11 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-04-20 18:45:35 +0000 |
commit | 62e4f3daf7262463774ca0434a9232a8e2292350 (patch) | |
tree | 0402b8e6fb48469d3dc23c697ecc4fda9ee39fb2 /gm | |
parent | 2fda63abcdd4ba7ee41e5226b68c93b102b76fb2 (diff) |
Analytic dashing of circles with single on/off intervals and butt caps.
Change-Id: If19ac52cb78af57572a102cec0084f5b6c037680
Reviewed-on: https://skia-review.googlesource.com/121882
Auto-Submit: Brian Salomon <bsalomon@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
Diffstat (limited to 'gm')
-rw-r--r-- | gm/dashcircle.cpp | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/gm/dashcircle.cpp b/gm/dashcircle.cpp index fbe08b7bbe..72e3d1c549 100644 --- a/gm/dashcircle.cpp +++ b/gm/dashcircle.cpp @@ -108,3 +108,120 @@ private: }; 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(const SkAnimTimer& timer) override { + fPhaseDegrees = timer.secs(); + 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;) |