| Index: src/pathops/SkOpSpan.h
|
| diff --git a/src/pathops/SkOpSpan.h b/src/pathops/SkOpSpan.h
|
| index c6fc4b138f0c8135dd367f1ac717e3705e030df2..63fc1e9a1e52c2bb088a8c6c7faa6679b75e7542 100644
|
| --- a/src/pathops/SkOpSpan.h
|
| +++ b/src/pathops/SkOpSpan.h
|
| @@ -12,12 +12,13 @@
|
| #include "SkPoint.h"
|
|
|
| class SkChunkAlloc;
|
| -struct SkOpAngle;
|
| +class SkOpAngle;
|
| class SkOpContour;
|
| class SkOpGlobalState;
|
| class SkOpSegment;
|
| class SkOpSpanBase;
|
| class SkOpSpan;
|
| +struct SkPathOpsBounds;
|
|
|
| // subset of op span used by terminal span (when t is equal to one)
|
| class SkOpPtT {
|
| @@ -27,37 +28,43 @@ public:
|
| kIsDuplicate = 1
|
| };
|
|
|
| - void addOpp(SkOpPtT* opp) {
|
| + // please keep in sync with debugAddOpp()
|
| + bool addOpp(SkOpPtT* opp) {
|
| // find the fOpp ptr to opp
|
| SkOpPtT* oppPrev = opp->fNext;
|
| if (oppPrev == this) {
|
| - return;
|
| + return false;
|
| }
|
| while (oppPrev->fNext != opp) {
|
| oppPrev = oppPrev->fNext;
|
| - if (oppPrev == this) {
|
| - return;
|
| - }
|
| + if (oppPrev == this) {
|
| + return false;
|
| + }
|
| }
|
| -
|
| SkOpPtT* oldNext = this->fNext;
|
| SkASSERT(this != opp);
|
| this->fNext = opp;
|
| SkASSERT(oppPrev != oldNext);
|
| oppPrev->fNext = oldNext;
|
| + return true;
|
| }
|
|
|
| bool alias() const;
|
| + bool coincident() const { return fCoincident; }
|
| bool collapsed(const SkOpPtT* ) const;
|
| bool contains(const SkOpPtT* ) const;
|
| - SkOpPtT* contains(const SkOpSegment* );
|
| + bool contains(const SkOpSegment*, const SkPoint& ) const;
|
| + bool contains(const SkOpSegment*, double t) const;
|
| + const SkOpPtT* contains(const SkOpSegment* ) const;
|
| SkOpContour* contour() const;
|
|
|
| int debugID() const {
|
| return SkDEBUGRELEASE(fID, -1);
|
| }
|
|
|
| + bool debugAddOpp(const SkOpPtT* opp) const;
|
| const SkOpAngle* debugAngle(int id) const;
|
| + const SkOpCoincidence* debugCoincidence() const;
|
| bool debugContains(const SkOpPtT* ) const;
|
| const SkOpPtT* debugContains(const SkOpSegment* check) const;
|
| SkOpContour* debugContour(int id);
|
| @@ -72,8 +79,6 @@ public:
|
| return fDeleted;
|
| }
|
|
|
| - SkOpPtT* doppelganger();
|
| -
|
| bool duplicate() const {
|
| return fDuplicatePt;
|
| }
|
| @@ -82,7 +87,7 @@ public:
|
| void dumpAll() const;
|
| void dumpBase() const;
|
|
|
| - SkOpPtT* find(SkOpSegment* );
|
| + const SkOpPtT* find(const SkOpSegment* ) const;
|
| SkOpGlobalState* globalState() const;
|
| void init(SkOpSpanBase* , double t, const SkPoint& , bool dup);
|
|
|
| @@ -102,14 +107,14 @@ public:
|
|
|
| bool onEnd() const;
|
|
|
| - static bool Overlaps(SkOpPtT* s1, SkOpPtT* e1, SkOpPtT* s2, SkOpPtT* e2,
|
| - SkOpPtT** sOut, SkOpPtT** eOut) {
|
| - SkOpPtT* start1 = s1->fT < e1->fT ? s1 : e1;
|
| - SkOpPtT* start2 = s2->fT < e2->fT ? s2 : e2;
|
| + static bool Overlaps(const SkOpPtT* s1, const SkOpPtT* e1, const SkOpPtT* s2,
|
| + const SkOpPtT* e2, const SkOpPtT** sOut, const SkOpPtT** eOut) {
|
| + const SkOpPtT* start1 = s1->fT < e1->fT ? s1 : e1;
|
| + const SkOpPtT* start2 = s2->fT < e2->fT ? s2 : e2;
|
| *sOut = between(s1->fT, start2->fT, e1->fT) ? start2
|
| : between(s2->fT, start1->fT, e2->fT) ? start1 : nullptr;
|
| - SkOpPtT* end1 = s1->fT < e1->fT ? e1 : s1;
|
| - SkOpPtT* end2 = s2->fT < e2->fT ? e2 : s2;
|
| + const SkOpPtT* end1 = s1->fT < e1->fT ? e1 : s1;
|
| + const SkOpPtT* end2 = s2->fT < e2->fT ? e2 : s2;
|
| *eOut = between(s1->fT, end2->fT, e1->fT) ? end2
|
| : between(s2->fT, end1->fT, e2->fT) ? end1 : nullptr;
|
| if (*sOut == *eOut) {
|
| @@ -120,16 +125,23 @@ public:
|
| return *sOut && *eOut;
|
| }
|
|
|
| + bool ptAlreadySeen(const SkOpPtT* head) const;
|
| SkOpPtT* prev();
|
| - SkOpPtT* remove();
|
| - void removeNext(SkOpPtT* kept);
|
| + SkOpPtT* remove(const SkOpPtT* kept);
|
| + void removeNext(const SkOpPtT* kept);
|
|
|
| const SkOpSegment* segment() const;
|
| SkOpSegment* segment();
|
|
|
| - void setDeleted() {
|
| + void setCoincident() const {
|
| SkASSERT(!fDeleted);
|
| - fDeleted = true;
|
| + fCoincident = true;
|
| + }
|
| +
|
| + void setDeleted();
|
| +
|
| + void setSpan(const SkOpSpanBase* span) {
|
| + fSpan = const_cast<SkOpSpanBase*>(span);
|
| }
|
|
|
| const SkOpSpanBase* span() const {
|
| @@ -144,25 +156,21 @@ public:
|
| return fT < end->fT ? this : end;
|
| }
|
|
|
| - double fT;
|
| + double fT;
|
| SkPoint fPt; // cache of point value at this t
|
| protected:
|
| SkOpSpanBase* fSpan; // contains winding data
|
| SkOpPtT* fNext; // intersection on opposite curve or alias on this curve
|
| - bool fDeleted; // set if removed from span list
|
| + bool fDeleted; // set if removed from span list
|
| bool fDuplicatePt; // set if identical pt is somewhere in the next loop
|
| + // below mutable since referrer is otherwise always const
|
| + mutable bool fCoincident; // set if at some point a coincident span pointed here
|
| SkDEBUGCODE(int fID);
|
| };
|
|
|
| class SkOpSpanBase {
|
| public:
|
| - void align();
|
| -
|
| - bool aligned() const {
|
| - return fAligned;
|
| - }
|
| -
|
| - void alignEnd(double t, const SkPoint& pt);
|
| + void addOppAndMerge(SkOpSpanBase* );
|
|
|
| void bumpSpanAdds() {
|
| ++fSpanAdds;
|
| @@ -172,17 +180,14 @@ public:
|
| return fChased;
|
| }
|
|
|
| - void clearCoinEnd() {
|
| - SkASSERT(fCoinEnd != this);
|
| - fCoinEnd = this;
|
| - }
|
| + void checkForCollapsedCoincidence();
|
|
|
| const SkOpSpanBase* coinEnd() const {
|
| return fCoinEnd;
|
| }
|
|
|
| bool contains(const SkOpSpanBase* ) const;
|
| - SkOpPtT* contains(const SkOpSegment* );
|
| + const SkOpPtT* contains(const SkOpSegment* ) const;
|
|
|
| bool containsCoinEnd(const SkOpSpanBase* coin) const {
|
| SkASSERT(this != coin);
|
| @@ -198,6 +203,11 @@ public:
|
| bool containsCoinEnd(const SkOpSegment* ) const;
|
| SkOpContour* contour() const;
|
|
|
| +#if DEBUG_COINCIDENCE_VERBOSE
|
| + void debugAddOppAndMerge(const char* id, SkPathOpsDebug::GlitchLog* , const SkOpSpanBase* ,
|
| + bool* del1, bool* del2) const;
|
| +#endif
|
| +
|
| int debugBumpCount() {
|
| return SkDEBUGRELEASE(++fCount, -1);
|
| }
|
| @@ -209,9 +219,21 @@ public:
|
| bool debugAlignedEnd(double t, const SkPoint& pt) const;
|
| bool debugAlignedInner() const;
|
| const SkOpAngle* debugAngle(int id) const;
|
| +#if DEBUG_COINCIDENCE_VERBOSE
|
| + void debugCheckForCollapsedCoincidence(const char* id, SkPathOpsDebug::GlitchLog* ) const;
|
| +#endif
|
| + const SkOpCoincidence* debugCoincidence() const;
|
| bool debugCoinEndLoopCheck() const;
|
| - bool debugContains(const SkOpSegment* ) const;
|
| SkOpContour* debugContour(int id);
|
| +#ifdef SK_DEBUG
|
| + bool debugDeleted() const { return fDeleted; }
|
| +#endif
|
| +#if DEBUG_COINCIDENCE_VERBOSE
|
| + void debugInsertCoinEnd(const char* id, SkPathOpsDebug::GlitchLog* ,
|
| + const SkOpSpanBase* ) const;
|
| + void debugMergeContained(const char* id, SkPathOpsDebug::GlitchLog* ,
|
| + const SkPathOpsBounds& bounds, bool* deleted) const;
|
| +#endif
|
| const SkOpPtT* debugPtT(int id) const;
|
| const SkOpSegment* debugSegment(int id) const;
|
| const SkOpSpanBase* debugSpan(int id) const;
|
| @@ -227,6 +249,7 @@ public:
|
| void dumpCoin() const;
|
| void dumpAll() const;
|
| void dumpBase() const;
|
| + void dumpHead() const;
|
|
|
| bool final() const {
|
| return fPtT.fT == 1;
|
| @@ -238,6 +261,7 @@ public:
|
|
|
| void initBase(SkOpSegment* parent, SkOpSpan* prev, double t, const SkPoint& pt);
|
|
|
| + // Please keep this in sync with debugInsertCoinEnd()
|
| void insertCoinEnd(SkOpSpanBase* coin) {
|
| if (containsCoinEnd(coin)) {
|
| SkASSERT(coin->containsCoinEnd(this));
|
| @@ -252,8 +276,13 @@ public:
|
| }
|
|
|
| void merge(SkOpSpan* span);
|
| + void mergeContained(const SkPathOpsBounds& bounds);
|
|
|
| - SkOpSpan* prev() const {
|
| + const SkOpSpan* prev() const {
|
| + return fPrev;
|
| + }
|
| +
|
| + SkOpSpan* prev() {
|
| return fPrev;
|
| }
|
|
|
| @@ -281,8 +310,6 @@ public:
|
| fChased = chased;
|
| }
|
|
|
| - SkOpPtT* setCoinEnd(SkOpSpanBase* oldCoinEnd, SkOpSegment* oppSegment);
|
| -
|
| void setFromAngle(SkOpAngle* angle) {
|
| fFromAngle = angle;
|
| }
|
| @@ -293,7 +320,7 @@ public:
|
|
|
| bool simple() const {
|
| fPtT.debugValidate();
|
| - return fPtT.next()->next() == &fPtT;
|
| + return fPtT.next()->next() == &fPtT;
|
| }
|
|
|
| int spanAddsCount() const {
|
| @@ -368,6 +395,7 @@ protected: // no direct access to internals to avoid treating a span base as a
|
| bool fChased; // set after span has been added to chase array
|
| SkDEBUGCODE(int fCount); // number of pt/t pairs added
|
| SkDEBUGCODE(int fID);
|
| + SkDEBUGCODE(bool fDeleted); // set when span was merged with another span
|
| };
|
|
|
| class SkOpSpan : public SkOpSpanBase {
|
| @@ -404,7 +432,12 @@ public:
|
| }
|
|
|
| bool debugCoinLoopCheck() const;
|
| - void release(SkOpPtT* );
|
| +#if DEBUG_COINCIDENCE_VERBOSE
|
| + void debugInsertCoincidence(const char* , SkPathOpsDebug::GlitchLog* , const SkOpSpan* ) const;
|
| + void debugInsertCoincidence(const char* , SkPathOpsDebug::GlitchLog* ,
|
| + const SkOpSegment* , bool flipped) const;
|
| +#endif
|
| + void release(const SkOpPtT* );
|
|
|
| bool done() const {
|
| SkASSERT(!final());
|
| @@ -414,7 +447,9 @@ public:
|
| void dumpCoin() const;
|
| bool dumpSpan() const;
|
| void init(SkOpSegment* parent, SkOpSpan* prev, double t, const SkPoint& pt);
|
| + bool insertCoincidence(const SkOpSegment* , bool flipped);
|
|
|
| + // Please keep this in sync with debugInsertCoincidence()
|
| void insertCoincidence(SkOpSpan* coin) {
|
| if (containsCoincidence(coin)) {
|
| SkASSERT(coin->containsCoincidence(this));
|
| @@ -470,6 +505,7 @@ public:
|
| void setOppValue(int oppValue) {
|
| SkASSERT(!final());
|
| SkASSERT(fOppSum == SK_MinS32);
|
| + SkASSERT(!oppValue || !fDone);
|
| fOppValue = oppValue;
|
| }
|
|
|
| @@ -484,6 +520,7 @@ public:
|
| SkASSERT(!final());
|
| SkASSERT(windValue >= 0);
|
| SkASSERT(fWindSum == SK_MinS32);
|
| + SkASSERT(!windValue || !fDone);
|
| fWindValue = windValue;
|
| }
|
|
|
|
|