1 /* 2 * Copyright 2011 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 "SampleCode.h" 9 #include "SkAnimTimer.h" 10 #include "SkView.h" 11 #include "SkCanvas.h" 12 #include "SkGradientShader.h" 13 #include "SkPath.h" 14 #include "SkRegion.h" 15 #include "SkShader.h" 16 #include "SkUtils.h" 17 #include "Sk1DPathEffect.h" 18 #include "SkCornerPathEffect.h" 19 #include "SkPathMeasure.h" 20 #include "SkRandom.h" 21 #include "SkColorPriv.h" 22 23 #define CORNER_RADIUS 12 24 25 static const int gXY[] = { 26 4, 0, 0, -4, 8, -4, 12, 0, 8, 4, 0, 4 27 }; 28 29 static sk_sp<SkPathEffect> make_pe(int flags, SkScalar phase) { 30 if (flags == 1) { 31 return SkCornerPathEffect::Make(SkIntToScalar(CORNER_RADIUS)); 32 } 33 34 SkPath path; 35 path.moveTo(SkIntToScalar(gXY[0]), SkIntToScalar(gXY[1])); 36 for (unsigned i = 2; i < SK_ARRAY_COUNT(gXY); i += 2) 37 path.lineTo(SkIntToScalar(gXY[i]), SkIntToScalar(gXY[i+1])); 38 path.close(); 39 path.offset(SkIntToScalar(-6), 0); 40 41 auto outer = SkPath1DPathEffect::Make(path, 12, phase, SkPath1DPathEffect::kRotate_Style); 42 43 if (flags == 2) 44 return outer; 45 46 auto inner = SkCornerPathEffect::Make(SkIntToScalar(CORNER_RADIUS)); 47 48 return SkPathEffect::MakeCompose(outer, inner); 49 } 50 51 static sk_sp<SkPathEffect> make_warp_pe(SkScalar phase) { 52 SkPath path; 53 path.moveTo(SkIntToScalar(gXY[0]), SkIntToScalar(gXY[1])); 54 for (unsigned i = 2; i < SK_ARRAY_COUNT(gXY); i += 2) { 55 path.lineTo(SkIntToScalar(gXY[i]), SkIntToScalar(gXY[i+1])); 56 } 57 path.close(); 58 path.offset(SkIntToScalar(-6), 0); 59 60 auto outer = SkPath1DPathEffect::Make( 61 path, 12, phase, SkPath1DPathEffect::kMorph_Style); 62 auto inner = SkCornerPathEffect::Make(SkIntToScalar(CORNER_RADIUS)); 63 64 return SkPathEffect::MakeCompose(outer, inner); 65 } 66 67 /////////////////////////////////////////////////////////// 68 69 #include "SkColorFilter.h" 70 #include "SkLayerRasterizer.h" 71 72 class TestRastBuilder : public SkLayerRasterizer::Builder { 73 public: 74 TestRastBuilder() { 75 SkPaint paint; 76 paint.setAntiAlias(true); 77 78 paint.setAlpha(0x66); 79 this->addLayer(paint, SkIntToScalar(4), SkIntToScalar(4)); 80 81 paint.setAlpha(0xFF); 82 this->addLayer(paint); 83 } 84 }; 85 86 class PathEffectView : public SampleView { 87 SkPath fPath; 88 SkPoint fClickPt; 89 SkScalar fPhase; 90 91 public: 92 PathEffectView() : fPhase(0) { 93 } 94 95 protected: 96 void onOnceBeforeDraw() override { 97 SkRandom rand; 98 int steps = 20; 99 SkScalar dist = SkIntToScalar(400); 100 SkScalar x = SkIntToScalar(20); 101 SkScalar y = SkIntToScalar(50); 102 103 fPath.moveTo(x, y); 104 for (int i = 0; i < steps; i++) { 105 x += dist/steps; 106 SkScalar tmpY = y + SkIntToScalar(rand.nextS() % 25); 107 if (i == steps/2) { 108 fPath.moveTo(x, tmpY); 109 } else { 110 fPath.lineTo(x, tmpY); 111 } 112 } 113 114 { 115 SkRect oval; 116 oval.set(SkIntToScalar(20), SkIntToScalar(30), 117 SkIntToScalar(100), SkIntToScalar(60)); 118 oval.offset(x, 0); 119 fPath.addRoundRect(oval, SkIntToScalar(8), SkIntToScalar(8)); 120 } 121 122 fClickPt.set(SkIntToScalar(200), SkIntToScalar(200)); 123 124 this->setBGColor(0xFFDDDDDD); 125 } 126 127 bool onQuery(SkEvent* evt) override { 128 if (SampleCode::TitleQ(*evt)) { 129 SampleCode::TitleR(evt, "PathEffects"); 130 return true; 131 } 132 return this->INHERITED::onQuery(evt); 133 } 134 135 void onDrawContent(SkCanvas* canvas) override { 136 SkPaint paint; 137 138 canvas->translate(0, 50); 139 140 paint.setColor(SK_ColorBLUE); 141 paint.setPathEffect(make_pe(2, fPhase)); 142 canvas->drawPath(fPath, paint); 143 144 canvas->translate(0, 50); 145 146 paint.setARGB(0xFF, 0, 0xBB, 0); 147 paint.setPathEffect(make_pe(3, fPhase)); 148 canvas->drawPath(fPath, paint); 149 150 canvas->translate(0, 50); 151 152 paint.setARGB(0xFF, 0, 0, 0); 153 paint.setPathEffect(make_warp_pe(fPhase)); 154 TestRastBuilder testRastBuilder; 155 paint.setRasterizer(testRastBuilder.detach()); 156 canvas->drawPath(fPath, paint); 157 } 158 159 bool onAnimate(const SkAnimTimer& timer) override { 160 fPhase = timer.scaled(40); 161 return true; 162 } 163 164 private: 165 typedef SampleView INHERITED; 166 }; 167 168 ////////////////////////////////////////////////////////////////////////////// 169 170 static SkView* MyFactory() { return new PathEffectView; } 171 static SkViewRegister reg(MyFactory); 172