|  | /* | 
|  | * 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.h" | 
|  | #include "SkAnimTimer.h" | 
|  | #include "SkPath.h" | 
|  | #include "SkDashPathEffect.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(const SkAnimTimer& timer) override { | 
|  | static const SkScalar kDesiredDurationSecs = 100.0f; | 
|  |  | 
|  | fRotation = timer.scaled(360.0f/kDesiredDurationSecs, 360.0f); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | private: | 
|  | SkScalar fRotation; | 
|  |  | 
|  | typedef GM INHERITED; | 
|  | }; | 
|  |  | 
|  | DEF_GM(return new DashCircleGM; ) |