blob: 2974cf02db6d12644fdf4ac5278d031aed98c86d [file] [log] [blame]
ethannicholase9709e82016-01-07 13:34:16 -08001/*
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#include "GrTessellator.h"
9
senorblancof57372d2016-08-31 10:36:19 -070010#include "GrDefaultGeoProcFactory.h"
ethannicholase9709e82016-01-07 13:34:16 -080011#include "GrPathUtils.h"
ethannicholase9709e82016-01-07 13:34:16 -080012
Herb Derby5cdc9dd2017-02-13 12:10:46 -050013#include "SkArenaAlloc.h"
senorblanco6599eff2016-03-10 08:38:45 -080014#include "SkGeometry.h"
15#include "SkPath.h"
Cary Clarkdf429f32017-11-08 11:44:31 -050016#include "SkPointPriv.h"
Stephen Whitee260c462017-12-19 18:09:54 -050017#include "SkTDPQueue.h"
ethannicholase9709e82016-01-07 13:34:16 -080018
Stephen White94b7e542018-01-04 14:01:10 -050019#include <algorithm>
ethannicholase9709e82016-01-07 13:34:16 -080020#include <stdio.h>
21
22/*
senorblancof57372d2016-08-31 10:36:19 -070023 * There are six stages to the basic algorithm:
ethannicholase9709e82016-01-07 13:34:16 -080024 *
25 * 1) Linearize the path contours into piecewise linear segments (path_to_contours()).
26 * 2) Build a mesh of edges connecting the vertices (build_edges()).
27 * 3) Sort the vertices in Y (and secondarily in X) (merge_sort()).
28 * 4) Simplify the mesh by inserting new vertices at intersecting edges (simplify()).
29 * 5) Tessellate the simplified mesh into monotone polygons (tessellate()).
30 * 6) Triangulate the monotone polygons directly into a vertex buffer (polys_to_triangles()).
31 *
senorblancof57372d2016-08-31 10:36:19 -070032 * For screenspace antialiasing, the algorithm is modified as follows:
33 *
34 * Run steps 1-5 above to produce polygons.
35 * 5b) Apply fill rules to extract boundary contours from the polygons (extract_boundaries()).
Stephen Whitebda29c02017-03-13 15:10:13 -040036 * 5c) Simplify boundaries to remove "pointy" vertices that cause inversions (simplify_boundary()).
senorblancof57372d2016-08-31 10:36:19 -070037 * 5d) Displace edges by half a pixel inward and outward along their normals. Intersect to find
38 * new vertices, and set zero alpha on the exterior and one alpha on the interior. Build a new
Stephen Whitebda29c02017-03-13 15:10:13 -040039 * antialiased mesh from those vertices (stroke_boundary()).
senorblancof57372d2016-08-31 10:36:19 -070040 * Run steps 3-6 above on the new mesh, and produce antialiased triangles.
41 *
ethannicholase9709e82016-01-07 13:34:16 -080042 * The vertex sorting in step (3) is a merge sort, since it plays well with the linked list
43 * of vertices (and the necessity of inserting new vertices on intersection).
44 *
Stephen Whitebda29c02017-03-13 15:10:13 -040045 * Stages (4) and (5) use an active edge list -- a list of all edges for which the
ethannicholase9709e82016-01-07 13:34:16 -080046 * sweep line has crossed the top vertex, but not the bottom vertex. It's sorted
47 * left-to-right based on the point where both edges are active (when both top vertices
48 * have been seen, so the "lower" top vertex of the two). If the top vertices are equal
49 * (shared), it's sorted based on the last point where both edges are active, so the
50 * "upper" bottom vertex.
51 *
52 * The most complex step is the simplification (4). It's based on the Bentley-Ottman
53 * line-sweep algorithm, but due to floating point inaccuracy, the intersection points are
54 * not exact and may violate the mesh topology or active edge list ordering. We
55 * accommodate this by adjusting the topology of the mesh and AEL to match the intersection
Stephen White3b5a3fa2017-06-06 14:51:19 -040056 * points. This occurs in two ways:
ethannicholase9709e82016-01-07 13:34:16 -080057 *
58 * A) Intersections may cause a shortened edge to no longer be ordered with respect to its
59 * neighbouring edges at the top or bottom vertex. This is handled by merging the
60 * edges (merge_collinear_edges()).
61 * B) Intersections may cause an edge to violate the left-to-right ordering of the
Stephen White019f6c02017-06-09 10:06:26 -040062 * active edge list. This is handled by detecting potential violations and rewinding
Stephen White3b5a3fa2017-06-06 14:51:19 -040063 * the active edge list to the vertex before they occur (rewind() during merging,
64 * rewind_if_necessary() during splitting).
ethannicholase9709e82016-01-07 13:34:16 -080065 *
66 * The tessellation steps (5) and (6) are based on "Triangulating Simple Polygons and
67 * Equivalent Problems" (Fournier and Montuno); also a line-sweep algorithm. Note that it
68 * currently uses a linked list for the active edge list, rather than a 2-3 tree as the
69 * paper describes. The 2-3 tree gives O(lg N) lookups, but insertion and removal also
70 * become O(lg N). In all the test cases, it was found that the cost of frequent O(lg N)
71 * insertions and removals was greater than the cost of infrequent O(N) lookups with the
72 * linked list implementation. With the latter, all removals are O(1), and most insertions
73 * are O(1), since we know the adjacent edge in the active edge list based on the topology.
74 * Only type 2 vertices (see paper) require the O(N) lookups, and these are much less
75 * frequent. There may be other data structures worth investigating, however.
76 *
77 * Note that the orientation of the line sweep algorithms is determined by the aspect ratio of the
78 * path bounds. When the path is taller than it is wide, we sort vertices based on increasing Y
79 * coordinate, and secondarily by increasing X coordinate. When the path is wider than it is tall,
80 * we sort by increasing X coordinate, but secondarily by *decreasing* Y coordinate. This is so
81 * that the "left" and "right" orientation in the code remains correct (edges to the left are
82 * increasing in Y; edges to the right are decreasing in Y). That is, the setting rotates 90
83 * degrees counterclockwise, rather that transposing.
84 */
85
86#define LOGGING_ENABLED 0
87
88#if LOGGING_ENABLED
89#define LOG printf
90#else
91#define LOG(...)
92#endif
93
ethannicholase9709e82016-01-07 13:34:16 -080094namespace {
95
Stephen White11f65e02017-02-16 19:00:39 -050096const int kArenaChunkSize = 16 * 1024;
Stephen Whitee260c462017-12-19 18:09:54 -050097#ifndef GR_TESSELLATOR_LEGACY_INVERSION_HANDLING
98const float kCosMiterAngle = 0.97f; // Corresponds to an angle of ~14 degrees.
99#endif
Stephen White11f65e02017-02-16 19:00:39 -0500100
ethannicholase9709e82016-01-07 13:34:16 -0800101struct Vertex;
102struct Edge;
Stephen Whitee260c462017-12-19 18:09:54 -0500103struct Event;
ethannicholase9709e82016-01-07 13:34:16 -0800104struct Poly;
105
106template <class T, T* T::*Prev, T* T::*Next>
senorblancoe6eaa322016-03-08 09:06:44 -0800107void list_insert(T* t, T* prev, T* next, T** head, T** tail) {
ethannicholase9709e82016-01-07 13:34:16 -0800108 t->*Prev = prev;
109 t->*Next = next;
110 if (prev) {
111 prev->*Next = t;
112 } else if (head) {
113 *head = t;
114 }
115 if (next) {
116 next->*Prev = t;
117 } else if (tail) {
118 *tail = t;
119 }
120}
121
122template <class T, T* T::*Prev, T* T::*Next>
senorblancoe6eaa322016-03-08 09:06:44 -0800123void list_remove(T* t, T** head, T** tail) {
ethannicholase9709e82016-01-07 13:34:16 -0800124 if (t->*Prev) {
125 t->*Prev->*Next = t->*Next;
126 } else if (head) {
127 *head = t->*Next;
128 }
129 if (t->*Next) {
130 t->*Next->*Prev = t->*Prev;
131 } else if (tail) {
132 *tail = t->*Prev;
133 }
134 t->*Prev = t->*Next = nullptr;
135}
136
137/**
138 * Vertices are used in three ways: first, the path contours are converted into a
139 * circularly-linked list of Vertices for each contour. After edge construction, the same Vertices
140 * are re-ordered by the merge sort according to the sweep_lt comparator (usually, increasing
141 * in Y) using the same fPrev/fNext pointers that were used for the contours, to avoid
142 * reallocation. Finally, MonotonePolys are built containing a circularly-linked list of
143 * Vertices. (Currently, those Vertices are newly-allocated for the MonotonePolys, since
144 * an individual Vertex from the path mesh may belong to multiple
145 * MonotonePolys, so the original Vertices cannot be re-used.
146 */
147
148struct Vertex {
senorblancof57372d2016-08-31 10:36:19 -0700149 Vertex(const SkPoint& point, uint8_t alpha)
ethannicholase9709e82016-01-07 13:34:16 -0800150 : fPoint(point), fPrev(nullptr), fNext(nullptr)
151 , fFirstEdgeAbove(nullptr), fLastEdgeAbove(nullptr)
152 , fFirstEdgeBelow(nullptr), fLastEdgeBelow(nullptr)
Stephen White3b5a3fa2017-06-06 14:51:19 -0400153 , fLeftEnclosingEdge(nullptr), fRightEnclosingEdge(nullptr)
Stephen Whitebda29c02017-03-13 15:10:13 -0400154 , fPartner(nullptr)
senorblancof57372d2016-08-31 10:36:19 -0700155 , fAlpha(alpha)
ethannicholase9709e82016-01-07 13:34:16 -0800156#if LOGGING_ENABLED
157 , fID (-1.0f)
158#endif
159 {}
Stephen White3b5a3fa2017-06-06 14:51:19 -0400160 SkPoint fPoint; // Vertex position
161 Vertex* fPrev; // Linked list of contours, then Y-sorted vertices.
162 Vertex* fNext; // "
163 Edge* fFirstEdgeAbove; // Linked list of edges above this vertex.
164 Edge* fLastEdgeAbove; // "
165 Edge* fFirstEdgeBelow; // Linked list of edges below this vertex.
166 Edge* fLastEdgeBelow; // "
167 Edge* fLeftEnclosingEdge; // Nearest edge in the AEL left of this vertex.
168 Edge* fRightEnclosingEdge; // Nearest edge in the AEL right of this vertex.
169 Vertex* fPartner; // Corresponding inner or outer vertex (for AA).
senorblancof57372d2016-08-31 10:36:19 -0700170 uint8_t fAlpha;
ethannicholase9709e82016-01-07 13:34:16 -0800171#if LOGGING_ENABLED
Stephen White3b5a3fa2017-06-06 14:51:19 -0400172 float fID; // Identifier used for logging.
ethannicholase9709e82016-01-07 13:34:16 -0800173#endif
174};
175
176/***************************************************************************************/
177
senorblancof57372d2016-08-31 10:36:19 -0700178struct AAParams {
179 bool fTweakAlpha;
180 GrColor fColor;
181};
182
ethannicholase9709e82016-01-07 13:34:16 -0800183typedef bool (*CompareFunc)(const SkPoint& a, const SkPoint& b);
184
ethannicholase9709e82016-01-07 13:34:16 -0800185bool sweep_lt_horiz(const SkPoint& a, const SkPoint& b) {
Stephen White16a40cb2017-02-23 11:10:01 -0500186 return a.fX < b.fX || (a.fX == b.fX && a.fY > b.fY);
ethannicholase9709e82016-01-07 13:34:16 -0800187}
188
189bool sweep_lt_vert(const SkPoint& a, const SkPoint& b) {
Stephen White16a40cb2017-02-23 11:10:01 -0500190 return a.fY < b.fY || (a.fY == b.fY && a.fX < b.fX);
ethannicholase9709e82016-01-07 13:34:16 -0800191}
192
Stephen White16a40cb2017-02-23 11:10:01 -0500193struct Comparator {
194 enum class Direction { kVertical, kHorizontal };
195 Comparator(Direction direction) : fDirection(direction) {}
196 bool sweep_lt(const SkPoint& a, const SkPoint& b) const {
197 return fDirection == Direction::kHorizontal ? sweep_lt_horiz(a, b) : sweep_lt_vert(a, b);
198 }
Stephen White16a40cb2017-02-23 11:10:01 -0500199 Direction fDirection;
200};
201
senorblancof57372d2016-08-31 10:36:19 -0700202inline void* emit_vertex(Vertex* v, const AAParams* aaParams, void* data) {
203 if (!aaParams) {
204 SkPoint* d = static_cast<SkPoint*>(data);
205 *d++ = v->fPoint;
206 return d;
207 }
208 if (aaParams->fTweakAlpha) {
209 auto d = static_cast<GrDefaultGeoProcFactory::PositionColorAttr*>(data);
210 d->fPosition = v->fPoint;
lsalzman8c8fcef2016-10-11 12:20:17 -0700211 d->fColor = SkAlphaMulQ(aaParams->fColor, SkAlpha255To256(v->fAlpha));
senorblancof57372d2016-08-31 10:36:19 -0700212 d++;
213 return d;
214 }
215 auto d = static_cast<GrDefaultGeoProcFactory::PositionColorCoverageAttr*>(data);
216 d->fPosition = v->fPoint;
217 d->fColor = aaParams->fColor;
218 d->fCoverage = GrNormalizeByteToFloat(v->fAlpha);
219 d++;
220 return d;
ethannicholase9709e82016-01-07 13:34:16 -0800221}
222
senorblancof57372d2016-08-31 10:36:19 -0700223void* emit_triangle(Vertex* v0, Vertex* v1, Vertex* v2, const AAParams* aaParams, void* data) {
Stephen White95152e12017-12-18 10:52:44 -0500224 LOG("emit_triangle %g (%g, %g) %d\n", v0->fID, v0->fPoint.fX, v0->fPoint.fY, v0->fAlpha);
225 LOG(" %g (%g, %g) %d\n", v1->fID, v1->fPoint.fX, v1->fPoint.fY, v1->fAlpha);
226 LOG(" %g (%g, %g) %d\n", v2->fID, v2->fPoint.fX, v2->fPoint.fY, v2->fAlpha);
senorblancof57372d2016-08-31 10:36:19 -0700227#if TESSELLATOR_WIREFRAME
228 data = emit_vertex(v0, aaParams, data);
229 data = emit_vertex(v1, aaParams, data);
230 data = emit_vertex(v1, aaParams, data);
231 data = emit_vertex(v2, aaParams, data);
232 data = emit_vertex(v2, aaParams, data);
233 data = emit_vertex(v0, aaParams, data);
ethannicholase9709e82016-01-07 13:34:16 -0800234#else
senorblancof57372d2016-08-31 10:36:19 -0700235 data = emit_vertex(v0, aaParams, data);
236 data = emit_vertex(v1, aaParams, data);
237 data = emit_vertex(v2, aaParams, data);
ethannicholase9709e82016-01-07 13:34:16 -0800238#endif
239 return data;
240}
241
senorblancoe6eaa322016-03-08 09:06:44 -0800242struct VertexList {
243 VertexList() : fHead(nullptr), fTail(nullptr) {}
Stephen White16a40cb2017-02-23 11:10:01 -0500244 VertexList(Vertex* head, Vertex* tail) : fHead(head), fTail(tail) {}
senorblancoe6eaa322016-03-08 09:06:44 -0800245 Vertex* fHead;
246 Vertex* fTail;
247 void insert(Vertex* v, Vertex* prev, Vertex* next) {
248 list_insert<Vertex, &Vertex::fPrev, &Vertex::fNext>(v, prev, next, &fHead, &fTail);
249 }
250 void append(Vertex* v) {
251 insert(v, fTail, nullptr);
252 }
Stephen Whitebda29c02017-03-13 15:10:13 -0400253 void append(const VertexList& list) {
254 if (!list.fHead) {
255 return;
256 }
257 if (fTail) {
258 fTail->fNext = list.fHead;
259 list.fHead->fPrev = fTail;
260 } else {
261 fHead = list.fHead;
262 }
263 fTail = list.fTail;
264 }
senorblancoe6eaa322016-03-08 09:06:44 -0800265 void prepend(Vertex* v) {
266 insert(v, nullptr, fHead);
267 }
Stephen Whitebf6137e2017-01-04 15:43:26 -0500268 void remove(Vertex* v) {
269 list_remove<Vertex, &Vertex::fPrev, &Vertex::fNext>(v, &fHead, &fTail);
270 }
senorblancof57372d2016-08-31 10:36:19 -0700271 void close() {
272 if (fHead && fTail) {
273 fTail->fNext = fHead;
274 fHead->fPrev = fTail;
275 }
276 }
senorblancoe6eaa322016-03-08 09:06:44 -0800277};
278
senorblancof57372d2016-08-31 10:36:19 -0700279// Round to nearest quarter-pixel. This is used for screenspace tessellation.
280
281inline void round(SkPoint* p) {
282 p->fX = SkScalarRoundToScalar(p->fX * SkFloatToScalar(4.0f)) * SkFloatToScalar(0.25f);
283 p->fY = SkScalarRoundToScalar(p->fY * SkFloatToScalar(4.0f)) * SkFloatToScalar(0.25f);
284}
285
Stephen White94b7e542018-01-04 14:01:10 -0500286inline SkScalar double_to_clamped_scalar(double d) {
287 return SkDoubleToScalar(std::min((double) SK_ScalarMax, std::max(d, (double) -SK_ScalarMax)));
288}
289
senorblanco49df8d12016-10-07 08:36:56 -0700290// A line equation in implicit form. fA * x + fB * y + fC = 0, for all points (x, y) on the line.
291struct Line {
Stephen Whitee260c462017-12-19 18:09:54 -0500292 Line(double a, double b, double c) : fA(a), fB(b), fC(c) {}
senorblanco49df8d12016-10-07 08:36:56 -0700293 Line(Vertex* p, Vertex* q) : Line(p->fPoint, q->fPoint) {}
294 Line(const SkPoint& p, const SkPoint& q)
295 : fA(static_cast<double>(q.fY) - p.fY) // a = dY
296 , fB(static_cast<double>(p.fX) - q.fX) // b = -dX
297 , fC(static_cast<double>(p.fY) * q.fX - // c = cross(q, p)
298 static_cast<double>(p.fX) * q.fY) {}
299 double dist(const SkPoint& p) const {
300 return fA * p.fX + fB * p.fY + fC;
301 }
Stephen Whitee260c462017-12-19 18:09:54 -0500302 Line operator*(double v) const {
303 return Line(fA * v, fB * v, fC * v);
304 }
senorblanco49df8d12016-10-07 08:36:56 -0700305 double magSq() const {
306 return fA * fA + fB * fB;
307 }
Stephen Whitee260c462017-12-19 18:09:54 -0500308 void normalize() {
309 double len = sqrt(this->magSq());
310 if (len == 0.0) {
311 return;
312 }
313 double scale = 1.0f / len;
314 fA *= scale;
315 fB *= scale;
316 fC *= scale;
317 }
318 bool nearParallel(const Line& o) const {
319 return fabs(o.fA - fA) < 0.00001 && fabs(o.fB - fB) < 0.00001;
320 }
senorblanco49df8d12016-10-07 08:36:56 -0700321
322 // Compute the intersection of two (infinite) Lines.
Stephen White95152e12017-12-18 10:52:44 -0500323 bool intersect(const Line& other, SkPoint* point) const {
senorblanco49df8d12016-10-07 08:36:56 -0700324 double denom = fA * other.fB - fB * other.fA;
325 if (denom == 0.0) {
326 return false;
327 }
Stephen White94b7e542018-01-04 14:01:10 -0500328 double scale = 1.0 / denom;
329 point->fX = double_to_clamped_scalar((fB * other.fC - other.fB * fC) * scale);
330 point->fY = double_to_clamped_scalar((other.fA * fC - fA * other.fC) * scale);
Stephen Whiteb56dedf2017-03-02 10:35:56 -0500331 round(point);
senorblanco49df8d12016-10-07 08:36:56 -0700332 return true;
333 }
334 double fA, fB, fC;
335};
336
ethannicholase9709e82016-01-07 13:34:16 -0800337/**
338 * An Edge joins a top Vertex to a bottom Vertex. Edge ordering for the list of "edges above" and
339 * "edge below" a vertex as well as for the active edge list is handled by isLeftOf()/isRightOf().
340 * Note that an Edge will give occasionally dist() != 0 for its own endpoints (because floating
Stephen Whitebda29c02017-03-13 15:10:13 -0400341 * point). For speed, that case is only tested by the callers that require it (e.g.,
Stephen White3b5a3fa2017-06-06 14:51:19 -0400342 * rewind_if_necessary()). Edges also handle checking for intersection with other edges.
ethannicholase9709e82016-01-07 13:34:16 -0800343 * Currently, this converts the edges to the parametric form, in order to avoid doing a division
344 * until an intersection has been confirmed. This is slightly slower in the "found" case, but
345 * a lot faster in the "not found" case.
346 *
347 * The coefficients of the line equation stored in double precision to avoid catastrphic
348 * cancellation in the isLeftOf() and isRightOf() checks. Using doubles ensures that the result is
349 * correct in float, since it's a polynomial of degree 2. The intersect() function, being
350 * degree 5, is still subject to catastrophic cancellation. We deal with that by assuming its
351 * output may be incorrect, and adjusting the mesh topology to match (see comment at the top of
352 * this file).
353 */
354
355struct Edge {
Stephen White2f4686f2017-01-03 16:20:01 -0500356 enum class Type { kInner, kOuter, kConnector };
357 Edge(Vertex* top, Vertex* bottom, int winding, Type type)
ethannicholase9709e82016-01-07 13:34:16 -0800358 : fWinding(winding)
359 , fTop(top)
360 , fBottom(bottom)
Stephen White2f4686f2017-01-03 16:20:01 -0500361 , fType(type)
ethannicholase9709e82016-01-07 13:34:16 -0800362 , fLeft(nullptr)
363 , fRight(nullptr)
364 , fPrevEdgeAbove(nullptr)
365 , fNextEdgeAbove(nullptr)
366 , fPrevEdgeBelow(nullptr)
367 , fNextEdgeBelow(nullptr)
368 , fLeftPoly(nullptr)
senorblanco531237e2016-06-02 11:36:48 -0700369 , fRightPoly(nullptr)
Stephen Whitee260c462017-12-19 18:09:54 -0500370 , fEvent(nullptr)
senorblanco531237e2016-06-02 11:36:48 -0700371 , fLeftPolyPrev(nullptr)
372 , fLeftPolyNext(nullptr)
373 , fRightPolyPrev(nullptr)
senorblanco70f52512016-08-17 14:56:22 -0700374 , fRightPolyNext(nullptr)
Stephen Whitee260c462017-12-19 18:09:54 -0500375 , fOverlap(false)
senorblanco70f52512016-08-17 14:56:22 -0700376 , fUsedInLeftPoly(false)
senorblanco49df8d12016-10-07 08:36:56 -0700377 , fUsedInRightPoly(false)
378 , fLine(top, bottom) {
ethannicholase9709e82016-01-07 13:34:16 -0800379 }
380 int fWinding; // 1 == edge goes downward; -1 = edge goes upward.
381 Vertex* fTop; // The top vertex in vertex-sort-order (sweep_lt).
382 Vertex* fBottom; // The bottom vertex in vertex-sort-order.
Stephen White2f4686f2017-01-03 16:20:01 -0500383 Type fType;
ethannicholase9709e82016-01-07 13:34:16 -0800384 Edge* fLeft; // The linked list of edges in the active edge list.
385 Edge* fRight; // "
386 Edge* fPrevEdgeAbove; // The linked list of edges in the bottom Vertex's "edges above".
387 Edge* fNextEdgeAbove; // "
388 Edge* fPrevEdgeBelow; // The linked list of edges in the top Vertex's "edges below".
389 Edge* fNextEdgeBelow; // "
390 Poly* fLeftPoly; // The Poly to the left of this edge, if any.
391 Poly* fRightPoly; // The Poly to the right of this edge, if any.
Stephen Whitee260c462017-12-19 18:09:54 -0500392 Event* fEvent;
senorblanco531237e2016-06-02 11:36:48 -0700393 Edge* fLeftPolyPrev;
394 Edge* fLeftPolyNext;
395 Edge* fRightPolyPrev;
396 Edge* fRightPolyNext;
Stephen Whitee260c462017-12-19 18:09:54 -0500397 bool fOverlap; // True if there's an overlap region adjacent to this edge.
senorblanco70f52512016-08-17 14:56:22 -0700398 bool fUsedInLeftPoly;
399 bool fUsedInRightPoly;
senorblanco49df8d12016-10-07 08:36:56 -0700400 Line fLine;
ethannicholase9709e82016-01-07 13:34:16 -0800401 double dist(const SkPoint& p) const {
senorblanco49df8d12016-10-07 08:36:56 -0700402 return fLine.dist(p);
ethannicholase9709e82016-01-07 13:34:16 -0800403 }
404 bool isRightOf(Vertex* v) const {
senorblanco49df8d12016-10-07 08:36:56 -0700405 return fLine.dist(v->fPoint) < 0.0;
ethannicholase9709e82016-01-07 13:34:16 -0800406 }
407 bool isLeftOf(Vertex* v) const {
senorblanco49df8d12016-10-07 08:36:56 -0700408 return fLine.dist(v->fPoint) > 0.0;
ethannicholase9709e82016-01-07 13:34:16 -0800409 }
410 void recompute() {
senorblanco49df8d12016-10-07 08:36:56 -0700411 fLine = Line(fTop, fBottom);
ethannicholase9709e82016-01-07 13:34:16 -0800412 }
Stephen White95152e12017-12-18 10:52:44 -0500413 bool intersect(const Edge& other, SkPoint* p, uint8_t* alpha = nullptr) const {
ethannicholase9709e82016-01-07 13:34:16 -0800414 LOG("intersecting %g -> %g with %g -> %g\n",
415 fTop->fID, fBottom->fID,
416 other.fTop->fID, other.fBottom->fID);
417 if (fTop == other.fTop || fBottom == other.fBottom) {
418 return false;
419 }
senorblanco49df8d12016-10-07 08:36:56 -0700420 double denom = fLine.fA * other.fLine.fB - fLine.fB * other.fLine.fA;
ethannicholase9709e82016-01-07 13:34:16 -0800421 if (denom == 0.0) {
422 return false;
423 }
Stephen White8a0bfc52017-02-21 15:24:13 -0500424 double dx = static_cast<double>(other.fTop->fPoint.fX) - fTop->fPoint.fX;
425 double dy = static_cast<double>(other.fTop->fPoint.fY) - fTop->fPoint.fY;
426 double sNumer = dy * other.fLine.fB + dx * other.fLine.fA;
427 double tNumer = dy * fLine.fB + dx * fLine.fA;
ethannicholase9709e82016-01-07 13:34:16 -0800428 // If (sNumer / denom) or (tNumer / denom) is not in [0..1], exit early.
429 // This saves us doing the divide below unless absolutely necessary.
430 if (denom > 0.0 ? (sNumer < 0.0 || sNumer > denom || tNumer < 0.0 || tNumer > denom)
431 : (sNumer > 0.0 || sNumer < denom || tNumer > 0.0 || tNumer < denom)) {
432 return false;
433 }
434 double s = sNumer / denom;
435 SkASSERT(s >= 0.0 && s <= 1.0);
senorblanco49df8d12016-10-07 08:36:56 -0700436 p->fX = SkDoubleToScalar(fTop->fPoint.fX - s * fLine.fB);
437 p->fY = SkDoubleToScalar(fTop->fPoint.fY + s * fLine.fA);
Stephen White56158ae2017-01-30 14:31:31 -0500438 if (alpha) {
Stephen White92eba8a2017-02-06 09:50:27 -0500439 if (fType == Type::kConnector) {
440 *alpha = (1.0 - s) * fTop->fAlpha + s * fBottom->fAlpha;
441 } else if (other.fType == Type::kConnector) {
442 double t = tNumer / denom;
443 *alpha = (1.0 - t) * other.fTop->fAlpha + t * other.fBottom->fAlpha;
Stephen White56158ae2017-01-30 14:31:31 -0500444 } else if (fType == Type::kOuter && other.fType == Type::kOuter) {
445 *alpha = 0;
446 } else {
Stephen White92eba8a2017-02-06 09:50:27 -0500447 *alpha = 255;
Stephen White56158ae2017-01-30 14:31:31 -0500448 }
449 }
ethannicholase9709e82016-01-07 13:34:16 -0800450 return true;
451 }
senorblancof57372d2016-08-31 10:36:19 -0700452};
453
454struct EdgeList {
Stephen White5ad721e2017-02-23 16:50:47 -0500455 EdgeList() : fHead(nullptr), fTail(nullptr) {}
senorblancof57372d2016-08-31 10:36:19 -0700456 Edge* fHead;
457 Edge* fTail;
senorblancof57372d2016-08-31 10:36:19 -0700458 void insert(Edge* edge, Edge* prev, Edge* next) {
459 list_insert<Edge, &Edge::fLeft, &Edge::fRight>(edge, prev, next, &fHead, &fTail);
senorblancof57372d2016-08-31 10:36:19 -0700460 }
461 void append(Edge* e) {
462 insert(e, fTail, nullptr);
463 }
464 void remove(Edge* edge) {
465 list_remove<Edge, &Edge::fLeft, &Edge::fRight>(edge, &fHead, &fTail);
senorblancof57372d2016-08-31 10:36:19 -0700466 }
Stephen Whitebda29c02017-03-13 15:10:13 -0400467 void removeAll() {
468 while (fHead) {
469 this->remove(fHead);
470 }
471 }
senorblancof57372d2016-08-31 10:36:19 -0700472 void close() {
473 if (fHead && fTail) {
474 fTail->fRight = fHead;
475 fHead->fLeft = fTail;
476 }
477 }
478 bool contains(Edge* edge) const {
479 return edge->fLeft || edge->fRight || fHead == edge;
ethannicholase9709e82016-01-07 13:34:16 -0800480 }
481};
482
Stephen Whitee260c462017-12-19 18:09:54 -0500483#ifndef GR_TESSELLATOR_LEGACY_INVERSION_HANDLING
484struct Event {
485 Event(Edge* edge, const SkPoint& point, uint8_t alpha)
486 : fEdge(edge), fPoint(point), fAlpha(alpha), fPrev(nullptr), fNext(nullptr) {
487 }
488 Edge* fEdge;
489 SkPoint fPoint;
490 uint8_t fAlpha;
491 Event* fPrev;
492 Event* fNext;
493 void apply(VertexList* mesh, Comparator& c, SkArenaAlloc& alloc);
494};
495
496bool compare(Event* const& e1, Event* const& e2) {
497 return e1->fAlpha > e2->fAlpha;
498}
499
500struct EventList : public SkTDPQueue<Event*, &compare> {};
501
502void create_event(Edge* e, EventList* events, SkArenaAlloc& alloc) {
503 Edge bisector1(e->fTop, e->fTop->fPartner, 1, Edge::Type::kConnector);
504 Edge bisector2(e->fBottom, e->fBottom->fPartner, 1, Edge::Type::kConnector);
505 SkPoint p;
506 uint8_t alpha;
507 if (bisector1.intersect(bisector2, &p, &alpha)) {
508 LOG("found overlap edge %g -> %g, will collapse to %g,%g alpha %d\n",
509 e->fTop->fID, e->fBottom->fID, p.fX, p.fY, alpha);
510 e->fEvent = alloc.make<Event>(e, p, alpha);
511 events->insert(e->fEvent);
512 }
513}
514#endif
515
ethannicholase9709e82016-01-07 13:34:16 -0800516/***************************************************************************************/
517
518struct Poly {
senorblanco531237e2016-06-02 11:36:48 -0700519 Poly(Vertex* v, int winding)
520 : fFirstVertex(v)
521 , fWinding(winding)
ethannicholase9709e82016-01-07 13:34:16 -0800522 , fHead(nullptr)
523 , fTail(nullptr)
ethannicholase9709e82016-01-07 13:34:16 -0800524 , fNext(nullptr)
525 , fPartner(nullptr)
526 , fCount(0)
527 {
528#if LOGGING_ENABLED
529 static int gID = 0;
530 fID = gID++;
531 LOG("*** created Poly %d\n", fID);
532#endif
533 }
senorblanco531237e2016-06-02 11:36:48 -0700534 typedef enum { kLeft_Side, kRight_Side } Side;
ethannicholase9709e82016-01-07 13:34:16 -0800535 struct MonotonePoly {
senorblanco531237e2016-06-02 11:36:48 -0700536 MonotonePoly(Edge* edge, Side side)
537 : fSide(side)
538 , fFirstEdge(nullptr)
539 , fLastEdge(nullptr)
ethannicholase9709e82016-01-07 13:34:16 -0800540 , fPrev(nullptr)
senorblanco531237e2016-06-02 11:36:48 -0700541 , fNext(nullptr) {
542 this->addEdge(edge);
543 }
ethannicholase9709e82016-01-07 13:34:16 -0800544 Side fSide;
senorblanco531237e2016-06-02 11:36:48 -0700545 Edge* fFirstEdge;
546 Edge* fLastEdge;
ethannicholase9709e82016-01-07 13:34:16 -0800547 MonotonePoly* fPrev;
548 MonotonePoly* fNext;
senorblanco531237e2016-06-02 11:36:48 -0700549 void addEdge(Edge* edge) {
senorblancoe6eaa322016-03-08 09:06:44 -0800550 if (fSide == kRight_Side) {
senorblanco212c7c32016-08-18 10:20:47 -0700551 SkASSERT(!edge->fUsedInRightPoly);
senorblanco531237e2016-06-02 11:36:48 -0700552 list_insert<Edge, &Edge::fRightPolyPrev, &Edge::fRightPolyNext>(
553 edge, fLastEdge, nullptr, &fFirstEdge, &fLastEdge);
senorblanco70f52512016-08-17 14:56:22 -0700554 edge->fUsedInRightPoly = true;
ethannicholase9709e82016-01-07 13:34:16 -0800555 } else {
senorblanco212c7c32016-08-18 10:20:47 -0700556 SkASSERT(!edge->fUsedInLeftPoly);
senorblanco531237e2016-06-02 11:36:48 -0700557 list_insert<Edge, &Edge::fLeftPolyPrev, &Edge::fLeftPolyNext>(
558 edge, fLastEdge, nullptr, &fFirstEdge, &fLastEdge);
senorblanco70f52512016-08-17 14:56:22 -0700559 edge->fUsedInLeftPoly = true;
ethannicholase9709e82016-01-07 13:34:16 -0800560 }
ethannicholase9709e82016-01-07 13:34:16 -0800561 }
562
senorblancof57372d2016-08-31 10:36:19 -0700563 void* emit(const AAParams* aaParams, void* data) {
senorblanco531237e2016-06-02 11:36:48 -0700564 Edge* e = fFirstEdge;
senorblanco531237e2016-06-02 11:36:48 -0700565 VertexList vertices;
566 vertices.append(e->fTop);
Stephen White651cbe92017-03-03 12:24:16 -0500567 int count = 1;
senorblanco531237e2016-06-02 11:36:48 -0700568 while (e != nullptr) {
senorblanco531237e2016-06-02 11:36:48 -0700569 if (kRight_Side == fSide) {
570 vertices.append(e->fBottom);
571 e = e->fRightPolyNext;
572 } else {
573 vertices.prepend(e->fBottom);
574 e = e->fLeftPolyNext;
575 }
Stephen White651cbe92017-03-03 12:24:16 -0500576 count++;
senorblanco531237e2016-06-02 11:36:48 -0700577 }
578 Vertex* first = vertices.fHead;
ethannicholase9709e82016-01-07 13:34:16 -0800579 Vertex* v = first->fNext;
senorblanco531237e2016-06-02 11:36:48 -0700580 while (v != vertices.fTail) {
ethannicholase9709e82016-01-07 13:34:16 -0800581 SkASSERT(v && v->fPrev && v->fNext);
582 Vertex* prev = v->fPrev;
583 Vertex* curr = v;
584 Vertex* next = v->fNext;
Stephen White651cbe92017-03-03 12:24:16 -0500585 if (count == 3) {
586 return emit_triangle(prev, curr, next, aaParams, data);
587 }
ethannicholase9709e82016-01-07 13:34:16 -0800588 double ax = static_cast<double>(curr->fPoint.fX) - prev->fPoint.fX;
589 double ay = static_cast<double>(curr->fPoint.fY) - prev->fPoint.fY;
590 double bx = static_cast<double>(next->fPoint.fX) - curr->fPoint.fX;
591 double by = static_cast<double>(next->fPoint.fY) - curr->fPoint.fY;
592 if (ax * by - ay * bx >= 0.0) {
senorblancof57372d2016-08-31 10:36:19 -0700593 data = emit_triangle(prev, curr, next, aaParams, data);
ethannicholase9709e82016-01-07 13:34:16 -0800594 v->fPrev->fNext = v->fNext;
595 v->fNext->fPrev = v->fPrev;
Stephen White651cbe92017-03-03 12:24:16 -0500596 count--;
ethannicholase9709e82016-01-07 13:34:16 -0800597 if (v->fPrev == first) {
598 v = v->fNext;
599 } else {
600 v = v->fPrev;
601 }
602 } else {
603 v = v->fNext;
604 }
605 }
606 return data;
607 }
608 };
Herb Derby5cdc9dd2017-02-13 12:10:46 -0500609 Poly* addEdge(Edge* e, Side side, SkArenaAlloc& alloc) {
senorblanco70f52512016-08-17 14:56:22 -0700610 LOG("addEdge (%g -> %g) to poly %d, %s side\n",
611 e->fTop->fID, e->fBottom->fID, fID, side == kLeft_Side ? "left" : "right");
ethannicholase9709e82016-01-07 13:34:16 -0800612 Poly* partner = fPartner;
613 Poly* poly = this;
senorblanco212c7c32016-08-18 10:20:47 -0700614 if (side == kRight_Side) {
615 if (e->fUsedInRightPoly) {
616 return this;
617 }
618 } else {
619 if (e->fUsedInLeftPoly) {
620 return this;
621 }
622 }
ethannicholase9709e82016-01-07 13:34:16 -0800623 if (partner) {
624 fPartner = partner->fPartner = nullptr;
625 }
senorblanco531237e2016-06-02 11:36:48 -0700626 if (!fTail) {
Herb Derby5cdc9dd2017-02-13 12:10:46 -0500627 fHead = fTail = alloc.make<MonotonePoly>(e, side);
senorblanco531237e2016-06-02 11:36:48 -0700628 fCount += 2;
senorblanco93e3fff2016-06-07 12:36:00 -0700629 } else if (e->fBottom == fTail->fLastEdge->fBottom) {
630 return poly;
senorblanco531237e2016-06-02 11:36:48 -0700631 } else if (side == fTail->fSide) {
632 fTail->addEdge(e);
633 fCount++;
634 } else {
Herb Derby5cdc9dd2017-02-13 12:10:46 -0500635 e = alloc.make<Edge>(fTail->fLastEdge->fBottom, e->fBottom, 1, Edge::Type::kInner);
senorblanco531237e2016-06-02 11:36:48 -0700636 fTail->addEdge(e);
637 fCount++;
ethannicholase9709e82016-01-07 13:34:16 -0800638 if (partner) {
senorblanco531237e2016-06-02 11:36:48 -0700639 partner->addEdge(e, side, alloc);
ethannicholase9709e82016-01-07 13:34:16 -0800640 poly = partner;
641 } else {
Herb Derby5cdc9dd2017-02-13 12:10:46 -0500642 MonotonePoly* m = alloc.make<MonotonePoly>(e, side);
senorblanco531237e2016-06-02 11:36:48 -0700643 m->fPrev = fTail;
644 fTail->fNext = m;
645 fTail = m;
ethannicholase9709e82016-01-07 13:34:16 -0800646 }
647 }
ethannicholase9709e82016-01-07 13:34:16 -0800648 return poly;
649 }
senorblancof57372d2016-08-31 10:36:19 -0700650 void* emit(const AAParams* aaParams, void *data) {
ethannicholase9709e82016-01-07 13:34:16 -0800651 if (fCount < 3) {
652 return data;
653 }
654 LOG("emit() %d, size %d\n", fID, fCount);
655 for (MonotonePoly* m = fHead; m != nullptr; m = m->fNext) {
senorblancof57372d2016-08-31 10:36:19 -0700656 data = m->emit(aaParams, data);
ethannicholase9709e82016-01-07 13:34:16 -0800657 }
658 return data;
659 }
senorblanco531237e2016-06-02 11:36:48 -0700660 Vertex* lastVertex() const { return fTail ? fTail->fLastEdge->fBottom : fFirstVertex; }
661 Vertex* fFirstVertex;
ethannicholase9709e82016-01-07 13:34:16 -0800662 int fWinding;
663 MonotonePoly* fHead;
664 MonotonePoly* fTail;
ethannicholase9709e82016-01-07 13:34:16 -0800665 Poly* fNext;
666 Poly* fPartner;
667 int fCount;
668#if LOGGING_ENABLED
669 int fID;
670#endif
671};
672
673/***************************************************************************************/
674
675bool coincident(const SkPoint& a, const SkPoint& b) {
676 return a == b;
677}
678
Herb Derby5cdc9dd2017-02-13 12:10:46 -0500679Poly* new_poly(Poly** head, Vertex* v, int winding, SkArenaAlloc& alloc) {
680 Poly* poly = alloc.make<Poly>(v, winding);
ethannicholase9709e82016-01-07 13:34:16 -0800681 poly->fNext = *head;
682 *head = poly;
683 return poly;
684}
685
Stephen White3a9aab92017-03-07 14:07:18 -0500686void append_point_to_contour(const SkPoint& p, VertexList* contour, SkArenaAlloc& alloc) {
Herb Derby5cdc9dd2017-02-13 12:10:46 -0500687 Vertex* v = alloc.make<Vertex>(p, 255);
ethannicholase9709e82016-01-07 13:34:16 -0800688#if LOGGING_ENABLED
689 static float gID = 0.0f;
690 v->fID = gID++;
691#endif
Stephen White3a9aab92017-03-07 14:07:18 -0500692 contour->append(v);
ethannicholase9709e82016-01-07 13:34:16 -0800693}
694
Stephen White36e4f062017-03-27 16:11:31 -0400695SkScalar quad_error_at(const SkPoint pts[3], SkScalar t, SkScalar u) {
696 SkQuadCoeff quad(pts);
697 SkPoint p0 = to_point(quad.eval(t - 0.5f * u));
698 SkPoint mid = to_point(quad.eval(t));
699 SkPoint p1 = to_point(quad.eval(t + 0.5f * u));
Stephen Whitee3a0be72017-06-12 11:43:18 -0400700 if (!p0.isFinite() || !mid.isFinite() || !p1.isFinite()) {
701 return 0;
702 }
Cary Clarkdf429f32017-11-08 11:44:31 -0500703 return SkPointPriv::DistanceToLineSegmentBetweenSqd(mid, p0, p1);
Stephen White36e4f062017-03-27 16:11:31 -0400704}
705
706void append_quadratic_to_contour(const SkPoint pts[3], SkScalar toleranceSqd, VertexList* contour,
707 SkArenaAlloc& alloc) {
708 SkQuadCoeff quad(pts);
709 Sk2s aa = quad.fA * quad.fA;
710 SkScalar denom = 2.0f * (aa[0] + aa[1]);
711 Sk2s ab = quad.fA * quad.fB;
712 SkScalar t = denom ? (-ab[0] - ab[1]) / denom : 0.0f;
713 int nPoints = 1;
Stephen Whitee40c3612018-01-09 11:49:08 -0500714 SkScalar u = 1.0f;
Stephen White36e4f062017-03-27 16:11:31 -0400715 // Test possible subdivision values only at the point of maximum curvature.
716 // If it passes the flatness metric there, it'll pass everywhere.
Stephen Whitee40c3612018-01-09 11:49:08 -0500717 while (nPoints < GrPathUtils::kMaxPointsPerCurve) {
Stephen White36e4f062017-03-27 16:11:31 -0400718 u = 1.0f / nPoints;
719 if (quad_error_at(pts, t, u) < toleranceSqd) {
720 break;
721 }
722 nPoints++;
ethannicholase9709e82016-01-07 13:34:16 -0800723 }
Stephen White36e4f062017-03-27 16:11:31 -0400724 for (int j = 1; j <= nPoints; j++) {
725 append_point_to_contour(to_point(quad.eval(j * u)), contour, alloc);
726 }
ethannicholase9709e82016-01-07 13:34:16 -0800727}
728
Stephen White3a9aab92017-03-07 14:07:18 -0500729void generate_cubic_points(const SkPoint& p0,
730 const SkPoint& p1,
731 const SkPoint& p2,
732 const SkPoint& p3,
733 SkScalar tolSqd,
734 VertexList* contour,
735 int pointsLeft,
736 SkArenaAlloc& alloc) {
Cary Clarkdf429f32017-11-08 11:44:31 -0500737 SkScalar d1 = SkPointPriv::DistanceToLineSegmentBetweenSqd(p1, p0, p3);
738 SkScalar d2 = SkPointPriv::DistanceToLineSegmentBetweenSqd(p2, p0, p3);
ethannicholase9709e82016-01-07 13:34:16 -0800739 if (pointsLeft < 2 || (d1 < tolSqd && d2 < tolSqd) ||
740 !SkScalarIsFinite(d1) || !SkScalarIsFinite(d2)) {
Stephen White3a9aab92017-03-07 14:07:18 -0500741 append_point_to_contour(p3, contour, alloc);
742 return;
ethannicholase9709e82016-01-07 13:34:16 -0800743 }
744 const SkPoint q[] = {
745 { SkScalarAve(p0.fX, p1.fX), SkScalarAve(p0.fY, p1.fY) },
746 { SkScalarAve(p1.fX, p2.fX), SkScalarAve(p1.fY, p2.fY) },
747 { SkScalarAve(p2.fX, p3.fX), SkScalarAve(p2.fY, p3.fY) }
748 };
749 const SkPoint r[] = {
750 { SkScalarAve(q[0].fX, q[1].fX), SkScalarAve(q[0].fY, q[1].fY) },
751 { SkScalarAve(q[1].fX, q[2].fX), SkScalarAve(q[1].fY, q[2].fY) }
752 };
753 const SkPoint s = { SkScalarAve(r[0].fX, r[1].fX), SkScalarAve(r[0].fY, r[1].fY) };
754 pointsLeft >>= 1;
Stephen White3a9aab92017-03-07 14:07:18 -0500755 generate_cubic_points(p0, q[0], r[0], s, tolSqd, contour, pointsLeft, alloc);
756 generate_cubic_points(s, r[1], q[2], p3, tolSqd, contour, pointsLeft, alloc);
ethannicholase9709e82016-01-07 13:34:16 -0800757}
758
759// Stage 1: convert the input path to a set of linear contours (linked list of Vertices).
760
761void path_to_contours(const SkPath& path, SkScalar tolerance, const SkRect& clipBounds,
Stephen White3a9aab92017-03-07 14:07:18 -0500762 VertexList* contours, SkArenaAlloc& alloc, bool *isLinear) {
ethannicholase9709e82016-01-07 13:34:16 -0800763 SkScalar toleranceSqd = tolerance * tolerance;
764
765 SkPoint pts[4];
ethannicholase9709e82016-01-07 13:34:16 -0800766 *isLinear = true;
Stephen White3a9aab92017-03-07 14:07:18 -0500767 VertexList* contour = contours;
ethannicholase9709e82016-01-07 13:34:16 -0800768 SkPath::Iter iter(path, false);
ethannicholase9709e82016-01-07 13:34:16 -0800769 if (path.isInverseFillType()) {
770 SkPoint quad[4];
771 clipBounds.toQuad(quad);
senorblanco7ab96e92016-10-12 06:47:44 -0700772 for (int i = 3; i >= 0; i--) {
Stephen White3a9aab92017-03-07 14:07:18 -0500773 append_point_to_contour(quad[i], contours, alloc);
ethannicholase9709e82016-01-07 13:34:16 -0800774 }
Stephen White3a9aab92017-03-07 14:07:18 -0500775 contour++;
ethannicholase9709e82016-01-07 13:34:16 -0800776 }
777 SkAutoConicToQuads converter;
Stephen White3a9aab92017-03-07 14:07:18 -0500778 SkPath::Verb verb;
Stephen White2cee2832017-08-23 09:37:16 -0400779 while ((verb = iter.next(pts, false)) != SkPath::kDone_Verb) {
ethannicholase9709e82016-01-07 13:34:16 -0800780 switch (verb) {
781 case SkPath::kConic_Verb: {
782 SkScalar weight = iter.conicWeight();
783 const SkPoint* quadPts = converter.computeQuads(pts, weight, toleranceSqd);
784 for (int i = 0; i < converter.countQuads(); ++i) {
Stephen White36e4f062017-03-27 16:11:31 -0400785 append_quadratic_to_contour(quadPts, toleranceSqd, contour, alloc);
ethannicholase9709e82016-01-07 13:34:16 -0800786 quadPts += 2;
787 }
788 *isLinear = false;
789 break;
790 }
791 case SkPath::kMove_Verb:
Stephen White3a9aab92017-03-07 14:07:18 -0500792 if (contour->fHead) {
793 contour++;
ethannicholase9709e82016-01-07 13:34:16 -0800794 }
Stephen White3a9aab92017-03-07 14:07:18 -0500795 append_point_to_contour(pts[0], contour, alloc);
ethannicholase9709e82016-01-07 13:34:16 -0800796 break;
797 case SkPath::kLine_Verb: {
Stephen White3a9aab92017-03-07 14:07:18 -0500798 append_point_to_contour(pts[1], contour, alloc);
ethannicholase9709e82016-01-07 13:34:16 -0800799 break;
800 }
801 case SkPath::kQuad_Verb: {
Stephen White36e4f062017-03-27 16:11:31 -0400802 append_quadratic_to_contour(pts, toleranceSqd, contour, alloc);
ethannicholase9709e82016-01-07 13:34:16 -0800803 *isLinear = false;
804 break;
805 }
806 case SkPath::kCubic_Verb: {
807 int pointsLeft = GrPathUtils::cubicPointCount(pts, tolerance);
Stephen White3a9aab92017-03-07 14:07:18 -0500808 generate_cubic_points(pts[0], pts[1], pts[2], pts[3], toleranceSqd, contour,
809 pointsLeft, alloc);
ethannicholase9709e82016-01-07 13:34:16 -0800810 *isLinear = false;
811 break;
812 }
813 case SkPath::kClose_Verb:
ethannicholase9709e82016-01-07 13:34:16 -0800814 case SkPath::kDone_Verb:
ethannicholase9709e82016-01-07 13:34:16 -0800815 break;
816 }
817 }
818}
819
Stephen White49789062017-02-21 10:35:49 -0500820inline bool apply_fill_type(SkPath::FillType fillType, int winding) {
ethannicholase9709e82016-01-07 13:34:16 -0800821 switch (fillType) {
822 case SkPath::kWinding_FillType:
823 return winding != 0;
824 case SkPath::kEvenOdd_FillType:
825 return (winding & 1) != 0;
826 case SkPath::kInverseWinding_FillType:
senorblanco7ab96e92016-10-12 06:47:44 -0700827 return winding == 1;
ethannicholase9709e82016-01-07 13:34:16 -0800828 case SkPath::kInverseEvenOdd_FillType:
829 return (winding & 1) == 1;
830 default:
831 SkASSERT(false);
832 return false;
833 }
834}
835
Stephen White49789062017-02-21 10:35:49 -0500836inline bool apply_fill_type(SkPath::FillType fillType, Poly* poly) {
837 return poly && apply_fill_type(fillType, poly->fWinding);
838}
839
Herb Derby5cdc9dd2017-02-13 12:10:46 -0500840Edge* new_edge(Vertex* prev, Vertex* next, Edge::Type type, Comparator& c, SkArenaAlloc& alloc) {
Stephen White2f4686f2017-01-03 16:20:01 -0500841 int winding = c.sweep_lt(prev->fPoint, next->fPoint) ? 1 : -1;
ethannicholase9709e82016-01-07 13:34:16 -0800842 Vertex* top = winding < 0 ? next : prev;
843 Vertex* bottom = winding < 0 ? prev : next;
Herb Derby5cdc9dd2017-02-13 12:10:46 -0500844 return alloc.make<Edge>(top, bottom, winding, type);
ethannicholase9709e82016-01-07 13:34:16 -0800845}
846
847void remove_edge(Edge* edge, EdgeList* edges) {
848 LOG("removing edge %g -> %g\n", edge->fTop->fID, edge->fBottom->fID);
senorblancof57372d2016-08-31 10:36:19 -0700849 SkASSERT(edges->contains(edge));
850 edges->remove(edge);
ethannicholase9709e82016-01-07 13:34:16 -0800851}
852
853void insert_edge(Edge* edge, Edge* prev, EdgeList* edges) {
854 LOG("inserting edge %g -> %g\n", edge->fTop->fID, edge->fBottom->fID);
senorblancof57372d2016-08-31 10:36:19 -0700855 SkASSERT(!edges->contains(edge));
ethannicholase9709e82016-01-07 13:34:16 -0800856 Edge* next = prev ? prev->fRight : edges->fHead;
senorblancof57372d2016-08-31 10:36:19 -0700857 edges->insert(edge, prev, next);
ethannicholase9709e82016-01-07 13:34:16 -0800858}
859
860void find_enclosing_edges(Vertex* v, EdgeList* edges, Edge** left, Edge** right) {
Stephen White90732fd2017-03-02 16:16:33 -0500861 if (v->fFirstEdgeAbove && v->fLastEdgeAbove) {
ethannicholase9709e82016-01-07 13:34:16 -0800862 *left = v->fFirstEdgeAbove->fLeft;
863 *right = v->fLastEdgeAbove->fRight;
864 return;
865 }
866 Edge* next = nullptr;
867 Edge* prev;
868 for (prev = edges->fTail; prev != nullptr; prev = prev->fLeft) {
869 if (prev->isLeftOf(v)) {
870 break;
871 }
872 next = prev;
873 }
874 *left = prev;
875 *right = next;
ethannicholase9709e82016-01-07 13:34:16 -0800876}
877
ethannicholase9709e82016-01-07 13:34:16 -0800878void insert_edge_above(Edge* edge, Vertex* v, Comparator& c) {
879 if (edge->fTop->fPoint == edge->fBottom->fPoint ||
Stephen Whitee30cf802017-02-27 11:37:55 -0500880 c.sweep_lt(edge->fBottom->fPoint, edge->fTop->fPoint)) {
ethannicholase9709e82016-01-07 13:34:16 -0800881 return;
882 }
883 LOG("insert edge (%g -> %g) above vertex %g\n", edge->fTop->fID, edge->fBottom->fID, v->fID);
884 Edge* prev = nullptr;
885 Edge* next;
886 for (next = v->fFirstEdgeAbove; next; next = next->fNextEdgeAbove) {
887 if (next->isRightOf(edge->fTop)) {
888 break;
889 }
890 prev = next;
891 }
senorblancoe6eaa322016-03-08 09:06:44 -0800892 list_insert<Edge, &Edge::fPrevEdgeAbove, &Edge::fNextEdgeAbove>(
ethannicholase9709e82016-01-07 13:34:16 -0800893 edge, prev, next, &v->fFirstEdgeAbove, &v->fLastEdgeAbove);
894}
895
896void insert_edge_below(Edge* edge, Vertex* v, Comparator& c) {
897 if (edge->fTop->fPoint == edge->fBottom->fPoint ||
Stephen Whitee30cf802017-02-27 11:37:55 -0500898 c.sweep_lt(edge->fBottom->fPoint, edge->fTop->fPoint)) {
ethannicholase9709e82016-01-07 13:34:16 -0800899 return;
900 }
901 LOG("insert edge (%g -> %g) below vertex %g\n", edge->fTop->fID, edge->fBottom->fID, v->fID);
902 Edge* prev = nullptr;
903 Edge* next;
904 for (next = v->fFirstEdgeBelow; next; next = next->fNextEdgeBelow) {
905 if (next->isRightOf(edge->fBottom)) {
906 break;
907 }
908 prev = next;
909 }
senorblancoe6eaa322016-03-08 09:06:44 -0800910 list_insert<Edge, &Edge::fPrevEdgeBelow, &Edge::fNextEdgeBelow>(
ethannicholase9709e82016-01-07 13:34:16 -0800911 edge, prev, next, &v->fFirstEdgeBelow, &v->fLastEdgeBelow);
912}
913
914void remove_edge_above(Edge* edge) {
915 LOG("removing edge (%g -> %g) above vertex %g\n", edge->fTop->fID, edge->fBottom->fID,
916 edge->fBottom->fID);
senorblancoe6eaa322016-03-08 09:06:44 -0800917 list_remove<Edge, &Edge::fPrevEdgeAbove, &Edge::fNextEdgeAbove>(
ethannicholase9709e82016-01-07 13:34:16 -0800918 edge, &edge->fBottom->fFirstEdgeAbove, &edge->fBottom->fLastEdgeAbove);
919}
920
921void remove_edge_below(Edge* edge) {
922 LOG("removing edge (%g -> %g) below vertex %g\n", edge->fTop->fID, edge->fBottom->fID,
923 edge->fTop->fID);
senorblancoe6eaa322016-03-08 09:06:44 -0800924 list_remove<Edge, &Edge::fPrevEdgeBelow, &Edge::fNextEdgeBelow>(
ethannicholase9709e82016-01-07 13:34:16 -0800925 edge, &edge->fTop->fFirstEdgeBelow, &edge->fTop->fLastEdgeBelow);
926}
927
Stephen Whitee7a364d2017-01-11 16:19:26 -0500928void disconnect(Edge* edge)
929{
ethannicholase9709e82016-01-07 13:34:16 -0800930 remove_edge_above(edge);
931 remove_edge_below(edge);
Stephen Whitee7a364d2017-01-11 16:19:26 -0500932}
933
Stephen White3b5a3fa2017-06-06 14:51:19 -0400934void merge_collinear_edges(Edge* edge, EdgeList* activeEdges, Vertex** current, Comparator& c);
935
936void rewind(EdgeList* activeEdges, Vertex** current, Vertex* dst, Comparator& c) {
937 if (!current || *current == dst || c.sweep_lt((*current)->fPoint, dst->fPoint)) {
938 return;
939 }
940 Vertex* v = *current;
941 LOG("rewinding active edges from vertex %g to vertex %g\n", v->fID, dst->fID);
942 while (v != dst) {
943 v = v->fPrev;
944 for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
945 remove_edge(e, activeEdges);
946 }
947 Edge* leftEdge = v->fLeftEnclosingEdge;
948 for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove) {
949 insert_edge(e, leftEdge, activeEdges);
950 leftEdge = e;
951 }
952 }
953 *current = v;
954}
955
956void rewind_if_necessary(Edge* edge, EdgeList* activeEdges, Vertex** current, Comparator& c) {
957 if (!activeEdges || !current) {
958 return;
959 }
960 Vertex* top = edge->fTop;
961 Vertex* bottom = edge->fBottom;
962 if (edge->fLeft) {
963 Vertex* leftTop = edge->fLeft->fTop;
964 Vertex* leftBottom = edge->fLeft->fBottom;
965 if (c.sweep_lt(leftTop->fPoint, top->fPoint) && !edge->fLeft->isLeftOf(top)) {
966 rewind(activeEdges, current, leftTop, c);
967 } else if (c.sweep_lt(top->fPoint, leftTop->fPoint) && !edge->isRightOf(leftTop)) {
968 rewind(activeEdges, current, top, c);
969 } else if (c.sweep_lt(bottom->fPoint, leftBottom->fPoint) &&
970 !edge->fLeft->isLeftOf(bottom)) {
971 rewind(activeEdges, current, leftTop, c);
972 } else if (c.sweep_lt(leftBottom->fPoint, bottom->fPoint) && !edge->isRightOf(leftBottom)) {
973 rewind(activeEdges, current, top, c);
974 }
975 }
976 if (edge->fRight) {
977 Vertex* rightTop = edge->fRight->fTop;
978 Vertex* rightBottom = edge->fRight->fBottom;
979 if (c.sweep_lt(rightTop->fPoint, top->fPoint) && !edge->fRight->isRightOf(top)) {
980 rewind(activeEdges, current, rightTop, c);
981 } else if (c.sweep_lt(top->fPoint, rightTop->fPoint) && !edge->isLeftOf(rightTop)) {
982 rewind(activeEdges, current, top, c);
983 } else if (c.sweep_lt(bottom->fPoint, rightBottom->fPoint) &&
984 !edge->fRight->isRightOf(bottom)) {
985 rewind(activeEdges, current, rightTop, c);
986 } else if (c.sweep_lt(rightBottom->fPoint, bottom->fPoint) &&
987 !edge->isLeftOf(rightBottom)) {
988 rewind(activeEdges, current, top, c);
989 }
ethannicholase9709e82016-01-07 13:34:16 -0800990 }
991}
992
Stephen White3b5a3fa2017-06-06 14:51:19 -0400993void set_top(Edge* edge, Vertex* v, EdgeList* activeEdges, Vertex** current, Comparator& c) {
ethannicholase9709e82016-01-07 13:34:16 -0800994 remove_edge_below(edge);
995 edge->fTop = v;
996 edge->recompute();
997 insert_edge_below(edge, v, c);
Stephen White3b5a3fa2017-06-06 14:51:19 -0400998 rewind_if_necessary(edge, activeEdges, current, c);
999 merge_collinear_edges(edge, activeEdges, current, c);
ethannicholase9709e82016-01-07 13:34:16 -08001000}
1001
Stephen White3b5a3fa2017-06-06 14:51:19 -04001002void set_bottom(Edge* edge, Vertex* v, EdgeList* activeEdges, Vertex** current, Comparator& c) {
ethannicholase9709e82016-01-07 13:34:16 -08001003 remove_edge_above(edge);
1004 edge->fBottom = v;
1005 edge->recompute();
1006 insert_edge_above(edge, v, c);
Stephen White3b5a3fa2017-06-06 14:51:19 -04001007 rewind_if_necessary(edge, activeEdges, current, c);
1008 merge_collinear_edges(edge, activeEdges, current, c);
ethannicholase9709e82016-01-07 13:34:16 -08001009}
1010
Stephen White3b5a3fa2017-06-06 14:51:19 -04001011void merge_edges_above(Edge* edge, Edge* other, EdgeList* activeEdges, Vertex** current,
1012 Comparator& c) {
ethannicholase9709e82016-01-07 13:34:16 -08001013 if (coincident(edge->fTop->fPoint, other->fTop->fPoint)) {
1014 LOG("merging coincident above edges (%g, %g) -> (%g, %g)\n",
1015 edge->fTop->fPoint.fX, edge->fTop->fPoint.fY,
1016 edge->fBottom->fPoint.fX, edge->fBottom->fPoint.fY);
Stephen White3b5a3fa2017-06-06 14:51:19 -04001017 rewind(activeEdges, current, edge->fTop, c);
ethannicholase9709e82016-01-07 13:34:16 -08001018 other->fWinding += edge->fWinding;
Stephen White3b5a3fa2017-06-06 14:51:19 -04001019 disconnect(edge);
ethannicholase9709e82016-01-07 13:34:16 -08001020 } else if (c.sweep_lt(edge->fTop->fPoint, other->fTop->fPoint)) {
Stephen White3b5a3fa2017-06-06 14:51:19 -04001021 rewind(activeEdges, current, edge->fTop, c);
ethannicholase9709e82016-01-07 13:34:16 -08001022 other->fWinding += edge->fWinding;
Stephen White3b5a3fa2017-06-06 14:51:19 -04001023 set_bottom(edge, other->fTop, activeEdges, current, c);
ethannicholase9709e82016-01-07 13:34:16 -08001024 } else {
Stephen White3b5a3fa2017-06-06 14:51:19 -04001025 rewind(activeEdges, current, other->fTop, c);
ethannicholase9709e82016-01-07 13:34:16 -08001026 edge->fWinding += other->fWinding;
Stephen White3b5a3fa2017-06-06 14:51:19 -04001027 set_bottom(other, edge->fTop, activeEdges, current, c);
ethannicholase9709e82016-01-07 13:34:16 -08001028 }
1029}
1030
Stephen White3b5a3fa2017-06-06 14:51:19 -04001031void merge_edges_below(Edge* edge, Edge* other, EdgeList* activeEdges, Vertex** current,
1032 Comparator& c) {
ethannicholase9709e82016-01-07 13:34:16 -08001033 if (coincident(edge->fBottom->fPoint, other->fBottom->fPoint)) {
1034 LOG("merging coincident below edges (%g, %g) -> (%g, %g)\n",
1035 edge->fTop->fPoint.fX, edge->fTop->fPoint.fY,
1036 edge->fBottom->fPoint.fX, edge->fBottom->fPoint.fY);
Stephen White3b5a3fa2017-06-06 14:51:19 -04001037 rewind(activeEdges, current, edge->fTop, c);
ethannicholase9709e82016-01-07 13:34:16 -08001038 other->fWinding += edge->fWinding;
Stephen White3b5a3fa2017-06-06 14:51:19 -04001039 disconnect(edge);
ethannicholase9709e82016-01-07 13:34:16 -08001040 } else if (c.sweep_lt(edge->fBottom->fPoint, other->fBottom->fPoint)) {
Stephen White3b5a3fa2017-06-06 14:51:19 -04001041 rewind(activeEdges, current, other->fTop, c);
ethannicholase9709e82016-01-07 13:34:16 -08001042 edge->fWinding += other->fWinding;
Stephen White3b5a3fa2017-06-06 14:51:19 -04001043 set_top(other, edge->fBottom, activeEdges, current, c);
ethannicholase9709e82016-01-07 13:34:16 -08001044 } else {
Stephen White3b5a3fa2017-06-06 14:51:19 -04001045 rewind(activeEdges, current, edge->fTop, c);
ethannicholase9709e82016-01-07 13:34:16 -08001046 other->fWinding += edge->fWinding;
Stephen White3b5a3fa2017-06-06 14:51:19 -04001047 set_top(edge, other->fBottom, activeEdges, current, c);
ethannicholase9709e82016-01-07 13:34:16 -08001048 }
1049}
1050
Stephen White3b5a3fa2017-06-06 14:51:19 -04001051void merge_collinear_edges(Edge* edge, EdgeList* activeEdges, Vertex** current, Comparator& c) {
Stephen White6eca90f2017-05-25 14:47:11 -04001052 for (;;) {
1053 if (edge->fPrevEdgeAbove && (edge->fTop == edge->fPrevEdgeAbove->fTop ||
1054 !edge->fPrevEdgeAbove->isLeftOf(edge->fTop))) {
Stephen White3b5a3fa2017-06-06 14:51:19 -04001055 merge_edges_above(edge, edge->fPrevEdgeAbove, activeEdges, current, c);
Stephen White6eca90f2017-05-25 14:47:11 -04001056 } else if (edge->fNextEdgeAbove && (edge->fTop == edge->fNextEdgeAbove->fTop ||
1057 !edge->isLeftOf(edge->fNextEdgeAbove->fTop))) {
Stephen White3b5a3fa2017-06-06 14:51:19 -04001058 merge_edges_above(edge, edge->fNextEdgeAbove, activeEdges, current, c);
Stephen White6eca90f2017-05-25 14:47:11 -04001059 } else if (edge->fPrevEdgeBelow && (edge->fBottom == edge->fPrevEdgeBelow->fBottom ||
1060 !edge->fPrevEdgeBelow->isLeftOf(edge->fBottom))) {
Stephen White3b5a3fa2017-06-06 14:51:19 -04001061 merge_edges_below(edge, edge->fPrevEdgeBelow, activeEdges, current, c);
Stephen White6eca90f2017-05-25 14:47:11 -04001062 } else if (edge->fNextEdgeBelow && (edge->fBottom == edge->fNextEdgeBelow->fBottom ||
1063 !edge->isLeftOf(edge->fNextEdgeBelow->fBottom))) {
Stephen White3b5a3fa2017-06-06 14:51:19 -04001064 merge_edges_below(edge, edge->fNextEdgeBelow, activeEdges, current, c);
Stephen White6eca90f2017-05-25 14:47:11 -04001065 } else {
1066 break;
1067 }
ethannicholase9709e82016-01-07 13:34:16 -08001068 }
Stephen White6eca90f2017-05-25 14:47:11 -04001069 SkASSERT(!edge->fPrevEdgeAbove || edge->fPrevEdgeAbove->isLeftOf(edge->fTop));
1070 SkASSERT(!edge->fPrevEdgeBelow || edge->fPrevEdgeBelow->isLeftOf(edge->fBottom));
1071 SkASSERT(!edge->fNextEdgeAbove || edge->fNextEdgeAbove->isRightOf(edge->fTop));
1072 SkASSERT(!edge->fNextEdgeBelow || edge->fNextEdgeBelow->isRightOf(edge->fBottom));
ethannicholase9709e82016-01-07 13:34:16 -08001073}
1074
Stephen White3b5a3fa2017-06-06 14:51:19 -04001075void split_edge(Edge* edge, Vertex* v, EdgeList* activeEdges, Vertex** current, Comparator& c,
1076 SkArenaAlloc& alloc) {
Stephen White0cb31672017-06-08 14:41:01 -04001077 if (v == edge->fTop || v == edge->fBottom) {
1078 return;
1079 }
ethannicholase9709e82016-01-07 13:34:16 -08001080 LOG("splitting edge (%g -> %g) at vertex %g (%g, %g)\n",
1081 edge->fTop->fID, edge->fBottom->fID,
1082 v->fID, v->fPoint.fX, v->fPoint.fY);
Stephen White3b5a3fa2017-06-06 14:51:19 -04001083 Vertex* top;
1084 Vertex* bottom;
ethannicholase9709e82016-01-07 13:34:16 -08001085 if (c.sweep_lt(v->fPoint, edge->fTop->fPoint)) {
Stephen White3b5a3fa2017-06-06 14:51:19 -04001086 top = v;
1087 bottom = edge->fTop;
1088 set_top(edge, v, activeEdges, current, c);
Stephen Whitee30cf802017-02-27 11:37:55 -05001089 } else if (c.sweep_lt(edge->fBottom->fPoint, v->fPoint)) {
Stephen White3b5a3fa2017-06-06 14:51:19 -04001090 top = edge->fBottom;
1091 bottom = v;
1092 set_bottom(edge, v, activeEdges, current, c);
ethannicholase9709e82016-01-07 13:34:16 -08001093 } else {
Stephen White3b5a3fa2017-06-06 14:51:19 -04001094 top = v;
1095 bottom = edge->fBottom;
1096 set_bottom(edge, v, activeEdges, current, c);
ethannicholase9709e82016-01-07 13:34:16 -08001097 }
Stephen White3b5a3fa2017-06-06 14:51:19 -04001098 Edge* newEdge = alloc.make<Edge>(top, bottom, edge->fWinding, edge->fType);
1099 insert_edge_below(newEdge, top, c);
1100 insert_edge_above(newEdge, bottom, c);
1101 merge_collinear_edges(newEdge, activeEdges, current, c);
ethannicholase9709e82016-01-07 13:34:16 -08001102}
1103
Herb Derby5cdc9dd2017-02-13 12:10:46 -05001104Edge* connect(Vertex* prev, Vertex* next, Edge::Type type, Comparator& c, SkArenaAlloc& alloc,
Stephen White48ded382017-02-03 10:15:16 -05001105 int winding_scale = 1) {
Stephen Whitee260c462017-12-19 18:09:54 -05001106 if (!prev || !next || prev->fPoint == next->fPoint) {
1107 return nullptr;
1108 }
Stephen Whitebf6137e2017-01-04 15:43:26 -05001109 Edge* edge = new_edge(prev, next, type, c, alloc);
Stephen White8a0bfc52017-02-21 15:24:13 -05001110 insert_edge_below(edge, edge->fTop, c);
1111 insert_edge_above(edge, edge->fBottom, c);
Stephen White48ded382017-02-03 10:15:16 -05001112 edge->fWinding *= winding_scale;
Stephen White3b5a3fa2017-06-06 14:51:19 -04001113 merge_collinear_edges(edge, nullptr, nullptr, c);
senorblancof57372d2016-08-31 10:36:19 -07001114 return edge;
1115}
1116
Stephen Whitebf6137e2017-01-04 15:43:26 -05001117void merge_vertices(Vertex* src, Vertex* dst, VertexList* mesh, Comparator& c,
Herb Derby5cdc9dd2017-02-13 12:10:46 -05001118 SkArenaAlloc& alloc) {
ethannicholase9709e82016-01-07 13:34:16 -08001119 LOG("found coincident verts at %g, %g; merging %g into %g\n", src->fPoint.fX, src->fPoint.fY,
1120 src->fID, dst->fID);
senorblancof57372d2016-08-31 10:36:19 -07001121 dst->fAlpha = SkTMax(src->fAlpha, dst->fAlpha);
Stephen Whitebda29c02017-03-13 15:10:13 -04001122 if (src->fPartner) {
1123 src->fPartner->fPartner = dst;
1124 }
ethannicholase9709e82016-01-07 13:34:16 -08001125 for (Edge* edge = src->fFirstEdgeAbove; edge;) {
1126 Edge* next = edge->fNextEdgeAbove;
Stephen White3b5a3fa2017-06-06 14:51:19 -04001127 set_bottom(edge, dst, nullptr, nullptr, c);
ethannicholase9709e82016-01-07 13:34:16 -08001128 edge = next;
1129 }
1130 for (Edge* edge = src->fFirstEdgeBelow; edge;) {
1131 Edge* next = edge->fNextEdgeBelow;
Stephen White3b5a3fa2017-06-06 14:51:19 -04001132 set_top(edge, dst, nullptr, nullptr, c);
ethannicholase9709e82016-01-07 13:34:16 -08001133 edge = next;
1134 }
Stephen Whitebf6137e2017-01-04 15:43:26 -05001135 mesh->remove(src);
ethannicholase9709e82016-01-07 13:34:16 -08001136}
1137
Stephen Whitee260c462017-12-19 18:09:54 -05001138#ifdef GR_TESSELLATOR_LEGACY_INVERSION_HANDLING
senorblancof57372d2016-08-31 10:36:19 -07001139uint8_t max_edge_alpha(Edge* a, Edge* b) {
Stephen White56158ae2017-01-30 14:31:31 -05001140 if (a->fType == Edge::Type::kInner || b->fType == Edge::Type::kInner) {
Stephen White2f4686f2017-01-03 16:20:01 -05001141 return 255;
1142 } else if (a->fType == Edge::Type::kOuter && b->fType == Edge::Type::kOuter) {
1143 return 0;
1144 } else {
1145 return SkTMax(SkTMax(a->fTop->fAlpha, a->fBottom->fAlpha),
1146 SkTMax(b->fTop->fAlpha, b->fBottom->fAlpha));
1147 }
senorblancof57372d2016-08-31 10:36:19 -07001148}
Stephen Whitee260c462017-12-19 18:09:54 -05001149#endif
senorblancof57372d2016-08-31 10:36:19 -07001150
Stephen White3f5301b2017-08-15 17:01:15 -04001151bool out_of_range_and_collinear(const SkPoint& p, Edge* edge, Comparator& c) {
1152 if (c.sweep_lt(p, edge->fTop->fPoint) &&
1153 !Line(p, edge->fBottom->fPoint).dist(edge->fTop->fPoint)) {
1154 return true;
1155 } else if (c.sweep_lt(edge->fBottom->fPoint, p) &&
1156 !Line(edge->fTop->fPoint, p).dist(edge->fBottom->fPoint)) {
1157 return true;
1158 }
1159 return false;
1160}
1161
Stephen White95152e12017-12-18 10:52:44 -05001162Vertex* create_sorted_vertex(const SkPoint& p, uint8_t alpha, VertexList* mesh,
1163 Vertex* reference, Comparator& c, SkArenaAlloc& alloc) {
1164 Vertex* prevV = reference;
1165 while (prevV && c.sweep_lt(p, prevV->fPoint)) {
1166 prevV = prevV->fPrev;
1167 }
1168 Vertex* nextV = prevV ? prevV->fNext : mesh->fHead;
1169 while (nextV && c.sweep_lt(nextV->fPoint, p)) {
1170 prevV = nextV;
1171 nextV = nextV->fNext;
1172 }
1173 Vertex* v;
1174 if (prevV && coincident(prevV->fPoint, p)) {
1175 v = prevV;
1176 } else if (nextV && coincident(nextV->fPoint, p)) {
1177 v = nextV;
1178 } else {
1179 v = alloc.make<Vertex>(p, alpha);
1180#if LOGGING_ENABLED
1181 if (!prevV) {
1182 v->fID = mesh->fHead->fID - 1.0f;
1183 } else if (!nextV) {
1184 v->fID = mesh->fTail->fID + 1.0f;
1185 } else {
1186 v->fID = (prevV->fID + nextV->fID) * 0.5f;
1187 }
1188#endif
1189 mesh->insert(v, prevV, nextV);
1190 }
1191 return v;
1192}
1193
Stephen White3b5a3fa2017-06-06 14:51:19 -04001194bool check_for_intersection(Edge* edge, Edge* other, EdgeList* activeEdges, Vertex** current,
Stephen White0cb31672017-06-08 14:41:01 -04001195 VertexList* mesh, Comparator& c, SkArenaAlloc& alloc) {
ethannicholase9709e82016-01-07 13:34:16 -08001196 if (!edge || !other) {
Stephen White3b5a3fa2017-06-06 14:51:19 -04001197 return false;
ethannicholase9709e82016-01-07 13:34:16 -08001198 }
Stephen White56158ae2017-01-30 14:31:31 -05001199 SkPoint p;
1200 uint8_t alpha;
Stephen Whitee3a0be72017-06-12 11:43:18 -04001201 if (edge->intersect(*other, &p, &alpha) && p.isFinite()) {
Stephen White3f5301b2017-08-15 17:01:15 -04001202 // Ignore any out-of-range intersections which are also collinear,
1203 // since the resulting edges would cancel each other out by merging.
1204 if (out_of_range_and_collinear(p, edge, c) ||
1205 out_of_range_and_collinear(p, other, c)) {
1206 return false;
1207 }
ethannicholase9709e82016-01-07 13:34:16 -08001208 Vertex* v;
1209 LOG("found intersection, pt is %g, %g\n", p.fX, p.fY);
Stephen White3b5a3fa2017-06-06 14:51:19 -04001210 Vertex* top = *current;
1211 // If the intersection point is above the current vertex, rewind to the vertex above the
1212 // intersection.
Stephen White0cb31672017-06-08 14:41:01 -04001213 while (top && c.sweep_lt(p, top->fPoint)) {
Stephen White3b5a3fa2017-06-06 14:51:19 -04001214 top = top->fPrev;
1215 }
Stephen White3b5a3fa2017-06-06 14:51:19 -04001216 if (p == edge->fTop->fPoint) {
ethannicholase9709e82016-01-07 13:34:16 -08001217 v = edge->fTop;
Stephen White3b5a3fa2017-06-06 14:51:19 -04001218 } else if (p == edge->fBottom->fPoint) {
ethannicholase9709e82016-01-07 13:34:16 -08001219 v = edge->fBottom;
Stephen White3b5a3fa2017-06-06 14:51:19 -04001220 } else if (p == other->fTop->fPoint) {
ethannicholase9709e82016-01-07 13:34:16 -08001221 v = other->fTop;
Stephen White3b5a3fa2017-06-06 14:51:19 -04001222 } else if (p == other->fBottom->fPoint) {
ethannicholase9709e82016-01-07 13:34:16 -08001223 v = other->fBottom;
1224 } else {
Stephen White95152e12017-12-18 10:52:44 -05001225 v = create_sorted_vertex(p, alpha, mesh, top, c, alloc);
Stephen Whitee260c462017-12-19 18:09:54 -05001226#ifndef GR_TESSELLATOR_LEGACY_INVERSION_HANDLING
1227 if (edge->fTop->fPartner) {
1228 Line line1 = edge->fLine;
1229 Line line2 = other->fLine;
1230 int dir = edge->fType == Edge::Type::kOuter ? -1 : 1;
1231 line1.fC += sqrt(edge->fLine.magSq()) * (edge->fWinding > 0 ? 1 : -1) * dir;
1232 line2.fC += sqrt(other->fLine.magSq()) * (other->fWinding > 0 ? 1 : -1) * dir;
1233 SkPoint p;
1234 if (line1.intersect(line2, &p)) {
1235 LOG("synthesizing partner (%g,%g) for intersection vertex %g\n",
1236 p.fX, p.fY, v->fID);
1237 v->fPartner = alloc.make<Vertex>(p, 255 - v->fAlpha);
1238 }
1239 }
1240#endif
ethannicholase9709e82016-01-07 13:34:16 -08001241 }
Stephen White0cb31672017-06-08 14:41:01 -04001242 rewind(activeEdges, current, top ? top : v, c);
1243 split_edge(edge, v, activeEdges, current, c, alloc);
1244 split_edge(other, v, activeEdges, current, c, alloc);
Stephen White92eba8a2017-02-06 09:50:27 -05001245 v->fAlpha = SkTMax(v->fAlpha, alpha);
Stephen White3b5a3fa2017-06-06 14:51:19 -04001246 return true;
ethannicholase9709e82016-01-07 13:34:16 -08001247 }
Stephen White3b5a3fa2017-06-06 14:51:19 -04001248 return false;
ethannicholase9709e82016-01-07 13:34:16 -08001249}
1250
Stephen White3a9aab92017-03-07 14:07:18 -05001251void sanitize_contours(VertexList* contours, int contourCnt, bool approximate) {
1252 for (VertexList* contour = contours; contourCnt > 0; --contourCnt, ++contour) {
1253 SkASSERT(contour->fHead);
1254 Vertex* prev = contour->fTail;
Stephen White5926f2d2017-02-13 13:55:42 -05001255 if (approximate) {
Stephen White3a9aab92017-03-07 14:07:18 -05001256 round(&prev->fPoint);
Stephen White5926f2d2017-02-13 13:55:42 -05001257 }
Stephen White3a9aab92017-03-07 14:07:18 -05001258 for (Vertex* v = contour->fHead; v;) {
senorblancof57372d2016-08-31 10:36:19 -07001259 if (approximate) {
1260 round(&v->fPoint);
1261 }
Stephen White3a9aab92017-03-07 14:07:18 -05001262 Vertex* next = v->fNext;
1263 if (coincident(prev->fPoint, v->fPoint)) {
ethannicholase9709e82016-01-07 13:34:16 -08001264 LOG("vertex %g,%g coincident; removing\n", v->fPoint.fX, v->fPoint.fY);
Stephen White3a9aab92017-03-07 14:07:18 -05001265 contour->remove(v);
Stephen White73e7f802017-08-23 13:56:07 -04001266 } else if (!v->fPoint.isFinite()) {
1267 LOG("vertex %g,%g non-finite; removing\n", v->fPoint.fX, v->fPoint.fY);
1268 contour->remove(v);
ethannicholase9709e82016-01-07 13:34:16 -08001269 }
Stephen White3a9aab92017-03-07 14:07:18 -05001270 prev = v;
1271 v = next;
ethannicholase9709e82016-01-07 13:34:16 -08001272 }
1273 }
1274}
1275
Stephen Whitee260c462017-12-19 18:09:54 -05001276bool merge_coincident_vertices(VertexList* mesh, Comparator& c, SkArenaAlloc& alloc) {
Stephen Whitebda29c02017-03-13 15:10:13 -04001277 if (!mesh->fHead) {
Stephen Whitee260c462017-12-19 18:09:54 -05001278 return false;
Stephen Whitebda29c02017-03-13 15:10:13 -04001279 }
Stephen Whitee260c462017-12-19 18:09:54 -05001280 bool merged = false;
1281 for (Vertex* v = mesh->fHead->fNext; v;) {
1282 Vertex* next = v->fNext;
ethannicholase9709e82016-01-07 13:34:16 -08001283 if (c.sweep_lt(v->fPoint, v->fPrev->fPoint)) {
1284 v->fPoint = v->fPrev->fPoint;
1285 }
1286 if (coincident(v->fPrev->fPoint, v->fPoint)) {
Stephen Whitee260c462017-12-19 18:09:54 -05001287 merge_vertices(v, v->fPrev, mesh, c, alloc);
1288 merged = true;
ethannicholase9709e82016-01-07 13:34:16 -08001289 }
Stephen Whitee260c462017-12-19 18:09:54 -05001290 v = next;
ethannicholase9709e82016-01-07 13:34:16 -08001291 }
Stephen Whitee260c462017-12-19 18:09:54 -05001292 return merged;
ethannicholase9709e82016-01-07 13:34:16 -08001293}
1294
1295// Stage 2: convert the contours to a mesh of edges connecting the vertices.
1296
Stephen White3a9aab92017-03-07 14:07:18 -05001297void build_edges(VertexList* contours, int contourCnt, VertexList* mesh, Comparator& c,
Herb Derby5cdc9dd2017-02-13 12:10:46 -05001298 SkArenaAlloc& alloc) {
Stephen White3a9aab92017-03-07 14:07:18 -05001299 for (VertexList* contour = contours; contourCnt > 0; --contourCnt, ++contour) {
1300 Vertex* prev = contour->fTail;
1301 for (Vertex* v = contour->fHead; v;) {
1302 Vertex* next = v->fNext;
1303 connect(prev, v, Edge::Type::kInner, c, alloc);
1304 mesh->append(v);
ethannicholase9709e82016-01-07 13:34:16 -08001305 prev = v;
Stephen White3a9aab92017-03-07 14:07:18 -05001306 v = next;
ethannicholase9709e82016-01-07 13:34:16 -08001307 }
1308 }
ethannicholase9709e82016-01-07 13:34:16 -08001309}
1310
Stephen Whitee260c462017-12-19 18:09:54 -05001311void connect_partners(VertexList* mesh, Comparator& c, SkArenaAlloc& alloc) {
1312 for (Vertex* outer = mesh->fHead; outer; outer = outer->fNext) {
Stephen Whitebda29c02017-03-13 15:10:13 -04001313 if (Vertex* inner = outer->fPartner) {
Stephen Whitee260c462017-12-19 18:09:54 -05001314 if ((inner->fPrev || inner->fNext) && (outer->fPrev || outer->fNext)) {
1315 // Connector edges get zero winding, since they're only structural (i.e., to ensure
1316 // no 0-0-0 alpha triangles are produced), and shouldn't affect the poly winding
1317 // number.
1318 connect(outer, inner, Edge::Type::kConnector, c, alloc, 0);
1319 inner->fPartner = outer->fPartner = nullptr;
1320 }
Stephen Whitebda29c02017-03-13 15:10:13 -04001321 }
1322 }
1323}
1324
1325template <CompareFunc sweep_lt>
1326void sorted_merge(VertexList* front, VertexList* back, VertexList* result) {
1327 Vertex* a = front->fHead;
1328 Vertex* b = back->fHead;
1329 while (a && b) {
1330 if (sweep_lt(a->fPoint, b->fPoint)) {
1331 front->remove(a);
1332 result->append(a);
1333 a = front->fHead;
1334 } else {
1335 back->remove(b);
1336 result->append(b);
1337 b = back->fHead;
1338 }
1339 }
1340 result->append(*front);
1341 result->append(*back);
1342}
1343
1344void sorted_merge(VertexList* front, VertexList* back, VertexList* result, Comparator& c) {
1345 if (c.fDirection == Comparator::Direction::kHorizontal) {
1346 sorted_merge<sweep_lt_horiz>(front, back, result);
1347 } else {
1348 sorted_merge<sweep_lt_vert>(front, back, result);
1349 }
Stephen White3b5a3fa2017-06-06 14:51:19 -04001350#if LOGGING_ENABLED
1351 float id = 0.0f;
1352 for (Vertex* v = result->fHead; v; v = v->fNext) {
1353 v->fID = id++;
1354 }
1355#endif
Stephen Whitebda29c02017-03-13 15:10:13 -04001356}
1357
ethannicholase9709e82016-01-07 13:34:16 -08001358// Stage 3: sort the vertices by increasing sweep direction.
1359
Stephen White16a40cb2017-02-23 11:10:01 -05001360template <CompareFunc sweep_lt>
1361void merge_sort(VertexList* vertices) {
1362 Vertex* slow = vertices->fHead;
1363 if (!slow) {
ethannicholase9709e82016-01-07 13:34:16 -08001364 return;
1365 }
Stephen White16a40cb2017-02-23 11:10:01 -05001366 Vertex* fast = slow->fNext;
1367 if (!fast) {
1368 return;
1369 }
1370 do {
1371 fast = fast->fNext;
1372 if (fast) {
1373 fast = fast->fNext;
1374 slow = slow->fNext;
1375 }
1376 } while (fast);
1377 VertexList front(vertices->fHead, slow);
1378 VertexList back(slow->fNext, vertices->fTail);
1379 front.fTail->fNext = back.fHead->fPrev = nullptr;
ethannicholase9709e82016-01-07 13:34:16 -08001380
Stephen White16a40cb2017-02-23 11:10:01 -05001381 merge_sort<sweep_lt>(&front);
1382 merge_sort<sweep_lt>(&back);
ethannicholase9709e82016-01-07 13:34:16 -08001383
Stephen White16a40cb2017-02-23 11:10:01 -05001384 vertices->fHead = vertices->fTail = nullptr;
Stephen Whitebda29c02017-03-13 15:10:13 -04001385 sorted_merge<sweep_lt>(&front, &back, vertices);
ethannicholase9709e82016-01-07 13:34:16 -08001386}
1387
Stephen White95152e12017-12-18 10:52:44 -05001388void dump_mesh(const VertexList& mesh) {
1389#if LOGGING_ENABLED
1390 for (Vertex* v = mesh.fHead; v; v = v->fNext) {
1391 LOG("vertex %g (%g, %g) alpha %d", v->fID, v->fPoint.fX, v->fPoint.fY, v->fAlpha);
1392 if (Vertex* p = v->fPartner) {
1393 LOG(", partner %g (%g, %g) alpha %d\n", p->fID, p->fPoint.fX, p->fPoint.fY, p->fAlpha);
1394 } else {
1395 LOG(", null partner\n");
1396 }
1397 for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove) {
1398 LOG(" edge %g -> %g, winding %d\n", e->fTop->fID, e->fBottom->fID, e->fWinding);
1399 }
1400 for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
1401 LOG(" edge %g -> %g, winding %d\n", e->fTop->fID, e->fBottom->fID, e->fWinding);
1402 }
1403 }
1404#endif
1405}
1406
ethannicholase9709e82016-01-07 13:34:16 -08001407// Stage 4: Simplify the mesh by inserting new vertices at intersecting edges.
1408
Stephen Whitee260c462017-12-19 18:09:54 -05001409bool simplify(VertexList* mesh, Comparator& c, SkArenaAlloc& alloc) {
ethannicholase9709e82016-01-07 13:34:16 -08001410 LOG("simplifying complex polygons\n");
1411 EdgeList activeEdges;
Stephen Whitee260c462017-12-19 18:09:54 -05001412 bool found = false;
Stephen White0cb31672017-06-08 14:41:01 -04001413 for (Vertex* v = mesh->fHead; v != nullptr; v = v->fNext) {
ethannicholase9709e82016-01-07 13:34:16 -08001414 if (!v->fFirstEdgeAbove && !v->fFirstEdgeBelow) {
1415 continue;
1416 }
Stephen White8a0bfc52017-02-21 15:24:13 -05001417 Edge* leftEnclosingEdge;
1418 Edge* rightEnclosingEdge;
ethannicholase9709e82016-01-07 13:34:16 -08001419 bool restartChecks;
1420 do {
Stephen White3b5a3fa2017-06-06 14:51:19 -04001421 LOG("\nvertex %g: (%g,%g), alpha %d\n", v->fID, v->fPoint.fX, v->fPoint.fY, v->fAlpha);
ethannicholase9709e82016-01-07 13:34:16 -08001422 restartChecks = false;
1423 find_enclosing_edges(v, &activeEdges, &leftEnclosingEdge, &rightEnclosingEdge);
Stephen White64dbb892017-05-03 16:00:38 -04001424 if (rightEnclosingEdge && !rightEnclosingEdge->isRightOf(v)) {
Stephen White3b5a3fa2017-06-06 14:51:19 -04001425 split_edge(rightEnclosingEdge, v, &activeEdges, &v, c, alloc);
Stephen White64dbb892017-05-03 16:00:38 -04001426 restartChecks = true;
1427 continue;
1428 }
Stephen White3b5a3fa2017-06-06 14:51:19 -04001429 SkASSERT(!rightEnclosingEdge || rightEnclosingEdge->isRightOf(v));
1430 v->fLeftEnclosingEdge = leftEnclosingEdge;
1431 v->fRightEnclosingEdge = rightEnclosingEdge;
ethannicholase9709e82016-01-07 13:34:16 -08001432 if (v->fFirstEdgeBelow) {
Stephen Whitebf6137e2017-01-04 15:43:26 -05001433 for (Edge* edge = v->fFirstEdgeBelow; edge; edge = edge->fNextEdgeBelow) {
Stephen White0cb31672017-06-08 14:41:01 -04001434 if (check_for_intersection(edge, leftEnclosingEdge, &activeEdges, &v, mesh, c,
Stephen White3b5a3fa2017-06-06 14:51:19 -04001435 alloc)) {
ethannicholase9709e82016-01-07 13:34:16 -08001436 restartChecks = true;
1437 break;
1438 }
Stephen White0cb31672017-06-08 14:41:01 -04001439 if (check_for_intersection(edge, rightEnclosingEdge, &activeEdges, &v, mesh, c,
Stephen White3b5a3fa2017-06-06 14:51:19 -04001440 alloc)) {
ethannicholase9709e82016-01-07 13:34:16 -08001441 restartChecks = true;
1442 break;
1443 }
1444 }
1445 } else {
Stephen White3b5a3fa2017-06-06 14:51:19 -04001446 if (check_for_intersection(leftEnclosingEdge, rightEnclosingEdge,
Stephen White0cb31672017-06-08 14:41:01 -04001447 &activeEdges, &v, mesh, c, alloc)) {
ethannicholase9709e82016-01-07 13:34:16 -08001448 restartChecks = true;
1449 }
1450
1451 }
Stephen Whitee260c462017-12-19 18:09:54 -05001452 found = found || restartChecks;
ethannicholase9709e82016-01-07 13:34:16 -08001453 } while (restartChecks);
Stephen Whitee260c462017-12-19 18:09:54 -05001454#ifdef GR_TESSELLATOR_LEGACY_INVERSION_HANDLING
senorblancof57372d2016-08-31 10:36:19 -07001455 if (v->fAlpha == 0) {
Stephen White48ded382017-02-03 10:15:16 -05001456 if ((leftEnclosingEdge && leftEnclosingEdge->fWinding < 0) &&
1457 (rightEnclosingEdge && rightEnclosingEdge->fWinding > 0)) {
senorblancof57372d2016-08-31 10:36:19 -07001458 v->fAlpha = max_edge_alpha(leftEnclosingEdge, rightEnclosingEdge);
1459 }
1460 }
Stephen Whitee260c462017-12-19 18:09:54 -05001461#endif
ethannicholase9709e82016-01-07 13:34:16 -08001462 for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove) {
1463 remove_edge(e, &activeEdges);
1464 }
1465 Edge* leftEdge = leftEnclosingEdge;
1466 for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
1467 insert_edge(e, leftEdge, &activeEdges);
1468 leftEdge = e;
1469 }
ethannicholase9709e82016-01-07 13:34:16 -08001470 }
Stephen Whitee260c462017-12-19 18:09:54 -05001471 SkASSERT(!activeEdges.fHead && !activeEdges.fTail);
1472 return found;
ethannicholase9709e82016-01-07 13:34:16 -08001473}
1474
Stephen Whitee260c462017-12-19 18:09:54 -05001475#ifdef GR_TESSELLATOR_LEGACY_INVERSION_HANDLING
Stephen Whitebda29c02017-03-13 15:10:13 -04001476// This is a stripped-down version of simplify() (the Bentley-Ottmann algorithm) that
1477// early-returns true on the first found intersection, false if none.
1478bool is_complex(const VertexList& vertices) {
1479 LOG("testing polygon complexity\n");
1480 EdgeList activeEdges;
1481 for (Vertex* v = vertices.fHead; v != nullptr; v = v->fNext) {
1482 if (!v->fFirstEdgeAbove && !v->fFirstEdgeBelow) {
1483 continue;
1484 }
1485 Edge* leftEnclosingEdge;
1486 Edge* rightEnclosingEdge;
1487 find_enclosing_edges(v, &activeEdges, &leftEnclosingEdge, &rightEnclosingEdge);
1488 SkPoint dummy;
1489 if (v->fFirstEdgeBelow) {
1490 for (Edge* edge = v->fFirstEdgeBelow; edge; edge = edge->fNextEdgeBelow) {
1491 if (edge && leftEnclosingEdge && edge->intersect(*leftEnclosingEdge, &dummy)) {
1492 activeEdges.removeAll();
1493 return true;
1494 }
1495 if (edge && rightEnclosingEdge && edge->intersect(*rightEnclosingEdge, &dummy)) {
1496 activeEdges.removeAll();
1497 return true;
1498 }
1499 }
1500 } else if (leftEnclosingEdge && rightEnclosingEdge &&
1501 leftEnclosingEdge->intersect(*rightEnclosingEdge, &dummy)) {
1502 activeEdges.removeAll();
1503 return true;
1504 }
1505 for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove) {
1506 remove_edge(e, &activeEdges);
1507 }
1508 Edge* leftEdge = leftEnclosingEdge;
1509 for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
1510 insert_edge(e, leftEdge, &activeEdges);
1511 leftEdge = e;
1512 }
1513 }
1514 activeEdges.removeAll();
1515 return false;
1516}
Stephen Whitee260c462017-12-19 18:09:54 -05001517#endif
Stephen Whitebda29c02017-03-13 15:10:13 -04001518
ethannicholase9709e82016-01-07 13:34:16 -08001519// Stage 5: Tessellate the simplified mesh into monotone polygons.
1520
Herb Derby5cdc9dd2017-02-13 12:10:46 -05001521Poly* tessellate(const VertexList& vertices, SkArenaAlloc& alloc) {
Stephen White95152e12017-12-18 10:52:44 -05001522 LOG("\ntessellating simple polygons\n");
ethannicholase9709e82016-01-07 13:34:16 -08001523 EdgeList activeEdges;
1524 Poly* polys = nullptr;
Stephen Whitebf6137e2017-01-04 15:43:26 -05001525 for (Vertex* v = vertices.fHead; v != nullptr; v = v->fNext) {
ethannicholase9709e82016-01-07 13:34:16 -08001526 if (!v->fFirstEdgeAbove && !v->fFirstEdgeBelow) {
1527 continue;
1528 }
1529#if LOGGING_ENABLED
senorblancof57372d2016-08-31 10:36:19 -07001530 LOG("\nvertex %g: (%g,%g), alpha %d\n", v->fID, v->fPoint.fX, v->fPoint.fY, v->fAlpha);
ethannicholase9709e82016-01-07 13:34:16 -08001531#endif
Stephen White8a0bfc52017-02-21 15:24:13 -05001532 Edge* leftEnclosingEdge;
1533 Edge* rightEnclosingEdge;
ethannicholase9709e82016-01-07 13:34:16 -08001534 find_enclosing_edges(v, &activeEdges, &leftEnclosingEdge, &rightEnclosingEdge);
Stephen White8a0bfc52017-02-21 15:24:13 -05001535 Poly* leftPoly;
1536 Poly* rightPoly;
ethannicholase9709e82016-01-07 13:34:16 -08001537 if (v->fFirstEdgeAbove) {
1538 leftPoly = v->fFirstEdgeAbove->fLeftPoly;
1539 rightPoly = v->fLastEdgeAbove->fRightPoly;
1540 } else {
1541 leftPoly = leftEnclosingEdge ? leftEnclosingEdge->fRightPoly : nullptr;
1542 rightPoly = rightEnclosingEdge ? rightEnclosingEdge->fLeftPoly : nullptr;
1543 }
1544#if LOGGING_ENABLED
1545 LOG("edges above:\n");
1546 for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove) {
1547 LOG("%g -> %g, lpoly %d, rpoly %d\n", e->fTop->fID, e->fBottom->fID,
1548 e->fLeftPoly ? e->fLeftPoly->fID : -1, e->fRightPoly ? e->fRightPoly->fID : -1);
1549 }
1550 LOG("edges below:\n");
1551 for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
1552 LOG("%g -> %g, lpoly %d, rpoly %d\n", e->fTop->fID, e->fBottom->fID,
1553 e->fLeftPoly ? e->fLeftPoly->fID : -1, e->fRightPoly ? e->fRightPoly->fID : -1);
1554 }
1555#endif
1556 if (v->fFirstEdgeAbove) {
1557 if (leftPoly) {
senorblanco531237e2016-06-02 11:36:48 -07001558 leftPoly = leftPoly->addEdge(v->fFirstEdgeAbove, Poly::kRight_Side, alloc);
ethannicholase9709e82016-01-07 13:34:16 -08001559 }
1560 if (rightPoly) {
senorblanco531237e2016-06-02 11:36:48 -07001561 rightPoly = rightPoly->addEdge(v->fLastEdgeAbove, Poly::kLeft_Side, alloc);
ethannicholase9709e82016-01-07 13:34:16 -08001562 }
1563 for (Edge* e = v->fFirstEdgeAbove; e != v->fLastEdgeAbove; e = e->fNextEdgeAbove) {
ethannicholase9709e82016-01-07 13:34:16 -08001564 Edge* rightEdge = e->fNextEdgeAbove;
Stephen White8a0bfc52017-02-21 15:24:13 -05001565 remove_edge(e, &activeEdges);
1566 if (e->fRightPoly) {
1567 e->fRightPoly->addEdge(e, Poly::kLeft_Side, alloc);
ethannicholase9709e82016-01-07 13:34:16 -08001568 }
Stephen White8a0bfc52017-02-21 15:24:13 -05001569 if (rightEdge->fLeftPoly && rightEdge->fLeftPoly != e->fRightPoly) {
senorblanco531237e2016-06-02 11:36:48 -07001570 rightEdge->fLeftPoly->addEdge(e, Poly::kRight_Side, alloc);
ethannicholase9709e82016-01-07 13:34:16 -08001571 }
1572 }
1573 remove_edge(v->fLastEdgeAbove, &activeEdges);
1574 if (!v->fFirstEdgeBelow) {
1575 if (leftPoly && rightPoly && leftPoly != rightPoly) {
1576 SkASSERT(leftPoly->fPartner == nullptr && rightPoly->fPartner == nullptr);
1577 rightPoly->fPartner = leftPoly;
1578 leftPoly->fPartner = rightPoly;
1579 }
1580 }
1581 }
1582 if (v->fFirstEdgeBelow) {
1583 if (!v->fFirstEdgeAbove) {
senorblanco93e3fff2016-06-07 12:36:00 -07001584 if (leftPoly && rightPoly) {
senorblanco531237e2016-06-02 11:36:48 -07001585 if (leftPoly == rightPoly) {
1586 if (leftPoly->fTail && leftPoly->fTail->fSide == Poly::kLeft_Side) {
1587 leftPoly = new_poly(&polys, leftPoly->lastVertex(),
1588 leftPoly->fWinding, alloc);
1589 leftEnclosingEdge->fRightPoly = leftPoly;
1590 } else {
1591 rightPoly = new_poly(&polys, rightPoly->lastVertex(),
1592 rightPoly->fWinding, alloc);
1593 rightEnclosingEdge->fLeftPoly = rightPoly;
1594 }
ethannicholase9709e82016-01-07 13:34:16 -08001595 }
Herb Derby5cdc9dd2017-02-13 12:10:46 -05001596 Edge* join = alloc.make<Edge>(leftPoly->lastVertex(), v, 1, Edge::Type::kInner);
senorblanco531237e2016-06-02 11:36:48 -07001597 leftPoly = leftPoly->addEdge(join, Poly::kRight_Side, alloc);
1598 rightPoly = rightPoly->addEdge(join, Poly::kLeft_Side, alloc);
ethannicholase9709e82016-01-07 13:34:16 -08001599 }
1600 }
1601 Edge* leftEdge = v->fFirstEdgeBelow;
1602 leftEdge->fLeftPoly = leftPoly;
1603 insert_edge(leftEdge, leftEnclosingEdge, &activeEdges);
1604 for (Edge* rightEdge = leftEdge->fNextEdgeBelow; rightEdge;
1605 rightEdge = rightEdge->fNextEdgeBelow) {
1606 insert_edge(rightEdge, leftEdge, &activeEdges);
1607 int winding = leftEdge->fLeftPoly ? leftEdge->fLeftPoly->fWinding : 0;
1608 winding += leftEdge->fWinding;
1609 if (winding != 0) {
1610 Poly* poly = new_poly(&polys, v, winding, alloc);
1611 leftEdge->fRightPoly = rightEdge->fLeftPoly = poly;
1612 }
1613 leftEdge = rightEdge;
1614 }
1615 v->fLastEdgeBelow->fRightPoly = rightPoly;
1616 }
1617#if LOGGING_ENABLED
1618 LOG("\nactive edges:\n");
1619 for (Edge* e = activeEdges.fHead; e != nullptr; e = e->fRight) {
1620 LOG("%g -> %g, lpoly %d, rpoly %d\n", e->fTop->fID, e->fBottom->fID,
1621 e->fLeftPoly ? e->fLeftPoly->fID : -1, e->fRightPoly ? e->fRightPoly->fID : -1);
1622 }
1623#endif
1624 }
1625 return polys;
1626}
1627
Stephen Whitebf6137e2017-01-04 15:43:26 -05001628void remove_non_boundary_edges(const VertexList& mesh, SkPath::FillType fillType,
Herb Derby5cdc9dd2017-02-13 12:10:46 -05001629 SkArenaAlloc& alloc) {
Stephen White49789062017-02-21 10:35:49 -05001630 LOG("removing non-boundary edges\n");
1631 EdgeList activeEdges;
Stephen Whitebf6137e2017-01-04 15:43:26 -05001632 for (Vertex* v = mesh.fHead; v != nullptr; v = v->fNext) {
Stephen White49789062017-02-21 10:35:49 -05001633 if (!v->fFirstEdgeAbove && !v->fFirstEdgeBelow) {
1634 continue;
1635 }
1636 Edge* leftEnclosingEdge;
1637 Edge* rightEnclosingEdge;
1638 find_enclosing_edges(v, &activeEdges, &leftEnclosingEdge, &rightEnclosingEdge);
1639 bool prevFilled = leftEnclosingEdge &&
1640 apply_fill_type(fillType, leftEnclosingEdge->fWinding);
1641 for (Edge* e = v->fFirstEdgeAbove; e;) {
1642 Edge* next = e->fNextEdgeAbove;
1643 remove_edge(e, &activeEdges);
1644 bool filled = apply_fill_type(fillType, e->fWinding);
1645 if (filled == prevFilled) {
Stephen Whitee7a364d2017-01-11 16:19:26 -05001646 disconnect(e);
senorblancof57372d2016-08-31 10:36:19 -07001647 }
Stephen White49789062017-02-21 10:35:49 -05001648 prevFilled = filled;
senorblancof57372d2016-08-31 10:36:19 -07001649 e = next;
1650 }
Stephen White49789062017-02-21 10:35:49 -05001651 Edge* prev = leftEnclosingEdge;
1652 for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
1653 if (prev) {
1654 e->fWinding += prev->fWinding;
1655 }
1656 insert_edge(e, prev, &activeEdges);
1657 prev = e;
1658 }
senorblancof57372d2016-08-31 10:36:19 -07001659 }
senorblancof57372d2016-08-31 10:36:19 -07001660}
1661
Stephen White66412122017-03-01 11:48:27 -05001662// Note: this is the normal to the edge, but not necessarily unit length.
senorblancof57372d2016-08-31 10:36:19 -07001663void get_edge_normal(const Edge* e, SkVector* normal) {
Stephen Whitee260c462017-12-19 18:09:54 -05001664#ifdef GR_TESSELLATOR_LEGACY_INVERSION_HANDLING
Stephen White66412122017-03-01 11:48:27 -05001665 normal->set(SkDoubleToScalar(e->fLine.fA) * e->fWinding,
1666 SkDoubleToScalar(e->fLine.fB) * e->fWinding);
Stephen Whitee260c462017-12-19 18:09:54 -05001667#else
1668 normal->set(SkDoubleToScalar(e->fLine.fA),
1669 SkDoubleToScalar(e->fLine.fB));
1670#endif
senorblancof57372d2016-08-31 10:36:19 -07001671}
1672
Stephen Whitee260c462017-12-19 18:09:54 -05001673#ifndef GR_TESSELLATOR_LEGACY_INVERSION_HANDLING
1674void reconnect(Edge* edge, Vertex* src, Vertex* dst, Comparator& c) {
1675 disconnect(edge);
1676 if (src == edge->fTop) {
1677 edge->fTop = dst;
1678 } else {
1679 SkASSERT(src == edge->fBottom);
1680 edge->fBottom = dst;
1681 }
1682 if (edge->fEvent) {
1683 edge->fEvent->fEdge = nullptr;
1684 }
1685 if (edge->fTop == edge->fBottom) {
1686 return;
1687 }
1688 if (c.sweep_lt(edge->fBottom->fPoint, edge->fTop->fPoint)) {
1689 SkTSwap(edge->fTop, edge->fBottom);
1690 edge->fWinding *= -1;
1691 }
1692 edge->recompute();
1693 insert_edge_below(edge, edge->fTop, c);
1694 insert_edge_above(edge, edge->fBottom, c);
1695 merge_collinear_edges(edge, nullptr, nullptr, c);
1696}
1697#endif
1698
senorblancof57372d2016-08-31 10:36:19 -07001699// Stage 5c: detect and remove "pointy" vertices whose edge normals point in opposite directions
1700// and whose adjacent vertices are less than a quarter pixel from an edge. These are guaranteed to
1701// invert on stroking.
1702
Herb Derby5cdc9dd2017-02-13 12:10:46 -05001703void simplify_boundary(EdgeList* boundary, Comparator& c, SkArenaAlloc& alloc) {
senorblancof57372d2016-08-31 10:36:19 -07001704 Edge* prevEdge = boundary->fTail;
1705 SkVector prevNormal;
1706 get_edge_normal(prevEdge, &prevNormal);
1707 for (Edge* e = boundary->fHead; e != nullptr;) {
1708 Vertex* prev = prevEdge->fWinding == 1 ? prevEdge->fTop : prevEdge->fBottom;
1709 Vertex* next = e->fWinding == 1 ? e->fBottom : e->fTop;
1710 double dist = e->dist(prev->fPoint);
1711 SkVector normal;
1712 get_edge_normal(e, &normal);
Stephen Whitee260c462017-12-19 18:09:54 -05001713#ifdef GR_TESSELLATOR_LEGACY_INVERSION_HANDLING
Stephen White66412122017-03-01 11:48:27 -05001714 double denom = 0.0625f * e->fLine.magSq();
Stephen Whitee260c462017-12-19 18:09:54 -05001715#else
1716 double denom = 0.0625f;
1717#endif
senorblancof57372d2016-08-31 10:36:19 -07001718 if (prevNormal.dot(normal) < 0.0 && (dist * dist) <= denom) {
Stephen Whitebf6137e2017-01-04 15:43:26 -05001719 Edge* join = new_edge(prev, next, Edge::Type::kInner, c, alloc);
Stephen Whitee260c462017-12-19 18:09:54 -05001720#ifndef GR_TESSELLATOR_LEGACY_INVERSION_HANDLING
1721 if (prev->fPoint != next->fPoint) {
1722 join->fLine.normalize();
1723 join->fLine = join->fLine * join->fWinding;
1724 }
1725#endif
senorblancof57372d2016-08-31 10:36:19 -07001726 insert_edge(join, e, boundary);
1727 remove_edge(prevEdge, boundary);
1728 remove_edge(e, boundary);
1729 if (join->fLeft && join->fRight) {
1730 prevEdge = join->fLeft;
1731 e = join;
1732 } else {
1733 prevEdge = boundary->fTail;
1734 e = boundary->fHead; // join->fLeft ? join->fLeft : join;
1735 }
1736 get_edge_normal(prevEdge, &prevNormal);
1737 } else {
1738 prevEdge = e;
1739 prevNormal = normal;
1740 e = e->fRight;
1741 }
1742 }
1743}
1744
Stephen Whitee260c462017-12-19 18:09:54 -05001745#ifdef GR_TESSELLATOR_LEGACY_INVERSION_HANDLING
Ben Wagnerdab48112017-02-16 22:28:02 +00001746void fix_inversions(Vertex* prev, Vertex* next, Edge* prevBisector, Edge* nextBisector,
Stephen White92eba8a2017-02-06 09:50:27 -05001747 Edge* prevEdge, Comparator& c) {
1748 if (!prev || !next) {
1749 return;
1750 }
1751 int winding = c.sweep_lt(prev->fPoint, next->fPoint) ? 1 : -1;
1752 SkPoint p;
1753 uint8_t alpha;
Ben Wagnerdab48112017-02-16 22:28:02 +00001754 if (winding != prevEdge->fWinding && prevBisector->intersect(*nextBisector, &p, &alpha)) {
Stephen White92eba8a2017-02-06 09:50:27 -05001755 prev->fPoint = next->fPoint = p;
1756 prev->fAlpha = next->fAlpha = alpha;
1757 }
1758}
Stephen Whitee260c462017-12-19 18:09:54 -05001759#else
1760void reconnect_all_overlap_edges(Vertex* src, Vertex* dst, Edge* current, Comparator& c) {
1761 if (src->fPartner) {
1762 src->fPartner->fPartner = dst;
1763 }
1764 for (Edge* e = src->fFirstEdgeAbove; e; ) {
1765 Edge* next = e->fNextEdgeAbove;
1766 if (e->fOverlap && e != current) {
1767 reconnect(e, src, dst, c);
1768 }
1769 e = next;
1770 }
1771 for (Edge* e = src->fFirstEdgeBelow; e; ) {
1772 Edge* next = e->fNextEdgeBelow;
1773 if (e->fOverlap && e != current) {
1774 reconnect(e, src, dst, c);
1775 }
1776 e = next;
1777 }
1778}
1779
1780void Event::apply(VertexList* mesh, Comparator& c, SkArenaAlloc& alloc) {
1781 if (!fEdge) {
1782 return;
1783 }
1784 Vertex* top = fEdge->fTop;
1785 Vertex* bottom = fEdge->fBottom;
1786 Vertex* dest = create_sorted_vertex(fPoint, fAlpha, mesh, fEdge->fTop, c, alloc);
1787 LOG("collapsing edge %g -> %g to %g (%g, %g) alpha %d\n",
1788 top->fID, bottom->fID, dest->fID, fPoint.fX, fPoint.fY, fAlpha);
1789 reconnect_all_overlap_edges(top, dest, fEdge, c);
1790 reconnect_all_overlap_edges(bottom, dest, fEdge, c);
1791
1792 // Since the destination has multiple partners, give it none.
1793 dest->fPartner = nullptr;
1794 disconnect(fEdge);
1795
1796 // If top still has some connected edges, set its partner to dest.
1797 top->fPartner = top->fFirstEdgeAbove || top->fFirstEdgeBelow ? dest : nullptr;
1798
1799 // If bottom still has some connected edges, set its partner to dest.
1800 bottom->fPartner = bottom->fFirstEdgeAbove || bottom->fFirstEdgeBelow ? dest : nullptr;
1801}
1802
1803bool is_overlap_edge(Edge* e) {
1804 if (e->fType == Edge::Type::kOuter) {
1805 return e->fWinding != 0 && e->fWinding != 1;
1806 } else if (e->fType == Edge::Type::kInner) {
1807 return e->fWinding != 0 && e->fWinding != -2;
1808 } else {
1809 return false;
1810 }
1811}
1812
1813// This is a stripped-down version of tessellate() which computes edges which
1814// join two filled regions, which represent overlap regions, and collapses them.
1815bool collapse_overlap_regions(VertexList* mesh, Comparator& c, SkArenaAlloc& alloc) {
1816 LOG("\nfinding overlap regions\n");
1817 EdgeList activeEdges;
1818 EventList events;
1819 for (Vertex* v = mesh->fHead; v != nullptr; v = v->fNext) {
1820 if (!v->fFirstEdgeAbove && !v->fFirstEdgeBelow) {
1821 continue;
1822 }
1823 Edge* leftEnclosingEdge;
1824 Edge* rightEnclosingEdge;
1825 find_enclosing_edges(v, &activeEdges, &leftEnclosingEdge, &rightEnclosingEdge);
1826 for (Edge* e = v->fLastEdgeAbove; e; e = e->fPrevEdgeAbove) {
1827 Edge* prev = e->fPrevEdgeAbove ? e->fPrevEdgeAbove : leftEnclosingEdge;
1828 remove_edge(e, &activeEdges);
1829 if (prev) {
1830 e->fWinding -= prev->fWinding;
1831 }
1832 }
1833 Edge* prev = leftEnclosingEdge;
1834 for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
1835 if (prev) {
1836 e->fWinding += prev->fWinding;
1837 e->fOverlap = e->fOverlap || is_overlap_edge(prev);
1838 }
1839 e->fOverlap = e->fOverlap || is_overlap_edge(e);
1840 if (e->fOverlap) {
1841 create_event(e, &events, alloc);
1842 }
1843 insert_edge(e, prev, &activeEdges);
1844 prev = e;
1845 }
1846 }
1847 LOG("\ncollapsing overlap regions\n");
1848 if (events.count() == 0) {
1849 return false;
1850 }
1851 while (events.count() > 0) {
1852 Event* event = events.peek();
1853 events.pop();
1854 event->apply(mesh, c, alloc);
1855 }
1856 return true;
1857}
1858
1859bool inversion(Vertex* prev, Vertex* next, Edge* origEdge, Comparator& c) {
1860 if (!prev || !next) {
1861 return true;
1862 }
1863 int winding = c.sweep_lt(prev->fPoint, next->fPoint) ? 1 : -1;
1864 return winding != origEdge->fWinding;
1865}
1866#endif
Stephen White92eba8a2017-02-06 09:50:27 -05001867
senorblancof57372d2016-08-31 10:36:19 -07001868// Stage 5d: Displace edges by half a pixel inward and outward along their normals. Intersect to
1869// find new vertices, and set zero alpha on the exterior and one alpha on the interior. Build a
1870// new antialiased mesh from those vertices.
1871
Stephen Whitee260c462017-12-19 18:09:54 -05001872#ifdef GR_TESSELLATOR_LEGACY_INVERSION_HANDLING
Stephen Whitebda29c02017-03-13 15:10:13 -04001873void stroke_boundary(EdgeList* boundary, VertexList* innerMesh, VertexList* outerMesh,
1874 Comparator& c, SkArenaAlloc& alloc) {
Stephen White8a0bfc52017-02-21 15:24:13 -05001875 // A boundary with fewer than 3 edges is degenerate.
1876 if (!boundary->fHead || !boundary->fHead->fRight || !boundary->fHead->fRight->fRight) {
1877 return;
1878 }
senorblancof57372d2016-08-31 10:36:19 -07001879 Edge* prevEdge = boundary->fTail;
1880 float radius = 0.5f;
senorblanco49df8d12016-10-07 08:36:56 -07001881 double offset = radius * sqrt(prevEdge->fLine.magSq()) * prevEdge->fWinding;
Stephen White66412122017-03-01 11:48:27 -05001882 Line prevInner(prevEdge->fLine);
senorblancof57372d2016-08-31 10:36:19 -07001883 prevInner.fC -= offset;
Stephen White66412122017-03-01 11:48:27 -05001884 Line prevOuter(prevEdge->fLine);
senorblancof57372d2016-08-31 10:36:19 -07001885 prevOuter.fC += offset;
1886 VertexList innerVertices;
1887 VertexList outerVertices;
Ben Wagnerdab48112017-02-16 22:28:02 +00001888 Edge* prevBisector = nullptr;
senorblancof57372d2016-08-31 10:36:19 -07001889 for (Edge* e = boundary->fHead; e != nullptr; e = e->fRight) {
senorblanco49df8d12016-10-07 08:36:56 -07001890 double offset = radius * sqrt(e->fLine.magSq()) * e->fWinding;
Stephen White66412122017-03-01 11:48:27 -05001891 Line inner(e->fLine);
senorblancof57372d2016-08-31 10:36:19 -07001892 inner.fC -= offset;
Stephen White66412122017-03-01 11:48:27 -05001893 Line outer(e->fLine);
senorblancof57372d2016-08-31 10:36:19 -07001894 outer.fC += offset;
1895 SkPoint innerPoint, outerPoint;
senorblanco49df8d12016-10-07 08:36:56 -07001896 if (prevInner.intersect(inner, &innerPoint) &&
1897 prevOuter.intersect(outer, &outerPoint)) {
Herb Derby5cdc9dd2017-02-13 12:10:46 -05001898 Vertex* innerVertex = alloc.make<Vertex>(innerPoint, 255);
1899 Vertex* outerVertex = alloc.make<Vertex>(outerPoint, 0);
Ben Wagnerdab48112017-02-16 22:28:02 +00001900 Edge* bisector = new_edge(outerVertex, innerVertex, Edge::Type::kConnector, c, alloc);
Stephen White92eba8a2017-02-06 09:50:27 -05001901 fix_inversions(innerVertices.fTail, innerVertex, prevBisector, bisector, prevEdge, c);
1902 fix_inversions(outerVertices.fTail, outerVertex, prevBisector, bisector, prevEdge, c);
Stephen Whitebda29c02017-03-13 15:10:13 -04001903 innerVertex->fPartner = outerVertex;
1904 outerVertex->fPartner = innerVertex;
Stephen White92eba8a2017-02-06 09:50:27 -05001905 innerVertices.append(innerVertex);
1906 outerVertices.append(outerVertex);
1907 prevBisector = bisector;
senorblancof57372d2016-08-31 10:36:19 -07001908 }
1909 prevInner = inner;
1910 prevOuter = outer;
Stephen White86cc8412017-01-27 10:53:15 -05001911 prevEdge = e;
senorblancof57372d2016-08-31 10:36:19 -07001912 }
senorblancof57372d2016-08-31 10:36:19 -07001913
1914 Vertex* innerVertex = innerVertices.fHead;
1915 Vertex* outerVertex = outerVertices.fHead;
senorblancof57372d2016-08-31 10:36:19 -07001916 if (!innerVertex || !outerVertex) {
1917 return;
1918 }
Ben Wagnerdab48112017-02-16 22:28:02 +00001919 Edge* bisector = new_edge(outerVertices.fHead, innerVertices.fHead, Edge::Type::kConnector, c,
1920 alloc);
Stephen White92eba8a2017-02-06 09:50:27 -05001921 fix_inversions(innerVertices.fTail, innerVertices.fHead, prevBisector, bisector, prevEdge, c);
1922 fix_inversions(outerVertices.fTail, outerVertices.fHead, prevBisector, bisector, prevEdge, c);
Stephen Whitebda29c02017-03-13 15:10:13 -04001923 Vertex* prevInnerVertex = innerVertices.fTail;
1924 Vertex* prevOuterVertex = outerVertices.fTail;
1925 while (innerVertex && outerVertex) {
Stephen White48ded382017-02-03 10:15:16 -05001926 // Connect vertices into a quad mesh. Outer edges get default (1) winding.
1927 // Inner edges get -2 winding. This ensures that the interior is always filled
1928 // (-1 winding number for normal cases, 3 for thin features where the interior inverts).
Stephen Whitebda29c02017-03-13 15:10:13 -04001929 connect(prevOuterVertex, outerVertex, Edge::Type::kOuter, c, alloc);
1930 connect(prevInnerVertex, innerVertex, Edge::Type::kInner, c, alloc, -2);
1931 prevInnerVertex = innerVertex;
1932 prevOuterVertex = outerVertex;
1933 innerVertex = innerVertex->fNext;
1934 outerVertex = outerVertex->fNext;
1935 }
1936 innerMesh->append(innerVertices);
1937 outerMesh->append(outerVertices);
senorblancof57372d2016-08-31 10:36:19 -07001938}
Stephen Whitee260c462017-12-19 18:09:54 -05001939#else
1940void stroke_boundary(EdgeList* boundary, VertexList* innerMesh, VertexList* outerMesh,
1941 Comparator& c, SkArenaAlloc& alloc) {
1942 LOG("\nstroking boundary\n");
1943 // A boundary with fewer than 3 edges is degenerate.
1944 if (!boundary->fHead || !boundary->fHead->fRight || !boundary->fHead->fRight->fRight) {
1945 return;
1946 }
1947 Edge* prevEdge = boundary->fTail;
1948 Vertex* prevV = prevEdge->fWinding > 0 ? prevEdge->fTop : prevEdge->fBottom;
1949 SkVector prevNormal;
1950 get_edge_normal(prevEdge, &prevNormal);
1951 double radius = 0.5;
1952 Line prevInner(prevEdge->fLine);
1953 prevInner.fC -= radius;
1954 Line prevOuter(prevEdge->fLine);
1955 prevOuter.fC += radius;
1956 VertexList innerVertices;
1957 VertexList outerVertices;
1958 bool innerInversion = true;
1959 bool outerInversion = true;
1960 for (Edge* e = boundary->fHead; e != nullptr; e = e->fRight) {
1961 Vertex* v = e->fWinding > 0 ? e->fTop : e->fBottom;
1962 SkVector normal;
1963 get_edge_normal(e, &normal);
1964 Line inner(e->fLine);
1965 inner.fC -= radius;
1966 Line outer(e->fLine);
1967 outer.fC += radius;
1968 SkPoint innerPoint, outerPoint;
1969 LOG("stroking vertex %g (%g, %g)\n", v->fID, v->fPoint.fX, v->fPoint.fY);
1970 if (!prevEdge->fLine.nearParallel(e->fLine) && prevInner.intersect(inner, &innerPoint) &&
1971 prevOuter.intersect(outer, &outerPoint)) {
1972 float cosAngle = normal.dot(prevNormal);
1973 if (cosAngle < -kCosMiterAngle) {
1974 Vertex* nextV = e->fWinding > 0 ? e->fBottom : e->fTop;
1975
1976 // This is a pointy vertex whose angle is smaller than the threshold; miter it.
1977 Line bisector(innerPoint, outerPoint);
1978 Line tangent(v->fPoint, v->fPoint + SkPoint::Make(bisector.fA, bisector.fB));
1979 if (tangent.fA == 0 && tangent.fB == 0) {
1980 continue;
1981 }
1982 tangent.normalize();
1983 Line innerTangent(tangent);
1984 Line outerTangent(tangent);
1985 innerTangent.fC -= 0.5;
1986 outerTangent.fC += 0.5;
1987 SkPoint innerPoint1, innerPoint2, outerPoint1, outerPoint2;
1988 if (prevNormal.cross(normal) > 0) {
1989 // Miter inner points
1990 if (!innerTangent.intersect(prevInner, &innerPoint1) ||
1991 !innerTangent.intersect(inner, &innerPoint2) ||
1992 !outerTangent.intersect(bisector, &outerPoint)) {
Stephen Whitef470b7e2018-01-04 16:45:51 -05001993 continue;
Stephen Whitee260c462017-12-19 18:09:54 -05001994 }
1995 Line prevTangent(prevV->fPoint,
1996 prevV->fPoint + SkVector::Make(prevOuter.fA, prevOuter.fB));
1997 Line nextTangent(nextV->fPoint,
1998 nextV->fPoint + SkVector::Make(outer.fA, outer.fB));
Stephen Whitee260c462017-12-19 18:09:54 -05001999 if (prevTangent.dist(outerPoint) > 0) {
Stephen White4f34fca2018-01-11 16:14:04 -05002000 bisector.intersect(prevTangent, &outerPoint);
Stephen Whitee260c462017-12-19 18:09:54 -05002001 }
2002 if (nextTangent.dist(outerPoint) < 0) {
Stephen White4f34fca2018-01-11 16:14:04 -05002003 bisector.intersect(nextTangent, &outerPoint);
Stephen Whitee260c462017-12-19 18:09:54 -05002004 }
2005 outerPoint1 = outerPoint2 = outerPoint;
2006 } else {
2007 // Miter outer points
2008 if (!outerTangent.intersect(prevOuter, &outerPoint1) ||
2009 !outerTangent.intersect(outer, &outerPoint2)) {
Stephen Whitef470b7e2018-01-04 16:45:51 -05002010 continue;
Stephen Whitee260c462017-12-19 18:09:54 -05002011 }
2012 Line prevTangent(prevV->fPoint,
2013 prevV->fPoint + SkVector::Make(prevInner.fA, prevInner.fB));
2014 Line nextTangent(nextV->fPoint,
2015 nextV->fPoint + SkVector::Make(inner.fA, inner.fB));
Stephen Whitee260c462017-12-19 18:09:54 -05002016 if (prevTangent.dist(innerPoint) > 0) {
Stephen White4f34fca2018-01-11 16:14:04 -05002017 bisector.intersect(prevTangent, &innerPoint);
Stephen Whitee260c462017-12-19 18:09:54 -05002018 }
2019 if (nextTangent.dist(innerPoint) < 0) {
Stephen White4f34fca2018-01-11 16:14:04 -05002020 bisector.intersect(nextTangent, &innerPoint);
Stephen Whitee260c462017-12-19 18:09:54 -05002021 }
2022 innerPoint1 = innerPoint2 = innerPoint;
2023 }
2024 LOG("inner (%g, %g), (%g, %g), ",
2025 innerPoint1.fX, innerPoint1.fY, innerPoint2.fX, innerPoint2.fY);
2026 LOG("outer (%g, %g), (%g, %g)\n",
2027 outerPoint1.fX, outerPoint1.fY, outerPoint2.fX, outerPoint2.fY);
2028 Vertex* innerVertex1 = alloc.make<Vertex>(innerPoint1, 255);
2029 Vertex* innerVertex2 = alloc.make<Vertex>(innerPoint2, 255);
2030 Vertex* outerVertex1 = alloc.make<Vertex>(outerPoint1, 0);
2031 Vertex* outerVertex2 = alloc.make<Vertex>(outerPoint2, 0);
2032 innerVertex1->fPartner = outerVertex1;
2033 innerVertex2->fPartner = outerVertex2;
2034 outerVertex1->fPartner = innerVertex1;
2035 outerVertex2->fPartner = innerVertex2;
2036 if (!inversion(innerVertices.fTail, innerVertex1, prevEdge, c)) {
2037 innerInversion = false;
2038 }
2039 if (!inversion(outerVertices.fTail, outerVertex1, prevEdge, c)) {
2040 outerInversion = false;
2041 }
2042 innerVertices.append(innerVertex1);
2043 innerVertices.append(innerVertex2);
2044 outerVertices.append(outerVertex1);
2045 outerVertices.append(outerVertex2);
2046 } else {
2047 LOG("inner (%g, %g), ", innerPoint.fX, innerPoint.fY);
2048 LOG("outer (%g, %g)\n", outerPoint.fX, outerPoint.fY);
2049 Vertex* innerVertex = alloc.make<Vertex>(innerPoint, 255);
2050 Vertex* outerVertex = alloc.make<Vertex>(outerPoint, 0);
2051 innerVertex->fPartner = outerVertex;
2052 outerVertex->fPartner = innerVertex;
2053 if (!inversion(innerVertices.fTail, innerVertex, prevEdge, c)) {
2054 innerInversion = false;
2055 }
2056 if (!inversion(outerVertices.fTail, outerVertex, prevEdge, c)) {
2057 outerInversion = false;
2058 }
2059 innerVertices.append(innerVertex);
2060 outerVertices.append(outerVertex);
2061 }
2062 }
2063 prevInner = inner;
2064 prevOuter = outer;
2065 prevV = v;
2066 prevEdge = e;
2067 prevNormal = normal;
2068 }
2069 if (!inversion(innerVertices.fTail, innerVertices.fHead, prevEdge, c)) {
2070 innerInversion = false;
2071 }
2072 if (!inversion(outerVertices.fTail, outerVertices.fHead, prevEdge, c)) {
2073 outerInversion = false;
2074 }
2075 // Outer edges get 1 winding, and inner edges get -2 winding. This ensures that the interior
2076 // is always filled (1 + -2 = -1 for normal cases, 1 + 2 = 3 for thin features where the
2077 // interior inverts).
2078 // For total inversion cases, the shape has now reversed handedness, so invert the winding
2079 // so it will be detected during collapse_overlap_regions().
2080 int innerWinding = innerInversion ? 2 : -2;
2081 int outerWinding = outerInversion ? -1 : 1;
2082 for (Vertex* v = innerVertices.fHead; v && v->fNext; v = v->fNext) {
2083 connect(v, v->fNext, Edge::Type::kInner, c, alloc, innerWinding);
2084 }
2085 connect(innerVertices.fTail, innerVertices.fHead, Edge::Type::kInner, c, alloc, innerWinding);
2086 for (Vertex* v = outerVertices.fHead; v && v->fNext; v = v->fNext) {
2087 connect(v, v->fNext, Edge::Type::kOuter, c, alloc, outerWinding);
2088 }
2089 connect(outerVertices.fTail, outerVertices.fHead, Edge::Type::kOuter, c, alloc, outerWinding);
2090 innerMesh->append(innerVertices);
2091 outerMesh->append(outerVertices);
2092}
2093#endif
senorblancof57372d2016-08-31 10:36:19 -07002094
Herb Derby5cdc9dd2017-02-13 12:10:46 -05002095void extract_boundary(EdgeList* boundary, Edge* e, SkPath::FillType fillType, SkArenaAlloc& alloc) {
Stephen White95152e12017-12-18 10:52:44 -05002096 LOG("\nextracting boundary\n");
Stephen White49789062017-02-21 10:35:49 -05002097 bool down = apply_fill_type(fillType, e->fWinding);
senorblancof57372d2016-08-31 10:36:19 -07002098 while (e) {
2099 e->fWinding = down ? 1 : -1;
2100 Edge* next;
Stephen Whitee260c462017-12-19 18:09:54 -05002101#ifndef GR_TESSELLATOR_LEGACY_INVERSION_HANDLING
2102 e->fLine.normalize();
2103 e->fLine = e->fLine * e->fWinding;
2104#endif
senorblancof57372d2016-08-31 10:36:19 -07002105 boundary->append(e);
2106 if (down) {
2107 // Find outgoing edge, in clockwise order.
2108 if ((next = e->fNextEdgeAbove)) {
2109 down = false;
2110 } else if ((next = e->fBottom->fLastEdgeBelow)) {
2111 down = true;
2112 } else if ((next = e->fPrevEdgeAbove)) {
2113 down = false;
2114 }
2115 } else {
2116 // Find outgoing edge, in counter-clockwise order.
2117 if ((next = e->fPrevEdgeBelow)) {
2118 down = true;
2119 } else if ((next = e->fTop->fFirstEdgeAbove)) {
2120 down = false;
2121 } else if ((next = e->fNextEdgeBelow)) {
2122 down = true;
2123 }
2124 }
Stephen Whitee7a364d2017-01-11 16:19:26 -05002125 disconnect(e);
senorblancof57372d2016-08-31 10:36:19 -07002126 e = next;
2127 }
2128}
2129
Stephen White5ad721e2017-02-23 16:50:47 -05002130// Stage 5b: Extract boundaries from mesh, simplify and stroke them into a new mesh.
senorblancof57372d2016-08-31 10:36:19 -07002131
Stephen Whitebda29c02017-03-13 15:10:13 -04002132void extract_boundaries(const VertexList& inMesh, VertexList* innerVertices,
2133 VertexList* outerVertices, SkPath::FillType fillType,
Stephen White5ad721e2017-02-23 16:50:47 -05002134 Comparator& c, SkArenaAlloc& alloc) {
2135 remove_non_boundary_edges(inMesh, fillType, alloc);
2136 for (Vertex* v = inMesh.fHead; v; v = v->fNext) {
senorblancof57372d2016-08-31 10:36:19 -07002137 while (v->fFirstEdgeBelow) {
Stephen White5ad721e2017-02-23 16:50:47 -05002138 EdgeList boundary;
2139 extract_boundary(&boundary, v->fFirstEdgeBelow, fillType, alloc);
2140 simplify_boundary(&boundary, c, alloc);
Stephen Whitebda29c02017-03-13 15:10:13 -04002141 stroke_boundary(&boundary, innerVertices, outerVertices, c, alloc);
senorblancof57372d2016-08-31 10:36:19 -07002142 }
2143 }
senorblancof57372d2016-08-31 10:36:19 -07002144}
2145
Stephen Whitebda29c02017-03-13 15:10:13 -04002146// This is a driver function that calls stages 2-5 in turn.
ethannicholase9709e82016-01-07 13:34:16 -08002147
Stephen White3a9aab92017-03-07 14:07:18 -05002148void contours_to_mesh(VertexList* contours, int contourCnt, bool antialias,
Herb Derby5cdc9dd2017-02-13 12:10:46 -05002149 VertexList* mesh, Comparator& c, SkArenaAlloc& alloc) {
ethannicholase9709e82016-01-07 13:34:16 -08002150#if LOGGING_ENABLED
2151 for (int i = 0; i < contourCnt; ++i) {
Stephen White3a9aab92017-03-07 14:07:18 -05002152 Vertex* v = contours[i].fHead;
ethannicholase9709e82016-01-07 13:34:16 -08002153 SkASSERT(v);
2154 LOG("path.moveTo(%20.20g, %20.20g);\n", v->fPoint.fX, v->fPoint.fY);
Stephen White3a9aab92017-03-07 14:07:18 -05002155 for (v = v->fNext; v; v = v->fNext) {
ethannicholase9709e82016-01-07 13:34:16 -08002156 LOG("path.lineTo(%20.20g, %20.20g);\n", v->fPoint.fX, v->fPoint.fY);
2157 }
2158 }
2159#endif
senorblancof57372d2016-08-31 10:36:19 -07002160 sanitize_contours(contours, contourCnt, antialias);
Stephen Whitebf6137e2017-01-04 15:43:26 -05002161 build_edges(contours, contourCnt, mesh, c, alloc);
senorblancof57372d2016-08-31 10:36:19 -07002162}
2163
Stephen Whitebda29c02017-03-13 15:10:13 -04002164void sort_mesh(VertexList* vertices, Comparator& c, SkArenaAlloc& alloc) {
Stephen Whitebf6137e2017-01-04 15:43:26 -05002165 if (!vertices || !vertices->fHead) {
Stephen White2f4686f2017-01-03 16:20:01 -05002166 return;
ethannicholase9709e82016-01-07 13:34:16 -08002167 }
2168
2169 // Sort vertices in Y (secondarily in X).
Stephen White16a40cb2017-02-23 11:10:01 -05002170 if (c.fDirection == Comparator::Direction::kHorizontal) {
2171 merge_sort<sweep_lt_horiz>(vertices);
2172 } else {
2173 merge_sort<sweep_lt_vert>(vertices);
2174 }
ethannicholase9709e82016-01-07 13:34:16 -08002175#if LOGGING_ENABLED
Stephen White2e2cb9b2017-01-09 13:11:18 -05002176 for (Vertex* v = vertices->fHead; v != nullptr; v = v->fNext) {
ethannicholase9709e82016-01-07 13:34:16 -08002177 static float gID = 0.0f;
2178 v->fID = gID++;
2179 }
2180#endif
Stephen White2f4686f2017-01-03 16:20:01 -05002181}
2182
Stephen White3a9aab92017-03-07 14:07:18 -05002183Poly* contours_to_polys(VertexList* contours, int contourCnt, SkPath::FillType fillType,
Stephen Whitebda29c02017-03-13 15:10:13 -04002184 const SkRect& pathBounds, bool antialias, VertexList* outerMesh,
Herb Derby5cdc9dd2017-02-13 12:10:46 -05002185 SkArenaAlloc& alloc) {
Stephen White16a40cb2017-02-23 11:10:01 -05002186 Comparator c(pathBounds.width() > pathBounds.height() ? Comparator::Direction::kHorizontal
2187 : Comparator::Direction::kVertical);
Stephen Whitebf6137e2017-01-04 15:43:26 -05002188 VertexList mesh;
2189 contours_to_mesh(contours, contourCnt, antialias, &mesh, c, alloc);
Stephen Whitebda29c02017-03-13 15:10:13 -04002190 sort_mesh(&mesh, c, alloc);
2191 merge_coincident_vertices(&mesh, c, alloc);
Stephen White0cb31672017-06-08 14:41:01 -04002192 simplify(&mesh, c, alloc);
senorblancof57372d2016-08-31 10:36:19 -07002193 if (antialias) {
Stephen Whitebda29c02017-03-13 15:10:13 -04002194 VertexList innerMesh;
2195 extract_boundaries(mesh, &innerMesh, outerMesh, fillType, c, alloc);
2196 sort_mesh(&innerMesh, c, alloc);
2197 sort_mesh(outerMesh, c, alloc);
Stephen Whitee260c462017-12-19 18:09:54 -05002198#ifdef GR_TESSELLATOR_LEGACY_INVERSION_HANDLING
Stephen Whitebda29c02017-03-13 15:10:13 -04002199 if (is_complex(innerMesh) || is_complex(*outerMesh)) {
Stephen Whitee260c462017-12-19 18:09:54 -05002200#else
2201 merge_coincident_vertices(&innerMesh, c, alloc);
2202 bool was_complex = merge_coincident_vertices(outerMesh, c, alloc);
2203 was_complex = simplify(&innerMesh, c, alloc) || was_complex;
2204 was_complex = simplify(outerMesh, c, alloc) || was_complex;
2205 LOG("\ninner mesh before:\n");
2206 dump_mesh(innerMesh);
2207 LOG("\nouter mesh before:\n");
2208 dump_mesh(*outerMesh);
2209 was_complex = collapse_overlap_regions(&innerMesh, c, alloc) || was_complex;
2210 was_complex = collapse_overlap_regions(outerMesh, c, alloc) || was_complex;
2211 if (was_complex) {
2212#endif
Stephen Whitebda29c02017-03-13 15:10:13 -04002213 LOG("found complex mesh; taking slow path\n");
2214 VertexList aaMesh;
Stephen White95152e12017-12-18 10:52:44 -05002215 LOG("\ninner mesh after:\n");
2216 dump_mesh(innerMesh);
2217 LOG("\nouter mesh after:\n");
2218 dump_mesh(*outerMesh);
Stephen Whitebda29c02017-03-13 15:10:13 -04002219 connect_partners(outerMesh, c, alloc);
Stephen Whitee260c462017-12-19 18:09:54 -05002220 connect_partners(&innerMesh, c, alloc);
Stephen Whitebda29c02017-03-13 15:10:13 -04002221 sorted_merge(&innerMesh, outerMesh, &aaMesh, c);
2222 merge_coincident_vertices(&aaMesh, c, alloc);
Stephen White0cb31672017-06-08 14:41:01 -04002223 simplify(&aaMesh, c, alloc);
Stephen White95152e12017-12-18 10:52:44 -05002224 dump_mesh(aaMesh);
Stephen Whitebda29c02017-03-13 15:10:13 -04002225 outerMesh->fHead = outerMesh->fTail = nullptr;
2226 return tessellate(aaMesh, alloc);
2227 } else {
2228 LOG("no complex polygons; taking fast path\n");
Stephen Whitee260c462017-12-19 18:09:54 -05002229#ifdef GR_TESSELLATOR_LEGACY_INVERSION_HANDLING
Stephen Whitebda29c02017-03-13 15:10:13 -04002230 merge_coincident_vertices(&innerMesh, c, alloc);
Stephen Whitee260c462017-12-19 18:09:54 -05002231#endif
Stephen Whitebda29c02017-03-13 15:10:13 -04002232 return tessellate(innerMesh, alloc);
2233 }
Stephen White49789062017-02-21 10:35:49 -05002234 } else {
2235 return tessellate(mesh, alloc);
senorblancof57372d2016-08-31 10:36:19 -07002236 }
senorblancof57372d2016-08-31 10:36:19 -07002237}
2238
2239// Stage 6: Triangulate the monotone polygons into a vertex buffer.
2240void* polys_to_triangles(Poly* polys, SkPath::FillType fillType, const AAParams* aaParams,
2241 void* data) {
2242 for (Poly* poly = polys; poly; poly = poly->fNext) {
2243 if (apply_fill_type(fillType, poly)) {
2244 data = poly->emit(aaParams, data);
2245 }
2246 }
2247 return data;
ethannicholase9709e82016-01-07 13:34:16 -08002248}
2249
halcanary9d524f22016-03-29 09:03:52 -07002250Poly* path_to_polys(const SkPath& path, SkScalar tolerance, const SkRect& clipBounds,
Stephen Whitebda29c02017-03-13 15:10:13 -04002251 int contourCnt, SkArenaAlloc& alloc, bool antialias, bool* isLinear,
2252 VertexList* outerMesh) {
ethannicholase9709e82016-01-07 13:34:16 -08002253 SkPath::FillType fillType = path.getFillType();
2254 if (SkPath::IsInverseFillType(fillType)) {
2255 contourCnt++;
2256 }
Stephen White3a9aab92017-03-07 14:07:18 -05002257 std::unique_ptr<VertexList[]> contours(new VertexList[contourCnt]);
ethannicholase9709e82016-01-07 13:34:16 -08002258
2259 path_to_contours(path, tolerance, clipBounds, contours.get(), alloc, isLinear);
senorblancof57372d2016-08-31 10:36:19 -07002260 return contours_to_polys(contours.get(), contourCnt, path.getFillType(), path.getBounds(),
Stephen Whitebda29c02017-03-13 15:10:13 -04002261 antialias, outerMesh, alloc);
ethannicholase9709e82016-01-07 13:34:16 -08002262}
2263
Stephen White11f65e02017-02-16 19:00:39 -05002264int get_contour_count(const SkPath& path, SkScalar tolerance) {
2265 int contourCnt;
2266 int maxPts = GrPathUtils::worstCasePointCount(path, &contourCnt, tolerance);
ethannicholase9709e82016-01-07 13:34:16 -08002267 if (maxPts <= 0) {
Stephen White11f65e02017-02-16 19:00:39 -05002268 return 0;
ethannicholase9709e82016-01-07 13:34:16 -08002269 }
2270 if (maxPts > ((int)SK_MaxU16 + 1)) {
2271 SkDebugf("Path not rendered, too many verts (%d)\n", maxPts);
Stephen White11f65e02017-02-16 19:00:39 -05002272 return 0;
ethannicholase9709e82016-01-07 13:34:16 -08002273 }
Stephen White11f65e02017-02-16 19:00:39 -05002274 return contourCnt;
ethannicholase9709e82016-01-07 13:34:16 -08002275}
2276
2277int count_points(Poly* polys, SkPath::FillType fillType) {
2278 int count = 0;
2279 for (Poly* poly = polys; poly; poly = poly->fNext) {
senorblancof57372d2016-08-31 10:36:19 -07002280 if (apply_fill_type(fillType, poly) && poly->fCount >= 3) {
ethannicholase9709e82016-01-07 13:34:16 -08002281 count += (poly->fCount - 2) * (TESSELLATOR_WIREFRAME ? 6 : 3);
2282 }
2283 }
2284 return count;
2285}
2286
Stephen Whitebda29c02017-03-13 15:10:13 -04002287int count_outer_mesh_points(const VertexList& outerMesh) {
2288 int count = 0;
2289 for (Vertex* v = outerMesh.fHead; v; v = v->fNext) {
2290 for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
2291 count += TESSELLATOR_WIREFRAME ? 12 : 6;
2292 }
2293 }
2294 return count;
2295}
2296
2297void* outer_mesh_to_triangles(const VertexList& outerMesh, const AAParams* aaParams, void* data) {
2298 for (Vertex* v = outerMesh.fHead; v; v = v->fNext) {
2299 for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
2300 Vertex* v0 = e->fTop;
2301 Vertex* v1 = e->fBottom;
2302 Vertex* v2 = e->fBottom->fPartner;
2303 Vertex* v3 = e->fTop->fPartner;
2304 data = emit_triangle(v0, v1, v2, aaParams, data);
2305 data = emit_triangle(v0, v2, v3, aaParams, data);
2306 }
2307 }
2308 return data;
2309}
2310
ethannicholase9709e82016-01-07 13:34:16 -08002311} // namespace
2312
2313namespace GrTessellator {
2314
2315// Stage 6: Triangulate the monotone polygons into a vertex buffer.
2316
halcanary9d524f22016-03-29 09:03:52 -07002317int PathToTriangles(const SkPath& path, SkScalar tolerance, const SkRect& clipBounds,
senorblancof57372d2016-08-31 10:36:19 -07002318 VertexAllocator* vertexAllocator, bool antialias, const GrColor& color,
2319 bool canTweakAlphaForCoverage, bool* isLinear) {
Stephen White11f65e02017-02-16 19:00:39 -05002320 int contourCnt = get_contour_count(path, tolerance);
ethannicholase9709e82016-01-07 13:34:16 -08002321 if (contourCnt <= 0) {
2322 *isLinear = true;
2323 return 0;
2324 }
Stephen White11f65e02017-02-16 19:00:39 -05002325 SkArenaAlloc alloc(kArenaChunkSize);
Stephen Whitebda29c02017-03-13 15:10:13 -04002326 VertexList outerMesh;
senorblancof57372d2016-08-31 10:36:19 -07002327 Poly* polys = path_to_polys(path, tolerance, clipBounds, contourCnt, alloc, antialias,
Stephen Whitebda29c02017-03-13 15:10:13 -04002328 isLinear, &outerMesh);
senorblanco7ab96e92016-10-12 06:47:44 -07002329 SkPath::FillType fillType = antialias ? SkPath::kWinding_FillType : path.getFillType();
ethannicholase9709e82016-01-07 13:34:16 -08002330 int count = count_points(polys, fillType);
Stephen Whitebda29c02017-03-13 15:10:13 -04002331 if (antialias) {
2332 count += count_outer_mesh_points(outerMesh);
2333 }
Stephen Whiteff60b172017-05-05 15:54:52 -04002334 if (0 == count) {
2335 return 0;
2336 }
ethannicholase9709e82016-01-07 13:34:16 -08002337
senorblancof57372d2016-08-31 10:36:19 -07002338 void* verts = vertexAllocator->lock(count);
senorblanco6599eff2016-03-10 08:38:45 -08002339 if (!verts) {
ethannicholase9709e82016-01-07 13:34:16 -08002340 SkDebugf("Could not allocate vertices\n");
2341 return 0;
2342 }
senorblancof57372d2016-08-31 10:36:19 -07002343
2344 LOG("emitting %d verts\n", count);
2345 AAParams aaParams;
2346 aaParams.fTweakAlpha = canTweakAlphaForCoverage;
2347 aaParams.fColor = color;
2348
2349 void* end = polys_to_triangles(polys, fillType, antialias ? &aaParams : nullptr, verts);
Stephen Whitebda29c02017-03-13 15:10:13 -04002350 end = outer_mesh_to_triangles(outerMesh, &aaParams, end);
senorblancof57372d2016-08-31 10:36:19 -07002351 int actualCount = static_cast<int>((static_cast<uint8_t*>(end) - static_cast<uint8_t*>(verts))
2352 / vertexAllocator->stride());
ethannicholase9709e82016-01-07 13:34:16 -08002353 SkASSERT(actualCount <= count);
senorblanco6599eff2016-03-10 08:38:45 -08002354 vertexAllocator->unlock(actualCount);
ethannicholase9709e82016-01-07 13:34:16 -08002355 return actualCount;
2356}
2357
halcanary9d524f22016-03-29 09:03:52 -07002358int PathToVertices(const SkPath& path, SkScalar tolerance, const SkRect& clipBounds,
ethannicholase9709e82016-01-07 13:34:16 -08002359 GrTessellator::WindingVertex** verts) {
Stephen White11f65e02017-02-16 19:00:39 -05002360 int contourCnt = get_contour_count(path, tolerance);
ethannicholase9709e82016-01-07 13:34:16 -08002361 if (contourCnt <= 0) {
2362 return 0;
2363 }
Stephen White11f65e02017-02-16 19:00:39 -05002364 SkArenaAlloc alloc(kArenaChunkSize);
ethannicholase9709e82016-01-07 13:34:16 -08002365 bool isLinear;
Stephen Whitebda29c02017-03-13 15:10:13 -04002366 Poly* polys = path_to_polys(path, tolerance, clipBounds, contourCnt, alloc, false, &isLinear,
2367 nullptr);
ethannicholase9709e82016-01-07 13:34:16 -08002368 SkPath::FillType fillType = path.getFillType();
2369 int count = count_points(polys, fillType);
2370 if (0 == count) {
2371 *verts = nullptr;
2372 return 0;
2373 }
2374
2375 *verts = new GrTessellator::WindingVertex[count];
2376 GrTessellator::WindingVertex* vertsEnd = *verts;
2377 SkPoint* points = new SkPoint[count];
2378 SkPoint* pointsEnd = points;
2379 for (Poly* poly = polys; poly; poly = poly->fNext) {
senorblancof57372d2016-08-31 10:36:19 -07002380 if (apply_fill_type(fillType, poly)) {
ethannicholase9709e82016-01-07 13:34:16 -08002381 SkPoint* start = pointsEnd;
senorblancof57372d2016-08-31 10:36:19 -07002382 pointsEnd = static_cast<SkPoint*>(poly->emit(nullptr, pointsEnd));
ethannicholase9709e82016-01-07 13:34:16 -08002383 while (start != pointsEnd) {
2384 vertsEnd->fPos = *start;
2385 vertsEnd->fWinding = poly->fWinding;
2386 ++start;
2387 ++vertsEnd;
2388 }
2389 }
2390 }
2391 int actualCount = static_cast<int>(vertsEnd - *verts);
2392 SkASSERT(actualCount <= count);
2393 SkASSERT(pointsEnd - points == actualCount);
2394 delete[] points;
2395 return actualCount;
2396}
2397
2398} // namespace