1/* 2 * Copyright 2020 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "src/gpu/geometry/GrAATriangulator.h" 9 10#include "src/gpu/GrEagerVertexAllocator.h" 11#include <queue> 12#include <vector> 13#include <unordered_map> 14 15#if TRIANGULATOR_LOGGING 16#define TESS_LOG SkDebugf 17#define DUMP_MESH(MESH) (MESH).dump() 18#else 19#define TESS_LOG(...) 20#define DUMP_MESH(MESH) 21#endif 22 23constexpr static float kCosMiterAngle = 0.97f; // Corresponds to an angle of ~14 degrees. 24 25using EdgeType = GrTriangulator::EdgeType; 26using Vertex = GrTriangulator::Vertex; 27using VertexList = GrTriangulator::VertexList; 28using Line = GrTriangulator::Line; 29using Edge = GrTriangulator::Edge; 30using EdgeList = GrTriangulator::EdgeList; 31using Poly = GrTriangulator::Poly; 32using Comparator = GrTriangulator::Comparator; 33using SSEdge = GrAATriangulator::SSEdge; 34using EventList = GrAATriangulator::EventList; 35using Event = GrAATriangulator::Event; 36using EventComparator = GrAATriangulator::EventComparator; 37 38struct SSVertex { 39 SSVertex(Vertex* v) : fVertex(v), fPrev(nullptr), fNext(nullptr) {} 40 Vertex* fVertex; 41 SSEdge* fPrev; 42 SSEdge* fNext; 43}; 44 45struct GrAATriangulator::SSEdge { 46 SSEdge(Edge* edge, SSVertex* prev, SSVertex* next) 47 : fEdge(edge), fEvent(nullptr), fPrev(prev), fNext(next) { 48 } 49 Edge* fEdge; 50 Event* fEvent; 51 SSVertex* fPrev; 52 SSVertex* fNext; 53}; 54 55typedef std::unordered_map<Vertex*, SSVertex*> SSVertexMap; 56typedef std::vector<SSEdge*> SSEdgeList; 57typedef std::priority_queue<Event*, std::vector<Event*>, EventComparator> EventPQ; 58 59struct GrAATriangulator::EventList : EventPQ { 60 EventList(EventComparator comparison) : EventPQ(comparison) { 61 } 62}; 63 64void GrAATriangulator::makeEvent(SSEdge* e, EventList* events) const { 65 Vertex* prev = e->fPrev->fVertex; 66 Vertex* next = e->fNext->fVertex; 67 if (prev == next || !prev->fPartner || !next->fPartner) { 68 return; 69 } 70 Edge bisector1(prev, prev->fPartner, 1, EdgeType::kConnector); 71 Edge bisector2(next, next->fPartner, 1, EdgeType::kConnector); 72 SkPoint p; 73 uint8_t alpha; 74 if (bisector1.intersect(bisector2, &p, &alpha)) { 75 TESS_LOG("found edge event for %g, %g (original %g -> %g), " 76 "will collapse to %g,%g alpha %d\n", 77 prev->fID, next->fID, e->fEdge->fTop->fID, e->fEdge->fBottom->fID, p.fX, p.fY, 78 alpha); 79 e->fEvent = fAlloc->make<Event>(e, p, alpha); 80 events->push(e->fEvent); 81 } 82} 83 84void GrAATriangulator::makeEvent(SSEdge* edge, Vertex* v, SSEdge* other, Vertex* dest, 85 EventList* events, const Comparator& c) const { 86 if (!v->fPartner) { 87 return; 88 } 89 Vertex* top = edge->fEdge->fTop; 90 Vertex* bottom = edge->fEdge->fBottom; 91 if (!top || !bottom ) { 92 return; 93 } 94 Line line = edge->fEdge->fLine; 95 line.fC = -(dest->fPoint.fX * line.fA + dest->fPoint.fY * line.fB); 96 Edge bisector(v, v->fPartner, 1, EdgeType::kConnector); 97 SkPoint p; 98 uint8_t alpha = dest->fAlpha; 99 if (line.intersect(bisector.fLine, &p) && !c.sweep_lt(p, top->fPoint) && 100 c.sweep_lt(p, bottom->fPoint)) { 101 TESS_LOG("found p edge event for %g, %g (original %g -> %g), " 102 "will collapse to %g,%g alpha %d\n", 103 dest->fID, v->fID, top->fID, bottom->fID, p.fX, p.fY, alpha); 104 edge->fEvent = fAlloc->make<Event>(edge, p, alpha); 105 events->push(edge->fEvent); 106 } 107} 108 109void GrAATriangulator::connectPartners(VertexList* mesh, const Comparator& c) const { 110 for (Vertex* outer = mesh->fHead; outer; outer = outer->fNext) { 111 if (Vertex* inner = outer->fPartner) { 112 if ((inner->fPrev || inner->fNext) && (outer->fPrev || outer->fNext)) { 113 // Connector edges get zero winding, since they're only structural (i.e., to ensure 114 // no 0-0-0 alpha triangles are produced), and shouldn't affect the poly winding 115 // number. 116 this->makeConnectingEdge(outer, inner, EdgeType::kConnector, c, 0); 117 inner->fPartner = outer->fPartner = nullptr; 118 } 119 } 120 } 121} 122 123static void dump_skel(const SSEdgeList& ssEdges) { 124#if TRIANGULATOR_LOGGING 125 for (SSEdge* edge : ssEdges) { 126 if (edge->fEdge) { 127 TESS_LOG("skel edge %g -> %g", 128 edge->fPrev->fVertex->fID, 129 edge->fNext->fVertex->fID); 130 if (edge->fEdge->fTop && edge->fEdge->fBottom) { 131 TESS_LOG(" (original %g -> %g)\n", 132 edge->fEdge->fTop->fID, 133 edge->fEdge->fBottom->fID); 134 } else { 135 TESS_LOG("\n"); 136 } 137 } 138 } 139#endif 140} 141 142void GrAATriangulator::removeNonBoundaryEdges(const VertexList& mesh) const { 143 TESS_LOG("removing non-boundary edges\n"); 144 EdgeList activeEdges; 145 for (Vertex* v = mesh.fHead; v != nullptr; v = v->fNext) { 146 if (!v->isConnected()) { 147 continue; 148 } 149 Edge* leftEnclosingEdge; 150 Edge* rightEnclosingEdge; 151 FindEnclosingEdges(v, &activeEdges, &leftEnclosingEdge, &rightEnclosingEdge); 152 bool prevFilled = leftEnclosingEdge && this->applyFillType(leftEnclosingEdge->fWinding); 153 for (Edge* e = v->fFirstEdgeAbove; e;) { 154 Edge* next = e->fNextEdgeAbove; 155 activeEdges.remove(e); 156 bool filled = this->applyFillType(e->fWinding); 157 if (filled == prevFilled) { 158 e->disconnect(); 159 } 160 prevFilled = filled; 161 e = next; 162 } 163 Edge* prev = leftEnclosingEdge; 164 for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) { 165 if (prev) { 166 e->fWinding += prev->fWinding; 167 } 168 activeEdges.insert(e, prev); 169 prev = e; 170 } 171 } 172} 173 174// Note: this is the normal to the edge, but not necessarily unit length. 175static void get_edge_normal(const Edge* e, SkVector* normal) { 176 normal->set(SkDoubleToScalar(e->fLine.fA), 177 SkDoubleToScalar(e->fLine.fB)); 178} 179 180// Stage 5c: detect and remove "pointy" vertices whose edge normals point in opposite directions 181// and whose adjacent vertices are less than a quarter pixel from an edge. These are guaranteed to 182// invert on stroking. 183 184void GrAATriangulator::simplifyBoundary(EdgeList* boundary, const Comparator& c) const { 185 Edge* prevEdge = boundary->fTail; 186 SkVector prevNormal; 187 get_edge_normal(prevEdge, &prevNormal); 188 for (Edge* e = boundary->fHead; e != nullptr;) { 189 Vertex* prev = prevEdge->fWinding == 1 ? prevEdge->fTop : prevEdge->fBottom; 190 Vertex* next = e->fWinding == 1 ? e->fBottom : e->fTop; 191 double distPrev = e->dist(prev->fPoint); 192 double distNext = prevEdge->dist(next->fPoint); 193 SkVector normal; 194 get_edge_normal(e, &normal); 195 constexpr double kQuarterPixelSq = 0.25f * 0.25f; 196 if (prev == next) { 197 boundary->remove(prevEdge); 198 boundary->remove(e); 199 prevEdge = boundary->fTail; 200 e = boundary->fHead; 201 if (prevEdge) { 202 get_edge_normal(prevEdge, &prevNormal); 203 } 204 } else if (prevNormal.dot(normal) < 0.0 && 205 (distPrev * distPrev <= kQuarterPixelSq || distNext * distNext <= kQuarterPixelSq)) { 206 Edge* join = this->makeEdge(prev, next, EdgeType::kInner, c); 207 if (prev->fPoint != next->fPoint) { 208 join->fLine.normalize(); 209 join->fLine = join->fLine * join->fWinding; 210 } 211 boundary->insert(join, e); 212 boundary->remove(prevEdge); 213 boundary->remove(e); 214 if (join->fLeft && join->fRight) { 215 prevEdge = join->fLeft; 216 e = join; 217 } else { 218 prevEdge = boundary->fTail; 219 e = boundary->fHead; // join->fLeft ? join->fLeft : join; 220 } 221 get_edge_normal(prevEdge, &prevNormal); 222 } else { 223 prevEdge = e; 224 prevNormal = normal; 225 e = e->fRight; 226 } 227 } 228} 229 230void GrAATriangulator::connectSSEdge(Vertex* v, Vertex* dest, const Comparator& c) const { 231 if (v == dest) { 232 return; 233 } 234 TESS_LOG("ss_connecting vertex %g to vertex %g\n", v->fID, dest->fID); 235 if (v->fSynthetic) { 236 this->makeConnectingEdge(v, dest, EdgeType::kConnector, c, 0); 237 } else if (v->fPartner) { 238 TESS_LOG("setting %g's partner to %g ", v->fPartner->fID, dest->fID); 239 TESS_LOG("and %g's partner to null\n", v->fID); 240 v->fPartner->fPartner = dest; 241 v->fPartner = nullptr; 242 } 243} 244 245void GrAATriangulator::Event::apply(VertexList* mesh, const Comparator& c, EventList* events, 246 const GrAATriangulator* triangulator) { 247 if (!fEdge) { 248 return; 249 } 250 Vertex* prev = fEdge->fPrev->fVertex; 251 Vertex* next = fEdge->fNext->fVertex; 252 SSEdge* prevEdge = fEdge->fPrev->fPrev; 253 SSEdge* nextEdge = fEdge->fNext->fNext; 254 if (!prevEdge || !nextEdge || !prevEdge->fEdge || !nextEdge->fEdge) { 255 return; 256 } 257 Vertex* dest = triangulator->makeSortedVertex(fPoint, fAlpha, mesh, prev, c); 258 dest->fSynthetic = true; 259 SSVertex* ssv = triangulator->fAlloc->make<SSVertex>(dest); 260 TESS_LOG("collapsing %g, %g (original edge %g -> %g) to %g (%g, %g) alpha %d\n", 261 prev->fID, next->fID, fEdge->fEdge->fTop->fID, fEdge->fEdge->fBottom->fID, dest->fID, 262 fPoint.fX, fPoint.fY, fAlpha); 263 fEdge->fEdge = nullptr; 264 265 triangulator->connectSSEdge(prev, dest, c); 266 triangulator->connectSSEdge(next, dest, c); 267 268 prevEdge->fNext = nextEdge->fPrev = ssv; 269 ssv->fPrev = prevEdge; 270 ssv->fNext = nextEdge; 271 if (!prevEdge->fEdge || !nextEdge->fEdge) { 272 return; 273 } 274 if (prevEdge->fEvent) { 275 prevEdge->fEvent->fEdge = nullptr; 276 } 277 if (nextEdge->fEvent) { 278 nextEdge->fEvent->fEdge = nullptr; 279 } 280 if (prevEdge->fPrev == nextEdge->fNext) { 281 triangulator->connectSSEdge(prevEdge->fPrev->fVertex, dest, c); 282 prevEdge->fEdge = nextEdge->fEdge = nullptr; 283 } else { 284 triangulator->computeBisector(prevEdge->fEdge, nextEdge->fEdge, dest); 285 SkASSERT(prevEdge != fEdge && nextEdge != fEdge); 286 if (dest->fPartner) { 287 triangulator->makeEvent(prevEdge, events); 288 triangulator->makeEvent(nextEdge, events); 289 } else { 290 triangulator->makeEvent(prevEdge, prevEdge->fPrev->fVertex, nextEdge, dest, events, c); 291 triangulator->makeEvent(nextEdge, nextEdge->fNext->fVertex, prevEdge, dest, events, c); 292 } 293 } 294} 295 296static bool is_overlap_edge(Edge* e) { 297 if (e->fType == EdgeType::kOuter) { 298 return e->fWinding != 0 && e->fWinding != 1; 299 } else if (e->fType == EdgeType::kInner) { 300 return e->fWinding != 0 && e->fWinding != -2; 301 } else { 302 return false; 303 } 304} 305 306// This is a stripped-down version of tessellate() which computes edges which 307// join two filled regions, which represent overlap regions, and collapses them. 308bool GrAATriangulator::collapseOverlapRegions(VertexList* mesh, const Comparator& c, 309 EventComparator comp) const { 310 TESS_LOG("\nfinding overlap regions\n"); 311 EdgeList activeEdges; 312 EventList events(comp); 313 SSVertexMap ssVertices; 314 SSEdgeList ssEdges; 315 for (Vertex* v = mesh->fHead; v != nullptr; v = v->fNext) { 316 if (!v->isConnected()) { 317 continue; 318 } 319 Edge* leftEnclosingEdge; 320 Edge* rightEnclosingEdge; 321 FindEnclosingEdges(v, &activeEdges, &leftEnclosingEdge, &rightEnclosingEdge); 322 for (Edge* e = v->fLastEdgeAbove; e && e != leftEnclosingEdge;) { 323 Edge* prev = e->fPrevEdgeAbove ? e->fPrevEdgeAbove : leftEnclosingEdge; 324 activeEdges.remove(e); 325 bool leftOverlap = prev && is_overlap_edge(prev); 326 bool rightOverlap = is_overlap_edge(e); 327 bool isOuterBoundary = e->fType == EdgeType::kOuter && 328 (!prev || prev->fWinding == 0 || e->fWinding == 0); 329 if (prev) { 330 e->fWinding -= prev->fWinding; 331 } 332 if (leftOverlap && rightOverlap) { 333 TESS_LOG("found interior overlap edge %g -> %g, disconnecting\n", 334 e->fTop->fID, e->fBottom->fID); 335 e->disconnect(); 336 } else if (leftOverlap || rightOverlap) { 337 TESS_LOG("found overlap edge %g -> %g%s\n", 338 e->fTop->fID, e->fBottom->fID, 339 isOuterBoundary ? ", is outer boundary" : ""); 340 Vertex* prevVertex = e->fWinding < 0 ? e->fBottom : e->fTop; 341 Vertex* nextVertex = e->fWinding < 0 ? e->fTop : e->fBottom; 342 SSVertex* ssPrev = ssVertices[prevVertex]; 343 if (!ssPrev) { 344 ssPrev = ssVertices[prevVertex] = fAlloc->make<SSVertex>(prevVertex); 345 } 346 SSVertex* ssNext = ssVertices[nextVertex]; 347 if (!ssNext) { 348 ssNext = ssVertices[nextVertex] = fAlloc->make<SSVertex>(nextVertex); 349 } 350 SSEdge* ssEdge = fAlloc->make<SSEdge>(e, ssPrev, ssNext); 351 ssEdges.push_back(ssEdge); 352// SkASSERT(!ssPrev->fNext && !ssNext->fPrev); 353 ssPrev->fNext = ssNext->fPrev = ssEdge; 354 this->makeEvent(ssEdge, &events); 355 if (!isOuterBoundary) { 356 e->disconnect(); 357 } else { 358 SkASSERT(e->fType != EdgeType::kConnector); 359 // Ensure winding values match expected scale for the edge type. During merging of 360 // collinear edges in overlap regions, windings are summed and so could exceed the 361 // expected +/-1 for outer and +/-2 for inner that is used to fill properly during 362 // subsequent polygon generation. 363 e->fWinding = SkScalarCopySign(e->fType == EdgeType::kInner ? 2 : 1, 364 e->fWinding); 365 } 366 } 367 e = prev; 368 } 369 Edge* prev = leftEnclosingEdge; 370 for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) { 371 if (prev) { 372 e->fWinding += prev->fWinding; 373 } 374 activeEdges.insert(e, prev); 375 prev = e; 376 } 377 } 378 bool complex = events.size() > 0; 379 380 TESS_LOG("\ncollapsing overlap regions\n"); 381 TESS_LOG("skeleton before:\n"); 382 dump_skel(ssEdges); 383 while (events.size() > 0) { 384 Event* event = events.top(); 385 events.pop(); 386 event->apply(mesh, c, &events, this); 387 } 388 TESS_LOG("skeleton after:\n"); 389 dump_skel(ssEdges); 390 for (SSEdge* edge : ssEdges) { 391 if (Edge* e = edge->fEdge) { 392 this->makeConnectingEdge(edge->fPrev->fVertex, edge->fNext->fVertex, e->fType, c, 0); 393 } 394 } 395 return complex; 396} 397 398static bool inversion(Vertex* prev, Vertex* next, Edge* origEdge, const Comparator& c) { 399 if (!prev || !next) { 400 return true; 401 } 402 int winding = c.sweep_lt(prev->fPoint, next->fPoint) ? 1 : -1; 403 return winding != origEdge->fWinding; 404} 405 406// Stage 5d: Displace edges by half a pixel inward and outward along their normals. Intersect to 407// find new vertices, and set zero alpha on the exterior and one alpha on the interior. Build a 408// new antialiased mesh from those vertices. 409 410void GrAATriangulator::strokeBoundary(EdgeList* boundary, VertexList* innerMesh, 411 const Comparator& c) const { 412 TESS_LOG("\nstroking boundary\n"); 413 // A boundary with fewer than 3 edges is degenerate. 414 if (!boundary->fHead || !boundary->fHead->fRight || !boundary->fHead->fRight->fRight) { 415 return; 416 } 417 Edge* prevEdge = boundary->fTail; 418 Vertex* prevV = prevEdge->fWinding > 0 ? prevEdge->fTop : prevEdge->fBottom; 419 SkVector prevNormal; 420 get_edge_normal(prevEdge, &prevNormal); 421 double radius = 0.5; 422 Line prevInner(prevEdge->fLine); 423 prevInner.fC -= radius; 424 Line prevOuter(prevEdge->fLine); 425 prevOuter.fC += radius; 426 VertexList innerVertices; 427 VertexList outerVertices; 428 bool innerInversion = true; 429 bool outerInversion = true; 430 for (Edge* e = boundary->fHead; e != nullptr; e = e->fRight) { 431 Vertex* v = e->fWinding > 0 ? e->fTop : e->fBottom; 432 SkVector normal; 433 get_edge_normal(e, &normal); 434 Line inner(e->fLine); 435 inner.fC -= radius; 436 Line outer(e->fLine); 437 outer.fC += radius; 438 SkPoint innerPoint, outerPoint; 439 TESS_LOG("stroking vertex %g (%g, %g)\n", v->fID, v->fPoint.fX, v->fPoint.fY); 440 if (!prevEdge->fLine.nearParallel(e->fLine) && prevInner.intersect(inner, &innerPoint) && 441 prevOuter.intersect(outer, &outerPoint)) { 442 float cosAngle = normal.dot(prevNormal); 443 if (cosAngle < -kCosMiterAngle) { 444 Vertex* nextV = e->fWinding > 0 ? e->fBottom : e->fTop; 445 446 // This is a pointy vertex whose angle is smaller than the threshold; miter it. 447 Line bisector(innerPoint, outerPoint); 448 Line tangent(v->fPoint, v->fPoint + SkPoint::Make(bisector.fA, bisector.fB)); 449 if (tangent.fA == 0 && tangent.fB == 0) { 450 continue; 451 } 452 tangent.normalize(); 453 Line innerTangent(tangent); 454 Line outerTangent(tangent); 455 innerTangent.fC -= 0.5; 456 outerTangent.fC += 0.5; 457 SkPoint innerPoint1, innerPoint2, outerPoint1, outerPoint2; 458 if (prevNormal.cross(normal) > 0) { 459 // Miter inner points 460 if (!innerTangent.intersect(prevInner, &innerPoint1) || 461 !innerTangent.intersect(inner, &innerPoint2) || 462 !outerTangent.intersect(bisector, &outerPoint)) { 463 continue; 464 } 465 Line prevTangent(prevV->fPoint, 466 prevV->fPoint + SkVector::Make(prevOuter.fA, prevOuter.fB)); 467 Line nextTangent(nextV->fPoint, 468 nextV->fPoint + SkVector::Make(outer.fA, outer.fB)); 469 if (prevTangent.dist(outerPoint) > 0) { 470 bisector.intersect(prevTangent, &outerPoint); 471 } 472 if (nextTangent.dist(outerPoint) < 0) { 473 bisector.intersect(nextTangent, &outerPoint); 474 } 475 outerPoint1 = outerPoint2 = outerPoint; 476 } else { 477 // Miter outer points 478 if (!outerTangent.intersect(prevOuter, &outerPoint1) || 479 !outerTangent.intersect(outer, &outerPoint2)) { 480 continue; 481 } 482 Line prevTangent(prevV->fPoint, 483 prevV->fPoint + SkVector::Make(prevInner.fA, prevInner.fB)); 484 Line nextTangent(nextV->fPoint, 485 nextV->fPoint + SkVector::Make(inner.fA, inner.fB)); 486 if (prevTangent.dist(innerPoint) > 0) { 487 bisector.intersect(prevTangent, &innerPoint); 488 } 489 if (nextTangent.dist(innerPoint) < 0) { 490 bisector.intersect(nextTangent, &innerPoint); 491 } 492 innerPoint1 = innerPoint2 = innerPoint; 493 } 494 if (!innerPoint1.isFinite() || !innerPoint2.isFinite() || 495 !outerPoint1.isFinite() || !outerPoint2.isFinite()) { 496 continue; 497 } 498 TESS_LOG("inner (%g, %g), (%g, %g), ", 499 innerPoint1.fX, innerPoint1.fY, innerPoint2.fX, innerPoint2.fY); 500 TESS_LOG("outer (%g, %g), (%g, %g)\n", 501 outerPoint1.fX, outerPoint1.fY, outerPoint2.fX, outerPoint2.fY); 502 Vertex* innerVertex1 = fAlloc->make<Vertex>(innerPoint1, 255); 503 Vertex* innerVertex2 = fAlloc->make<Vertex>(innerPoint2, 255); 504 Vertex* outerVertex1 = fAlloc->make<Vertex>(outerPoint1, 0); 505 Vertex* outerVertex2 = fAlloc->make<Vertex>(outerPoint2, 0); 506 innerVertex1->fPartner = outerVertex1; 507 innerVertex2->fPartner = outerVertex2; 508 outerVertex1->fPartner = innerVertex1; 509 outerVertex2->fPartner = innerVertex2; 510 if (!inversion(innerVertices.fTail, innerVertex1, prevEdge, c)) { 511 innerInversion = false; 512 } 513 if (!inversion(outerVertices.fTail, outerVertex1, prevEdge, c)) { 514 outerInversion = false; 515 } 516 innerVertices.append(innerVertex1); 517 innerVertices.append(innerVertex2); 518 outerVertices.append(outerVertex1); 519 outerVertices.append(outerVertex2); 520 } else { 521 TESS_LOG("inner (%g, %g), ", innerPoint.fX, innerPoint.fY); 522 TESS_LOG("outer (%g, %g)\n", outerPoint.fX, outerPoint.fY); 523 Vertex* innerVertex = fAlloc->make<Vertex>(innerPoint, 255); 524 Vertex* outerVertex = fAlloc->make<Vertex>(outerPoint, 0); 525 innerVertex->fPartner = outerVertex; 526 outerVertex->fPartner = innerVertex; 527 if (!inversion(innerVertices.fTail, innerVertex, prevEdge, c)) { 528 innerInversion = false; 529 } 530 if (!inversion(outerVertices.fTail, outerVertex, prevEdge, c)) { 531 outerInversion = false; 532 } 533 innerVertices.append(innerVertex); 534 outerVertices.append(outerVertex); 535 } 536 } 537 prevInner = inner; 538 prevOuter = outer; 539 prevV = v; 540 prevEdge = e; 541 prevNormal = normal; 542 } 543 if (!inversion(innerVertices.fTail, innerVertices.fHead, prevEdge, c)) { 544 innerInversion = false; 545 } 546 if (!inversion(outerVertices.fTail, outerVertices.fHead, prevEdge, c)) { 547 outerInversion = false; 548 } 549 // Outer edges get 1 winding, and inner edges get -2 winding. This ensures that the interior 550 // is always filled (1 + -2 = -1 for normal cases, 1 + 2 = 3 for thin features where the 551 // interior inverts). 552 // For total inversion cases, the shape has now reversed handedness, so invert the winding 553 // so it will be detected during collapseOverlapRegions(). 554 int innerWinding = innerInversion ? 2 : -2; 555 int outerWinding = outerInversion ? -1 : 1; 556 for (Vertex* v = innerVertices.fHead; v && v->fNext; v = v->fNext) { 557 this->makeConnectingEdge(v, v->fNext, EdgeType::kInner, c, innerWinding); 558 } 559 this->makeConnectingEdge(innerVertices.fTail, innerVertices.fHead, EdgeType::kInner, c, 560 innerWinding); 561 for (Vertex* v = outerVertices.fHead; v && v->fNext; v = v->fNext) { 562 this->makeConnectingEdge(v, v->fNext, EdgeType::kOuter, c, outerWinding); 563 } 564 this->makeConnectingEdge(outerVertices.fTail, outerVertices.fHead, EdgeType::kOuter, c, 565 outerWinding); 566 innerMesh->append(innerVertices); 567 fOuterMesh.append(outerVertices); 568} 569 570void GrAATriangulator::extractBoundary(EdgeList* boundary, Edge* e) const { 571 TESS_LOG("\nextracting boundary\n"); 572 bool down = this->applyFillType(e->fWinding); 573 Vertex* start = down ? e->fTop : e->fBottom; 574 do { 575 e->fWinding = down ? 1 : -1; 576 Edge* next; 577 e->fLine.normalize(); 578 e->fLine = e->fLine * e->fWinding; 579 boundary->append(e); 580 if (down) { 581 // Find outgoing edge, in clockwise order. 582 if ((next = e->fNextEdgeAbove)) { 583 down = false; 584 } else if ((next = e->fBottom->fLastEdgeBelow)) { 585 down = true; 586 } else if ((next = e->fPrevEdgeAbove)) { 587 down = false; 588 } 589 } else { 590 // Find outgoing edge, in counter-clockwise order. 591 if ((next = e->fPrevEdgeBelow)) { 592 down = true; 593 } else if ((next = e->fTop->fFirstEdgeAbove)) { 594 down = false; 595 } else if ((next = e->fNextEdgeBelow)) { 596 down = true; 597 } 598 } 599 e->disconnect(); 600 e = next; 601 } while (e && (down ? e->fTop : e->fBottom) != start); 602} 603 604// Stage 5b: Extract boundaries from mesh, simplify and stroke them into a new mesh. 605 606void GrAATriangulator::extractBoundaries(const VertexList& inMesh, VertexList* innerVertices, 607 const Comparator& c) const { 608 this->removeNonBoundaryEdges(inMesh); 609 for (Vertex* v = inMesh.fHead; v; v = v->fNext) { 610 while (v->fFirstEdgeBelow) { 611 EdgeList boundary; 612 this->extractBoundary(&boundary, v->fFirstEdgeBelow); 613 this->simplifyBoundary(&boundary, c); 614 this->strokeBoundary(&boundary, innerVertices, c); 615 } 616 } 617} 618 619Poly* GrAATriangulator::tessellate(const VertexList& mesh, const Comparator& c) const { 620 VertexList innerMesh; 621 this->extractBoundaries(mesh, &innerMesh, c); 622 SortMesh(&innerMesh, c); 623 SortMesh(&fOuterMesh, c); 624 this->mergeCoincidentVertices(&innerMesh, c); 625 bool was_complex = this->mergeCoincidentVertices(&fOuterMesh, c); 626 auto result = this->simplify(&innerMesh, c); 627 was_complex = (SimplifyResult::kFoundSelfIntersection == result) || was_complex; 628 result = this->simplify(&fOuterMesh, c); 629 was_complex = (SimplifyResult::kFoundSelfIntersection == result) || was_complex; 630 TESS_LOG("\ninner mesh before:\n"); 631 DUMP_MESH(innerMesh); 632 TESS_LOG("\nouter mesh before:\n"); 633 DUMP_MESH(fOuterMesh); 634 EventComparator eventLT(EventComparator::Op::kLessThan); 635 EventComparator eventGT(EventComparator::Op::kGreaterThan); 636 was_complex = this->collapseOverlapRegions(&innerMesh, c, eventLT) || was_complex; 637 was_complex = this->collapseOverlapRegions(&fOuterMesh, c, eventGT) || was_complex; 638 if (was_complex) { 639 TESS_LOG("found complex mesh; taking slow path\n"); 640 VertexList aaMesh; 641 TESS_LOG("\ninner mesh after:\n"); 642 DUMP_MESH(innerMesh); 643 TESS_LOG("\nouter mesh after:\n"); 644 DUMP_MESH(fOuterMesh); 645 this->connectPartners(&fOuterMesh, c); 646 this->connectPartners(&innerMesh, c); 647 SortedMerge(&innerMesh, &fOuterMesh, &aaMesh, c); 648 TESS_LOG("\nmerged mesh:\n"); 649 DUMP_MESH(aaMesh); 650 this->mergeCoincidentVertices(&aaMesh, c); 651 result = this->simplify(&aaMesh, c); 652 TESS_LOG("combined and simplified mesh:\n"); 653 DUMP_MESH(aaMesh); 654 fOuterMesh.fHead = fOuterMesh.fTail = nullptr; 655 return this->GrTriangulator::tessellate(aaMesh, c); 656 } else { 657 TESS_LOG("no complex polygons; taking fast path\n"); 658 return this->GrTriangulator::tessellate(innerMesh, c); 659 } 660} 661 662int GrAATriangulator::polysToAATriangles(Poly* polys, 663 GrEagerVertexAllocator* vertexAllocator) const { 664 int64_t count64 = CountPoints(polys, SkPathFillType::kWinding); 665 // Count the points from the outer mesh. 666 for (Vertex* v = fOuterMesh.fHead; v; v = v->fNext) { 667 for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) { 668 count64 += TRIANGULATOR_WIREFRAME ? 12 : 6; 669 } 670 } 671 if (0 == count64 || count64 > SK_MaxS32) { 672 return 0; 673 } 674 int count = count64; 675 676 size_t vertexStride = sizeof(SkPoint) + sizeof(float); 677 void* verts = vertexAllocator->lock(vertexStride, count); 678 if (!verts) { 679 SkDebugf("Could not allocate vertices\n"); 680 return 0; 681 } 682 683 TESS_LOG("emitting %d verts\n", count); 684 void* end = this->polysToTriangles(polys, verts, SkPathFillType::kWinding); 685 // Emit the triangles from the outer mesh. 686 for (Vertex* v = fOuterMesh.fHead; v; v = v->fNext) { 687 for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) { 688 Vertex* v0 = e->fTop; 689 Vertex* v1 = e->fBottom; 690 Vertex* v2 = e->fBottom->fPartner; 691 Vertex* v3 = e->fTop->fPartner; 692 end = this->emitTriangle(v0, v1, v2, 0/*winding*/, end); 693 end = this->emitTriangle(v0, v2, v3, 0/*winding*/, end); 694 } 695 } 696 697 int actualCount = static_cast<int>((static_cast<uint8_t*>(end) - static_cast<uint8_t*>(verts)) 698 / vertexStride); 699 SkASSERT(actualCount <= count); 700 vertexAllocator->unlock(actualCount); 701 return actualCount; 702} 703