10#if !defined(SK_ENABLE_OPTIMIZE_SIZE)
19#include <unordered_map>
23#if TRIANGULATOR_LOGGING
24#define TESS_LOG SkDebugf
25#define DUMP_MESH(MESH) (MESH).dump()
28#define DUMP_MESH(MESH)
82 if (bisector1.intersect(bisector2, &
p, &alpha)) {
83 TESS_LOG(
"found edge event for %g, %g (original %g -> %g), "
84 "will collapse to %g,%g alpha %d\n",
85 prev->fID,
next->fID,
e->fEdge->fTop->fID,
e->fEdge->fBottom->fID,
p.fX,
p.fY,
88 events->push(
e->fEvent);
99 if (!top || !bottom ) {
106 uint8_t alpha =
dest->fAlpha;
107 if (
line.intersect(bisector.fLine, &
p) && !c.
sweep_lt(
p, top->fPoint) &&
109 TESS_LOG(
"found p edge event for %g, %g (original %g -> %g), "
110 "will collapse to %g,%g alpha %d\n",
111 dest->fID, v->fID, top->fID, bottom->fID,
p.fX,
p.fY, alpha);
113 events->push(edge->fEvent);
118 for (
Vertex* outer =
mesh->fHead; outer; outer = outer->fNext) {
119 if (
Vertex* inner = outer->fPartner) {
120 if ((inner->fPrev || inner->fNext) && (outer->fPrev || outer->fNext)) {
125 inner->fPartner = outer->fPartner =
nullptr;
132#if TRIANGULATOR_LOGGING
133 for (
SSEdge* edge : ssEdges) {
150void GrAATriangulator::removeNonBoundaryEdges(
const VertexList&
mesh)
const {
151 TESS_LOG(
"removing non-boundary edges\n");
153 for (
Vertex* v =
mesh.fHead; v !=
nullptr; v = v->fNext) {
154 if (!v->isConnected()) {
157 Edge* leftEnclosingEdge;
158 Edge* rightEnclosingEdge;
160 bool prevFilled = leftEnclosingEdge && this->
applyFillType(leftEnclosingEdge->fWinding);
161 for (
Edge*
e = v->fFirstEdgeAbove;
e;) {
165 if (filled == prevFilled) {
172 for (
Edge*
e = v->fFirstEdgeBelow;
e;
e =
e->fNextEdgeBelow) {
174 e->fWinding +=
prev->fWinding;
197 Vertex*
prev = prevEdge->fWinding == 1 ? prevEdge->fTop : prevEdge->fBottom;
199 double distPrev =
e->dist(
prev->fPoint);
200 double distNext = prevEdge->dist(
next->fPoint);
203 constexpr double kQuarterPixelSq = 0.25f * 0.25f;
205 boundary->
remove(prevEdge);
207 prevEdge = boundary->
fTail;
212 }
else if (prevNormal.
dot(normal) < 0.0 &&
213 (distPrev * distPrev <= kQuarterPixelSq || distNext * distNext <= kQuarterPixelSq)) {
216 join->fLine.normalize();
220 boundary->
remove(prevEdge);
223 prevEdge =
join->fLeft;
226 prevEdge = boundary->
fTail;
242 TESS_LOG(
"ss_connecting vertex %g to vertex %g\n", v->fID,
dest->fID);
245 }
else if (v->fPartner) {
246 TESS_LOG(
"setting %g's partner to %g ", v->fPartner->fID,
dest->fID);
247 TESS_LOG(
"and %g's partner to null\n", v->fID);
248 v->fPartner->fPartner =
dest;
249 v->fPartner =
nullptr;
262 if (!prevEdge || !nextEdge || !prevEdge->
fEdge || !nextEdge->
fEdge) {
266 dest->fSynthetic =
true;
268 TESS_LOG(
"collapsing %g, %g (original edge %g -> %g) to %g (%g, %g) alpha %d\n",
273 triangulator->connectSSEdge(
prev,
dest, c);
274 triangulator->connectSSEdge(
next,
dest, c);
277 ssv->
fPrev = prevEdge;
278 ssv->
fNext = nextEdge;
292 triangulator->computeBisector(prevEdge->
fEdge, nextEdge->
fEdge,
dest);
294 if (
dest->fPartner) {
295 triangulator->makeEvent(prevEdge, events);
296 triangulator->makeEvent(nextEdge, events);
298 triangulator->makeEvent(prevEdge, prevEdge->
fPrev->
fVertex, nextEdge,
dest, events, c);
299 triangulator->makeEvent(nextEdge, nextEdge->
fNext->
fVertex, prevEdge,
dest, events, c);
306 return e->fWinding != 0 &&
e->fWinding != 1;
308 return e->fWinding != 0 &&
e->fWinding != -2;
318 TESS_LOG(
"\nfinding overlap regions\n");
323 for (
Vertex* v =
mesh->fHead; v !=
nullptr; v = v->fNext) {
324 if (!v->isConnected()) {
327 Edge* leftEnclosingEdge;
328 Edge* rightEnclosingEdge;
330 for (
Edge*
e = v->fLastEdgeAbove;
e &&
e != leftEnclosingEdge;) {
331 Edge*
prev =
e->fPrevEdgeAbove ?
e->fPrevEdgeAbove : leftEnclosingEdge;
336 (!
prev ||
prev->fWinding == 0 ||
e->fWinding == 0);
338 e->fWinding -=
prev->fWinding;
340 if (leftOverlap && rightOverlap) {
341 TESS_LOG(
"found interior overlap edge %g -> %g, disconnecting\n",
342 e->fTop->fID,
e->fBottom->fID);
344 }
else if (leftOverlap || rightOverlap) {
345 TESS_LOG(
"found overlap edge %g -> %g%s\n",
346 e->fTop->fID,
e->fBottom->fID,
347 isOuterBoundary ?
", is outer boundary" :
"");
348 Vertex* prevVertex =
e->fWinding < 0 ?
e->fBottom :
e->fTop;
349 Vertex* nextVertex =
e->fWinding < 0 ?
e->fTop :
e->fBottom;
350 SSVertex* ssPrev = ssVertices[prevVertex];
354 SSVertex* ssNext = ssVertices[nextVertex];
359 ssEdges.push_back(ssEdge);
362 this->makeEvent(ssEdge, &events);
363 if (!isOuterBoundary) {
378 for (
Edge*
e = v->fFirstEdgeBelow;
e;
e =
e->fNextEdgeBelow) {
380 e->fWinding +=
prev->fWinding;
386 bool complex = !events.empty();
388 TESS_LOG(
"\ncollapsing overlap regions\n");
391 while (!events.empty()) {
392 Event*
event = events.top();
394 event->apply(
mesh, c, &events,
this);
398 for (
SSEdge* edge : ssEdges) {
411 return winding != origEdge->fWinding;
426 Vertex* prevV = prevEdge->fWinding > 0 ? prevEdge->fTop : prevEdge->fBottom;
430 Line prevInner(prevEdge->fLine);
431 prevInner.fC -= radius;
432 Line prevOuter(prevEdge->fLine);
433 prevOuter.fC += radius;
436 bool innerInversion =
true;
437 bool outerInversion =
true;
438 for (
Edge*
e = boundary->
fHead;
e !=
nullptr;
e =
e->fRight) {
439 Vertex* v =
e->fWinding > 0 ?
e->fTop :
e->fBottom;
442 Line inner(
e->fLine);
444 Line outer(
e->fLine);
446 SkPoint innerPoint, outerPoint;
447 TESS_LOG(
"stroking vertex %g (%g, %g)\n", v->fID, v->fPoint.
fX, v->fPoint.
fY);
448 if (!prevEdge->fLine.nearParallel(
e->fLine) && prevInner.intersect(inner, &innerPoint) &&
449 prevOuter.intersect(outer, &outerPoint)) {
450 float cosAngle =
normal.dot(prevNormal);
452 Vertex* nextV =
e->fWinding > 0 ?
e->fBottom :
e->fTop;
455 Line bisector(innerPoint, outerPoint);
457 if (tangent.fA == 0 && tangent.fB == 0) {
461 Line innerTangent(tangent);
462 Line outerTangent(tangent);
463 innerTangent.fC -= 0.5;
464 outerTangent.fC += 0.5;
465 SkPoint innerPoint1, innerPoint2, outerPoint1, outerPoint2;
466 if (prevNormal.
cross(normal) > 0) {
468 if (!innerTangent.intersect(prevInner, &innerPoint1) ||
469 !innerTangent.intersect(inner, &innerPoint2) ||
470 !outerTangent.intersect(bisector, &outerPoint)) {
473 Line prevTangent(prevV->fPoint,
475 Line nextTangent(nextV->fPoint,
477 if (prevTangent.dist(outerPoint) > 0) {
478 bisector.intersect(prevTangent, &outerPoint);
480 if (nextTangent.dist(outerPoint) < 0) {
481 bisector.intersect(nextTangent, &outerPoint);
483 outerPoint1 = outerPoint2 = outerPoint;
486 if (!outerTangent.intersect(prevOuter, &outerPoint1) ||
487 !outerTangent.intersect(outer, &outerPoint2)) {
490 Line prevTangent(prevV->fPoint,
492 Line nextTangent(nextV->fPoint,
494 if (prevTangent.dist(innerPoint) > 0) {
495 bisector.intersect(prevTangent, &innerPoint);
497 if (nextTangent.dist(innerPoint) < 0) {
498 bisector.intersect(nextTangent, &innerPoint);
500 innerPoint1 = innerPoint2 = innerPoint;
506 TESS_LOG(
"inner (%g, %g), (%g, %g), ",
507 innerPoint1.
fX, innerPoint1.
fY, innerPoint2.
fX, innerPoint2.
fY);
508 TESS_LOG(
"outer (%g, %g), (%g, %g)\n",
509 outerPoint1.
fX, outerPoint1.
fY, outerPoint2.
fX, outerPoint2.
fY);
514 innerVertex1->fPartner = outerVertex1;
515 innerVertex2->fPartner = outerVertex2;
516 outerVertex1->fPartner = innerVertex1;
517 outerVertex2->fPartner = innerVertex2;
519 innerInversion =
false;
522 outerInversion =
false;
524 innerVertices.
append(innerVertex1);
525 innerVertices.
append(innerVertex2);
526 outerVertices.
append(outerVertex1);
527 outerVertices.
append(outerVertex2);
529 TESS_LOG(
"inner (%g, %g), ", innerPoint.
fX, innerPoint.
fY);
530 TESS_LOG(
"outer (%g, %g)\n", outerPoint.
fX, outerPoint.
fY);
533 innerVertex->fPartner = outerVertex;
534 outerVertex->fPartner = innerVertex;
536 innerInversion =
false;
539 outerInversion =
false;
541 innerVertices.
append(innerVertex);
542 outerVertices.
append(outerVertex);
552 innerInversion =
false;
555 outerInversion =
false;
562 int innerWinding = innerInversion ? 2 : -2;
563 int outerWinding = outerInversion ? -1 : 1;
564 for (
Vertex* v = innerVertices.
fHead; v && v->fNext; v = v->fNext) {
569 for (
Vertex* v = outerVertices.
fHead; v && v->fNext; v = v->fNext) {
574 innerMesh->
append(innerVertices);
575 fOuterMesh.
append(outerVertices);
578void GrAATriangulator::extractBoundary(
EdgeList* boundary,
Edge*
e)
const {
579 TESS_LOG(
"\nextracting boundary\n");
583 e->fWinding = down ? 1 : -1;
585 e->fLine.normalize();
586 e->fLine =
e->fLine *
e->fWinding;
590 if ((
next =
e->fNextEdgeAbove)) {
592 }
else if ((
next =
e->fBottom->fLastEdgeBelow)) {
594 }
else if ((
next =
e->fPrevEdgeAbove)) {
599 if ((
next =
e->fPrevEdgeBelow)) {
601 }
else if ((
next =
e->fTop->fFirstEdgeAbove)) {
603 }
else if ((
next =
e->fNextEdgeBelow)) {
609 }
while (
e && (down ?
e->fTop :
e->fBottom) !=
start);
616 this->removeNonBoundaryEdges(inMesh);
618 while (v->fFirstEdgeBelow) {
620 this->extractBoundary(&boundary, v->fFirstEdgeBelow);
621 this->simplifyBoundary(&boundary, c);
622 this->strokeBoundary(&boundary, innerVertices, c);
629 this->extractBoundaries(
mesh, &innerMesh, c);
636 return {
nullptr,
false };
641 return {
nullptr,
false };
650 was_complex = this->collapseOverlapRegions(&innerMesh, c, eventLT) || was_complex;
651 was_complex = this->collapseOverlapRegions(&fOuterMesh, c, eventGT) || was_complex;
653 TESS_LOG(
"found complex mesh; taking slow path\n");
659 this->connectPartners(&fOuterMesh, c);
660 this->connectPartners(&innerMesh, c);
667 return {
nullptr,
false };
669 TESS_LOG(
"combined and simplified mesh:\n");
671 fOuterMesh.
fHead = fOuterMesh.
fTail =
nullptr;
674 TESS_LOG(
"no complex polygons; taking fast path\n");
679int GrAATriangulator::polysToAATriangles(
Poly* polys,
683 for (
Vertex* v = fOuterMesh.
fHead; v; v = v->fNext) {
684 for (
Edge*
e = v->fFirstEdgeBelow;
e;
e =
e->fNextEdgeBelow) {
688 if (0 == count64 || count64 >
SK_MaxS32) {
693 size_t vertexStride =
sizeof(
SkPoint) +
sizeof(
float);
696 SkDebugf(
"Could not allocate vertices\n");
704 for (
Vertex* v = fOuterMesh.
fHead; v; v = v->fNext) {
705 for (
Edge*
e = v->fFirstEdgeBelow;
e;
e =
e->fNextEdgeBelow) {
709 Vertex* v3 =
e->fTop->fPartner;
715 int actualCount =
static_cast<int>((verts.
mark() -
start) / vertexStride);
717 vertexAllocator->
unlock(actualCount);
GrTriangulator::VertexList VertexList
GrAATriangulator::EventList EventList
GrAATriangulator::SSEdge SSEdge
GrTriangulator::Comparator Comparator
GrTriangulator::Vertex Vertex
GrTriangulator::Line Line
static void get_edge_normal(const Edge *e, SkVector *normal)
GrTriangulator::Edge Edge
static void dump_skel(const SSEdgeList &ssEdges)
static constexpr float kCosMiterAngle
GrAATriangulator::EventComparator EventComparator
GrAATriangulator::Event Event
GrTriangulator::EdgeList EdgeList
std::vector< SSEdge * > SSEdgeList
GrTriangulator::Poly Poly
static bool is_overlap_edge(Edge *e)
static bool inversion(Vertex *prev, Vertex *next, Edge *origEdge, const Comparator &c)
std::unordered_map< Vertex *, SSVertex * > SSVertexMap
std::priority_queue< Event *, std::vector< Event * >, EventComparator > EventPQ
#define TRIANGULATOR_WIREFRAME
static float next(float f)
static float prev(float f)
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static constexpr int32_t SK_MaxS32
#define SkScalarCopySign(x, y)
#define SkDoubleToScalar(x)
skgpu::VertexWriter lockWriter(size_t stride, int eagerCount)
virtual void unlock(int actualCount)=0
static int64_t CountPoints(Poly *polys, SkPathFillType overrideFillType)
static void SortMesh(VertexList *vertices, const Comparator &)
Edge * makeEdge(Vertex *prev, Vertex *next, EdgeType type, const Comparator &)
SkArenaAlloc *const fAlloc
bool applyFillType(int winding) const
SimplifyResult simplify(VertexList *mesh, const Comparator &)
virtual std::tuple< Poly *, bool > tessellate(const VertexList &vertices, const Comparator &)
skgpu::VertexWriter polysToTriangles(Poly *polys, SkPathFillType overrideFillType, skgpu::VertexWriter data) const
static void SortedMerge(VertexList *front, VertexList *back, VertexList *result, const Comparator &)
Edge * makeConnectingEdge(Vertex *prev, Vertex *next, EdgeType, const Comparator &, int windingScale=1)
static void FindEnclosingEdges(const Vertex &v, const EdgeList &edges, Edge **left, Edge **right)
skgpu::VertexWriter emitTriangle(Vertex *prev, Vertex *curr, Vertex *next, int winding, skgpu::VertexWriter data) const
bool mergeCoincidentVertices(VertexList *mesh, const Comparator &) const
auto make(Ctor &&ctor) -> decltype(ctor(nullptr))
static SkString join(const CommandLineFlags::StringArray &)
EventList(EventComparator comparison)
void apply(VertexList *mesh, const Comparator &, EventList *events, GrAATriangulator *)
SSEdge(Edge *edge, SSVertex *prev, SSVertex *next)
bool sweep_lt(const SkPoint &a, const SkPoint &b) const
void insert(Edge *edge, Edge *prev, Edge *next)
float dot(const SkVector &vec) const
static constexpr SkPoint Make(float x, float y)
float cross(const SkVector &vec) const
Mark mark(size_t offset=0) const