Flutter Engine
The Flutter Engine
patheffects.cpp
Go to the documentation of this file.
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
8#include "gm/gm.h"
14#include "include/core/SkRect.h"
17#include "include/core/SkSize.h"
26
27#include <initializer_list>
28
29namespace skiagm {
30
31static void compose_pe(SkPaint* paint) {
32 SkPathEffect* pe = paint->getPathEffect();
34 sk_sp<SkPathEffect> compose;
35 if (pe) {
36 compose = SkPathEffect::MakeCompose(sk_ref_sp(pe), corner);
37 } else {
38 compose = corner;
39 }
40 paint->setPathEffect(compose);
41}
42
43static void hair_pe(SkPaint* paint) {
44 paint->setStrokeWidth(0);
45}
46
47static void hair2_pe(SkPaint* paint) {
48 paint->setStrokeWidth(0);
50}
51
52static void stroke_pe(SkPaint* paint) {
53 paint->setStrokeWidth(12);
55}
56
57static void dash_pe(SkPaint* paint) {
58 SkScalar inter[] = { 20, 10, 10, 10 };
59 paint->setStrokeWidth(12);
60 paint->setPathEffect(SkDashPathEffect::Make(inter, std::size(inter), 0));
62}
63
64constexpr int gXY[] = {
654, 0, 0, -4, 8, -4, 12, 0, 8, 4, 0, 4
66};
67
69 SkMatrix m;
70 m.setScale(scale, scale);
71 return path.makeTransform(m);
72}
73
74static void one_d_pe(SkPaint* paint) {
76 b.moveTo(SkIntToScalar(gXY[0]), SkIntToScalar(gXY[1]));
77 for (unsigned i = 2; i < std::size(gXY); i += 2) {
78 b.lineTo(SkIntToScalar(gXY[i]), SkIntToScalar(gXY[i+1]));
79 }
80 b.close().offset(SkIntToScalar(-6), 0);
81 SkPath path = scale(b.detach(), 1.5f);
82
83 paint->setPathEffect(SkPath1DPathEffect::Make(path, SkIntToScalar(21), 0,
86}
87
88typedef void (*PE_Proc)(SkPaint*);
90
91static void fill_pe(SkPaint* paint) {
92 paint->setStyle(SkPaint::kFill_Style);
93 paint->setPathEffect(nullptr);
94}
95
96static void discrete_pe(SkPaint* paint) {
97 paint->setPathEffect(SkDiscretePathEffect::Make(10, 4));
98}
99
101 SkMatrix m;
102 m.setScale(SkIntToScalar(12), SkIntToScalar(12));
103
105}
106
107static void tile_pe(SkPaint* paint) {
108 paint->setPathEffect(MakeTileEffect());
109}
110
112
113class PathEffectGM : public GM {
114public:
116
117protected:
118 SkString getName() const override { return SkString("patheffect"); }
119
120 SkISize getISize() override { return SkISize::Make(800, 600); }
121
122 void onDraw(SkCanvas* canvas) override {
124 paint.setAntiAlias(true);
126
128 {20, 20},
129 {70, 120},
130 {120, 30},
131 {170, 80},
132 {240, 50},
133 }, false);
134
135 canvas->save();
136 for (size_t i = 0; i < std::size(gPE); i++) {
137 gPE[i](&paint);
138 canvas->drawPath(path, paint);
139 canvas->translate(0, 75);
140 }
141 canvas->restore();
142
143 path.reset();
144 SkRect r = { 0, 0, 250, 120 };
147 .detach();
148
149 canvas->translate(320, 20);
150 for (size_t i = 0; i < std::size(gPE2); i++) {
151 gPE2[i](&paint);
152 canvas->drawPath(path, paint);
153 canvas->translate(0, 160);
154 }
155
156 const SkIRect rect = SkIRect::MakeXYWH(20, 20, 60, 60);
157 for (size_t i = 0; i < std::size(gPE); i++) {
158 SkPaint p;
159 p.setAntiAlias(true);
160 p.setStyle(SkPaint::kFill_Style);
161 gPE[i](&p);
162 canvas->drawIRect(rect, p);
163 canvas->translate(75, 0);
164 }
165 }
166
167private:
168 using INHERITED = GM;
169};
170
171DEF_GM( return new PathEffectGM; )
172
173} // namespace skiagm
174
175//////////////////////////////////////////////////////////////////////////////
176
179
180namespace {
181/**
182 * Example path effect using CTM. This "strokes" a single line segment with some stroke width,
183 * and then inflates the result by some number of pixels.
184 */
185class StrokeLineInflated : public SkPathEffectBase {
186public:
187 StrokeLineInflated(float strokeWidth, float pxInflate)
188 : fRadius(strokeWidth / 2.f), fPxInflate(pxInflate) {}
189
190 bool onNeedsCTM() const final { return true; }
191
192 bool onFilterPath(SkPath* dst,
193 const SkPath& src,
194 SkStrokeRec* rec,
195 const SkRect* cullR,
196 const SkMatrix& ctm) const final {
197 SkASSERT(src.countPoints() == 2);
198 const SkPoint pts[2] = {src.getPoint(0), src.getPoint(1)};
199
200 SkMatrix invCtm;
201 if (!ctm.invert(&invCtm)) {
202 return false;
203 }
204
205 // For a line segment, we can just map the (scaled) normal vector to pixel-space,
206 // increase its length by the desired number of pixels, and then map back to canvas space.
207 SkPoint n = {pts[0].fY - pts[1].fY, pts[1].fX - pts[0].fX};
208 if (!n.setLength(fRadius)) {
209 return false;
210 }
211
212 SkPoint mappedN = ctm.mapVector(n.fX, n.fY);
213 if (!mappedN.setLength(mappedN.length() + fPxInflate)) {
214 return false;
215 }
216 n = invCtm.mapVector(mappedN.fX, mappedN.fY);
217
218 dst->moveTo(pts[0] + n);
219 dst->lineTo(pts[1] + n);
220 dst->lineTo(pts[1] - n);
221 dst->lineTo(pts[0] - n);
222 dst->close();
223
224 rec->setFillStyle();
225
226 return true;
227 }
228
229protected:
230 void flatten(SkWriteBuffer&) const final {}
231
232private:
233 SK_FLATTENABLE_HOOKS(StrokeLineInflated)
234
235 bool computeFastBounds(SkRect* bounds) const final { return false; }
236
237 const float fRadius;
238 const float fPxInflate;
239};
240
241sk_sp<SkFlattenable> StrokeLineInflated::CreateProc(SkReadBuffer&) { return nullptr; }
242
243} // namespace
244
246protected:
247 SkString getName() const override { return SkString("ctmpatheffect"); }
248
249 SkISize getISize() override { return SkISize::Make(800, 600); }
250
251 // TODO: ctm-aware path effects are currently CPU only
253 auto dctx = GrAsDirectContext(canvas->recordingContext());
254 return dctx == nullptr ? DrawResult::kOk : DrawResult::kSkip;
255 }
256
257 void onDraw(SkCanvas* canvas) override {
258 const float strokeWidth = 16;
259 const float pxInflate = 0.5f;
260 sk_sp<SkPathEffect> pathEffect(new StrokeLineInflated(strokeWidth, pxInflate));
261
262 SkPath path;
263 path.moveTo(100, 100);
264 path.lineTo(200, 200);
265
266 // Draw the inflated path, and a scaled version, in blue.
268 paint.setAntiAlias(true);
269 paint.setColor(SkColorSetA(SK_ColorBLUE, 0xff));
270 paint.setPathEffect(pathEffect);
271 canvas->drawPath(path, paint);
272 canvas->save();
273 canvas->translate(150, 0);
274 canvas->scale(2.5, 0.5f);
275 canvas->drawPath(path, paint);
276 canvas->restore();
277
278 // Draw the regular stroked version on top in green.
279 // The inflated version should be visible underneath as a blue "border".
280 paint.setPathEffect(nullptr);
282 paint.setStrokeWidth(strokeWidth);
283 paint.setColor(SkColorSetA(SK_ColorGREEN, 0xff));
284 canvas->drawPath(path, paint);
285 canvas->save();
286 canvas->translate(150, 0);
287 canvas->scale(2.5, 0.5f);
288 canvas->drawPath(path, paint);
289 canvas->restore();
290 }
291
292private:
293 using INHERITED = GM;
294};
295DEF_GM(return new CTMPathEffectGM;)
static const int strokeWidth
Definition: BlurTest.cpp:60
static GrDirectContext * GrAsDirectContext(GrContext_Base *base)
#define SkASSERT(cond)
Definition: SkAssert.h:116
constexpr SkColor SK_ColorBLUE
Definition: SkColor.h:135
static constexpr SkColor SkColorSetA(SkColor c, U8CPU a)
Definition: SkColor.h:82
constexpr SkColor SK_ColorGREEN
Definition: SkColor.h:131
#define SK_FLATTENABLE_HOOKS(type)
sk_sp< T > sk_ref_sp(T *obj)
Definition: SkRefCnt.h:381
#define SkIntToScalar(x)
Definition: SkScalar.h:57
SkISize getISize() override
DrawResult onGpuSetup(SkCanvas *canvas, SkString *, GraphiteTestContext *) override
SkString getName() const override
void onDraw(SkCanvas *canvas) override
void restore()
Definition: SkCanvas.cpp:461
void translate(SkScalar dx, SkScalar dy)
Definition: SkCanvas.cpp:1278
virtual GrRecordingContext * recordingContext() const
Definition: SkCanvas.cpp:1637
void drawIRect(const SkIRect &rect, const SkPaint &paint)
Definition: SkCanvas.h:1358
int save()
Definition: SkCanvas.cpp:447
void drawPath(const SkPath &path, const SkPaint &paint)
Definition: SkCanvas.cpp:1747
void scale(SkScalar sx, SkScalar sy)
Definition: SkCanvas.cpp:1289
static sk_sp< SkPathEffect > Make(SkScalar radius)
static sk_sp< SkPathEffect > Make(const SkScalar intervals[], int count, SkScalar phase)
static sk_sp< SkPathEffect > Make(SkScalar segLength, SkScalar dev, uint32_t seedAssist=0)
virtual void flatten(SkWriteBuffer &) const
Definition: SkFlattenable.h:67
void mapVector(SkScalar dx, SkScalar dy, SkVector *result) const
Definition: SkMatrix.h:1524
@ kStroke_Style
set to stroke geometry
Definition: SkPaint.h:194
@ kFill_Style
set to fill geometry
Definition: SkPaint.h:193
static sk_sp< SkPathEffect > Make(const SkPath &path, SkScalar advance, SkScalar phase, Style)
static sk_sp< SkPathEffect > Make(const SkMatrix &matrix, const SkPath &path)
SkPathBuilder & addRect(const SkRect &, SkPathDirection, unsigned startIndex)
SkPathBuilder & addOval(const SkRect &, SkPathDirection, unsigned startIndex)
virtual bool onNeedsCTM() const
virtual bool computeFastBounds(SkRect *bounds) const =0
virtual bool onFilterPath(SkPath *, const SkPath &, SkStrokeRec *, const SkRect *, const SkMatrix &) const =0
static sk_sp< SkPathEffect > MakeCompose(sk_sp< SkPathEffect > outer, sk_sp< SkPathEffect > inner)
Definition: SkPath.h:59
static SkPath Circle(SkScalar center_x, SkScalar center_y, SkScalar radius, SkPathDirection dir=SkPathDirection::kCW)
Definition: SkPath.cpp:3598
static SkPath Polygon(const SkPoint pts[], int count, bool isClosed, SkPathFillType=SkPathFillType::kWinding, bool isVolatile=false)
Definition: SkPath.cpp:3614
Definition: gm.h:110
GM(SkColor backgroundColor=SK_ColorWHITE)
Definition: gm.cpp:81
void onDraw(SkCanvas *canvas) override
SkString getName() const override
SkISize getISize() override
const Paint & paint
Definition: color_source.cc:38
float SkScalar
Definition: extension.cpp:12
static bool b
#define DEF_GM(CODE)
Definition: gm.h:40
Optional< SkRect > bounds
Definition: SkRecords.h:189
sk_sp< SkBlender > blender SkRect rect
Definition: SkRecords.h:350
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
dst
Definition: cp.py:12
void(* PE_Proc)(SkPaint *)
Definition: patheffects.cpp:88
constexpr PE_Proc gPE[]
Definition: patheffects.cpp:89
static void hair_pe(SkPaint *paint)
Definition: patheffects.cpp:43
static void compose_pe(SkPaint *paint)
Definition: patheffects.cpp:31
DEF_GM(return F(C(clipbox), 0.0f, 0.0f, {})) DEF_GM(return F(C(clipbox)
static void one_d_pe(SkPaint *paint)
Definition: patheffects.cpp:74
static void dash_pe(SkPaint *paint)
Definition: patheffects.cpp:57
constexpr PE_Proc gPE2[]
static void hair2_pe(SkPaint *paint)
Definition: patheffects.cpp:47
static sk_sp< SkPathEffect > MakeTileEffect()
static SkPath scale(const SkPath &path, SkScalar scale)
Definition: patheffects.cpp:68
static void fill_pe(SkPaint *paint)
Definition: patheffects.cpp:91
static void tile_pe(SkPaint *paint)
constexpr int gXY[]
Definition: patheffects.cpp:64
static void discrete_pe(SkPaint *paint)
Definition: patheffects.cpp:96
static void stroke_pe(SkPaint *paint)
Definition: patheffects.cpp:52
DrawResult
Definition: gm.h:104
Definition: SkRect.h:32
static constexpr SkIRect MakeXYWH(int32_t x, int32_t y, int32_t w, int32_t h)
Definition: SkRect.h:104
Definition: SkSize.h:16
static constexpr SkISize Make(int32_t w, int32_t h)
Definition: SkSize.h:20
bool setLength(float length)
Definition: SkPoint.cpp:30
float fX
x-axis value
Definition: SkPoint_impl.h:164
float length() const
Definition: SkPoint_impl.h:282
float fY
y-axis value
Definition: SkPoint_impl.h:165
SkRect makeInset(float dx, float dy) const
Definition: SkRect.h:987