1 /* 2 * Copyright 2016 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 8 #include "gm.h" 9 #include "SkAnimTimer.h" 10 #include "SkPath.h" 11 #include "SkDashPathEffect.h" 12 13 int dash1[] = { 1, 1 }; 14 int dash2[] = { 1, 3 }; 15 int dash3[] = { 1, 1, 3, 3 }; 16 int dash4[] = { 1, 3, 2, 4 }; 17 18 struct DashExample { 19 int* pattern; 20 int length; 21 } dashExamples[] = { 22 { dash1, SK_ARRAY_COUNT(dash1) }, 23 { dash2, SK_ARRAY_COUNT(dash2) }, 24 { dash3, SK_ARRAY_COUNT(dash3) }, 25 { dash4, SK_ARRAY_COUNT(dash4) } 26 }; 27 28 29 class DashCircleGM : public skiagm::GM { 30 public: DashCircleGM()31 DashCircleGM() : fRotation(0) { } 32 33 protected: onShortName()34 SkString onShortName() override { return SkString("dashcircle"); } 35 onISize()36 SkISize onISize() override { return SkISize::Make(900, 1200); } 37 onDraw(SkCanvas * canvas)38 void onDraw(SkCanvas* canvas) override { 39 SkPaint refPaint; 40 refPaint.setAntiAlias(true); 41 refPaint.setColor(0xFFbf3f7f); 42 refPaint.setStyle(SkPaint::kStroke_Style); 43 refPaint.setStrokeWidth(1); 44 const SkScalar radius = 125; 45 SkRect oval = SkRect::MakeLTRB(-radius - 20, -radius - 20, radius + 20, radius + 20); 46 SkPath circle; 47 circle.addCircle(0, 0, radius); 48 SkScalar circumference = radius * SK_ScalarPI * 2; 49 int wedges[] = { 6, 12, 36 }; 50 canvas->translate(radius+20, radius+20); 51 for (int wedge : wedges) { 52 SkScalar arcLength = 360.f / wedge; 53 canvas->save(); 54 for (const DashExample& dashExample : dashExamples) { 55 SkPath refPath; 56 int dashUnits = 0; 57 for (int index = 0; index < dashExample.length; ++index) { 58 dashUnits += dashExample.pattern[index]; 59 } 60 SkScalar unitLength = arcLength / dashUnits; 61 SkScalar angle = 0; 62 for (int index = 0; index < wedge; ++index) { 63 for (int i2 = 0; i2 < dashExample.length; i2 += 2) { 64 SkScalar span = dashExample.pattern[i2] * unitLength; 65 refPath.moveTo(0, 0); 66 refPath.arcTo(oval, angle, span, false); 67 refPath.close(); 68 angle += span + (dashExample.pattern[i2 + 1]) * unitLength; 69 } 70 } 71 canvas->save(); 72 canvas->rotate(fRotation); 73 canvas->drawPath(refPath, refPaint); 74 canvas->restore(); 75 SkPaint p; 76 p.setAntiAlias(true); 77 p.setStyle(SkPaint::kStroke_Style); 78 p.setStrokeWidth(10); 79 SkScalar intervals[4]; 80 int intervalCount = dashExample.length; 81 SkScalar dashLength = circumference / wedge / dashUnits; 82 for (int index = 0; index < dashExample.length; ++index) { 83 intervals[index] = dashExample.pattern[index] * dashLength; 84 } 85 p.setPathEffect(SkDashPathEffect::Make(intervals, intervalCount, 0)); 86 canvas->save(); 87 canvas->rotate(fRotation); 88 canvas->drawPath(circle, p); 89 canvas->restore(); 90 canvas->translate(0, radius * 2 + 50); 91 } 92 canvas->restore(); 93 canvas->translate(radius * 2 + 50, 0); 94 } 95 } 96 onAnimate(const SkAnimTimer & timer)97 bool onAnimate(const SkAnimTimer& timer) override { 98 constexpr SkScalar kDesiredDurationSecs = 100.0f; 99 100 fRotation = timer.scaled(360.0f/kDesiredDurationSecs, 360.0f); 101 return true; 102 } 103 104 private: 105 SkScalar fRotation; 106 107 typedef GM INHERITED; 108 }; 109 110 DEF_GM(return new DashCircleGM; ) 111