aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/pathops/SkOpSegment.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/pathops/SkOpSegment.h')
-rw-r--r--src/pathops/SkOpSegment.h191
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