blob: a8fa79e56059ec9606f8a99ac231c5a9e9bf15ff [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
10#include "GrBatchFlushState.h"
11#include "GrBatchTest.h"
12#include "GrDefaultGeoProcFactory.h"
13#include "GrPathUtils.h"
14#include "GrVertices.h"
15#include "GrResourceCache.h"
16#include "GrResourceProvider.h"
17#include "SkGeometry.h"
18#include "SkChunkAlloc.h"
19
20#include "batches/GrVertexBatch.h"
21
22#include <stdio.h>
23
24/*
25 * There are six stages to the algorithm:
26 *
27 * 1) Linearize the path contours into piecewise linear segments (path_to_contours()).
28 * 2) Build a mesh of edges connecting the vertices (build_edges()).
29 * 3) Sort the vertices in Y (and secondarily in X) (merge_sort()).
30 * 4) Simplify the mesh by inserting new vertices at intersecting edges (simplify()).
31 * 5) Tessellate the simplified mesh into monotone polygons (tessellate()).
32 * 6) Triangulate the monotone polygons directly into a vertex buffer (polys_to_triangles()).
33 *
34 * The vertex sorting in step (3) is a merge sort, since it plays well with the linked list
35 * of vertices (and the necessity of inserting new vertices on intersection).
36 *
37 * Stages (4) and (5) use an active edge list, which a list of all edges for which the
38 * sweep line has crossed the top vertex, but not the bottom vertex. It's sorted
39 * left-to-right based on the point where both edges are active (when both top vertices
40 * have been seen, so the "lower" top vertex of the two). If the top vertices are equal
41 * (shared), it's sorted based on the last point where both edges are active, so the
42 * "upper" bottom vertex.
43 *
44 * The most complex step is the simplification (4). It's based on the Bentley-Ottman
45 * line-sweep algorithm, but due to floating point inaccuracy, the intersection points are
46 * not exact and may violate the mesh topology or active edge list ordering. We
47 * accommodate this by adjusting the topology of the mesh and AEL to match the intersection
48 * points. This occurs in three ways:
49 *
50 * A) Intersections may cause a shortened edge to no longer be ordered with respect to its
51 * neighbouring edges at the top or bottom vertex. This is handled by merging the
52 * edges (merge_collinear_edges()).
53 * B) Intersections may cause an edge to violate the left-to-right ordering of the
54 * active edge list. This is handled by splitting the neighbour edge on the
55 * intersected vertex (cleanup_active_edges()).
56 * C) Shortening an edge may cause an active edge to become inactive or an inactive edge
57 * to become active. This is handled by removing or inserting the edge in the active
58 * edge list (fix_active_state()).
59 *
60 * The tessellation steps (5) and (6) are based on "Triangulating Simple Polygons and
61 * Equivalent Problems" (Fournier and Montuno); also a line-sweep algorithm. Note that it
62 * currently uses a linked list for the active edge list, rather than a 2-3 tree as the
63 * paper describes. The 2-3 tree gives O(lg N) lookups, but insertion and removal also
64 * become O(lg N). In all the test cases, it was found that the cost of frequent O(lg N)
65 * insertions and removals was greater than the cost of infrequent O(N) lookups with the
66 * linked list implementation. With the latter, all removals are O(1), and most insertions
67 * are O(1), since we know the adjacent edge in the active edge list based on the topology.
68 * Only type 2 vertices (see paper) require the O(N) lookups, and these are much less
69 * frequent. There may be other data structures worth investigating, however.
70 *
71 * Note that the orientation of the line sweep algorithms is determined by the aspect ratio of the
72 * path bounds. When the path is taller than it is wide, we sort vertices based on increasing Y
73 * coordinate, and secondarily by increasing X coordinate. When the path is wider than it is tall,
74 * we sort by increasing X coordinate, but secondarily by *decreasing* Y coordinate. This is so
75 * that the "left" and "right" orientation in the code remains correct (edges to the left are
76 * increasing in Y; edges to the right are decreasing in Y). That is, the setting rotates 90
77 * degrees counterclockwise, rather that transposing.
78 */
79
80#define LOGGING_ENABLED 0
81
82#if LOGGING_ENABLED
83#define LOG printf
84#else
85#define LOG(...)
86#endif
87
88#define ALLOC_NEW(Type, args, alloc) new (alloc.allocThrow(sizeof(Type))) Type args
89
90namespace {
91
92struct Vertex;
93struct Edge;
94struct Poly;
95
96template <class T, T* T::*Prev, T* T::*Next>
senorblancoe6eaa322016-03-08 09:06:44 -080097void list_insert(T* t, T* prev, T* next, T** head, T** tail) {
ethannicholase9709e82016-01-07 13:34:16 -080098 t->*Prev = prev;
99 t->*Next = next;
100 if (prev) {
101 prev->*Next = t;
102 } else if (head) {
103 *head = t;
104 }
105 if (next) {
106 next->*Prev = t;
107 } else if (tail) {
108 *tail = t;
109 }
110}
111
112template <class T, T* T::*Prev, T* T::*Next>
senorblancoe6eaa322016-03-08 09:06:44 -0800113void list_remove(T* t, T** head, T** tail) {
ethannicholase9709e82016-01-07 13:34:16 -0800114 if (t->*Prev) {
115 t->*Prev->*Next = t->*Next;
116 } else if (head) {
117 *head = t->*Next;
118 }
119 if (t->*Next) {
120 t->*Next->*Prev = t->*Prev;
121 } else if (tail) {
122 *tail = t->*Prev;
123 }
124 t->*Prev = t->*Next = nullptr;
125}
126
127/**
128 * Vertices are used in three ways: first, the path contours are converted into a
129 * circularly-linked list of Vertices for each contour. After edge construction, the same Vertices
130 * are re-ordered by the merge sort according to the sweep_lt comparator (usually, increasing
131 * in Y) using the same fPrev/fNext pointers that were used for the contours, to avoid
132 * reallocation. Finally, MonotonePolys are built containing a circularly-linked list of
133 * Vertices. (Currently, those Vertices are newly-allocated for the MonotonePolys, since
134 * an individual Vertex from the path mesh may belong to multiple
135 * MonotonePolys, so the original Vertices cannot be re-used.
136 */
137
138struct Vertex {
139 Vertex(const SkPoint& point)
140 : fPoint(point), fPrev(nullptr), fNext(nullptr)
141 , fFirstEdgeAbove(nullptr), fLastEdgeAbove(nullptr)
142 , fFirstEdgeBelow(nullptr), fLastEdgeBelow(nullptr)
143 , fProcessed(false)
144#if LOGGING_ENABLED
145 , fID (-1.0f)
146#endif
147 {}
148 SkPoint fPoint; // Vertex position
149 Vertex* fPrev; // Linked list of contours, then Y-sorted vertices.
150 Vertex* fNext; // "
151 Edge* fFirstEdgeAbove; // Linked list of edges above this vertex.
152 Edge* fLastEdgeAbove; // "
153 Edge* fFirstEdgeBelow; // Linked list of edges below this vertex.
154 Edge* fLastEdgeBelow; // "
155 bool fProcessed; // Has this vertex been seen in simplify()?
156#if LOGGING_ENABLED
157 float fID; // Identifier used for logging.
158#endif
159};
160
161/***************************************************************************************/
162
163typedef bool (*CompareFunc)(const SkPoint& a, const SkPoint& b);
164
165struct Comparator {
166 CompareFunc sweep_lt;
167 CompareFunc sweep_gt;
168};
169
170bool sweep_lt_horiz(const SkPoint& a, const SkPoint& b) {
171 return a.fX == b.fX ? a.fY > b.fY : a.fX < b.fX;
172}
173
174bool sweep_lt_vert(const SkPoint& a, const SkPoint& b) {
175 return a.fY == b.fY ? a.fX < b.fX : a.fY < b.fY;
176}
177
178bool sweep_gt_horiz(const SkPoint& a, const SkPoint& b) {
179 return a.fX == b.fX ? a.fY < b.fY : a.fX > b.fX;
180}
181
182bool sweep_gt_vert(const SkPoint& a, const SkPoint& b) {
183 return a.fY == b.fY ? a.fX > b.fX : a.fY > b.fY;
184}
185
186inline SkPoint* emit_vertex(Vertex* v, SkPoint* data) {
187 *data++ = v->fPoint;
188 return data;
189}
190
191SkPoint* emit_triangle(Vertex* v0, Vertex* v1, Vertex* v2, SkPoint* data) {
192#if WIREFRAME
193 data = emit_vertex(v0, data);
194 data = emit_vertex(v1, data);
195 data = emit_vertex(v1, data);
196 data = emit_vertex(v2, data);
197 data = emit_vertex(v2, data);
198 data = emit_vertex(v0, data);
199#else
200 data = emit_vertex(v0, data);
201 data = emit_vertex(v1, data);
202 data = emit_vertex(v2, data);
203#endif
204 return data;
205}
206
207struct EdgeList {
208 EdgeList() : fHead(nullptr), fTail(nullptr) {}
209 Edge* fHead;
210 Edge* fTail;
211};
212
senorblancoe6eaa322016-03-08 09:06:44 -0800213struct VertexList {
214 VertexList() : fHead(nullptr), fTail(nullptr) {}
215 Vertex* fHead;
216 Vertex* fTail;
217 void insert(Vertex* v, Vertex* prev, Vertex* next) {
218 list_insert<Vertex, &Vertex::fPrev, &Vertex::fNext>(v, prev, next, &fHead, &fTail);
219 }
220 void append(Vertex* v) {
221 insert(v, fTail, nullptr);
222 }
223 void prepend(Vertex* v) {
224 insert(v, nullptr, fHead);
225 }
226};
227
ethannicholase9709e82016-01-07 13:34:16 -0800228/**
229 * An Edge joins a top Vertex to a bottom Vertex. Edge ordering for the list of "edges above" and
230 * "edge below" a vertex as well as for the active edge list is handled by isLeftOf()/isRightOf().
231 * Note that an Edge will give occasionally dist() != 0 for its own endpoints (because floating
232 * point). For speed, that case is only tested by the callers which require it (e.g.,
233 * cleanup_active_edges()). Edges also handle checking for intersection with other edges.
234 * Currently, this converts the edges to the parametric form, in order to avoid doing a division
235 * until an intersection has been confirmed. This is slightly slower in the "found" case, but
236 * a lot faster in the "not found" case.
237 *
238 * The coefficients of the line equation stored in double precision to avoid catastrphic
239 * cancellation in the isLeftOf() and isRightOf() checks. Using doubles ensures that the result is
240 * correct in float, since it's a polynomial of degree 2. The intersect() function, being
241 * degree 5, is still subject to catastrophic cancellation. We deal with that by assuming its
242 * output may be incorrect, and adjusting the mesh topology to match (see comment at the top of
243 * this file).
244 */
245
246struct Edge {
247 Edge(Vertex* top, Vertex* bottom, int winding)
248 : fWinding(winding)
249 , fTop(top)
250 , fBottom(bottom)
251 , fLeft(nullptr)
252 , fRight(nullptr)
253 , fPrevEdgeAbove(nullptr)
254 , fNextEdgeAbove(nullptr)
255 , fPrevEdgeBelow(nullptr)
256 , fNextEdgeBelow(nullptr)
257 , fLeftPoly(nullptr)
258 , fRightPoly(nullptr) {
259 recompute();
260 }
261 int fWinding; // 1 == edge goes downward; -1 = edge goes upward.
262 Vertex* fTop; // The top vertex in vertex-sort-order (sweep_lt).
263 Vertex* fBottom; // The bottom vertex in vertex-sort-order.
264 Edge* fLeft; // The linked list of edges in the active edge list.
265 Edge* fRight; // "
266 Edge* fPrevEdgeAbove; // The linked list of edges in the bottom Vertex's "edges above".
267 Edge* fNextEdgeAbove; // "
268 Edge* fPrevEdgeBelow; // The linked list of edges in the top Vertex's "edges below".
269 Edge* fNextEdgeBelow; // "
270 Poly* fLeftPoly; // The Poly to the left of this edge, if any.
271 Poly* fRightPoly; // The Poly to the right of this edge, if any.
272 double fDX; // The line equation for this edge, in implicit form.
273 double fDY; // fDY * x + fDX * y + fC = 0, for point (x, y) on the line.
274 double fC;
275 double dist(const SkPoint& p) const {
276 return fDY * p.fX - fDX * p.fY + fC;
277 }
278 bool isRightOf(Vertex* v) const {
279 return dist(v->fPoint) < 0.0;
280 }
281 bool isLeftOf(Vertex* v) const {
282 return dist(v->fPoint) > 0.0;
283 }
284 void recompute() {
285 fDX = static_cast<double>(fBottom->fPoint.fX) - fTop->fPoint.fX;
286 fDY = static_cast<double>(fBottom->fPoint.fY) - fTop->fPoint.fY;
287 fC = static_cast<double>(fTop->fPoint.fY) * fBottom->fPoint.fX -
288 static_cast<double>(fTop->fPoint.fX) * fBottom->fPoint.fY;
289 }
290 bool intersect(const Edge& other, SkPoint* p) {
291 LOG("intersecting %g -> %g with %g -> %g\n",
292 fTop->fID, fBottom->fID,
293 other.fTop->fID, other.fBottom->fID);
294 if (fTop == other.fTop || fBottom == other.fBottom) {
295 return false;
296 }
297 double denom = fDX * other.fDY - fDY * other.fDX;
298 if (denom == 0.0) {
299 return false;
300 }
301 double dx = static_cast<double>(fTop->fPoint.fX) - other.fTop->fPoint.fX;
302 double dy = static_cast<double>(fTop->fPoint.fY) - other.fTop->fPoint.fY;
303 double sNumer = dy * other.fDX - dx * other.fDY;
304 double tNumer = dy * fDX - dx * fDY;
305 // If (sNumer / denom) or (tNumer / denom) is not in [0..1], exit early.
306 // This saves us doing the divide below unless absolutely necessary.
307 if (denom > 0.0 ? (sNumer < 0.0 || sNumer > denom || tNumer < 0.0 || tNumer > denom)
308 : (sNumer > 0.0 || sNumer < denom || tNumer > 0.0 || tNumer < denom)) {
309 return false;
310 }
311 double s = sNumer / denom;
312 SkASSERT(s >= 0.0 && s <= 1.0);
313 p->fX = SkDoubleToScalar(fTop->fPoint.fX + s * fDX);
314 p->fY = SkDoubleToScalar(fTop->fPoint.fY + s * fDY);
315 return true;
316 }
317 bool isActive(EdgeList* activeEdges) const {
318 return activeEdges && (fLeft || fRight || activeEdges->fHead == this);
319 }
320};
321
322/***************************************************************************************/
323
324struct Poly {
325 Poly(int winding)
326 : fWinding(winding)
327 , fHead(nullptr)
328 , fTail(nullptr)
329 , fActive(nullptr)
330 , fNext(nullptr)
331 , fPartner(nullptr)
332 , fCount(0)
333 {
334#if LOGGING_ENABLED
335 static int gID = 0;
336 fID = gID++;
337 LOG("*** created Poly %d\n", fID);
338#endif
339 }
340 typedef enum { kNeither_Side, kLeft_Side, kRight_Side } Side;
341 struct MonotonePoly {
342 MonotonePoly()
343 : fSide(kNeither_Side)
ethannicholase9709e82016-01-07 13:34:16 -0800344 , fPrev(nullptr)
345 , fNext(nullptr) {}
346 Side fSide;
senorblancoe6eaa322016-03-08 09:06:44 -0800347 VertexList fVertices;
ethannicholase9709e82016-01-07 13:34:16 -0800348 MonotonePoly* fPrev;
349 MonotonePoly* fNext;
350 bool addVertex(Vertex* v, Side side, SkChunkAlloc& alloc) {
351 Vertex* newV = ALLOC_NEW(Vertex, (v->fPoint), alloc);
352 bool done = false;
353 if (fSide == kNeither_Side) {
354 fSide = side;
355 } else {
356 done = side != fSide;
357 }
senorblancoe6eaa322016-03-08 09:06:44 -0800358 if (fSide == kRight_Side) {
359 fVertices.append(newV);
ethannicholase9709e82016-01-07 13:34:16 -0800360 } else {
senorblancoe6eaa322016-03-08 09:06:44 -0800361 fVertices.prepend(newV);
ethannicholase9709e82016-01-07 13:34:16 -0800362 }
363 return done;
364 }
365
366 SkPoint* emit(SkPoint* data) {
senorblancoe6eaa322016-03-08 09:06:44 -0800367 Vertex* first = fVertices.fHead;
ethannicholase9709e82016-01-07 13:34:16 -0800368 Vertex* v = first->fNext;
senorblancoe6eaa322016-03-08 09:06:44 -0800369 while (v != fVertices.fTail) {
ethannicholase9709e82016-01-07 13:34:16 -0800370 SkASSERT(v && v->fPrev && v->fNext);
371 Vertex* prev = v->fPrev;
372 Vertex* curr = v;
373 Vertex* next = v->fNext;
374 double ax = static_cast<double>(curr->fPoint.fX) - prev->fPoint.fX;
375 double ay = static_cast<double>(curr->fPoint.fY) - prev->fPoint.fY;
376 double bx = static_cast<double>(next->fPoint.fX) - curr->fPoint.fX;
377 double by = static_cast<double>(next->fPoint.fY) - curr->fPoint.fY;
378 if (ax * by - ay * bx >= 0.0) {
379 data = emit_triangle(prev, curr, next, data);
380 v->fPrev->fNext = v->fNext;
381 v->fNext->fPrev = v->fPrev;
382 if (v->fPrev == first) {
383 v = v->fNext;
384 } else {
385 v = v->fPrev;
386 }
387 } else {
388 v = v->fNext;
389 }
390 }
391 return data;
392 }
393 };
394 Poly* addVertex(Vertex* v, Side side, SkChunkAlloc& alloc) {
395 LOG("addVertex() to %d at %g (%g, %g), %s side\n", fID, v->fID, v->fPoint.fX, v->fPoint.fY,
396 side == kLeft_Side ? "left" : side == kRight_Side ? "right" : "neither");
397 Poly* partner = fPartner;
398 Poly* poly = this;
399 if (partner) {
400 fPartner = partner->fPartner = nullptr;
401 }
402 if (!fActive) {
403 fActive = ALLOC_NEW(MonotonePoly, (), alloc);
404 }
405 if (fActive->addVertex(v, side, alloc)) {
406 if (fTail) {
407 fActive->fPrev = fTail;
408 fTail->fNext = fActive;
409 fTail = fActive;
410 } else {
411 fHead = fTail = fActive;
412 }
413 if (partner) {
414 partner->addVertex(v, side, alloc);
415 poly = partner;
416 } else {
417 Vertex* prev = fActive->fSide == Poly::kLeft_Side ?
senorblancoe6eaa322016-03-08 09:06:44 -0800418 fActive->fVertices.fHead->fNext : fActive->fVertices.fTail->fPrev;
ethannicholase9709e82016-01-07 13:34:16 -0800419 fActive = ALLOC_NEW(MonotonePoly, , alloc);
420 fActive->addVertex(prev, Poly::kNeither_Side, alloc);
421 fActive->addVertex(v, side, alloc);
422 }
423 }
424 fCount++;
425 return poly;
426 }
427 void end(Vertex* v, SkChunkAlloc& alloc) {
428 LOG("end() %d at %g, %g\n", fID, v->fPoint.fX, v->fPoint.fY);
429 if (fPartner) {
430 fPartner = fPartner->fPartner = nullptr;
431 }
432 addVertex(v, fActive->fSide == kLeft_Side ? kRight_Side : kLeft_Side, alloc);
433 }
434 SkPoint* emit(SkPoint *data) {
435 if (fCount < 3) {
436 return data;
437 }
438 LOG("emit() %d, size %d\n", fID, fCount);
439 for (MonotonePoly* m = fHead; m != nullptr; m = m->fNext) {
440 data = m->emit(data);
441 }
442 return data;
443 }
444 int fWinding;
445 MonotonePoly* fHead;
446 MonotonePoly* fTail;
447 MonotonePoly* fActive;
448 Poly* fNext;
449 Poly* fPartner;
450 int fCount;
451#if LOGGING_ENABLED
452 int fID;
453#endif
454};
455
456/***************************************************************************************/
457
458bool coincident(const SkPoint& a, const SkPoint& b) {
459 return a == b;
460}
461
462Poly* new_poly(Poly** head, Vertex* v, int winding, SkChunkAlloc& alloc) {
463 Poly* poly = ALLOC_NEW(Poly, (winding), alloc);
464 poly->addVertex(v, Poly::kNeither_Side, alloc);
465 poly->fNext = *head;
466 *head = poly;
467 return poly;
468}
469
470Vertex* append_point_to_contour(const SkPoint& p, Vertex* prev, Vertex** head,
471 SkChunkAlloc& alloc) {
472 Vertex* v = ALLOC_NEW(Vertex, (p), alloc);
473#if LOGGING_ENABLED
474 static float gID = 0.0f;
475 v->fID = gID++;
476#endif
477 if (prev) {
478 prev->fNext = v;
479 v->fPrev = prev;
480 } else {
481 *head = v;
482 }
483 return v;
484}
485
486Vertex* generate_quadratic_points(const SkPoint& p0,
487 const SkPoint& p1,
488 const SkPoint& p2,
489 SkScalar tolSqd,
490 Vertex* prev,
491 Vertex** head,
492 int pointsLeft,
493 SkChunkAlloc& alloc) {
494 SkScalar d = p1.distanceToLineSegmentBetweenSqd(p0, p2);
495 if (pointsLeft < 2 || d < tolSqd || !SkScalarIsFinite(d)) {
496 return append_point_to_contour(p2, prev, head, alloc);
497 }
498
499 const SkPoint q[] = {
500 { SkScalarAve(p0.fX, p1.fX), SkScalarAve(p0.fY, p1.fY) },
501 { SkScalarAve(p1.fX, p2.fX), SkScalarAve(p1.fY, p2.fY) },
502 };
503 const SkPoint r = { SkScalarAve(q[0].fX, q[1].fX), SkScalarAve(q[0].fY, q[1].fY) };
504
505 pointsLeft >>= 1;
506 prev = generate_quadratic_points(p0, q[0], r, tolSqd, prev, head, pointsLeft, alloc);
507 prev = generate_quadratic_points(r, q[1], p2, tolSqd, prev, head, pointsLeft, alloc);
508 return prev;
509}
510
511Vertex* generate_cubic_points(const SkPoint& p0,
512 const SkPoint& p1,
513 const SkPoint& p2,
514 const SkPoint& p3,
515 SkScalar tolSqd,
516 Vertex* prev,
517 Vertex** head,
518 int pointsLeft,
519 SkChunkAlloc& alloc) {
520 SkScalar d1 = p1.distanceToLineSegmentBetweenSqd(p0, p3);
521 SkScalar d2 = p2.distanceToLineSegmentBetweenSqd(p0, p3);
522 if (pointsLeft < 2 || (d1 < tolSqd && d2 < tolSqd) ||
523 !SkScalarIsFinite(d1) || !SkScalarIsFinite(d2)) {
524 return append_point_to_contour(p3, prev, head, alloc);
525 }
526 const SkPoint q[] = {
527 { SkScalarAve(p0.fX, p1.fX), SkScalarAve(p0.fY, p1.fY) },
528 { SkScalarAve(p1.fX, p2.fX), SkScalarAve(p1.fY, p2.fY) },
529 { SkScalarAve(p2.fX, p3.fX), SkScalarAve(p2.fY, p3.fY) }
530 };
531 const SkPoint r[] = {
532 { SkScalarAve(q[0].fX, q[1].fX), SkScalarAve(q[0].fY, q[1].fY) },
533 { SkScalarAve(q[1].fX, q[2].fX), SkScalarAve(q[1].fY, q[2].fY) }
534 };
535 const SkPoint s = { SkScalarAve(r[0].fX, r[1].fX), SkScalarAve(r[0].fY, r[1].fY) };
536 pointsLeft >>= 1;
537 prev = generate_cubic_points(p0, q[0], r[0], s, tolSqd, prev, head, pointsLeft, alloc);
538 prev = generate_cubic_points(s, r[1], q[2], p3, tolSqd, prev, head, pointsLeft, alloc);
539 return prev;
540}
541
542// Stage 1: convert the input path to a set of linear contours (linked list of Vertices).
543
544void path_to_contours(const SkPath& path, SkScalar tolerance, const SkRect& clipBounds,
545 Vertex** contours, SkChunkAlloc& alloc, bool *isLinear) {
546 SkScalar toleranceSqd = tolerance * tolerance;
547
548 SkPoint pts[4];
549 bool done = false;
550 *isLinear = true;
551 SkPath::Iter iter(path, false);
552 Vertex* prev = nullptr;
553 Vertex* head = nullptr;
554 if (path.isInverseFillType()) {
555 SkPoint quad[4];
556 clipBounds.toQuad(quad);
557 for (int i = 3; i >= 0; i--) {
558 prev = append_point_to_contour(quad[i], prev, &head, alloc);
559 }
560 head->fPrev = prev;
561 prev->fNext = head;
562 *contours++ = head;
563 head = prev = nullptr;
564 }
565 SkAutoConicToQuads converter;
566 while (!done) {
567 SkPath::Verb verb = iter.next(pts);
568 switch (verb) {
569 case SkPath::kConic_Verb: {
570 SkScalar weight = iter.conicWeight();
571 const SkPoint* quadPts = converter.computeQuads(pts, weight, toleranceSqd);
572 for (int i = 0; i < converter.countQuads(); ++i) {
573 int pointsLeft = GrPathUtils::quadraticPointCount(quadPts, tolerance);
574 prev = generate_quadratic_points(quadPts[0], quadPts[1], quadPts[2],
575 toleranceSqd, prev, &head, pointsLeft, alloc);
576 quadPts += 2;
577 }
578 *isLinear = false;
579 break;
580 }
581 case SkPath::kMove_Verb:
582 if (head) {
583 head->fPrev = prev;
584 prev->fNext = head;
585 *contours++ = head;
586 }
587 head = prev = nullptr;
588 prev = append_point_to_contour(pts[0], prev, &head, alloc);
589 break;
590 case SkPath::kLine_Verb: {
591 prev = append_point_to_contour(pts[1], prev, &head, alloc);
592 break;
593 }
594 case SkPath::kQuad_Verb: {
595 int pointsLeft = GrPathUtils::quadraticPointCount(pts, tolerance);
596 prev = generate_quadratic_points(pts[0], pts[1], pts[2], toleranceSqd, prev,
597 &head, pointsLeft, alloc);
598 *isLinear = false;
599 break;
600 }
601 case SkPath::kCubic_Verb: {
602 int pointsLeft = GrPathUtils::cubicPointCount(pts, tolerance);
603 prev = generate_cubic_points(pts[0], pts[1], pts[2], pts[3],
604 toleranceSqd, prev, &head, pointsLeft, alloc);
605 *isLinear = false;
606 break;
607 }
608 case SkPath::kClose_Verb:
609 if (head) {
610 head->fPrev = prev;
611 prev->fNext = head;
612 *contours++ = head;
613 }
614 head = prev = nullptr;
615 break;
616 case SkPath::kDone_Verb:
617 if (head) {
618 head->fPrev = prev;
619 prev->fNext = head;
620 *contours++ = head;
621 }
622 done = true;
623 break;
624 }
625 }
626}
627
628inline bool apply_fill_type(SkPath::FillType fillType, int winding) {
629 switch (fillType) {
630 case SkPath::kWinding_FillType:
631 return winding != 0;
632 case SkPath::kEvenOdd_FillType:
633 return (winding & 1) != 0;
634 case SkPath::kInverseWinding_FillType:
635 return winding == 1;
636 case SkPath::kInverseEvenOdd_FillType:
637 return (winding & 1) == 1;
638 default:
639 SkASSERT(false);
640 return false;
641 }
642}
643
644Edge* new_edge(Vertex* prev, Vertex* next, SkChunkAlloc& alloc, Comparator& c) {
645 int winding = c.sweep_lt(prev->fPoint, next->fPoint) ? 1 : -1;
646 Vertex* top = winding < 0 ? next : prev;
647 Vertex* bottom = winding < 0 ? prev : next;
648 return ALLOC_NEW(Edge, (top, bottom, winding), alloc);
649}
650
651void remove_edge(Edge* edge, EdgeList* edges) {
652 LOG("removing edge %g -> %g\n", edge->fTop->fID, edge->fBottom->fID);
653 SkASSERT(edge->isActive(edges));
senorblancoe6eaa322016-03-08 09:06:44 -0800654 list_remove<Edge, &Edge::fLeft, &Edge::fRight>(edge, &edges->fHead, &edges->fTail);
ethannicholase9709e82016-01-07 13:34:16 -0800655}
656
657void insert_edge(Edge* edge, Edge* prev, EdgeList* edges) {
658 LOG("inserting edge %g -> %g\n", edge->fTop->fID, edge->fBottom->fID);
659 SkASSERT(!edge->isActive(edges));
660 Edge* next = prev ? prev->fRight : edges->fHead;
senorblancoe6eaa322016-03-08 09:06:44 -0800661 list_insert<Edge, &Edge::fLeft, &Edge::fRight>(edge, prev, next, &edges->fHead, &edges->fTail);
ethannicholase9709e82016-01-07 13:34:16 -0800662}
663
664void find_enclosing_edges(Vertex* v, EdgeList* edges, Edge** left, Edge** right) {
665 if (v->fFirstEdgeAbove) {
666 *left = v->fFirstEdgeAbove->fLeft;
667 *right = v->fLastEdgeAbove->fRight;
668 return;
669 }
670 Edge* next = nullptr;
671 Edge* prev;
672 for (prev = edges->fTail; prev != nullptr; prev = prev->fLeft) {
673 if (prev->isLeftOf(v)) {
674 break;
675 }
676 next = prev;
677 }
678 *left = prev;
679 *right = next;
ethannicholase9709e82016-01-07 13:34:16 -0800680}
681
682void find_enclosing_edges(Edge* edge, EdgeList* edges, Comparator& c, Edge** left, Edge** right) {
683 Edge* prev = nullptr;
684 Edge* next;
685 for (next = edges->fHead; next != nullptr; next = next->fRight) {
686 if ((c.sweep_gt(edge->fTop->fPoint, next->fTop->fPoint) && next->isRightOf(edge->fTop)) ||
687 (c.sweep_gt(next->fTop->fPoint, edge->fTop->fPoint) && edge->isLeftOf(next->fTop)) ||
688 (c.sweep_lt(edge->fBottom->fPoint, next->fBottom->fPoint) &&
689 next->isRightOf(edge->fBottom)) ||
690 (c.sweep_lt(next->fBottom->fPoint, edge->fBottom->fPoint) &&
691 edge->isLeftOf(next->fBottom))) {
692 break;
693 }
694 prev = next;
695 }
696 *left = prev;
697 *right = next;
ethannicholase9709e82016-01-07 13:34:16 -0800698}
699
700void fix_active_state(Edge* edge, EdgeList* activeEdges, Comparator& c) {
701 if (edge->isActive(activeEdges)) {
702 if (edge->fBottom->fProcessed || !edge->fTop->fProcessed) {
703 remove_edge(edge, activeEdges);
704 }
705 } else if (edge->fTop->fProcessed && !edge->fBottom->fProcessed) {
706 Edge* left;
707 Edge* right;
708 find_enclosing_edges(edge, activeEdges, c, &left, &right);
709 insert_edge(edge, left, activeEdges);
710 }
711}
712
713void insert_edge_above(Edge* edge, Vertex* v, Comparator& c) {
714 if (edge->fTop->fPoint == edge->fBottom->fPoint ||
715 c.sweep_gt(edge->fTop->fPoint, edge->fBottom->fPoint)) {
716 return;
717 }
718 LOG("insert edge (%g -> %g) above vertex %g\n", edge->fTop->fID, edge->fBottom->fID, v->fID);
719 Edge* prev = nullptr;
720 Edge* next;
721 for (next = v->fFirstEdgeAbove; next; next = next->fNextEdgeAbove) {
722 if (next->isRightOf(edge->fTop)) {
723 break;
724 }
725 prev = next;
726 }
senorblancoe6eaa322016-03-08 09:06:44 -0800727 list_insert<Edge, &Edge::fPrevEdgeAbove, &Edge::fNextEdgeAbove>(
ethannicholase9709e82016-01-07 13:34:16 -0800728 edge, prev, next, &v->fFirstEdgeAbove, &v->fLastEdgeAbove);
729}
730
731void insert_edge_below(Edge* edge, Vertex* v, Comparator& c) {
732 if (edge->fTop->fPoint == edge->fBottom->fPoint ||
733 c.sweep_gt(edge->fTop->fPoint, edge->fBottom->fPoint)) {
734 return;
735 }
736 LOG("insert edge (%g -> %g) below vertex %g\n", edge->fTop->fID, edge->fBottom->fID, v->fID);
737 Edge* prev = nullptr;
738 Edge* next;
739 for (next = v->fFirstEdgeBelow; next; next = next->fNextEdgeBelow) {
740 if (next->isRightOf(edge->fBottom)) {
741 break;
742 }
743 prev = next;
744 }
senorblancoe6eaa322016-03-08 09:06:44 -0800745 list_insert<Edge, &Edge::fPrevEdgeBelow, &Edge::fNextEdgeBelow>(
ethannicholase9709e82016-01-07 13:34:16 -0800746 edge, prev, next, &v->fFirstEdgeBelow, &v->fLastEdgeBelow);
747}
748
749void remove_edge_above(Edge* edge) {
750 LOG("removing edge (%g -> %g) above vertex %g\n", edge->fTop->fID, edge->fBottom->fID,
751 edge->fBottom->fID);
senorblancoe6eaa322016-03-08 09:06:44 -0800752 list_remove<Edge, &Edge::fPrevEdgeAbove, &Edge::fNextEdgeAbove>(
ethannicholase9709e82016-01-07 13:34:16 -0800753 edge, &edge->fBottom->fFirstEdgeAbove, &edge->fBottom->fLastEdgeAbove);
754}
755
756void remove_edge_below(Edge* edge) {
757 LOG("removing edge (%g -> %g) below vertex %g\n", edge->fTop->fID, edge->fBottom->fID,
758 edge->fTop->fID);
senorblancoe6eaa322016-03-08 09:06:44 -0800759 list_remove<Edge, &Edge::fPrevEdgeBelow, &Edge::fNextEdgeBelow>(
ethannicholase9709e82016-01-07 13:34:16 -0800760 edge, &edge->fTop->fFirstEdgeBelow, &edge->fTop->fLastEdgeBelow);
761}
762
763void erase_edge_if_zero_winding(Edge* edge, EdgeList* edges) {
764 if (edge->fWinding != 0) {
765 return;
766 }
767 LOG("erasing edge (%g -> %g)\n", edge->fTop->fID, edge->fBottom->fID);
768 remove_edge_above(edge);
769 remove_edge_below(edge);
770 if (edge->isActive(edges)) {
771 remove_edge(edge, edges);
772 }
773}
774
775void merge_collinear_edges(Edge* edge, EdgeList* activeEdges, Comparator& c);
776
777void set_top(Edge* edge, Vertex* v, EdgeList* activeEdges, Comparator& c) {
778 remove_edge_below(edge);
779 edge->fTop = v;
780 edge->recompute();
781 insert_edge_below(edge, v, c);
782 fix_active_state(edge, activeEdges, c);
783 merge_collinear_edges(edge, activeEdges, c);
784}
785
786void set_bottom(Edge* edge, Vertex* v, EdgeList* activeEdges, Comparator& c) {
787 remove_edge_above(edge);
788 edge->fBottom = v;
789 edge->recompute();
790 insert_edge_above(edge, v, c);
791 fix_active_state(edge, activeEdges, c);
792 merge_collinear_edges(edge, activeEdges, c);
793}
794
795void merge_edges_above(Edge* edge, Edge* other, EdgeList* activeEdges, Comparator& c) {
796 if (coincident(edge->fTop->fPoint, other->fTop->fPoint)) {
797 LOG("merging coincident above edges (%g, %g) -> (%g, %g)\n",
798 edge->fTop->fPoint.fX, edge->fTop->fPoint.fY,
799 edge->fBottom->fPoint.fX, edge->fBottom->fPoint.fY);
800 other->fWinding += edge->fWinding;
801 erase_edge_if_zero_winding(other, activeEdges);
802 edge->fWinding = 0;
803 erase_edge_if_zero_winding(edge, activeEdges);
804 } else if (c.sweep_lt(edge->fTop->fPoint, other->fTop->fPoint)) {
805 other->fWinding += edge->fWinding;
806 erase_edge_if_zero_winding(other, activeEdges);
807 set_bottom(edge, other->fTop, activeEdges, c);
808 } else {
809 edge->fWinding += other->fWinding;
810 erase_edge_if_zero_winding(edge, activeEdges);
811 set_bottom(other, edge->fTop, activeEdges, c);
812 }
813}
814
815void merge_edges_below(Edge* edge, Edge* other, EdgeList* activeEdges, Comparator& c) {
816 if (coincident(edge->fBottom->fPoint, other->fBottom->fPoint)) {
817 LOG("merging coincident below edges (%g, %g) -> (%g, %g)\n",
818 edge->fTop->fPoint.fX, edge->fTop->fPoint.fY,
819 edge->fBottom->fPoint.fX, edge->fBottom->fPoint.fY);
820 other->fWinding += edge->fWinding;
821 erase_edge_if_zero_winding(other, activeEdges);
822 edge->fWinding = 0;
823 erase_edge_if_zero_winding(edge, activeEdges);
824 } else if (c.sweep_lt(edge->fBottom->fPoint, other->fBottom->fPoint)) {
825 edge->fWinding += other->fWinding;
826 erase_edge_if_zero_winding(edge, activeEdges);
827 set_top(other, edge->fBottom, activeEdges, c);
828 } else {
829 other->fWinding += edge->fWinding;
830 erase_edge_if_zero_winding(other, activeEdges);
831 set_top(edge, other->fBottom, activeEdges, c);
832 }
833}
834
835void merge_collinear_edges(Edge* edge, EdgeList* activeEdges, Comparator& c) {
836 if (edge->fPrevEdgeAbove && (edge->fTop == edge->fPrevEdgeAbove->fTop ||
837 !edge->fPrevEdgeAbove->isLeftOf(edge->fTop))) {
838 merge_edges_above(edge, edge->fPrevEdgeAbove, activeEdges, c);
839 } else if (edge->fNextEdgeAbove && (edge->fTop == edge->fNextEdgeAbove->fTop ||
840 !edge->isLeftOf(edge->fNextEdgeAbove->fTop))) {
841 merge_edges_above(edge, edge->fNextEdgeAbove, activeEdges, c);
842 }
843 if (edge->fPrevEdgeBelow && (edge->fBottom == edge->fPrevEdgeBelow->fBottom ||
844 !edge->fPrevEdgeBelow->isLeftOf(edge->fBottom))) {
845 merge_edges_below(edge, edge->fPrevEdgeBelow, activeEdges, c);
846 } else if (edge->fNextEdgeBelow && (edge->fBottom == edge->fNextEdgeBelow->fBottom ||
847 !edge->isLeftOf(edge->fNextEdgeBelow->fBottom))) {
848 merge_edges_below(edge, edge->fNextEdgeBelow, activeEdges, c);
849 }
850}
851
852void split_edge(Edge* edge, Vertex* v, EdgeList* activeEdges, Comparator& c, SkChunkAlloc& alloc);
853
854void cleanup_active_edges(Edge* edge, EdgeList* activeEdges, Comparator& c, SkChunkAlloc& alloc) {
855 Vertex* top = edge->fTop;
856 Vertex* bottom = edge->fBottom;
857 if (edge->fLeft) {
858 Vertex* leftTop = edge->fLeft->fTop;
859 Vertex* leftBottom = edge->fLeft->fBottom;
860 if (c.sweep_gt(top->fPoint, leftTop->fPoint) && !edge->fLeft->isLeftOf(top)) {
861 split_edge(edge->fLeft, edge->fTop, activeEdges, c, alloc);
862 } else if (c.sweep_gt(leftTop->fPoint, top->fPoint) && !edge->isRightOf(leftTop)) {
863 split_edge(edge, leftTop, activeEdges, c, alloc);
864 } else if (c.sweep_lt(bottom->fPoint, leftBottom->fPoint) &&
865 !edge->fLeft->isLeftOf(bottom)) {
866 split_edge(edge->fLeft, bottom, activeEdges, c, alloc);
867 } else if (c.sweep_lt(leftBottom->fPoint, bottom->fPoint) && !edge->isRightOf(leftBottom)) {
868 split_edge(edge, leftBottom, activeEdges, c, alloc);
869 }
870 }
871 if (edge->fRight) {
872 Vertex* rightTop = edge->fRight->fTop;
873 Vertex* rightBottom = edge->fRight->fBottom;
874 if (c.sweep_gt(top->fPoint, rightTop->fPoint) && !edge->fRight->isRightOf(top)) {
875 split_edge(edge->fRight, top, activeEdges, c, alloc);
876 } else if (c.sweep_gt(rightTop->fPoint, top->fPoint) && !edge->isLeftOf(rightTop)) {
877 split_edge(edge, rightTop, activeEdges, c, alloc);
878 } else if (c.sweep_lt(bottom->fPoint, rightBottom->fPoint) &&
879 !edge->fRight->isRightOf(bottom)) {
880 split_edge(edge->fRight, bottom, activeEdges, c, alloc);
881 } else if (c.sweep_lt(rightBottom->fPoint, bottom->fPoint) &&
882 !edge->isLeftOf(rightBottom)) {
883 split_edge(edge, rightBottom, activeEdges, c, alloc);
884 }
885 }
886}
887
888void split_edge(Edge* edge, Vertex* v, EdgeList* activeEdges, Comparator& c, SkChunkAlloc& alloc) {
889 LOG("splitting edge (%g -> %g) at vertex %g (%g, %g)\n",
890 edge->fTop->fID, edge->fBottom->fID,
891 v->fID, v->fPoint.fX, v->fPoint.fY);
892 if (c.sweep_lt(v->fPoint, edge->fTop->fPoint)) {
893 set_top(edge, v, activeEdges, c);
894 } else if (c.sweep_gt(v->fPoint, edge->fBottom->fPoint)) {
895 set_bottom(edge, v, activeEdges, c);
896 } else {
897 Edge* newEdge = ALLOC_NEW(Edge, (v, edge->fBottom, edge->fWinding), alloc);
898 insert_edge_below(newEdge, v, c);
899 insert_edge_above(newEdge, edge->fBottom, c);
900 set_bottom(edge, v, activeEdges, c);
901 cleanup_active_edges(edge, activeEdges, c, alloc);
902 fix_active_state(newEdge, activeEdges, c);
903 merge_collinear_edges(newEdge, activeEdges, c);
904 }
905}
906
907void merge_vertices(Vertex* src, Vertex* dst, Vertex** head, Comparator& c, SkChunkAlloc& alloc) {
908 LOG("found coincident verts at %g, %g; merging %g into %g\n", src->fPoint.fX, src->fPoint.fY,
909 src->fID, dst->fID);
910 for (Edge* edge = src->fFirstEdgeAbove; edge;) {
911 Edge* next = edge->fNextEdgeAbove;
912 set_bottom(edge, dst, nullptr, c);
913 edge = next;
914 }
915 for (Edge* edge = src->fFirstEdgeBelow; edge;) {
916 Edge* next = edge->fNextEdgeBelow;
917 set_top(edge, dst, nullptr, c);
918 edge = next;
919 }
senorblancoe6eaa322016-03-08 09:06:44 -0800920 list_remove<Vertex, &Vertex::fPrev, &Vertex::fNext>(src, head, nullptr);
ethannicholase9709e82016-01-07 13:34:16 -0800921}
922
923Vertex* check_for_intersection(Edge* edge, Edge* other, EdgeList* activeEdges, Comparator& c,
924 SkChunkAlloc& alloc) {
925 SkPoint p;
926 if (!edge || !other) {
927 return nullptr;
928 }
929 if (edge->intersect(*other, &p)) {
930 Vertex* v;
931 LOG("found intersection, pt is %g, %g\n", p.fX, p.fY);
932 if (p == edge->fTop->fPoint || c.sweep_lt(p, edge->fTop->fPoint)) {
933 split_edge(other, edge->fTop, activeEdges, c, alloc);
934 v = edge->fTop;
935 } else if (p == edge->fBottom->fPoint || c.sweep_gt(p, edge->fBottom->fPoint)) {
936 split_edge(other, edge->fBottom, activeEdges, c, alloc);
937 v = edge->fBottom;
938 } else if (p == other->fTop->fPoint || c.sweep_lt(p, other->fTop->fPoint)) {
939 split_edge(edge, other->fTop, activeEdges, c, alloc);
940 v = other->fTop;
941 } else if (p == other->fBottom->fPoint || c.sweep_gt(p, other->fBottom->fPoint)) {
942 split_edge(edge, other->fBottom, activeEdges, c, alloc);
943 v = other->fBottom;
944 } else {
945 Vertex* nextV = edge->fTop;
946 while (c.sweep_lt(p, nextV->fPoint)) {
947 nextV = nextV->fPrev;
948 }
949 while (c.sweep_lt(nextV->fPoint, p)) {
950 nextV = nextV->fNext;
951 }
952 Vertex* prevV = nextV->fPrev;
953 if (coincident(prevV->fPoint, p)) {
954 v = prevV;
955 } else if (coincident(nextV->fPoint, p)) {
956 v = nextV;
957 } else {
958 v = ALLOC_NEW(Vertex, (p), alloc);
959 LOG("inserting between %g (%g, %g) and %g (%g, %g)\n",
960 prevV->fID, prevV->fPoint.fX, prevV->fPoint.fY,
961 nextV->fID, nextV->fPoint.fX, nextV->fPoint.fY);
962#if LOGGING_ENABLED
963 v->fID = (nextV->fID + prevV->fID) * 0.5f;
964#endif
965 v->fPrev = prevV;
966 v->fNext = nextV;
967 prevV->fNext = v;
968 nextV->fPrev = v;
969 }
970 split_edge(edge, v, activeEdges, c, alloc);
971 split_edge(other, v, activeEdges, c, alloc);
972 }
973 return v;
974 }
975 return nullptr;
976}
977
978void sanitize_contours(Vertex** contours, int contourCnt) {
979 for (int i = 0; i < contourCnt; ++i) {
980 SkASSERT(contours[i]);
981 for (Vertex* v = contours[i];;) {
982 if (coincident(v->fPrev->fPoint, v->fPoint)) {
983 LOG("vertex %g,%g coincident; removing\n", v->fPoint.fX, v->fPoint.fY);
984 if (v->fPrev == v) {
985 contours[i] = nullptr;
986 break;
987 }
988 v->fPrev->fNext = v->fNext;
989 v->fNext->fPrev = v->fPrev;
990 if (contours[i] == v) {
991 contours[i] = v->fNext;
992 }
993 v = v->fPrev;
994 } else {
995 v = v->fNext;
996 if (v == contours[i]) break;
997 }
998 }
999 }
1000}
1001
1002void merge_coincident_vertices(Vertex** vertices, Comparator& c, SkChunkAlloc& alloc) {
1003 for (Vertex* v = (*vertices)->fNext; v != nullptr; v = v->fNext) {
1004 if (c.sweep_lt(v->fPoint, v->fPrev->fPoint)) {
1005 v->fPoint = v->fPrev->fPoint;
1006 }
1007 if (coincident(v->fPrev->fPoint, v->fPoint)) {
1008 merge_vertices(v->fPrev, v, vertices, c, alloc);
1009 }
1010 }
1011}
1012
1013// Stage 2: convert the contours to a mesh of edges connecting the vertices.
1014
1015Vertex* build_edges(Vertex** contours, int contourCnt, Comparator& c, SkChunkAlloc& alloc) {
1016 Vertex* vertices = nullptr;
1017 Vertex* prev = nullptr;
1018 for (int i = 0; i < contourCnt; ++i) {
1019 for (Vertex* v = contours[i]; v != nullptr;) {
1020 Vertex* vNext = v->fNext;
1021 Edge* edge = new_edge(v->fPrev, v, alloc, c);
1022 if (edge->fWinding > 0) {
1023 insert_edge_below(edge, v->fPrev, c);
1024 insert_edge_above(edge, v, c);
1025 } else {
1026 insert_edge_below(edge, v, c);
1027 insert_edge_above(edge, v->fPrev, c);
1028 }
1029 merge_collinear_edges(edge, nullptr, c);
1030 if (prev) {
1031 prev->fNext = v;
1032 v->fPrev = prev;
1033 } else {
1034 vertices = v;
1035 }
1036 prev = v;
1037 v = vNext;
1038 if (v == contours[i]) break;
1039 }
1040 }
1041 if (prev) {
1042 prev->fNext = vertices->fPrev = nullptr;
1043 }
1044 return vertices;
1045}
1046
1047// Stage 3: sort the vertices by increasing sweep direction.
1048
1049Vertex* sorted_merge(Vertex* a, Vertex* b, Comparator& c);
1050
1051void front_back_split(Vertex* v, Vertex** pFront, Vertex** pBack) {
1052 Vertex* fast;
1053 Vertex* slow;
1054 if (!v || !v->fNext) {
1055 *pFront = v;
1056 *pBack = nullptr;
1057 } else {
1058 slow = v;
1059 fast = v->fNext;
1060
1061 while (fast != nullptr) {
1062 fast = fast->fNext;
1063 if (fast != nullptr) {
1064 slow = slow->fNext;
1065 fast = fast->fNext;
1066 }
1067 }
1068
1069 *pFront = v;
1070 *pBack = slow->fNext;
1071 slow->fNext->fPrev = nullptr;
1072 slow->fNext = nullptr;
1073 }
1074}
1075
1076void merge_sort(Vertex** head, Comparator& c) {
1077 if (!*head || !(*head)->fNext) {
1078 return;
1079 }
1080
1081 Vertex* a;
1082 Vertex* b;
1083 front_back_split(*head, &a, &b);
1084
1085 merge_sort(&a, c);
1086 merge_sort(&b, c);
1087
1088 *head = sorted_merge(a, b, c);
1089}
1090
ethannicholase9709e82016-01-07 13:34:16 -08001091Vertex* sorted_merge(Vertex* a, Vertex* b, Comparator& c) {
senorblancoe6eaa322016-03-08 09:06:44 -08001092 VertexList vertices;
ethannicholase9709e82016-01-07 13:34:16 -08001093
1094 while (a && b) {
1095 if (c.sweep_lt(a->fPoint, b->fPoint)) {
1096 Vertex* next = a->fNext;
senorblancoe6eaa322016-03-08 09:06:44 -08001097 vertices.append(a);
ethannicholase9709e82016-01-07 13:34:16 -08001098 a = next;
1099 } else {
1100 Vertex* next = b->fNext;
senorblancoe6eaa322016-03-08 09:06:44 -08001101 vertices.append(b);
ethannicholase9709e82016-01-07 13:34:16 -08001102 b = next;
1103 }
1104 }
1105 if (a) {
senorblancoe6eaa322016-03-08 09:06:44 -08001106 vertices.insert(a, vertices.fTail, a->fNext);
ethannicholase9709e82016-01-07 13:34:16 -08001107 }
1108 if (b) {
senorblancoe6eaa322016-03-08 09:06:44 -08001109 vertices.insert(b, vertices.fTail, b->fNext);
ethannicholase9709e82016-01-07 13:34:16 -08001110 }
senorblancoe6eaa322016-03-08 09:06:44 -08001111 return vertices.fHead;
ethannicholase9709e82016-01-07 13:34:16 -08001112}
1113
1114// Stage 4: Simplify the mesh by inserting new vertices at intersecting edges.
1115
1116void simplify(Vertex* vertices, Comparator& c, SkChunkAlloc& alloc) {
1117 LOG("simplifying complex polygons\n");
1118 EdgeList activeEdges;
1119 for (Vertex* v = vertices; v != nullptr; v = v->fNext) {
1120 if (!v->fFirstEdgeAbove && !v->fFirstEdgeBelow) {
1121 continue;
1122 }
1123#if LOGGING_ENABLED
1124 LOG("\nvertex %g: (%g,%g)\n", v->fID, v->fPoint.fX, v->fPoint.fY);
1125#endif
1126 Edge* leftEnclosingEdge = nullptr;
1127 Edge* rightEnclosingEdge = nullptr;
1128 bool restartChecks;
1129 do {
1130 restartChecks = false;
1131 find_enclosing_edges(v, &activeEdges, &leftEnclosingEdge, &rightEnclosingEdge);
1132 if (v->fFirstEdgeBelow) {
1133 for (Edge* edge = v->fFirstEdgeBelow; edge != nullptr; edge = edge->fNextEdgeBelow) {
1134 if (check_for_intersection(edge, leftEnclosingEdge, &activeEdges, c, alloc)) {
1135 restartChecks = true;
1136 break;
1137 }
1138 if (check_for_intersection(edge, rightEnclosingEdge, &activeEdges, c, alloc)) {
1139 restartChecks = true;
1140 break;
1141 }
1142 }
1143 } else {
1144 if (Vertex* pv = check_for_intersection(leftEnclosingEdge, rightEnclosingEdge,
1145 &activeEdges, c, alloc)) {
1146 if (c.sweep_lt(pv->fPoint, v->fPoint)) {
1147 v = pv;
1148 }
1149 restartChecks = true;
1150 }
1151
1152 }
1153 } while (restartChecks);
1154 for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove) {
1155 remove_edge(e, &activeEdges);
1156 }
1157 Edge* leftEdge = leftEnclosingEdge;
1158 for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
1159 insert_edge(e, leftEdge, &activeEdges);
1160 leftEdge = e;
1161 }
1162 v->fProcessed = true;
1163 }
1164}
1165
1166// Stage 5: Tessellate the simplified mesh into monotone polygons.
1167
1168Poly* tessellate(Vertex* vertices, SkChunkAlloc& alloc) {
1169 LOG("tessellating simple polygons\n");
1170 EdgeList activeEdges;
1171 Poly* polys = nullptr;
1172 for (Vertex* v = vertices; v != nullptr; v = v->fNext) {
1173 if (!v->fFirstEdgeAbove && !v->fFirstEdgeBelow) {
1174 continue;
1175 }
1176#if LOGGING_ENABLED
1177 LOG("\nvertex %g: (%g,%g)\n", v->fID, v->fPoint.fX, v->fPoint.fY);
1178#endif
1179 Edge* leftEnclosingEdge = nullptr;
1180 Edge* rightEnclosingEdge = nullptr;
1181 find_enclosing_edges(v, &activeEdges, &leftEnclosingEdge, &rightEnclosingEdge);
1182 Poly* leftPoly = nullptr;
1183 Poly* rightPoly = nullptr;
1184 if (v->fFirstEdgeAbove) {
1185 leftPoly = v->fFirstEdgeAbove->fLeftPoly;
1186 rightPoly = v->fLastEdgeAbove->fRightPoly;
1187 } else {
1188 leftPoly = leftEnclosingEdge ? leftEnclosingEdge->fRightPoly : nullptr;
1189 rightPoly = rightEnclosingEdge ? rightEnclosingEdge->fLeftPoly : nullptr;
1190 }
1191#if LOGGING_ENABLED
1192 LOG("edges above:\n");
1193 for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove) {
1194 LOG("%g -> %g, lpoly %d, rpoly %d\n", e->fTop->fID, e->fBottom->fID,
1195 e->fLeftPoly ? e->fLeftPoly->fID : -1, e->fRightPoly ? e->fRightPoly->fID : -1);
1196 }
1197 LOG("edges below:\n");
1198 for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
1199 LOG("%g -> %g, lpoly %d, rpoly %d\n", e->fTop->fID, e->fBottom->fID,
1200 e->fLeftPoly ? e->fLeftPoly->fID : -1, e->fRightPoly ? e->fRightPoly->fID : -1);
1201 }
1202#endif
1203 if (v->fFirstEdgeAbove) {
1204 if (leftPoly) {
1205 leftPoly = leftPoly->addVertex(v, Poly::kRight_Side, alloc);
1206 }
1207 if (rightPoly) {
1208 rightPoly = rightPoly->addVertex(v, Poly::kLeft_Side, alloc);
1209 }
1210 for (Edge* e = v->fFirstEdgeAbove; e != v->fLastEdgeAbove; e = e->fNextEdgeAbove) {
1211 Edge* leftEdge = e;
1212 Edge* rightEdge = e->fNextEdgeAbove;
1213 SkASSERT(rightEdge->isRightOf(leftEdge->fTop));
1214 remove_edge(leftEdge, &activeEdges);
1215 if (leftEdge->fRightPoly) {
1216 leftEdge->fRightPoly->end(v, alloc);
1217 }
1218 if (rightEdge->fLeftPoly && rightEdge->fLeftPoly != leftEdge->fRightPoly) {
1219 rightEdge->fLeftPoly->end(v, alloc);
1220 }
1221 }
1222 remove_edge(v->fLastEdgeAbove, &activeEdges);
1223 if (!v->fFirstEdgeBelow) {
1224 if (leftPoly && rightPoly && leftPoly != rightPoly) {
1225 SkASSERT(leftPoly->fPartner == nullptr && rightPoly->fPartner == nullptr);
1226 rightPoly->fPartner = leftPoly;
1227 leftPoly->fPartner = rightPoly;
1228 }
1229 }
1230 }
1231 if (v->fFirstEdgeBelow) {
1232 if (!v->fFirstEdgeAbove) {
1233 if (leftPoly && leftPoly == rightPoly) {
1234 // Split the poly.
1235 if (leftPoly->fActive->fSide == Poly::kLeft_Side) {
1236 leftPoly = new_poly(&polys, leftEnclosingEdge->fTop, leftPoly->fWinding,
1237 alloc);
1238 leftPoly->addVertex(v, Poly::kRight_Side, alloc);
1239 rightPoly->addVertex(v, Poly::kLeft_Side, alloc);
1240 leftEnclosingEdge->fRightPoly = leftPoly;
1241 } else {
1242 rightPoly = new_poly(&polys, rightEnclosingEdge->fTop, rightPoly->fWinding,
1243 alloc);
1244 rightPoly->addVertex(v, Poly::kLeft_Side, alloc);
1245 leftPoly->addVertex(v, Poly::kRight_Side, alloc);
1246 rightEnclosingEdge->fLeftPoly = rightPoly;
1247 }
1248 } else {
1249 if (leftPoly) {
1250 leftPoly = leftPoly->addVertex(v, Poly::kRight_Side, alloc);
1251 }
1252 if (rightPoly) {
1253 rightPoly = rightPoly->addVertex(v, Poly::kLeft_Side, alloc);
1254 }
1255 }
1256 }
1257 Edge* leftEdge = v->fFirstEdgeBelow;
1258 leftEdge->fLeftPoly = leftPoly;
1259 insert_edge(leftEdge, leftEnclosingEdge, &activeEdges);
1260 for (Edge* rightEdge = leftEdge->fNextEdgeBelow; rightEdge;
1261 rightEdge = rightEdge->fNextEdgeBelow) {
1262 insert_edge(rightEdge, leftEdge, &activeEdges);
1263 int winding = leftEdge->fLeftPoly ? leftEdge->fLeftPoly->fWinding : 0;
1264 winding += leftEdge->fWinding;
1265 if (winding != 0) {
1266 Poly* poly = new_poly(&polys, v, winding, alloc);
1267 leftEdge->fRightPoly = rightEdge->fLeftPoly = poly;
1268 }
1269 leftEdge = rightEdge;
1270 }
1271 v->fLastEdgeBelow->fRightPoly = rightPoly;
1272 }
1273#if LOGGING_ENABLED
1274 LOG("\nactive edges:\n");
1275 for (Edge* e = activeEdges.fHead; e != nullptr; e = e->fRight) {
1276 LOG("%g -> %g, lpoly %d, rpoly %d\n", e->fTop->fID, e->fBottom->fID,
1277 e->fLeftPoly ? e->fLeftPoly->fID : -1, e->fRightPoly ? e->fRightPoly->fID : -1);
1278 }
1279#endif
1280 }
1281 return polys;
1282}
1283
1284// This is a driver function which calls stages 2-5 in turn.
1285
1286Poly* contours_to_polys(Vertex** contours, int contourCnt, const SkRect& pathBounds,
1287 SkChunkAlloc& alloc) {
1288 Comparator c;
1289 if (pathBounds.width() > pathBounds.height()) {
1290 c.sweep_lt = sweep_lt_horiz;
1291 c.sweep_gt = sweep_gt_horiz;
1292 } else {
1293 c.sweep_lt = sweep_lt_vert;
1294 c.sweep_gt = sweep_gt_vert;
1295 }
1296#if LOGGING_ENABLED
1297 for (int i = 0; i < contourCnt; ++i) {
1298 Vertex* v = contours[i];
1299 SkASSERT(v);
1300 LOG("path.moveTo(%20.20g, %20.20g);\n", v->fPoint.fX, v->fPoint.fY);
1301 for (v = v->fNext; v != contours[i]; v = v->fNext) {
1302 LOG("path.lineTo(%20.20g, %20.20g);\n", v->fPoint.fX, v->fPoint.fY);
1303 }
1304 }
1305#endif
1306 sanitize_contours(contours, contourCnt);
1307 Vertex* vertices = build_edges(contours, contourCnt, c, alloc);
1308 if (!vertices) {
1309 return nullptr;
1310 }
1311
1312 // Sort vertices in Y (secondarily in X).
1313 merge_sort(&vertices, c);
1314 merge_coincident_vertices(&vertices, c, alloc);
1315#if LOGGING_ENABLED
1316 for (Vertex* v = vertices; v != nullptr; v = v->fNext) {
1317 static float gID = 0.0f;
1318 v->fID = gID++;
1319 }
1320#endif
1321 simplify(vertices, c, alloc);
1322 return tessellate(vertices, alloc);
1323}
1324
1325Poly* path_to_polys(const SkPath& path, SkScalar tolerance, const SkRect& clipBounds,
1326 int contourCnt, SkChunkAlloc& alloc, bool* isLinear) {
1327 SkPath::FillType fillType = path.getFillType();
1328 if (SkPath::IsInverseFillType(fillType)) {
1329 contourCnt++;
1330 }
1331 SkAutoTDeleteArray<Vertex*> contours(new Vertex* [contourCnt]);
1332
1333 path_to_contours(path, tolerance, clipBounds, contours.get(), alloc, isLinear);
1334 return contours_to_polys(contours.get(), contourCnt, path.getBounds(), alloc);
1335}
1336
1337void get_contour_count_and_size_estimate(const SkPath& path, SkScalar tolerance, int* contourCnt,
1338 int* sizeEstimate) {
1339 int maxPts = GrPathUtils::worstCasePointCount(path, contourCnt, tolerance);
1340 if (maxPts <= 0) {
1341 *contourCnt = 0;
1342 return;
1343 }
1344 if (maxPts > ((int)SK_MaxU16 + 1)) {
1345 SkDebugf("Path not rendered, too many verts (%d)\n", maxPts);
1346 *contourCnt = 0;
1347 return;
1348 }
1349 // For the initial size of the chunk allocator, estimate based on the point count:
1350 // one vertex per point for the initial passes, plus two for the vertices in the
1351 // resulting Polys, since the same point may end up in two Polys. Assume minimal
1352 // connectivity of one Edge per Vertex (will grow for intersections).
1353 *sizeEstimate = maxPts * (3 * sizeof(Vertex) + sizeof(Edge));
1354}
1355
1356int count_points(Poly* polys, SkPath::FillType fillType) {
1357 int count = 0;
1358 for (Poly* poly = polys; poly; poly = poly->fNext) {
1359 if (apply_fill_type(fillType, poly->fWinding) && poly->fCount >= 3) {
1360 count += (poly->fCount - 2) * (TESSELLATOR_WIREFRAME ? 6 : 3);
1361 }
1362 }
1363 return count;
1364}
1365
1366} // namespace
1367
1368namespace GrTessellator {
1369
1370// Stage 6: Triangulate the monotone polygons into a vertex buffer.
1371
1372int PathToTriangles(const SkPath& path, SkScalar tolerance, const SkRect& clipBounds,
1373 GrResourceProvider* resourceProvider,
1374 SkAutoTUnref<GrVertexBuffer>& vertexBuffer, bool canMapVB, bool* isLinear) {
1375 int contourCnt;
1376 int sizeEstimate;
1377 get_contour_count_and_size_estimate(path, tolerance, &contourCnt, &sizeEstimate);
1378 if (contourCnt <= 0) {
1379 *isLinear = true;
1380 return 0;
1381 }
1382 SkChunkAlloc alloc(sizeEstimate);
1383 Poly* polys = path_to_polys(path, tolerance, clipBounds, contourCnt, alloc, isLinear);
1384 SkPath::FillType fillType = path.getFillType();
1385 int count = count_points(polys, fillType);
1386 if (0 == count) {
1387 return 0;
1388 }
1389
1390 size_t size = count * sizeof(SkPoint);
1391 if (!vertexBuffer.get() || vertexBuffer->gpuMemorySize() < size) {
1392 vertexBuffer.reset(resourceProvider->createVertexBuffer(
1393 size, GrResourceProvider::kStatic_BufferUsage, 0));
1394 }
1395 if (!vertexBuffer.get()) {
1396 SkDebugf("Could not allocate vertices\n");
1397 return 0;
1398 }
1399 SkPoint* verts;
1400 if (canMapVB) {
1401 verts = static_cast<SkPoint*>(vertexBuffer->map());
1402 } else {
1403 verts = new SkPoint[count];
1404 }
1405 SkPoint* end = verts;
1406 for (Poly* poly = polys; poly; poly = poly->fNext) {
1407 if (apply_fill_type(fillType, poly->fWinding)) {
1408 end = poly->emit(end);
1409 }
1410 }
1411 int actualCount = static_cast<int>(end - verts);
1412 LOG("actual count: %d\n", actualCount);
1413 SkASSERT(actualCount <= count);
1414 if (canMapVB) {
1415 vertexBuffer->unmap();
1416 } else {
1417 vertexBuffer->updateData(verts, actualCount * sizeof(SkPoint));
1418 delete[] verts;
1419 }
1420
1421 return actualCount;
1422}
1423
1424int PathToVertices(const SkPath& path, SkScalar tolerance, const SkRect& clipBounds,
1425 GrTessellator::WindingVertex** verts) {
1426 int contourCnt;
1427 int sizeEstimate;
1428 get_contour_count_and_size_estimate(path, tolerance, &contourCnt, &sizeEstimate);
1429 if (contourCnt <= 0) {
1430 return 0;
1431 }
1432 SkChunkAlloc alloc(sizeEstimate);
1433 bool isLinear;
1434 Poly* polys = path_to_polys(path, tolerance, clipBounds, contourCnt, alloc, &isLinear);
1435 SkPath::FillType fillType = path.getFillType();
1436 int count = count_points(polys, fillType);
1437 if (0 == count) {
1438 *verts = nullptr;
1439 return 0;
1440 }
1441
1442 *verts = new GrTessellator::WindingVertex[count];
1443 GrTessellator::WindingVertex* vertsEnd = *verts;
1444 SkPoint* points = new SkPoint[count];
1445 SkPoint* pointsEnd = points;
1446 for (Poly* poly = polys; poly; poly = poly->fNext) {
1447 if (apply_fill_type(fillType, poly->fWinding)) {
1448 SkPoint* start = pointsEnd;
1449 pointsEnd = poly->emit(pointsEnd);
1450 while (start != pointsEnd) {
1451 vertsEnd->fPos = *start;
1452 vertsEnd->fWinding = poly->fWinding;
1453 ++start;
1454 ++vertsEnd;
1455 }
1456 }
1457 }
1458 int actualCount = static_cast<int>(vertsEnd - *verts);
1459 SkASSERT(actualCount <= count);
1460 SkASSERT(pointsEnd - points == actualCount);
1461 delete[] points;
1462 return actualCount;
1463}
1464
1465} // namespace