Index: src/pathops/SkOpCoincidence.h |
diff --git a/src/pathops/SkOpCoincidence.h b/src/pathops/SkOpCoincidence.h |
index 1efe6c0613a91bdca17a3486e7f97e3ced080f87..c64d148c246c1cd45ea308ac081ae0c2aea63ba3 100644 |
--- a/src/pathops/SkOpCoincidence.h |
+++ b/src/pathops/SkOpCoincidence.h |
@@ -7,120 +7,300 @@ |
#ifndef SkOpCoincidence_DEFINED |
#define SkOpCoincidence_DEFINED |
+#include "SkTDArray.h" |
#include "SkOpTAllocator.h" |
#include "SkOpSpan.h" |
#include "SkPathOpsTypes.h" |
class SkOpPtT; |
+class SkOpSpanBase; |
-struct SkCoincidentSpans { |
- SkCoincidentSpans* fNext; |
- SkOpPtT* fCoinPtTStart; |
- SkOpPtT* fCoinPtTEnd; |
- SkOpPtT* fOppPtTStart; |
- SkOpPtT* fOppPtTEnd; |
- bool fFlipped; |
- SkDEBUGCODE(int fID); |
+class SkCoincidentSpans { |
+public: |
+ const SkOpPtT* coinPtTEnd() const { return fCoinPtTEnd; } |
+ const SkOpPtT* coinPtTStart() const { return fCoinPtTStart; } |
+ |
+ // These return non-const pointers so that, as copies, they can be added |
+ // to a new span pair |
+ SkOpPtT* coinPtTEndWritable() const { return const_cast<SkOpPtT*>(fCoinPtTEnd); } |
+ SkOpPtT* coinPtTStartWritable() const { return const_cast<SkOpPtT*>(fCoinPtTStart); } |
+ |
+ bool collapsed(const SkOpPtT* ) const; |
+ bool contains(const SkOpPtT* s, const SkOpPtT* e) const; |
+ void correctEnds(); |
+ void correctOneEnd(const SkOpPtT* (SkCoincidentSpans::* getEnd)() const, |
+ void (SkCoincidentSpans::* setEnd)(const SkOpPtT* ptT) ); |
+ |
+#if DEBUG_COINCIDENCE_VERBOSE |
+ bool debugExpand(const char* id, SkPathOpsDebug::GlitchLog* log) const; |
+#endif |
int debugID() const { |
return SkDEBUGRELEASE(fID, -1); |
} |
+ void debugShow() const; |
+#ifdef SK_DEBUG |
+ void debugStartCheck(const SkOpSpanBase* outer, const SkOpSpanBase* over, |
+ const SkOpGlobalState* debugState) const; |
+#endif |
void dump() const; |
+ bool expand(); |
+ bool extend(const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, |
+ const SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd); |
+ bool flipped() const { return fOppPtTStart->fT > fOppPtTEnd->fT; } |
+ void init() { sk_bzero(this, sizeof(*this)); } |
+ const SkOpPtT* oppPtTStart() const { return fOppPtTStart; } |
+ const SkOpPtT* oppPtTEnd() const { return fOppPtTEnd; } |
+ // These return non-const pointers so that, as copies, they can be added |
+ // to a new span pair |
+ SkOpPtT* oppPtTStartWritable() const { return const_cast<SkOpPtT*>(fOppPtTStart); } |
+ SkOpPtT* oppPtTEndWritable() const { return const_cast<SkOpPtT*>(fOppPtTEnd); } |
+ SkCoincidentSpans* next() { return fNext; } |
+ const SkCoincidentSpans* next() const { return fNext; } |
+ SkCoincidentSpans** nextPtr() { return &fNext; } |
+ int spanCount() const; |
+ |
+ void set(SkCoincidentSpans* next, const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, |
+ const SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd |
+ SkDEBUGPARAMS(int id)); |
+ |
+ void setCoinPtTEnd(const SkOpPtT* ptT) { |
+ SkASSERT(ptT == ptT->span()->ptT()) |
+ SkASSERT(!fCoinPtTStart || ptT->fT != fCoinPtTStart->fT); |
+ SkASSERT(!fCoinPtTStart || fCoinPtTStart->segment() == ptT->segment()); |
+ fCoinPtTEnd = ptT; |
+ ptT->setCoincident(); |
+ } |
+ |
+ void setCoinPtTStart(const SkOpPtT* ptT) { |
+ SkASSERT(ptT == ptT->span()->ptT()) |
+ SkASSERT(!fCoinPtTEnd || ptT->fT != fCoinPtTEnd->fT); |
+ SkASSERT(!fCoinPtTEnd || fCoinPtTEnd->segment() == ptT->segment()); |
+ fCoinPtTStart = ptT; |
+ ptT->setCoincident(); |
+ } |
+ |
+ void setEnds(const SkOpPtT* coinPtTEnd, const SkOpPtT* oppPtTEnd) { |
+ this->setCoinPtTEnd(coinPtTEnd); |
+ this->setOppPtTEnd(oppPtTEnd); |
+ } |
+ |
+ void setOppPtTEnd(const SkOpPtT* ptT) { |
+ SkASSERT(ptT == ptT->span()->ptT()) |
+ SkASSERT(!fOppPtTStart || ptT->fT != fOppPtTStart->fT); |
+ SkASSERT(!fOppPtTStart || fOppPtTStart->segment() == ptT->segment()); |
+ fOppPtTEnd = ptT; |
+ ptT->setCoincident(); |
+ } |
+ |
+ void setOppPtTStart(const SkOpPtT* ptT) { |
+ SkASSERT(ptT == ptT->span()->ptT()) |
+ SkASSERT(!fOppPtTEnd || ptT->fT != fOppPtTEnd->fT); |
+ SkASSERT(!fOppPtTEnd || fOppPtTEnd->segment() == ptT->segment()); |
+ fOppPtTStart = ptT; |
+ ptT->setCoincident(); |
+ } |
+ |
+ void setStarts(const SkOpPtT* coinPtTStart, const SkOpPtT* oppPtTStart) { |
+ this->setCoinPtTStart(coinPtTStart); |
+ this->setOppPtTStart(oppPtTStart); |
+ } |
+ |
+ void setNext(SkCoincidentSpans* next) { fNext = next; } |
+ |
+ bool startEquals(const SkOpSpanBase* outer, const SkOpSpanBase* over) const { |
+ return fCoinPtTStart->span() == over && fOppPtTStart->span() == outer; |
+ } |
+private: |
+ SkCoincidentSpans* fNext; |
+ const SkOpPtT* fCoinPtTStart; |
+ const SkOpPtT* fCoinPtTEnd; |
+ const SkOpPtT* fOppPtTStart; |
+ const SkOpPtT* fOppPtTEnd; |
+ SkDEBUGCODE(int fID); |
}; |
class SkOpCoincidence { |
public: |
- SkOpCoincidence() |
+ SkOpCoincidence(SkOpGlobalState* globalState) |
: fHead(nullptr) |
, fTop(nullptr) |
- SkDEBUGPARAMS(fDebugState(nullptr)) |
- { |
+ , fGlobalState(globalState) |
+ , fContinue(false) |
+ , fSpanDeleted(false) |
+ , fPtAllocated(false) |
+ , fCoinExtended(false) |
+ , fSpanMerged(false) { |
+ globalState->setCoincidence(this); |
} |
void add(SkOpPtT* coinPtTStart, SkOpPtT* coinPtTEnd, SkOpPtT* oppPtTStart, |
- SkOpPtT* oppPtTEnd, SkChunkAlloc* allocator); |
- bool addExpanded(SkChunkAlloc* allocator PATH_OPS_DEBUG_VALIDATE_PARAMS(SkOpGlobalState* )); |
- bool addMissing(SkChunkAlloc* allocator); |
+ SkOpPtT* oppPtTEnd); |
+ bool addEndMovedSpans(); |
+ bool addExpanded(); |
+ bool addMissing(); |
+ bool addUncommon(); |
bool apply(); |
bool contains(const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, |
- const SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd, bool flipped) const; |
+ const SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd) const; |
+ void correctEnds(); |
+#if DEBUG_COINCIDENCE_VERBOSE |
void debugAddExpanded(const char* id, SkPathOpsDebug::GlitchLog* ) const; |
void debugAddMissing(const char* id, SkPathOpsDebug::GlitchLog* ) const; |
+ void debugAddOrOverlap(const SkOpSegment* coinSeg, const SkOpSegment* oppSeg, |
+ double coinTs, double coinTe, double oppTs, double oppTe, |
+ const char* id, SkPathOpsDebug::GlitchLog* log) const; |
+#endif |
const SkOpAngle* debugAngle(int id) const { |
- return SkDEBUGRELEASE(fDebugState->debugAngle(id), nullptr); |
+ return SkDEBUGRELEASE(fGlobalState->debugAngle(id), nullptr); |
} |
+#if DEBUG_COINCIDENCE_VERBOSE |
+ void debugCheckOverlap(const char* id, SkPathOpsDebug::GlitchLog* log) const; |
+ void debugCheckValid(const char* id, SkPathOpsDebug::GlitchLog* log) const; |
+#endif |
+ |
SkOpContour* debugContour(int id) { |
- return SkDEBUGRELEASE(fDebugState->debugContour(id), nullptr); |
+ return SkDEBUGRELEASE(fGlobalState->debugContour(id), nullptr); |
} |
+#if DEBUG_COINCIDENCE_VERBOSE |
bool debugExpand(const char* id, SkPathOpsDebug::GlitchLog* ) const; |
void debugMark(const char* id, SkPathOpsDebug::GlitchLog* ) const; |
+ void debugMarkCollapsed(const char* id, SkPathOpsDebug::GlitchLog* , |
+ const SkCoincidentSpans* coin, const SkOpPtT* test) const; |
+ void debugMarkCollapsed(const char* id, SkPathOpsDebug::GlitchLog* , const SkOpPtT* test) const; |
+#endif |
const SkOpPtT* debugPtT(int id) const { |
- return SkDEBUGRELEASE(fDebugState->debugPtT(id), nullptr); |
+ return SkDEBUGRELEASE(fGlobalState->debugPtT(id), nullptr); |
} |
const SkOpSegment* debugSegment(int id) const { |
- return SkDEBUGRELEASE(fDebugState->debugSegment(id), nullptr); |
+ return SkDEBUGRELEASE(fGlobalState->debugSegment(id), nullptr); |
} |
- void debugSetGlobalState(SkOpGlobalState* debugState) { |
- SkDEBUGCODE(fDebugState = debugState); |
- } |
- |
- void debugFixAligned(const char* id, SkPathOpsDebug::GlitchLog* ) const; |
+#if DEBUG_COINCIDENCE_VERBOSE |
+ void debugRemoveCollapsed(const char* id, SkPathOpsDebug::GlitchLog* ) const; |
+ void debugReorder(const char* id, SkPathOpsDebug::GlitchLog* ) const; |
+ void debugRelease(const char* id, SkPathOpsDebug::GlitchLog* , const SkOpSegment* ) const; |
+#endif |
void debugShowCoincidence() const; |
const SkOpSpanBase* debugSpan(int id) const { |
- return SkDEBUGRELEASE(fDebugState->debugSpan(id), nullptr); |
+ return SkDEBUGRELEASE(fGlobalState->debugSpan(id), nullptr); |
} |
- void release(SkCoincidentSpans* ); |
+ void debugValidate() const; |
void dump() const; |
+ bool edge(const SkOpPtT* , bool* start) const; |
bool expand(); |
- bool extend(SkOpPtT* coinPtTStart, SkOpPtT* coinPtTEnd, SkOpPtT* oppPtTStart, |
- SkOpPtT* oppPtTEnd); |
- bool findOverlaps(SkOpCoincidence* , SkChunkAlloc* allocator) const; |
- bool fixAligned(); |
- void fixUp(SkOpPtT* deleted, SkOpPtT* kept); |
+ bool extend(const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, const SkOpPtT* oppPtTStart, |
+ const SkOpPtT* oppPtTEnd); |
+ bool findOverlaps(SkOpCoincidence* ) const; |
+ void fixUp(SkOpPtT* deleted, const SkOpPtT* kept); |
+ |
+ SkOpGlobalState* globalState() { |
+ return fGlobalState; |
+ } |
bool isEmpty() const { |
- return !fHead; |
+ return !fHead && !fTop; |
} |
bool mark(); |
+ void markCollapsed(SkOpPtT* ); |
+ |
+ static bool Ordered(const SkOpPtT* coinPtTStart, const SkOpPtT* oppPtTStart) { |
+ return Ordered(coinPtTStart->segment(), oppPtTStart->segment()); |
+ } |
+ |
+ static bool Ordered(const SkOpSegment* coin, const SkOpSegment* opp); |
+ void release(const SkOpSegment* ); |
+ bool removeCollapsed(); |
+ bool reorder(); |
private: |
- bool addIfMissing(const SkCoincidentSpans* outer, SkOpPtT* over1s, SkOpPtT* over1e, |
- SkChunkAlloc* ); |
+ void add(const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, const SkOpPtT* oppPtTStart, |
+ const SkOpPtT* oppPtTEnd) { |
+ this->add(const_cast<SkOpPtT*>(coinPtTStart), const_cast<SkOpPtT*>(coinPtTEnd), |
+ const_cast<SkOpPtT*>(oppPtTStart), const_cast<SkOpPtT*>(oppPtTEnd)); |
+ } |
+ |
+ void addEndMovedSpans(const SkOpSpan* base, const SkOpSpanBase* testSpan); |
+ bool addEndMovedSpans(const SkOpPtT* ptT); |
+ |
+ bool addIfMissing(const SkCoincidentSpans* outer, SkOpPtT* over1s, SkOpPtT* over1e); |
+ |
+ bool addIfMissing(const SkCoincidentSpans* outer, const SkOpPtT* over1s, |
+ const SkOpPtT* over1e) { |
+ return addIfMissing(outer, const_cast<SkOpPtT*>(over1s), const_cast<SkOpPtT*>(over1e)); |
+ } |
+ |
bool addIfMissing(const SkOpPtT* over1s, const SkOpPtT* over1e, |
const SkOpPtT* over2s, const SkOpPtT* over2e, |
double tStart, double tEnd, |
SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, |
- SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd, |
- SkChunkAlloc* ); |
- bool addOverlap(SkOpSegment* seg1, SkOpSegment* seg1o, SkOpSegment* seg2, SkOpSegment* seg2o, |
- SkOpPtT* overS, SkOpPtT* overE, SkChunkAlloc* ); |
- bool debugAddIfMissing(const SkCoincidentSpans* outer, const SkOpPtT* over1s, |
- const SkOpPtT* over1e) const; |
- bool debugAddIfMissing(const SkOpPtT* over1s, const SkOpPtT* over1e, |
+ SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd); |
+ |
+ bool addIfMissing(const SkOpPtT* over1s, const SkOpPtT* over1e, |
+ const SkOpPtT* over2s, const SkOpPtT* over2e, |
+ double tStart, double tEnd, |
+ const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, |
+ const SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd) { |
+ return addIfMissing(over1s, over1e, over2s, over2e, tStart, tEnd, |
+ const_cast<SkOpPtT*>(coinPtTStart), coinPtTEnd, |
+ const_cast<SkOpPtT*>(oppPtTStart), oppPtTEnd); |
+ } |
+ |
+ bool addOrOverlap(SkOpSegment* coinSeg, SkOpSegment* oppSeg, |
+ double coinTs, double coinTe, double oppTs, double oppTe); |
+ bool addOverlap(const SkOpSegment* seg1, const SkOpSegment* seg1o, |
+ const SkOpSegment* seg2, const SkOpSegment* seg2o, |
+ const SkOpPtT* overS, const SkOpPtT* overE); |
+ bool alreadyAdded(const SkCoincidentSpans* check, const SkCoincidentSpans* outer, |
+ const SkOpPtT* over1s, const SkOpPtT* over1e) const; |
+ bool checkOverlap(SkCoincidentSpans* check, |
+ const SkOpSegment* coinSeg, const SkOpSegment* oppSeg, |
+ double coinTs, double coinTe, double oppTs, double oppTe, |
+ SkTDArray<SkCoincidentSpans*>* overlaps) const; |
+ bool contains(const SkOpSegment* seg, const SkOpSegment* opp, double oppT) const; |
+ bool contains(const SkCoincidentSpans* coin, const SkOpSegment* seg, |
+ const SkOpSegment* opp, double oppT) const; |
+#if DEBUG_COINCIDENCE_VERBOSE |
+ void debugAddIfMissing(const SkCoincidentSpans* outer, const SkOpPtT* over1s, |
+ const SkOpPtT* over1e, const char* id, SkPathOpsDebug::GlitchLog*) const; |
+ void debugAddIfMissing(const SkOpPtT* over1s, const SkOpPtT* over1e, |
const SkOpPtT* over2s, const SkOpPtT* over2e, |
double tStart, double tEnd, |
- SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, |
- SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd) const; |
+ const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, |
+ const SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd, |
+ const char* id, SkPathOpsDebug::GlitchLog*) const; |
+#endif |
+ void fixUp(SkCoincidentSpans* coin, SkOpPtT* deleted, const SkOpPtT* kept); |
+ void markCollapsed(SkCoincidentSpans* head, SkOpPtT* test); |
bool overlap(const SkOpPtT* coinStart1, const SkOpPtT* coinEnd1, |
const SkOpPtT* coinStart2, const SkOpPtT* coinEnd2, |
double* overS, double* overE) const; |
- |
+ bool release(SkCoincidentSpans* coin, SkCoincidentSpans* ); |
+ void restoreHead(); |
bool testForCoincidence(const SkCoincidentSpans* outer, const SkOpPtT* testS, |
const SkOpPtT* testE) const; |
+ static void TRange(const SkOpPtT* overS, const SkOpPtT* overE, double tStart, |
+ double tEnd, const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, |
+ double* coinTs, double* coinTe); |
+ |
SkCoincidentSpans* fHead; |
SkCoincidentSpans* fTop; |
- SkDEBUGCODE_(SkOpGlobalState* fDebugState); |
+ SkOpGlobalState* fGlobalState; |
+ bool fContinue; |
+ bool fSpanDeleted; |
+ bool fPtAllocated; |
+ bool fCoinExtended; |
+ bool fSpanMerged; |
}; |
#endif |