diff options
Diffstat (limited to 'src/pathops/SkOpSegment.h')
-rw-r--r-- | src/pathops/SkOpSegment.h | 191 |
1 files changed, 138 insertions, 53 deletions
diff --git a/src/pathops/SkOpSegment.h b/src/pathops/SkOpSegment.h index 79d83b1155..54c1892d1b 100644 --- a/src/pathops/SkOpSegment.h +++ b/src/pathops/SkOpSegment.h @@ -19,7 +19,7 @@ class SkPathWriter; class SkOpSegment { public: SkOpSegment() { -#ifdef SK_DEBUG +#if defined(SK_DEBUG) || !FORCE_RELEASE fID = ++SkPathOpsDebug::gSegmentID; #endif } @@ -28,6 +28,12 @@ public: return fBounds.fTop < rh.fBounds.fTop; } + // FIXME: add some template or macro to avoid casting + SkOpAngle& angle(int index) { + const SkOpAngle& cAngle = (const_cast<const SkOpSegment*>(this))->angle(index); + return const_cast<SkOpAngle&>(cAngle); + } + const SkPathOpsBounds& bounds() const { return fBounds; } @@ -42,6 +48,8 @@ public: return count > 1 && fTs[0].fT == 0 && fTs[--count].fT == 1; } + void constructLine(SkPoint shortLine[2]); + int count() const { return fTs.count(); } @@ -59,7 +67,6 @@ public: return done(SkMin32(angle->start(), angle->end())); } - // used only by partial coincidence detection SkDPoint dPtAtT(double mid) const { return (*CurveDPointAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, mid); } @@ -72,6 +79,14 @@ public: return dxdy(index).fY; } + bool hasSmall() const { + return fSmall; + } + + bool hasTiny() const { + return fTiny; + } + bool intersected() const { return fTs.count() > 0; } @@ -131,11 +146,12 @@ public: return fTs[lesser].fOppValue; } - const SkOpSegment* other(int index) const { - return fTs[index].fOther; +#if DEBUG_VALIDATE + bool oppXor() const { + return fOppXor; } +#endif - // was used only by right angle winding finding SkPoint ptAtT(double mid) const { return (*CurvePointAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, mid); } @@ -160,11 +176,23 @@ public: *sumWinding -= deltaSum; } - // OPTIMIZATION: mark as debugging only if used solely by tests const SkOpSpan& span(int tIndex) const { return fTs[tIndex]; } + const SkOpAngle* spanToAngle(int tStart, int tEnd) const { + SkASSERT(tStart != tEnd); + const SkOpSpan& span = fTs[tStart]; + int index = tStart < tEnd ? span.fToAngleIndex : span.fFromAngleIndex; + return index >= 0 ? &angle(index) : NULL; + } + + // FIXME: create some sort of macro or template that avoids casting + SkOpAngle* spanToAngle(int tStart, int tEnd) { + const SkOpAngle* cAngle = (const_cast<const SkOpSegment*>(this))->spanToAngle(tStart, tEnd); + return const_cast<SkOpAngle*>(cAngle); + } + // OPTIMIZATION: mark as debugging only if used solely by tests const SkTDArray<SkOpSpan>& spans() const { return fTs; @@ -217,6 +245,12 @@ public: } #endif +#if DEBUG_VALIDATE + bool _xor() const { // FIXME: used only by SkOpAngle::debugValidateLoop() + return fXor; + } +#endif + const SkPoint& xyAtT(const SkOpSpan* span) const { return span->fPt; } @@ -231,44 +265,56 @@ public: } #endif - bool activeAngle(int index, int* done, SkTArray<SkOpAngle, true>* angles); + const SkOpAngle* activeAngle(int index, int* start, int* end, bool* done, + bool* sortable) const; SkPoint activeLeftTop(bool onlySortable, int* firstT) const; bool activeOp(int index, int endIndex, int xorMiMask, int xorSuMask, SkPathOp op); bool activeWinding(int index, int endIndex); void addCubic(const SkPoint pts[4], bool operand, bool evenOdd); void addCurveTo(int start, int end, SkPathWriter* path, bool active) const; + void addEndSpan(int endIndex); void addLine(const SkPoint pts[2], bool operand, bool evenOdd); void addOtherT(int index, double otherT, int otherIndex); void addQuad(const SkPoint pts[3], bool operand, bool evenOdd); - int addSelfT(SkOpSegment* other, const SkPoint& pt, double newT); + void addSimpleAngle(int endIndex); + int addSelfT(const SkPoint& pt, double newT); + void addStartSpan(int endIndex); int addT(SkOpSegment* other, const SkPoint& pt, double newT); void addTCancel(const SkPoint& startPt, const SkPoint& endPt, SkOpSegment* other); void addTCoincident(const SkPoint& startPt, const SkPoint& endPt, double endT, - SkOpSegment* other); - void addTPair(double t, SkOpSegment* other, double otherT, bool borrowWind, const SkPoint& pt); + SkOpSegment* other); + const SkOpSpan* addTPair(double t, SkOpSegment* other, double otherT, bool borrowWind, + const SkPoint& pt); + bool alignSpan(int index, double thisT, const SkPoint& thisPt); + void alignSpanState(int start, int end); + const SkOpAngle& angle(int index) const; bool betweenTs(int lesser, double testT, int greater) const; + bool calcAngles(); + void checkDuplicates(); void checkEnds(); + void checkMultiples(); + void checkSmall(); bool checkSmall(int index) const; void checkTiny(); - int computeSum(int startIndex, int endIndex, SkOpAngle::IncludeType includeType, - SkTArray<SkOpAngle, true>* angles, SkTArray<SkOpAngle*, true>* sorted); + int computeSum(int startIndex, int endIndex, SkOpAngle::IncludeType includeType); int crossedSpanY(const SkPoint& basePt, SkScalar* bestY, double* hitT, bool* hitSomething, double mid, bool opp, bool current) const; bool findCoincidentMatch(const SkOpSpan* span, const SkOpSegment* other, int oStart, int oEnd, int step, SkPoint* startPt, SkPoint* endPt, double* endT) const; SkOpSegment* findNextOp(SkTDArray<SkOpSpan*>* chase, int* nextStart, int* nextEnd, - bool* unsortable, SkPathOp op, const int xorMiMask, - const int xorSuMask); + bool* unsortable, SkPathOp op, int xorMiMask, int xorSuMask); SkOpSegment* findNextWinding(SkTDArray<SkOpSpan*>* chase, int* nextStart, int* nextEnd, bool* unsortable); SkOpSegment* findNextXor(int* nextStart, int* nextEnd, bool* unsortable); + int findExactT(double t, const SkOpSegment* ) const; int findT(double t, const SkOpSegment* ) const; - SkOpSegment* findTop(int* tIndex, int* endIndex, bool* unsortable, bool onlySortable); + SkOpSegment* findTop(int* tIndex, int* endIndex, bool* unsortable); void fixOtherTIndex(); - void initWinding(int start, int end); + void initWinding(int start, int end, SkOpAngle::IncludeType angleIncludeType); void initWinding(int start, int end, double tHit, int winding, SkScalar hitDx, int oppWind, SkScalar hitOppDx); bool isMissing(double startT, const SkPoint& pt) const; + bool isSmall(const SkOpAngle* angle) const; bool isTiny(const SkOpAngle* angle) const; bool joinCoincidence(SkOpSegment* other, double otherT, int step, bool cancel); SkOpSpan* markAndChaseDoneBinary(int index, int endIndex); @@ -283,44 +329,44 @@ public: int nextSpan(int from, int step) const; void setUpWindings(int index, int endIndex, int* sumMiWinding, int* sumSuWinding, int* maxWinding, int* sumWinding, int* oppMaxWinding, int* oppSumWinding); - enum SortAngleKind { - kMustBeOrdered_SortAngleKind, // required for winding calc - kMayBeUnordered_SortAngleKind // ok for find top - }; - static bool SortAngles(const SkTArray<SkOpAngle, true>& angles, // FIXME: replace with - SkTArray<SkOpAngle*, true>* angleList, // Sort Angles 2 - SortAngleKind ); - static bool SortAngles2(const SkTArray<SkOpAngle, true>& angles, - SkTArray<SkOpAngle*, true>* angleList); + void sortAngles(); bool subDivide(int start, int end, SkPoint edge[4]) const; bool subDivide(int start, int end, SkDCubic* result) const; void undoneSpan(int* start, int* end); int updateOppWindingReverse(const SkOpAngle* angle) const; int updateWindingReverse(const SkOpAngle* angle) const; static bool UseInnerWinding(int outerWinding, int innerWinding); + static bool UseInnerWindingReverse(int outerWinding, int innerWinding); int windingAtT(double tHit, int tIndex, bool crossOpp, SkScalar* dx) const; int windSum(const SkOpAngle* angle) const; - -#ifdef SK_DEBUG +// available for testing only +#if DEBUG_VALIDATE + bool debugContains(const SkOpAngle* ) const; +#endif +#if defined(SK_DEBUG) || !FORCE_RELEASE int debugID() const { return fID; } +#else + int debugID() const { + return -1; + } #endif #if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY void debugShowActiveSpans() const; #endif -#if DEBUG_SORT || DEBUG_SWAP_TOP - void debugShowSort(const char* fun, const SkTArray<SkOpAngle*, true>& angles, int first, - const int contourWinding, const int oppContourWinding, bool sortable) const; - void debugShowSort(const char* fun, const SkTArray<SkOpAngle*, true>& angles, int first, - bool sortable); -#endif #if DEBUG_CONCIDENT void debugShowTs(const char* prefix) const; #endif #if DEBUG_SHOW_WINDING int debugShowWindingValues(int slotCount, int ofInterest) const; #endif + void debugValidate() const; + // available to testing only + void dumpAngles() const; + void dumpContour(int firstID, int lastID) const; + void dumpPts() const; + void dumpSpans() const; private: struct MissingSpan { @@ -332,40 +378,55 @@ private: SkPoint fPt; }; - bool activeAngleOther(int index, int* done, SkTArray<SkOpAngle, true>* angles); - bool activeAngleInner(int index, int* done, SkTArray<SkOpAngle, true>* angles); + const SkOpAngle* activeAngleInner(int index, int* start, int* end, bool* done, + bool* sortable) const; + const SkOpAngle* activeAngleOther(int index, int* start, int* end, bool* done, + bool* sortable) const; bool activeOp(int xorMiMask, int xorSuMask, int index, int endIndex, SkPathOp op, - int* sumMiWinding, int* sumSuWinding, int* maxWinding, int* sumWinding, - int* oppMaxWinding, int* oppSumWinding); - bool activeWinding(int index, int endIndex, int* maxWinding, int* sumWinding); - void addAngle(SkTArray<SkOpAngle, true>* angles, int start, int end) const; + int* sumMiWinding, int* sumSuWinding); + bool activeWinding(int index, int endIndex, int* sumWinding); void addCancelOutsides(const SkPoint& startPt, const SkPoint& endPt, SkOpSegment* other); void addCoinOutsides(const SkPoint& startPt, const SkPoint& endPt, SkOpSegment* other); + int addSingletonAngleDown(int start, SkOpSegment** otherPtr); + int addSingletonAngleUp(int start, SkOpSegment** otherPtr); + SkOpAngle* addSingletonAngles(int start, int step); void addTPair(double t, SkOpSegment* other, double otherT, bool borrowWind, const SkPoint& pt, const SkPoint& oPt); - void addTwoAngles(int start, int end, SkTArray<SkOpAngle, true>* angles) const; bool betweenPoints(double midT, const SkPoint& pt1, const SkPoint& pt2) const; - bool buildAngles(int index, SkTArray<SkOpAngle, true>* angles, bool includeOpp) const; - void buildAnglesInner(int index, SkTArray<SkOpAngle, true>* angles) const; void bumpCoincidentThis(const SkOpSpan& oTest, bool binary, int* index, SkTArray<SkPoint, true>* outsideTs); void bumpCoincidentOther(const SkOpSpan& oTest, int* index, SkTArray<SkPoint, true>* outsideTs); bool bumpSpan(SkOpSpan* span, int windDelta, int oppDelta); + bool calcLoopSpanCount(const SkOpSpan& thisSpan, int* smallCounts); + void checkLinks(const SkOpSpan* , + SkTArray<MissingSpan, true>* missingSpans) const; + static void CheckOneLink(const SkOpSpan* test, const SkOpSpan* oSpan, + const SkOpSpan* oFirst, const SkOpSpan* oLast, + const SkOpSpan** missingPtr, + SkTArray<MissingSpan, true>* missingSpans); + int checkSetAngle(int tIndex) const; + void checkSmallCoincidence(const SkOpSpan& span, SkTArray<MissingSpan, true>* ); bool clockwise(int tStart, int tEnd) const; static void ComputeOneSum(const SkOpAngle* baseAngle, SkOpAngle* nextAngle, SkOpAngle::IncludeType ); static void ComputeOneSumReverse(const SkOpAngle* baseAngle, SkOpAngle* nextAngle, SkOpAngle::IncludeType ); bool decrementSpan(SkOpSpan* span); - int findStartingEdge(const SkTArray<SkOpAngle*, true>& sorted, int start, int end); + int findEndSpan(int endIndex) const; + int findStartSpan(int startIndex) const; + int firstActive(int tIndex) const; + const SkOpSpan& firstSpan(const SkOpSpan& thisSpan) const; void init(const SkPoint pts[], SkPath::Verb verb, bool operand, bool evenOdd); + bool inLoop(const SkOpAngle* baseAngle, int spanCount, int* indexPtr) const; bool isSimple(int end) const; bool isTiny(int index) const; + const SkOpSpan& lastSpan(const SkOpSpan& thisSpan) const; void matchWindingValue(int tIndex, double t, bool borrowWind); SkOpSpan* markAndChaseDone(int index, int endIndex, int winding); SkOpSpan* markAndChaseDoneBinary(const SkOpAngle* angle, int winding, int oppWinding); - SkOpSpan* markAndChaseWinding(const SkOpAngle* angle, const int winding); + SkOpSpan* markAndChaseWinding(const SkOpAngle* angle, int winding); + SkOpSpan* markAndChaseWinding(int index, int endIndex, int winding); SkOpSpan* markAndChaseWinding(int index, int endIndex, int winding, int oppWinding); SkOpSpan* markAngle(int maxWinding, int sumWinding, const SkOpAngle* angle); void markDoneBinary(int index, int winding, int oppWinding); @@ -380,10 +441,21 @@ private: void markWinding(int index, int winding, int oppWinding); void markUnsortable(int start, int end); bool monotonicInY(int tStart, int tEnd) const; + + bool multipleEnds() const { + return fTs[count() - 2].fT == 1; + } + + bool multipleStarts() const { + return fTs[1].fT == 0; + } + bool multipleSpans(int end) const; SkOpSegment* nextChase(int* index, const int step, int* min, SkOpSpan** last); int nextExactSpan(int from, int step) const; bool serpentine(int tStart, int tEnd) const; + void setFromAngleIndex(int endIndex, int angleIndex); + void setToAngleIndex(int endIndex, int angleIndex); void setUpWindings(int index, int endIndex, int* sumMiWinding, int* maxWinding, int* sumWinding); void subDivideBounds(int start, int end, SkPathOpsBounds* bounds) const; @@ -395,7 +467,6 @@ private: int updateWinding(int index, int endIndex) const; int updateWinding(const SkOpAngle* angle) const; int updateWindingReverse(int index, int endIndex) const; - static bool UseInnerWindingReverse(int outerWinding, int innerWinding); SkOpSpan* verifyOneWinding(const char* funName, int tIndex); SkOpSpan* verifyOneWindingU(const char* funName, int tIndex); @@ -412,8 +483,12 @@ private: #if DEBUG_SWAP_TOP bool controlsContainedByEnds(int tStart, int tEnd) const; #endif + void debugAddAngle(int start, int end); #if DEBUG_CONCIDENT - void debugAddTPair(double t, const SkOpSegment& other, double otherT) const; + void debugAddTPair(double t, const SkOpSegment& other, double otherT) const; +#endif +#if DEBUG_ANGLE + void debugCheckPointsEqualish(int tStart, int tEnd) const; #endif #if DEBUG_MARK_DONE || DEBUG_UNSORTABLE void debugShowNewWinding(const char* fun, const SkOpSpan& span, int winding); @@ -424,27 +499,37 @@ private: return value < 0 ? '?' : value <= 9 ? '0' + value : '+'; } #endif - void debugValidate() const; -#ifdef SK_DEBUG - void dumpPts() const; + // available to testing only + void debugConstruct(); + void debugConstructCubic(SkPoint shortQuad[4]); + void debugConstructLine(SkPoint shortQuad[2]); + void debugConstructQuad(SkPoint shortQuad[3]); + void debugReset(); void dumpDPts() const; - void dumpSpans() const; -#endif + void dumpSpan(int index) const; const SkPoint* fPts; SkPathOpsBounds fBounds; // FIXME: can't convert to SkTArray because it uses insert - SkTDArray<SkOpSpan> fTs; // two or more (always includes t=0 t=1) + SkTDArray<SkOpSpan> fTs; // 2+ (always includes t=0 t=1) -- at least (number of spans) + 1 +// FIXME: replace both with bucket storage that allows direct immovable pointers to angles + SkTArray<SkOpAngle, true> fSingletonAngles; // 0 or 2 -- allocated for singletons + SkTArray<SkOpAngle, true> fAngles; // 0 or 2+ -- (number of non-zero spans) * 2 // OPTIMIZATION: could pack donespans, verb, operand, xor into 1 int-sized value int fDoneSpans; // quick check that segment is finished // OPTIMIZATION: force the following to be byte-sized SkPath::Verb fVerb; + bool fLoop; // set if cubic intersects itself bool fOperand; bool fXor; // set if original contour had even-odd fill bool fOppXor; // set if opposite operand had even-odd fill -#ifdef SK_DEBUG + bool fSmall; // set if some span is small + bool fTiny; // set if some span is tiny +#if defined(SK_DEBUG) || !FORCE_RELEASE int fID; #endif + + friend class PathOpsSegmentTester; }; #endif |