Ejemplo n.º 1
0
void SkOpSpan::release(const SkOpPtT* kept) {
    SkDEBUGCODE(fDebugDeleted = true);
    SkOPASSERT(kept->span() != this);
    SkASSERT(!final());
    SkOpSpan* prev = this->prev();
    SkASSERT(prev);
    SkOpSpanBase* next = this->next();
    SkASSERT(next);
    prev->setNext(next);
    next->setPrev(prev);
    this->segment()->release(this);
    SkOpCoincidence* coincidence = this->globalState()->coincidence();
    if (coincidence) {
        coincidence->fixUp(this->ptT(), kept);
    }
    this->ptT()->setDeleted();
    SkOpPtT* stopPtT = this->ptT();
    SkOpPtT* testPtT = stopPtT;
    const SkOpSpanBase* keptSpan = kept->span();
    do {
        if (this == testPtT->span()) {
            testPtT->setSpan(keptSpan);
        }
    } while ((testPtT = testPtT->next()) != stopPtT);
}
Ejemplo n.º 2
0
// Please keep this in sync with debugInsertCoincidence()
bool SkOpSpan::insertCoincidence(const SkOpSegment* segment, bool flipped, bool ordered) {
    if (this->containsCoincidence(segment)) {
        return true;
    }
    SkOpPtT* next = &fPtT;
    while ((next = next->next()) != &fPtT) {
        if (next->segment() == segment) {
            SkOpSpan* span;
            SkOpSpanBase* base = next->span();
            if (!ordered) {
                const SkOpPtT* spanEndPtT = fNext->contains(segment);
                FAIL_IF(!spanEndPtT);
                const SkOpSpanBase* spanEnd = spanEndPtT->span();
                const SkOpPtT* start = base->ptT()->starter(spanEnd->ptT());
                FAIL_IF(!start->span()->upCastable());
                span = const_cast<SkOpSpan*>(start->span()->upCast());
            } else if (flipped) {
                span = base->prev();
                FAIL_IF(!span);
            } else {
                FAIL_IF(!base->upCastable());
                span = base->upCast();
            }
            this->insertCoincidence(span);
            return true;
        }
    }
#if DEBUG_COINCIDENCE
    SkASSERT(0); // FIXME? if we get here, the span is missing its opposite segment...
#endif
    return true;
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
0
// please keep in sync with debugMergeMatches()
// Look to see if pt-t linked list contains same segment more than once
// if so, and if each pt-t is directly pointed to by spans in that segment,
// merge them
// keep the points, but remove spans so that the segment doesn't have 2 or more
// spans pointing to the same pt-t loop at different loop elements
void SkOpSpanBase::mergeMatches(SkOpSpanBase* opp) {
    SkOpPtT* test = &fPtT;
    SkOpPtT* testNext;
    const SkOpPtT* stop = test;
    do {
        testNext = test->next();
        if (test->deleted()) {
            continue;
        }
        SkOpSpanBase* testBase = test->span();
        SkASSERT(testBase->ptT() == test);
        SkOpSegment* segment = test->segment();
        if (segment->done()) {
            continue;
        }
        SkOpPtT* inner = opp->ptT();
        const SkOpPtT* innerStop = inner;
        do {
            if (inner->segment() != segment) {
                continue;
            }
            if (inner->deleted()) {
                continue;
            }
            SkOpSpanBase* innerBase = inner->span();
            SkASSERT(innerBase->ptT() == inner);
            // when the intersection is first detected, the span base is marked if there are 
            // more than one point in the intersection.
            if (!zero_or_one(inner->fT)) {
                innerBase->upCast()->release(test);
            } else {
                SkOPASSERT(inner->fT != test->fT);
                if (!zero_or_one(test->fT)) {
                    testBase->upCast()->release(inner);
                } else {
                    segment->markAllDone();  // mark segment as collapsed
                    SkDEBUGCODE(testBase->debugSetDeleted());
                    test->setDeleted();
                    SkDEBUGCODE(innerBase->debugSetDeleted());
                    inner->setDeleted();
                }
            }
#ifdef SK_DEBUG   // assert if another undeleted entry points to segment
            const SkOpPtT* debugInner = inner;
            while ((debugInner = debugInner->next()) != innerStop) {
                if (debugInner->segment() != segment) {
                    continue;
                }
                if (debugInner->deleted()) {
                    continue;
                }
                SkOPASSERT(0);
            }
#endif
            break;
        } while ((inner = inner->next()) != innerStop);
    } while ((test = testNext) != stop);
    this->checkForCollapsedCoincidence();
}
Ejemplo n.º 5
0
SkOpSegment* SkOpContour::nonVerticalSegment(SkOpSpanBase** start, SkOpSpanBase** end) {
    int segmentCount = fSortedSegments.count();
    SkASSERT(segmentCount > 0);
    for (int sortedIndex = fFirstSorted; sortedIndex < segmentCount; ++sortedIndex) {
        SkOpSegment* testSegment = fSortedSegments[sortedIndex];
        if (testSegment->done()) {
            continue;
        }
        SkOpSpanBase* span = testSegment->head();
        SkOpSpanBase* testS, * testE;
        while (SkOpSegment::NextCandidate(span, &testS, &testE)) {
            if (!testSegment->isVertical(testS, testE)) {
                *start = testS;
                *end = testE;
                return testSegment;
            }
            span = span->upCast()->next();
        }
    }
    return NULL;
}
Ejemplo n.º 6
0
SkOpSegment* FindChase(SkTDArray<SkOpSpanBase*>* chase, SkOpSpanBase** startPtr,
        SkOpSpanBase** endPtr) {
    while (chase->count()) {
        SkOpSpanBase* span;
        chase->pop(&span);
        SkOpSegment* segment = span->segment();
        *startPtr = span->ptT()->next()->span();
        bool done = true;
        *endPtr = nullptr;
        if (SkOpAngle* last = segment->activeAngle(*startPtr, startPtr, endPtr, &done)) {
            *startPtr = last->start();
            *endPtr = last->end();
    #if TRY_ROTATE
            *chase->insert(0) = span;
    #else
            *chase->append() = span;
    #endif
            return last->segment();
        }
        if (done) {
            continue;
        }
        // find first angle, initialize winding to computed wind sum
        int winding;
        bool sortable;
        const SkOpAngle* angle = AngleWinding(*startPtr, *endPtr, &winding, &sortable);
        if (winding == SK_MinS32) {
            continue;
        }
        int sumWinding SK_INIT_TO_AVOID_WARNING;
        if (sortable) {
            segment = angle->segment();
            sumWinding = segment->updateWindingReverse(angle);
        }
        SkOpSegment* first = nullptr;
        const SkOpAngle* firstAngle = angle;
        while ((angle = angle->next()) != firstAngle) {
            segment = angle->segment();
            SkOpSpanBase* start = angle->start();
            SkOpSpanBase* end = angle->end();
            int maxWinding;
            if (sortable) {
                segment->setUpWinding(start, end, &maxWinding, &sumWinding);
            }
            if (!segment->done(angle)) {
                if (!first && (sortable || start->starter(end)->windSum() != SK_MinS32)) {
                    first = segment;
                    *startPtr = start;
                    *endPtr = end;
                }
                // OPTIMIZATION: should this also add to the chase?
                if (sortable) {
                    (void) segment->markAngle(maxWinding, sumWinding, angle);
                }
            }
        }
        if (first) {
       #if TRY_ROTATE
            *chase->insert(0) = span;
       #else
            *chase->append() = span;
       #endif
            return first;
        }
    }
    return nullptr;
}