aboutsummaryrefslogtreecommitdiffhomepage
path: root/gm
diff options
context:
space:
mode:
authorGravatar Brian Salomon <bsalomon@google.com>2018-04-20 13:54:11 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-04-20 18:45:35 +0000
commit62e4f3daf7262463774ca0434a9232a8e2292350 (patch)
tree0402b8e6fb48469d3dc23c697ecc4fda9ee39fb2 /gm
parent2fda63abcdd4ba7ee41e5226b68c93b102b76fb2 (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.cpp117
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;)