bool HandleCoincidence(SkOpContourHead* contourList, SkOpCoincidence* coincidence, SkChunkAlloc* allocator) { SkOpGlobalState* globalState = contourList->globalState(); // combine t values when multiple intersections occur on some segments but not others moveMultiples(contourList); findCollapsed(contourList); // move t values and points together to eliminate small/tiny gaps moveNearby(contourList); align(contourList); // give all span members common values coincidence->fixAligned(); // aligning may have marked a coincidence pt-t deleted #if DEBUG_VALIDATE globalState->setPhase(SkOpGlobalState::kIntersecting); #endif // look for intersections on line segments formed by moving end points addAlignIntersections(contourList, allocator); coincidence->addMissing(allocator); #if DEBUG_VALIDATE globalState->setPhase(SkOpGlobalState::kWalking); #endif // check to see if, loosely, coincident ranges may be expanded if (coincidence->expand()) { coincidence->addExpanded(allocator PATH_OPS_DEBUG_VALIDATE_PARAMS(globalState)); } // the expanded ranges may not align -- add the missing spans coincidence->mark(); // mark spans of coincident segments as coincident // look for coincidence missed earlier if (missingCoincidence(contourList, coincidence, allocator)) { (void) coincidence->expand(); coincidence->addExpanded(allocator PATH_OPS_DEBUG_VALIDATE_PARAMS(globalState)); coincidence->mark(); } SkOpCoincidence overlaps; do { SkOpCoincidence* pairs = overlaps.isEmpty() ? coincidence : &overlaps; if (!pairs->apply()) { // adjust the winding value to account for coincident edges return false; } // For each coincident pair that overlaps another, when the receivers (the 1st of the pair) // are different, construct a new pair to resolve their mutual span pairs->findOverlaps(&overlaps, allocator); } while (!overlaps.isEmpty()); calcAngles(contourList, allocator); sortAngles(contourList); if (globalState->angleCoincidence()) { (void) missingCoincidence(contourList, coincidence, allocator); if (!coincidence->apply()) { return false; } } #if DEBUG_ACTIVE_SPANS coincidence->debugShowCoincidence(); DebugShowActiveSpans(contourList); #endif return true; }
this->fHead = coinRec; } static void t_range(const SkOpPtT* overS, const SkOpPtT* overE, double tStart, double tEnd, const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, double* coinTs, double* coinTe) { double denom = overE->fT - overS->fT; double start = 0 < denom ? tStart : tEnd; double end = 0 < denom ? tEnd : tStart; double sRatio = (start - overS->fT) / denom; double eRatio = (end - overS->fT) / denom; *coinTs = coinPtTStart->fT + (coinPtTEnd->fT - coinPtTStart->fT) * sRatio; *coinTe = coinPtTStart->fT + (coinPtTEnd->fT - coinPtTStart->fT) * eRatio; } bool SkOpCoincidence::addExpanded(SkChunkAlloc* allocator PATH_OPS_DEBUG_VALIDATE_PARAMS(SkOpGlobalState* globalState)) { #if DEBUG_VALIDATE globalState->setPhase(SkOpGlobalState::kIntersecting); #endif // for each coincident pair, match the spans // if the spans don't match, add the mssing pt to the segment and loop it in the opposite span SkCoincidentSpans* coin = this->fHead; SkASSERT(coin); do { SkOpPtT* startPtT = coin->fCoinPtTStart; SkOpPtT* oStartPtT = coin->fOppPtTStart; SkASSERT(startPtT->contains(oStartPtT)); SkASSERT(coin->fCoinPtTEnd->contains(coin->fOppPtTEnd)); SkOpSpanBase* start = startPtT->span(); SkOpSpanBase* oStart = oStartPtT->span(); const SkOpSpanBase* end = coin->fCoinPtTEnd->span();