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

Unified Diff: src/pathops/SkOpSpan.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/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;
}

Powered by Google App Engine
This is Rietveld 408576698