| Index: src/pathops/SkOpAngle.cpp
|
| diff --git a/src/pathops/SkOpAngle.cpp b/src/pathops/SkOpAngle.cpp
|
| index c13a51a8cca39c6da63b725ba747c30a11648597..52a98d0ba773646b8b40c2551b0ab8dc44e8428f 100644
|
| --- a/src/pathops/SkOpAngle.cpp
|
| +++ b/src/pathops/SkOpAngle.cpp
|
| @@ -189,7 +189,7 @@ int SkOpAngle::allOnOneSide(const SkOpAngle* test) {
|
| SkPath::Verb testVerb = test->segment()->verb();
|
| int iMax = SkPathOpsVerbToPoints(testVerb);
|
| // SkASSERT(origin == test.fCurveHalf[0]);
|
| - const SkDCubic& testCurve = test->fCurvePart;
|
| + const SkDCurve& testCurve = test->fCurvePart;
|
| for (int index = 1; index <= iMax; ++index) {
|
| float xy1 = (float) (line.fX * (testCurve[index].fY - origin.fY));
|
| float xy2 = (float) (line.fY * (testCurve[index].fX - origin.fX));
|
| @@ -292,11 +292,14 @@ 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 (this->endToSide(rh, &inside)) {
|
| - return inside;
|
| - }
|
| - if (rh->endToSide(this, &inside)) {
|
| - return !inside;
|
| + if (!fCurvePart[SkPathOpsVerbToPoints(this->segment()->verb())].approximatelyEqual(
|
| + rh->fCurvePart[SkPathOpsVerbToPoints(rh->segment()->verb())])) {
|
| + if (this->endToSide(rh, &inside)) {
|
| + return inside;
|
| + }
|
| + if (rh->endToSide(this, &inside)) {
|
| + return !inside;
|
| + }
|
| }
|
| if (this->midToSide(rh, &inside)) {
|
| return inside;
|
| @@ -445,14 +448,14 @@ bool SkOpAngle::endsIntersect(SkOpAngle* rh) {
|
| double smallTs[2] = {-1, -1};
|
| bool limited[2] = {false, false};
|
| for (int index = 0; index < 2; ++index) {
|
| - int cPts = index ? rPts : lPts;
|
| + SkPath::Verb cVerb = index ? rVerb : lVerb;
|
| // if the curve is a line, then the line and the ray intersect only at their crossing
|
| - if (cPts == 1) { // line
|
| + if (cVerb == SkPath::kLine_Verb) {
|
| continue;
|
| }
|
| const SkOpSegment& segment = index ? *rh->segment() : *this->segment();
|
| SkIntersections i;
|
| - (*CurveIntersectRay[cPts])(segment.pts(), rays[index], &i);
|
| + (*CurveIntersectRay[cVerb])(segment.pts(), segment.weight(), rays[index], &i);
|
| double tStart = index ? rh->fStart->t() : this->fStart->t();
|
| double tEnd = index ? rh->fComputedEnd->t() : this->fComputedEnd->t();
|
| bool testAscends = tStart < (index ? rh->fComputedEnd->t() : this->fComputedEnd->t());
|
| @@ -509,7 +512,7 @@ bool SkOpAngle::endsIntersect(SkOpAngle* rh) {
|
| double minX, minY, maxX, maxY;
|
| minX = minY = SK_ScalarInfinity;
|
| maxX = maxY = -SK_ScalarInfinity;
|
| - const SkDCubic& curve = index ? rh->fCurvePart : this->fCurvePart;
|
| + const SkDCurve& curve = index ? rh->fCurvePart : this->fCurvePart;
|
| int ptCount = index ? rPts : lPts;
|
| for (int idx2 = 0; idx2 <= ptCount; ++idx2) {
|
| minX = SkTMin(minX, curve[idx2].fX);
|
| @@ -527,7 +530,7 @@ bool SkOpAngle::endsIntersect(SkOpAngle* rh) {
|
| }
|
| }
|
| if (useIntersect) {
|
| - const SkDCubic& curve = sIndex ? rh->fCurvePart : this->fCurvePart;
|
| + const SkDCurve& curve = sIndex ? rh->fCurvePart : this->fCurvePart;
|
| const SkOpSegment& segment = sIndex ? *rh->segment() : *this->segment();
|
| double tStart = sIndex ? rh->fStart->t() : fStart->t();
|
| SkDVector mid = segment.dPtAtT(tStart + (sCeptT - tStart) / 2) - curve[0];
|
| @@ -544,18 +547,17 @@ bool SkOpAngle::endsIntersect(SkOpAngle* rh) {
|
| bool SkOpAngle::endToSide(const SkOpAngle* rh, bool* inside) const {
|
| const SkOpSegment* segment = this->segment();
|
| SkPath::Verb verb = segment->verb();
|
| - int pts = SkPathOpsVerbToPoints(verb);
|
| SkDLine rayEnd;
|
| rayEnd[0].set(this->fEnd->pt());
|
| rayEnd[1] = rayEnd[0];
|
| - SkDVector slopeAtEnd = (*CurveDSlopeAtT[pts])(segment->pts(), this->fEnd->t());
|
| + SkDVector slopeAtEnd = (*CurveDSlopeAtT[verb])(segment->pts(), segment->weight(),
|
| + this->fEnd->t());
|
| rayEnd[1].fX += slopeAtEnd.fY;
|
| rayEnd[1].fY -= slopeAtEnd.fX;
|
| SkIntersections iEnd;
|
| const SkOpSegment* oppSegment = rh->segment();
|
| SkPath::Verb oppVerb = oppSegment->verb();
|
| - int oppPts = SkPathOpsVerbToPoints(oppVerb);
|
| - (*CurveIntersectRay[oppPts])(oppSegment->pts(), rayEnd, &iEnd);
|
| + (*CurveIntersectRay[oppVerb])(oppSegment->pts(), oppSegment->weight(), rayEnd, &iEnd);
|
| double endDist;
|
| int closestEnd = iEnd.closestTo(rh->fStart->t(), rh->fEnd->t(), rayEnd[0], &endDist);
|
| if (closestEnd < 0) {
|
| @@ -570,7 +572,8 @@ bool SkOpAngle::endToSide(const SkOpAngle* rh, bool* inside) const {
|
| double minX, minY, maxX, maxY;
|
| minX = minY = SK_ScalarInfinity;
|
| maxX = maxY = -SK_ScalarInfinity;
|
| - const SkDCubic& curve = rh->fCurvePart;
|
| + const SkDCurve& curve = rh->fCurvePart;
|
| + int oppPts = SkPathOpsVerbToPoints(oppVerb);
|
| for (int idx2 = 0; idx2 <= oppPts; ++idx2) {
|
| minX = SkTMin(minX, curve[idx2].fX);
|
| minY = SkTMin(minY, curve[idx2].fY);
|
| @@ -814,11 +817,14 @@ int SkOpAngle::loopCount() const {
|
| }
|
|
|
| // OPTIMIZATION: can this be done better in after when angles are sorted?
|
| -void SkOpAngle::markStops() {
|
| +bool SkOpAngle::markStops() {
|
| SkOpAngle* angle = this;
|
| int lastEnd = SkTMax(fSectorStart, fSectorEnd);
|
| do {
|
| angle = angle->fNext;
|
| + if (!angle) {
|
| + return false;
|
| + }
|
| int angleStart = SkTMin(angle->fSectorStart, angle->fSectorEnd);
|
| // angles that are smaller by one aren't necessary better, since the larger may be a line
|
| // and the smaller may be a curve that curls to the other side of the line.
|
| @@ -827,6 +833,7 @@ void SkOpAngle::markStops() {
|
| }
|
| lastEnd = SkTMax(angle->fSectorStart, angle->fSectorEnd);
|
| } while (angle != this);
|
| + return true;
|
| }
|
|
|
| bool SkOpAngle::merge(SkOpAngle* angle) {
|
| @@ -857,7 +864,6 @@ double SkOpAngle::midT() const {
|
| bool SkOpAngle::midToSide(const SkOpAngle* rh, bool* inside) const {
|
| const SkOpSegment* segment = this->segment();
|
| SkPath::Verb verb = segment->verb();
|
| - int pts = SkPathOpsVerbToPoints(verb);
|
| const SkPoint& startPt = this->fStart->pt();
|
| const SkPoint& endPt = this->fEnd->pt();
|
| SkDPoint dStartPt;
|
| @@ -868,16 +874,15 @@ bool SkOpAngle::midToSide(const SkOpAngle* rh, bool* inside) const {
|
| rayMid[1].fX = rayMid[0].fX + (endPt.fY - startPt.fY);
|
| rayMid[1].fY = rayMid[0].fY - (endPt.fX - startPt.fX);
|
| SkIntersections iMid;
|
| - (*CurveIntersectRay[pts])(segment->pts(), rayMid, &iMid);
|
| + (*CurveIntersectRay[verb])(segment->pts(), segment->weight(), rayMid, &iMid);
|
| int iOutside = iMid.mostOutside(this->fStart->t(), this->fEnd->t(), dStartPt);
|
| if (iOutside < 0) {
|
| return false;
|
| }
|
| const SkOpSegment* oppSegment = rh->segment();
|
| SkPath::Verb oppVerb = oppSegment->verb();
|
| - int oppPts = SkPathOpsVerbToPoints(oppVerb);
|
| SkIntersections oppMid;
|
| - (*CurveIntersectRay[oppPts])(oppSegment->pts(), rayMid, &oppMid);
|
| + (*CurveIntersectRay[oppVerb])(oppSegment->pts(), oppSegment->weight(), rayMid, &oppMid);
|
| int oppOutside = oppMid.mostOutside(rh->fStart->t(), rh->fEnd->t(), dStartPt);
|
| if (oppOutside < 0) {
|
| return false;
|
| @@ -966,7 +971,7 @@ void SkOpAngle::set(SkOpSpanBase* start, SkOpSpanBase* end) {
|
| fStop = false;
|
| setSpans();
|
| setSector();
|
| - PATH_OPS_DEBUG_CODE(fID = start->globalState()->nextAngleID());
|
| + SkDEBUGCODE(fID = start ? start->globalState()->nextAngleID() : -1);
|
| }
|
|
|
| void SkOpAngle::setCurveHullSweep() {
|
| @@ -1015,10 +1020,16 @@ void SkOpAngle::setCurveHullSweep() {
|
| void SkOpAngle::setSpans() {
|
| fUnorderable = false;
|
| fLastMarked = NULL;
|
| + if (!fStart) {
|
| + fUnorderable = true;
|
| + return;
|
| + }
|
| const SkOpSegment* segment = fStart->segment();
|
| const SkPoint* pts = segment->pts();
|
| + SkDEBUGCODE(fCurvePart.fVerb = SkPath::kCubic_Verb);
|
| SkDEBUGCODE(fCurvePart[2].fX = fCurvePart[2].fY = fCurvePart[3].fX = fCurvePart[3].fY
|
| = SK_ScalarNaN);
|
| + SkDEBUGCODE(fCurvePart.fVerb = segment->verb());
|
| segment->subDivide(fStart, fEnd, &fCurvePart);
|
| setCurveHullSweep();
|
| const SkPath::Verb verb = segment->verb();
|
| @@ -1041,15 +1052,15 @@ void SkOpAngle::setSpans() {
|
| fSide = 0;
|
| fIsCurve = false;
|
| } return;
|
| - case SkPath::kQuad_Verb: {
|
| + case SkPath::kQuad_Verb:
|
| + case SkPath::kConic_Verb: {
|
| SkLineParameters tangentPart;
|
| - SkDQuad& quad2 = *SkTCast<SkDQuad*>(&fCurvePart);
|
| - (void) tangentPart.quadEndPoints(quad2);
|
| + (void) tangentPart.quadEndPoints(fCurvePart.fQuad);
|
| fSide = -tangentPart.pointDistance(fCurvePart[2]); // not normalized -- compare sign only
|
| } break;
|
| case SkPath::kCubic_Verb: {
|
| SkLineParameters tangentPart;
|
| - (void) tangentPart.cubicPart(fCurvePart);
|
| + (void) tangentPart.cubicPart(fCurvePart.fCubic);
|
| fSide = -tangentPart.pointDistance(fCurvePart[3]);
|
| double testTs[4];
|
| // OPTIMIZATION: keep inflections precomputed with cubic segment?
|
| @@ -1080,9 +1091,9 @@ void SkOpAngle::setSpans() {
|
| testT = (testT + testTs[testIndex + 1]) / 2;
|
| }
|
| // OPTIMIZE: could avoid call for t == startT, endT
|
| - SkDPoint pt = dcubic_xy_at_t(pts, testT);
|
| + SkDPoint pt = dcubic_xy_at_t(pts, segment->weight(), testT);
|
| SkLineParameters tangentPart;
|
| - tangentPart.cubicEndPoints(fCurvePart);
|
| + tangentPart.cubicEndPoints(fCurvePart.fCubic);
|
| double testSide = tangentPart.pointDistance(pt);
|
| if (fabs(bestSide) < fabs(testSide)) {
|
| bestSide = testSide;
|
| @@ -1096,6 +1107,10 @@ void SkOpAngle::setSpans() {
|
| }
|
|
|
| void SkOpAngle::setSector() {
|
| + if (!fStart) {
|
| + fUnorderable = true;
|
| + return;
|
| + }
|
| const SkOpSegment* segment = fStart->segment();
|
| SkPath::Verb verb = segment->verb();
|
| fSectorStart = this->findSector(verb, fSweep[0].fX, fSweep[0].fY);
|
| @@ -1176,5 +1191,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 < 5000; // empirically found limit
|
| + return mFactor < 2400; // empirically found limit
|
| }
|
|
|