const SkOpAngle* AngleWinding(SkOpSpanBase* start, SkOpSpanBase* end, int* windingPtr, bool* sortablePtr) { // find first angle, initialize winding to computed fWindSum SkOpSegment* segment = start->segment(); const SkOpAngle* angle = segment->spanToAngle(start, end); if (!angle) { *windingPtr = SK_MinS32; return nullptr; } bool computeWinding = false; const SkOpAngle* firstAngle = angle; bool loop = false; bool unorderable = false; int winding = SK_MinS32; do { angle = angle->next(); if (!angle) { return nullptr; } unorderable |= angle->unorderable(); if ((computeWinding = unorderable || (angle == firstAngle && loop))) { break; // if we get here, there's no winding, loop is unorderable } loop |= angle == firstAngle; segment = angle->segment(); winding = segment->windSum(angle); } while (winding == SK_MinS32); // if the angle loop contains an unorderable span, the angle order may be useless // directly compute the winding in this case for each span if (computeWinding) { firstAngle = angle; winding = SK_MinS32; do { SkOpSpanBase* startSpan = angle->start(); SkOpSpanBase* endSpan = angle->end(); SkOpSpan* lesser = startSpan->starter(endSpan); int testWinding = lesser->windSum(); if (testWinding == SK_MinS32) { testWinding = lesser->computeWindSum(); } if (testWinding != SK_MinS32) { segment = angle->segment(); winding = testWinding; } angle = angle->next(); } while (angle != firstAngle); } *sortablePtr = !unorderable; *windingPtr = winding; return angle; }
SkOpSegment* FindChase(SkTDArray<SkOpSpan*>* chase, int* tIndex, int* endIndex) { while (chase->count()) { SkOpSpan* span; chase->pop(&span); const SkOpSpan& backPtr = span->fOther->span(span->fOtherIndex); SkOpSegment* segment = backPtr.fOther; *tIndex = backPtr.fOtherIndex; bool sortable = true; bool done = true; *endIndex = -1; if (const SkOpAngle* last = segment->activeAngle(*tIndex, tIndex, endIndex, &done, &sortable)) { *tIndex = last->start(); *endIndex = last->end(); #if TRY_ROTATE *chase->insert(0) = span; #else *chase->append() = span; #endif return last->segment(); } if (done) { continue; } if (!sortable) { continue; } // find first angle, initialize winding to computed fWindSum const SkOpAngle* angle = segment->spanToAngle(*tIndex, *endIndex); const SkOpAngle* firstAngle; SkDEBUGCODE(firstAngle = angle); SkDEBUGCODE(bool loop = false); int winding; do { angle = angle->next(); SkASSERT(angle != firstAngle || !loop); SkDEBUGCODE(loop |= angle == firstAngle); segment = angle->segment(); winding = segment->windSum(angle); } while (winding == SK_MinS32); int spanWinding = segment->spanSign(angle->start(), angle->end()); #if DEBUG_WINDING SkDebugf("%s winding=%d spanWinding=%d\n", __FUNCTION__, winding, spanWinding); #endif // turn span winding into contour winding if (spanWinding * winding < 0) { winding += spanWinding; } // we care about first sign and whether wind sum indicates this // edge is inside or outside. Maybe need to pass span winding // or first winding or something into this function? // advance to first undone angle, then return it and winding // (to set whether edges are active or not) firstAngle = angle; winding -= firstAngle->segment()->spanSign(firstAngle); while ((angle = angle->next()) != firstAngle) { segment = angle->segment(); int maxWinding = winding; winding -= segment->spanSign(angle); #if DEBUG_SORT SkDebugf("%s id=%d maxWinding=%d winding=%d sign=%d\n", __FUNCTION__, segment->debugID(), maxWinding, winding, angle->sign()); #endif *tIndex = angle->start(); *endIndex = angle->end(); int lesser = SkMin32(*tIndex, *endIndex); const SkOpSpan& nextSpan = segment->span(lesser); if (!nextSpan.fDone) { // FIXME: this be wrong? assign startWinding if edge is in // same direction. If the direction is opposite, winding to // assign is flipped sign or +/- 1? if (SkOpSegment::UseInnerWinding(maxWinding, winding)) { maxWinding = winding; } (void) segment->markAndChaseWinding(angle, maxWinding, 0); break; } } *chase->insert(0) = span; return segment; } return NULL; }
static SkOpSegment* findChaseOp(SkTDArray<SkOpSpan*>& chase, int* tIndex, int* endIndex) { while (chase.count()) { SkOpSpan* span; chase.pop(&span); const SkOpSpan& backPtr = span->fOther->span(span->fOtherIndex); SkOpSegment* segment = backPtr.fOther; *tIndex = backPtr.fOtherIndex; bool sortable = true; bool done = true; *endIndex = -1; if (const SkOpAngle* last = segment->activeAngle(*tIndex, tIndex, endIndex, &done, &sortable)) { if (last->unorderable()) { continue; } *tIndex = last->start(); *endIndex = last->end(); #if TRY_ROTATE *chase.insert(0) = span; #else *chase.append() = span; #endif return last->segment(); } if (done) { continue; } if (!sortable) { continue; } // find first angle, initialize winding to computed fWindSum const SkOpAngle* angle = segment->spanToAngle(*tIndex, *endIndex); if (!angle) { continue; } const SkOpAngle* firstAngle = angle; SkDEBUGCODE(bool loop = false); int winding; do { angle = angle->next(); SkASSERT(angle != firstAngle || !loop); SkDEBUGCODE(loop |= angle == firstAngle); segment = angle->segment(); winding = segment->windSum(angle); } while (winding == SK_MinS32); int sumMiWinding = segment->updateWindingReverse(angle); int sumSuWinding = segment->updateOppWindingReverse(angle); if (segment->operand()) { SkTSwap<int>(sumMiWinding, sumSuWinding); } SkOpSegment* first = NULL; while ((angle = angle->next()) != firstAngle) { segment = angle->segment(); int start = angle->start(); int end = angle->end(); int maxWinding, sumWinding, oppMaxWinding, oppSumWinding; segment->setUpWindings(start, end, &sumMiWinding, &sumSuWinding, &maxWinding, &sumWinding, &oppMaxWinding, &oppSumWinding); if (!segment->done(angle)) { if (!first) { first = segment; *tIndex = start; *endIndex = end; } // OPTIMIZATION: should this also add to the chase? (void) segment->markAngle(maxWinding, sumWinding, oppMaxWinding, oppSumWinding, angle); } } if (first) { #if TRY_ROTATE *chase.insert(0) = span; #else *chase.append() = span; #endif return first; } } return NULL; }