aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/pathops
diff options
context:
space:
mode:
authorGravatar Cary Clark <caryclark@google.com>2017-01-23 14:38:52 +0000
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-01-23 15:31:25 +0000
commit59d5a0e3f560da40e0ae7036a01d7d58ce3718d8 (patch)
tree55a3467bdbbda58dc30eca902d20130a2a20346d /src/pathops
parentb07a01e6b9bd552bab12aabd48dc77a7562f4f97 (diff)
Revert "offset angle check edge in common"
This reverts commit d2eb581ebc8f8009e80cccccd74d5b341ef5bd5b. Reason for revert: broke Google3 MSAN run of dm Original change's description: > offset angle check edge in common > > When curves cross, their intersection points may be nearby, but not exactly the same. > Sort the angles formed by the crossing curves when all angles don't have the same > origin. > > This sets up the framework to solve test case that currently fail (e.g., joel6) but > does not fix all related test cases (e.g., joel9). > > All older existing test cases, including extended tests, pass. > > Rework the test framework to better report when tests expected to produce failing > results now pass. > > Add new point and vector operations to support offset angles. > > TBR=reed@google.com > BUG=skia:6041 > > Change-Id: I67c651ded0a25e99ad93d55d6a35109b3ee3698e > Reviewed-on: https://skia-review.googlesource.com/6624 > Commit-Queue: Cary Clark <caryclark@google.com> > Reviewed-by: Cary Clark <caryclark@google.com> > TBR=caryclark@google.com,reviews@skia.org # Not skipping CQ checks because original CL landed > 1 day ago. BUG=skia:6041 Change-Id: I43db0808522ac44aceeb4f70e296167ea84a3663 Reviewed-on: https://skia-review.googlesource.com/7373 Commit-Queue: Cary Clark <caryclark@google.com> Reviewed-by: Cary Clark <caryclark@google.com>
Diffstat (limited to 'src/pathops')
-rw-r--r--src/pathops/SkOpAngle.cpp356
-rw-r--r--src/pathops/SkOpAngle.h20
-rw-r--r--src/pathops/SkPathOpsDebug.cpp24
-rw-r--r--src/pathops/SkPathOpsDebug.h1
-rw-r--r--src/pathops/SkPathOpsPoint.h30
-rw-r--r--src/pathops/SkPathOpsTypes.h2
6 files changed, 72 insertions, 361 deletions
diff --git a/src/pathops/SkOpAngle.cpp b/src/pathops/SkOpAngle.cpp
index f41ef234d4..c07e8cc73f 100644
--- a/src/pathops/SkOpAngle.cpp
+++ b/src/pathops/SkOpAngle.cpp
@@ -62,15 +62,23 @@ bool SkOpAngle::after(SkOpAngle* test) {
SkOpAngle* lh = test;
SkOpAngle* rh = lh->fNext;
SkASSERT(lh != rh);
+ fPart.fCurve = fOriginalCurvePart;
+ lh->fPart.fCurve = lh->fOriginalCurvePart;
+ lh->fPart.fCurve.offset(lh->segment()->verb(), fPart.fCurve[0] - lh->fPart.fCurve[0]);
+ rh->fPart.fCurve = rh->fOriginalCurvePart;
+ rh->fPart.fCurve.offset(rh->segment()->verb(), fPart.fCurve[0] - rh->fPart.fCurve[0]);
+
#if DEBUG_ANGLE
SkString bugOut;
- this->debugAfter(lh, rh, &bugOut);
+ bugOut.printf("%s [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g"
+ " < [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g"
+ " < [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g ", __FUNCTION__,
+ lh->segment()->debugID(), lh->debugID(), lh->fSectorStart, lh->fSectorEnd,
+ lh->fStart->t(), lh->fEnd->t(),
+ segment()->debugID(), debugID(), fSectorStart, fSectorEnd, fStart->t(), fEnd->t(),
+ rh->segment()->debugID(), rh->debugID(), rh->fSectorStart, rh->fSectorEnd,
+ rh->fStart->t(), rh->fEnd->t());
SkString bugPart[3] = { lh->debugPart(), this->debugPart(), rh->debugPart() };
-#if 0 // convenient place to set a breakpoint to trace through a specific angle compare
- if (lh->debugID() == 4 && this->debugID() == 16 && rh->debugID() == 5) {
- SkDebugf("");
- }
-#endif
#endif
if (lh->fComputeSector && !lh->computeSector()) {
return COMPARE_RESULT(1, true);
@@ -82,106 +90,23 @@ bool SkOpAngle::after(SkOpAngle* test) {
return COMPARE_RESULT(3, true);
}
#if DEBUG_ANGLE // reset bugOut with computed sectors
- this->debugAfter(lh, rh, &bugOut);
+ bugOut.printf("%s [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g"
+ " < [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g"
+ " < [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g ", __FUNCTION__,
+ lh->segment()->debugID(), lh->debugID(), lh->fSectorStart, lh->fSectorEnd,
+ lh->fStart->t(), lh->fEnd->t(),
+ segment()->debugID(), debugID(), fSectorStart, fSectorEnd, fStart->t(), fEnd->t(),
+ rh->segment()->debugID(), rh->debugID(), rh->fSectorStart, rh->fSectorEnd,
+ rh->fStart->t(), rh->fEnd->t());
#endif
- /* If the curve pairs share a point, the computed sector is valid. Otherwise, the sectors must
- be sufficiently different that translating them won't change the sort order. For instance,
- curves with different origins may mis-sort if the computed sectors are 1 and 5.
-
- Curves with different origins have more information though -- there are more ways for their
- convex hulls not to overlap. Try to resolve different origins directly before translating
- one curve to share the opposite's origin.
- */
- bool lrOverlap, ltrOverlap;
- SkDVector lhOffset = fOriginalCurvePart[0] - lh->fOriginalCurvePart[0];
- bool lhHasOffset = lhOffset.fX || lhOffset.fY;
- SkDVector rhOffset = fOriginalCurvePart[0] - rh->fOriginalCurvePart[0];
- bool rhHasOffset = rhOffset.fX || rhOffset.fY;
- int lhStart, lhEnd, thStart, thEnd, rhStart, rhEnd;
- bool lhX0, thX0, rhX0;
- if (lhHasOffset | rhHasOffset) {
- lhX0 = lh->sectorRange(&lhStart, &lhEnd, lhHasOffset);
- thX0 = this->sectorRange(&thStart, &thEnd, false);
- rhX0 = rh->sectorRange(&rhStart, &rhEnd, rhHasOffset);
- lrOverlap = lhX0 + rhX0 + (lhStart <= rhEnd) + (rhStart <= lhEnd) >= 2;
- ltrOverlap = thX0 + lhX0 + (lhStart <= thEnd) + (thStart <= lhEnd) >= 2
- || rhX0 + thX0 + (thStart <= rhEnd) + (rhStart <= thEnd) >= 2;
- } else {
- lrOverlap = lh->fSectorMask & rh->fSectorMask;
- ltrOverlap = (lh->fSectorMask | rh->fSectorMask) & fSectorMask;
- }
- if (!lrOverlap & !ltrOverlap) { // no lh/this/rh sector overlap
- return COMPARE_RESULT(4, (lh->fSectorEnd > rh->fSectorStart)
- ^ (fSectorStart > lh->fSectorEnd) ^ (fSectorStart > rh->fSectorStart));
- }
+ bool ltrOverlap = (lh->fSectorMask | rh->fSectorMask) & fSectorMask;
+ bool lrOverlap = lh->fSectorMask & rh->fSectorMask;
int lrOrder; // set to -1 if either order works
- fPart.fCurve = fOriginalCurvePart;
- lh->fPart.fCurve = lh->fOriginalCurvePart;
- rh->fPart.fCurve = rh->fOriginalCurvePart;
- if (lhHasOffset | rhHasOffset) {
- bool lhSweepsCCW = lh->sweepsCCW();
- bool thSweepsCCW = this->sweepsCCW();
- bool rhSweepsCCW = rh->sweepsCCW();
- Turn thStartFromLhEnd = this->ccwOf(lh, lhSweepsCCW, !thSweepsCCW);
- Turn thEndFromRhStart = this->ccwOf(rh, !rhSweepsCCW, thSweepsCCW);
- if (!lrOverlap && Turn::kCcw == thStartFromLhEnd && Turn::kCw == thEndFromRhStart) {
- if (!this->sweepContains(lh) && !this->sweepContains(rh)) {
- return COMPARE_RESULT(5, true);
- }
- }
- Turn lhStartFromRhStart = lh->ccwOf(rh, !rhSweepsCCW, !lhSweepsCCW);
- Turn lhEndFromRhStart = lh->fPart.isCurve()
- ? lh->ccwOf(rh, !rhSweepsCCW, lhSweepsCCW) : lhStartFromRhStart;
- bool lhOrRhIsCurve = lh->fPart.isCurve() || rh->fPart.isCurve();
- Turn lhStartFromRhEnd;
- if (lhOrRhIsCurve) {
- if (rh->fPart.isCurve()) {
- lhStartFromRhEnd = lh->ccwOf(rh, rhSweepsCCW, !lhSweepsCCW);
- } else {
- lhStartFromRhEnd = lhStartFromRhStart;
- }
- // cancel overlap only if sweep doesn't contain other curve's sweep pts
- if (!lh->sweepContains(rh)) {
- // clear overlap if both turn in the same direction
- lrOverlap &= (int) lhStartFromRhEnd * (int) lhEndFromRhStart < 0;
- }
- } else {
- lrOverlap = false;
- }
- Turn thStartFromRhEnd SkDEBUGCODE(= Turn::kDebugUninitialized);
- Turn thEndFromLhStart SkDEBUGCODE(= Turn::kDebugUninitialized);
- if (lhOrRhIsCurve || fPart.isCurve()) {
- thStartFromRhEnd = rh->fPart.isCurve() || fPart.isCurve()
- ? this->ccwOf(rh, rhSweepsCCW, !thSweepsCCW) : thEndFromRhStart;
- thEndFromLhStart = lh->fPart.isCurve() || fPart.isCurve()
- ? this->ccwOf(lh, !lhSweepsCCW, thSweepsCCW) : thStartFromLhEnd;
- // clear overlap if both pairs turn in the same direction
- if (!this->sweepContains(lh) && !this->sweepContains(rh)) {
- ltrOverlap &= (int) thStartFromRhEnd * (int) thEndFromRhStart <= 0
- || (int) thStartFromLhEnd * (int) thEndFromLhStart <= 0;
- }
- } else {
- ltrOverlap = false;
+ if (!lrOverlap) { // no lh/rh sector overlap
+ if (!ltrOverlap) { // no lh/this/rh sector overlap
+ return COMPARE_RESULT(4, (lh->fSectorEnd > rh->fSectorStart)
+ ^ (fSectorStart > lh->fSectorEnd) ^ (fSectorStart > rh->fSectorStart));
}
- if (!lrOverlap & !ltrOverlap) {
- Turn lhFromRh = (Turn) ((int) lhEndFromRhStart | (int) lhStartFromRhStart);
- Turn thFromLh = (Turn) ((int) thEndFromLhStart | (int) thStartFromLhEnd);
- Turn thFromRh = (Turn) ((int) thEndFromRhStart | (int) thStartFromRhEnd);
- bool result = Turn::kCw == lhFromRh ?
- Turn::kCcw == thFromLh && Turn::kCw == thFromRh :
- Turn::kCcw == thFromLh || Turn::kCw == thFromRh;
- return COMPARE_RESULT(6, result);
- }
- if (lhHasOffset) {
- lh->fPart.fCurve.offset(lh->segment()->verb(), lhOffset);
- }
- if (rhHasOffset) {
- rh->fPart.fCurve.offset(rh->segment()->verb(), rhOffset);
- }
- lrOverlap = lh->fSectorMask & rh->fSectorMask;
- ltrOverlap = (lh->fSectorMask | rh->fSectorMask) & fSectorMask;
- }
- if (!lrOverlap) { // no lh/rh sector overlap, no offsets
int lrGap = (rh->fSectorStart - lh->fSectorStart + 32) & 0x1f;
/* A tiny change can move the start +/- 4. The order can only be determined if
lr gap is not 12 to 20 or -12 to -20.
@@ -197,13 +122,11 @@ bool SkOpAngle::after(SkOpAngle* test) {
} else {
lrOrder = (int) lh->orderable(rh);
if (!ltrOverlap) {
- return COMPARE_RESULT(7, !lrOrder);
+ return COMPARE_RESULT(5, !lrOrder);
}
}
int ltOrder;
- SkDEBUGCODE(bool ltOverlap = lhHasOffset || lh->fSectorMask & fSectorMask);
- SkDEBUGCODE(bool trOverlap = rhHasOffset || rh->fSectorMask & fSectorMask);
- SkASSERT(ltOverlap || trOverlap);
+ SkASSERT((lh->fSectorMask & fSectorMask) || (rh->fSectorMask & fSectorMask));
if (lh->fSectorMask & fSectorMask) {
ltOrder = (int) lh->orderable(this);
} else {
@@ -220,7 +143,7 @@ bool SkOpAngle::after(SkOpAngle* test) {
this->alignmentSameSide(lh, &ltOrder);
this->alignmentSameSide(rh, &trOrder);
if (lrOrder >= 0 && ltOrder >= 0 && trOrder >= 0) {
- return COMPARE_RESULT(8, lrOrder ? (ltOrder & trOrder) : (ltOrder | trOrder));
+ return COMPARE_RESULT(7, lrOrder ? (ltOrder & trOrder) : (ltOrder | trOrder));
}
SkASSERT(lrOrder >= 0 || ltOrder >= 0 || trOrder >= 0);
// There's not enough information to sort. Get the pairs of angles in opposite planes.
@@ -232,25 +155,25 @@ bool SkOpAngle::after(SkOpAngle* test) {
SkDEBUGCODE(bool lrOpposite = lh->oppositePlanes(rh));
bool ltOpposite = lh->oppositePlanes(this);
SkOPASSERT(lrOpposite != ltOpposite);
- return COMPARE_RESULT(9, ltOpposite);
+ return COMPARE_RESULT(8, ltOpposite);
} else if (ltOrder == 1 && trOrder == 0) {
SkASSERT(lrOrder < 0);
bool trOpposite = oppositePlanes(rh);
- return COMPARE_RESULT(10, trOpposite);
+ return COMPARE_RESULT(9, trOpposite);
} else if (lrOrder == 1 && trOrder == 1) {
SkASSERT(ltOrder < 0);
// SkDEBUGCODE(bool trOpposite = oppositePlanes(rh));
bool lrOpposite = lh->oppositePlanes(rh);
// SkASSERT(lrOpposite != trOpposite);
- return COMPARE_RESULT(11, lrOpposite);
+ return COMPARE_RESULT(10, lrOpposite);
}
if (lrOrder < 0) {
if (ltOrder < 0) {
- return COMPARE_RESULT(12, trOrder);
+ return COMPARE_RESULT(11, trOrder);
}
- return COMPARE_RESULT(13, ltOrder);
+ return COMPARE_RESULT(12, ltOrder);
}
- return COMPARE_RESULT(14, !lrOrder);
+ return COMPARE_RESULT(13, !lrOrder);
}
// given a line, see if the opposite curve's convex hull is all on one side
@@ -325,101 +248,10 @@ void SkOpAngle::alignmentSameSide(const SkOpAngle* test, int* order) const {
}
}
-static bool same_side(double cross1, double cross2) {
- return cross1 * cross2 > 0 && !roughly_zero_when_compared_to(cross1, cross2)
- && !roughly_zero_when_compared_to(cross2, cross1);
-}
-
-static double same_side_candidate(double cross1, double cross2) {
- return same_side(cross1, cross2) ? SkTAbs(cross1) > SkTAbs(cross2) ? cross1 : cross2 : 0;
-}
-
-SkOpAngle::Turn SkOpAngle::ccwOf(const SkOpAngle* rh, bool rhCW, bool thisCCW, bool recursed)
- const {
- const SkDPoint& startPt = fPart.fCurve[0];
- const SkDPoint& rhStartPt = rh->fPart.fCurve[0];
- SkDVector startOffset = rhStartPt - startPt;
- bool commonPt = 0 == startOffset.fX && 0 == startOffset.fY;
- const SkDVector& sweep = fPart.fSweep[(int) thisCCW];
- const SkDVector& rhSweep = rh->fPart.fSweep[(int) rhCW];
- const SkDVector* testV;
- SkDVector rhEndV;
- if (commonPt) {
- testV = &rhSweep;
- } else {
- rhEndV = rhSweep + startOffset;
- testV = &rhEndV;
- }
- double endCheck = sweep.crossCheck(*testV);
-#if 0 && DEBUG_ANGLE // too verbose to show on all the time
- SkDebugf("%s {{{%1.9g,%1.9g}, {%1.9g,%1.9g}}} id=1\n", __func__, rhStartPt.fX, rhStartPt.fY,
- rhStartPt.fX + rhSweep.fX, rhStartPt.fY + rhSweep.fY);
- SkDebugf("%s {{{%1.9g,%1.9g}, {%1.9g,%1.9g}}} id=2\n", __func__, startPt.fX, startPt.fY,
- startPt.fX + sweep.fX, startPt.fY + sweep.fY);
-#endif
- if (0 == endCheck) {
- if (sweep.dot(*testV) < 0) {
- return Turn::kNone; // neither clockwise nor counterclockwise
- }
- // if the pair of angles share an edge, use its other sweep to check the turn value
- if ((fPart.isCurve() || rh->fPart.isCurve())) {
- if (recursed) {
- return Turn::kNone;
- }
- return this->ccwOf(rh, !rhCW, !thisCCW, true);
- }
- }
- if (commonPt) {
- return toTurn(endCheck > 0);
- }
- double startCheck = sweep.crossCheck(startOffset);
- if ((startCheck == 0 || startOffset.lengthSquared() < FLT_EPSILON_SQUARED * 2049) &&
- (endCheck == 0 || testV->lengthSquared() < FLT_EPSILON_SQUARED * 2049)) {
- double cross = sweep.cross(rhSweep);
- if (cross != 0)
- return toTurn(cross > 0);
- }
- if (same_side(startCheck, endCheck)) {
- return toTurn(startCheck > 0);
- }
- SkDVector reverseSweep = -sweep;
- SkDVector rhReverseStartV = startOffset - sweep;
- double reverseStartCheck = reverseSweep.crossCheck(rhReverseStartV);
- SkDVector rhReverseEndV = rhReverseStartV + rhSweep;
- double reverseEndCheck = reverseSweep.crossCheck(rhReverseEndV);
- if (same_side(reverseStartCheck, reverseEndCheck)) {
- return toTurn(reverseStartCheck < 0);
- }
- double rhEndCheck = rhSweep.crossCheck(rhReverseEndV);
- double rhStartCheck = rhSweep.crossCheck(*testV);
- double endSide = same_side_candidate(rhEndCheck, rhStartCheck);
- SkDVector rhReverseSweep = -rhSweep;
- double rhReverseEndCheck = rhReverseSweep.crossCheck(rhReverseStartV);
- double rhReverseStartCheck = rhReverseSweep.crossCheck(startOffset);
- double startSide = -same_side_candidate(rhReverseEndCheck, rhReverseStartCheck);
- if (startSide || endSide) {
- return toTurn((SkTAbs(startSide) > SkTAbs(endSide) ? startSide : endSide) > 0);
- }
- // if a pair crosses only slightly, no two ends will be on the same side
- // look for the smaller ratio to guess which segment only crosses the other slightly
- double crosses[] = { endCheck, reverseStartCheck, reverseEndCheck,
- rhStartCheck, rhEndCheck, rhReverseStartCheck, rhReverseEndCheck };
- int smallest = -1;
- double smallCross = SkTAbs(startCheck);
- for (int index = 0; index < (int) SK_ARRAY_COUNT(crosses); ++index) {
- double testCross = SkTAbs(crosses[index]);
- if (smallCross > testCross) {
- smallCross = testCross;
- smallest = index;
- }
- }
- return toTurn((smallest <= 2 ? endCheck : -rhReverseEndCheck) > 0);
-}
-
-bool SkOpAngle::checkCrossesZero(int* start, int* end) const {
- *start = SkTMin(fSectorStart, fSectorEnd);
- *end = SkTMax(fSectorStart, fSectorEnd);
- bool crossesZero = *end - *start > 16;
+bool SkOpAngle::checkCrossesZero() const {
+ int start = SkTMin(fSectorStart, fSectorEnd);
+ int end = SkTMax(fSectorStart, fSectorEnd);
+ bool crossesZero = end - start > 16;
return crossesZero;
}
@@ -794,6 +626,7 @@ SkOpGlobalState* SkOpAngle::globalState() const {
return this->segment()->globalState();
}
+
// OPTIMIZE: if this loops to only one other angle, after first compare fails, insert on other side
// OPTIMIZE: return where insertion succeeded. Then, start next insertion on opposite side
bool SkOpAngle::insert(SkOpAngle* angle) {
@@ -1016,19 +849,6 @@ SkOpAngle* SkOpAngle::previous() const {
} while (true);
}
-// returns true if rounded sector range crosses zero
-bool SkOpAngle::sectorRange(int* start, int* end, bool roundOut) const {
- if (checkCrossesZero(start, end)) {
- SkTSwap(*start, *end);
- }
- // round away since the offset curves may swap order
- if (roundOut) {
- *start = (((*start + 1) & ~0x03) - 1) & 0x1f;
- *end |= 0x03;
- }
- return *end < *start;
-}
-
SkOpSegment* SkOpAngle::segment() const {
return fStart->segment();
}
@@ -1165,25 +985,23 @@ deferTilLater:
fSectorMask = 1 << fSectorStart;
return;
}
- int start, end;
- bool crossesZero = this->checkCrossesZero(&start, &end);
- bool bumpStart = (fSectorStart & 3) == 3;
- bool bumpEnd = (fSectorEnd & 3) == 3;
- if (bumpStart | bumpEnd) {
- bool curveBendsCCW = (fSectorStart == start) ^ crossesZero;
- // bump the start and end of the sector span if they are on exact compass points
- if (bumpStart) {
- fSectorStart = (fSectorStart + (curveBendsCCW ? 1 : 31)) & 0x1f;
- }
- if (bumpEnd) {
- fSectorEnd = (fSectorEnd + (curveBendsCCW ? 31 : 1)) & 0x1f;
- }
- crossesZero = this->checkCrossesZero(&start, &end);
+ bool crossesZero = this->checkCrossesZero();
+ int start = SkTMin(fSectorStart, fSectorEnd);
+ bool curveBendsCCW = (fSectorStart == start) ^ crossesZero;
+ // bump the start and end of the sector span if they are on exact compass points
+ if ((fSectorStart & 3) == 3) {
+ fSectorStart = (fSectorStart + (curveBendsCCW ? 1 : 31)) & 0x1f;
}
+ if ((fSectorEnd & 3) == 3) {
+ fSectorEnd = (fSectorEnd + (curveBendsCCW ? 31 : 1)) & 0x1f;
+ }
+ crossesZero = this->checkCrossesZero();
+ start = SkTMin(fSectorStart, fSectorEnd);
+ int end = SkTMax(fSectorStart, fSectorEnd);
if (!crossesZero) {
fSectorMask = (unsigned) -1 >> (31 - end + start) << start;
} else {
- fSectorMask = (unsigned) -1 >> (31 - start) | (unsigned) -1 << end;
+ fSectorMask = (unsigned) -1 >> (31 - start) | ((unsigned) -1 << end);
}
}
@@ -1191,70 +1009,6 @@ SkOpSpan* SkOpAngle::starter() {
return fStart->starter(fEnd);
}
-bool SkOpAngle::sweepsCCW() const {
- if (!fPart.isCurve()) {
- return false; // lines have no sweep
- }
-#if 0 && DEBUG_ANGLE // too verbose to show all the time
- SkDebugf("%s {{{0,0}, {%g,%g}}} id=1\n", __func__, fPart.fSweep[0].fX, fPart.fSweep[0].fY);
- SkDebugf("%s {{{0,0}, {%g,%g}}} id=2\n", __func__, fPart.fSweep[1].fX, fPart.fSweep[1].fY);
-#endif
- return fPart.fSweep[0].crossCheck(fPart.fSweep[1]) < 0;
-}
-
-static bool sweep_edge_contains(const SkDVector& edge, const SkDVector& v, double* direction) {
- double cross = edge.crossCheck(v);
- if (cross) {
- if (cross * *direction < 0) {
- return true;
- }
- *direction = cross;
- }
- return false;
-}
-
-static bool sweep_contains(const SkDVector sweep[2], const SkDVector& v, double* direction) {
- if (sweep_edge_contains(sweep[0], v, direction)) {
- return true;
- }
- return sweep_edge_contains(sweep[1], v, direction);
-}
-
-bool SkOpAngle::sweepContains(const SkOpAngle* rh) const {
- if (!fPart.isCurve()) {
- return false;
- }
- if (!rh->fPart.isCurve()) {
- return false;
- }
- const SkDPoint& startPt = fPart.fCurve[0];
- const SkDVector* sweep = fPart.fSweep;
- const SkDPoint& rhStartPt = rh->fPart.fCurve[0];
- double direction = 0;
- if (startPt != rhStartPt) {
- SkDVector vTest = rhStartPt - startPt;
- if (sweep_contains(sweep, vTest, &direction)) {
- return true;
- }
- for (int index = 0; index < (int) SK_ARRAY_COUNT(rh->fPart.fSweep); ++index) {
- SkDPoint sweepEnd = rhStartPt;
- sweepEnd += rh->fPart.fSweep[index];
- SkDVector vTest = sweepEnd - startPt;
- if (sweep_contains(sweep, vTest, &direction)) {
- return true;
- }
- }
- } else {
- for (int index = 0; index < (int) SK_ARRAY_COUNT(rh->fPart.fSweep); ++index) {
- const SkDVector& vTest = rh->fPart.fSweep[index];
- if (sweep_contains(sweep, vTest, &direction)) {
- return true;
- }
- }
- }
- return false;
-}
-
bool SkOpAngle::tangentsDiverge(const SkOpAngle* rh, double s0xt0) {
if (s0xt0 == 0) {
return false;
diff --git a/src/pathops/SkOpAngle.h b/src/pathops/SkOpAngle.h
index d11a1c1ee5..d8615c3229 100644
--- a/src/pathops/SkOpAngle.h
+++ b/src/pathops/SkOpAngle.h
@@ -41,12 +41,8 @@ public:
#endif
#if DEBUG_ANGLE
- void debugAfter(const SkOpAngle* lh, const SkOpAngle* rh, SkString* bugOut) const;
bool debugCheckCoincidence() const { return fCheckCoincidence; }
void debugCheckNearCoincidence() const;
-#endif
- SkDPoint* debugFirstPt() { return &fOriginalCurvePart.fLine.fPts[0]; }
-#if DEBUG_ANGLE
SkString debugPart() const;
#endif
const SkOpPtT* debugPtT(int id) const;
@@ -100,20 +96,10 @@ public:
}
private:
- enum class Turn {
-#ifdef SK_DEBUG
- kDebugUninitialized = -2,
-#endif
- kCcw = -1,
- kNone,
- kCw
- };
-
bool after(SkOpAngle* test);
void alignmentSameSide(const SkOpAngle* test, int* order) const;
int allOnOneSide(const SkOpAngle* test);
- Turn ccwOf(const SkOpAngle* rh, bool rhCW, bool thisCCW, bool recursed = false) const;
- bool checkCrossesZero(int* start, int* end) const;
+ bool checkCrossesZero() const;
bool checkParallel(SkOpAngle* );
bool computeSector();
int convexHullOverlaps(const SkOpAngle* );
@@ -126,13 +112,9 @@ private:
bool midToSide(const SkOpAngle* rh, bool* inside) const;
bool oppositePlanes(const SkOpAngle* rh) const;
bool orderable(SkOpAngle* rh); // false == this < rh ; true == this > rh
- bool sectorRange(int* start, int* end, bool roundOut) const;
void setSector();
void setSpans();
- bool sweepContains(const SkOpAngle* rh) const;
- bool sweepsCCW() const;
bool tangentsDiverge(const SkOpAngle* rh, double s0xt0);
- Turn toTurn(bool ccw) const { return ccw ? Turn::kCcw : Turn::kCw; }
SkDCurve fOriginalCurvePart; // the curve from start to end
SkDCurveSweep fPart; // the curve from start to end offset as needed
diff --git a/src/pathops/SkPathOpsDebug.cpp b/src/pathops/SkPathOpsDebug.cpp
index 6ed37dc133..45a1138488 100644
--- a/src/pathops/SkPathOpsDebug.cpp
+++ b/src/pathops/SkPathOpsDebug.cpp
@@ -18,6 +18,7 @@ bool SkPathOpsDebug::gDumpOp; // set to true to write op to file before a crash
bool SkPathOpsDebug::gVerifyOp; // set to true to compare result against regions
#endif
+bool SkPathOpsDebug::gRunFail; // set to true to check for success on tests known to fail
bool SkPathOpsDebug::gVeryVerbose; // set to true to run extensive checking tests
#undef FAIL_IF
@@ -666,6 +667,10 @@ void SkOpGlobalState::debugResetLoopCounts() {
}
#endif
+bool SkOpGlobalState::DebugRunFail() {
+ return SkPathOpsDebug::gRunFail;
+}
+
// this is const so it can be called by const methods that overwise don't alter state
#if DEBUG_VALIDATE || DEBUG_COIN
void SkOpGlobalState::debugSetPhase(const char* funcName DEBUG_COIN_DECLARE_PARAMS()) const {
@@ -1244,17 +1249,6 @@ void SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan* span, int
This checks the distance between start points; the distance between
*/
#if DEBUG_ANGLE
-void SkOpAngle::debugAfter(const SkOpAngle* lh, const SkOpAngle* rh, SkString* bugOut) const {
- bugOut->printf("%s [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g"
- " < [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g"
- " < [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g ", __FUNCTION__,
- lh->segment()->debugID(), lh->debugID(), lh->fSectorStart, lh->fSectorEnd,
- lh->fStart->t(), lh->fEnd->t(),
- segment()->debugID(), debugID(), fSectorStart, fSectorEnd, fStart->t(), fEnd->t(),
- rh->segment()->debugID(), rh->debugID(), rh->fSectorStart, rh->fSectorEnd,
- rh->fStart->t(), rh->fEnd->t());
-}
-
void SkOpAngle::debugCheckNearCoincidence() const {
const SkOpAngle* test = this;
do {
@@ -1382,8 +1376,8 @@ void SkOpAngle::debugValidate() const {
}
next = next->fNext;
} while (next && next != first);
- SkASSERT(wind == 0);
- SkASSERT(opp == 0);
+ SkASSERT(wind == 0 || !SkPathOpsDebug::gRunFail);
+ SkASSERT(opp == 0 || !SkPathOpsDebug::gRunFail);
#endif
}
@@ -1410,8 +1404,8 @@ void SkOpAngle::debugValidateNext() const {
#ifdef SK_DEBUG
void SkCoincidentSpans::debugStartCheck(const SkOpSpanBase* outer, const SkOpSpanBase* over,
const SkOpGlobalState* debugState) const {
- SkASSERT(coinPtTEnd()->span() == over);
- SkASSERT(oppPtTEnd()->span() == outer);
+ SkASSERT(coinPtTEnd()->span() == over || !SkOpGlobalState::DebugRunFail());
+ SkASSERT(oppPtTEnd()->span() == outer || !SkOpGlobalState::DebugRunFail());
}
#endif
diff --git a/src/pathops/SkPathOpsDebug.h b/src/pathops/SkPathOpsDebug.h
index 0f3fadaf14..97fa534a2a 100644
--- a/src/pathops/SkPathOpsDebug.h
+++ b/src/pathops/SkPathOpsDebug.h
@@ -374,6 +374,7 @@ public:
static void DumpGlitchType(GlitchType );
#endif
+ static bool gRunFail;
static bool gVeryVerbose;
#if DEBUG_DUMP_VERIFY
diff --git a/src/pathops/SkPathOpsPoint.h b/src/pathops/SkPathOpsPoint.h
index deadbc2aa0..f314f69d0e 100644
--- a/src/pathops/SkPathOpsPoint.h
+++ b/src/pathops/SkPathOpsPoint.h
@@ -29,29 +29,13 @@ struct SkDVector {
fY += v.fY;
}
- SkDVector operator+(const SkDVector& v) const {
- SkDVector result = *this;
- result += v;
- return result;
- }
-
// only called by nearestT, which is currently only used by testing
void operator-=(const SkDVector& v) {
fX -= v.fX;
fY -= v.fY;
}
- SkDVector operator-(const SkDVector& v) const {
- SkDVector result = *this;
- result -= v;
- return result;
- }
-
- SkDVector operator-() const {
- SkDVector result = { -fX, -fY };
- return result;
- }
-
+ // only used by testing
void operator/=(const double s) {
fX /= s;
fY /= s;
@@ -105,13 +89,6 @@ struct SkDVector {
fX *= inverseLength;
fY *= inverseLength;
}
-
- void setLengthSquared(double lenSquared) {
- double inverseLength = lenSquared / this->lengthSquared();
- fX *= inverseLength;
- fY *= inverseLength;
- }
-
};
struct SkDPoint {
@@ -150,14 +127,15 @@ struct SkDPoint {
fY -= v.fY;
}
- SkDPoint operator+(const SkDVector& v) const {
+ // only used by testing
+ SkDPoint operator+(const SkDVector& v) {
SkDPoint result = *this;
result += v;
return result;
}
// only used by testing
- SkDPoint operator-(const SkDVector& v) const {
+ SkDPoint operator-(const SkDVector& v) {
SkDPoint result = *this;
result -= v;
return result;
diff --git a/src/pathops/SkPathOpsTypes.h b/src/pathops/SkPathOpsTypes.h
index 4e9fbe9ac5..f525ea49db 100644
--- a/src/pathops/SkPathOpsTypes.h
+++ b/src/pathops/SkPathOpsTypes.h
@@ -77,6 +77,8 @@ public:
const class SkOpPtT* debugPtT(int id) const;
#endif
+ static bool DebugRunFail();
+
#ifdef SK_DEBUG
const class SkOpSegment* debugSegment(int id) const;
bool debugSkipAssert() const { return fDebugSkipAssert; }