blob: a1080dcb6852de1343d43fad894017da37f37316 [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
Chris Dalton17dc4182020-03-25 16:18:16 -06008#include "src/gpu/GrTriangulator.h"
ethannicholase9709e82016-01-07 13:34:16 -08009
Chris Daltond081dce2020-01-23 12:09:04 -070010#include "src/gpu/GrEagerVertexAllocator.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "src/gpu/GrVertexWriter.h"
Michael Ludwig663afe52019-06-03 16:46:19 -040012#include "src/gpu/geometry/GrPathUtils.h"
Chris Daltond60c9192021-01-07 18:30:08 +000013
14#include "src/core/SkGeometry.h"
15#include "src/core/SkPointPriv.h"
16
Stephen White94b7e542018-01-04 14:01:10 -050017#include <algorithm>
Ben Wagnerf08d1d02018-06-18 15:11:00 -040018#include <cstdio>
Stephen Whitec4dbc372019-05-22 10:50:14 -040019#include <queue>
20#include <unordered_map>
Ben Wagnerf08d1d02018-06-18 15:11:00 -040021#include <utility>
ethannicholase9709e82016-01-07 13:34:16 -080022
Chris Daltond60c9192021-01-07 18:30:08 +000023
Chris Dalton5045de32021-01-07 19:09:01 -070024#if TRIANGULATOR_LOGGING
Chris Daltond60c9192021-01-07 18:30:08 +000025#define TESS_LOG printf
Chris Dalton24472af2021-01-11 20:05:00 -070026#define DUMP_MESH(M) (M).dump()
ethannicholase9709e82016-01-07 13:34:16 -080027#else
Brian Salomon120e7d62019-09-11 10:29:22 -040028#define TESS_LOG(...)
Chris Dalton7cf3add2021-01-11 18:33:28 -070029#define DUMP_MESH(M)
ethannicholase9709e82016-01-07 13:34:16 -080030#endif
31
Chris Dalton57ea1fc2021-01-05 13:37:44 -070032constexpr static float kCosMiterAngle = 0.97f; // Corresponds to an angle of ~14 degrees.
ethannicholase9709e82016-01-07 13:34:16 -080033
Chris Dalton17ce8c52021-01-07 18:08:46 -070034using EdgeType = GrTriangulator::EdgeType;
Chris Dalton57ea1fc2021-01-05 13:37:44 -070035using Vertex = GrTriangulator::Vertex;
36using VertexList = GrTriangulator::VertexList;
Chris Dalton17ce8c52021-01-07 18:08:46 -070037using Line = GrTriangulator::Line;
Chris Dalton57ea1fc2021-01-05 13:37:44 -070038using Edge = GrTriangulator::Edge;
39using EdgeList = GrTriangulator::EdgeList;
40using Poly = GrTriangulator::Poly;
Chris Dalton17ce8c52021-01-07 18:08:46 -070041using MonotonePoly = GrTriangulator::MonotonePoly;
Chris Dalton57ea1fc2021-01-05 13:37:44 -070042using Comparator = GrTriangulator::Comparator;
Chris Dalton7cf3add2021-01-11 18:33:28 -070043using SSEdge = GrAATriangulator::SSEdge;
44using EventList = GrAATriangulator::EventList;
45using Event = GrAATriangulator::Event;
46using EventComparator = GrAATriangulator::EventComparator;
ethannicholase9709e82016-01-07 13:34:16 -080047
48template <class T, T* T::*Prev, T* T::*Next>
Chris Dalton57ea1fc2021-01-05 13:37:44 -070049static void list_insert(T* t, T* prev, T* next, T** head, T** tail) {
ethannicholase9709e82016-01-07 13:34:16 -080050 t->*Prev = prev;
51 t->*Next = next;
52 if (prev) {
53 prev->*Next = t;
54 } else if (head) {
55 *head = t;
56 }
57 if (next) {
58 next->*Prev = t;
59 } else if (tail) {
60 *tail = t;
61 }
62}
63
64template <class T, T* T::*Prev, T* T::*Next>
Chris Dalton57ea1fc2021-01-05 13:37:44 -070065static void list_remove(T* t, T** head, T** tail) {
ethannicholase9709e82016-01-07 13:34:16 -080066 if (t->*Prev) {
67 t->*Prev->*Next = t->*Next;
68 } else if (head) {
69 *head = t->*Next;
70 }
71 if (t->*Next) {
72 t->*Next->*Prev = t->*Prev;
73 } else if (tail) {
74 *tail = t->*Prev;
75 }
76 t->*Prev = t->*Next = nullptr;
77}
78
ethannicholase9709e82016-01-07 13:34:16 -080079typedef bool (*CompareFunc)(const SkPoint& a, const SkPoint& b);
80
Chris Dalton57ea1fc2021-01-05 13:37:44 -070081static bool sweep_lt_horiz(const SkPoint& a, const SkPoint& b) {
Stephen White16a40cb2017-02-23 11:10:01 -050082 return a.fX < b.fX || (a.fX == b.fX && a.fY > b.fY);
ethannicholase9709e82016-01-07 13:34:16 -080083}
84
Chris Dalton57ea1fc2021-01-05 13:37:44 -070085static bool sweep_lt_vert(const SkPoint& a, const SkPoint& b) {
Stephen White16a40cb2017-02-23 11:10:01 -050086 return a.fY < b.fY || (a.fY == b.fY && a.fX < b.fX);
ethannicholase9709e82016-01-07 13:34:16 -080087}
88
Chris Dalton5045de32021-01-07 19:09:01 -070089bool GrTriangulator::Comparator::sweep_lt(const SkPoint& a, const SkPoint& b) const {
90 return fDirection == Direction::kHorizontal ? sweep_lt_horiz(a, b) : sweep_lt_vert(a, b);
91}
Stephen White16a40cb2017-02-23 11:10:01 -050092
Chris Daltond60c9192021-01-07 18:30:08 +000093static inline void* emit_vertex(Vertex* v, bool emitCoverage, void* data) {
Brian Osmanf9aabff2018-11-13 16:11:38 -050094 GrVertexWriter verts{data};
95 verts.write(v->fPoint);
96
Brian Osman80879d42019-01-07 16:15:27 -050097 if (emitCoverage) {
98 verts.write(GrNormalizeByteToFloat(v->fAlpha));
99 }
Brian Osman0995fd52019-01-09 09:52:25 -0500100
Brian Osmanf9aabff2018-11-13 16:11:38 -0500101 return verts.fPtr;
ethannicholase9709e82016-01-07 13:34:16 -0800102}
103
Chris Daltond60c9192021-01-07 18:30:08 +0000104static void* emit_triangle(Vertex* v0, Vertex* v1, Vertex* v2, bool emitCoverage, void* data) {
Brian Salomon120e7d62019-09-11 10:29:22 -0400105 TESS_LOG("emit_triangle %g (%g, %g) %d\n", v0->fID, v0->fPoint.fX, v0->fPoint.fY, v0->fAlpha);
106 TESS_LOG(" %g (%g, %g) %d\n", v1->fID, v1->fPoint.fX, v1->fPoint.fY, v1->fAlpha);
107 TESS_LOG(" %g (%g, %g) %d\n", v2->fID, v2->fPoint.fX, v2->fPoint.fY, v2->fAlpha);
senorblancof57372d2016-08-31 10:36:19 -0700108#if TESSELLATOR_WIREFRAME
Brian Osman0995fd52019-01-09 09:52:25 -0500109 data = emit_vertex(v0, emitCoverage, data);
110 data = emit_vertex(v1, emitCoverage, data);
111 data = emit_vertex(v1, emitCoverage, data);
112 data = emit_vertex(v2, emitCoverage, data);
113 data = emit_vertex(v2, emitCoverage, data);
114 data = emit_vertex(v0, emitCoverage, data);
ethannicholase9709e82016-01-07 13:34:16 -0800115#else
Brian Osman0995fd52019-01-09 09:52:25 -0500116 data = emit_vertex(v0, emitCoverage, data);
117 data = emit_vertex(v1, emitCoverage, data);
118 data = emit_vertex(v2, emitCoverage, data);
ethannicholase9709e82016-01-07 13:34:16 -0800119#endif
120 return data;
121}
122
Chris Dalton5045de32021-01-07 19:09:01 -0700123void GrTriangulator::VertexList::insert(Vertex* v, Vertex* prev, Vertex* next) {
124 list_insert<Vertex, &Vertex::fPrev, &Vertex::fNext>(v, prev, next, &fHead, &fTail);
125}
126
127void GrTriangulator::VertexList::remove(Vertex* v) {
128 list_remove<Vertex, &Vertex::fPrev, &Vertex::fNext>(v, &fHead, &fTail);
129}
senorblancoe6eaa322016-03-08 09:06:44 -0800130
senorblancof57372d2016-08-31 10:36:19 -0700131// Round to nearest quarter-pixel. This is used for screenspace tessellation.
132
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700133static inline void round(SkPoint* p) {
senorblancof57372d2016-08-31 10:36:19 -0700134 p->fX = SkScalarRoundToScalar(p->fX * SkFloatToScalar(4.0f)) * SkFloatToScalar(0.25f);
135 p->fY = SkScalarRoundToScalar(p->fY * SkFloatToScalar(4.0f)) * SkFloatToScalar(0.25f);
136}
137
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700138static inline SkScalar double_to_clamped_scalar(double d) {
Stephen White94b7e542018-01-04 14:01:10 -0500139 return SkDoubleToScalar(std::min((double) SK_ScalarMax, std::max(d, (double) -SK_ScalarMax)));
140}
141
Chris Dalton5045de32021-01-07 19:09:01 -0700142bool GrTriangulator::Line::intersect(const Line& other, SkPoint* point) const {
143 double denom = fA * other.fB - fB * other.fA;
144 if (denom == 0.0) {
145 return false;
senorblanco49df8d12016-10-07 08:36:56 -0700146 }
Chris Dalton5045de32021-01-07 19:09:01 -0700147 double scale = 1.0 / denom;
148 point->fX = double_to_clamped_scalar((fB * other.fC - other.fB * fC) * scale);
149 point->fY = double_to_clamped_scalar((other.fA * fC - fA * other.fC) * scale);
150 round(point);
151 return point->isFinite();
152}
Chris Daltond60c9192021-01-07 18:30:08 +0000153
Chris Dalton5045de32021-01-07 19:09:01 -0700154bool GrTriangulator::Edge::intersect(const Edge& other, SkPoint* p, uint8_t* alpha) const {
155 TESS_LOG("intersecting %g -> %g with %g -> %g\n",
156 fTop->fID, fBottom->fID, other.fTop->fID, other.fBottom->fID);
157 if (fTop == other.fTop || fBottom == other.fBottom) {
158 return false;
Chris Daltond60c9192021-01-07 18:30:08 +0000159 }
Chris Dalton5045de32021-01-07 19:09:01 -0700160 double denom = fLine.fA * other.fLine.fB - fLine.fB * other.fLine.fA;
161 if (denom == 0.0) {
162 return false;
Chris Daltond60c9192021-01-07 18:30:08 +0000163 }
Chris Dalton5045de32021-01-07 19:09:01 -0700164 double dx = static_cast<double>(other.fTop->fPoint.fX) - fTop->fPoint.fX;
165 double dy = static_cast<double>(other.fTop->fPoint.fY) - fTop->fPoint.fY;
166 double sNumer = dy * other.fLine.fB + dx * other.fLine.fA;
167 double tNumer = dy * fLine.fB + dx * fLine.fA;
168 // If (sNumer / denom) or (tNumer / denom) is not in [0..1], exit early.
169 // This saves us doing the divide below unless absolutely necessary.
170 if (denom > 0.0 ? (sNumer < 0.0 || sNumer > denom || tNumer < 0.0 || tNumer > denom)
171 : (sNumer > 0.0 || sNumer < denom || tNumer > 0.0 || tNumer < denom)) {
172 return false;
Chris Daltond60c9192021-01-07 18:30:08 +0000173 }
Chris Dalton5045de32021-01-07 19:09:01 -0700174 double s = sNumer / denom;
175 SkASSERT(s >= 0.0 && s <= 1.0);
176 p->fX = SkDoubleToScalar(fTop->fPoint.fX - s * fLine.fB);
177 p->fY = SkDoubleToScalar(fTop->fPoint.fY + s * fLine.fA);
178 if (alpha) {
179 if (fType == EdgeType::kConnector) {
180 *alpha = (1.0 - s) * fTop->fAlpha + s * fBottom->fAlpha;
181 } else if (other.fType == EdgeType::kConnector) {
182 double t = tNumer / denom;
183 *alpha = (1.0 - t) * other.fTop->fAlpha + t * other.fBottom->fAlpha;
184 } else if (fType == EdgeType::kOuter && other.fType == EdgeType::kOuter) {
185 *alpha = 0;
186 } else {
187 *alpha = 255;
188 }
Chris Daltond60c9192021-01-07 18:30:08 +0000189 }
Chris Dalton5045de32021-01-07 19:09:01 -0700190 return true;
191}
senorblancof57372d2016-08-31 10:36:19 -0700192
Stephen Whitec4dbc372019-05-22 10:50:14 -0400193struct SSVertex {
194 SSVertex(Vertex* v) : fVertex(v), fPrev(nullptr), fNext(nullptr) {}
195 Vertex* fVertex;
196 SSEdge* fPrev;
197 SSEdge* fNext;
198};
199
Chris Dalton7cf3add2021-01-11 18:33:28 -0700200struct GrAATriangulator::SSEdge {
Stephen Whitec4dbc372019-05-22 10:50:14 -0400201 SSEdge(Edge* edge, SSVertex* prev, SSVertex* next)
202 : fEdge(edge), fEvent(nullptr), fPrev(prev), fNext(next) {
203 }
204 Edge* fEdge;
205 Event* fEvent;
206 SSVertex* fPrev;
207 SSVertex* fNext;
208};
209
210typedef std::unordered_map<Vertex*, SSVertex*> SSVertexMap;
211typedef std::vector<SSEdge*> SSEdgeList;
212
Chris Dalton5045de32021-01-07 19:09:01 -0700213void GrTriangulator::EdgeList::insert(Edge* edge, Edge* prev, Edge* next) {
214 list_insert<Edge, &Edge::fLeft, &Edge::fRight>(edge, prev, next, &fHead, &fTail);
215}
Chris Dalton24472af2021-01-11 20:05:00 -0700216
Chris Dalton5045de32021-01-07 19:09:01 -0700217void GrTriangulator::EdgeList::remove(Edge* edge) {
Chris Dalton24472af2021-01-11 20:05:00 -0700218 TESS_LOG("removing edge %g -> %g\n", edge->fTop->fID, edge->fBottom->fID);
219 SkASSERT(this->contains(edge));
Chris Dalton5045de32021-01-07 19:09:01 -0700220 list_remove<Edge, &Edge::fLeft, &Edge::fRight>(edge, &fHead, &fTail);
221}
ethannicholase9709e82016-01-07 13:34:16 -0800222
Stephen Whitec4dbc372019-05-22 10:50:14 -0400223typedef std::priority_queue<Event*, std::vector<Event*>, EventComparator> EventPQ;
Stephen Whitee260c462017-12-19 18:09:54 -0500224
Chris Dalton7cf3add2021-01-11 18:33:28 -0700225struct GrAATriangulator::EventList : EventPQ {
Stephen Whitec4dbc372019-05-22 10:50:14 -0400226 EventList(EventComparator comparison) : EventPQ(comparison) {
227 }
228};
229
Chris Dalton7cf3add2021-01-11 18:33:28 -0700230void GrAATriangulator::makeEvent(SSEdge* e, EventList* events) {
Stephen Whitec4dbc372019-05-22 10:50:14 -0400231 Vertex* prev = e->fPrev->fVertex;
232 Vertex* next = e->fNext->fVertex;
233 if (prev == next || !prev->fPartner || !next->fPartner) {
234 return;
235 }
Chris Dalton17ce8c52021-01-07 18:08:46 -0700236 Edge bisector1(prev, prev->fPartner, 1, EdgeType::kConnector);
237 Edge bisector2(next, next->fPartner, 1, EdgeType::kConnector);
Stephen Whitee260c462017-12-19 18:09:54 -0500238 SkPoint p;
239 uint8_t alpha;
240 if (bisector1.intersect(bisector2, &p, &alpha)) {
Brian Salomon120e7d62019-09-11 10:29:22 -0400241 TESS_LOG("found edge event for %g, %g (original %g -> %g), "
242 "will collapse to %g,%g alpha %d\n",
243 prev->fID, next->fID, e->fEdge->fTop->fID, e->fEdge->fBottom->fID, p.fX, p.fY,
244 alpha);
Chris Dalton7cf3add2021-01-11 18:33:28 -0700245 e->fEvent = fAlloc.make<Event>(e, p, alpha);
Stephen Whitec4dbc372019-05-22 10:50:14 -0400246 events->push(e->fEvent);
247 }
248}
249
Chris Dalton7cf3add2021-01-11 18:33:28 -0700250void GrAATriangulator::makeEvent(SSEdge* edge, Vertex* v, SSEdge* other, Vertex* dest,
251 EventList* events, const Comparator& c) {
Stephen Whitec4dbc372019-05-22 10:50:14 -0400252 if (!v->fPartner) {
253 return;
254 }
Stephen White8a3c0592019-05-29 11:26:16 -0400255 Vertex* top = edge->fEdge->fTop;
256 Vertex* bottom = edge->fEdge->fBottom;
257 if (!top || !bottom ) {
258 return;
259 }
Stephen Whitec4dbc372019-05-22 10:50:14 -0400260 Line line = edge->fEdge->fLine;
261 line.fC = -(dest->fPoint.fX * line.fA + dest->fPoint.fY * line.fB);
Chris Dalton17ce8c52021-01-07 18:08:46 -0700262 Edge bisector(v, v->fPartner, 1, EdgeType::kConnector);
Stephen Whitec4dbc372019-05-22 10:50:14 -0400263 SkPoint p;
264 uint8_t alpha = dest->fAlpha;
Stephen White8a3c0592019-05-29 11:26:16 -0400265 if (line.intersect(bisector.fLine, &p) && !c.sweep_lt(p, top->fPoint) &&
266 c.sweep_lt(p, bottom->fPoint)) {
Brian Salomon120e7d62019-09-11 10:29:22 -0400267 TESS_LOG("found p edge event for %g, %g (original %g -> %g), "
268 "will collapse to %g,%g alpha %d\n",
269 dest->fID, v->fID, top->fID, bottom->fID, p.fX, p.fY, alpha);
Chris Dalton7cf3add2021-01-11 18:33:28 -0700270 edge->fEvent = fAlloc.make<Event>(edge, p, alpha);
Stephen Whitec4dbc372019-05-22 10:50:14 -0400271 events->push(edge->fEvent);
Stephen Whitee260c462017-12-19 18:09:54 -0500272 }
273}
Stephen Whitee260c462017-12-19 18:09:54 -0500274
Chris Dalton5045de32021-01-07 19:09:01 -0700275void GrTriangulator::MonotonePoly::addEdge(Edge* edge) {
276 if (fSide == kRight_Side) {
277 SkASSERT(!edge->fUsedInRightPoly);
278 list_insert<Edge, &Edge::fRightPolyPrev, &Edge::fRightPolyNext>(
279 edge, fLastEdge, nullptr, &fFirstEdge, &fLastEdge);
280 edge->fUsedInRightPoly = true;
281 } else {
282 SkASSERT(!edge->fUsedInLeftPoly);
283 list_insert<Edge, &Edge::fLeftPolyPrev, &Edge::fLeftPolyNext>(
284 edge, fLastEdge, nullptr, &fFirstEdge, &fLastEdge);
285 edge->fUsedInLeftPoly = true;
Chris Dalton17ce8c52021-01-07 18:08:46 -0700286 }
Chris Dalton5045de32021-01-07 19:09:01 -0700287}
Chris Dalton17ce8c52021-01-07 18:08:46 -0700288
Chris Dalton9a4904f2021-01-07 19:10:14 -0700289void* GrTriangulator::emitMonotonePoly(const MonotonePoly* monotonePoly, void* data) {
Chris Dalton93c2d812021-01-11 19:51:59 -0700290 SkASSERT(monotonePoly->fWinding != 0);
Chris Dalton9a4904f2021-01-07 19:10:14 -0700291 Edge* e = monotonePoly->fFirstEdge;
Chris Dalton5045de32021-01-07 19:09:01 -0700292 VertexList vertices;
293 vertices.append(e->fTop);
294 int count = 1;
295 while (e != nullptr) {
Chris Dalton9a4904f2021-01-07 19:10:14 -0700296 if (kRight_Side == monotonePoly->fSide) {
Chris Dalton5045de32021-01-07 19:09:01 -0700297 vertices.append(e->fBottom);
298 e = e->fRightPolyNext;
299 } else {
300 vertices.prepend(e->fBottom);
301 e = e->fLeftPolyNext;
Chris Dalton17ce8c52021-01-07 18:08:46 -0700302 }
Chris Dalton5045de32021-01-07 19:09:01 -0700303 count++;
304 }
305 Vertex* first = vertices.fHead;
306 Vertex* v = first->fNext;
307 while (v != vertices.fTail) {
308 SkASSERT(v && v->fPrev && v->fNext);
309 Vertex* prev = v->fPrev;
310 Vertex* curr = v;
311 Vertex* next = v->fNext;
312 if (count == 3) {
Chris Dalton9a4904f2021-01-07 19:10:14 -0700313 return this->emitTriangle(prev, curr, next, monotonePoly->fWinding, data);
Chris Dalton5045de32021-01-07 19:09:01 -0700314 }
315 double ax = static_cast<double>(curr->fPoint.fX) - prev->fPoint.fX;
316 double ay = static_cast<double>(curr->fPoint.fY) - prev->fPoint.fY;
317 double bx = static_cast<double>(next->fPoint.fX) - curr->fPoint.fX;
318 double by = static_cast<double>(next->fPoint.fY) - curr->fPoint.fY;
319 if (ax * by - ay * bx >= 0.0) {
Chris Dalton9a4904f2021-01-07 19:10:14 -0700320 data = this->emitTriangle(prev, curr, next, monotonePoly->fWinding, data);
Chris Dalton5045de32021-01-07 19:09:01 -0700321 v->fPrev->fNext = v->fNext;
322 v->fNext->fPrev = v->fPrev;
323 count--;
324 if (v->fPrev == first) {
Chris Dalton17ce8c52021-01-07 18:08:46 -0700325 v = v->fNext;
Chris Daltond60c9192021-01-07 18:30:08 +0000326 } else {
Chris Dalton5045de32021-01-07 19:09:01 -0700327 v = v->fPrev;
Chris Daltond60c9192021-01-07 18:30:08 +0000328 }
Chris Dalton5045de32021-01-07 19:09:01 -0700329 } else {
330 v = v->fNext;
Chris Daltond60c9192021-01-07 18:30:08 +0000331 }
Chris Dalton75887a22021-01-06 00:23:13 -0700332 }
Chris Dalton5045de32021-01-07 19:09:01 -0700333 return data;
334}
335
Chris Dalton9a4904f2021-01-07 19:10:14 -0700336void* GrTriangulator::emitTriangle(Vertex* prev, Vertex* curr, Vertex* next, int winding,
337 void* data) const {
Chris Dalton93c2d812021-01-11 19:51:59 -0700338 if (winding > 0) {
Chris Dalton5045de32021-01-07 19:09:01 -0700339 // Ensure our triangles always wind in the same direction as if the path had been
340 // triangulated as a simple fan (a la red book).
341 std::swap(prev, next);
342 }
Chris Dalton93c2d812021-01-11 19:51:59 -0700343 return emit_triangle(prev, curr, next, fEmitCoverage, data);
Chris Dalton5045de32021-01-07 19:09:01 -0700344}
345
346Poly* GrTriangulator::Poly::addEdge(Edge* e, Side side, SkArenaAlloc& alloc) {
347 TESS_LOG("addEdge (%g -> %g) to poly %d, %s side\n",
348 e->fTop->fID, e->fBottom->fID, fID, side == kLeft_Side ? "left" : "right");
349 Poly* partner = fPartner;
350 Poly* poly = this;
351 if (side == kRight_Side) {
352 if (e->fUsedInRightPoly) {
353 return this;
Chris Daltond60c9192021-01-07 18:30:08 +0000354 }
Chris Dalton5045de32021-01-07 19:09:01 -0700355 } else {
356 if (e->fUsedInLeftPoly) {
357 return this;
Chris Daltond60c9192021-01-07 18:30:08 +0000358 }
Chris Dalton5045de32021-01-07 19:09:01 -0700359 }
360 if (partner) {
361 fPartner = partner->fPartner = nullptr;
362 }
363 if (!fTail) {
364 fHead = fTail = alloc.make<MonotonePoly>(e, side, fWinding);
365 fCount += 2;
366 } else if (e->fBottom == fTail->fLastEdge->fBottom) {
367 return poly;
368 } else if (side == fTail->fSide) {
369 fTail->addEdge(e);
370 fCount++;
371 } else {
372 e = alloc.make<Edge>(fTail->fLastEdge->fBottom, e->fBottom, 1, EdgeType::kInner);
373 fTail->addEdge(e);
374 fCount++;
375 if (partner) {
376 partner->addEdge(e, side, alloc);
377 poly = partner;
378 } else {
379 MonotonePoly* m = alloc.make<MonotonePoly>(e, side, fWinding);
380 m->fPrev = fTail;
381 fTail->fNext = m;
382 fTail = m;
383 }
384 }
385 return poly;
386}
Chris Dalton9a4904f2021-01-07 19:10:14 -0700387void* GrTriangulator::emitPoly(const Poly* poly, void *data) {
388 if (poly->fCount < 3) {
ethannicholase9709e82016-01-07 13:34:16 -0800389 return data;
390 }
Chris Dalton5045de32021-01-07 19:09:01 -0700391 TESS_LOG("emit() %d, size %d\n", fID, fCount);
Chris Dalton9a4904f2021-01-07 19:10:14 -0700392 for (MonotonePoly* m = poly->fHead; m != nullptr; m = m->fNext) {
393 data = this->emitMonotonePoly(m, data);
Chris Dalton5045de32021-01-07 19:09:01 -0700394 }
395 return data;
396}
ethannicholase9709e82016-01-07 13:34:16 -0800397
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700398static bool coincident(const SkPoint& a, const SkPoint& b) {
ethannicholase9709e82016-01-07 13:34:16 -0800399 return a == b;
400}
401
Chris Dalton7cf3add2021-01-11 18:33:28 -0700402Poly* GrTriangulator::makePoly(Poly** head, Vertex* v, int winding) {
403 Poly* poly = fAlloc.make<Poly>(v, winding);
ethannicholase9709e82016-01-07 13:34:16 -0800404 poly->fNext = *head;
405 *head = poly;
406 return poly;
407}
408
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700409void GrTriangulator::appendPointToContour(const SkPoint& p, VertexList* contour) {
410 Vertex* v = fAlloc.make<Vertex>(p, 255);
Chris Dalton5045de32021-01-07 19:09:01 -0700411#if TRIANGULATOR_LOGGING
ethannicholase9709e82016-01-07 13:34:16 -0800412 static float gID = 0.0f;
413 v->fID = gID++;
414#endif
Stephen White3a9aab92017-03-07 14:07:18 -0500415 contour->append(v);
ethannicholase9709e82016-01-07 13:34:16 -0800416}
417
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700418static SkScalar quad_error_at(const SkPoint pts[3], SkScalar t, SkScalar u) {
Stephen White36e4f062017-03-27 16:11:31 -0400419 SkQuadCoeff quad(pts);
420 SkPoint p0 = to_point(quad.eval(t - 0.5f * u));
421 SkPoint mid = to_point(quad.eval(t));
422 SkPoint p1 = to_point(quad.eval(t + 0.5f * u));
Stephen Whitee3a0be72017-06-12 11:43:18 -0400423 if (!p0.isFinite() || !mid.isFinite() || !p1.isFinite()) {
424 return 0;
425 }
Cary Clarkdf429f32017-11-08 11:44:31 -0500426 return SkPointPriv::DistanceToLineSegmentBetweenSqd(mid, p0, p1);
Stephen White36e4f062017-03-27 16:11:31 -0400427}
428
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700429void GrTriangulator::appendQuadraticToContour(const SkPoint pts[3], SkScalar toleranceSqd,
430 VertexList* contour) {
Stephen White36e4f062017-03-27 16:11:31 -0400431 SkQuadCoeff quad(pts);
432 Sk2s aa = quad.fA * quad.fA;
433 SkScalar denom = 2.0f * (aa[0] + aa[1]);
434 Sk2s ab = quad.fA * quad.fB;
435 SkScalar t = denom ? (-ab[0] - ab[1]) / denom : 0.0f;
436 int nPoints = 1;
Stephen Whitee40c3612018-01-09 11:49:08 -0500437 SkScalar u = 1.0f;
Stephen White36e4f062017-03-27 16:11:31 -0400438 // Test possible subdivision values only at the point of maximum curvature.
439 // If it passes the flatness metric there, it'll pass everywhere.
Stephen Whitee40c3612018-01-09 11:49:08 -0500440 while (nPoints < GrPathUtils::kMaxPointsPerCurve) {
Stephen White36e4f062017-03-27 16:11:31 -0400441 u = 1.0f / nPoints;
442 if (quad_error_at(pts, t, u) < toleranceSqd) {
443 break;
444 }
445 nPoints++;
ethannicholase9709e82016-01-07 13:34:16 -0800446 }
Stephen White36e4f062017-03-27 16:11:31 -0400447 for (int j = 1; j <= nPoints; j++) {
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700448 this->appendPointToContour(to_point(quad.eval(j * u)), contour);
Stephen White36e4f062017-03-27 16:11:31 -0400449 }
ethannicholase9709e82016-01-07 13:34:16 -0800450}
451
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700452void GrTriangulator::generateCubicPoints(const SkPoint& p0, const SkPoint& p1, const SkPoint& p2,
453 const SkPoint& p3, SkScalar tolSqd, VertexList* contour,
454 int pointsLeft) {
Cary Clarkdf429f32017-11-08 11:44:31 -0500455 SkScalar d1 = SkPointPriv::DistanceToLineSegmentBetweenSqd(p1, p0, p3);
456 SkScalar d2 = SkPointPriv::DistanceToLineSegmentBetweenSqd(p2, p0, p3);
ethannicholase9709e82016-01-07 13:34:16 -0800457 if (pointsLeft < 2 || (d1 < tolSqd && d2 < tolSqd) ||
458 !SkScalarIsFinite(d1) || !SkScalarIsFinite(d2)) {
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700459 this->appendPointToContour(p3, contour);
Stephen White3a9aab92017-03-07 14:07:18 -0500460 return;
ethannicholase9709e82016-01-07 13:34:16 -0800461 }
462 const SkPoint q[] = {
463 { SkScalarAve(p0.fX, p1.fX), SkScalarAve(p0.fY, p1.fY) },
464 { SkScalarAve(p1.fX, p2.fX), SkScalarAve(p1.fY, p2.fY) },
465 { SkScalarAve(p2.fX, p3.fX), SkScalarAve(p2.fY, p3.fY) }
466 };
467 const SkPoint r[] = {
468 { SkScalarAve(q[0].fX, q[1].fX), SkScalarAve(q[0].fY, q[1].fY) },
469 { SkScalarAve(q[1].fX, q[2].fX), SkScalarAve(q[1].fY, q[2].fY) }
470 };
471 const SkPoint s = { SkScalarAve(r[0].fX, r[1].fX), SkScalarAve(r[0].fY, r[1].fY) };
472 pointsLeft >>= 1;
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700473 this->generateCubicPoints(p0, q[0], r[0], s, tolSqd, contour, pointsLeft);
474 this->generateCubicPoints(s, r[1], q[2], p3, tolSqd, contour, pointsLeft);
ethannicholase9709e82016-01-07 13:34:16 -0800475}
476
477// Stage 1: convert the input path to a set of linear contours (linked list of Vertices).
478
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700479void GrTriangulator::pathToContours(float tolerance, const SkRect& clipBounds,
480 VertexList* contours) {
ethannicholase9709e82016-01-07 13:34:16 -0800481 SkScalar toleranceSqd = tolerance * tolerance;
Chris Dalton7156db22020-05-07 22:06:28 +0000482 SkPoint pts[4];
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700483 fIsLinear = true;
Stephen White3a9aab92017-03-07 14:07:18 -0500484 VertexList* contour = contours;
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700485 SkPath::Iter iter(fPath, false);
486 if (fPath.isInverseFillType()) {
ethannicholase9709e82016-01-07 13:34:16 -0800487 SkPoint quad[4];
488 clipBounds.toQuad(quad);
senorblanco7ab96e92016-10-12 06:47:44 -0700489 for (int i = 3; i >= 0; i--) {
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700490 this->appendPointToContour(quad[i], contours);
ethannicholase9709e82016-01-07 13:34:16 -0800491 }
Stephen White3a9aab92017-03-07 14:07:18 -0500492 contour++;
ethannicholase9709e82016-01-07 13:34:16 -0800493 }
494 SkAutoConicToQuads converter;
Chris Dalton7156db22020-05-07 22:06:28 +0000495 SkPath::Verb verb;
496 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
ethannicholase9709e82016-01-07 13:34:16 -0800497 switch (verb) {
Chris Dalton7156db22020-05-07 22:06:28 +0000498 case SkPath::kConic_Verb: {
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700499 fIsLinear = false;
Chris Dalton854ee852021-01-05 15:12:59 -0700500 if (fSimpleInnerPolygons) {
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700501 this->appendPointToContour(pts[2], contour);
Chris Dalton6ccc0322020-01-29 11:38:16 -0700502 break;
503 }
Chris Dalton7156db22020-05-07 22:06:28 +0000504 SkScalar weight = iter.conicWeight();
505 const SkPoint* quadPts = converter.computeQuads(pts, weight, toleranceSqd);
ethannicholase9709e82016-01-07 13:34:16 -0800506 for (int i = 0; i < converter.countQuads(); ++i) {
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700507 this->appendQuadraticToContour(quadPts, toleranceSqd, contour);
ethannicholase9709e82016-01-07 13:34:16 -0800508 quadPts += 2;
509 }
ethannicholase9709e82016-01-07 13:34:16 -0800510 break;
511 }
Chris Dalton7156db22020-05-07 22:06:28 +0000512 case SkPath::kMove_Verb:
Stephen White3a9aab92017-03-07 14:07:18 -0500513 if (contour->fHead) {
514 contour++;
ethannicholase9709e82016-01-07 13:34:16 -0800515 }
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700516 this->appendPointToContour(pts[0], contour);
ethannicholase9709e82016-01-07 13:34:16 -0800517 break;
Chris Dalton7156db22020-05-07 22:06:28 +0000518 case SkPath::kLine_Verb: {
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700519 this->appendPointToContour(pts[1], contour);
ethannicholase9709e82016-01-07 13:34:16 -0800520 break;
521 }
Chris Dalton7156db22020-05-07 22:06:28 +0000522 case SkPath::kQuad_Verb: {
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700523 fIsLinear = false;
Chris Dalton854ee852021-01-05 15:12:59 -0700524 if (fSimpleInnerPolygons) {
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700525 this->appendPointToContour(pts[2], contour);
Chris Dalton6ccc0322020-01-29 11:38:16 -0700526 break;
527 }
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700528 this->appendQuadraticToContour(pts, toleranceSqd, contour);
ethannicholase9709e82016-01-07 13:34:16 -0800529 break;
530 }
Chris Dalton7156db22020-05-07 22:06:28 +0000531 case SkPath::kCubic_Verb: {
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700532 fIsLinear = false;
Chris Dalton854ee852021-01-05 15:12:59 -0700533 if (fSimpleInnerPolygons) {
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700534 this->appendPointToContour(pts[3], contour);
Chris Dalton6ccc0322020-01-29 11:38:16 -0700535 break;
536 }
ethannicholase9709e82016-01-07 13:34:16 -0800537 int pointsLeft = GrPathUtils::cubicPointCount(pts, tolerance);
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700538 this->generateCubicPoints(pts[0], pts[1], pts[2], pts[3], toleranceSqd, contour,
539 pointsLeft);
ethannicholase9709e82016-01-07 13:34:16 -0800540 break;
541 }
Chris Dalton7156db22020-05-07 22:06:28 +0000542 case SkPath::kClose_Verb:
543 case SkPath::kDone_Verb:
ethannicholase9709e82016-01-07 13:34:16 -0800544 break;
545 }
546 }
547}
548
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700549static inline bool apply_fill_type(SkPathFillType fillType, int winding) {
ethannicholase9709e82016-01-07 13:34:16 -0800550 switch (fillType) {
Mike Reed7d34dc72019-11-26 12:17:17 -0500551 case SkPathFillType::kWinding:
ethannicholase9709e82016-01-07 13:34:16 -0800552 return winding != 0;
Mike Reed7d34dc72019-11-26 12:17:17 -0500553 case SkPathFillType::kEvenOdd:
ethannicholase9709e82016-01-07 13:34:16 -0800554 return (winding & 1) != 0;
Mike Reed7d34dc72019-11-26 12:17:17 -0500555 case SkPathFillType::kInverseWinding:
senorblanco7ab96e92016-10-12 06:47:44 -0700556 return winding == 1;
Mike Reed7d34dc72019-11-26 12:17:17 -0500557 case SkPathFillType::kInverseEvenOdd:
ethannicholase9709e82016-01-07 13:34:16 -0800558 return (winding & 1) == 1;
559 default:
560 SkASSERT(false);
561 return false;
562 }
563}
564
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700565static inline bool apply_fill_type(SkPathFillType fillType, Poly* poly) {
Stephen White49789062017-02-21 10:35:49 -0500566 return poly && apply_fill_type(fillType, poly->fWinding);
567}
568
Chris Dalton7cf3add2021-01-11 18:33:28 -0700569Edge* GrTriangulator::makeEdge(Vertex* prev, Vertex* next, EdgeType type, const Comparator& c) {
Stephen White2f4686f2017-01-03 16:20:01 -0500570 int winding = c.sweep_lt(prev->fPoint, next->fPoint) ? 1 : -1;
ethannicholase9709e82016-01-07 13:34:16 -0800571 Vertex* top = winding < 0 ? next : prev;
572 Vertex* bottom = winding < 0 ? prev : next;
Chris Dalton7cf3add2021-01-11 18:33:28 -0700573 return fAlloc.make<Edge>(top, bottom, winding, type);
ethannicholase9709e82016-01-07 13:34:16 -0800574}
575
Chris Dalton24472af2021-01-11 20:05:00 -0700576void EdgeList::insert(Edge* edge, Edge* prev) {
Brian Salomon120e7d62019-09-11 10:29:22 -0400577 TESS_LOG("inserting edge %g -> %g\n", edge->fTop->fID, edge->fBottom->fID);
Chris Dalton24472af2021-01-11 20:05:00 -0700578 SkASSERT(!this->contains(edge));
579 Edge* next = prev ? prev->fRight : fHead;
580 this->insert(edge, prev, next);
ethannicholase9709e82016-01-07 13:34:16 -0800581}
582
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700583static void find_enclosing_edges(Vertex* v, EdgeList* edges, Edge** left, Edge** right) {
Stephen White90732fd2017-03-02 16:16:33 -0500584 if (v->fFirstEdgeAbove && v->fLastEdgeAbove) {
ethannicholase9709e82016-01-07 13:34:16 -0800585 *left = v->fFirstEdgeAbove->fLeft;
586 *right = v->fLastEdgeAbove->fRight;
587 return;
588 }
589 Edge* next = nullptr;
590 Edge* prev;
591 for (prev = edges->fTail; prev != nullptr; prev = prev->fLeft) {
592 if (prev->isLeftOf(v)) {
593 break;
594 }
595 next = prev;
596 }
597 *left = prev;
598 *right = next;
ethannicholase9709e82016-01-07 13:34:16 -0800599}
600
Chris Dalton24472af2021-01-11 20:05:00 -0700601void GrTriangulator::Edge::insertAbove(Vertex* v, const Comparator& c) {
602 if (fTop->fPoint == fBottom->fPoint ||
603 c.sweep_lt(fBottom->fPoint, fTop->fPoint)) {
ethannicholase9709e82016-01-07 13:34:16 -0800604 return;
605 }
Chris Dalton24472af2021-01-11 20:05:00 -0700606 TESS_LOG("insert edge (%g -> %g) above vertex %g\n", fTop->fID, fBottom->fID, v->fID);
ethannicholase9709e82016-01-07 13:34:16 -0800607 Edge* prev = nullptr;
608 Edge* next;
Chris Daltond60c9192021-01-07 18:30:08 +0000609 for (next = v->fFirstEdgeAbove; next; next = next->fNextEdgeAbove) {
Chris Dalton24472af2021-01-11 20:05:00 -0700610 if (next->isRightOf(fTop)) {
ethannicholase9709e82016-01-07 13:34:16 -0800611 break;
612 }
613 prev = next;
614 }
senorblancoe6eaa322016-03-08 09:06:44 -0800615 list_insert<Edge, &Edge::fPrevEdgeAbove, &Edge::fNextEdgeAbove>(
Chris Dalton24472af2021-01-11 20:05:00 -0700616 this, prev, next, &v->fFirstEdgeAbove, &v->fLastEdgeAbove);
ethannicholase9709e82016-01-07 13:34:16 -0800617}
618
Chris Dalton24472af2021-01-11 20:05:00 -0700619void GrTriangulator::Edge::insertBelow(Vertex* v, const Comparator& c) {
620 if (fTop->fPoint == fBottom->fPoint ||
621 c.sweep_lt(fBottom->fPoint, fTop->fPoint)) {
ethannicholase9709e82016-01-07 13:34:16 -0800622 return;
623 }
Chris Dalton24472af2021-01-11 20:05:00 -0700624 TESS_LOG("insert edge (%g -> %g) below vertex %g\n", fTop->fID, fBottom->fID, v->fID);
ethannicholase9709e82016-01-07 13:34:16 -0800625 Edge* prev = nullptr;
626 Edge* next;
Chris Daltond60c9192021-01-07 18:30:08 +0000627 for (next = v->fFirstEdgeBelow; next; next = next->fNextEdgeBelow) {
Chris Dalton24472af2021-01-11 20:05:00 -0700628 if (next->isRightOf(fBottom)) {
ethannicholase9709e82016-01-07 13:34:16 -0800629 break;
630 }
631 prev = next;
632 }
senorblancoe6eaa322016-03-08 09:06:44 -0800633 list_insert<Edge, &Edge::fPrevEdgeBelow, &Edge::fNextEdgeBelow>(
Chris Dalton24472af2021-01-11 20:05:00 -0700634 this, prev, next, &v->fFirstEdgeBelow, &v->fLastEdgeBelow);
ethannicholase9709e82016-01-07 13:34:16 -0800635}
636
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700637static void remove_edge_above(Edge* edge) {
Stephen White7b376942018-05-22 11:51:32 -0400638 SkASSERT(edge->fTop && edge->fBottom);
Brian Salomon120e7d62019-09-11 10:29:22 -0400639 TESS_LOG("removing edge (%g -> %g) above vertex %g\n", edge->fTop->fID, edge->fBottom->fID,
640 edge->fBottom->fID);
senorblancoe6eaa322016-03-08 09:06:44 -0800641 list_remove<Edge, &Edge::fPrevEdgeAbove, &Edge::fNextEdgeAbove>(
ethannicholase9709e82016-01-07 13:34:16 -0800642 edge, &edge->fBottom->fFirstEdgeAbove, &edge->fBottom->fLastEdgeAbove);
643}
644
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700645static void remove_edge_below(Edge* edge) {
Stephen White7b376942018-05-22 11:51:32 -0400646 SkASSERT(edge->fTop && edge->fBottom);
Brian Salomon120e7d62019-09-11 10:29:22 -0400647 TESS_LOG("removing edge (%g -> %g) below vertex %g\n",
648 edge->fTop->fID, edge->fBottom->fID, edge->fTop->fID);
senorblancoe6eaa322016-03-08 09:06:44 -0800649 list_remove<Edge, &Edge::fPrevEdgeBelow, &Edge::fNextEdgeBelow>(
ethannicholase9709e82016-01-07 13:34:16 -0800650 edge, &edge->fTop->fFirstEdgeBelow, &edge->fTop->fLastEdgeBelow);
651}
652
Chris Dalton24472af2021-01-11 20:05:00 -0700653void GrTriangulator::Edge::disconnect() {
654 remove_edge_above(this);
655 remove_edge_below(this);
Stephen Whitee7a364d2017-01-11 16:19:26 -0500656}
657
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700658static void merge_collinear_edges(Edge* edge, EdgeList* activeEdges, Vertex** current,
Chris Dalton811dc6a2021-01-07 16:40:32 -0700659 const Comparator& c);
Stephen White3b5a3fa2017-06-06 14:51:19 -0400660
Chris Dalton811dc6a2021-01-07 16:40:32 -0700661static void rewind(EdgeList* activeEdges, Vertex** current, Vertex* dst, const Comparator& c) {
Stephen White3b5a3fa2017-06-06 14:51:19 -0400662 if (!current || *current == dst || c.sweep_lt((*current)->fPoint, dst->fPoint)) {
663 return;
664 }
665 Vertex* v = *current;
Brian Salomon120e7d62019-09-11 10:29:22 -0400666 TESS_LOG("rewinding active edges from vertex %g to vertex %g\n", v->fID, dst->fID);
Stephen White3b5a3fa2017-06-06 14:51:19 -0400667 while (v != dst) {
668 v = v->fPrev;
669 for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
Chris Dalton24472af2021-01-11 20:05:00 -0700670 activeEdges->remove(e);
Stephen White3b5a3fa2017-06-06 14:51:19 -0400671 }
672 Edge* leftEdge = v->fLeftEnclosingEdge;
673 for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove) {
Chris Dalton24472af2021-01-11 20:05:00 -0700674 activeEdges->insert(e, leftEdge);
Stephen White3b5a3fa2017-06-06 14:51:19 -0400675 leftEdge = e;
Stephen Whitec03e6982020-02-06 16:32:14 -0500676 Vertex* top = e->fTop;
677 if (c.sweep_lt(top->fPoint, dst->fPoint) &&
678 ((top->fLeftEnclosingEdge && !top->fLeftEnclosingEdge->isLeftOf(e->fTop)) ||
679 (top->fRightEnclosingEdge && !top->fRightEnclosingEdge->isRightOf(e->fTop)))) {
680 dst = top;
681 }
Stephen White3b5a3fa2017-06-06 14:51:19 -0400682 }
683 }
684 *current = v;
685}
686
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700687static void rewind_if_necessary(Edge* edge, EdgeList* activeEdges, Vertex** current,
Chris Dalton811dc6a2021-01-07 16:40:32 -0700688 const Comparator& c) {
Stephen Whitec03e6982020-02-06 16:32:14 -0500689 if (!activeEdges || !current) {
690 return;
691 }
692 Vertex* top = edge->fTop;
693 Vertex* bottom = edge->fBottom;
694 if (edge->fLeft) {
695 Vertex* leftTop = edge->fLeft->fTop;
696 Vertex* leftBottom = edge->fLeft->fBottom;
697 if (c.sweep_lt(leftTop->fPoint, top->fPoint) && !edge->fLeft->isLeftOf(top)) {
698 rewind(activeEdges, current, leftTop, c);
699 } else if (c.sweep_lt(top->fPoint, leftTop->fPoint) && !edge->isRightOf(leftTop)) {
700 rewind(activeEdges, current, top, c);
701 } else if (c.sweep_lt(bottom->fPoint, leftBottom->fPoint) &&
702 !edge->fLeft->isLeftOf(bottom)) {
703 rewind(activeEdges, current, leftTop, c);
704 } else if (c.sweep_lt(leftBottom->fPoint, bottom->fPoint) && !edge->isRightOf(leftBottom)) {
705 rewind(activeEdges, current, top, c);
706 }
707 }
708 if (edge->fRight) {
709 Vertex* rightTop = edge->fRight->fTop;
710 Vertex* rightBottom = edge->fRight->fBottom;
711 if (c.sweep_lt(rightTop->fPoint, top->fPoint) && !edge->fRight->isRightOf(top)) {
712 rewind(activeEdges, current, rightTop, c);
713 } else if (c.sweep_lt(top->fPoint, rightTop->fPoint) && !edge->isLeftOf(rightTop)) {
714 rewind(activeEdges, current, top, c);
715 } else if (c.sweep_lt(bottom->fPoint, rightBottom->fPoint) &&
716 !edge->fRight->isRightOf(bottom)) {
717 rewind(activeEdges, current, rightTop, c);
718 } else if (c.sweep_lt(rightBottom->fPoint, bottom->fPoint) &&
719 !edge->isLeftOf(rightBottom)) {
720 rewind(activeEdges, current, top, c);
721 }
722 }
723}
724
Chris Dalton811dc6a2021-01-07 16:40:32 -0700725static void set_top(Edge* edge, Vertex* v, EdgeList* activeEdges, Vertex** current,
726 const Comparator& c) {
ethannicholase9709e82016-01-07 13:34:16 -0800727 remove_edge_below(edge);
728 edge->fTop = v;
729 edge->recompute();
Chris Dalton24472af2021-01-11 20:05:00 -0700730 edge->insertBelow(v, c);
Stephen Whitec03e6982020-02-06 16:32:14 -0500731 rewind_if_necessary(edge, activeEdges, current, c);
Stephen White3b5a3fa2017-06-06 14:51:19 -0400732 merge_collinear_edges(edge, activeEdges, current, c);
ethannicholase9709e82016-01-07 13:34:16 -0800733}
734
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700735static void set_bottom(Edge* edge, Vertex* v, EdgeList* activeEdges, Vertex** current,
Chris Dalton811dc6a2021-01-07 16:40:32 -0700736 const Comparator& c) {
ethannicholase9709e82016-01-07 13:34:16 -0800737 remove_edge_above(edge);
738 edge->fBottom = v;
739 edge->recompute();
Chris Dalton24472af2021-01-11 20:05:00 -0700740 edge->insertAbove(v, c);
Stephen Whitec03e6982020-02-06 16:32:14 -0500741 rewind_if_necessary(edge, activeEdges, current, c);
Stephen White3b5a3fa2017-06-06 14:51:19 -0400742 merge_collinear_edges(edge, activeEdges, current, c);
ethannicholase9709e82016-01-07 13:34:16 -0800743}
744
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700745static void merge_edges_above(Edge* edge, Edge* other, EdgeList* activeEdges, Vertex** current,
Chris Dalton811dc6a2021-01-07 16:40:32 -0700746 const Comparator& c) {
ethannicholase9709e82016-01-07 13:34:16 -0800747 if (coincident(edge->fTop->fPoint, other->fTop->fPoint)) {
Brian Salomon120e7d62019-09-11 10:29:22 -0400748 TESS_LOG("merging coincident above edges (%g, %g) -> (%g, %g)\n",
749 edge->fTop->fPoint.fX, edge->fTop->fPoint.fY,
750 edge->fBottom->fPoint.fX, edge->fBottom->fPoint.fY);
Stephen White3b5a3fa2017-06-06 14:51:19 -0400751 rewind(activeEdges, current, edge->fTop, c);
ethannicholase9709e82016-01-07 13:34:16 -0800752 other->fWinding += edge->fWinding;
Chris Dalton24472af2021-01-11 20:05:00 -0700753 edge->disconnect();
Stephen Whiteec79c392018-05-18 11:49:21 -0400754 edge->fTop = edge->fBottom = nullptr;
ethannicholase9709e82016-01-07 13:34:16 -0800755 } else if (c.sweep_lt(edge->fTop->fPoint, other->fTop->fPoint)) {
Stephen White3b5a3fa2017-06-06 14:51:19 -0400756 rewind(activeEdges, current, edge->fTop, c);
ethannicholase9709e82016-01-07 13:34:16 -0800757 other->fWinding += edge->fWinding;
Stephen White3b5a3fa2017-06-06 14:51:19 -0400758 set_bottom(edge, other->fTop, activeEdges, current, c);
ethannicholase9709e82016-01-07 13:34:16 -0800759 } else {
Stephen White3b5a3fa2017-06-06 14:51:19 -0400760 rewind(activeEdges, current, other->fTop, c);
ethannicholase9709e82016-01-07 13:34:16 -0800761 edge->fWinding += other->fWinding;
Stephen White3b5a3fa2017-06-06 14:51:19 -0400762 set_bottom(other, edge->fTop, activeEdges, current, c);
ethannicholase9709e82016-01-07 13:34:16 -0800763 }
764}
765
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700766static void merge_edges_below(Edge* edge, Edge* other, EdgeList* activeEdges, Vertex** current,
Chris Dalton811dc6a2021-01-07 16:40:32 -0700767 const Comparator& c) {
ethannicholase9709e82016-01-07 13:34:16 -0800768 if (coincident(edge->fBottom->fPoint, other->fBottom->fPoint)) {
Brian Salomon120e7d62019-09-11 10:29:22 -0400769 TESS_LOG("merging coincident below edges (%g, %g) -> (%g, %g)\n",
770 edge->fTop->fPoint.fX, edge->fTop->fPoint.fY,
771 edge->fBottom->fPoint.fX, edge->fBottom->fPoint.fY);
Stephen White3b5a3fa2017-06-06 14:51:19 -0400772 rewind(activeEdges, current, edge->fTop, c);
ethannicholase9709e82016-01-07 13:34:16 -0800773 other->fWinding += edge->fWinding;
Chris Dalton24472af2021-01-11 20:05:00 -0700774 edge->disconnect();
Stephen Whiteec79c392018-05-18 11:49:21 -0400775 edge->fTop = edge->fBottom = nullptr;
ethannicholase9709e82016-01-07 13:34:16 -0800776 } else if (c.sweep_lt(edge->fBottom->fPoint, other->fBottom->fPoint)) {
Stephen White3b5a3fa2017-06-06 14:51:19 -0400777 rewind(activeEdges, current, other->fTop, c);
ethannicholase9709e82016-01-07 13:34:16 -0800778 edge->fWinding += other->fWinding;
Stephen White3b5a3fa2017-06-06 14:51:19 -0400779 set_top(other, edge->fBottom, activeEdges, current, c);
ethannicholase9709e82016-01-07 13:34:16 -0800780 } else {
Stephen White3b5a3fa2017-06-06 14:51:19 -0400781 rewind(activeEdges, current, edge->fTop, c);
ethannicholase9709e82016-01-07 13:34:16 -0800782 other->fWinding += edge->fWinding;
Stephen White3b5a3fa2017-06-06 14:51:19 -0400783 set_top(edge, other->fBottom, activeEdges, current, c);
ethannicholase9709e82016-01-07 13:34:16 -0800784 }
785}
786
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700787static bool top_collinear(Edge* left, Edge* right) {
Stephen Whited26b4d82018-07-26 10:02:27 -0400788 if (!left || !right) {
789 return false;
790 }
791 return left->fTop->fPoint == right->fTop->fPoint ||
792 !left->isLeftOf(right->fTop) || !right->isRightOf(left->fTop);
793}
794
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700795static bool bottom_collinear(Edge* left, Edge* right) {
Stephen Whited26b4d82018-07-26 10:02:27 -0400796 if (!left || !right) {
797 return false;
798 }
799 return left->fBottom->fPoint == right->fBottom->fPoint ||
800 !left->isLeftOf(right->fBottom) || !right->isRightOf(left->fBottom);
801}
802
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700803static void merge_collinear_edges(Edge* edge, EdgeList* activeEdges, Vertex** current,
Chris Dalton811dc6a2021-01-07 16:40:32 -0700804 const Comparator& c) {
Stephen White6eca90f2017-05-25 14:47:11 -0400805 for (;;) {
Stephen Whited26b4d82018-07-26 10:02:27 -0400806 if (top_collinear(edge->fPrevEdgeAbove, edge)) {
Stephen White24289e02018-06-29 17:02:21 -0400807 merge_edges_above(edge->fPrevEdgeAbove, edge, activeEdges, current, c);
Stephen Whited26b4d82018-07-26 10:02:27 -0400808 } else if (top_collinear(edge, edge->fNextEdgeAbove)) {
Stephen White24289e02018-06-29 17:02:21 -0400809 merge_edges_above(edge->fNextEdgeAbove, edge, activeEdges, current, c);
Stephen Whited26b4d82018-07-26 10:02:27 -0400810 } else if (bottom_collinear(edge->fPrevEdgeBelow, edge)) {
Stephen White24289e02018-06-29 17:02:21 -0400811 merge_edges_below(edge->fPrevEdgeBelow, edge, activeEdges, current, c);
Stephen Whited26b4d82018-07-26 10:02:27 -0400812 } else if (bottom_collinear(edge, edge->fNextEdgeBelow)) {
Stephen White24289e02018-06-29 17:02:21 -0400813 merge_edges_below(edge->fNextEdgeBelow, edge, activeEdges, current, c);
Stephen White6eca90f2017-05-25 14:47:11 -0400814 } else {
815 break;
816 }
ethannicholase9709e82016-01-07 13:34:16 -0800817 }
Stephen Whited26b4d82018-07-26 10:02:27 -0400818 SkASSERT(!top_collinear(edge->fPrevEdgeAbove, edge));
819 SkASSERT(!top_collinear(edge, edge->fNextEdgeAbove));
820 SkASSERT(!bottom_collinear(edge->fPrevEdgeBelow, edge));
821 SkASSERT(!bottom_collinear(edge, edge->fNextEdgeBelow));
ethannicholase9709e82016-01-07 13:34:16 -0800822}
823
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700824bool GrTriangulator::splitEdge(Edge* edge, Vertex* v, EdgeList* activeEdges, Vertex** current,
Chris Dalton811dc6a2021-01-07 16:40:32 -0700825 const Comparator& c) {
Stephen Whiteec79c392018-05-18 11:49:21 -0400826 if (!edge->fTop || !edge->fBottom || v == edge->fTop || v == edge->fBottom) {
Stephen White89042d52018-06-08 12:18:22 -0400827 return false;
Stephen White0cb31672017-06-08 14:41:01 -0400828 }
Brian Salomon120e7d62019-09-11 10:29:22 -0400829 TESS_LOG("splitting edge (%g -> %g) at vertex %g (%g, %g)\n",
830 edge->fTop->fID, edge->fBottom->fID, v->fID, v->fPoint.fX, v->fPoint.fY);
Stephen White3b5a3fa2017-06-06 14:51:19 -0400831 Vertex* top;
832 Vertex* bottom;
Stephen White531a48e2018-06-01 09:49:39 -0400833 int winding = edge->fWinding;
ethannicholase9709e82016-01-07 13:34:16 -0800834 if (c.sweep_lt(v->fPoint, edge->fTop->fPoint)) {
Stephen White3b5a3fa2017-06-06 14:51:19 -0400835 top = v;
836 bottom = edge->fTop;
837 set_top(edge, v, activeEdges, current, c);
Stephen Whitee30cf802017-02-27 11:37:55 -0500838 } else if (c.sweep_lt(edge->fBottom->fPoint, v->fPoint)) {
Stephen White3b5a3fa2017-06-06 14:51:19 -0400839 top = edge->fBottom;
840 bottom = v;
841 set_bottom(edge, v, activeEdges, current, c);
ethannicholase9709e82016-01-07 13:34:16 -0800842 } else {
Stephen White3b5a3fa2017-06-06 14:51:19 -0400843 top = v;
844 bottom = edge->fBottom;
845 set_bottom(edge, v, activeEdges, current, c);
ethannicholase9709e82016-01-07 13:34:16 -0800846 }
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700847 Edge* newEdge = fAlloc.make<Edge>(top, bottom, winding, edge->fType);
Chris Dalton24472af2021-01-11 20:05:00 -0700848 newEdge->insertBelow(top, c);
849 newEdge->insertAbove(bottom, c);
Stephen White3b5a3fa2017-06-06 14:51:19 -0400850 merge_collinear_edges(newEdge, activeEdges, current, c);
Stephen White89042d52018-06-08 12:18:22 -0400851 return true;
852}
853
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700854bool GrTriangulator::intersectEdgePair(Edge* left, Edge* right, EdgeList* activeEdges,
Chris Dalton811dc6a2021-01-07 16:40:32 -0700855 Vertex** current, const Comparator& c) {
Stephen White89042d52018-06-08 12:18:22 -0400856 if (!left->fTop || !left->fBottom || !right->fTop || !right->fBottom) {
857 return false;
858 }
Stephen White1c5fd182018-07-12 15:54:05 -0400859 if (left->fTop == right->fTop || left->fBottom == right->fBottom) {
860 return false;
861 }
Stephen White89042d52018-06-08 12:18:22 -0400862 if (c.sweep_lt(left->fTop->fPoint, right->fTop->fPoint)) {
863 if (!left->isLeftOf(right->fTop)) {
Stephen White1c5fd182018-07-12 15:54:05 -0400864 rewind(activeEdges, current, right->fTop, c);
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700865 return this->splitEdge(left, right->fTop, activeEdges, current, c);
Stephen White89042d52018-06-08 12:18:22 -0400866 }
867 } else {
868 if (!right->isRightOf(left->fTop)) {
Stephen White1c5fd182018-07-12 15:54:05 -0400869 rewind(activeEdges, current, left->fTop, c);
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700870 return this->splitEdge(right, left->fTop, activeEdges, current, c);
Stephen White89042d52018-06-08 12:18:22 -0400871 }
872 }
873 if (c.sweep_lt(right->fBottom->fPoint, left->fBottom->fPoint)) {
874 if (!left->isLeftOf(right->fBottom)) {
Stephen White1c5fd182018-07-12 15:54:05 -0400875 rewind(activeEdges, current, right->fBottom, c);
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700876 return this->splitEdge(left, right->fBottom, activeEdges, current, c);
Stephen White89042d52018-06-08 12:18:22 -0400877 }
878 } else {
879 if (!right->isRightOf(left->fBottom)) {
Stephen White1c5fd182018-07-12 15:54:05 -0400880 rewind(activeEdges, current, left->fBottom, c);
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700881 return this->splitEdge(right, left->fBottom, activeEdges, current, c);
Stephen White89042d52018-06-08 12:18:22 -0400882 }
883 }
884 return false;
ethannicholase9709e82016-01-07 13:34:16 -0800885}
886
Chris Dalton7cf3add2021-01-11 18:33:28 -0700887Edge* GrTriangulator::makeConnectingEdge(Vertex* prev, Vertex* next, EdgeType type,
888 const Comparator& c, int windingScale) {
Stephen Whitee260c462017-12-19 18:09:54 -0500889 if (!prev || !next || prev->fPoint == next->fPoint) {
890 return nullptr;
891 }
Chris Dalton7cf3add2021-01-11 18:33:28 -0700892 Edge* edge = this->makeEdge(prev, next, type, c);
Chris Dalton24472af2021-01-11 20:05:00 -0700893 edge->insertBelow(edge->fTop, c);
894 edge->insertAbove(edge->fBottom, c);
Chris Dalton7cf3add2021-01-11 18:33:28 -0700895 edge->fWinding *= windingScale;
Stephen White3b5a3fa2017-06-06 14:51:19 -0400896 merge_collinear_edges(edge, nullptr, nullptr, c);
senorblancof57372d2016-08-31 10:36:19 -0700897 return edge;
898}
899
Chris Dalton811dc6a2021-01-07 16:40:32 -0700900static void merge_vertices(Vertex* src, Vertex* dst, VertexList* mesh, const Comparator& c) {
Brian Salomon120e7d62019-09-11 10:29:22 -0400901 TESS_LOG("found coincident verts at %g, %g; merging %g into %g\n",
902 src->fPoint.fX, src->fPoint.fY, src->fID, dst->fID);
Brian Osman788b9162020-02-07 10:36:46 -0500903 dst->fAlpha = std::max(src->fAlpha, dst->fAlpha);
Stephen Whitebda29c02017-03-13 15:10:13 -0400904 if (src->fPartner) {
905 src->fPartner->fPartner = dst;
906 }
Stephen White7b376942018-05-22 11:51:32 -0400907 while (Edge* edge = src->fFirstEdgeAbove) {
Stephen White3b5a3fa2017-06-06 14:51:19 -0400908 set_bottom(edge, dst, nullptr, nullptr, c);
ethannicholase9709e82016-01-07 13:34:16 -0800909 }
Stephen White7b376942018-05-22 11:51:32 -0400910 while (Edge* edge = src->fFirstEdgeBelow) {
Stephen White3b5a3fa2017-06-06 14:51:19 -0400911 set_top(edge, dst, nullptr, nullptr, c);
ethannicholase9709e82016-01-07 13:34:16 -0800912 }
Stephen Whitebf6137e2017-01-04 15:43:26 -0500913 mesh->remove(src);
Stephen Whitec4dbc372019-05-22 10:50:14 -0400914 dst->fSynthetic = true;
ethannicholase9709e82016-01-07 13:34:16 -0800915}
916
Chris Dalton7cf3add2021-01-11 18:33:28 -0700917Vertex* GrTriangulator::makeSortedVertex(const SkPoint& p, uint8_t alpha, VertexList* mesh,
918 Vertex* reference, const Comparator& c) {
Stephen White95152e12017-12-18 10:52:44 -0500919 Vertex* prevV = reference;
920 while (prevV && c.sweep_lt(p, prevV->fPoint)) {
921 prevV = prevV->fPrev;
922 }
923 Vertex* nextV = prevV ? prevV->fNext : mesh->fHead;
924 while (nextV && c.sweep_lt(nextV->fPoint, p)) {
925 prevV = nextV;
926 nextV = nextV->fNext;
927 }
928 Vertex* v;
929 if (prevV && coincident(prevV->fPoint, p)) {
930 v = prevV;
931 } else if (nextV && coincident(nextV->fPoint, p)) {
932 v = nextV;
933 } else {
Chris Dalton7cf3add2021-01-11 18:33:28 -0700934 v = fAlloc.make<Vertex>(p, alpha);
Chris Dalton5045de32021-01-07 19:09:01 -0700935#if TRIANGULATOR_LOGGING
Stephen White95152e12017-12-18 10:52:44 -0500936 if (!prevV) {
937 v->fID = mesh->fHead->fID - 1.0f;
938 } else if (!nextV) {
939 v->fID = mesh->fTail->fID + 1.0f;
940 } else {
941 v->fID = (prevV->fID + nextV->fID) * 0.5f;
942 }
943#endif
944 mesh->insert(v, prevV, nextV);
945 }
946 return v;
947}
948
Stephen White53a02982018-05-30 22:47:46 -0400949// If an edge's top and bottom points differ only by 1/2 machine epsilon in the primary
950// sort criterion, it may not be possible to split correctly, since there is no point which is
951// below the top and above the bottom. This function detects that case.
Chris Dalton811dc6a2021-01-07 16:40:32 -0700952static bool nearly_flat(const Comparator& c, Edge* edge) {
Stephen White53a02982018-05-30 22:47:46 -0400953 SkPoint diff = edge->fBottom->fPoint - edge->fTop->fPoint;
954 float primaryDiff = c.fDirection == Comparator::Direction::kHorizontal ? diff.fX : diff.fY;
Stephen White13f3d8d2018-06-22 10:19:20 -0400955 return fabs(primaryDiff) < std::numeric_limits<float>::epsilon() && primaryDiff != 0.0f;
Stephen White53a02982018-05-30 22:47:46 -0400956}
957
Chris Dalton811dc6a2021-01-07 16:40:32 -0700958static SkPoint clamp(SkPoint p, SkPoint min, SkPoint max, const Comparator& c) {
Stephen Whitee62999f2018-06-05 18:45:07 -0400959 if (c.sweep_lt(p, min)) {
960 return min;
961 } else if (c.sweep_lt(max, p)) {
962 return max;
963 } else {
964 return p;
965 }
966}
967
Chris Dalton7cf3add2021-01-11 18:33:28 -0700968void GrTriangulator::computeBisector(Edge* edge1, Edge* edge2, Vertex* v) {
Stephen Whitec4dbc372019-05-22 10:50:14 -0400969 Line line1 = edge1->fLine;
970 Line line2 = edge2->fLine;
971 line1.normalize();
972 line2.normalize();
973 double cosAngle = line1.fA * line2.fA + line1.fB * line2.fB;
974 if (cosAngle > 0.999) {
975 return;
976 }
977 line1.fC += edge1->fWinding > 0 ? -1 : 1;
978 line2.fC += edge2->fWinding > 0 ? -1 : 1;
979 SkPoint p;
980 if (line1.intersect(line2, &p)) {
Chris Dalton17ce8c52021-01-07 18:08:46 -0700981 uint8_t alpha = edge1->fType == EdgeType::kOuter ? 255 : 0;
Chris Dalton7cf3add2021-01-11 18:33:28 -0700982 v->fPartner = fAlloc.make<Vertex>(p, alpha);
Brian Salomon120e7d62019-09-11 10:29:22 -0400983 TESS_LOG("computed bisector (%g,%g) alpha %d for vertex %g\n", p.fX, p.fY, alpha, v->fID);
Stephen Whitec4dbc372019-05-22 10:50:14 -0400984 }
985}
986
Chris Dalton57ea1fc2021-01-05 13:37:44 -0700987bool GrTriangulator::checkForIntersection(Edge* left, Edge* right, EdgeList* activeEdges,
Chris Dalton811dc6a2021-01-07 16:40:32 -0700988 Vertex** current, VertexList* mesh, const Comparator& c) {
Stephen Whiteb141fcb2018-06-14 10:15:47 -0400989 if (!left || !right) {
Stephen White3b5a3fa2017-06-06 14:51:19 -0400990 return false;
ethannicholase9709e82016-01-07 13:34:16 -0800991 }
Stephen White56158ae2017-01-30 14:31:31 -0500992 SkPoint p;
993 uint8_t alpha;
Stephen Whiteb141fcb2018-06-14 10:15:47 -0400994 if (left->intersect(*right, &p, &alpha) && p.isFinite()) {
Ravi Mistrybfe95982018-05-29 18:19:07 +0000995 Vertex* v;
Brian Salomon120e7d62019-09-11 10:29:22 -0400996 TESS_LOG("found intersection, pt is %g, %g\n", p.fX, p.fY);
Stephen White3b5a3fa2017-06-06 14:51:19 -0400997 Vertex* top = *current;
998 // If the intersection point is above the current vertex, rewind to the vertex above the
999 // intersection.
Stephen White0cb31672017-06-08 14:41:01 -04001000 while (top && c.sweep_lt(p, top->fPoint)) {
Stephen White3b5a3fa2017-06-06 14:51:19 -04001001 top = top->fPrev;
1002 }
Stephen Whiteb141fcb2018-06-14 10:15:47 -04001003 if (!nearly_flat(c, left)) {
1004 p = clamp(p, left->fTop->fPoint, left->fBottom->fPoint, c);
Stephen Whitee62999f2018-06-05 18:45:07 -04001005 }
Stephen Whiteb141fcb2018-06-14 10:15:47 -04001006 if (!nearly_flat(c, right)) {
1007 p = clamp(p, right->fTop->fPoint, right->fBottom->fPoint, c);
Stephen Whitee62999f2018-06-05 18:45:07 -04001008 }
Stephen Whiteb141fcb2018-06-14 10:15:47 -04001009 if (p == left->fTop->fPoint) {
1010 v = left->fTop;
1011 } else if (p == left->fBottom->fPoint) {
1012 v = left->fBottom;
1013 } else if (p == right->fTop->fPoint) {
1014 v = right->fTop;
1015 } else if (p == right->fBottom->fPoint) {
1016 v = right->fBottom;
Ravi Mistrybfe95982018-05-29 18:19:07 +00001017 } else {
Chris Dalton7cf3add2021-01-11 18:33:28 -07001018 v = this->makeSortedVertex(p, alpha, mesh, top, c);
Stephen Whiteb141fcb2018-06-14 10:15:47 -04001019 if (left->fTop->fPartner) {
Stephen Whitec4dbc372019-05-22 10:50:14 -04001020 v->fSynthetic = true;
Chris Dalton7cf3add2021-01-11 18:33:28 -07001021 this->computeBisector(left, right, v);
Stephen Whitee260c462017-12-19 18:09:54 -05001022 }
ethannicholase9709e82016-01-07 13:34:16 -08001023 }
Stephen White0cb31672017-06-08 14:41:01 -04001024 rewind(activeEdges, current, top ? top : v, c);
Chris Dalton57ea1fc2021-01-05 13:37:44 -07001025 this->splitEdge(left, v, activeEdges, current, c);
1026 this->splitEdge(right, v, activeEdges, current, c);
Brian Osman788b9162020-02-07 10:36:46 -05001027 v->fAlpha = std::max(v->fAlpha, alpha);
Stephen White3b5a3fa2017-06-06 14:51:19 -04001028 return true;
ethannicholase9709e82016-01-07 13:34:16 -08001029 }
Chris Dalton57ea1fc2021-01-05 13:37:44 -07001030 return this->intersectEdgePair(left, right, activeEdges, current, c);
ethannicholase9709e82016-01-07 13:34:16 -08001031}
1032
Chris Dalton57ea1fc2021-01-05 13:37:44 -07001033void GrTriangulator::sanitizeContours(VertexList* contours, int contourCnt) {
Stephen White3a9aab92017-03-07 14:07:18 -05001034 for (VertexList* contour = contours; contourCnt > 0; --contourCnt, ++contour) {
1035 SkASSERT(contour->fHead);
1036 Vertex* prev = contour->fTail;
Chris Dalton854ee852021-01-05 15:12:59 -07001037 if (fRoundVerticesToQuarterPixel) {
Stephen White3a9aab92017-03-07 14:07:18 -05001038 round(&prev->fPoint);
Stephen White5926f2d2017-02-13 13:55:42 -05001039 }
Stephen White3a9aab92017-03-07 14:07:18 -05001040 for (Vertex* v = contour->fHead; v;) {
Chris Dalton854ee852021-01-05 15:12:59 -07001041 if (fRoundVerticesToQuarterPixel) {
senorblancof57372d2016-08-31 10:36:19 -07001042 round(&v->fPoint);
1043 }
Stephen White3a9aab92017-03-07 14:07:18 -05001044 Vertex* next = v->fNext;
Stephen White3de40f82018-06-28 09:36:49 -04001045 Vertex* nextWrap = next ? next : contour->fHead;
Stephen White3a9aab92017-03-07 14:07:18 -05001046 if (coincident(prev->fPoint, v->fPoint)) {
Brian Salomon120e7d62019-09-11 10:29:22 -04001047 TESS_LOG("vertex %g,%g coincident; removing\n", v->fPoint.fX, v->fPoint.fY);
Stephen White3a9aab92017-03-07 14:07:18 -05001048 contour->remove(v);
Stephen White73e7f802017-08-23 13:56:07 -04001049 } else if (!v->fPoint.isFinite()) {
Brian Salomon120e7d62019-09-11 10:29:22 -04001050 TESS_LOG("vertex %g,%g non-finite; removing\n", v->fPoint.fX, v->fPoint.fY);
Stephen White73e7f802017-08-23 13:56:07 -04001051 contour->remove(v);
Chris Dalton854ee852021-01-05 15:12:59 -07001052 } else if (fCullCollinearVertices &&
Chris Dalton6ccc0322020-01-29 11:38:16 -07001053 Line(prev->fPoint, nextWrap->fPoint).dist(v->fPoint) == 0.0) {
Brian Salomon120e7d62019-09-11 10:29:22 -04001054 TESS_LOG("vertex %g,%g collinear; removing\n", v->fPoint.fX, v->fPoint.fY);
Stephen White06768ca2018-05-25 14:50:56 -04001055 contour->remove(v);
1056 } else {
1057 prev = v;
ethannicholase9709e82016-01-07 13:34:16 -08001058 }
Stephen White3a9aab92017-03-07 14:07:18 -05001059 v = next;
ethannicholase9709e82016-01-07 13:34:16 -08001060 }
1061 }
1062}
1063
Chris Dalton811dc6a2021-01-07 16:40:32 -07001064bool GrTriangulator::mergeCoincidentVertices(VertexList* mesh, const Comparator& c) {
Stephen Whitebda29c02017-03-13 15:10:13 -04001065 if (!mesh->fHead) {
Stephen Whitee260c462017-12-19 18:09:54 -05001066 return false;
Stephen Whitebda29c02017-03-13 15:10:13 -04001067 }
Stephen Whitee260c462017-12-19 18:09:54 -05001068 bool merged = false;
1069 for (Vertex* v = mesh->fHead->fNext; v;) {
1070 Vertex* next = v->fNext;
ethannicholase9709e82016-01-07 13:34:16 -08001071 if (c.sweep_lt(v->fPoint, v->fPrev->fPoint)) {
1072 v->fPoint = v->fPrev->fPoint;
1073 }
1074 if (coincident(v->fPrev->fPoint, v->fPoint)) {
Chris Dalton57ea1fc2021-01-05 13:37:44 -07001075 merge_vertices(v, v->fPrev, mesh, c);
Stephen Whitee260c462017-12-19 18:09:54 -05001076 merged = true;
ethannicholase9709e82016-01-07 13:34:16 -08001077 }
Stephen Whitee260c462017-12-19 18:09:54 -05001078 v = next;
ethannicholase9709e82016-01-07 13:34:16 -08001079 }
Stephen Whitee260c462017-12-19 18:09:54 -05001080 return merged;
ethannicholase9709e82016-01-07 13:34:16 -08001081}
1082
1083// Stage 2: convert the contours to a mesh of edges connecting the vertices.
1084
Chris Dalton57ea1fc2021-01-05 13:37:44 -07001085void GrTriangulator::buildEdges(VertexList* contours, int contourCnt, VertexList* mesh,
Chris Dalton811dc6a2021-01-07 16:40:32 -07001086 const Comparator& c) {
Stephen White3a9aab92017-03-07 14:07:18 -05001087 for (VertexList* contour = contours; contourCnt > 0; --contourCnt, ++contour) {
1088 Vertex* prev = contour->fTail;
1089 for (Vertex* v = contour->fHead; v;) {
1090 Vertex* next = v->fNext;
Chris Dalton7cf3add2021-01-11 18:33:28 -07001091 this->makeConnectingEdge(prev, v, EdgeType::kInner, c);
Stephen White3a9aab92017-03-07 14:07:18 -05001092 mesh->append(v);
ethannicholase9709e82016-01-07 13:34:16 -08001093 prev = v;
Stephen White3a9aab92017-03-07 14:07:18 -05001094 v = next;
ethannicholase9709e82016-01-07 13:34:16 -08001095 }
1096 }
ethannicholase9709e82016-01-07 13:34:16 -08001097}
1098
Chris Dalton7cf3add2021-01-11 18:33:28 -07001099void GrAATriangulator::connectPartners(VertexList* mesh, const Comparator& c) {
Stephen Whitee260c462017-12-19 18:09:54 -05001100 for (Vertex* outer = mesh->fHead; outer; outer = outer->fNext) {
Stephen Whitebda29c02017-03-13 15:10:13 -04001101 if (Vertex* inner = outer->fPartner) {
Stephen Whitee260c462017-12-19 18:09:54 -05001102 if ((inner->fPrev || inner->fNext) && (outer->fPrev || outer->fNext)) {
1103 // Connector edges get zero winding, since they're only structural (i.e., to ensure
1104 // no 0-0-0 alpha triangles are produced), and shouldn't affect the poly winding
1105 // number.
Chris Dalton7cf3add2021-01-11 18:33:28 -07001106 this->makeConnectingEdge(outer, inner, EdgeType::kConnector, c, 0);
Stephen Whitee260c462017-12-19 18:09:54 -05001107 inner->fPartner = outer->fPartner = nullptr;
1108 }
Stephen Whitebda29c02017-03-13 15:10:13 -04001109 }
1110 }
1111}
1112
1113template <CompareFunc sweep_lt>
Chris Dalton57ea1fc2021-01-05 13:37:44 -07001114static void sorted_merge(VertexList* front, VertexList* back, VertexList* result) {
Stephen Whitebda29c02017-03-13 15:10:13 -04001115 Vertex* a = front->fHead;
1116 Vertex* b = back->fHead;
1117 while (a && b) {
1118 if (sweep_lt(a->fPoint, b->fPoint)) {
1119 front->remove(a);
1120 result->append(a);
1121 a = front->fHead;
1122 } else {
1123 back->remove(b);
1124 result->append(b);
1125 b = back->fHead;
1126 }
1127 }
1128 result->append(*front);
1129 result->append(*back);
1130}
1131
Chris Dalton811dc6a2021-01-07 16:40:32 -07001132static void sorted_merge(VertexList* front, VertexList* back, VertexList* result,
1133 const Comparator& c) {
Stephen Whitebda29c02017-03-13 15:10:13 -04001134 if (c.fDirection == Comparator::Direction::kHorizontal) {
1135 sorted_merge<sweep_lt_horiz>(front, back, result);
1136 } else {
1137 sorted_merge<sweep_lt_vert>(front, back, result);
1138 }
Chris Dalton5045de32021-01-07 19:09:01 -07001139#if TRIANGULATOR_LOGGING
Stephen White3b5a3fa2017-06-06 14:51:19 -04001140 float id = 0.0f;
1141 for (Vertex* v = result->fHead; v; v = v->fNext) {
1142 v->fID = id++;
1143 }
1144#endif
Stephen Whitebda29c02017-03-13 15:10:13 -04001145}
1146
ethannicholase9709e82016-01-07 13:34:16 -08001147// Stage 3: sort the vertices by increasing sweep direction.
1148
Stephen White16a40cb2017-02-23 11:10:01 -05001149template <CompareFunc sweep_lt>
Chris Dalton57ea1fc2021-01-05 13:37:44 -07001150static void merge_sort(VertexList* vertices) {
Stephen White16a40cb2017-02-23 11:10:01 -05001151 Vertex* slow = vertices->fHead;
1152 if (!slow) {
ethannicholase9709e82016-01-07 13:34:16 -08001153 return;
1154 }
Stephen White16a40cb2017-02-23 11:10:01 -05001155 Vertex* fast = slow->fNext;
1156 if (!fast) {
1157 return;
1158 }
1159 do {
1160 fast = fast->fNext;
1161 if (fast) {
1162 fast = fast->fNext;
1163 slow = slow->fNext;
1164 }
1165 } while (fast);
1166 VertexList front(vertices->fHead, slow);
1167 VertexList back(slow->fNext, vertices->fTail);
1168 front.fTail->fNext = back.fHead->fPrev = nullptr;
ethannicholase9709e82016-01-07 13:34:16 -08001169
Stephen White16a40cb2017-02-23 11:10:01 -05001170 merge_sort<sweep_lt>(&front);
1171 merge_sort<sweep_lt>(&back);
ethannicholase9709e82016-01-07 13:34:16 -08001172
Stephen White16a40cb2017-02-23 11:10:01 -05001173 vertices->fHead = vertices->fTail = nullptr;
Stephen Whitebda29c02017-03-13 15:10:13 -04001174 sorted_merge<sweep_lt>(&front, &back, vertices);
ethannicholase9709e82016-01-07 13:34:16 -08001175}
1176
Chris Dalton5045de32021-01-07 19:09:01 -07001177#if TRIANGULATOR_LOGGING
Chris Dalton24472af2021-01-11 20:05:00 -07001178void VertexList::dump() {
1179 for (Vertex* v = fHead; v; v = v->fNext) {
Brian Salomon120e7d62019-09-11 10:29:22 -04001180 TESS_LOG("vertex %g (%g, %g) alpha %d", v->fID, v->fPoint.fX, v->fPoint.fY, v->fAlpha);
Stephen White95152e12017-12-18 10:52:44 -05001181 if (Vertex* p = v->fPartner) {
Brian Salomon120e7d62019-09-11 10:29:22 -04001182 TESS_LOG(", partner %g (%g, %g) alpha %d\n",
1183 p->fID, p->fPoint.fX, p->fPoint.fY, p->fAlpha);
Stephen White95152e12017-12-18 10:52:44 -05001184 } else {
Brian Salomon120e7d62019-09-11 10:29:22 -04001185 TESS_LOG(", null partner\n");
Stephen White95152e12017-12-18 10:52:44 -05001186 }
1187 for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove) {
Brian Salomon120e7d62019-09-11 10:29:22 -04001188 TESS_LOG(" edge %g -> %g, winding %d\n", e->fTop->fID, e->fBottom->fID, e->fWinding);
Stephen White95152e12017-12-18 10:52:44 -05001189 }
1190 for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
Brian Salomon120e7d62019-09-11 10:29:22 -04001191 TESS_LOG(" edge %g -> %g, winding %d\n", e->fTop->fID, e->fBottom->fID, e->fWinding);
Stephen White95152e12017-12-18 10:52:44 -05001192 }
1193 }
Chris Daltond60c9192021-01-07 18:30:08 +00001194}
Chris Dalton7cf3add2021-01-11 18:33:28 -07001195#endif
Stephen White95152e12017-12-18 10:52:44 -05001196
Chris Dalton57ea1fc2021-01-05 13:37:44 -07001197static void dump_skel(const SSEdgeList& ssEdges) {
Chris Dalton5045de32021-01-07 19:09:01 -07001198#if TRIANGULATOR_LOGGING
Stephen Whitec4dbc372019-05-22 10:50:14 -04001199 for (SSEdge* edge : ssEdges) {
1200 if (edge->fEdge) {
Brian Salomon120e7d62019-09-11 10:29:22 -04001201 TESS_LOG("skel edge %g -> %g",
Stephen Whitec4dbc372019-05-22 10:50:14 -04001202 edge->fPrev->fVertex->fID,
Stephen White8a3c0592019-05-29 11:26:16 -04001203 edge->fNext->fVertex->fID);
1204 if (edge->fEdge->fTop && edge->fEdge->fBottom) {
Brian Salomon120e7d62019-09-11 10:29:22 -04001205 TESS_LOG(" (original %g -> %g)\n",
1206 edge->fEdge->fTop->fID,
1207 edge->fEdge->fBottom->fID);
Stephen White8a3c0592019-05-29 11:26:16 -04001208 } else {
Brian Salomon120e7d62019-09-11 10:29:22 -04001209 TESS_LOG("\n");
Stephen White8a3c0592019-05-29 11:26:16 -04001210 }
Stephen Whitec4dbc372019-05-22 10:50:14 -04001211 }
1212 }
1213#endif
1214}
1215
Stephen White89042d52018-06-08 12:18:22 -04001216#ifdef SK_DEBUG
Chris Dalton811dc6a2021-01-07 16:40:32 -07001217static void validate_edge_pair(Edge* left, Edge* right, const Comparator& c) {
Stephen White89042d52018-06-08 12:18:22 -04001218 if (!left || !right) {
1219 return;
1220 }
1221 if (left->fTop == right->fTop) {
1222 SkASSERT(left->isLeftOf(right->fBottom));
1223 SkASSERT(right->isRightOf(left->fBottom));
1224 } else if (c.sweep_lt(left->fTop->fPoint, right->fTop->fPoint)) {
1225 SkASSERT(left->isLeftOf(right->fTop));
1226 } else {
1227 SkASSERT(right->isRightOf(left->fTop));
1228 }
1229 if (left->fBottom == right->fBottom) {
1230 SkASSERT(left->isLeftOf(right->fTop));
1231 SkASSERT(right->isRightOf(left->fTop));
1232 } else if (c.sweep_lt(right->fBottom->fPoint, left->fBottom->fPoint)) {
1233 SkASSERT(left->isLeftOf(right->fBottom));
1234 } else {
1235 SkASSERT(right->isRightOf(left->fBottom));
1236 }
1237}
1238
Chris Dalton811dc6a2021-01-07 16:40:32 -07001239static void validate_edge_list(EdgeList* edges, const Comparator& c) {
Stephen White89042d52018-06-08 12:18:22 -04001240 Edge* left = edges->fHead;
1241 if (!left) {
1242 return;
1243 }
1244 for (Edge* right = left->fRight; right; right = right->fRight) {
1245 validate_edge_pair(left, right, c);
1246 left = right;
1247 }
1248}
1249#endif
1250
ethannicholase9709e82016-01-07 13:34:16 -08001251// Stage 4: Simplify the mesh by inserting new vertices at intersecting edges.
1252
Chris Dalton811dc6a2021-01-07 16:40:32 -07001253GrTriangulator::SimplifyResult GrTriangulator::simplify(VertexList* mesh, const Comparator& c) {
Brian Salomon120e7d62019-09-11 10:29:22 -04001254 TESS_LOG("simplifying complex polygons\n");
ethannicholase9709e82016-01-07 13:34:16 -08001255 EdgeList activeEdges;
Chris Dalton6ccc0322020-01-29 11:38:16 -07001256 auto result = SimplifyResult::kAlreadySimple;
Stephen White0cb31672017-06-08 14:41:01 -04001257 for (Vertex* v = mesh->fHead; v != nullptr; v = v->fNext) {
Chris Dalton24472af2021-01-11 20:05:00 -07001258 if (!v->isConnected()) {
ethannicholase9709e82016-01-07 13:34:16 -08001259 continue;
1260 }
Stephen White8a0bfc52017-02-21 15:24:13 -05001261 Edge* leftEnclosingEdge;
1262 Edge* rightEnclosingEdge;
ethannicholase9709e82016-01-07 13:34:16 -08001263 bool restartChecks;
1264 do {
Brian Salomon120e7d62019-09-11 10:29:22 -04001265 TESS_LOG("\nvertex %g: (%g,%g), alpha %d\n",
1266 v->fID, v->fPoint.fX, v->fPoint.fY, v->fAlpha);
ethannicholase9709e82016-01-07 13:34:16 -08001267 restartChecks = false;
1268 find_enclosing_edges(v, &activeEdges, &leftEnclosingEdge, &rightEnclosingEdge);
Stephen White3b5a3fa2017-06-06 14:51:19 -04001269 v->fLeftEnclosingEdge = leftEnclosingEdge;
1270 v->fRightEnclosingEdge = rightEnclosingEdge;
ethannicholase9709e82016-01-07 13:34:16 -08001271 if (v->fFirstEdgeBelow) {
Stephen Whitebf6137e2017-01-04 15:43:26 -05001272 for (Edge* edge = v->fFirstEdgeBelow; edge; edge = edge->fNextEdgeBelow) {
Chris Dalton57ea1fc2021-01-05 13:37:44 -07001273 if (this->checkForIntersection(
1274 leftEnclosingEdge, edge, &activeEdges, &v, mesh, c) ||
1275 this->checkForIntersection(
1276 edge, rightEnclosingEdge, &activeEdges, &v, mesh, c)) {
Chris Dalton854ee852021-01-05 15:12:59 -07001277 if (fSimpleInnerPolygons) {
Chris Dalton6ccc0322020-01-29 11:38:16 -07001278 return SimplifyResult::kAbort;
1279 }
1280 result = SimplifyResult::kFoundSelfIntersection;
ethannicholase9709e82016-01-07 13:34:16 -08001281 restartChecks = true;
1282 break;
1283 }
1284 }
1285 } else {
Chris Dalton57ea1fc2021-01-05 13:37:44 -07001286 if (this->checkForIntersection(leftEnclosingEdge, rightEnclosingEdge, &activeEdges,
1287 &v, mesh, c)) {
Chris Dalton854ee852021-01-05 15:12:59 -07001288 if (fSimpleInnerPolygons) {
Chris Dalton6ccc0322020-01-29 11:38:16 -07001289 return SimplifyResult::kAbort;
1290 }
1291 result = SimplifyResult::kFoundSelfIntersection;
ethannicholase9709e82016-01-07 13:34:16 -08001292 restartChecks = true;
1293 }
1294
1295 }
1296 } while (restartChecks);
Stephen White89042d52018-06-08 12:18:22 -04001297#ifdef SK_DEBUG
1298 validate_edge_list(&activeEdges, c);
1299#endif
ethannicholase9709e82016-01-07 13:34:16 -08001300 for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove) {
Chris Dalton24472af2021-01-11 20:05:00 -07001301 activeEdges.remove(e);
ethannicholase9709e82016-01-07 13:34:16 -08001302 }
1303 Edge* leftEdge = leftEnclosingEdge;
1304 for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
Chris Dalton24472af2021-01-11 20:05:00 -07001305 activeEdges.insert(e, leftEdge);
ethannicholase9709e82016-01-07 13:34:16 -08001306 leftEdge = e;
1307 }
ethannicholase9709e82016-01-07 13:34:16 -08001308 }
Stephen Whitee260c462017-12-19 18:09:54 -05001309 SkASSERT(!activeEdges.fHead && !activeEdges.fTail);
Chris Dalton6ccc0322020-01-29 11:38:16 -07001310 return result;
ethannicholase9709e82016-01-07 13:34:16 -08001311}
1312
1313// Stage 5: Tessellate the simplified mesh into monotone polygons.
1314
Chris Dalton93c2d812021-01-11 19:51:59 -07001315Poly* GrTriangulator::tessellate(const VertexList& vertices, const Comparator&) {
Brian Salomon120e7d62019-09-11 10:29:22 -04001316 TESS_LOG("\ntessellating simple polygons\n");
Chris Dalton6ccc0322020-01-29 11:38:16 -07001317 int maxWindMagnitude = std::numeric_limits<int>::max();
Chris Dalton854ee852021-01-05 15:12:59 -07001318 if (fSimpleInnerPolygons && !SkPathFillType_IsEvenOdd(fPath.getFillType())) {
Chris Dalton6ccc0322020-01-29 11:38:16 -07001319 maxWindMagnitude = 1;
1320 }
ethannicholase9709e82016-01-07 13:34:16 -08001321 EdgeList activeEdges;
1322 Poly* polys = nullptr;
Stephen Whitebf6137e2017-01-04 15:43:26 -05001323 for (Vertex* v = vertices.fHead; v != nullptr; v = v->fNext) {
Chris Dalton24472af2021-01-11 20:05:00 -07001324 if (!v->isConnected()) {
ethannicholase9709e82016-01-07 13:34:16 -08001325 continue;
1326 }
Chris Dalton5045de32021-01-07 19:09:01 -07001327#if TRIANGULATOR_LOGGING
Brian Salomon120e7d62019-09-11 10:29:22 -04001328 TESS_LOG("\nvertex %g: (%g,%g), alpha %d\n", v->fID, v->fPoint.fX, v->fPoint.fY, v->fAlpha);
ethannicholase9709e82016-01-07 13:34:16 -08001329#endif
Stephen White8a0bfc52017-02-21 15:24:13 -05001330 Edge* leftEnclosingEdge;
1331 Edge* rightEnclosingEdge;
ethannicholase9709e82016-01-07 13:34:16 -08001332 find_enclosing_edges(v, &activeEdges, &leftEnclosingEdge, &rightEnclosingEdge);
Stephen White8a0bfc52017-02-21 15:24:13 -05001333 Poly* leftPoly;
1334 Poly* rightPoly;
ethannicholase9709e82016-01-07 13:34:16 -08001335 if (v->fFirstEdgeAbove) {
1336 leftPoly = v->fFirstEdgeAbove->fLeftPoly;
1337 rightPoly = v->fLastEdgeAbove->fRightPoly;
1338 } else {
1339 leftPoly = leftEnclosingEdge ? leftEnclosingEdge->fRightPoly : nullptr;
1340 rightPoly = rightEnclosingEdge ? rightEnclosingEdge->fLeftPoly : nullptr;
1341 }
Chris Dalton5045de32021-01-07 19:09:01 -07001342#if TRIANGULATOR_LOGGING
Brian Salomon120e7d62019-09-11 10:29:22 -04001343 TESS_LOG("edges above:\n");
ethannicholase9709e82016-01-07 13:34:16 -08001344 for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove) {
Brian Salomon120e7d62019-09-11 10:29:22 -04001345 TESS_LOG("%g -> %g, lpoly %d, rpoly %d\n",
1346 e->fTop->fID, e->fBottom->fID,
1347 e->fLeftPoly ? e->fLeftPoly->fID : -1,
1348 e->fRightPoly ? e->fRightPoly->fID : -1);
ethannicholase9709e82016-01-07 13:34:16 -08001349 }
Brian Salomon120e7d62019-09-11 10:29:22 -04001350 TESS_LOG("edges below:\n");
ethannicholase9709e82016-01-07 13:34:16 -08001351 for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
Brian Salomon120e7d62019-09-11 10:29:22 -04001352 TESS_LOG("%g -> %g, lpoly %d, rpoly %d\n",
1353 e->fTop->fID, e->fBottom->fID,
1354 e->fLeftPoly ? e->fLeftPoly->fID : -1,
1355 e->fRightPoly ? e->fRightPoly->fID : -1);
ethannicholase9709e82016-01-07 13:34:16 -08001356 }
1357#endif
1358 if (v->fFirstEdgeAbove) {
1359 if (leftPoly) {
Chris Dalton17ce8c52021-01-07 18:08:46 -07001360 leftPoly = leftPoly->addEdge(v->fFirstEdgeAbove, kRight_Side, fAlloc);
ethannicholase9709e82016-01-07 13:34:16 -08001361 }
1362 if (rightPoly) {
Chris Dalton17ce8c52021-01-07 18:08:46 -07001363 rightPoly = rightPoly->addEdge(v->fLastEdgeAbove, kLeft_Side, fAlloc);
ethannicholase9709e82016-01-07 13:34:16 -08001364 }
1365 for (Edge* e = v->fFirstEdgeAbove; e != v->fLastEdgeAbove; e = e->fNextEdgeAbove) {
ethannicholase9709e82016-01-07 13:34:16 -08001366 Edge* rightEdge = e->fNextEdgeAbove;
Chris Dalton24472af2021-01-11 20:05:00 -07001367 activeEdges.remove(e);
Stephen White8a0bfc52017-02-21 15:24:13 -05001368 if (e->fRightPoly) {
Chris Dalton17ce8c52021-01-07 18:08:46 -07001369 e->fRightPoly->addEdge(e, kLeft_Side, fAlloc);
ethannicholase9709e82016-01-07 13:34:16 -08001370 }
Stephen White8a0bfc52017-02-21 15:24:13 -05001371 if (rightEdge->fLeftPoly && rightEdge->fLeftPoly != e->fRightPoly) {
Chris Dalton17ce8c52021-01-07 18:08:46 -07001372 rightEdge->fLeftPoly->addEdge(e, kRight_Side, fAlloc);
ethannicholase9709e82016-01-07 13:34:16 -08001373 }
1374 }
Chris Dalton24472af2021-01-11 20:05:00 -07001375 activeEdges.remove(v->fLastEdgeAbove);
ethannicholase9709e82016-01-07 13:34:16 -08001376 if (!v->fFirstEdgeBelow) {
1377 if (leftPoly && rightPoly && leftPoly != rightPoly) {
1378 SkASSERT(leftPoly->fPartner == nullptr && rightPoly->fPartner == nullptr);
1379 rightPoly->fPartner = leftPoly;
1380 leftPoly->fPartner = rightPoly;
1381 }
1382 }
1383 }
1384 if (v->fFirstEdgeBelow) {
1385 if (!v->fFirstEdgeAbove) {
senorblanco93e3fff2016-06-07 12:36:00 -07001386 if (leftPoly && rightPoly) {
senorblanco531237e2016-06-02 11:36:48 -07001387 if (leftPoly == rightPoly) {
Chris Dalton17ce8c52021-01-07 18:08:46 -07001388 if (leftPoly->fTail && leftPoly->fTail->fSide == kLeft_Side) {
Chris Dalton7cf3add2021-01-11 18:33:28 -07001389 leftPoly = this->makePoly(&polys, leftPoly->lastVertex(),
1390 leftPoly->fWinding);
senorblanco531237e2016-06-02 11:36:48 -07001391 leftEnclosingEdge->fRightPoly = leftPoly;
1392 } else {
Chris Dalton7cf3add2021-01-11 18:33:28 -07001393 rightPoly = this->makePoly(&polys, rightPoly->lastVertex(),
1394 rightPoly->fWinding);
senorblanco531237e2016-06-02 11:36:48 -07001395 rightEnclosingEdge->fLeftPoly = rightPoly;
1396 }
ethannicholase9709e82016-01-07 13:34:16 -08001397 }
Chris Daltond60c9192021-01-07 18:30:08 +00001398 Edge* join = fAlloc.make<Edge>(leftPoly->lastVertex(), v, 1,
Chris Dalton17ce8c52021-01-07 18:08:46 -07001399 EdgeType::kInner);
1400 leftPoly = leftPoly->addEdge(join, kRight_Side, fAlloc);
1401 rightPoly = rightPoly->addEdge(join, kLeft_Side, fAlloc);
ethannicholase9709e82016-01-07 13:34:16 -08001402 }
1403 }
1404 Edge* leftEdge = v->fFirstEdgeBelow;
1405 leftEdge->fLeftPoly = leftPoly;
Chris Dalton24472af2021-01-11 20:05:00 -07001406 activeEdges.insert(leftEdge, leftEnclosingEdge);
ethannicholase9709e82016-01-07 13:34:16 -08001407 for (Edge* rightEdge = leftEdge->fNextEdgeBelow; rightEdge;
1408 rightEdge = rightEdge->fNextEdgeBelow) {
Chris Dalton24472af2021-01-11 20:05:00 -07001409 activeEdges.insert(rightEdge, leftEdge);
ethannicholase9709e82016-01-07 13:34:16 -08001410 int winding = leftEdge->fLeftPoly ? leftEdge->fLeftPoly->fWinding : 0;
1411 winding += leftEdge->fWinding;
1412 if (winding != 0) {
Chris Dalton6ccc0322020-01-29 11:38:16 -07001413 if (abs(winding) > maxWindMagnitude) {
1414 return nullptr; // We can't have weighted wind in kSimpleInnerPolygons mode
1415 }
Chris Dalton7cf3add2021-01-11 18:33:28 -07001416 Poly* poly = this->makePoly(&polys, v, winding);
ethannicholase9709e82016-01-07 13:34:16 -08001417 leftEdge->fRightPoly = rightEdge->fLeftPoly = poly;
1418 }
1419 leftEdge = rightEdge;
1420 }
1421 v->fLastEdgeBelow->fRightPoly = rightPoly;
1422 }
Chris Dalton5045de32021-01-07 19:09:01 -07001423#if TRIANGULATOR_LOGGING
Brian Salomon120e7d62019-09-11 10:29:22 -04001424 TESS_LOG("\nactive edges:\n");
ethannicholase9709e82016-01-07 13:34:16 -08001425 for (Edge* e = activeEdges.fHead; e != nullptr; e = e->fRight) {
Brian Salomon120e7d62019-09-11 10:29:22 -04001426 TESS_LOG("%g -> %g, lpoly %d, rpoly %d\n",
1427 e->fTop->fID, e->fBottom->fID,
1428 e->fLeftPoly ? e->fLeftPoly->fID : -1,
1429 e->fRightPoly ? e->fRightPoly->fID : -1);
ethannicholase9709e82016-01-07 13:34:16 -08001430 }
1431#endif
1432 }
1433 return polys;
1434}
1435
Chris Dalton7cf3add2021-01-11 18:33:28 -07001436void GrAATriangulator::removeNonBoundaryEdges(const VertexList& mesh) {
Brian Salomon120e7d62019-09-11 10:29:22 -04001437 TESS_LOG("removing non-boundary edges\n");
Stephen White49789062017-02-21 10:35:49 -05001438 EdgeList activeEdges;
Stephen Whitebf6137e2017-01-04 15:43:26 -05001439 for (Vertex* v = mesh.fHead; v != nullptr; v = v->fNext) {
Chris Dalton24472af2021-01-11 20:05:00 -07001440 if (!v->isConnected()) {
Stephen White49789062017-02-21 10:35:49 -05001441 continue;
1442 }
1443 Edge* leftEnclosingEdge;
1444 Edge* rightEnclosingEdge;
1445 find_enclosing_edges(v, &activeEdges, &leftEnclosingEdge, &rightEnclosingEdge);
1446 bool prevFilled = leftEnclosingEdge &&
Chris Dalton7cf3add2021-01-11 18:33:28 -07001447 apply_fill_type(fPath.getFillType(), leftEnclosingEdge->fWinding);
Stephen White49789062017-02-21 10:35:49 -05001448 for (Edge* e = v->fFirstEdgeAbove; e;) {
1449 Edge* next = e->fNextEdgeAbove;
Chris Dalton24472af2021-01-11 20:05:00 -07001450 activeEdges.remove(e);
Chris Dalton7cf3add2021-01-11 18:33:28 -07001451 bool filled = apply_fill_type(fPath.getFillType(), e->fWinding);
Stephen White49789062017-02-21 10:35:49 -05001452 if (filled == prevFilled) {
Chris Dalton24472af2021-01-11 20:05:00 -07001453 e->disconnect();
senorblancof57372d2016-08-31 10:36:19 -07001454 }
Stephen White49789062017-02-21 10:35:49 -05001455 prevFilled = filled;
senorblancof57372d2016-08-31 10:36:19 -07001456 e = next;
1457 }
Stephen White49789062017-02-21 10:35:49 -05001458 Edge* prev = leftEnclosingEdge;
1459 for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
1460 if (prev) {
1461 e->fWinding += prev->fWinding;
1462 }
Chris Dalton24472af2021-01-11 20:05:00 -07001463 activeEdges.insert(e, prev);
Stephen White49789062017-02-21 10:35:49 -05001464 prev = e;
1465 }
senorblancof57372d2016-08-31 10:36:19 -07001466 }
senorblancof57372d2016-08-31 10:36:19 -07001467}
1468
Stephen White66412122017-03-01 11:48:27 -05001469// Note: this is the normal to the edge, but not necessarily unit length.
Chris Dalton57ea1fc2021-01-05 13:37:44 -07001470static void get_edge_normal(const Edge* e, SkVector* normal) {
Stephen Whitee260c462017-12-19 18:09:54 -05001471 normal->set(SkDoubleToScalar(e->fLine.fA),
1472 SkDoubleToScalar(e->fLine.fB));
senorblancof57372d2016-08-31 10:36:19 -07001473}
1474
1475// Stage 5c: detect and remove "pointy" vertices whose edge normals point in opposite directions
1476// and whose adjacent vertices are less than a quarter pixel from an edge. These are guaranteed to
1477// invert on stroking.
1478
Chris Dalton7cf3add2021-01-11 18:33:28 -07001479void GrAATriangulator::simplifyBoundary(EdgeList* boundary, const Comparator& c) {
senorblancof57372d2016-08-31 10:36:19 -07001480 Edge* prevEdge = boundary->fTail;
1481 SkVector prevNormal;
1482 get_edge_normal(prevEdge, &prevNormal);
1483 for (Edge* e = boundary->fHead; e != nullptr;) {
1484 Vertex* prev = prevEdge->fWinding == 1 ? prevEdge->fTop : prevEdge->fBottom;
1485 Vertex* next = e->fWinding == 1 ? e->fBottom : e->fTop;
Stephen Whitecfe12642018-09-26 17:25:59 -04001486 double distPrev = e->dist(prev->fPoint);
1487 double distNext = prevEdge->dist(next->fPoint);
senorblancof57372d2016-08-31 10:36:19 -07001488 SkVector normal;
1489 get_edge_normal(e, &normal);
Stephen Whitecfe12642018-09-26 17:25:59 -04001490 constexpr double kQuarterPixelSq = 0.25f * 0.25f;
Stephen Whitec4dbc372019-05-22 10:50:14 -04001491 if (prev == next) {
Chris Dalton24472af2021-01-11 20:05:00 -07001492 boundary->remove(prevEdge);
1493 boundary->remove(e);
Stephen Whitec4dbc372019-05-22 10:50:14 -04001494 prevEdge = boundary->fTail;
1495 e = boundary->fHead;
1496 if (prevEdge) {
1497 get_edge_normal(prevEdge, &prevNormal);
1498 }
1499 } else if (prevNormal.dot(normal) < 0.0 &&
Stephen Whitecfe12642018-09-26 17:25:59 -04001500 (distPrev * distPrev <= kQuarterPixelSq || distNext * distNext <= kQuarterPixelSq)) {
Chris Dalton7cf3add2021-01-11 18:33:28 -07001501 Edge* join = this->makeEdge(prev, next, EdgeType::kInner, c);
Stephen Whitee260c462017-12-19 18:09:54 -05001502 if (prev->fPoint != next->fPoint) {
1503 join->fLine.normalize();
1504 join->fLine = join->fLine * join->fWinding;
1505 }
Chris Dalton24472af2021-01-11 20:05:00 -07001506 boundary->insert(join, e);
1507 boundary->remove(prevEdge);
1508 boundary->remove(e);
senorblancof57372d2016-08-31 10:36:19 -07001509 if (join->fLeft && join->fRight) {
1510 prevEdge = join->fLeft;
1511 e = join;
1512 } else {
1513 prevEdge = boundary->fTail;
1514 e = boundary->fHead; // join->fLeft ? join->fLeft : join;
1515 }
1516 get_edge_normal(prevEdge, &prevNormal);
1517 } else {
1518 prevEdge = e;
1519 prevNormal = normal;
1520 e = e->fRight;
1521 }
1522 }
1523}
1524
Chris Dalton7cf3add2021-01-11 18:33:28 -07001525void GrAATriangulator::connectSSEdge(Vertex* v, Vertex* dest, const Comparator& c) {
Stephen Whitec4dbc372019-05-22 10:50:14 -04001526 if (v == dest) {
1527 return;
Stephen Whitee260c462017-12-19 18:09:54 -05001528 }
Brian Salomon120e7d62019-09-11 10:29:22 -04001529 TESS_LOG("ss_connecting vertex %g to vertex %g\n", v->fID, dest->fID);
Stephen Whitec4dbc372019-05-22 10:50:14 -04001530 if (v->fSynthetic) {
Chris Dalton7cf3add2021-01-11 18:33:28 -07001531 this->makeConnectingEdge(v, dest, EdgeType::kConnector, c, 0);
Stephen Whitec4dbc372019-05-22 10:50:14 -04001532 } else if (v->fPartner) {
Brian Salomon120e7d62019-09-11 10:29:22 -04001533 TESS_LOG("setting %g's partner to %g ", v->fPartner->fID, dest->fID);
1534 TESS_LOG("and %g's partner to null\n", v->fID);
Stephen Whitec4dbc372019-05-22 10:50:14 -04001535 v->fPartner->fPartner = dest;
1536 v->fPartner = nullptr;
Stephen Whitee260c462017-12-19 18:09:54 -05001537 }
1538}
1539
Chris Dalton7cf3add2021-01-11 18:33:28 -07001540void GrAATriangulator::Event::apply(VertexList* mesh, const Comparator& c, EventList* events,
1541 GrAATriangulator* triangulator) {
Stephen Whitec4dbc372019-05-22 10:50:14 -04001542 if (!fEdge) {
Stephen Whitee260c462017-12-19 18:09:54 -05001543 return;
1544 }
Stephen Whitec4dbc372019-05-22 10:50:14 -04001545 Vertex* prev = fEdge->fPrev->fVertex;
1546 Vertex* next = fEdge->fNext->fVertex;
1547 SSEdge* prevEdge = fEdge->fPrev->fPrev;
1548 SSEdge* nextEdge = fEdge->fNext->fNext;
1549 if (!prevEdge || !nextEdge || !prevEdge->fEdge || !nextEdge->fEdge) {
1550 return;
Stephen White77169c82018-06-05 09:15:59 -04001551 }
Chris Dalton7cf3add2021-01-11 18:33:28 -07001552 Vertex* dest = triangulator->makeSortedVertex(fPoint, fAlpha, mesh, prev, c);
Stephen Whitec4dbc372019-05-22 10:50:14 -04001553 dest->fSynthetic = true;
Chris Dalton7cf3add2021-01-11 18:33:28 -07001554 SSVertex* ssv = triangulator->fAlloc.make<SSVertex>(dest);
Brian Salomon120e7d62019-09-11 10:29:22 -04001555 TESS_LOG("collapsing %g, %g (original edge %g -> %g) to %g (%g, %g) alpha %d\n",
1556 prev->fID, next->fID, fEdge->fEdge->fTop->fID, fEdge->fEdge->fBottom->fID, dest->fID,
1557 fPoint.fX, fPoint.fY, fAlpha);
Stephen Whitec4dbc372019-05-22 10:50:14 -04001558 fEdge->fEdge = nullptr;
Stephen Whitee260c462017-12-19 18:09:54 -05001559
Chris Dalton7cf3add2021-01-11 18:33:28 -07001560 triangulator->connectSSEdge(prev, dest, c);
1561 triangulator->connectSSEdge(next, dest, c);
Stephen Whitee260c462017-12-19 18:09:54 -05001562
Stephen Whitec4dbc372019-05-22 10:50:14 -04001563 prevEdge->fNext = nextEdge->fPrev = ssv;
1564 ssv->fPrev = prevEdge;
1565 ssv->fNext = nextEdge;
1566 if (!prevEdge->fEdge || !nextEdge->fEdge) {
1567 return;
1568 }
1569 if (prevEdge->fEvent) {
1570 prevEdge->fEvent->fEdge = nullptr;
1571 }
1572 if (nextEdge->fEvent) {
1573 nextEdge->fEvent->fEdge = nullptr;
1574 }
1575 if (prevEdge->fPrev == nextEdge->fNext) {
Chris Dalton7cf3add2021-01-11 18:33:28 -07001576 triangulator->connectSSEdge(prevEdge->fPrev->fVertex, dest, c);
Stephen Whitec4dbc372019-05-22 10:50:14 -04001577 prevEdge->fEdge = nextEdge->fEdge = nullptr;
1578 } else {
Chris Dalton7cf3add2021-01-11 18:33:28 -07001579 triangulator->computeBisector(prevEdge->fEdge, nextEdge->fEdge, dest);
Stephen Whitec4dbc372019-05-22 10:50:14 -04001580 SkASSERT(prevEdge != fEdge && nextEdge != fEdge);
1581 if (dest->fPartner) {
Chris Dalton7cf3add2021-01-11 18:33:28 -07001582 triangulator->makeEvent(prevEdge, events);
1583 triangulator->makeEvent(nextEdge, events);
Stephen Whitec4dbc372019-05-22 10:50:14 -04001584 } else {
Chris Dalton7cf3add2021-01-11 18:33:28 -07001585 triangulator->makeEvent(prevEdge, prevEdge->fPrev->fVertex, nextEdge, dest, events, c);
1586 triangulator->makeEvent(nextEdge, nextEdge->fNext->fVertex, prevEdge, dest, events, c);
Stephen Whitec4dbc372019-05-22 10:50:14 -04001587 }
1588 }
Stephen Whitee260c462017-12-19 18:09:54 -05001589}
1590
Chris Dalton57ea1fc2021-01-05 13:37:44 -07001591static bool is_overlap_edge(Edge* e) {
Chris Dalton17ce8c52021-01-07 18:08:46 -07001592 if (e->fType == EdgeType::kOuter) {
Stephen Whitee260c462017-12-19 18:09:54 -05001593 return e->fWinding != 0 && e->fWinding != 1;
Chris Dalton17ce8c52021-01-07 18:08:46 -07001594 } else if (e->fType == EdgeType::kInner) {
Stephen Whitee260c462017-12-19 18:09:54 -05001595 return e->fWinding != 0 && e->fWinding != -2;
1596 } else {
1597 return false;
1598 }
1599}
1600
1601// This is a stripped-down version of tessellate() which computes edges which
1602// join two filled regions, which represent overlap regions, and collapses them.
Chris Dalton7cf3add2021-01-11 18:33:28 -07001603bool GrAATriangulator::collapseOverlapRegions(VertexList* mesh, const Comparator& c,
1604 EventComparator comp) {
Brian Salomon120e7d62019-09-11 10:29:22 -04001605 TESS_LOG("\nfinding overlap regions\n");
Stephen Whitee260c462017-12-19 18:09:54 -05001606 EdgeList activeEdges;
Stephen Whitec4dbc372019-05-22 10:50:14 -04001607 EventList events(comp);
1608 SSVertexMap ssVertices;
1609 SSEdgeList ssEdges;
Stephen Whitee260c462017-12-19 18:09:54 -05001610 for (Vertex* v = mesh->fHead; v != nullptr; v = v->fNext) {
Chris Dalton24472af2021-01-11 20:05:00 -07001611 if (!v->isConnected()) {
Stephen Whitee260c462017-12-19 18:09:54 -05001612 continue;
1613 }
1614 Edge* leftEnclosingEdge;
1615 Edge* rightEnclosingEdge;
1616 find_enclosing_edges(v, &activeEdges, &leftEnclosingEdge, &rightEnclosingEdge);
Stephen Whitec4dbc372019-05-22 10:50:14 -04001617 for (Edge* e = v->fLastEdgeAbove; e && e != leftEnclosingEdge;) {
Stephen Whitee260c462017-12-19 18:09:54 -05001618 Edge* prev = e->fPrevEdgeAbove ? e->fPrevEdgeAbove : leftEnclosingEdge;
Chris Dalton24472af2021-01-11 20:05:00 -07001619 activeEdges.remove(e);
Stephen Whitec4dbc372019-05-22 10:50:14 -04001620 bool leftOverlap = prev && is_overlap_edge(prev);
1621 bool rightOverlap = is_overlap_edge(e);
Chris Dalton17ce8c52021-01-07 18:08:46 -07001622 bool isOuterBoundary = e->fType == EdgeType::kOuter &&
Stephen Whitec4dbc372019-05-22 10:50:14 -04001623 (!prev || prev->fWinding == 0 || e->fWinding == 0);
Stephen Whitee260c462017-12-19 18:09:54 -05001624 if (prev) {
1625 e->fWinding -= prev->fWinding;
1626 }
Stephen Whitec4dbc372019-05-22 10:50:14 -04001627 if (leftOverlap && rightOverlap) {
Brian Salomon120e7d62019-09-11 10:29:22 -04001628 TESS_LOG("found interior overlap edge %g -> %g, disconnecting\n",
1629 e->fTop->fID, e->fBottom->fID);
Chris Dalton24472af2021-01-11 20:05:00 -07001630 e->disconnect();
Stephen Whitec4dbc372019-05-22 10:50:14 -04001631 } else if (leftOverlap || rightOverlap) {
Brian Salomon120e7d62019-09-11 10:29:22 -04001632 TESS_LOG("found overlap edge %g -> %g%s\n",
1633 e->fTop->fID, e->fBottom->fID,
1634 isOuterBoundary ? ", is outer boundary" : "");
Stephen Whitec4dbc372019-05-22 10:50:14 -04001635 Vertex* prevVertex = e->fWinding < 0 ? e->fBottom : e->fTop;
1636 Vertex* nextVertex = e->fWinding < 0 ? e->fTop : e->fBottom;
1637 SSVertex* ssPrev = ssVertices[prevVertex];
1638 if (!ssPrev) {
Chris Dalton7cf3add2021-01-11 18:33:28 -07001639 ssPrev = ssVertices[prevVertex] = fAlloc.make<SSVertex>(prevVertex);
Stephen Whitec4dbc372019-05-22 10:50:14 -04001640 }
1641 SSVertex* ssNext = ssVertices[nextVertex];
1642 if (!ssNext) {
Chris Dalton7cf3add2021-01-11 18:33:28 -07001643 ssNext = ssVertices[nextVertex] = fAlloc.make<SSVertex>(nextVertex);
Stephen Whitec4dbc372019-05-22 10:50:14 -04001644 }
Chris Dalton7cf3add2021-01-11 18:33:28 -07001645 SSEdge* ssEdge = fAlloc.make<SSEdge>(e, ssPrev, ssNext);
Stephen Whitec4dbc372019-05-22 10:50:14 -04001646 ssEdges.push_back(ssEdge);
1647// SkASSERT(!ssPrev->fNext && !ssNext->fPrev);
1648 ssPrev->fNext = ssNext->fPrev = ssEdge;
Chris Dalton7cf3add2021-01-11 18:33:28 -07001649 this->makeEvent(ssEdge, &events);
Stephen Whitec4dbc372019-05-22 10:50:14 -04001650 if (!isOuterBoundary) {
Chris Dalton24472af2021-01-11 20:05:00 -07001651 e->disconnect();
Stephen Whitec4dbc372019-05-22 10:50:14 -04001652 }
1653 }
1654 e = prev;
Stephen Whitee260c462017-12-19 18:09:54 -05001655 }
1656 Edge* prev = leftEnclosingEdge;
1657 for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
1658 if (prev) {
1659 e->fWinding += prev->fWinding;
Stephen Whitee260c462017-12-19 18:09:54 -05001660 }
Chris Dalton24472af2021-01-11 20:05:00 -07001661 activeEdges.insert(e, prev);
Stephen Whitee260c462017-12-19 18:09:54 -05001662 prev = e;
1663 }
1664 }
Stephen Whitec4dbc372019-05-22 10:50:14 -04001665 bool complex = events.size() > 0;
1666
Brian Salomon120e7d62019-09-11 10:29:22 -04001667 TESS_LOG("\ncollapsing overlap regions\n");
1668 TESS_LOG("skeleton before:\n");
Stephen White8a3c0592019-05-29 11:26:16 -04001669 dump_skel(ssEdges);
Stephen Whitec4dbc372019-05-22 10:50:14 -04001670 while (events.size() > 0) {
1671 Event* event = events.top();
Stephen Whitee260c462017-12-19 18:09:54 -05001672 events.pop();
Chris Dalton7cf3add2021-01-11 18:33:28 -07001673 event->apply(mesh, c, &events, this);
Stephen Whitee260c462017-12-19 18:09:54 -05001674 }
Brian Salomon120e7d62019-09-11 10:29:22 -04001675 TESS_LOG("skeleton after:\n");
Stephen Whitec4dbc372019-05-22 10:50:14 -04001676 dump_skel(ssEdges);
1677 for (SSEdge* edge : ssEdges) {
1678 if (Edge* e = edge->fEdge) {
Chris Dalton7cf3add2021-01-11 18:33:28 -07001679 this->makeConnectingEdge(edge->fPrev->fVertex, edge->fNext->fVertex, e->fType, c, 0);
Stephen Whitec4dbc372019-05-22 10:50:14 -04001680 }
1681 }
1682 return complex;
Stephen Whitee260c462017-12-19 18:09:54 -05001683}
1684
Chris Dalton811dc6a2021-01-07 16:40:32 -07001685static bool inversion(Vertex* prev, Vertex* next, Edge* origEdge, const Comparator& c) {
Stephen Whitee260c462017-12-19 18:09:54 -05001686 if (!prev || !next) {
1687 return true;
1688 }
1689 int winding = c.sweep_lt(prev->fPoint, next->fPoint) ? 1 : -1;
1690 return winding != origEdge->fWinding;
1691}
Stephen White92eba8a2017-02-06 09:50:27 -05001692
senorblancof57372d2016-08-31 10:36:19 -07001693// Stage 5d: Displace edges by half a pixel inward and outward along their normals. Intersect to
1694// find new vertices, and set zero alpha on the exterior and one alpha on the interior. Build a
1695// new antialiased mesh from those vertices.
1696
Chris Dalton7cf3add2021-01-11 18:33:28 -07001697void GrAATriangulator::strokeBoundary(EdgeList* boundary, VertexList* innerMesh,
Chris Dalton93c2d812021-01-11 19:51:59 -07001698 const Comparator& c) {
Brian Salomon120e7d62019-09-11 10:29:22 -04001699 TESS_LOG("\nstroking boundary\n");
Stephen Whitee260c462017-12-19 18:09:54 -05001700 // A boundary with fewer than 3 edges is degenerate.
1701 if (!boundary->fHead || !boundary->fHead->fRight || !boundary->fHead->fRight->fRight) {
1702 return;
1703 }
1704 Edge* prevEdge = boundary->fTail;
1705 Vertex* prevV = prevEdge->fWinding > 0 ? prevEdge->fTop : prevEdge->fBottom;
1706 SkVector prevNormal;
1707 get_edge_normal(prevEdge, &prevNormal);
1708 double radius = 0.5;
1709 Line prevInner(prevEdge->fLine);
1710 prevInner.fC -= radius;
1711 Line prevOuter(prevEdge->fLine);
1712 prevOuter.fC += radius;
1713 VertexList innerVertices;
1714 VertexList outerVertices;
1715 bool innerInversion = true;
1716 bool outerInversion = true;
1717 for (Edge* e = boundary->fHead; e != nullptr; e = e->fRight) {
1718 Vertex* v = e->fWinding > 0 ? e->fTop : e->fBottom;
1719 SkVector normal;
1720 get_edge_normal(e, &normal);
1721 Line inner(e->fLine);
1722 inner.fC -= radius;
1723 Line outer(e->fLine);
1724 outer.fC += radius;
1725 SkPoint innerPoint, outerPoint;
Brian Salomon120e7d62019-09-11 10:29:22 -04001726 TESS_LOG("stroking vertex %g (%g, %g)\n", v->fID, v->fPoint.fX, v->fPoint.fY);
Stephen Whitee260c462017-12-19 18:09:54 -05001727 if (!prevEdge->fLine.nearParallel(e->fLine) && prevInner.intersect(inner, &innerPoint) &&
1728 prevOuter.intersect(outer, &outerPoint)) {
1729 float cosAngle = normal.dot(prevNormal);
1730 if (cosAngle < -kCosMiterAngle) {
1731 Vertex* nextV = e->fWinding > 0 ? e->fBottom : e->fTop;
1732
1733 // This is a pointy vertex whose angle is smaller than the threshold; miter it.
1734 Line bisector(innerPoint, outerPoint);
1735 Line tangent(v->fPoint, v->fPoint + SkPoint::Make(bisector.fA, bisector.fB));
1736 if (tangent.fA == 0 && tangent.fB == 0) {
1737 continue;
1738 }
1739 tangent.normalize();
1740 Line innerTangent(tangent);
1741 Line outerTangent(tangent);
1742 innerTangent.fC -= 0.5;
1743 outerTangent.fC += 0.5;
1744 SkPoint innerPoint1, innerPoint2, outerPoint1, outerPoint2;
1745 if (prevNormal.cross(normal) > 0) {
1746 // Miter inner points
1747 if (!innerTangent.intersect(prevInner, &innerPoint1) ||
1748 !innerTangent.intersect(inner, &innerPoint2) ||
1749 !outerTangent.intersect(bisector, &outerPoint)) {
Stephen Whitef470b7e2018-01-04 16:45:51 -05001750 continue;
Stephen Whitee260c462017-12-19 18:09:54 -05001751 }
1752 Line prevTangent(prevV->fPoint,
1753 prevV->fPoint + SkVector::Make(prevOuter.fA, prevOuter.fB));
1754 Line nextTangent(nextV->fPoint,
1755 nextV->fPoint + SkVector::Make(outer.fA, outer.fB));
Stephen Whitee260c462017-12-19 18:09:54 -05001756 if (prevTangent.dist(outerPoint) > 0) {
Stephen White4f34fca2018-01-11 16:14:04 -05001757 bisector.intersect(prevTangent, &outerPoint);
Stephen Whitee260c462017-12-19 18:09:54 -05001758 }
1759 if (nextTangent.dist(outerPoint) < 0) {
Stephen White4f34fca2018-01-11 16:14:04 -05001760 bisector.intersect(nextTangent, &outerPoint);
Stephen Whitee260c462017-12-19 18:09:54 -05001761 }
1762 outerPoint1 = outerPoint2 = outerPoint;
1763 } else {
1764 // Miter outer points
1765 if (!outerTangent.intersect(prevOuter, &outerPoint1) ||
1766 !outerTangent.intersect(outer, &outerPoint2)) {
Stephen Whitef470b7e2018-01-04 16:45:51 -05001767 continue;
Stephen Whitee260c462017-12-19 18:09:54 -05001768 }
1769 Line prevTangent(prevV->fPoint,
1770 prevV->fPoint + SkVector::Make(prevInner.fA, prevInner.fB));
1771 Line nextTangent(nextV->fPoint,
1772 nextV->fPoint + SkVector::Make(inner.fA, inner.fB));
Stephen Whitee260c462017-12-19 18:09:54 -05001773 if (prevTangent.dist(innerPoint) > 0) {
Stephen White4f34fca2018-01-11 16:14:04 -05001774 bisector.intersect(prevTangent, &innerPoint);
Stephen Whitee260c462017-12-19 18:09:54 -05001775 }
1776 if (nextTangent.dist(innerPoint) < 0) {
Stephen White4f34fca2018-01-11 16:14:04 -05001777 bisector.intersect(nextTangent, &innerPoint);
Stephen Whitee260c462017-12-19 18:09:54 -05001778 }
1779 innerPoint1 = innerPoint2 = innerPoint;
1780 }
Stephen Whiteea495232018-04-03 11:28:15 -04001781 if (!innerPoint1.isFinite() || !innerPoint2.isFinite() ||
1782 !outerPoint1.isFinite() || !outerPoint2.isFinite()) {
1783 continue;
1784 }
Brian Salomon120e7d62019-09-11 10:29:22 -04001785 TESS_LOG("inner (%g, %g), (%g, %g), ",
1786 innerPoint1.fX, innerPoint1.fY, innerPoint2.fX, innerPoint2.fY);
1787 TESS_LOG("outer (%g, %g), (%g, %g)\n",
1788 outerPoint1.fX, outerPoint1.fY, outerPoint2.fX, outerPoint2.fY);
Chris Dalton7cf3add2021-01-11 18:33:28 -07001789 Vertex* innerVertex1 = fAlloc.make<Vertex>(innerPoint1, 255);
1790 Vertex* innerVertex2 = fAlloc.make<Vertex>(innerPoint2, 255);
1791 Vertex* outerVertex1 = fAlloc.make<Vertex>(outerPoint1, 0);
1792 Vertex* outerVertex2 = fAlloc.make<Vertex>(outerPoint2, 0);
Stephen Whitee260c462017-12-19 18:09:54 -05001793 innerVertex1->fPartner = outerVertex1;
1794 innerVertex2->fPartner = outerVertex2;
1795 outerVertex1->fPartner = innerVertex1;
1796 outerVertex2->fPartner = innerVertex2;
1797 if (!inversion(innerVertices.fTail, innerVertex1, prevEdge, c)) {
1798 innerInversion = false;
1799 }
1800 if (!inversion(outerVertices.fTail, outerVertex1, prevEdge, c)) {
1801 outerInversion = false;
1802 }
1803 innerVertices.append(innerVertex1);
1804 innerVertices.append(innerVertex2);
1805 outerVertices.append(outerVertex1);
1806 outerVertices.append(outerVertex2);
1807 } else {
Brian Salomon120e7d62019-09-11 10:29:22 -04001808 TESS_LOG("inner (%g, %g), ", innerPoint.fX, innerPoint.fY);
1809 TESS_LOG("outer (%g, %g)\n", outerPoint.fX, outerPoint.fY);
Chris Dalton7cf3add2021-01-11 18:33:28 -07001810 Vertex* innerVertex = fAlloc.make<Vertex>(innerPoint, 255);
1811 Vertex* outerVertex = fAlloc.make<Vertex>(outerPoint, 0);
Stephen Whitee260c462017-12-19 18:09:54 -05001812 innerVertex->fPartner = outerVertex;
1813 outerVertex->fPartner = innerVertex;
1814 if (!inversion(innerVertices.fTail, innerVertex, prevEdge, c)) {
1815 innerInversion = false;
1816 }
1817 if (!inversion(outerVertices.fTail, outerVertex, prevEdge, c)) {
1818 outerInversion = false;
1819 }
1820 innerVertices.append(innerVertex);
1821 outerVertices.append(outerVertex);
1822 }
1823 }
1824 prevInner = inner;
1825 prevOuter = outer;
1826 prevV = v;
1827 prevEdge = e;
1828 prevNormal = normal;
1829 }
1830 if (!inversion(innerVertices.fTail, innerVertices.fHead, prevEdge, c)) {
1831 innerInversion = false;
1832 }
1833 if (!inversion(outerVertices.fTail, outerVertices.fHead, prevEdge, c)) {
1834 outerInversion = false;
1835 }
1836 // Outer edges get 1 winding, and inner edges get -2 winding. This ensures that the interior
1837 // is always filled (1 + -2 = -1 for normal cases, 1 + 2 = 3 for thin features where the
1838 // interior inverts).
1839 // For total inversion cases, the shape has now reversed handedness, so invert the winding
Chris Dalton7cf3add2021-01-11 18:33:28 -07001840 // so it will be detected during collapseOverlapRegions().
Stephen Whitee260c462017-12-19 18:09:54 -05001841 int innerWinding = innerInversion ? 2 : -2;
1842 int outerWinding = outerInversion ? -1 : 1;
1843 for (Vertex* v = innerVertices.fHead; v && v->fNext; v = v->fNext) {
Chris Dalton7cf3add2021-01-11 18:33:28 -07001844 this->makeConnectingEdge(v, v->fNext, EdgeType::kInner, c, innerWinding);
Stephen Whitee260c462017-12-19 18:09:54 -05001845 }
Chris Dalton7cf3add2021-01-11 18:33:28 -07001846 this->makeConnectingEdge(innerVertices.fTail, innerVertices.fHead, EdgeType::kInner, c,
1847 innerWinding);
Stephen Whitee260c462017-12-19 18:09:54 -05001848 for (Vertex* v = outerVertices.fHead; v && v->fNext; v = v->fNext) {
Chris Dalton7cf3add2021-01-11 18:33:28 -07001849 this->makeConnectingEdge(v, v->fNext, EdgeType::kOuter, c, outerWinding);
Stephen Whitee260c462017-12-19 18:09:54 -05001850 }
Chris Dalton7cf3add2021-01-11 18:33:28 -07001851 this->makeConnectingEdge(outerVertices.fTail, outerVertices.fHead, EdgeType::kOuter, c,
1852 outerWinding);
Stephen Whitee260c462017-12-19 18:09:54 -05001853 innerMesh->append(innerVertices);
Chris Dalton93c2d812021-01-11 19:51:59 -07001854 fOuterMesh.append(outerVertices);
Stephen Whitee260c462017-12-19 18:09:54 -05001855}
senorblancof57372d2016-08-31 10:36:19 -07001856
Chris Dalton7cf3add2021-01-11 18:33:28 -07001857void GrAATriangulator::extractBoundary(EdgeList* boundary, Edge* e) {
Brian Salomon120e7d62019-09-11 10:29:22 -04001858 TESS_LOG("\nextracting boundary\n");
Chris Dalton7cf3add2021-01-11 18:33:28 -07001859 bool down = apply_fill_type(fPath.getFillType(), e->fWinding);
Stephen White0c72ed32019-06-13 13:13:13 -04001860 Vertex* start = down ? e->fTop : e->fBottom;
1861 do {
senorblancof57372d2016-08-31 10:36:19 -07001862 e->fWinding = down ? 1 : -1;
1863 Edge* next;
Stephen Whitee260c462017-12-19 18:09:54 -05001864 e->fLine.normalize();
1865 e->fLine = e->fLine * e->fWinding;
senorblancof57372d2016-08-31 10:36:19 -07001866 boundary->append(e);
1867 if (down) {
1868 // Find outgoing edge, in clockwise order.
1869 if ((next = e->fNextEdgeAbove)) {
1870 down = false;
1871 } else if ((next = e->fBottom->fLastEdgeBelow)) {
1872 down = true;
1873 } else if ((next = e->fPrevEdgeAbove)) {
1874 down = false;
1875 }
1876 } else {
1877 // Find outgoing edge, in counter-clockwise order.
1878 if ((next = e->fPrevEdgeBelow)) {
1879 down = true;
1880 } else if ((next = e->fTop->fFirstEdgeAbove)) {
1881 down = false;
1882 } else if ((next = e->fNextEdgeBelow)) {
1883 down = true;
1884 }
1885 }
Chris Dalton24472af2021-01-11 20:05:00 -07001886 e->disconnect();
senorblancof57372d2016-08-31 10:36:19 -07001887 e = next;
Stephen White0c72ed32019-06-13 13:13:13 -04001888 } while (e && (down ? e->fTop : e->fBottom) != start);
senorblancof57372d2016-08-31 10:36:19 -07001889}
1890
Stephen White5ad721e2017-02-23 16:50:47 -05001891// Stage 5b: Extract boundaries from mesh, simplify and stroke them into a new mesh.
senorblancof57372d2016-08-31 10:36:19 -07001892
Chris Dalton7cf3add2021-01-11 18:33:28 -07001893void GrAATriangulator::extractBoundaries(const VertexList& inMesh, VertexList* innerVertices,
Chris Dalton93c2d812021-01-11 19:51:59 -07001894 const Comparator& c) {
Chris Dalton7cf3add2021-01-11 18:33:28 -07001895 this->removeNonBoundaryEdges(inMesh);
Stephen White5ad721e2017-02-23 16:50:47 -05001896 for (Vertex* v = inMesh.fHead; v; v = v->fNext) {
senorblancof57372d2016-08-31 10:36:19 -07001897 while (v->fFirstEdgeBelow) {
Stephen White5ad721e2017-02-23 16:50:47 -05001898 EdgeList boundary;
Chris Dalton7cf3add2021-01-11 18:33:28 -07001899 this->extractBoundary(&boundary, v->fFirstEdgeBelow);
1900 this->simplifyBoundary(&boundary, c);
Chris Dalton93c2d812021-01-11 19:51:59 -07001901 this->strokeBoundary(&boundary, innerVertices, c);
senorblancof57372d2016-08-31 10:36:19 -07001902 }
1903 }
senorblancof57372d2016-08-31 10:36:19 -07001904}
1905
Stephen Whitebda29c02017-03-13 15:10:13 -04001906// This is a driver function that calls stages 2-5 in turn.
ethannicholase9709e82016-01-07 13:34:16 -08001907
Chris Dalton57ea1fc2021-01-05 13:37:44 -07001908void GrTriangulator::contoursToMesh(VertexList* contours, int contourCnt, VertexList* mesh,
Chris Dalton811dc6a2021-01-07 16:40:32 -07001909 const Comparator& c) {
Chris Dalton5045de32021-01-07 19:09:01 -07001910#if TRIANGULATOR_LOGGING
ethannicholase9709e82016-01-07 13:34:16 -08001911 for (int i = 0; i < contourCnt; ++i) {
Stephen White3a9aab92017-03-07 14:07:18 -05001912 Vertex* v = contours[i].fHead;
ethannicholase9709e82016-01-07 13:34:16 -08001913 SkASSERT(v);
Brian Salomon120e7d62019-09-11 10:29:22 -04001914 TESS_LOG("path.moveTo(%20.20g, %20.20g);\n", v->fPoint.fX, v->fPoint.fY);
Stephen White3a9aab92017-03-07 14:07:18 -05001915 for (v = v->fNext; v; v = v->fNext) {
Brian Salomon120e7d62019-09-11 10:29:22 -04001916 TESS_LOG("path.lineTo(%20.20g, %20.20g);\n", v->fPoint.fX, v->fPoint.fY);
ethannicholase9709e82016-01-07 13:34:16 -08001917 }
1918 }
1919#endif
Chris Dalton57ea1fc2021-01-05 13:37:44 -07001920 this->sanitizeContours(contours, contourCnt);
1921 this->buildEdges(contours, contourCnt, mesh, c);
senorblancof57372d2016-08-31 10:36:19 -07001922}
1923
Chris Dalton57ea1fc2021-01-05 13:37:44 -07001924void GrTriangulator::SortMesh(VertexList* vertices, const Comparator& c) {
Stephen Whitebf6137e2017-01-04 15:43:26 -05001925 if (!vertices || !vertices->fHead) {
Stephen White2f4686f2017-01-03 16:20:01 -05001926 return;
ethannicholase9709e82016-01-07 13:34:16 -08001927 }
1928
1929 // Sort vertices in Y (secondarily in X).
Stephen White16a40cb2017-02-23 11:10:01 -05001930 if (c.fDirection == Comparator::Direction::kHorizontal) {
1931 merge_sort<sweep_lt_horiz>(vertices);
1932 } else {
1933 merge_sort<sweep_lt_vert>(vertices);
1934 }
Chris Dalton5045de32021-01-07 19:09:01 -07001935#if TRIANGULATOR_LOGGING
Stephen White2e2cb9b2017-01-09 13:11:18 -05001936 for (Vertex* v = vertices->fHead; v != nullptr; v = v->fNext) {
ethannicholase9709e82016-01-07 13:34:16 -08001937 static float gID = 0.0f;
1938 v->fID = gID++;
1939 }
1940#endif
Stephen White2f4686f2017-01-03 16:20:01 -05001941}
1942
Chris Dalton93c2d812021-01-11 19:51:59 -07001943Poly* GrTriangulator::contoursToPolys(VertexList* contours, int contourCnt) {
Chris Dalton57ea1fc2021-01-05 13:37:44 -07001944 const SkRect& pathBounds = fPath.getBounds();
Stephen White16a40cb2017-02-23 11:10:01 -05001945 Comparator c(pathBounds.width() > pathBounds.height() ? Comparator::Direction::kHorizontal
1946 : Comparator::Direction::kVertical);
Stephen Whitebf6137e2017-01-04 15:43:26 -05001947 VertexList mesh;
Chris Dalton57ea1fc2021-01-05 13:37:44 -07001948 this->contoursToMesh(contours, contourCnt, &mesh, c);
1949 SortMesh(&mesh, c);
1950 this->mergeCoincidentVertices(&mesh, c);
1951 if (SimplifyResult::kAbort == this->simplify(&mesh, c)) {
Chris Dalton6ccc0322020-01-29 11:38:16 -07001952 return nullptr;
1953 }
Brian Salomon120e7d62019-09-11 10:29:22 -04001954 TESS_LOG("\nsimplified mesh:\n");
Chris Dalton7cf3add2021-01-11 18:33:28 -07001955 DUMP_MESH(mesh);
Chris Dalton93c2d812021-01-11 19:51:59 -07001956 return this->tessellate(mesh, c);
Chris Dalton7cf3add2021-01-11 18:33:28 -07001957}
1958
Chris Dalton93c2d812021-01-11 19:51:59 -07001959Poly* GrAATriangulator::tessellate(const VertexList& mesh, const Comparator& c) {
Chris Dalton7cf3add2021-01-11 18:33:28 -07001960 VertexList innerMesh;
Chris Dalton93c2d812021-01-11 19:51:59 -07001961 this->extractBoundaries(mesh, &innerMesh, c);
Chris Dalton7cf3add2021-01-11 18:33:28 -07001962 SortMesh(&innerMesh, c);
Chris Dalton93c2d812021-01-11 19:51:59 -07001963 SortMesh(&fOuterMesh, c);
Chris Dalton7cf3add2021-01-11 18:33:28 -07001964 this->mergeCoincidentVertices(&innerMesh, c);
Chris Dalton93c2d812021-01-11 19:51:59 -07001965 bool was_complex = this->mergeCoincidentVertices(&fOuterMesh, c);
Chris Dalton7cf3add2021-01-11 18:33:28 -07001966 auto result = this->simplify(&innerMesh, c);
1967 SkASSERT(SimplifyResult::kAbort != result);
1968 was_complex = (SimplifyResult::kFoundSelfIntersection == result) || was_complex;
Chris Dalton93c2d812021-01-11 19:51:59 -07001969 result = this->simplify(&fOuterMesh, c);
Chris Dalton7cf3add2021-01-11 18:33:28 -07001970 SkASSERT(SimplifyResult::kAbort != result);
1971 was_complex = (SimplifyResult::kFoundSelfIntersection == result) || was_complex;
1972 TESS_LOG("\ninner mesh before:\n");
1973 DUMP_MESH(innerMesh);
1974 TESS_LOG("\nouter mesh before:\n");
Chris Dalton93c2d812021-01-11 19:51:59 -07001975 DUMP_MESH(fOuterMesh);
Chris Dalton7cf3add2021-01-11 18:33:28 -07001976 EventComparator eventLT(EventComparator::Op::kLessThan);
1977 EventComparator eventGT(EventComparator::Op::kGreaterThan);
1978 was_complex = this->collapseOverlapRegions(&innerMesh, c, eventLT) || was_complex;
Chris Dalton93c2d812021-01-11 19:51:59 -07001979 was_complex = this->collapseOverlapRegions(&fOuterMesh, c, eventGT) || was_complex;
Chris Dalton7cf3add2021-01-11 18:33:28 -07001980 if (was_complex) {
1981 TESS_LOG("found complex mesh; taking slow path\n");
1982 VertexList aaMesh;
1983 TESS_LOG("\ninner mesh after:\n");
1984 DUMP_MESH(innerMesh);
1985 TESS_LOG("\nouter mesh after:\n");
Chris Dalton93c2d812021-01-11 19:51:59 -07001986 DUMP_MESH(fOuterMesh);
1987 this->connectPartners(&fOuterMesh, c);
Chris Dalton7cf3add2021-01-11 18:33:28 -07001988 this->connectPartners(&innerMesh, c);
Chris Dalton93c2d812021-01-11 19:51:59 -07001989 sorted_merge(&innerMesh, &fOuterMesh, &aaMesh, c);
Chris Dalton7cf3add2021-01-11 18:33:28 -07001990 this->mergeCoincidentVertices(&aaMesh, c);
1991 result = this->simplify(&aaMesh, c);
Chris Dalton6ccc0322020-01-29 11:38:16 -07001992 SkASSERT(SimplifyResult::kAbort != result);
Chris Dalton7cf3add2021-01-11 18:33:28 -07001993 TESS_LOG("combined and simplified mesh:\n");
1994 DUMP_MESH(aaMesh);
Chris Dalton93c2d812021-01-11 19:51:59 -07001995 fOuterMesh.fHead = fOuterMesh.fTail = nullptr;
1996 return this->GrTriangulator::tessellate(aaMesh, c);
Stephen White49789062017-02-21 10:35:49 -05001997 } else {
Chris Dalton7cf3add2021-01-11 18:33:28 -07001998 TESS_LOG("no complex polygons; taking fast path\n");
Chris Dalton93c2d812021-01-11 19:51:59 -07001999 return this->GrTriangulator::tessellate(innerMesh, c);
senorblancof57372d2016-08-31 10:36:19 -07002000 }
senorblancof57372d2016-08-31 10:36:19 -07002001}
2002
2003// Stage 6: Triangulate the monotone polygons into a vertex buffer.
Chris Dalton93c2d812021-01-11 19:51:59 -07002004void* GrTriangulator::polysToTrianglesImpl(Poly* polys, void* data,
2005 SkPathFillType overrideFillType) {
senorblancof57372d2016-08-31 10:36:19 -07002006 for (Poly* poly = polys; poly; poly = poly->fNext) {
Chris Dalton57ea1fc2021-01-05 13:37:44 -07002007 if (apply_fill_type(overrideFillType, poly)) {
Chris Dalton9a4904f2021-01-07 19:10:14 -07002008 data = this->emitPoly(poly, data);
senorblancof57372d2016-08-31 10:36:19 -07002009 }
2010 }
2011 return data;
ethannicholase9709e82016-01-07 13:34:16 -08002012}
2013
Chris Dalton93c2d812021-01-11 19:51:59 -07002014Poly* GrTriangulator::pathToPolys(float tolerance, const SkRect& clipBounds, int contourCnt) {
Chris Dalton57ea1fc2021-01-05 13:37:44 -07002015 if (SkPathFillType_IsInverse(fPath.getFillType())) {
ethannicholase9709e82016-01-07 13:34:16 -08002016 contourCnt++;
2017 }
Stephen White3a9aab92017-03-07 14:07:18 -05002018 std::unique_ptr<VertexList[]> contours(new VertexList[contourCnt]);
ethannicholase9709e82016-01-07 13:34:16 -08002019
Chris Dalton57ea1fc2021-01-05 13:37:44 -07002020 this->pathToContours(tolerance, clipBounds, contours.get());
Chris Dalton93c2d812021-01-11 19:51:59 -07002021 return this->contoursToPolys(contours.get(), contourCnt);
ethannicholase9709e82016-01-07 13:34:16 -08002022}
2023
Chris Dalton57ea1fc2021-01-05 13:37:44 -07002024static int get_contour_count(const SkPath& path, SkScalar tolerance) {
Chris Daltonc71b3d42020-01-08 21:29:59 -07002025 // We could theoretically be more aggressive about not counting empty contours, but we need to
2026 // actually match the exact number of contour linked lists the tessellator will create later on.
2027 int contourCnt = 1;
2028 bool hasPoints = false;
2029
Chris Dalton7156db22020-05-07 22:06:28 +00002030 SkPath::Iter iter(path, false);
2031 SkPath::Verb verb;
2032 SkPoint pts[4];
Chris Daltonc71b3d42020-01-08 21:29:59 -07002033 bool first = true;
Chris Dalton7156db22020-05-07 22:06:28 +00002034 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
Chris Daltonc71b3d42020-01-08 21:29:59 -07002035 switch (verb) {
Chris Dalton7156db22020-05-07 22:06:28 +00002036 case SkPath::kMove_Verb:
Chris Daltonc71b3d42020-01-08 21:29:59 -07002037 if (!first) {
2038 ++contourCnt;
2039 }
John Stiles30212b72020-06-11 17:55:07 -04002040 [[fallthrough]];
Chris Dalton7156db22020-05-07 22:06:28 +00002041 case SkPath::kLine_Verb:
2042 case SkPath::kConic_Verb:
2043 case SkPath::kQuad_Verb:
2044 case SkPath::kCubic_Verb:
Chris Daltonc71b3d42020-01-08 21:29:59 -07002045 hasPoints = true;
John Stiles30212b72020-06-11 17:55:07 -04002046 break;
Chris Daltonc71b3d42020-01-08 21:29:59 -07002047 default:
2048 break;
2049 }
2050 first = false;
2051 }
2052 if (!hasPoints) {
Stephen White11f65e02017-02-16 19:00:39 -05002053 return 0;
ethannicholase9709e82016-01-07 13:34:16 -08002054 }
Stephen White11f65e02017-02-16 19:00:39 -05002055 return contourCnt;
ethannicholase9709e82016-01-07 13:34:16 -08002056}
2057
Chris Dalton93c2d812021-01-11 19:51:59 -07002058int64_t GrTriangulator::countPointsImpl(Poly* polys, SkPathFillType overrideFillType) const {
Greg Danield5b45932018-06-07 13:15:10 -04002059 int64_t count = 0;
ethannicholase9709e82016-01-07 13:34:16 -08002060 for (Poly* poly = polys; poly; poly = poly->fNext) {
Chris Dalton93c2d812021-01-11 19:51:59 -07002061 if (apply_fill_type(overrideFillType, poly) && poly->fCount >= 3) {
Chris Dalton17dc4182020-03-25 16:18:16 -06002062 count += (poly->fCount - 2) * (TRIANGULATOR_WIREFRAME ? 6 : 3);
ethannicholase9709e82016-01-07 13:34:16 -08002063 }
2064 }
2065 return count;
2066}
2067
Chris Dalton93c2d812021-01-11 19:51:59 -07002068int64_t GrAATriangulator::countPoints(Poly* polys) const {
2069 int64_t count = this->countPointsImpl(polys, SkPathFillType::kWinding);
2070 // Count the points from the outer mesh.
2071 for (Vertex* v = fOuterMesh.fHead; v; v = v->fNext) {
Stephen Whitebda29c02017-03-13 15:10:13 -04002072 for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
Chris Dalton17dc4182020-03-25 16:18:16 -06002073 count += TRIANGULATOR_WIREFRAME ? 12 : 6;
Stephen Whitebda29c02017-03-13 15:10:13 -04002074 }
2075 }
2076 return count;
2077}
2078
Chris Dalton93c2d812021-01-11 19:51:59 -07002079void* GrAATriangulator::polysToTriangles(Poly* polys, void* data) {
2080 data = this->polysToTrianglesImpl(polys, data, SkPathFillType::kWinding);
2081 // Emit the triangles from the outer mesh.
2082 for (Vertex* v = fOuterMesh.fHead; v; v = v->fNext) {
Stephen Whitebda29c02017-03-13 15:10:13 -04002083 for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
2084 Vertex* v0 = e->fTop;
2085 Vertex* v1 = e->fBottom;
2086 Vertex* v2 = e->fBottom->fPartner;
2087 Vertex* v3 = e->fTop->fPartner;
Chris Dalton93c2d812021-01-11 19:51:59 -07002088 data = this->emitTriangle(v0, v1, v2, 0/*winding*/, data);
2089 data = this->emitTriangle(v0, v2, v3, 0/*winding*/, data);
Stephen Whitebda29c02017-03-13 15:10:13 -04002090 }
2091 }
2092 return data;
2093}
2094
ethannicholase9709e82016-01-07 13:34:16 -08002095// Stage 6: Triangulate the monotone polygons into a vertex buffer.
2096
Chris Dalton57ea1fc2021-01-05 13:37:44 -07002097int GrTriangulator::pathToTriangles(float tolerance, const SkRect& clipBounds,
Chris Dalton93c2d812021-01-11 19:51:59 -07002098 GrEagerVertexAllocator* vertexAllocator) {
Chris Dalton57ea1fc2021-01-05 13:37:44 -07002099 int contourCnt = get_contour_count(fPath, tolerance);
ethannicholase9709e82016-01-07 13:34:16 -08002100 if (contourCnt <= 0) {
Chris Dalton57ea1fc2021-01-05 13:37:44 -07002101 fIsLinear = true;
ethannicholase9709e82016-01-07 13:34:16 -08002102 return 0;
2103 }
Chris Dalton93c2d812021-01-11 19:51:59 -07002104 Poly* polys = this->pathToPolys(tolerance, clipBounds, contourCnt);
2105 int64_t count64 = this->countPoints(polys);
Greg Danield5b45932018-06-07 13:15:10 -04002106 if (0 == count64 || count64 > SK_MaxS32) {
Stephen Whiteff60b172017-05-05 15:54:52 -04002107 return 0;
2108 }
Greg Danield5b45932018-06-07 13:15:10 -04002109 int count = count64;
ethannicholase9709e82016-01-07 13:34:16 -08002110
Chris Dalton854ee852021-01-05 15:12:59 -07002111 size_t vertexStride = sizeof(SkPoint);
2112 if (fEmitCoverage) {
2113 vertexStride += sizeof(float);
2114 }
Chris Daltond081dce2020-01-23 12:09:04 -07002115 void* verts = vertexAllocator->lock(vertexStride, count);
senorblanco6599eff2016-03-10 08:38:45 -08002116 if (!verts) {
ethannicholase9709e82016-01-07 13:34:16 -08002117 SkDebugf("Could not allocate vertices\n");
2118 return 0;
2119 }
senorblancof57372d2016-08-31 10:36:19 -07002120
Brian Salomon120e7d62019-09-11 10:29:22 -04002121 TESS_LOG("emitting %d verts\n", count);
Chris Dalton93c2d812021-01-11 19:51:59 -07002122 void* end = this->polysToTriangles(polys, verts);
Brian Osman80879d42019-01-07 16:15:27 -05002123
senorblancof57372d2016-08-31 10:36:19 -07002124 int actualCount = static_cast<int>((static_cast<uint8_t*>(end) - static_cast<uint8_t*>(verts))
Chris Daltond081dce2020-01-23 12:09:04 -07002125 / vertexStride);
ethannicholase9709e82016-01-07 13:34:16 -08002126 SkASSERT(actualCount <= count);
senorblanco6599eff2016-03-10 08:38:45 -08002127 vertexAllocator->unlock(actualCount);
ethannicholase9709e82016-01-07 13:34:16 -08002128 return actualCount;
2129}
2130
Chris Dalton57ea1fc2021-01-05 13:37:44 -07002131int GrTriangulator::PathToVertices(const SkPath& path, SkScalar tolerance, const SkRect& clipBounds,
2132 WindingVertex** verts) {
Stephen White11f65e02017-02-16 19:00:39 -05002133 int contourCnt = get_contour_count(path, tolerance);
ethannicholase9709e82016-01-07 13:34:16 -08002134 if (contourCnt <= 0) {
Chris Dalton84403d72018-02-13 21:46:17 -05002135 *verts = nullptr;
ethannicholase9709e82016-01-07 13:34:16 -08002136 return 0;
2137 }
Chris Dalton854ee852021-01-05 15:12:59 -07002138 GrTriangulator triangulator(path);
Chris Dalton93c2d812021-01-11 19:51:59 -07002139 Poly* polys = triangulator.pathToPolys(tolerance, clipBounds, contourCnt);
2140 int64_t count64 = triangulator.countPoints(polys);
Greg Danield5b45932018-06-07 13:15:10 -04002141 if (0 == count64 || count64 > SK_MaxS32) {
ethannicholase9709e82016-01-07 13:34:16 -08002142 *verts = nullptr;
2143 return 0;
2144 }
Greg Danield5b45932018-06-07 13:15:10 -04002145 int count = count64;
ethannicholase9709e82016-01-07 13:34:16 -08002146
Chris Dalton17dc4182020-03-25 16:18:16 -06002147 *verts = new WindingVertex[count];
2148 WindingVertex* vertsEnd = *verts;
ethannicholase9709e82016-01-07 13:34:16 -08002149 SkPoint* points = new SkPoint[count];
2150 SkPoint* pointsEnd = points;
2151 for (Poly* poly = polys; poly; poly = poly->fNext) {
Chris Dalton93c2d812021-01-11 19:51:59 -07002152 if (apply_fill_type(path.getFillType(), poly)) {
ethannicholase9709e82016-01-07 13:34:16 -08002153 SkPoint* start = pointsEnd;
Chris Dalton9a4904f2021-01-07 19:10:14 -07002154 pointsEnd = static_cast<SkPoint*>(triangulator.emitPoly(poly, pointsEnd));
ethannicholase9709e82016-01-07 13:34:16 -08002155 while (start != pointsEnd) {
2156 vertsEnd->fPos = *start;
2157 vertsEnd->fWinding = poly->fWinding;
2158 ++start;
2159 ++vertsEnd;
2160 }
2161 }
2162 }
2163 int actualCount = static_cast<int>(vertsEnd - *verts);
2164 SkASSERT(actualCount <= count);
2165 SkASSERT(pointsEnd - points == actualCount);
2166 delete[] points;
2167 return actualCount;
2168}