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 25static const int gXY[] = { 26 4, 0, 0, -4, 8, -4, 12, 0, 8, 4, 0, 4 27}; 28 29static 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 51static 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 72class TestRastBuilder : public SkLayerRasterizer::Builder { 73public: 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 86class PathEffectView : public SampleView { 87 SkPath fPath; 88 SkPoint fClickPt; 89 SkScalar fPhase; 90 91public: 92 PathEffectView() : fPhase(0) { 93 } 94 95protected: 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 164private: 165 typedef SampleView INHERITED; 166}; 167 168////////////////////////////////////////////////////////////////////////////// 169 170static SkView* MyFactory() { return new PathEffectView; } 171static SkViewRegister reg(MyFactory); 172