blob: 37715f1b361d93f1dabe8533496d07232031cc49 [file] [log] [blame]
bsalomon@google.com632151b2012-02-13 15:18:34 +00001/*
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 */
Ben Wagner7fde8e12019-05-01 17:28:53 -04007
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "gm/gm.h"
9#include "include/core/SkCanvas.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040010#include "include/core/SkMatrix.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "include/core/SkPaint.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040012#include "include/core/SkPath.h"
13#include "include/core/SkPathEffect.h"
14#include "include/core/SkRect.h"
15#include "include/core/SkRefCnt.h"
16#include "include/core/SkScalar.h"
17#include "include/core/SkSize.h"
18#include "include/core/SkString.h"
19#include "include/core/SkTypes.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050020#include "include/effects/Sk1DPathEffect.h"
21#include "include/effects/Sk2DPathEffect.h"
22#include "include/effects/SkCornerPathEffect.h"
23#include "include/effects/SkDashPathEffect.h"
24#include "include/effects/SkDiscretePathEffect.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040025#include "include/effects/SkOpPathEffect.h"
26#include "include/pathops/SkPathOps.h"
27
28#include <initializer_list>
bsalomon@google.com632151b2012-02-13 15:18:34 +000029
30namespace skiagm {
31
32static void compose_pe(SkPaint* paint) {
33 SkPathEffect* pe = paint->getPathEffect();
reeda4393342016-03-18 11:22:57 -070034 sk_sp<SkPathEffect> corner = SkCornerPathEffect::Make(25);
35 sk_sp<SkPathEffect> compose;
bsalomon@google.com632151b2012-02-13 15:18:34 +000036 if (pe) {
Mike Reeda07741a2017-02-25 22:34:32 -050037 compose = SkPathEffect::MakeCompose(sk_ref_sp(pe), corner);
bsalomon@google.com632151b2012-02-13 15:18:34 +000038 } else {
39 compose = corner;
40 }
reeda4393342016-03-18 11:22:57 -070041 paint->setPathEffect(compose);
bsalomon@google.com632151b2012-02-13 15:18:34 +000042}
43
44static void hair_pe(SkPaint* paint) {
45 paint->setStrokeWidth(0);
46}
47
48static void hair2_pe(SkPaint* paint) {
49 paint->setStrokeWidth(0);
50 compose_pe(paint);
51}
52
53static void stroke_pe(SkPaint* paint) {
54 paint->setStrokeWidth(12);
55 compose_pe(paint);
56}
57
58static void dash_pe(SkPaint* paint) {
59 SkScalar inter[] = { 20, 10, 10, 10 };
60 paint->setStrokeWidth(12);
reeda4393342016-03-18 11:22:57 -070061 paint->setPathEffect(SkDashPathEffect::Make(inter, SK_ARRAY_COUNT(inter), 0));
bsalomon@google.com632151b2012-02-13 15:18:34 +000062 compose_pe(paint);
63}
64
mtkleindbfd7ab2016-09-01 11:24:54 -070065constexpr int gXY[] = {
bsalomon@google.com632151b2012-02-13 15:18:34 +0000664, 0, 0, -4, 8, -4, 12, 0, 8, 4, 0, 4
67};
68
69static void scale(SkPath* path, SkScalar scale) {
70 SkMatrix m;
71 m.setScale(scale, scale);
72 path->transform(m);
73}
74
75static void one_d_pe(SkPaint* paint) {
76 SkPath path;
77 path.moveTo(SkIntToScalar(gXY[0]), SkIntToScalar(gXY[1]));
78 for (unsigned i = 2; i < SK_ARRAY_COUNT(gXY); i += 2)
79 path.lineTo(SkIntToScalar(gXY[i]), SkIntToScalar(gXY[i+1]));
80 path.close();
81 path.offset(SkIntToScalar(-6), 0);
caryclark@google.com13130862012-06-06 12:10:45 +000082 scale(&path, 1.5f);
rmistry@google.comae933ce2012-08-23 18:19:56 +000083
reeda4393342016-03-18 11:22:57 -070084 paint->setPathEffect(SkPath1DPathEffect::Make(path, SkIntToScalar(21), 0,
85 SkPath1DPathEffect::kRotate_Style));
bsalomon@google.com632151b2012-02-13 15:18:34 +000086 compose_pe(paint);
87}
88
89typedef void (*PE_Proc)(SkPaint*);
mtkleindbfd7ab2016-09-01 11:24:54 -070090constexpr PE_Proc gPE[] = { hair_pe, hair2_pe, stroke_pe, dash_pe, one_d_pe };
bsalomon@google.com632151b2012-02-13 15:18:34 +000091
92static void fill_pe(SkPaint* paint) {
93 paint->setStyle(SkPaint::kFill_Style);
halcanary96fcdcc2015-08-27 07:41:13 -070094 paint->setPathEffect(nullptr);
bsalomon@google.com632151b2012-02-13 15:18:34 +000095}
96
97static void discrete_pe(SkPaint* paint) {
reeda4393342016-03-18 11:22:57 -070098 paint->setPathEffect(SkDiscretePathEffect::Make(10, 4));
bsalomon@google.com632151b2012-02-13 15:18:34 +000099}
100
reeda4393342016-03-18 11:22:57 -0700101static sk_sp<SkPathEffect> MakeTileEffect() {
bsalomon@google.com632151b2012-02-13 15:18:34 +0000102 SkMatrix m;
103 m.setScale(SkIntToScalar(12), SkIntToScalar(12));
104
105 SkPath path;
106 path.addCircle(0, 0, SkIntToScalar(5));
rmistry@google.comae933ce2012-08-23 18:19:56 +0000107
reeda4393342016-03-18 11:22:57 -0700108 return SkPath2DPathEffect::Make(m, path);
bsalomon@google.com632151b2012-02-13 15:18:34 +0000109}
110
111static void tile_pe(SkPaint* paint) {
reeda4393342016-03-18 11:22:57 -0700112 paint->setPathEffect(MakeTileEffect());
bsalomon@google.com632151b2012-02-13 15:18:34 +0000113}
114
mtkleindbfd7ab2016-09-01 11:24:54 -0700115constexpr PE_Proc gPE2[] = { fill_pe, discrete_pe, tile_pe };
bsalomon@google.com632151b2012-02-13 15:18:34 +0000116
117class PathEffectGM : public GM {
118public:
119 PathEffectGM() {}
120
121protected:
commit-bot@chromium.orga90c6802014-04-30 13:20:45 +0000122
mtklein36352bf2015-03-25 18:17:31 -0700123 SkString onShortName() override {
bsalomon@google.com632151b2012-02-13 15:18:34 +0000124 return SkString("patheffect");
125 }
126
mtklein36352bf2015-03-25 18:17:31 -0700127 SkISize onISize() override { return SkISize::Make(800, 600); }
bsalomon@google.com632151b2012-02-13 15:18:34 +0000128
mtklein36352bf2015-03-25 18:17:31 -0700129 void onDraw(SkCanvas* canvas) override {
bsalomon@google.com632151b2012-02-13 15:18:34 +0000130 SkPaint paint;
131 paint.setAntiAlias(true);
132 paint.setStyle(SkPaint::kStroke_Style);
133
134 SkPath path;
135 path.moveTo(20, 20);
136 path.lineTo(70, 120);
137 path.lineTo(120, 30);
138 path.lineTo(170, 80);
139 path.lineTo(240, 50);
140
bsalomon@google.com632151b2012-02-13 15:18:34 +0000141 canvas->save();
Robert Phillips20390c32018-08-17 11:01:03 -0400142 for (size_t i = 0; i < SK_ARRAY_COUNT(gPE); i++) {
bsalomon@google.com632151b2012-02-13 15:18:34 +0000143 gPE[i](&paint);
144 canvas->drawPath(path, paint);
145 canvas->translate(0, 75);
146 }
147 canvas->restore();
148
149 path.reset();
150 SkRect r = { 0, 0, 250, 120 };
Mike Reed30bc5272019-11-22 18:34:02 +0000151 path.addOval(r, SkPathDirection::kCW);
bsalomon@google.com632151b2012-02-13 15:18:34 +0000152 r.inset(50, 50);
Mike Reed30bc5272019-11-22 18:34:02 +0000153 path.addRect(r, SkPathDirection::kCCW);
bsalomon@google.com632151b2012-02-13 15:18:34 +0000154
155 canvas->translate(320, 20);
Robert Phillips20390c32018-08-17 11:01:03 -0400156 for (size_t i = 0; i < SK_ARRAY_COUNT(gPE2); i++) {
bsalomon@google.com632151b2012-02-13 15:18:34 +0000157 gPE2[i](&paint);
158 canvas->drawPath(path, paint);
159 canvas->translate(0, 160);
160 }
bsalomon@google.com22f42b72012-03-26 14:36:55 +0000161
Robert Phillips20390c32018-08-17 11:01:03 -0400162 const SkIRect rect = SkIRect::MakeXYWH(20, 20, 60, 60);
163 for (size_t i = 0; i < SK_ARRAY_COUNT(gPE); i++) {
bsalomon@google.com22f42b72012-03-26 14:36:55 +0000164 SkPaint p;
165 p.setAntiAlias(true);
166 p.setStyle(SkPaint::kFill_Style);
167 gPE[i](&p);
168 canvas->drawIRect(rect, p);
169 canvas->translate(75, 0);
170 }
bsalomon@google.com632151b2012-02-13 15:18:34 +0000171 }
172
173private:
174 typedef GM INHERITED;
175};
176
Hal Canarye964c182019-01-23 10:22:01 -0500177DEF_GM( return new PathEffectGM; )
bsalomon@google.com632151b2012-02-13 15:18:34 +0000178
179}
Mike Reed0ef539a2018-07-18 13:28:42 -0400180
181//////////////////////////////////////////////////////////////////////////////
Mike Reed0ef539a2018-07-18 13:28:42 -0400182
183class ComboPathEfectsGM : public skiagm::GM {
184public:
185 ComboPathEfectsGM() {}
186
187protected:
188
189 SkString onShortName() override {
190 return SkString("combo-patheffects");
191 }
192
193 SkISize onISize() override { return SkISize::Make(360, 630); }
194
195 void onDraw(SkCanvas* canvas) override {
196 SkPath path0, path1, path2;
197 path0.addCircle(100, 100, 60);
198 path1.moveTo(20, 20); path1.cubicTo(20, 180, 140, 0, 140, 140);
199
200 sk_sp<SkPathEffect> effects[] = {
201 nullptr,
202 SkStrokePathEffect::Make(20, SkPaint::kRound_Join, SkPaint::kRound_Cap, 0),
Mike Reed310f44d2018-07-19 13:47:44 -0400203 SkMergePathEffect::Make(nullptr,
204 SkStrokePathEffect::Make(20, SkPaint::kRound_Join,
205 SkPaint::kRound_Cap, 0),
206 kDifference_SkPathOp),
207 SkMergePathEffect::Make(SkMatrixPathEffect::MakeTranslate(50, 30),
208 SkStrokePathEffect::Make(20, SkPaint::kRound_Join,
209 SkPaint::kRound_Cap, 0),
210 kReverseDifference_SkPathOp),
Mike Reed0ef539a2018-07-18 13:28:42 -0400211 };
212
213 SkPaint wireframe;
214 wireframe.setStyle(SkPaint::kStroke_Style);
215 wireframe.setAntiAlias(true);
216
217 SkPaint paint;
218 paint.setColor(0xFF8888FF);
219 paint.setAntiAlias(true);
220
221 for (auto& path : { path0, path1 }) {
222 canvas->save();
223 for (auto pe : effects) {
224 paint.setPathEffect(pe);
225 canvas->drawPath(path, paint);
226 canvas->drawPath(path, wireframe);
227
228 canvas->translate(0, 150);
229 }
230 canvas->restore();
231 canvas->translate(180, 0);
232 }
233 }
234
235private:
236 typedef GM INHERITED;
237};
238DEF_GM(return new ComboPathEfectsGM;)
239