Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(666)

Unified Diff: src/pathops/SkOpCoincidence.h

Issue 2128633003: pathops coincidence and security rewrite (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: require resulting t to be between 0 and 1 Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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

Powered by Google App Engine
This is Rietveld 408576698