Index: src/pathops/SkOpAngle.cpp |
diff --git a/src/pathops/SkOpAngle.cpp b/src/pathops/SkOpAngle.cpp |
index c2eb0c93266212360fb5f2550ffd7e13ee0880cc..479a6f673de9963fd786fb7b6f61ec5486defffb 100644 |
--- a/src/pathops/SkOpAngle.cpp |
+++ b/src/pathops/SkOpAngle.cpp |
@@ -62,6 +62,12 @@ bool SkOpAngle::after(SkOpAngle* test) { |
SkOpAngle* lh = test; |
SkOpAngle* rh = lh->fNext; |
SkASSERT(lh != rh); |
+ fCurvePart = fOriginalCurvePart; |
+ lh->fCurvePart = lh->fOriginalCurvePart; |
+ lh->fCurvePart.offset(lh->segment()->verb(), fCurvePart[0] - lh->fCurvePart[0]); |
+ rh->fCurvePart = rh->fOriginalCurvePart; |
+ rh->fCurvePart.offset(rh->segment()->verb(), fCurvePart[0] - rh->fCurvePart[0]); |
+ |
#if DEBUG_ANGLE |
SkString bugOut; |
bugOut.printf("%s [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g" |
@@ -150,9 +156,7 @@ bool SkOpAngle::after(SkOpAngle* test) { |
return COMPARE_RESULT(8, ltOpposite); |
} else if (ltOrder == 1 && trOrder == 0) { |
SkASSERT(lrOrder < 0); |
- SkDEBUGCODE(bool ltOpposite = lh->oppositePlanes(this)); |
bool trOpposite = oppositePlanes(rh); |
- SkASSERT(ltOpposite != trOpposite); |
return COMPARE_RESULT(9, trOpposite); |
} else if (lrOrder == 1 && trOrder == 1) { |
SkASSERT(ltOrder < 0); |
@@ -175,15 +179,8 @@ bool SkOpAngle::after(SkOpAngle* test) { |
int SkOpAngle::allOnOneSide(const SkOpAngle* test) { |
SkASSERT(!fIsCurve); |
SkASSERT(test->fIsCurve); |
- const SkDPoint& origin = test->fCurvePart[0]; |
- SkVector line; |
- if (segment()->verb() == SkPath::kLine_Verb) { |
- const SkPoint* linePts = segment()->pts(); |
- int lineStart = fStart->t() < fEnd->t() ? 0 : 1; |
- line = linePts[lineStart ^ 1] - linePts[lineStart]; |
- } else { |
- line = (fCurvePart[1] - fCurvePart[0]).asSkVector(); |
- } |
+ SkDPoint origin = fCurvePart[0]; |
+ SkDVector line = fCurvePart[1] - origin; |
float crosses[3]; |
SkPath::Verb testVerb = test->segment()->verb(); |
int iMax = SkPathOpsVerbToPoints(testVerb); |
@@ -244,8 +241,7 @@ bool SkOpAngle::checkParallel(SkOpAngle* rh) { |
// compute the perpendicular to the endpoints and see where it intersects the opposite curve |
// if the intersections within the t range, do a cross check on those |
bool inside; |
- if (!fCurvePart[SkPathOpsVerbToPoints(this->segment()->verb())].approximatelyEqual( |
- rh->fCurvePart[SkPathOpsVerbToPoints(rh->segment()->verb())])) { |
+ if (!fEnd->contains(rh->fEnd)) { |
if (this->endToSide(rh, &inside)) { |
return inside; |
} |
@@ -280,7 +276,7 @@ bool SkOpAngle::computeSector() { |
} |
fComputedSector = true; |
bool stepUp = fStart->t() < fEnd->t(); |
- const SkOpSpanBase* checkEnd = fEnd; |
+ SkOpSpanBase* checkEnd = fEnd; |
if (checkEnd->final() && stepUp) { |
fUnorderable = true; |
return false; |
@@ -306,7 +302,7 @@ bool SkOpAngle::computeSector() { |
: checkEnd->prev(); |
} while (checkEnd); |
recomputeSector: |
- SkOpSpanBase* computedEnd = stepUp ? checkEnd ? checkEnd->prev() : fEnd->segment()->head() |
+ SkOpSpanBase* computedEnd = stepUp ? checkEnd ? checkEnd->prev() : fEnd->segment()->head() |
: checkEnd ? checkEnd->upCast()->next() : fEnd->segment()->tail(); |
if (checkEnd == fEnd || computedEnd == fEnd || computedEnd == fStart) { |
fUnorderable = true; |
@@ -398,7 +394,7 @@ bool SkOpAngle::endsIntersect(SkOpAngle* rh) { |
int rPts = SkPathOpsVerbToPoints(rVerb); |
SkDLine rays[] = {{{this->fCurvePart[0], rh->fCurvePart[rPts]}}, |
{{this->fCurvePart[0], this->fCurvePart[lPts]}}}; |
- if (rays[0][1] == rays[1][1]) { |
+ if (this->fEnd->contains(rh->fEnd)) { |
return checkParallel(rh); |
} |
double smallTs[2] = {-1, -1}; |
@@ -538,14 +534,14 @@ bool SkOpAngle::endToSide(const SkOpAngle* rh, bool* inside) const { |
} |
double maxWidth = SkTMax(maxX - minX, maxY - minY); |
endDist /= maxWidth; |
- if (endDist < 5e-11) { // empirically found |
+ if (endDist < 5e-12) { // empirically found |
return false; |
} |
const SkDPoint* endPt = &rayEnd[0]; |
SkDPoint oppPt = iEnd.pt(closestEnd); |
SkDVector vLeft = *endPt - start; |
SkDVector vRight = oppPt - start; |
- double dir = vLeft.crossCheck(vRight); |
+ double dir = vLeft.crossNoNormalCheck(vRight); |
if (!dir) { |
return false; |
} |
@@ -785,7 +781,7 @@ bool SkOpAngle::orderable(SkOpAngle* rh) { |
SkASSERT(x_ry != rx_y); // indicates an undetected coincidence -- worth finding earlier |
return x_ry < rx_y; |
} |
- if ((result = allOnOneSide(rh)) >= 0) { |
+ if ((result = this->allOnOneSide(rh)) >= 0) { |
return result; |
} |
if (fUnorderable || approximately_zero(rh->fSide)) { |
@@ -798,11 +794,10 @@ bool SkOpAngle::orderable(SkOpAngle* rh) { |
if (rh->fUnorderable || approximately_zero(fSide)) { |
goto unorderable; |
} |
- } |
- if ((result = convexHullOverlaps(rh)) >= 0) { |
+ } else if ((result = this->convexHullOverlaps(rh)) >= 0) { |
return result; |
} |
- return endsIntersect(rh); |
+ return this->endsIntersect(rh); |
unorderable: |
fUnorderable = true; |
rh->fUnorderable = true; |
@@ -846,8 +841,17 @@ void SkOpAngle::setCurveHullSweep() { |
return; |
} |
fSweep[1] = fCurvePart[2] - fCurvePart[0]; |
+ // OPTIMIZE: I do the following float check a lot -- probably need a |
+ // central place for this val-is-small-compared-to-curve check |
+ double maxVal = 0; |
+ for (int index = 0; index < SkPathOpsVerbToPoints(segment->verb()); ++index) { |
+ maxVal = SkTMax(maxVal, SkTMax(SkTAbs(fCurvePart[index].fX), |
+ SkTAbs(fCurvePart[index].fY))); |
+ } |
+ |
if (SkPath::kCubic_Verb != segment->verb()) { |
- if (!fSweep[0].fX && !fSweep[0].fY) { |
+ if (roughly_zero_when_compared_to(fSweep[0].fX, maxVal) |
+ && roughly_zero_when_compared_to(fSweep[0].fY, maxVal)) { |
fSweep[0] = fSweep[1]; |
} |
return; |
@@ -856,7 +860,8 @@ void SkOpAngle::setCurveHullSweep() { |
if (fSweep[0].fX == 0 && fSweep[0].fY == 0) { |
fSweep[0] = fSweep[1]; |
fSweep[1] = thirdSweep; |
- if (fSweep[0].fX == 0 && fSweep[0].fY == 0) { |
+ if (roughly_zero_when_compared_to(fSweep[0].fX, maxVal) |
+ && roughly_zero_when_compared_to(fSweep[0].fY, maxVal)) { |
fSweep[0] = fSweep[1]; |
fCurvePart[1] = fCurvePart[3]; |
fIsCurve = false; |
@@ -894,6 +899,7 @@ void SkOpAngle::setSpans() { |
= SK_ScalarNaN); |
SkDEBUGCODE(fCurvePart.fVerb = segment->verb()); |
segment->subDivide(fStart, fEnd, &fCurvePart); |
+ fOriginalCurvePart = fCurvePart; |
setCurveHullSweep(); |
const SkPath::Verb verb = segment->verb(); |
if (verb != SkPath::kLine_Verb |
@@ -1049,5 +1055,5 @@ bool SkOpAngle::tangentsDiverge(const SkOpAngle* rh, double s0xt0) const { |
double tDist = tweep[0].length() * m; |
bool useS = fabs(sDist) < fabs(tDist); |
double mFactor = fabs(useS ? this->distEndRatio(sDist) : rh->distEndRatio(tDist)); |
- return mFactor < 2400; // empirically found limit |
+ return mFactor < 50; // empirically found limit |
} |