Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Sk2DPathEffect.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2006 The Android Open Source Project
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
9
12#include "include/core/SkPath.h"
15#include "include/core/SkRect.h"
24
26public:
27 Sk2DPathEffect(const SkMatrix& mat) : fMatrix(mat) {
28 // Calling invert will set the type mask on both matrices, making them thread safe.
29 fMatrixIsInvertible = fMatrix.invert(&fInverse);
30 }
31
32protected:
33 /** New virtual, to be overridden by subclasses.
34 This is called once from filterPath, and provides the
35 uv parameter bounds for the path. Subsequent calls to
36 next() will receive u and v values within these bounds,
37 and then a call to end() will signal the end of processing.
38 */
39 virtual void begin(const SkIRect& uvBounds, SkPath* dst) const {}
40 virtual void next(const SkPoint& loc, int u, int v, SkPath* dst) const {}
41 virtual void end(SkPath* dst) const {}
42
43 /** Low-level virtual called per span of locations in the u-direction.
44 The default implementation calls next() repeatedly with each
45 location.
46 */
47 virtual void nextSpan(int x, int y, int ucount, SkPath* path) const {
48 if (!fMatrixIsInvertible) {
49 return;
50 }
51 #if defined(SK_BUILD_FOR_FUZZER)
52 if (ucount > 100) {
53 return;
54 }
55 #endif
56
57 const SkMatrix& mat = this->getMatrix();
58 SkPoint src, dst;
59
61 do {
62 mat.mapPoints(&dst, &src, 1);
63 this->next(dst, x++, y, path);
64 src.fX += SK_Scalar1;
65 } while (--ucount > 0);
66 }
67
68 const SkMatrix& getMatrix() const { return fMatrix; }
69
70 void flatten(SkWriteBuffer& buffer) const override {
71 buffer.writeMatrix(fMatrix);
72 }
73
74 bool onFilterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec,
75 const SkRect* cullRect, const SkMatrix&) const override {
76 if (!fMatrixIsInvertible) {
77 return false;
78 }
79
80 SkPath tmp;
81 SkIRect ir;
82
83 src.transform(fInverse, &tmp);
84 tmp.getBounds().round(&ir);
85 if (!ir.isEmpty()) {
86 this->begin(ir, dst);
87
88 SkRegion rgn;
89 rgn.setPath(tmp, SkRegion(ir));
90 SkRegion::Iterator iter(rgn);
91 for (; !iter.done(); iter.next()) {
92 const SkIRect& rect = iter.rect();
93#if defined(SK_BUILD_FOR_FUZZER)
94 if (rect.height() > 100) {
95 continue;
96 }
97#endif
98 for (int y = rect.fTop; y < rect.fBottom; ++y) {
99 this->nextSpan(rect.fLeft, y, rect.width(), dst);
100 }
101 }
102
103 this->end(dst);
104 }
105 return true;
106 }
107
108private:
109 SkMatrix fMatrix, fInverse;
110 bool fMatrixIsInvertible;
111
112 // For simplicity, assume fast bounds cannot be computed
113 bool computeFastBounds(SkRect*) const override { return false; }
114
116};
117
118///////////////////////////////////////////////////////////////////////////////
119
121public:
123 : Sk2DPathEffect(matrix)
124 , fWidth(width)
125 {
126 SkASSERT(width >= 0);
127 }
128
129 bool onFilterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec,
130 const SkRect* cullRect, const SkMatrix& ctm) const override {
131 if (this->INHERITED::onFilterPath(dst, src, rec, cullRect, ctm)) {
132 rec->setStrokeStyle(fWidth);
133 return true;
134 }
135 return false;
136 }
137
138 void nextSpan(int u, int v, int ucount, SkPath* dst) const override {
139 if (ucount > 1) {
140 SkPoint src[2], dstP[2];
141
143 src[1].set(SkIntToScalar(u+ucount) + SK_ScalarHalf, SkIntToScalar(v) + SK_ScalarHalf);
144 this->getMatrix().mapPoints(dstP, src, 2);
145
146 dst->moveTo(dstP[0]);
147 dst->lineTo(dstP[1]);
148 }
149 }
150
152 SkMatrix matrix;
153 buffer.readMatrix(&matrix);
154 SkScalar width = buffer.readScalar();
155 return SkLine2DPathEffect::Make(width, matrix);
156 }
157
158 void flatten(SkWriteBuffer &buffer) const override {
159 buffer.writeMatrix(this->getMatrix());
160 buffer.writeScalar(fWidth);
161 }
162
163 Factory getFactory() const override { return CreateProc; }
164 const char* getTypeName() const override { return "SkLine2DPathEffect"; }
165
166private:
167 SkScalar fWidth;
168
169 using INHERITED = Sk2DPathEffect;
170};
171
172/////////////////////////////////////////////////////////////////////////////////////////////////
173
175public:
176 SkPath2DPathEffectImpl(const SkMatrix& m, const SkPath& p) : INHERITED(m), fPath(p) {}
177
178 void next(const SkPoint& loc, int u, int v, SkPath* dst) const override {
179 dst->addPath(fPath, loc.fX, loc.fY);
180 }
181
183 SkMatrix matrix;
184 buffer.readMatrix(&matrix);
185 SkPath path;
186 buffer.readPath(&path);
187 return SkPath2DPathEffect::Make(matrix, path);
188 }
189
190 void flatten(SkWriteBuffer& buffer) const override {
191 buffer.writeMatrix(this->getMatrix());
192 buffer.writePath(fPath);
193 }
194
195 Factory getFactory() const override { return CreateProc; }
196 const char* getTypeName() const override { return "SkPath2DPathEffect"; }
197
198private:
199 SkPath fPath;
200
201 using INHERITED = Sk2DPathEffect;
202};
203
204//////////////////////////////////////////////////////////////////////////////////////////////////
205
207 if (!(width >= 0)) {
208 return nullptr;
209 }
211}
212
214 return sk_sp<SkPathEffect>(new SkPath2DPathEffectImpl(matrix, path));
215}
216
220
#define SkASSERT(cond)
Definition SkAssert.h:116
#define SK_REGISTER_FLATTENABLE(type)
#define SK_Scalar1
Definition SkScalar.h:18
#define SK_ScalarHalf
Definition SkScalar.h:19
#define SkIntToScalar(x)
Definition SkScalar.h:57
bool computeFastBounds(SkRect *) const override
virtual void end(SkPath *dst) const
bool onFilterPath(SkPath *dst, const SkPath &src, SkStrokeRec *rec, const SkRect *cullRect, const SkMatrix &) const override
virtual void next(const SkPoint &loc, int u, int v, SkPath *dst) const
const SkMatrix & getMatrix() const
virtual void begin(const SkIRect &uvBounds, SkPath *dst) const
Sk2DPathEffect(const SkMatrix &mat)
friend class Sk2DPathEffectBlitter
void flatten(SkWriteBuffer &buffer) const override
virtual void nextSpan(int x, int y, int ucount, SkPath *path) const
sk_sp< SkFlattenable >(* Factory)(SkReadBuffer &)
bool onFilterPath(SkPath *dst, const SkPath &src, SkStrokeRec *rec, const SkRect *cullRect, const SkMatrix &ctm) const override
SkLine2DPathEffectImpl(SkScalar width, const SkMatrix &matrix)
static sk_sp< SkFlattenable > CreateProc(SkReadBuffer &buffer)
const char * getTypeName() const override
void flatten(SkWriteBuffer &buffer) const override
Factory getFactory() const override
void nextSpan(int u, int v, int ucount, SkPath *dst) const override
static sk_sp< SkPathEffect > Make(SkScalar width, const SkMatrix &matrix)
static void RegisterFlattenables()
void mapPoints(SkPoint dst[], const SkPoint src[], int count) const
Definition SkMatrix.cpp:770
bool invert(SkMatrix *inverse) const
Definition SkMatrix.h:1206
static sk_sp< SkFlattenable > CreateProc(SkReadBuffer &buffer)
void flatten(SkWriteBuffer &buffer) const override
const char * getTypeName() const override
void next(const SkPoint &loc, int u, int v, SkPath *dst) const override
Factory getFactory() const override
SkPath2DPathEffectImpl(const SkMatrix &m, const SkPath &p)
static sk_sp< SkPathEffect > Make(const SkMatrix &matrix, const SkPath &path)
static void RegisterFlattenables()
const SkRect & getBounds() const
Definition SkPath.cpp:420
const SkIRect & rect() const
Definition SkRegion.h:501
bool done() const
Definition SkRegion.h:488
bool setPath(const SkPath &path, const SkRegion &clip)
void setStrokeStyle(SkScalar width, bool strokeAndFill=false)
virtual void writeScalar(SkScalar value)=0
virtual void writePath(const SkPath &path)=0
float SkScalar
Definition extension.cpp:12
glong glong end
static const uint8_t buffer[]
double y
double x
int32_t width
bool isEmpty() const
Definition SkRect.h:202
int32_t fLeft
smaller x-axis bounds
Definition SkRect.h:33
float fX
x-axis value
float fY
y-axis value
void round(SkIRect *dst) const
Definition SkRect.h:1228