Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
GrAAConvexTessellator.h
Go to the documentation of this file.
1/*
2 * Copyright 2015 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#ifndef GrAAConvexTessellator_DEFINED
9#define GrAAConvexTessellator_DEFINED
10
18
19class SkMatrix;
20class SkPath;
21
22//#define GR_AA_CONVEX_TESSELLATOR_VIZ 1
23
24// device space distance which we inset / outset points in order to create the soft antialiased edge
25static const SkScalar kAntialiasingRadius = 0.5f;
26
27// The AAConvexTessellator holds the global pool of points and the triangulation
28// that connects them. It also drives the tessellation process.
29// The outward facing normals of the original polygon are stored (in 'fNorms') to service
30// computeDepthFromEdge requests.
32public:
34 SkScalar strokeWidth = -1.0f,
36 SkScalar miterLimit = 0.0f)
37 : fSide(SkPointPriv::kOn_Side)
38 , fStrokeWidth(strokeWidth)
39 , fStyle(style)
40 , fJoin(join)
41 , fMiterLimit(miterLimit) {
42 }
43
44 SkPointPriv::Side side() const { return fSide; }
45
46 bool tessellate(const SkMatrix& m, const SkPath& path);
47
48 // The next five should only be called after tessellate to extract the result
49 int numPts() const { return fPts.size(); }
50 int numIndices() const { return fIndices.size(); }
51
52 const SkPoint& lastPoint() const { return fPts.back(); }
53 const SkPoint& point(int index) const { return fPts[index]; }
54 int index(int index) const { return fIndices[index]; }
55 SkScalar coverage(int index) const { return fCoverages[index]; }
56
57#if GR_AA_CONVEX_TESSELLATOR_VIZ
58 void draw(SkCanvas* canvas) const;
59#endif
60
61 // The tessellator can be reused for multiple paths by clearing in between
62 void rewind();
63
64private:
65 // CandidateVerts holds the vertices for the next ring while they are
66 // being generated. Its main function is to de-dup the points.
67 class CandidateVerts {
68 public:
69 void setReserve(int numPts) { fPts.reserve(numPts); }
70 void rewind() { fPts.clear(); }
71
72 int numPts() const { return fPts.size(); }
73
74 const SkPoint& lastPoint() const { return fPts.back().fPt; }
75 const SkPoint& firstPoint() const { return fPts[0].fPt; }
76 const SkPoint& point(int index) const { return fPts[index].fPt; }
77
78 int originatingIdx(int index) const { return fPts[index].fOriginatingIdx; }
79 int origEdge(int index) const { return fPts[index].fOrigEdgeId; }
80 bool needsToBeNew(int index) const { return fPts[index].fNeedsToBeNew; }
81
82 int addNewPt(const SkPoint& newPt, int originatingIdx, int origEdge, bool needsToBeNew) {
83 struct PointData* pt = fPts.append();
84 pt->fPt = newPt;
85 pt->fOrigEdgeId = origEdge;
86 pt->fOriginatingIdx = originatingIdx;
87 pt->fNeedsToBeNew = needsToBeNew;
88 return fPts.size() - 1;
89 }
90
91 int fuseWithPrior(int origEdgeId) {
92 fPts.back().fOrigEdgeId = origEdgeId;
93 fPts.back().fOriginatingIdx = -1;
94 fPts.back().fNeedsToBeNew = true;
95 return fPts.size() - 1;
96 }
97
98 int fuseWithNext() {
99 fPts[0].fOriginatingIdx = -1;
100 fPts[0].fNeedsToBeNew = true;
101 return 0;
102 }
103
104 int fuseWithBoth() {
105 if (fPts.size() > 1) {
106 fPts.pop_back();
107 }
108
109 fPts[0].fOriginatingIdx = -1;
110 fPts[0].fNeedsToBeNew = true;
111 return 0;
112 }
113
114 private:
115 struct PointData {
116 SkPoint fPt;
117 int fOriginatingIdx;
118 int fOrigEdgeId;
119 bool fNeedsToBeNew;
120 };
121
123 };
124
125 // The Ring holds a set of indices into the global pool that together define
126 // a single polygon inset.
127 class Ring {
128 public:
129 void setReserve(int numPts) { fPts.reserve(numPts); }
130 void rewind() { fPts.clear(); }
131
132 int numPts() const { return fPts.size(); }
133
134 void addIdx(int index, int origEdgeId) {
135 struct PointData* pt = fPts.append();
136 pt->fIndex = index;
137 pt->fOrigEdgeId = origEdgeId;
138 }
139
140 // Upgrade this ring so that it can behave like an originating ring
141 void makeOriginalRing() {
142 for (int i = 0; i < fPts.size(); ++i) {
143 fPts[i].fOrigEdgeId = fPts[i].fIndex;
144 }
145 }
146
147 // init should be called after all the indices have been added (via addIdx)
148 void init(const GrAAConvexTessellator& tess);
149 void init(const SkTDArray<SkVector>& norms, const SkTDArray<SkVector>& bisectors);
150
151 const SkPoint& norm(int index) const { return fPts[index].fNorm; }
152 const SkPoint& bisector(int index) const { return fPts[index].fBisector; }
153 int index(int index) const { return fPts[index].fIndex; }
154 int origEdgeID(int index) const { return fPts[index].fOrigEdgeId; }
155 void setOrigEdgeId(int index, int id) { fPts[index].fOrigEdgeId = id; }
156
157 #if GR_AA_CONVEX_TESSELLATOR_VIZ
158 void draw(SkCanvas* canvas, const GrAAConvexTessellator& tess) const;
159 #endif
160
161 private:
162 void computeNormals(const GrAAConvexTessellator& result);
163 void computeBisectors(const GrAAConvexTessellator& tess);
164
165 SkDEBUGCODE(bool isConvex(const GrAAConvexTessellator& tess) const;)
166
167 struct PointData {
168 SkPoint fNorm;
169 SkPoint fBisector;
170 int fIndex;
171 int fOrigEdgeId;
172 };
173
175 };
176
177 // Represents whether a given point is within a curve. A point is inside a curve only if it is
178 // an interior point within a quad, cubic, or conic, or if it is the endpoint of a quad, cubic,
179 // or conic with another curve meeting it at (more or less) the same angle.
180 enum CurveState {
181 // point is a sharp vertex
182 kSharp_CurveState,
183 // endpoint of a curve with the other side's curvature not yet determined
184 kIndeterminate_CurveState,
185 // point is in the interior of a curve
186 kCurve_CurveState
187 };
188
189 bool movable(int index) const { return fMovable[index]; }
190
191 // Movable points are those that can be slid along their bisector.
192 // Basically, a point is immovable if it is part of the original
193 // polygon or it results from the fusing of two bisectors.
194 int addPt(const SkPoint& pt, SkScalar depth, SkScalar coverage, bool movable, CurveState curve);
195 void popLastPt();
196 void popFirstPtShuffle();
197
198 void updatePt(int index, const SkPoint& pt, SkScalar depth, SkScalar coverage);
199
200 void addTri(int i0, int i1, int i2);
201
202 void reservePts(int count) {
203 fPts.reserve(count);
204 fCoverages.reserve(count);
205 fMovable.reserve(count);
206 }
207
208 SkScalar computeDepthFromEdge(int edgeIdx, const SkPoint& p) const;
209
210 bool computePtAlongBisector(int startIdx, const SkPoint& bisector,
211 int edgeIdx, SkScalar desiredDepth,
212 SkPoint* result) const;
213
214 void lineTo(const SkPoint& p, CurveState curve);
215
216 void lineTo(const SkMatrix& m, const SkPoint& p, CurveState curve);
217
218 void quadTo(const SkPoint pts[3]);
219
220 void quadTo(const SkMatrix& m, const SkPoint pts[3]);
221
222 void cubicTo(const SkMatrix& m, const SkPoint pts[4]);
223
224 void conicTo(const SkMatrix& m, const SkPoint pts[3], SkScalar w);
225
226 void terminate(const Ring& lastRing);
227
228 // return false on failure/degenerate path
229 bool extractFromPath(const SkMatrix& m, const SkPath& path);
230 void computeBisectors();
231 void computeNormals();
232
233 void fanRing(const Ring& ring);
234
235 Ring* getNextRing(Ring* lastRing);
236
237 void createOuterRing(const Ring& previousRing, SkScalar outset, SkScalar coverage,
238 Ring* nextRing);
239
240 bool createInsetRings(Ring& previousRing, SkScalar initialDepth, SkScalar initialCoverage,
241 SkScalar targetDepth, SkScalar targetCoverage, Ring** finalRing);
242
243 bool createInsetRing(const Ring& lastRing, Ring* nextRing,
244 SkScalar initialDepth, SkScalar initialCoverage, SkScalar targetDepth,
245 SkScalar targetCoverage, bool forceNew);
246
247 void validate() const;
248
249 // fPts, fCoverages, fMovable & fCurveState should always have the same # of elements
251 SkTDArray<SkScalar> fCoverages;
252 // movable points are those that can be slid further along their bisector
253 SkTDArray<bool> fMovable;
254 // Tracks whether a given point is interior to a curve. Such points are
255 // assumed to have shallow curvature.
256 SkTDArray<CurveState> fCurveState;
257
258 // The outward facing normals for the original polygon
260 // The inward facing bisector at each point in the original polygon. Only
261 // needed for exterior ring creation and then handed off to the initial ring.
262 SkTDArray<SkVector> fBisectors;
263
264 SkPointPriv::Side fSide; // winding of the original polygon
265
266 // The triangulation of the points
267 SkTDArray<int> fIndices;
268
269 Ring fInitialRing;
270#if GR_AA_CONVEX_TESSELLATOR_VIZ
271 // When visualizing save all the rings
272 SkTDArray<Ring*> fRings;
273#else
274 Ring fRings[2];
275#endif
276 CandidateVerts fCandidateVerts;
277
278 // the stroke width is only used for stroke or stroke-and-fill styles
279 SkScalar fStrokeWidth;
281
283
284 SkScalar fMiterLimit;
285
286 // accumulated error when removing near colinear points to prevent an
287 // overly greedy simplification
288 SkScalar fAccumLinearError;
289
290 SkTDArray<SkPoint> fPointBuffer;
291};
292
293
294#endif
SkPoint fPts[2]
SkVector fNorms[2]
SkPaint::Join fJoin
SkStrokeRec::Style fStyle
static const int outset
Definition BlurTest.cpp:58
static const int strokeWidth
Definition BlurTest.cpp:60
int count
static const SkScalar kAntialiasingRadius
#define SkDEBUGCODE(...)
Definition SkDebug.h:23
static void draw(SkCanvas *canvas, SkRect &target, int x, int y)
Definition aaclip.cpp:27
bool tessellate(const SkMatrix &m, const SkPath &path)
const SkPoint & lastPoint() const
SkScalar coverage(int index) const
GrAAConvexTessellator(SkStrokeRec::Style style=SkStrokeRec::kFill_Style, SkScalar strokeWidth=-1.0f, SkPaint::Join join=SkPaint::Join::kBevel_Join, SkScalar miterLimit=0.0f)
SkPointPriv::Side side() const
const SkPoint & point(int index) const
int index(int index) const
@ kBevel_Join
connects outside edges
Definition SkPaint.h:361
const T & back() const
Definition SkTDArray.h:162
int size() const
Definition SkTDArray.h:138
void reserve(int n)
Definition SkTDArray.h:187
float SkScalar
Definition extension.cpp:12
GAsyncResult * result
init(device_serial, adb_binary)
Definition _adb_path.py:12
SkScalar w
const uintptr_t id