1 /* 2 * Copyright 2012 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 #include "gm.h" 8 #include "SkCanvas.h" 9 #include "SkPaint.h" 10 #include "Sk1DPathEffect.h" 11 #include "Sk2DPathEffect.h" 12 #include "SkCornerPathEffect.h" 13 #include "SkDashPathEffect.h" 14 #include "SkDiscretePathEffect.h" 15 16 namespace skiagm { 17 18 static void compose_pe(SkPaint* paint) { 19 SkPathEffect* pe = paint->getPathEffect(); 20 SkPathEffect* corner = SkCornerPathEffect::Create(25); 21 SkPathEffect* compose; 22 if (pe) { 23 compose = SkComposePathEffect::Create(pe, corner); 24 corner->unref(); 25 } else { 26 compose = corner; 27 } 28 paint->setPathEffect(compose)->unref(); 29 } 30 31 static void hair_pe(SkPaint* paint) { 32 paint->setStrokeWidth(0); 33 } 34 35 static void hair2_pe(SkPaint* paint) { 36 paint->setStrokeWidth(0); 37 compose_pe(paint); 38 } 39 40 static void stroke_pe(SkPaint* paint) { 41 paint->setStrokeWidth(12); 42 compose_pe(paint); 43 } 44 45 static void dash_pe(SkPaint* paint) { 46 SkScalar inter[] = { 20, 10, 10, 10 }; 47 paint->setStrokeWidth(12); 48 paint->setPathEffect(SkDashPathEffect::Create(inter, SK_ARRAY_COUNT(inter), 49 0))->unref(); 50 compose_pe(paint); 51 } 52 53 static const int gXY[] = { 54 4, 0, 0, -4, 8, -4, 12, 0, 8, 4, 0, 4 55 }; 56 57 static void scale(SkPath* path, SkScalar scale) { 58 SkMatrix m; 59 m.setScale(scale, scale); 60 path->transform(m); 61 } 62 63 static void one_d_pe(SkPaint* paint) { 64 SkPath path; 65 path.moveTo(SkIntToScalar(gXY[0]), SkIntToScalar(gXY[1])); 66 for (unsigned i = 2; i < SK_ARRAY_COUNT(gXY); i += 2) 67 path.lineTo(SkIntToScalar(gXY[i]), SkIntToScalar(gXY[i+1])); 68 path.close(); 69 path.offset(SkIntToScalar(-6), 0); 70 scale(&path, 1.5f); 71 72 paint->setPathEffect(SkPath1DPathEffect::Create(path, SkIntToScalar(21), 0, 73 SkPath1DPathEffect::kRotate_Style))->unref(); 74 compose_pe(paint); 75 } 76 77 typedef void (*PE_Proc)(SkPaint*); 78 static const PE_Proc gPE[] = { hair_pe, hair2_pe, stroke_pe, dash_pe, one_d_pe }; 79 80 static void fill_pe(SkPaint* paint) { 81 paint->setStyle(SkPaint::kFill_Style); 82 paint->setPathEffect(NULL); 83 } 84 85 static void discrete_pe(SkPaint* paint) { 86 paint->setPathEffect(SkDiscretePathEffect::Create(10, 4))->unref(); 87 } 88 89 static SkPathEffect* MakeTileEffect() { 90 SkMatrix m; 91 m.setScale(SkIntToScalar(12), SkIntToScalar(12)); 92 93 SkPath path; 94 path.addCircle(0, 0, SkIntToScalar(5)); 95 96 return SkPath2DPathEffect::Create(m, path); 97 } 98 99 static void tile_pe(SkPaint* paint) { 100 paint->setPathEffect(MakeTileEffect())->unref(); 101 } 102 103 static const PE_Proc gPE2[] = { fill_pe, discrete_pe, tile_pe }; 104 105 class PathEffectGM : public GM { 106 public: 107 PathEffectGM() {} 108 109 protected: 110 virtual uint32_t onGetFlags() const SK_OVERRIDE { 111 return kSkipTiled_Flag; 112 } 113 114 SkString onShortName() { 115 return SkString("patheffect"); 116 } 117 118 SkISize onISize() { return SkISize::Make(800, 600); } 119 120 virtual void onDraw(SkCanvas* canvas) { 121 SkPaint paint; 122 paint.setAntiAlias(true); 123 paint.setStyle(SkPaint::kStroke_Style); 124 125 SkPath path; 126 path.moveTo(20, 20); 127 path.lineTo(70, 120); 128 path.lineTo(120, 30); 129 path.lineTo(170, 80); 130 path.lineTo(240, 50); 131 132 size_t i; 133 canvas->save(); 134 for (i = 0; i < SK_ARRAY_COUNT(gPE); i++) { 135 gPE[i](&paint); 136 canvas->drawPath(path, paint); 137 canvas->translate(0, 75); 138 } 139 canvas->restore(); 140 141 path.reset(); 142 SkRect r = { 0, 0, 250, 120 }; 143 path.addOval(r, SkPath::kCW_Direction); 144 r.inset(50, 50); 145 path.addRect(r, SkPath::kCCW_Direction); 146 147 canvas->translate(320, 20); 148 for (i = 0; i < SK_ARRAY_COUNT(gPE2); i++) { 149 gPE2[i](&paint); 150 canvas->drawPath(path, paint); 151 canvas->translate(0, 160); 152 } 153 154 SkIRect rect = SkIRect::MakeXYWH(20, 20, 60, 60); 155 for (i = 0; i < SK_ARRAY_COUNT(gPE); i++) { 156 SkPaint p; 157 p.setAntiAlias(true); 158 p.setStyle(SkPaint::kFill_Style); 159 gPE[i](&p); 160 canvas->drawIRect(rect, p); 161 canvas->translate(75, 0); 162 } 163 } 164 165 private: 166 typedef GM INHERITED; 167 }; 168 169 ////////////////////////////////////////////////////////////////////////////// 170 171 static GM* PathEffectFactory(void*) { return new PathEffectGM; } 172 static GMRegistry regPathEffect(PathEffectFactory); 173 174 } 175