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

Unified Diff: src/pathops/SkOpSpan.h

Issue 1037573004: cumulative pathops patch (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: fix pathopsinverse gm Created 5 years, 9 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
« no previous file with comments | « src/pathops/SkOpSegment.cpp ('k') | src/pathops/SkOpSpan.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/pathops/SkOpSpan.h
diff --git a/src/pathops/SkOpSpan.h b/src/pathops/SkOpSpan.h
index d9ce44eb7720fb4fb4cd78521b1ec750f15b9358..9e5939a5e1e90f15a696b01af243144d1470085a 100644
--- a/src/pathops/SkOpSpan.h
+++ b/src/pathops/SkOpSpan.h
@@ -7,36 +7,460 @@
#ifndef SkOpSpan_DEFINED
#define SkOpSpan_DEFINED
+#include "SkPathOpsDebug.h"
#include "SkPoint.h"
-class SkOpAngle;
+class SkChunkAlloc;
+struct SkOpAngle;
+class SkOpContour;
+class SkOpGlobalState;
class SkOpSegment;
+class SkOpSpanBase;
+class SkOpSpan;
-struct SkOpSpan {
- SkPoint fPt; // computed when the curves are intersected
- double fT;
- double fOtherT; // value at fOther[fOtherIndex].fT
- SkOpSegment* fOther;
- SkOpAngle* fFromAngle; // (if t > 0) index into segment's angle array going negative in t
- SkOpAngle* fToAngle; // (if t < 1) index into segment's angle array going positive in t
- int fOtherIndex; // can't be used during intersection
+// subset of op span used by terminal span (when t is equal to one)
+class SkOpPtT {
+public:
+ enum {
+ kIsAlias = 1,
+ kIsDuplicate = 1
+ };
+
+ void addOpp(SkOpPtT* opp) {
+ // find the fOpp ptr to opp
+ SkOpPtT* oppPrev = opp->fNext;
+ if (oppPrev == this) {
+ return;
+ }
+ while (oppPrev->fNext != opp) {
+ oppPrev = oppPrev->fNext;
+ if (oppPrev == this) {
+ return;
+ }
+ }
+
+ SkOpPtT* oldNext = this->fNext;
+ SkASSERT(this != opp);
+ this->fNext = opp;
+ SkASSERT(oppPrev != oldNext);
+ oppPrev->fNext = oldNext;
+ }
+
+ bool alias() const;
+ SkOpContour* contour() const;
+
+ int debugID() const {
+ return PATH_OPS_DEBUG_RELEASE(fID, -1);
+ }
+
+ const SkOpAngle* debugAngle(int id) const;
+ SkOpContour* debugContour(int id);
+ int debugLoopLimit(bool report) const;
+ bool debugMatchID(int id) const;
+ const SkOpPtT* debugPtT(int id) const;
+ const SkOpSegment* debugSegment(int id) const;
+ const SkOpSpanBase* debugSpan(int id) const;
+ SkOpGlobalState* globalState() const;
+ void debugValidate() const;
+
+ bool deleted() const {
+ return fDeleted;
+ }
+
+ bool duplicate() const {
+ return fDuplicatePt;
+ }
+
+ void dump() const; // available to testing only
+ void dumpAll() const;
+ void dumpBase() const;
+
+ void init(SkOpSpanBase* , double t, const SkPoint& , bool dup);
+
+ void insert(SkOpPtT* span) {
+ SkASSERT(span != this);
+ span->fNext = fNext;
+ fNext = span;
+ }
+
+ const SkOpPtT* next() const {
+ return fNext;
+ }
+
+ SkOpPtT* next() {
+ return fNext;
+ }
+
+ bool onEnd() const;
+ SkOpPtT* prev();
+ SkOpPtT* remove();
+ void removeNext(SkOpPtT* kept);
+
+ const SkOpSegment* segment() const;
+ SkOpSegment* segment();
+
+ void setDeleted() {
+ SkASSERT(!fDeleted);
+ fDeleted = true;
+ }
+
+ const SkOpSpanBase* span() const {
+ return fSpan;
+ }
+
+ SkOpSpanBase* span() {
+ return fSpan;
+ }
+
+ 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 fDuplicatePt; // set if identical pt is somewhere in the next loop
+ PATH_OPS_DEBUG_CODE(int fID);
+};
+
+class SkOpSpanBase {
+public:
+ void addSimpleAngle(bool checkFrom , SkChunkAlloc* );
+ void align();
+
+ bool aligned() const {
+ return fAligned;
+ }
+
+ void alignEnd(double t, const SkPoint& pt);
+
+ bool chased() const {
+ return fChased;
+ }
+
+ void clearCoinEnd() {
+ SkASSERT(fCoinEnd != this);
+ fCoinEnd = this;
+ }
+
+ const SkOpSpanBase* coinEnd() const {
+ return fCoinEnd;
+ }
+
+ bool contains(const SkOpSpanBase* ) const;
+ SkOpPtT* contains(const SkOpSegment* );
+
+ bool containsCoinEnd(const SkOpSpanBase* coin) const {
+ SkASSERT(this != coin);
+ const SkOpSpanBase* next = this;
+ while ((next = next->fCoinEnd) != this) {
+ if (next == coin) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool containsCoinEnd(const SkOpSegment* ) const;
+ SkOpContour* contour() const;
+
+ int debugBumpCount() {
+ return PATH_OPS_DEBUG_RELEASE(++fCount, -1);
+ }
+
+ int debugID() const {
+ return PATH_OPS_DEBUG_RELEASE(fID, -1);
+ }
+
+ const SkOpAngle* debugAngle(int id) const;
+ bool debugCoinEndLoopCheck() const;
+ SkOpContour* debugContour(int id);
+ const SkOpPtT* debugPtT(int id) const;
+ const SkOpSegment* debugSegment(int id) const;
+ const SkOpSpanBase* debugSpan(int id) const;
+ SkOpGlobalState* globalState() const;
+ void debugValidate() const;
+
+ bool deleted() const {
+ return fPtT.deleted();
+ }
+
+ void dump() const; // available to testing only
+ void dumpCoin() const;
+ void dumpAll() const;
+ void dumpBase() const;
+
+ bool final() const {
+ return fPtT.fT == 1;
+ }
+
+ SkOpAngle* fromAngle() const {
+ return fFromAngle;
+ }
+
+ void initBase(SkOpSegment* parent, SkOpSpan* prev, double t, const SkPoint& pt);
+
+ void insertCoinEnd(SkOpSpanBase* coin) {
+ if (containsCoinEnd(coin)) {
+ SkASSERT(coin->containsCoinEnd(this));
+ return;
+ }
+ debugValidate();
+ SkASSERT(this != coin);
+ SkOpSpanBase* coinNext = coin->fCoinEnd;
+ coin->fCoinEnd = this->fCoinEnd;
+ this->fCoinEnd = coinNext;
+ debugValidate();
+ }
+
+ void merge(SkOpSpan* span);
+
+ SkOpSpan* prev() const {
+ return fPrev;
+ }
+
+ const SkPoint& pt() const {
+ return fPtT.fPt;
+ }
+
+ const SkOpPtT* ptT() const {
+ return &fPtT;
+ }
+
+ SkOpPtT* ptT() {
+ return &fPtT;
+ }
+
+ SkOpSegment* segment() const {
+ return fSegment;
+ }
+
+ void setChased(bool chased) {
+ fChased = chased;
+ }
+
+ SkOpPtT* setCoinEnd(SkOpSpanBase* oldCoinEnd, SkOpSegment* oppSegment);
+
+ void setFromAngle(SkOpAngle* angle) {
+ fFromAngle = angle;
+ }
+
+ void setPrev(SkOpSpan* prev) {
+ fPrev = prev;
+ }
+
+ bool simple() const {
+ fPtT.debugValidate();
+ return fPtT.next()->next() == &fPtT;
+ }
+
+ const SkOpSpan* starter(const SkOpSpanBase* end) const {
+ const SkOpSpanBase* result = t() < end->t() ? this : end;
+ return result->upCast();
+ }
+
+ SkOpSpan* starter(SkOpSpanBase* end) {
+ SkASSERT(this->segment() == end->segment());
+ SkOpSpanBase* result = t() < end->t() ? this : end;
+ return result->upCast();
+ }
+
+ SkOpSpan* starter(SkOpSpanBase** endPtr) {
+ SkOpSpanBase* end = *endPtr;
+ SkASSERT(this->segment() == end->segment());
+ SkOpSpanBase* result;
+ if (t() < end->t()) {
+ result = this;
+ } else {
+ result = end;
+ *endPtr = this;
+ }
+ return result->upCast();
+ }
+
+ int step(const SkOpSpanBase* end) const {
+ return t() < end->t() ? 1 : -1;
+ }
+
+ double t() const {
+ return fPtT.fT;
+ }
+
+ void unaligned() {
+ fAligned = false;
+ }
+
+ SkOpSpan* upCast() {
+ SkASSERT(!final());
+ return (SkOpSpan*) this;
+ }
+
+ const SkOpSpan* upCast() const {
+ SkASSERT(!final());
+ return (const SkOpSpan*) this;
+ }
+
+ SkOpSpan* upCastable() {
+ return final() ? NULL : upCast();
+ }
+
+ const SkOpSpan* upCastable() const {
+ return final() ? NULL : upCast();
+ }
+
+private:
+ void alignInner();
+
+protected: // no direct access to internals to avoid treating a span base as a span
+ SkOpPtT fPtT; // list of points and t values associated with the start of this span
+ SkOpSegment* fSegment; // segment that contains this span
+ SkOpSpanBase* fCoinEnd; // linked list of coincident spans that end here (may point to itself)
+ SkOpAngle* fFromAngle; // points to next angle from span start to end
+ SkOpSpan* fPrev; // previous intersection point
+ bool fAligned;
+ bool fChased; // set after span has been added to chase array
+ PATH_OPS_DEBUG_CODE(int fCount); // number of pt/t pairs added
+ PATH_OPS_DEBUG_CODE(int fID);
+};
+
+class SkOpSpan : public SkOpSpanBase {
+public:
+ void applyCoincidence(SkOpSpan* opp);
+
+ bool clearCoincident() {
+ SkASSERT(!final());
+ if (fCoincident == this) {
+ return false;
+ }
+ fCoincident = this;
+ return true;
+ }
+
+ bool containsCoincidence(const SkOpSegment* ) const;
+
+ bool containsCoincidence(const SkOpSpan* coin) const {
+ SkASSERT(this != coin);
+ const SkOpSpan* next = this;
+ while ((next = next->fCoincident) != this) {
+ if (next == coin) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool debugCoinLoopCheck() const;
+ void detach(SkOpPtT* );
+
+ bool done() const {
+ SkASSERT(!final());
+ return fDone;
+ }
+
+ void dumpCoin() const;
+ bool dumpSpan() const;
+ void init(SkOpSegment* parent, SkOpSpan* prev, double t, const SkPoint& pt);
+
+ void insertCoincidence(SkOpSpan* coin) {
+ if (containsCoincidence(coin)) {
+ SkASSERT(coin->containsCoincidence(this));
+ return;
+ }
+ debugValidate();
+ SkASSERT(this != coin);
+ SkOpSpan* coinNext = coin->fCoincident;
+ coin->fCoincident = this->fCoincident;
+ this->fCoincident = coinNext;
+ debugValidate();
+ }
+
+ bool isCanceled() const {
+ SkASSERT(!final());
+ return fWindValue == 0 && fOppValue == 0;
+ }
+
+ bool isCoincident() const {
+ SkASSERT(!final());
+ return fCoincident != this;
+ }
+
+ SkOpSpanBase* next() const {
+ SkASSERT(!final());
+ return fNext;
+ }
+
+ int oppSum() const {
+ SkASSERT(!final());
+ return fOppSum;
+ }
+
+ int oppValue() const {
+ SkASSERT(!final());
+ return fOppValue;
+ }
+
+ SkOpPtT* setCoinStart(SkOpSpan* oldCoinStart, SkOpSegment* oppSegment);
+
+ void setDone(bool done) {
+ SkASSERT(!final());
+ fDone = done;
+ }
+
+ void setNext(SkOpSpanBase* nextT) {
+ SkASSERT(!final());
+ fNext = nextT;
+ }
+
+ void setOppSum(int oppSum);
+
+ void setOppValue(int oppValue) {
+ SkASSERT(!final());
+ SkASSERT(fOppSum == SK_MinS32);
+ fOppValue = oppValue;
+ }
+
+ void setToAngle(SkOpAngle* angle) {
+ SkASSERT(!final());
+ fToAngle = angle;
+ }
+
+ void setWindSum(int windSum) {
+ SkASSERT(!final());
+ SkASSERT(fWindSum == SK_MinS32 || fWindSum == windSum);
+ SkASSERT(!DEBUG_LIMIT_WIND_SUM || abs(windSum) <= DEBUG_LIMIT_WIND_SUM);
+ fWindSum = windSum;
+ }
+
+ void setWindValue(int windValue) {
+ SkASSERT(!final());
+ SkASSERT(windValue >= 0);
+ SkASSERT(fWindSum == SK_MinS32);
+ fWindValue = windValue;
+ }
+
+ SkOpAngle* toAngle() const {
+ SkASSERT(!final());
+ return fToAngle;
+ }
+
+ int windSum() const {
+ SkASSERT(!final());
+ return fWindSum;
+ }
+
+ int windValue() const {
+ SkASSERT(!final());
+ return fWindValue;
+ }
+
+private: // no direct access to internals to avoid treating a span base as a span
+ SkOpSpan* fCoincident; // linked list of spans coincident with this one (may point to itself)
+ SkOpAngle* fToAngle; // points to next angle from span start to end
+ SkOpSpanBase* fNext; // next intersection point
int fWindSum; // accumulated from contours surrounding this one.
int fOppSum; // for binary operators: the opposite winding sum
int fWindValue; // 0 == canceled; 1 == normal; >1 == coincident
int fOppValue; // normally 0 -- when binary coincident edges combine, opp value goes here
- bool fChased; // set after span has been added to chase array
- bool fCoincident; // set if span is bumped -- if set additional points aren't inserted
bool fDone; // if set, this span to next higher T has been processed
- bool fLoop; // set when a cubic loops back to this point
- bool fMultiple; // set if this is one of mutiple spans with identical t and pt values
- bool fNear; // set if opposite end point is near but not equal to this one
- bool fSmall; // if set, consecutive points are almost equal
- bool fTiny; // if set, consecutive points are equal but consecutive ts are not precisely equal
-
- // available to testing only
- const SkOpSegment* debugToSegment(ptrdiff_t* ) const;
- void dump() const;
- void dumpOne() const;
};
#endif
« no previous file with comments | « src/pathops/SkOpSegment.cpp ('k') | src/pathops/SkOpSpan.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698