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 sk_sp<SkPathEffect> corner = SkCornerPathEffect::Make(25); 21 sk_sp<SkPathEffect> compose; 22 if (pe) { 23 compose = SkPathEffect::MakeCompose(sk_ref_sp(pe), corner); 24 } else { 25 compose = corner; 26 } 27 paint->setPathEffect(compose); 28 } 29 30 static void hair_pe(SkPaint* paint) { 31 paint->setStrokeWidth(0); 32 } 33 34 static void hair2_pe(SkPaint* paint) { 35 paint->setStrokeWidth(0); 36 compose_pe(paint); 37 } 38 39 static void stroke_pe(SkPaint* paint) { 40 paint->setStrokeWidth(12); 41 compose_pe(paint); 42 } 43 44 static void dash_pe(SkPaint* paint) { 45 SkScalar inter[] = { 20, 10, 10, 10 }; 46 paint->setStrokeWidth(12); 47 paint->setPathEffect(SkDashPathEffect::Make(inter, SK_ARRAY_COUNT(inter), 0)); 48 compose_pe(paint); 49 } 50 51 constexpr int gXY[] = { 52 4, 0, 0, -4, 8, -4, 12, 0, 8, 4, 0, 4 53 }; 54 55 static void scale(SkPath* path, SkScalar scale) { 56 SkMatrix m; 57 m.setScale(scale, scale); 58 path->transform(m); 59 } 60 61 static void one_d_pe(SkPaint* paint) { 62 SkPath path; 63 path.moveTo(SkIntToScalar(gXY[0]), SkIntToScalar(gXY[1])); 64 for (unsigned i = 2; i < SK_ARRAY_COUNT(gXY); i += 2) 65 path.lineTo(SkIntToScalar(gXY[i]), SkIntToScalar(gXY[i+1])); 66 path.close(); 67 path.offset(SkIntToScalar(-6), 0); 68 scale(&path, 1.5f); 69 70 paint->setPathEffect(SkPath1DPathEffect::Make(path, SkIntToScalar(21), 0, 71 SkPath1DPathEffect::kRotate_Style)); 72 compose_pe(paint); 73 } 74 75 typedef void (*PE_Proc)(SkPaint*); 76 constexpr PE_Proc gPE[] = { hair_pe, hair2_pe, stroke_pe, dash_pe, one_d_pe }; 77 78 static void fill_pe(SkPaint* paint) { 79 paint->setStyle(SkPaint::kFill_Style); 80 paint->setPathEffect(nullptr); 81 } 82 83 static void discrete_pe(SkPaint* paint) { 84 paint->setPathEffect(SkDiscretePathEffect::Make(10, 4)); 85 } 86 87 static sk_sp<SkPathEffect> MakeTileEffect() { 88 SkMatrix m; 89 m.setScale(SkIntToScalar(12), SkIntToScalar(12)); 90 91 SkPath path; 92 path.addCircle(0, 0, SkIntToScalar(5)); 93 94 return SkPath2DPathEffect::Make(m, path); 95 } 96 97 static void tile_pe(SkPaint* paint) { 98 paint->setPathEffect(MakeTileEffect()); 99 } 100 101 constexpr PE_Proc gPE2[] = { fill_pe, discrete_pe, tile_pe }; 102 103 class PathEffectGM : public GM { 104 public: 105 PathEffectGM() {} 106 107 protected: 108 109 SkString onShortName() override { 110 return SkString("patheffect"); 111 } 112 113 SkISize onISize() override { return SkISize::Make(800, 600); } 114 115 void onDraw(SkCanvas* canvas) override { 116 SkPaint paint; 117 paint.setAntiAlias(true); 118 paint.setStyle(SkPaint::kStroke_Style); 119 120 SkPath path; 121 path.moveTo(20, 20); 122 path.lineTo(70, 120); 123 path.lineTo(120, 30); 124 path.lineTo(170, 80); 125 path.lineTo(240, 50); 126 127 canvas->save(); 128 for (size_t i = 0; i < SK_ARRAY_COUNT(gPE); i++) { 129 gPE[i](&paint); 130 canvas->drawPath(path, paint); 131 canvas->translate(0, 75); 132 } 133 canvas->restore(); 134 135 path.reset(); 136 SkRect r = { 0, 0, 250, 120 }; 137 path.addOval(r, SkPath::kCW_Direction); 138 r.inset(50, 50); 139 path.addRect(r, SkPath::kCCW_Direction); 140 141 canvas->translate(320, 20); 142 for (size_t i = 0; i < SK_ARRAY_COUNT(gPE2); i++) { 143 gPE2[i](&paint); 144 canvas->drawPath(path, paint); 145 canvas->translate(0, 160); 146 } 147 148 const SkIRect rect = SkIRect::MakeXYWH(20, 20, 60, 60); 149 for (size_t i = 0; i < SK_ARRAY_COUNT(gPE); i++) { 150 SkPaint p; 151 p.setAntiAlias(true); 152 p.setStyle(SkPaint::kFill_Style); 153 gPE[i](&p); 154 canvas->drawIRect(rect, p); 155 canvas->translate(75, 0); 156 } 157 } 158 159 private: 160 typedef GM INHERITED; 161 }; 162 163 DEF_GM( return new PathEffectGM; ) 164 165 } 166 167 ////////////////////////////////////////////////////////////////////////////// 168 #include "SkOpPathEffect.h" 169 170 class ComboPathEfectsGM : public skiagm::GM { 171 public: 172 ComboPathEfectsGM() {} 173 174 protected: 175 176 SkString onShortName() override { 177 return SkString("combo-patheffects"); 178 } 179 180 SkISize onISize() override { return SkISize::Make(360, 630); } 181 182 void onDraw(SkCanvas* canvas) override { 183 SkPath path0, path1, path2; 184 path0.addCircle(100, 100, 60); 185 path1.moveTo(20, 20); path1.cubicTo(20, 180, 140, 0, 140, 140); 186 187 sk_sp<SkPathEffect> effects[] = { 188 nullptr, 189 SkStrokePathEffect::Make(20, SkPaint::kRound_Join, SkPaint::kRound_Cap, 0), 190 SkMergePathEffect::Make(nullptr, 191 SkStrokePathEffect::Make(20, SkPaint::kRound_Join, 192 SkPaint::kRound_Cap, 0), 193 kDifference_SkPathOp), 194 SkMergePathEffect::Make(SkMatrixPathEffect::MakeTranslate(50, 30), 195 SkStrokePathEffect::Make(20, SkPaint::kRound_Join, 196 SkPaint::kRound_Cap, 0), 197 kReverseDifference_SkPathOp), 198 }; 199 200 SkPaint wireframe; 201 wireframe.setStyle(SkPaint::kStroke_Style); 202 wireframe.setAntiAlias(true); 203 204 SkPaint paint; 205 paint.setColor(0xFF8888FF); 206 paint.setAntiAlias(true); 207 208 for (auto& path : { path0, path1 }) { 209 canvas->save(); 210 for (auto pe : effects) { 211 paint.setPathEffect(pe); 212 canvas->drawPath(path, paint); 213 canvas->drawPath(path, wireframe); 214 215 canvas->translate(0, 150); 216 } 217 canvas->restore(); 218 canvas->translate(180, 0); 219 } 220 } 221 222 private: 223 typedef GM INHERITED; 224 }; 225 DEF_GM(return new ComboPathEfectsGM;) 226 227