示例#1
0
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();