diff options
author | 2014-10-28 10:55:54 -0700 | |
---|---|---|
committer | 2014-10-28 10:55:54 -0700 | |
commit | 27c46a08a9210e9306b8ea1b00349ec198153c38 (patch) | |
tree | 31548283108b4e997adc12651ae77acbb6c3fc8c /src | |
parent | ee0c2e4fd429424beaa35f29e7f656997ba3f115 (diff) |
Revert of harden pathops for pathological test (patchset #19 id:410001 of https://codereview.chromium.org/633393002/)
Reason for revert:
Compile errors on bots
Original issue's description:
> These tests stress pathops by describing the union of circle-like paths that have tiny line segments embedded and double back to create near-coincident conditions.
>
> The fixes include
> - detect when finding the active top loops between two possible answers
> - preflight chasing winding to ensure answer is consistent
> - binary search more often when quadratic intersection fails
> - add more failure paths when an intersect is missed
>
> While this fixes the chrome bug, reenabling path ops in svg should be deferred until additional fixes are landed.
>
> TBR=
> BUG=421132
>
> Committed: https://skia.googlesource.com/skia/+/6f726addf3178b01949bb389ef83cf14a1d7b6b2
TBR=caryclark@google.com
NOTREECHECKS=true
NOTRY=true
BUG=421132
Review URL: https://codereview.chromium.org/686843002
Diffstat (limited to 'src')
-rw-r--r-- | src/pathops/SkAddIntersections.cpp | 1 | ||||
-rw-r--r-- | src/pathops/SkDCubicIntersection.cpp | 10 | ||||
-rw-r--r-- | src/pathops/SkDQuadIntersection.cpp | 70 | ||||
-rw-r--r-- | src/pathops/SkIntersections.cpp | 6 | ||||
-rw-r--r-- | src/pathops/SkIntersections.h | 15 | ||||
-rw-r--r-- | src/pathops/SkOpAngle.cpp | 11 | ||||
-rw-r--r-- | src/pathops/SkOpAngle.h | 8 | ||||
-rw-r--r-- | src/pathops/SkOpContour.cpp | 2 | ||||
-rw-r--r-- | src/pathops/SkOpContour.h | 9 | ||||
-rw-r--r-- | src/pathops/SkOpSegment.cpp | 556 | ||||
-rw-r--r-- | src/pathops/SkOpSegment.h | 42 | ||||
-rw-r--r-- | src/pathops/SkPathOpsCommon.cpp | 63 | ||||
-rw-r--r-- | src/pathops/SkPathOpsDebug.h | 4 | ||||
-rw-r--r-- | src/pathops/SkPathOpsOp.cpp | 57 | ||||
-rw-r--r-- | src/pathops/SkPathOpsPoint.h | 1 | ||||
-rw-r--r-- | src/pathops/SkPathOpsTypes.h | 6 | ||||
-rw-r--r-- | src/pathops/SkReduceOrder.cpp | 4 |
17 files changed, 135 insertions, 730 deletions
diff --git a/src/pathops/SkAddIntersections.cpp b/src/pathops/SkAddIntersections.cpp index d98d1777f0..27422eda5f 100644 --- a/src/pathops/SkAddIntersections.cpp +++ b/src/pathops/SkAddIntersections.cpp @@ -307,7 +307,6 @@ bool AddIntersectTs(SkOpContour* test, SkOpContour* next) { } case SkIntersectionHelper::kQuad_Segment: { pts = ts.quadQuad(wt.pts(), wn.pts()); - ts.alignQuadPts(wt.pts(), wn.pts()); debugShowQuadIntersection(pts, wt, wn, ts); break; } diff --git a/src/pathops/SkDCubicIntersection.cpp b/src/pathops/SkDCubicIntersection.cpp index 2fb35e1827..9d83242eda 100644 --- a/src/pathops/SkDCubicIntersection.cpp +++ b/src/pathops/SkDCubicIntersection.cpp @@ -109,14 +109,12 @@ static void intersect(const SkDCubic& cubic1, double t1s, double t1e, const SkDC __FUNCTION__, t1Start, t1, t2Start, t2); SkIntersections xlocals; xlocals.allowNear(false); - xlocals.allowFlatMeasure(true); intersectWithOrder(s1.fQuad, o1, s2.fQuad, o2, xlocals); SkDebugf(" xlocals.fUsed=%d\n", xlocals.used()); } #endif SkIntersections locals; locals.allowNear(false); - locals.allowFlatMeasure(true); intersectWithOrder(s1.fQuad, o1, s2.fQuad, o2, locals); int tCount = locals.used(); for (int tIdx = 0; tIdx < tCount; ++tIdx) { @@ -298,7 +296,6 @@ bool SkIntersections::cubicExactEnd(const SkDCubic& cubic1, bool start, const Sk tmpLine[1].fY -= cubic2[2 - start].fX - cubic2[t1Index].fX; SkIntersections impTs; impTs.allowNear(false); - impTs.allowFlatMeasure(true); impTs.intersectRay(cubic1, tmpLine); for (int index = 0; index < impTs.used(); ++index) { SkDPoint realPt = impTs.pt(index); @@ -559,7 +556,6 @@ int SkIntersections::intersect(const SkDCubic& c1, const SkDCubic& c2) { } SkIntersections i; i.fAllowNear = false; - i.fFlatMeasure = true; i.fMax = 9; ::intersect(c1, 0, 1, c2, 0, 1, 1, i); int compCount = i.used(); @@ -666,7 +662,7 @@ int SkIntersections::intersect(const SkDCubic& c1, const SkDCubic& c2) { // OPTIMIZATION If this is a common use case, optimize by duplicating // the intersect 3 loop to avoid the promotion / demotion code int SkIntersections::intersect(const SkDCubic& cubic, const SkDQuad& quad) { - fMax = 7; + fMax = 6; SkDCubic up = quad.toCubic(); (void) intersect(cubic, up); return used(); @@ -688,9 +684,7 @@ int SkIntersections::intersect(const SkDCubic& c) { // OPTIMIZATION: could quick reject if neither end point tangent ray intersected the line // segment formed by the opposite end point to the control point (void) intersect(c, c); - if (used() > 1) { - fUsed = 0; - } else if (used() > 0) { + if (used() > 0) { if (approximately_equal_double(fT[0][0], fT[1][0])) { fUsed = 0; } else { diff --git a/src/pathops/SkDQuadIntersection.cpp b/src/pathops/SkDQuadIntersection.cpp index fcb9171f32..239711c321 100644 --- a/src/pathops/SkDQuadIntersection.cpp +++ b/src/pathops/SkDQuadIntersection.cpp @@ -73,7 +73,6 @@ static int addValidRoots(const double roots[4], const int count, double valid[4] } else if (approximately_greater_than_one(t)) { t = 1; } - SkASSERT(t >= 0 && t <= 1); valid[result++] = t; } return result; @@ -243,18 +242,10 @@ static double flat_measure(const SkDQuad& q) { // FIXME ? should this measure both and then use the quad that is the flattest as the line? static bool is_linear(const SkDQuad& q1, const SkDQuad& q2, SkIntersections* i) { - if (i->flatMeasure()) { - // for backward compatibility, use the old method when called from cubics - // FIXME: figure out how to fix cubics when it calls the new path - double measure = flat_measure(q1); - // OPTIMIZE: (get rid of sqrt) use approximately_zero - if (!approximately_zero_sqrt(measure)) { // approximately_zero_sqrt - return false; - } - } else { - if (!q1.isLinear(0, 2)) { - return false; - } + double measure = flat_measure(q1); + // OPTIMIZE: (get rid of sqrt) use approximately_zero + if (!approximately_zero_sqrt(measure)) { + return false; } return is_linear_inner(q1, 0, 1, q2, 0, 1, i, NULL); } @@ -314,16 +305,6 @@ static bool binary_search(const SkDQuad& quad1, const SkDQuad& quad2, double* t1 SkDebugf("%s t1=%1.9g t2=%1.9g (%1.9g,%1.9g) == (%1.9g,%1.9g)\n", __FUNCTION__, t1Seed, t2Seed, t1[1].fX, t1[1].fY, t2[1].fX, t2[1].fY); #endif - if (*t1Seed < 0) { - *t1Seed = 0; - } else if (*t1Seed > 1) { - *t1Seed = 1; - } - if (*t2Seed < 0) { - *t2Seed = 0; - } else if (*t2Seed > 1) { - *t2Seed = 1; - } return true; } if (calcMask & (1 << 0)) t1[0] = quad1.ptAtT(SkTMax(0., *t1Seed - tStep)); @@ -417,13 +398,11 @@ static void lookNearEnd(const SkDQuad& q1, const SkDQuad& q2, int testT, int SkIntersections::intersect(const SkDQuad& q1, const SkDQuad& q2) { fMax = 4; - bool exactMatch = false; // if the quads share an end point, check to see if they overlap for (int i1 = 0; i1 < 3; i1 += 2) { for (int i2 = 0; i2 < 3; i2 += 2) { if (q1[i1].asSkPoint() == q2[i2].asSkPoint()) { insert(i1 >> 1, i2 >> 1, q1[i1]); - exactMatch = true; } } } @@ -490,7 +469,6 @@ int SkIntersections::intersect(const SkDQuad& q1, const SkDQuad& q2) { int rootCount = findRoots(i2, q1, roots1, useCubic, flip1, 0); // OPTIMIZATION: could short circuit here if all roots are < 0 or > 1 double roots1Copy[4]; - SkDEBUGCODE(sk_bzero(roots1Copy, sizeof(roots1Copy))); int r1Count = addValidRoots(roots1, rootCount, roots1Copy); SkDPoint pts1[4]; for (index = 0; index < r1Count; ++index) { @@ -504,14 +482,12 @@ int SkIntersections::intersect(const SkDQuad& q1, const SkDQuad& q2) { for (index = 0; index < r2Count; ++index) { pts2[index] = q2.ptAtT(roots2Copy[index]); } - bool triedBinary = false; if (r1Count == r2Count && r1Count <= 1) { if (r1Count == 1 && used() == 0) { if (pts1[0].approximatelyEqual(pts2[0])) { insert(roots1Copy[0], roots2Copy[0], pts1[0]); } else { // find intersection by chasing t - triedBinary = true; if (binary_search(q1, q2, roots1Copy, roots2Copy, pts1)) { insert(roots1Copy[0], roots2Copy[0], pts1[0]); } @@ -552,18 +528,7 @@ int SkIntersections::intersect(const SkDQuad& q1, const SkDQuad& q2) { } } if (r1Count && r2Count && !foundSomething) { - if (exactMatch) { - SkASSERT(fUsed > 0); - return fUsed; - } relaxed_is_linear(&q1, 0, 1, &q2, 0, 1, this); - if (fUsed) { - return fUsed; - } - // maybe the curves are nearly coincident - if (!triedBinary && binary_search(q1, q2, roots1Copy, roots2Copy, pts1)) { - insert(roots1Copy[0], roots2Copy[0], pts1[0]); - } return fUsed; } int used = 0; @@ -588,30 +553,3 @@ int SkIntersections::intersect(const SkDQuad& q1, const SkDQuad& q2) { } while (++used < r1Count); return fUsed; } - -void SkIntersections::alignQuadPts(const SkPoint q1[3], const SkPoint q2[3]) { - for (int index = 0; index < used(); ++index) { - const SkPoint result = pt(index).asSkPoint(); - if (q1[0] == result || q1[2] == result || q2[0] == result || q2[2] == result) { - continue; - } - if (SkDPoint::ApproximatelyEqual(q1[0], result)) { - fPt[index].set(q1[0]); -// SkASSERT(way_roughly_zero(fT[0][index])); // this value can be bigger than way rough - fT[0][index] = 0; - } else if (SkDPoint::ApproximatelyEqual(q1[2], result)) { - fPt[index].set(q1[2]); -// SkASSERT(way_roughly_equal(fT[0][index], 1)); - fT[0][index] = 1; - } - if (SkDPoint::ApproximatelyEqual(q2[0], result)) { - fPt[index].set(q2[0]); -// SkASSERT(way_roughly_zero(fT[1][index])); - fT[1][index] = 0; - } else if (SkDPoint::ApproximatelyEqual(q2[2], result)) { - fPt[index].set(q2[2]); -// SkASSERT(way_roughly_equal(fT[1][index], 1)); - fT[1][index] = 1; - } - } -} diff --git a/src/pathops/SkIntersections.cpp b/src/pathops/SkIntersections.cpp index e9875cf69d..62c1e411ad 100644 --- a/src/pathops/SkIntersections.cpp +++ b/src/pathops/SkIntersections.cpp @@ -79,8 +79,6 @@ int SkIntersections::insert(double one, double two, const SkDPoint& pt) { || (precisely_equal(one, 1) && !precisely_equal(oldOne, 1)) || (precisely_zero(two) && !precisely_zero(oldTwo)) || (precisely_equal(two, 1) && !precisely_equal(oldTwo, 1))) { - SkASSERT(one >= 0 && one <= 1); - SkASSERT(two >= 0 && two <= 1); fT[0][index] = one; fT[1][index] = two; fPt[index] = pt; @@ -113,8 +111,6 @@ int SkIntersections::insert(double one, double two, const SkDPoint& pt) { fIsCoincident[1] += fIsCoincident[1] & clearMask; } fPt[index] = pt; - SkASSERT(one >= 0 && one <= 1); - SkASSERT(two >= 0 && two <= 1); fT[0][index] = one; fT[1][index] = two; ++fUsed; @@ -175,7 +171,7 @@ void SkIntersections::removeOne(int index) { memmove(&fPt2[index], &fPt2[index + 1], sizeof(fPt2[0]) * remaining); memmove(&fT[0][index], &fT[0][index + 1], sizeof(fT[0][0]) * remaining); memmove(&fT[1][index], &fT[1][index + 1], sizeof(fT[1][0]) * remaining); -// SkASSERT(fIsCoincident[0] == 0); + SkASSERT(fIsCoincident[0] == 0); int coBit = fIsCoincident[0] & (1 << index); fIsCoincident[0] -= ((fIsCoincident[0] >> 1) & ~((1 << index) - 1)) + coBit; SkASSERT(!(coBit ^ (fIsCoincident[1] & (1 << index)))); diff --git a/src/pathops/SkIntersections.h b/src/pathops/SkIntersections.h index 20823fac2b..040671093c 100644 --- a/src/pathops/SkIntersections.h +++ b/src/pathops/SkIntersections.h @@ -16,7 +16,6 @@ class SkIntersections { public: SkIntersections() : fSwap(0) - , fFlatMeasure(false) #ifdef SK_DEBUG , fDepth(0) #endif @@ -40,10 +39,6 @@ public: }; TArray operator[](int n) const { return TArray(fT[n]); } - void allowFlatMeasure(bool flatAllowed) { - fFlatMeasure = flatAllowed; - } - void allowNear(bool nearAllowed) { fAllowNear = nearAllowed; } @@ -93,14 +88,10 @@ public: cubic.set(a); SkDQuad quad; quad.set(b); - fMax = 7; + fMax = 6; return intersect(cubic, quad); } - bool flatMeasure() const { - return fFlatMeasure; - } - bool hasT(double t) const { SkASSERT(t == 0 || t == 1); return fUsed > 0 && (t == 0 ? fT[0][0] == 0 : fT[0][fUsed - 1] == 1); @@ -210,7 +201,7 @@ public: bool swapped() const { return fSwap; } - + int used() const { return fUsed; } @@ -223,7 +214,6 @@ public: SkASSERT(++fDepth < 16); } - void alignQuadPts(const SkPoint a[3], const SkPoint b[3]); void append(const SkIntersections& ); void cleanUpCoincidence(); int coincidentUsed() const; @@ -292,7 +282,6 @@ private: unsigned char fMax; bool fAllowNear; bool fSwap; - bool fFlatMeasure; // backwards-compatibility when cubics uses quad intersection #ifdef SK_DEBUG int fDepth; #endif diff --git a/src/pathops/SkOpAngle.cpp b/src/pathops/SkOpAngle.cpp index b3a188c1e8..0c87d3ba9e 100644 --- a/src/pathops/SkOpAngle.cpp +++ b/src/pathops/SkOpAngle.cpp @@ -409,12 +409,7 @@ bool SkOpAngle::endsIntersect(const SkOpAngle& rh) const { for (int index = 0; index < 2; ++index) { const SkOpSegment& segment = index ? *rh.fSegment : *fSegment; SkIntersections i; - int cPts = index ? rPts : lPts; - (*CurveIntersectRay[cPts])(segment.pts(), rays[index], &i); - // if the curve is a line, then the line and the ray intersect only at their crossing - if (cPts == 1) { // line - continue; - } + (*CurveIntersectRay[index ? rPts : lPts])(segment.pts(), rays[index], &i); // SkASSERT(i.used() >= 1); // if (i.used() <= 1) { // continue; @@ -662,7 +657,7 @@ void SkOpAngle::insert(SkOpAngle* angle) { } SkOpAngle* next = fNext; if (next->fNext == this) { - if (angle->overlap(*this)) { // angles are essentially coincident + if (angle->overlap(*this)) { return; } if (singleton || angle->after(this)) { @@ -782,7 +777,7 @@ bool SkOpAngle::merge(SkOpAngle* angle) { working = next; } while (working != angle); // it's likely that a pair of the angles are unorderable -#if 0 && DEBUG_ANGLE +#if DEBUG_ANGLE SkOpAngle* last = angle; working = angle->fNext; do { diff --git a/src/pathops/SkOpAngle.h b/src/pathops/SkOpAngle.h index 1dc4250613..098c470128 100644 --- a/src/pathops/SkOpAngle.h +++ b/src/pathops/SkOpAngle.h @@ -50,14 +50,6 @@ public: SkOpAngle* previous() const; - int sectorEnd() const { - return fSectorEnd; - } - - int sectorStart() const { - return fSectorStart; - } - void set(const SkOpSegment* segment, int start, int end); void setLastMarked(SkOpSpan* marked) { diff --git a/src/pathops/SkOpContour.cpp b/src/pathops/SkOpContour.cpp index 28c072a3c1..6d6ad7926e 100644 --- a/src/pathops/SkOpContour.cpp +++ b/src/pathops/SkOpContour.cpp @@ -13,7 +13,7 @@ bool SkOpContour::addCoincident(int index, SkOpContour* other, int otherIndex, const SkIntersections& ts, bool swap) { SkPoint pt0 = ts.pt(0).asSkPoint(); SkPoint pt1 = ts.pt(1).asSkPoint(); - if (pt0 == pt1 || ts[0][0] == ts[0][1] || ts[1][0] == ts[1][1]) { + if (pt0 == pt1) { // FIXME: one could imagine a case where it would be incorrect to ignore this // suppose two self-intersecting cubics overlap to be coincident -- // this needs to check that by some measure the t values are far enough apart diff --git a/src/pathops/SkOpContour.h b/src/pathops/SkOpContour.h index 7a1cc09247..899367ab0e 100644 --- a/src/pathops/SkOpContour.h +++ b/src/pathops/SkOpContour.h @@ -127,9 +127,9 @@ public: } } - bool checkEnds() { + void checkEnds() { if (!fContainsCurves) { - return true; + return; } int segmentCount = fSegments.count(); for (int sIndex = 0; sIndex < segmentCount; ++sIndex) { @@ -140,11 +140,8 @@ public: if (segment->done()) { continue; // likely coincident, nothing to do } - if (!segment->checkEnds()) { - return false; - } + segment->checkEnds(); } - return true; } void checkMultiples() { diff --git a/src/pathops/SkOpSegment.cpp b/src/pathops/SkOpSegment.cpp index c233c0f9b6..95046e2fd2 100644 --- a/src/pathops/SkOpSegment.cpp +++ b/src/pathops/SkOpSegment.cpp @@ -160,10 +160,6 @@ next: bool SkOpSegment::activeOp(int index, int endIndex, int xorMiMask, int xorSuMask, SkPathOp op) { int sumMiWinding = updateWinding(endIndex, index); int sumSuWinding = updateOppWinding(endIndex, index); -#if DEBUG_LIMIT_WIND_SUM - SkASSERT(abs(sumMiWinding) <= DEBUG_LIMIT_WIND_SUM); - SkASSERT(abs(sumSuWinding) <= DEBUG_LIMIT_WIND_SUM); -#endif if (fOperand) { SkTSwap<int>(sumMiWinding, sumSuWinding); } @@ -621,11 +617,6 @@ int SkOpSegment::addT(SkOpSegment* other, const SkPoint& pt, double newT) { if ((span->fDone = newT == 1)) { ++fDoneSpans; } - setSpanFlags(pt, newT, span); - return insertedAt; -} - -void SkOpSegment::setSpanFlags(const SkPoint& pt, double newT, SkOpSpan* span) { int less = -1; // FIXME: note that this relies on spans being a continguous array // find range of spans with nearly the same point as this one @@ -661,10 +652,10 @@ void SkOpSegment::setSpanFlags(const SkPoint& pt, double newT, SkOpSpan* span) { --more; } if (less == more) { - return; + return insertedAt; } if (precisely_negative(span[more].fT - span[less].fT)) { - return; + return insertedAt; } // if the total range of t values is big enough, mark all tiny bool tiny = span[less].fPt == span[more].fPt; @@ -677,80 +668,7 @@ void SkOpSegment::setSpanFlags(const SkPoint& pt, double newT, SkOpSpan* span) { ++fDoneSpans; } } while (++index < more); - return; -} - -void SkOpSegment::resetSpanFlags() { - fSmall = fTiny = false; - fDoneSpans = 0; - int start = 0; - int last = this->count() - 1; - do { - SkOpSpan* startSpan = &this->fTs[start]; - double startT = startSpan->fT; - startSpan->fSmall = startSpan->fTiny = false; // sets range initial - bool terminus = startT == 1; - if ((startSpan->fDone = !startSpan->fWindValue | terminus)) { - ++fDoneSpans; - } - ++start; // range initial + 1 - if (terminus) { - continue; - } - const SkPoint& pt = startSpan->fPt; - int end = start; // range initial + 1 - while (end <= last) { - const SkOpSpan& endSpan = this->span(end); - if (!AlmostEqualUlps(endSpan.fPt, pt)) { - break; - } - if (fVerb == SkPath::kCubic_Verb) { - double tMid = (startSpan->fT + endSpan.fT) / 2; - SkDPoint midEndPt = dcubic_xy_at_t(fPts, tMid); - if (!midEndPt.approximatelyEqual(xyAtT(startSpan))) { - break; - } - } - ++end; - } - if (start == end) { // end == range final + 1 - continue; - } - while (--end >= start) { // end == range final - const SkOpSpan& endSpan = this->span(end); - const SkOpSpan& priorSpan = this->span(end - 1); - if (endSpan.fPt != priorSpan.fPt || endSpan.fT != priorSpan.fT) { - break; // end == range final + 1 - } - } - if (end < start) { // end == range final + 1 - continue; - } - int index = start - 1; // index == range initial - start = end; // start = range final + 1 - const SkOpSpan& nextSpan = this->span(end); - if (precisely_negative(nextSpan.fT - startSpan->fT)) { - while (++index < end) { - startSpan = &this->fTs[index]; - startSpan->fSmall = startSpan->fTiny = false; // sets range initial + 1 - if ((startSpan->fDone = !startSpan->fWindValue)) { - ++fDoneSpans; - } - } - continue; - } - if (!startSpan->fWindValue) { - --fDoneSpans; // added back below - } - bool tiny = nextSpan.fPt == startSpan->fPt; - do { - fSmall = startSpan->fSmall = true; // sets range initial - fTiny |= startSpan->fTiny = tiny; - startSpan->fDone = true; - ++fDoneSpans; - startSpan = &this->fTs[++index]; - } while (index < end); // loop through tiny small range end (last) - } while (start <= last); + return insertedAt; } // set spans from start to end to decrement by one @@ -1052,151 +970,6 @@ void SkOpSegment::alignMultiples(SkTDArray<AlignedSpan>* alignedArray) { debugValidate(); } -void SkOpSegment::alignRange(int lower, int upper, - const SkOpSegment* other, int oLower, int oUpper) { - for (int oIndex = oLower; oIndex <= oUpper; ++oIndex) { - const SkOpSpan& oSpan = other->span(oIndex); - const SkOpSegment* oOther = oSpan.fOther; - if (oOther == this) { - continue; - } - SkOpSpan* matchSpan; - int matchIndex; - const SkOpSpan* refSpan; - for (int iIndex = lower; iIndex <= upper; ++iIndex) { - const SkOpSpan& iSpan = this->span(iIndex); - const SkOpSegment* iOther = iSpan.fOther; - if (iOther == other) { - continue; - } - if (iOther == oOther) { - goto nextI; - } - } - { - // oSpan does not have a match in this - int iCount = this->count(); - const SkOpSpan* iMatch = NULL; - double iMatchTDiff; - matchIndex = -1; - for (int iIndex = 0; iIndex < iCount; ++iIndex) { - const SkOpSpan& iSpan = this->span(iIndex); - const SkOpSegment* iOther = iSpan.fOther; - if (iOther != oOther) { - continue; - } - double testTDiff = fabs(iSpan.fOtherT - oSpan.fOtherT); - if (!iMatch || testTDiff < iMatchTDiff) { - matchIndex = iIndex; - iMatch = &iSpan; - iMatchTDiff = testTDiff; - } - } - if (matchIndex < 0) { - continue; // the entry is missing, & will be picked up later (FIXME: fix it here?) - } - matchSpan = &this->fTs[matchIndex]; - refSpan = &this->span(lower); - if (!SkDPoint::ApproximatelyEqual(matchSpan->fPt, refSpan->fPt)) { - goto nextI; - } - if (matchIndex != lower - 1 && matchIndex != upper + 1) { - // the consecutive spans need to be rearranged to get the missing one close - continue; // FIXME: more work to do - } - } - { - this->fixOtherTIndex(); - SkScalar newT; - if (matchSpan->fT != 0 && matchSpan->fT != 1) { - newT = matchSpan->fT = refSpan->fT; - matchSpan->fOther->fTs[matchSpan->fOtherIndex].fOtherT = refSpan->fT; - } else { // leave span at the start or end there and adjust the neighbors - newT = matchSpan->fT; - for (int iIndex = lower; iIndex <= upper; ++iIndex) { - matchSpan = &this->fTs[iIndex]; - matchSpan->fT = newT; - matchSpan->fOther->fTs[matchSpan->fOtherIndex].fOtherT = newT; - } - } - this->resetSpanFlags(); // fix up small / tiny / done - // align ts of other ranges with adjacent spans that match the aligned points - lower = SkTMin(lower, matchIndex); - while (lower > 0) { - const SkOpSpan& span = this->span(lower - 1); - if (span.fT != newT) { - break; - } - --lower; - } - upper = SkTMax(upper, matchIndex); - int last = this->count() - 1; - while (upper < last) { - const SkOpSpan& span = this->span(upper + 1); - if (span.fT != newT) { - break; - } - ++upper; - } - for (int iIndex = lower; iIndex <= upper; ++iIndex) { - const SkOpSpan& span = this->span(iIndex); - SkOpSegment* aOther = span.fOther; - int aLower = span.fOtherIndex; - SkScalar aT = span.fOtherT; - bool aResetFlags = false; - while (aLower > 0) { - SkOpSpan* aSpan = &aOther->fTs[aLower - 1]; - for (int iIndex = lower; iIndex <= upper; ++iIndex) { - if (aSpan->fPt == this->fTs[iIndex].fPt) { - goto matchFound; - } - } - break; - matchFound: - --aLower; - } - int aUpper = span.fOtherIndex; - int aLast = aOther->count() - 1; - while (aUpper < aLast) { - SkOpSpan* aSpan = &aOther->fTs[aUpper + 1]; - for (int iIndex = lower; iIndex <= upper; ++iIndex) { - if (aSpan->fPt == this->fTs[iIndex].fPt) { - goto matchFound2; - } - } - break; - matchFound2: - ++aUpper; - } - if (aOther->fTs[aLower].fT == 0) { - aT = 0; - } else if (aOther->fTs[aUpper].fT == 1) { - aT = 1; - } - bool aFixed = false; - for (int aIndex = aLower; aIndex <= aUpper; ++aIndex) { - SkOpSpan* aSpan = &aOther->fTs[aIndex]; - if (aSpan->fT == aT) { - continue; - } - SkASSERT(way_roughly_equal(aSpan->fT, aT)); - if (!aFixed) { - aOther->fixOtherTIndex(); - aFixed = true; - } - aSpan->fT = aT; - aSpan->fOther->fTs[aSpan->fOtherIndex].fOtherT = aT; - aResetFlags = true; - } - if (aResetFlags) { - aOther->resetSpanFlags(); - } - } - } -nextI: ; - } -} - void SkOpSegment::alignSpan(const SkPoint& newPt, double newT, const SkOpSegment* other, double otherT, const SkOpSegment* other2, SkOpSpan* oSpan, SkTDArray<AlignedSpan>* alignedArray) { @@ -1472,8 +1245,8 @@ void SkOpSegment::bumpCoincidentOBlind(int index, int endIndex) { // may not have the same intermediate points. Compute the corresponding // intermediate T values (using this as the master, other as the follower) // and walk other conditionally -- hoping that it catches up in the end -bool SkOpSegment::bumpCoincidentOther(const SkOpSpan& test, int* oIndexPtr, - SkTArray<SkPoint, true>* oOutsidePts, const SkPoint& oEndPt) { +void SkOpSegment::bumpCoincidentOther(const SkOpSpan& test, int* oIndexPtr, + SkTArray<SkPoint, true>* oOutsidePts) { int oIndex = *oIndexPtr; SkOpSpan* const oTest = &fTs[oIndex]; SkOpSpan* oEnd = oTest; @@ -1486,14 +1259,11 @@ bool SkOpSegment::bumpCoincidentOther(const SkOpSpan& test, int* oIndexPtr, TrackOutside(oOutsidePts, startPt); } #endif - bool foundEnd = false; while (oStartPt == oEnd->fPt || precisely_equal(oStartT, oEnd->fT)) { - foundEnd |= oEndPt == oEnd->fPt; zeroSpan(oEnd); oEnd = &fTs[++oIndex]; } *oIndexPtr = oIndex; - return foundEnd; } // FIXME: need to test this case: @@ -1543,7 +1313,6 @@ bool SkOpSegment::addTCoincident(const SkPoint& startPt, const SkPoint& endPt, d } // consolidate the winding count even if done - bool foundEnd = false; if ((test->fWindValue == 0 && test->fOppValue == 0) || (oTest->fWindValue == 0 && oTest->fOppValue == 0)) { SkDEBUGCODE(int firstWind = test->fWindValue); @@ -1567,12 +1336,12 @@ bool SkOpSegment::addTCoincident(const SkPoint& startPt, const SkPoint& endPt, d if (!bumpCoincidentThis(*oTest, binary, &index, &outsidePts)) { return false; } - foundEnd = other->bumpCoincidentOther(*test, &oIndex, &oOutsidePts, endPt); + other->bumpCoincidentOther(*test, &oIndex, &oOutsidePts); } else { if (!other->bumpCoincidentThis(*test, binary, &oIndex, &oOutsidePts)) { return false; } - foundEnd = bumpCoincidentOther(*oTest, &index, &outsidePts, endPt); + bumpCoincidentOther(*oTest, &index, &outsidePts); } } test = &fTs[index]; @@ -1583,9 +1352,6 @@ bool SkOpSegment::addTCoincident(const SkPoint& startPt, const SkPoint& endPt, d if (endPt == *testPt || precisely_equal(endT, testT)) { break; } - if (0 && foundEnd) { // FIXME: this is likely needed but wait until a test case triggers it - break; - } // SkASSERT(AlmostEqualUlps(*testPt, *oTestPt)); } while (endPt != *oTestPt); // in rare cases, one may have ended before the other @@ -1598,7 +1364,6 @@ bool SkOpSegment::addTCoincident(const SkPoint& startPt, const SkPoint& endPt, d test->fWindValue = lastWind; test->fOppValue = lastOpp; if (zero) { - SkASSERT(!test->fDone); test->fDone = true; ++fDoneSpans; } @@ -1637,9 +1402,7 @@ bool SkOpSegment::addTCoincident(const SkPoint& startPt, const SkPoint& endPt, d if (success) { do { if (!binary || test->fWindValue + oTest->fOppValue >= 0) { - if (other->bumpCoincidentOther(*test, &oIndex, &oOutsidePts, endPt)) { - break; - } + other->bumpCoincidentOther(*test, &oIndex, &oOutsidePts); } else { if (!other->bumpCoincidentThis(*test, binary, &oIndex, &oOutsidePts)) { return false; @@ -1713,9 +1476,9 @@ const SkOpSpan* SkOpSegment::addTPair(double t, SkOpSegment* other, double other SkASSERT(other != this); int insertedAt = addT(other, pt, t); int otherInsertedAt = other->addT(this, pt2, otherT); - this->addOtherT(insertedAt, otherT, otherInsertedAt); + addOtherT(insertedAt, otherT, otherInsertedAt); other->addOtherT(otherInsertedAt, t, insertedAt); - this->matchWindingValue(insertedAt, t, borrowWind); + matchWindingValue(insertedAt, t, borrowWind); other->matchWindingValue(otherInsertedAt, otherT, borrowWind); SkOpSpan& span = this->fTs[insertedAt]; if (pt != pt2) { @@ -1723,27 +1486,6 @@ const SkOpSpan* SkOpSegment::addTPair(double t, SkOpSegment* other, double other SkOpSpan& oSpan = other->fTs[otherInsertedAt]; oSpan.fNear = true; } - // if the newly inserted spans match a neighbor on one but not the other, make them agree - int lower = this->nextExactSpan(insertedAt, -1) + 1; - int upper = this->nextExactSpan(insertedAt, 1) - 1; - if (upper < 0) { - upper = this->count() - 1; - } - int oLower = other->nextExactSpan(otherInsertedAt, -1) + 1; - int oUpper = other->nextExactSpan(otherInsertedAt, 1) - 1; - if (oUpper < 0) { - oUpper = other->count() - 1; - } - if (lower == upper && oLower == oUpper) { - return &span; - } -#if DEBUG_CONCIDENT - SkDebugf("%s id=%d lower=%d upper=%d other=%d oLower=%d oUpper=%d\n", __FUNCTION__, - debugID(), lower, upper, other->debugID(), oLower, oUpper); -#endif - // find the nearby spans in one range missing in the other - this->alignRange(lower, upper, other, oLower, oUpper); - other->alignRange(oLower, oUpper, this, lower, upper); return &span; } @@ -2151,10 +1893,8 @@ bool SkOpSegment::bumpSpan(SkOpSpan* span, int windDelta, int oppDelta) { span->fOppValue &= 1; } if (!span->fWindValue && !span->fOppValue) { - if (!span->fDone) { - span->fDone = true; - ++fDoneSpans; - } + span->fDone = true; + ++fDoneSpans; return true; } return false; @@ -2378,7 +2118,7 @@ void SkOpSegment::checkDuplicates() { } // look to see if the curve end intersects an intermediary that intersects the other -bool SkOpSegment::checkEnds() { +void SkOpSegment::checkEnds() { debugValidate(); SkSTArray<kMissingSpanCount, MissingSpan, true> missingSpans; int count = fTs.count(); @@ -2453,14 +2193,11 @@ bool SkOpSegment::checkEnds() { if (lastMissing.fT == t && lastMissing.fOther == match && lastMissing.fOtherT == matchT) { - SkASSERT(SkDPoint::ApproximatelyEqual(lastMissing.fPt, peekSpan.fPt)); + SkASSERT(lastMissing.fPt == peekSpan.fPt); continue; } } - if (this == match) { - return false; // extremely large paths can trigger this - } -#if DEBUG_CHECK_ALIGN +#if DEBUG_CHECK_ENDS SkDebugf("%s id=%d missing t=%1.9g other=%d otherT=%1.9g pt=(%1.9g,%1.9g)\n", __FUNCTION__, fID, t, match->fID, matchT, peekSpan.fPt.fX, peekSpan.fPt.fY); #endif @@ -2482,7 +2219,7 @@ nextPeekIndex: } if (missingSpans.count() == 0) { debugValidate(); - return true; + return; } debugValidate(); int missingCount = missingSpans.count(); @@ -2499,7 +2236,6 @@ nextPeekIndex: missingSpans[index].fOther->fixOtherTIndex(); } debugValidate(); - return true; } void SkOpSegment::checkLinks(const SkOpSpan* base, @@ -2521,7 +2257,7 @@ void SkOpSegment::checkLinks(const SkOpSpan* base, } test = base; while (test < last && (++test)->fPt == base->fPt) { - SkASSERT(this != test->fOther || test->fLoop); + SkASSERT(this != test->fOther); CheckOneLink(test, oSpan, oFirst, oLast, &missing, missingSpans); } } @@ -3375,8 +3111,6 @@ int SkOpSegment::findExactT(double t, const SkOpSegment* match) const { return -1; } - - int SkOpSegment::findOtherT(double t, const SkOpSegment* match) const { int count = this->count(); for (int index = 0; index < count; ++index) { @@ -3463,19 +3197,14 @@ SkOpSegment* SkOpSegment::findTop(int* tIndexPtr, int* endIndexPtr, bool* unsort SkOpSegment* next = angle->segment(); SkPathOpsBounds bounds; next->subDivideBounds(angle->end(), angle->start(), &bounds); - bool nearSame = AlmostEqualUlps(top, bounds.top()); - bool lowerSector = !firstAngle || angle->sectorEnd() < firstAngle->sectorStart(); - bool lesserSector = top > bounds.fTop; - if (lesserSector && (!nearSame || lowerSector)) { + if (approximately_greater(top, bounds.fTop)) { top = bounds.fTop; firstAngle = angle; } } angle = angle->next(); } while (angle != baseAngle); - if (!firstAngle) { - return NULL; // if all are unorderable, give up - } + SkASSERT(firstAngle); #if DEBUG_SORT SkDebugf("%s\n", __FUNCTION__); firstAngle->debugLoop(); @@ -3572,72 +3301,6 @@ bool SkOpSegment::inCoincidentSpan(double t, const SkOpSegment* other) const { return foundEnds == 0x3 || foundEnds == 0x5 || foundEnds == 0x6; // two bits set } -bool SkOpSegment::inconsistentAngle(int maxWinding, int sumWinding, int oppMaxWinding, - int oppSumWinding, const SkOpAngle* angle) const { - SkASSERT(angle->segment() == this); - if (UseInnerWinding(maxWinding, sumWinding)) { - maxWinding = sumWinding; - } - if (oppMaxWinding != oppSumWinding && UseInnerWinding(oppMaxWinding, oppSumWinding)) { - oppMaxWinding = oppSumWinding; - } - return inconsistentWinding(angle, maxWinding, oppMaxWinding); -} - -bool SkOpSegment::inconsistentWinding(const SkOpAngle* angle, int winding, - int oppWinding) const { - int index = angle->start(); - int endIndex = angle->end(); - int min = SkMin32(index, endIndex); - int step = SkSign32(endIndex - index); - if (inconsistentWinding(min, winding, oppWinding)) { - return true; - } - const SkOpSegment* other = this; - while ((other = other->nextChase(&index, &step, &min, NULL))) { - if (other->fTs[min].fWindSum != SK_MinS32) { - break; - } - if (fOperand == other->fOperand) { - if (other->inconsistentWinding(min, winding, oppWinding)) { - return true; - } - } else { - if (other->inconsistentWinding(min, oppWinding, winding)) { - return true; - } - } - } - return false; -} - -bool SkOpSegment::inconsistentWinding(int index, int winding, int oppWinding) const { - SkASSERT(winding || oppWinding); - double referenceT = this->span(index).fT; - int lesser = index; - while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) { - if (inconsistentWinding(__FUNCTION__, lesser, winding, oppWinding)) { - return true; - } - } - do { - if (inconsistentWinding(__FUNCTION__, index, winding, oppWinding)) { - return true; - } - } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenceT)); - return false; -} - -bool SkOpSegment::inconsistentWinding(const char* funName, int tIndex, int winding, - int oppWinding) const { - const SkOpSpan& span = this->span(tIndex); - if (span.fDone && !span.fSmall) { - return false; - } - return (span.fWindSum != SK_MinS32 && span.fWindSum != winding) - || (span.fOppSum != SK_MinS32 && span.fOppSum != oppWinding); -} - void SkOpSegment::init(const SkPoint pts[], SkPath::Verb verb, bool operand, bool evenOdd) { fDoneSpans = 0; fOperand = operand; @@ -3649,18 +3312,16 @@ void SkOpSegment::init(const SkPoint pts[], SkPath::Verb verb, bool operand, boo void SkOpSegment::initWinding(int start, int end, SkOpAngle::IncludeType angleIncludeType) { int local = spanSign(start, end); - SkDEBUGCODE(bool success); if (angleIncludeType == SkOpAngle::kBinarySingle) { int oppLocal = oppSign(start, end); - SkDEBUGCODE(success =) markAndChaseWinding(start, end, local, oppLocal, NULL); + (void) markAndChaseWinding(start, end, local, oppLocal); // OPTIMIZATION: the reverse mark and chase could skip the first marking - SkDEBUGCODE(success |=) markAndChaseWinding(end, start, local, oppLocal, NULL); + (void) markAndChaseWinding(end, start, local, oppLocal); } else { - SkDEBUGCODE(success =) markAndChaseWinding(start, end, local, NULL); + (void) markAndChaseWinding(start, end, local); // OPTIMIZATION: the reverse mark and chase could skip the first marking - SkDEBUGCODE(success |=) markAndChaseWinding(end, start, local, NULL); + (void) markAndChaseWinding(end, start, local); } - SkASSERT(success); } /* @@ -3672,7 +3333,7 @@ If there was a winding, then it may or may not need adjusting. If the span the w from has the same x direction as this span, the winding should change. If the dx is opposite, then the same winding is shared by both. */ -bool SkOpSegment::initWinding(int start, int end, double tHit, int winding, SkScalar hitDx, +void SkOpSegment::initWinding(int start, int end, double tHit, int winding, SkScalar hitDx, int oppWind, SkScalar hitOppDx) { SkASSERT(hitDx || !winding); SkScalar dx = (*CurveSlopeAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, tHit).fX; @@ -3700,11 +3361,9 @@ bool SkOpSegment::initWinding(int start, int end, double tHit, int winding, SkSc #if DEBUG_WINDING_AT_T SkDebugf(" winding=%d oppWind=%d\n", winding, oppWind); #endif - // if this fails to mark (because the edges are too small) inform caller to try again - bool success = markAndChaseWinding(start, end, winding, oppWind, NULL); + (void) markAndChaseWinding(start, end, winding, oppWind); // OPTIMIZATION: the reverse mark and chase could skip the first marking - success |= markAndChaseWinding(end, start, winding, oppWind, NULL); - return success; + (void) markAndChaseWinding(end, start, winding, oppWind); } bool SkOpSegment::inLoop(const SkOpAngle* baseAngle, int spanCount, int* indexPtr) const { @@ -3768,9 +3427,7 @@ bool SkOpSegment::joinCoincidence(SkOpSegment* other, double otherT, const SkPoi if (otherWind == 0) { return false; } - if (next < 0) { - return false; // can happen if t values were adjusted but coincident ts were not - } + SkASSERT(next >= 0); int tIndex = 0; do { SkOpSpan* test = &fTs[tIndex]; @@ -3785,9 +3442,7 @@ bool SkOpSegment::joinCoincidence(SkOpSegment* other, double otherT, const SkPoi if (cancel) { match->addTCancel(startPt, endPt, other); } else { - if (!match->addTCoincident(startPt, endPt, endT, other)) { - return false; - } + SkAssertResult(match->addTCoincident(startPt, endPt, endT, other)); } return true; } @@ -3831,16 +3486,29 @@ SkOpSpan* SkOpSegment::markAndChaseDoneUnary(int index, int endIndex) { return last; } -bool SkOpSegment::markAndChaseWinding(const SkOpAngle* angle, int winding, SkOpSpan** lastPtr) { +SkOpSpan* SkOpSegment::markAndChaseWinding(const SkOpAngle* angle, int winding) { int index = angle->start(); int endIndex = angle->end(); - return markAndChaseWinding(index, endIndex, winding, lastPtr); + int step = SkSign32(endIndex - index); + int min = SkMin32(index, endIndex); + markWinding(min, winding); + SkOpSpan* last = NULL; + SkOpSegment* other = this; + while ((other = other->nextChase(&index, &step, &min, &last))) { + if (other->fTs[min].fWindSum != SK_MinS32) { +// SkASSERT(other->fTs[min].fWindSum == winding); + SkASSERT(!last); + break; + } + other->markWinding(min, winding); + } + return last; } -bool SkOpSegment::markAndChaseWinding(int index, int endIndex, int winding, SkOpSpan** lastPtr) { +SkOpSpan* SkOpSegment::markAndChaseWinding(int index, int endIndex, int winding) { int min = SkMin32(index, endIndex); int step = SkSign32(endIndex - index); - bool success = markWinding(min, winding); + markWinding(min, winding); SkOpSpan* last = NULL; SkOpSegment* other = this; while ((other = other->nextChase(&index, &step, &min, &last))) { @@ -3849,19 +3517,15 @@ bool SkOpSegment::markAndChaseWinding(int index, int endIndex, int winding, SkOp SkASSERT(!last); break; } - (void) other->markWinding(min, winding); - } - if (lastPtr) { - *lastPtr = last; + other->markWinding(min, winding); } - return success; + return last; } -bool SkOpSegment::markAndChaseWinding(int index, int endIndex, int winding, int oppWinding, - SkOpSpan** lastPtr) { +SkOpSpan* SkOpSegment::markAndChaseWinding(int index, int endIndex, int winding, int oppWinding) { int min = SkMin32(index, endIndex); int step = SkSign32(endIndex - index); - bool success = markWinding(min, winding, oppWinding); + markWinding(min, winding, oppWinding); SkOpSpan* last = NULL; SkOpSegment* other = this; while ((other = other->nextChase(&index, &step, &min, &last))) { @@ -3885,22 +3549,18 @@ bool SkOpSegment::markAndChaseWinding(int index, int endIndex, int winding, int break; } if (fOperand == other->fOperand) { - (void) other->markWinding(min, winding, oppWinding); + other->markWinding(min, winding, oppWinding); } else { - (void) other->markWinding(min, oppWinding, winding); + other->markWinding(min, oppWinding, winding); } } - if (lastPtr) { - *lastPtr = last; - } - return success; + return last; } -bool SkOpSegment::markAndChaseWinding(const SkOpAngle* angle, int winding, int oppWinding, - SkOpSpan** lastPtr) { +SkOpSpan* SkOpSegment::markAndChaseWinding(const SkOpAngle* angle, int winding, int oppWinding) { int start = angle->start(); int end = angle->end(); - return markAndChaseWinding(start, end, winding, oppWinding, lastPtr); + return markAndChaseWinding(start, end, winding, oppWinding); } SkOpSpan* SkOpSegment::markAngle(int maxWinding, int sumWinding, const SkOpAngle* angle) { @@ -3908,8 +3568,7 @@ SkOpSpan* SkOpSegment::markAngle(int maxWinding, int sumWinding, const SkOpAngle if (UseInnerWinding(maxWinding, sumWinding)) { maxWinding = sumWinding; } - SkOpSpan* last; - SkAssertResult(markAndChaseWinding(angle, maxWinding, &last)); + SkOpSpan* last = markAndChaseWinding(angle, maxWinding); #if DEBUG_WINDING if (last) { SkDebugf("%s last id=%d windSum=", __FUNCTION__, @@ -3930,9 +3589,7 @@ SkOpSpan* SkOpSegment::markAngle(int maxWinding, int sumWinding, int oppMaxWindi if (oppMaxWinding != oppSumWinding && UseInnerWinding(oppMaxWinding, oppSumWinding)) { oppMaxWinding = oppSumWinding; } - SkOpSpan* last; - // caller doesn't require that this marks anything - (void) markAndChaseWinding(angle, maxWinding, oppMaxWinding, &last); + SkOpSpan* last = markAndChaseWinding(angle, maxWinding, oppMaxWinding); #if DEBUG_WINDING if (last) { SkDebugf("%s last id=%d windSum=", __FUNCTION__, @@ -3975,18 +3632,6 @@ void SkOpSegment::markDoneBinary(int index) { debugValidate(); } -void SkOpSegment::markDoneFinal(int index) { - double referenceT = fTs[index].fT; - int lesser = index; - while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) { - markOneDoneFinal(__FUNCTION__, lesser); - } - do { - markOneDoneFinal(__FUNCTION__, index); - } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenceT)); - debugValidate(); -} - void SkOpSegment::markDoneUnary(int index) { double referenceT = fTs[index].fT; int lesser = index; @@ -4000,22 +3645,12 @@ void SkOpSegment::markDoneUnary(int index) { } void SkOpSegment::markOneDone(const char* funName, int tIndex, int winding) { - SkOpSpan* span; - (void) markOneWinding(funName, tIndex, winding, &span); // allowed to do nothing - if (span->fDone) { + SkOpSpan* span = markOneWinding(funName, tIndex, winding); + if (!span || span->fDone) { return; } span->fDone = true; - ++fDoneSpans; -} - -void SkOpSegment::markOneDoneFinal(const char* funName, int tIndex) { - SkOpSpan* span = &fTs[tIndex]; - if (span->fDone) { - return; - } - span->fDone = true; - ++fDoneSpans; + fDoneSpans++; } void SkOpSegment::markOneDoneBinary(const char* funName, int tIndex) { @@ -4025,7 +3660,7 @@ void SkOpSegment::markOneDoneBinary(const char* funName, int tIndex) { } SkASSERT(!span->fDone); span->fDone = true; - ++fDoneSpans; + fDoneSpans++; } void SkOpSegment::markOneDoneUnary(const char* funName, int tIndex) { @@ -4038,52 +3673,46 @@ void SkOpSegment::markOneDoneUnary(const char* funName, int tIndex) { } SkASSERT(!span->fDone); span->fDone = true; - ++fDoneSpans; + fDoneSpans++; } -bool SkOpSegment::markOneWinding(const char* funName, int tIndex, int winding, SkOpSpan** lastPtr) { - SkOpSpan* span = &fTs[tIndex]; - if (lastPtr) { - *lastPtr = span; - } - if (span->fDone && !span->fSmall) { - return false; +SkOpSpan* SkOpSegment::markOneWinding(const char* funName, int tIndex, int winding) { + SkOpSpan& span = fTs[tIndex]; + if (span.fDone && !span.fSmall) { + return NULL; } #if DEBUG_MARK_DONE - debugShowNewWinding(funName, *span, winding); + debugShowNewWinding(funName, span, winding); #endif - SkASSERT(span->fWindSum == SK_MinS32 || span->fWindSum == winding); + SkASSERT(span.fWindSum == SK_MinS32 || span.fWindSum == winding); #if DEBUG_LIMIT_WIND_SUM SkASSERT(abs(winding) <= DEBUG_LIMIT_WIND_SUM); #endif - span->fWindSum = winding; - return true; + span.fWindSum = winding; + return &span; } -bool SkOpSegment::markOneWinding(const char* funName, int tIndex, int winding, - int oppWinding, SkOpSpan** lastPtr) { - SkOpSpan* span = &fTs[tIndex]; - if (span->fDone && !span->fSmall) { - return false; +SkOpSpan* SkOpSegment::markOneWinding(const char* funName, int tIndex, int winding, + int oppWinding) { + SkOpSpan& span = fTs[tIndex]; + if (span.fDone && !span.fSmall) { + return NULL; } #if DEBUG_MARK_DONE - debugShowNewWinding(funName, *span, winding, oppWinding); + debugShowNewWinding(funName, span, winding, oppWinding); #endif - SkASSERT(span->fWindSum == SK_MinS32 || span->fWindSum == winding); + SkASSERT(span.fWindSum == SK_MinS32 || span.fWindSum == winding); #if DEBUG_LIMIT_WIND_SUM SkASSERT(abs(winding) <= DEBUG_LIMIT_WIND_SUM); #endif - span->fWindSum = winding; - SkASSERT(span->fOppSum == SK_MinS32 || span->fOppSum == oppWinding); + span.fWindSum = winding; + SkASSERT(span.fOppSum == SK_MinS32 || span.fOppSum == oppWinding); #if DEBUG_LIMIT_WIND_SUM SkASSERT(abs(oppWinding) <= DEBUG_LIMIT_WIND_SUM); #endif - span->fOppSum = oppWinding; + span.fOppSum = oppWinding; debugValidate(); - if (lastPtr) { - *lastPtr = span; - } - return true; + return &span; } // from http://stackoverflow.com/questions/1165647/how-to-determine-if-a-list-of-polygon-points-are-in-clockwise-order @@ -4207,36 +3836,32 @@ SkOpSpan* SkOpSegment::verifyOneWindingU(const char* funName, int tIndex) { return &span; } -bool SkOpSegment::markWinding(int index, int winding) { +void SkOpSegment::markWinding(int index, int winding) { // SkASSERT(!done()); SkASSERT(winding); double referenceT = fTs[index].fT; int lesser = index; - bool success = false; while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) { - success |= markOneWinding(__FUNCTION__, lesser, winding, NULL); + markOneWinding(__FUNCTION__, lesser, winding); } do { - success |= markOneWinding(__FUNCTION__, index, winding, NULL); + markOneWinding(__FUNCTION__, index, winding); } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenceT)); debugValidate(); - return success; } -bool SkOpSegment::markWinding(int index, int winding, int oppWinding) { +void SkOpSegment::markWinding(int index, int winding, int oppWinding) { // SkASSERT(!done()); SkASSERT(winding || oppWinding); double referenceT = fTs[index].fT; int lesser = index; - bool success = false; while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) { - success |= markOneWinding(__FUNCTION__, lesser, winding, oppWinding, NULL); + markOneWinding(__FUNCTION__, lesser, winding, oppWinding); } do { - success |= markOneWinding(__FUNCTION__, index, winding, oppWinding, NULL); + markOneWinding(__FUNCTION__, index, winding, oppWinding); } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenceT)); debugValidate(); - return success; } void SkOpSegment::matchWindingValue(int tIndex, double t, bool borrowWind) { @@ -4299,20 +3924,19 @@ bool SkOpSegment::nextCandidate(int* start, int* end) const { return true; } -static SkOpSegment* set_last(SkOpSpan** last, const SkOpSpan* endSpan) { +static SkOpSegment* set_last(SkOpSpan** last, SkOpSpan* endSpan) { if (last && !endSpan->fSmall) { - *last = const_cast<SkOpSpan*>(endSpan); // FIXME: get rid of cast + *last = endSpan; } return NULL; } -SkOpSegment* SkOpSegment::nextChase(int* indexPtr, int* stepPtr, int* minPtr, - SkOpSpan** last) const { +SkOpSegment* SkOpSegment::nextChase(int* indexPtr, int* stepPtr, int* minPtr, SkOpSpan** last) { int origIndex = *indexPtr; int step = *stepPtr; int end = nextExactSpan(origIndex, step); SkASSERT(end >= 0); - const SkOpSpan& endSpan = this->span(end); + SkOpSpan& endSpan = fTs[end]; SkOpAngle* angle = step > 0 ? endSpan.fFromAngle : endSpan.fToAngle; int foundIndex; int otherEnd; diff --git a/src/pathops/SkOpSegment.h b/src/pathops/SkOpSegment.h index b4da929d99..4c35ac7e7e 100644 --- a/src/pathops/SkOpSegment.h +++ b/src/pathops/SkOpSegment.h @@ -302,7 +302,7 @@ public: double calcMissingTStart(const SkOpSegment* ref, double loEnd, double min, double max, double hiEnd, const SkOpSegment* other, int thisEnd); void checkDuplicates(); - bool checkEnds(); + void checkEnds(); void checkMultiples(); void checkSmall(); bool checkSmall(int index) const; @@ -323,10 +323,8 @@ public: int findT(double t, const SkPoint& , const SkOpSegment* ) const; SkOpSegment* findTop(int* tIndex, int* endIndex, bool* unsortable, bool firstPass); void fixOtherTIndex(); - bool inconsistentAngle(int maxWinding, int sumWinding, int oppMaxWinding, int oppSumWinding, - const SkOpAngle* angle) const; void initWinding(int start, int end, SkOpAngle::IncludeType angleIncludeType); - bool initWinding(int start, int end, double tHit, int winding, SkScalar hitDx, int oppWind, + 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 isTiny(const SkOpAngle* angle) const; @@ -334,13 +332,11 @@ public: bool cancel); SkOpSpan* markAndChaseDoneBinary(int index, int endIndex); SkOpSpan* markAndChaseDoneUnary(int index, int endIndex); - bool markAndChaseWinding(const SkOpAngle* angle, int winding, int oppWinding, - SkOpSpan** lastPtr); + SkOpSpan* markAndChaseWinding(const SkOpAngle* angle, int winding, int oppWinding); SkOpSpan* markAngle(int maxWinding, int sumWinding, int oppMaxWinding, int oppSumWinding, const SkOpAngle* angle); void markDone(int index, int winding); void markDoneBinary(int index); - void markDoneFinal(int index); void markDoneUnary(int index); bool nextCandidate(int* start, int* end) const; int nextSpan(int from, int step) const; @@ -407,16 +403,15 @@ private: SkOpAngle* addSingletonAngleDown(SkOpSegment** otherPtr, SkOpAngle** ); SkOpAngle* addSingletonAngleUp(SkOpSegment** otherPtr, SkOpAngle** ); SkOpAngle* addSingletonAngles(int step); - void alignRange(int lower, int upper, const SkOpSegment* other, int oLower, int oUpper); void alignSpan(const SkPoint& newPt, double newT, const SkOpSegment* other, double otherT, const SkOpSegment* other2, SkOpSpan* oSpan, SkTDArray<AlignedSpan>* ); bool betweenPoints(double midT, const SkPoint& pt1, const SkPoint& pt2) const; void bumpCoincidentBlind(bool binary, int index, int last); bool bumpCoincidentThis(const SkOpSpan& oTest, bool binary, int* index, - SkTArray<SkPoint, true>* outsideTs); + SkTArray<SkPoint, true>* outsideTs); void bumpCoincidentOBlind(int index, int last); - bool bumpCoincidentOther(const SkOpSpan& oTest, int* index, - SkTArray<SkPoint, true>* outsideTs, const SkPoint& endPt); + 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); bool checkForSmall(const SkOpSpan* span, const SkPoint& pt, double newT, @@ -443,9 +438,6 @@ private: const SkOpSpan& firstSpan(const SkOpSpan& thisSpan) const; void init(const SkPoint pts[], SkPath::Verb verb, bool operand, bool evenOdd); bool inCoincidentSpan(double t, const SkOpSegment* other) const; - bool inconsistentWinding(const SkOpAngle* , int maxWinding, int oppMaxWinding) const; - bool inconsistentWinding(int min, int maxWinding, int oppMaxWinding) const; - bool inconsistentWinding(const char* funName, int tIndex, int winding, int oppWinding) const; bool inLoop(const SkOpAngle* baseAngle, int spanCount, int* indexPtr) const; #if OLD_CHASE bool isSimple(int end) const; @@ -457,35 +449,30 @@ private: 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); - bool markAndChaseWinding(const SkOpAngle* angle, int winding, SkOpSpan** lastPtr); - bool markAndChaseWinding(int index, int endIndex, int winding, SkOpSpan** lastPtr); - bool markAndChaseWinding(int index, int endIndex, int winding, int oppWinding, - SkOpSpan** lastPtr); + 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); SkOpSpan* markAndChaseDoneUnary(const SkOpAngle* angle, int winding); void markOneDone(const char* funName, int tIndex, int winding); void markOneDoneBinary(const char* funName, int tIndex); void markOneDoneBinary(const char* funName, int tIndex, int winding, int oppWinding); - void markOneDoneFinal(const char* funName, int tIndex); void markOneDoneUnary(const char* funName, int tIndex); - bool markOneWinding(const char* funName, int tIndex, int winding, SkOpSpan** lastPtr); - bool markOneWinding(const char* funName, int tIndex, int winding, int oppWinding, - SkOpSpan** lastPtr); - bool markWinding(int index, int winding); - bool markWinding(int index, int winding, int oppWinding); + SkOpSpan* markOneWinding(const char* funName, int tIndex, int winding); + SkOpSpan* markOneWinding(const char* funName, int tIndex, int winding, int oppWinding); + void markWinding(int index, int winding); + void markWinding(int index, int winding, int oppWinding); bool monotonicInY(int tStart, int tEnd) const; bool multipleEnds() const { return fTs[count() - 2].fT == 1; } bool multipleStarts() const { return fTs[1].fT == 0; } - SkOpSegment* nextChase(int* index, int* step, int* min, SkOpSpan** last) const; + SkOpSegment* nextChase(int* index, int* step, int* min, SkOpSpan** last); int nextExactSpan(int from, int step) const; - void resetSpanFlags(); bool serpentine(int tStart, int tEnd) const; void setCoincidentRange(const SkPoint& startPt, const SkPoint& endPt, SkOpSegment* other); void setFromAngle(int endIndex, SkOpAngle* ); - void setSpanFlags(const SkPoint& pt, double newT, SkOpSpan* span); void setToAngle(int endIndex, SkOpAngle* ); void setUpWindings(int index, int endIndex, int* sumMiWinding, int* maxWinding, int* sumWinding); @@ -540,7 +527,6 @@ private: void debugConstructQuad(SkPoint shortQuad[3]); void debugReset(); void dumpDPts() const; - void dumpHexPts() const; void dumpSpan(int index) const; const SkPoint* fPts; diff --git a/src/pathops/SkPathOpsCommon.cpp b/src/pathops/SkPathOpsCommon.cpp index 1a5bfc1889..f7b7273a8d 100644 --- a/src/pathops/SkPathOpsCommon.cpp +++ b/src/pathops/SkPathOpsCommon.cpp @@ -161,7 +161,7 @@ SkOpSegment* FindChase(SkTDArray<SkOpSpan*>* chase, int* tIndex, int* endIndex) if (!sortable) { continue; } - // find first angle, initialize winding to computed wind sum + // find first angle, initialize winding to computed fWindSum const SkOpAngle* angle = segment->spanToAngle(*tIndex, *endIndex); const SkOpAngle* firstAngle; SkDEBUGCODE(firstAngle = angle); @@ -208,8 +208,7 @@ SkOpSegment* FindChase(SkTDArray<SkOpSpan*>* chase, int* tIndex, int* endIndex) if (SkOpSegment::UseInnerWinding(maxWinding, winding)) { maxWinding = winding; } - // allowed to do nothing - (void) segment->markAndChaseWinding(angle, maxWinding, 0, NULL); + (void) segment->markAndChaseWinding(angle, maxWinding, 0); break; } } @@ -316,12 +315,6 @@ static void skipVertical(const SkTArray<SkOpContour*, true>& contourList, return; } -struct SortableTop { // error if local in pre-C++11 - SkOpSegment* fSegment; - int fIndex; - int fEndIndex; -}; - SkOpSegment* FindSortableTop(const SkTArray<SkOpContour*, true>& contourList, SkOpAngle::IncludeType angleIncludeType, bool* firstContour, int* indexPtr, int* endIndexPtr, SkPoint* topLeft, bool* unsortable, bool* done, bool* onlyVertical, @@ -363,8 +356,6 @@ SkOpSegment* FindSortableTop(const SkTArray<SkOpContour*, true>& contourList, double tHit; SkScalar hitDx = 0; SkScalar hitOppDx = 0; - // keep track of subsequent returns to detect infinite loops - SkTDArray<SortableTop> sortableTops; do { // if current is vertical, find another candidate which is not // if only remaining candidates are vertical, then they can be marked done @@ -375,35 +366,6 @@ SkOpSegment* FindSortableTop(const SkTArray<SkOpContour*, true>& contourList, tryAgain = false; contourWinding = rightAngleWinding(contourList, ¤t, indexPtr, endIndexPtr, &tHit, &hitDx, &tryAgain, onlyVertical, false); - if (tryAgain) { - bool giveUp = false; - int count = sortableTops.count(); - for (int index = 0; index < count; ++index) { - const SortableTop& prev = sortableTops[index]; - if (giveUp) { - prev.fSegment->markDoneFinal(prev.fIndex); - } else if (prev.fSegment == current - && (prev.fIndex == *indexPtr || prev.fEndIndex == *endIndexPtr)) { - // remaining edges are non-vertical and cannot have their winding computed - // mark them as done and return, and hope that assembly can fill the holes - giveUp = true; - index = -1; - } - } - if (giveUp) { - *done = true; - return NULL; - } - } - SortableTop* sortableTop = sortableTops.append(); - sortableTop->fSegment = current; - sortableTop->fIndex = *indexPtr; - sortableTop->fEndIndex = *endIndexPtr; -#if DEBUG_SORT - SkDebugf("%s current=%d index=%d endIndex=%d tHit=%1.9g hitDx=%1.9g try=%d vert=%d\n", - __FUNCTION__, current->debugID(), *indexPtr, *endIndexPtr, tHit, hitDx, tryAgain, - *onlyVertical); -#endif if (*onlyVertical) { return current; } @@ -416,16 +378,10 @@ SkOpSegment* FindSortableTop(const SkTArray<SkOpContour*, true>& contourList, oppContourWinding = rightAngleWinding(contourList, ¤t, indexPtr, endIndexPtr, &tHit, &hitOppDx, &tryAgain, NULL, true); } while (tryAgain); - bool success = current->initWinding(*indexPtr, *endIndexPtr, tHit, contourWinding, hitDx, - oppContourWinding, hitOppDx); + current->initWinding(*indexPtr, *endIndexPtr, tHit, contourWinding, hitDx, oppContourWinding, + hitOppDx); if (current->done()) { return NULL; - } else if (!success) { // check if the span has a valid winding - int min = SkTMin(*indexPtr, *endIndexPtr); - const SkOpSpan& span = current->span(min); - if (span.fWindSum == SK_MinS32) { - return NULL; - } } return current; } @@ -449,17 +405,14 @@ static void checkDuplicates(SkTArray<SkOpContour*, true>* contourList) { } } -static bool checkEnds(SkTArray<SkOpContour*, true>* contourList) { +static void checkEnds(SkTArray<SkOpContour*, true>* contourList) { // it's hard to determine if the end of a cubic or conic nearly intersects another curve. // instead, look to see if the connecting curve intersected at that same end. int contourCount = (*contourList).count(); for (int cTest = 0; cTest < contourCount; ++cTest) { SkOpContour* contour = (*contourList)[cTest]; - if (!contour->checkEnds()) { - return false; - } + contour->checkEnds(); } - return true; } static bool checkMultiples(SkTArray<SkOpContour*, true>* contourList) { @@ -753,9 +706,7 @@ bool HandleCoincidence(SkTArray<SkOpContour*, true>* contourList, int total) { SkOpContour::debugShowWindingValues(contourList); #endif fixOtherTIndex(contourList); - if (!checkEnds(contourList)) { // check if connecting curve intersected at the same end - return false; - } + checkEnds(contourList); // check if connecting curve intersected at the same end bool hasM = checkMultiples(contourList); // check if intersections agree on t and point values SkTDArray<SkOpSegment::AlignedSpan> aligned; if (hasM) { diff --git a/src/pathops/SkPathOpsDebug.h b/src/pathops/SkPathOpsDebug.h index 5770aefec5..18097e7480 100644 --- a/src/pathops/SkPathOpsDebug.h +++ b/src/pathops/SkPathOpsDebug.h @@ -46,7 +46,7 @@ #define DEBUG_ANGLE 0 #define DEBUG_AS_C_CODE 1 #define DEBUG_ASSEMBLE 0 -#define DEBUG_CHECK_ALIGN 0 +#define DEBUG_CHECK_ENDS 0 #define DEBUG_CHECK_TINY 0 #define DEBUG_CONCIDENT 0 #define DEBUG_CROSS 0 @@ -82,7 +82,7 @@ #define DEBUG_ANGLE 1 #define DEBUG_AS_C_CODE 1 #define DEBUG_ASSEMBLE 1 -#define DEBUG_CHECK_ALIGN 1 +#define DEBUG_CHECK_ENDS 1 #define DEBUG_CHECK_TINY 1 #define DEBUG_CONCIDENT 1 #define DEBUG_CROSS 01 diff --git a/src/pathops/SkPathOpsOp.cpp b/src/pathops/SkPathOpsOp.cpp index ff40b475cd..72efb89d10 100644 --- a/src/pathops/SkPathOpsOp.cpp +++ b/src/pathops/SkPathOpsOp.cpp @@ -45,28 +45,22 @@ static SkOpSegment* findChaseOp(SkTDArray<SkOpSpan*>& chase, int* tIndex, int* e continue; } const SkOpAngle* firstAngle = angle; - bool loop = false; + SkDEBUGCODE(bool loop = false); int winding; do { angle = angle->next(); - if (angle == firstAngle && loop) { - break; // if we get here, there's no winding, loop is unorderable - } - loop |= angle == firstAngle; + SkASSERT(angle != firstAngle || !loop); + SkDEBUGCODE(loop |= angle == firstAngle); segment = angle->segment(); winding = segment->windSum(angle); } while (winding == SK_MinS32); - if (winding == SK_MinS32) { - continue; - } int sumMiWinding = segment->updateWindingReverse(angle); int sumSuWinding = segment->updateOppWindingReverse(angle); if (segment->operand()) { SkTSwap<int>(sumMiWinding, sumSuWinding); } SkOpSegment* first = NULL; - bool badData = false; - while ((angle = angle->next()) != firstAngle && !badData) { + while ((angle = angle->next()) != firstAngle) { segment = angle->segment(); int start = angle->start(); int end = angle->end(); @@ -79,19 +73,11 @@ static SkOpSegment* findChaseOp(SkTDArray<SkOpSpan*>& chase, int* tIndex, int* e *tIndex = start; *endIndex = end; } - if (segment->inconsistentAngle(maxWinding, sumWinding, oppMaxWinding, - oppSumWinding, angle)) { - badData = true; - break; - } // OPTIMIZATION: should this also add to the chase? (void) segment->markAngle(maxWinding, sumWinding, oppMaxWinding, oppSumWinding, angle); } } - if (badData) { - continue; - } if (first) { #if TRY_ROTATE *chase.insert(0) = span; @@ -259,42 +245,7 @@ static const bool gOutInverse[kReverseDifference_PathOp + 1][2][2] = { {{ false, true }, { false, false }}, // rev diff }; -#define DEBUGGING_PATHOPS_FROM_HOST 0 // enable to debug svg in chrome -- note path hardcoded below -#if DEBUGGING_PATHOPS_FROM_HOST -#include "SkData.h" -#include "SkStream.h" - -static void dump_path(FILE* file, const SkPath& path, bool force, bool dumpAsHex) { - SkDynamicMemoryWStream wStream; - path.dump(&wStream, force, dumpAsHex); - SkAutoDataUnref data(wStream.copyToData()); - fprintf(file, "%.*s\n", (int) data->size(), data->data()); -} - -static int dumpID = 0; - -static void dump_op(const SkPath& one, const SkPath& two, SkPathOp op) { - FILE* file = fopen("/usr/local/google/home/caryclark/Documents/svgop.txt", "w"); - fprintf(file, "\nstatic void test_%d(skiatest::Reporter* reporter, const char* filename) {\n", - ++dumpID); - fprintf(file, " SkPath path;\n"); - fprintf(file, " path.setFillType((SkPath::FillType) %d);\n", one.getFillType()); - dump_path(file, one, false, true); - fprintf(file, " SkPath path1(path);\n"); - fprintf(file, " path.reset();\n"); - fprintf(file, " path.setFillType((SkPath::FillType) %d);\n", two.getFillType()); - dump_path(file, two, false, true); - fprintf(file, " SkPath path2(path);\n"); - fprintf(file, " testPathOp(reporter, path1, path2, (SkPathOp) %d, filename);\n", op); - fprintf(file, "}\n"); - fclose(file); -} -#endif - bool Op(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result) { -#if DEBUGGING_PATHOPS_FROM_HOST - dump_op(one, two, op); -#endif #if DEBUG_SHOW_TEST_NAME char* debugName = DEBUG_FILENAME_STRING; if (debugName && debugName[0]) { diff --git a/src/pathops/SkPathOpsPoint.h b/src/pathops/SkPathOpsPoint.h index 7ddfbfb5d1..5c2e3a50dd 100644 --- a/src/pathops/SkPathOpsPoint.h +++ b/src/pathops/SkPathOpsPoint.h @@ -227,7 +227,6 @@ struct SkDPoint { // utilities callable by the user from the debugger when the implementation code is linked in void dump() const; static void Dump(const SkPoint& pt); - static void DumpHex(const SkPoint& pt); }; #endif diff --git a/src/pathops/SkPathOpsTypes.h b/src/pathops/SkPathOpsTypes.h index 01fec0d0b6..96627842b3 100644 --- a/src/pathops/SkPathOpsTypes.h +++ b/src/pathops/SkPathOpsTypes.h @@ -141,12 +141,6 @@ inline bool roughly_zero(double x) { return fabs(x) < ROUGH_EPSILON; } -#if 0 // unused for now -inline bool way_roughly_zero(double x) { - return fabs(x) < WAY_ROUGH_EPSILON; -} -#endif - inline bool approximately_zero_inverse(double x) { return fabs(x) > FLT_EPSILON_INVERSE; } diff --git a/src/pathops/SkReduceOrder.cpp b/src/pathops/SkReduceOrder.cpp index 6f06447a47..bb2038b45f 100644 --- a/src/pathops/SkReduceOrder.cpp +++ b/src/pathops/SkReduceOrder.cpp @@ -88,12 +88,12 @@ int SkReduceOrder::reduce(const SkDQuad& quad) { } } if (minXSet == 0x7) { // test for vertical line - if (minYSet == 0x7) { // return 1 if all three are coincident + if (minYSet == 0x7) { // return 1 if all four are coincident return coincident_line(quad, fQuad); } return vertical_line(quad, fQuad); } - if (minYSet == 0x7) { // test for horizontal line + if (minYSet == 0xF) { // test for horizontal line return horizontal_line(quad, fQuad); } int result = check_linear(quad, minX, maxX, minY, maxY, fQuad); |