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; |
} |