bool SkOpCoincidence::addOrOverlap()

in src/pathops/SkOpCoincidence.cpp [668:791]


bool SkOpCoincidence::addOrOverlap(SkOpSegment* coinSeg, SkOpSegment* oppSeg,
        double coinTs, double coinTe, double oppTs, double oppTe, bool* added) {
    SkTDArray<SkCoincidentSpans*> overlaps;
    FAIL_IF(!fTop);
    if (!this->checkOverlap(fTop, coinSeg, oppSeg, coinTs, coinTe, oppTs, oppTe, &overlaps)) {
        return true;
    }
    if (fHead && !this->checkOverlap(fHead, coinSeg, oppSeg, coinTs,
            coinTe, oppTs, oppTe, &overlaps)) {
        return true;
    }
    SkCoincidentSpans* overlap = !overlaps.empty() ? overlaps[0] : nullptr;
    for (int index = 1; index < overlaps.size(); ++index) { // combine overlaps before continuing
        SkCoincidentSpans* test = overlaps[index];
        if (overlap->coinPtTStart()->fT > test->coinPtTStart()->fT) {
            overlap->setCoinPtTStart(test->coinPtTStart());
        }
        if (overlap->coinPtTEnd()->fT < test->coinPtTEnd()->fT) {
            overlap->setCoinPtTEnd(test->coinPtTEnd());
        }
        if (overlap->flipped()
                ? overlap->oppPtTStart()->fT < test->oppPtTStart()->fT
                : overlap->oppPtTStart()->fT > test->oppPtTStart()->fT) {
            overlap->setOppPtTStart(test->oppPtTStart());
        }
        if (overlap->flipped()
                ? overlap->oppPtTEnd()->fT > test->oppPtTEnd()->fT
                : overlap->oppPtTEnd()->fT < test->oppPtTEnd()->fT) {
            overlap->setOppPtTEnd(test->oppPtTEnd());
        }
        if (!fHead || !this->release(fHead, test)) {
            SkAssertResult(this->release(fTop, test));
        }
    }
    const SkOpPtT* cs = coinSeg->existing(coinTs, oppSeg);
    const SkOpPtT* ce = coinSeg->existing(coinTe, oppSeg);
    if (overlap && cs && ce && overlap->contains(cs, ce)) {
        return true;
    }
    FAIL_IF(cs == ce && cs);
    const SkOpPtT* os = oppSeg->existing(oppTs, coinSeg);
    const SkOpPtT* oe = oppSeg->existing(oppTe, coinSeg);
    if (overlap && os && oe && overlap->contains(os, oe)) {
        return true;
    }
    FAIL_IF(cs && cs->deleted());
    FAIL_IF(os && os->deleted());
    FAIL_IF(ce && ce->deleted());
    FAIL_IF(oe && oe->deleted());
    const SkOpPtT* csExisting = !cs ? coinSeg->existing(coinTs, nullptr) : nullptr;
    const SkOpPtT* ceExisting = !ce ? coinSeg->existing(coinTe, nullptr) : nullptr;
    FAIL_IF(csExisting && csExisting == ceExisting);
//    FAIL_IF(csExisting && (csExisting == ce ||
//            csExisting->contains(ceExisting ? ceExisting : ce)));
    FAIL_IF(ceExisting && (ceExisting == cs ||
            ceExisting->contains(csExisting ? csExisting : cs)));
    const SkOpPtT* osExisting = !os ? oppSeg->existing(oppTs, nullptr) : nullptr;
    const SkOpPtT* oeExisting = !oe ? oppSeg->existing(oppTe, nullptr) : nullptr;
    FAIL_IF(osExisting && osExisting == oeExisting);
    FAIL_IF(osExisting && (osExisting == oe ||
            osExisting->contains(oeExisting ? oeExisting : oe)));
    FAIL_IF(oeExisting && (oeExisting == os ||
            oeExisting->contains(osExisting ? osExisting : os)));
    // extra line in debug code
    this->debugValidate();
    if (!cs || !os) {
        SkOpPtT* csWritable = cs ? const_cast<SkOpPtT*>(cs)
            : coinSeg->addT(coinTs);
        if (csWritable == ce) {
            return true;
        }
        SkOpPtT* osWritable = os ? const_cast<SkOpPtT*>(os)
            : oppSeg->addT(oppTs);
        FAIL_IF(!csWritable || !osWritable);
        csWritable->span()->addOpp(osWritable->span());
        cs = csWritable;
        os = osWritable->active();
        FAIL_IF(!os);
        FAIL_IF((ce && ce->deleted()) || (oe && oe->deleted()));
    }
    if (!ce || !oe) {
        SkOpPtT* ceWritable = ce ? const_cast<SkOpPtT*>(ce)
            : coinSeg->addT(coinTe);
        SkOpPtT* oeWritable = oe ? const_cast<SkOpPtT*>(oe)
            : oppSeg->addT(oppTe);
        FAIL_IF(!ceWritable->span()->addOpp(oeWritable->span()));
        ce = ceWritable;
        oe = oeWritable;
    }
    this->debugValidate();
    FAIL_IF(cs->deleted());
    FAIL_IF(os->deleted());
    FAIL_IF(ce->deleted());
    FAIL_IF(oe->deleted());
    FAIL_IF(cs->contains(ce) || os->contains(oe));
    bool result = true;
    if (overlap) {
        if (overlap->coinPtTStart()->segment() == coinSeg) {
            result = overlap->extend(cs, ce, os, oe);
        } else {
            if (os->fT > oe->fT) {
                using std::swap;
                swap(cs, ce);
                swap(os, oe);
            }
            result = overlap->extend(os, oe, cs, ce);
        }
#if DEBUG_COINCIDENCE_VERBOSE
        if (result) {
            overlaps[0]->debugShow();
        }
#endif
    } else {
        this->add(cs, ce, os, oe);
#if DEBUG_COINCIDENCE_VERBOSE
        fHead->debugShow();
#endif
    }
    this->debugValidate();
    if (result) {
        *added = true;
    }
    return true;
}