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