Index: src/pathops/SkOpSegment.cpp |
diff --git a/src/pathops/SkOpSegment.cpp b/src/pathops/SkOpSegment.cpp |
index ce35f846b3955a7b66790521dd13a7dce5a10a37..de813cb7c9c3ba022b1b6f4331124d462109f1b4 100644 |
--- a/src/pathops/SkOpSegment.cpp |
+++ b/src/pathops/SkOpSegment.cpp |
@@ -102,47 +102,6 @@ SkOpAngle* SkOpSegment::activeAngleOther(SkOpSpanBase* start, SkOpSpanBase** sta |
return other->activeAngleInner(oSpan, startPtr, endPtr, done, sortable); |
} |
-SkDPoint SkOpSegment::activeLeftTop(SkOpSpanBase** firstSpan) { |
- SkASSERT(!done()); |
- SkDPoint topPt = {SK_ScalarMax, SK_ScalarMax}; |
- // see if either end is not done since we want smaller Y of the pair |
- bool lastDone = true; |
- SkOpSpanBase* span = &fHead; |
- SkOpSpanBase* lastSpan = NULL; |
- do { |
- if (!lastDone || (!span->final() && !span->upCast()->done())) { |
- const SkPoint& xy = span->pt(); |
- if (topPt.fY > xy.fY || (topPt.fY == xy.fY && topPt.fX > xy.fX)) { |
- topPt = xy; |
- if (firstSpan) { |
- *firstSpan = span; |
- } |
- } |
- if (fVerb != SkPath::kLine_Verb && !lastDone) { |
- double curveTopT; |
- SkDCurve curve; |
- this->subDivide(lastSpan, span, &curve); |
- SkDPoint curveTop = (curve.*Top[fVerb])(fPts, fWeight, lastSpan->t(), span->t(), |
- &curveTopT); |
- if (topPt.fY > curveTop.fY || (topPt.fY == curveTop.fY && topPt.fX > curveTop.fX)) { |
- topPt = curveTop; |
- if (firstSpan) { |
- const SkPoint& lastXY = lastSpan->pt(); |
- *firstSpan = lastXY.fY > xy.fY || (lastXY.fY == xy.fY && lastXY.fX > xy.fX) |
- ? span : lastSpan; |
- } |
- } |
- } |
- lastSpan = span; |
- } |
- if (span->final()) { |
- break; |
- } |
- lastDone = span->upCast()->done(); |
- } while ((span = span->upCast()->next())); |
- return topPt; |
-} |
- |
bool SkOpSegment::activeOp(SkOpSpanBase* start, SkOpSpanBase* end, int xorMiMask, int xorSuMask, |
SkPathOp op) { |
int sumMiWinding = this->updateWinding(end, start); |
@@ -278,88 +237,6 @@ SkOpPtT* SkOpSegment::addMissing(double t, SkOpSegment* opp, SkChunkAlloc* alloc |
return result; |
} |
-SkOpAngle* SkOpSegment::addSingletonAngleDown(SkOpSegment** otherPtr, SkOpAngle** anglePtr, |
- SkChunkAlloc* allocator) { |
- SkOpSpan* startSpan = fTail.prev(); |
- SkASSERT(startSpan); |
- SkOpAngle* angle = SkOpTAllocator<SkOpAngle>::Allocate(allocator); |
- *anglePtr = angle; |
- angle->set(&fTail, startSpan); |
- fTail.setFromAngle(angle); |
- SkOpSegment* other = NULL; // these initializations silence a release build warning |
- SkOpSpan* oStartSpan = NULL; |
- SkOpSpanBase* oEndSpan = NULL; |
- SkOpPtT* ptT = fTail.ptT(), * startPtT = ptT; |
- while ((ptT = ptT->next()) != startPtT) { |
- other = ptT->segment(); |
- oStartSpan = ptT->span()->upCastable(); |
- if (oStartSpan && oStartSpan->windValue()) { |
- oEndSpan = oStartSpan->next(); |
- break; |
- } |
- oEndSpan = ptT->span(); |
- oStartSpan = oEndSpan->prev(); |
- if (oStartSpan && oStartSpan->windValue()) { |
- break; |
- } |
- } |
- if (!oStartSpan) { |
- return NULL; |
- } |
- SkOpAngle* oAngle = SkOpTAllocator<SkOpAngle>::Allocate(allocator); |
- oAngle->set(oStartSpan, oEndSpan); |
- oStartSpan->setToAngle(oAngle); |
- *otherPtr = other; |
- return oAngle; |
-} |
- |
-SkOpAngle* SkOpSegment::addSingletonAngles(int step, SkChunkAlloc* allocator) { |
- SkOpSegment* other; |
- SkOpAngle* angle, * otherAngle; |
- if (step > 0) { |
- otherAngle = addSingletonAngleUp(&other, &angle, allocator); |
- } else { |
- otherAngle = addSingletonAngleDown(&other, &angle, allocator); |
- } |
- if (!otherAngle) { |
- return NULL; |
- } |
- angle->insert(otherAngle); |
- return angle; |
-} |
- |
-SkOpAngle* SkOpSegment::addSingletonAngleUp(SkOpSegment** otherPtr, SkOpAngle** anglePtr, |
- SkChunkAlloc* allocator) { |
- SkOpSpanBase* endSpan = fHead.next(); |
- SkASSERT(endSpan); |
- SkOpAngle* angle = SkOpTAllocator<SkOpAngle>::Allocate(allocator); |
- *anglePtr = angle; |
- angle->set(&fHead, endSpan); |
- fHead.setToAngle(angle); |
- SkOpSegment* other = NULL; // these initializations silence a release build warning |
- SkOpSpan* oStartSpan = NULL; |
- SkOpSpanBase* oEndSpan = NULL; |
- SkOpPtT* ptT = fHead.ptT(), * startPtT = ptT; |
- while ((ptT = ptT->next()) != startPtT) { |
- other = ptT->segment(); |
- oEndSpan = ptT->span(); |
- oStartSpan = oEndSpan->prev(); |
- if (oStartSpan && oStartSpan->windValue()) { |
- break; |
- } |
- oStartSpan = oEndSpan->upCastable(); |
- if (oStartSpan && oStartSpan->windValue()) { |
- oEndSpan = oStartSpan->next(); |
- break; |
- } |
- } |
- SkOpAngle* oAngle = SkOpTAllocator<SkOpAngle>::Allocate(allocator); |
- oAngle->set(oEndSpan, oStartSpan); |
- oEndSpan->setFromAngle(oAngle); |
- *otherPtr = other; |
- return oAngle; |
-} |
- |
SkOpPtT* SkOpSegment::addT(double t, AllowAlias allowAlias, SkChunkAlloc* allocator) { |
debugValidate(); |
SkPoint pt = this->ptAtT(t); |
@@ -437,14 +314,6 @@ void SkOpSegment::align() { |
debugValidate(); |
} |
-bool SkOpSegment::BetweenTs(const SkOpSpanBase* lesser, double testT, |
- const SkOpSpanBase* greater) { |
- if (lesser->t() > greater->t()) { |
- SkTSwap<const SkOpSpanBase*>(lesser, greater); |
- } |
- return approximately_between(lesser->t(), testT, greater->t()); |
-} |
- |
void SkOpSegment::calcAngles(SkChunkAlloc* allocator) { |
bool activePrior = !fHead.isCanceled(); |
if (activePrior && !fHead.simple()) { |
@@ -494,20 +363,9 @@ void SkOpSegment::checkAngleCoin(SkOpCoincidence* coincidences, SkChunkAlloc* al |
} while ((base = span->next())); |
} |
-// from http://stackoverflow.com/questions/1165647/how-to-determine-if-a-list-of-polygon-points-are-in-clockwise-order |
-bool SkOpSegment::clockwise(const SkOpSpanBase* start, const SkOpSpanBase* end, bool* swap) const { |
- SkASSERT(fVerb != SkPath::kLine_Verb); |
- if (fVerb != SkPath::kCubic_Verb) { |
- SkOpCurve edge; |
- this->subDivide(start, end, &edge); |
- return SkDQuad::Clockwise(edge, swap); |
- } |
- return SkDCubic::Clockwise(fPts, start->t(), end->t(), swap); |
-} |
- |
void SkOpSegment::ComputeOneSum(const SkOpAngle* baseAngle, SkOpAngle* nextAngle, |
SkOpAngle::IncludeType includeType) { |
- const SkOpSegment* baseSegment = baseAngle->segment(); |
+ SkOpSegment* baseSegment = baseAngle->segment(); |
int sumMiWinding = baseSegment->updateWindingReverse(baseAngle); |
int sumSuWinding; |
bool binary = includeType >= SkOpAngle::kBinarySingle; |
@@ -534,9 +392,9 @@ void SkOpSegment::ComputeOneSum(const SkOpAngle* baseAngle, SkOpAngle* nextAngle |
nextAngle->setLastMarked(last); |
} |
-void SkOpSegment::ComputeOneSumReverse(const SkOpAngle* baseAngle, SkOpAngle* nextAngle, |
+void SkOpSegment::ComputeOneSumReverse(SkOpAngle* baseAngle, SkOpAngle* nextAngle, |
SkOpAngle::IncludeType includeType) { |
- const SkOpSegment* baseSegment = baseAngle->segment(); |
+ SkOpSegment* baseSegment = baseAngle->segment(); |
int sumMiWinding = baseSegment->updateWinding(baseAngle); |
int sumSuWinding; |
bool binary = includeType >= SkOpAngle::kBinarySingle; |
@@ -634,102 +492,6 @@ int SkOpSegment::computeSum(SkOpSpanBase* start, SkOpSpanBase* end, |
return start->starter(end)->windSum(); |
} |
-SkOpSpan* SkOpSegment::crossedSpanY(const SkPoint& basePt, double mid, bool opp, bool current, |
- SkScalar* bestY, double* hitT, bool* hitSomething, bool* vertical) { |
- SkScalar bottom = fBounds.fBottom; |
- *vertical = false; |
- if (bottom <= *bestY) { |
- return NULL; |
- } |
- SkScalar top = fBounds.fTop; |
- if (top >= basePt.fY) { |
- return NULL; |
- } |
- if (fBounds.fLeft > basePt.fX) { |
- return NULL; |
- } |
- if (fBounds.fRight < basePt.fX) { |
- return NULL; |
- } |
- if (fBounds.fLeft == fBounds.fRight) { |
- // if vertical, and directly above test point, wait for another one |
- *vertical = AlmostEqualUlps(basePt.fX, fBounds.fLeft); |
- return NULL; |
- } |
- // intersect ray starting at basePt with edge |
- SkIntersections intersections; |
- // OPTIMIZE: use specialty function that intersects ray with curve, |
- // returning t values only for curve (we don't care about t on ray) |
- intersections.allowNear(false); |
- int pts = (intersections.*CurveVertical[fVerb])(fPts, fWeight, top, bottom, basePt.fX, false); |
- if (pts == 0 || (current && pts == 1)) { |
- return NULL; |
- } |
- if (current) { |
- SkASSERT(pts > 1); |
- int closestIdx = 0; |
- double closest = fabs(intersections[0][0] - mid); |
- for (int idx = 1; idx < pts; ++idx) { |
- double test = fabs(intersections[0][idx] - mid); |
- if (closest > test) { |
- closestIdx = idx; |
- closest = test; |
- } |
- } |
- intersections.quickRemoveOne(closestIdx, --pts); |
- } |
- double bestT = -1; |
- for (int index = 0; index < pts; ++index) { |
- double foundT = intersections[0][index]; |
- if (approximately_less_than_zero(foundT) |
- || approximately_greater_than_one(foundT)) { |
- continue; |
- } |
- SkScalar testY = (*CurvePointAtT[fVerb])(fPts, fWeight, foundT).fY; |
- if (approximately_negative(testY - *bestY) |
- || approximately_negative(basePt.fY - testY)) { |
- continue; |
- } |
- if (pts > 1 && fVerb == SkPath::kLine_Verb) { |
- *vertical = true; |
- return NULL; // if the intersection is edge on, wait for another one |
- } |
- if (fVerb > SkPath::kLine_Verb) { |
- SkScalar dx = (*CurveSlopeAtT[fVerb])(fPts, fWeight, foundT).fX; |
- if (approximately_zero(dx)) { |
- *vertical = true; |
- return NULL; // hit vertical, wait for another one |
- } |
- } |
- *bestY = testY; |
- bestT = foundT; |
- } |
- if (bestT < 0) { |
- return NULL; |
- } |
- SkASSERT(bestT >= 0); |
- SkASSERT(bestT < 1); |
- SkOpSpanBase* testTSpanBase = &this->fHead; |
- SkOpSpanBase* nextTSpan; |
- double endT = 0; |
- do { |
- nextTSpan = testTSpanBase->upCast()->next(); |
- endT = nextTSpan->t(); |
- if (endT >= bestT) { |
- break; |
- } |
- testTSpanBase = nextTSpan; |
- } while (testTSpanBase); |
- SkOpSpan* bestTSpan = NULL; |
- SkOpSpan* testTSpan = testTSpanBase->upCast(); |
- if (!testTSpan->isCanceled()) { |
- *hitT = bestT; |
- bestTSpan = testTSpan; |
- *hitSomething = true; |
- } |
- return bestTSpan; |
-} |
- |
void SkOpSegment::detach(const SkOpSpan* span) { |
if (span->done()) { |
--fDoneCount; |
@@ -1036,126 +798,6 @@ SkOpSegment* SkOpSegment::findNextXor(SkOpSpanBase** nextStart, SkOpSpanBase** n |
return nextSegment; |
} |
-SkOpSegment* SkOpSegment::findTop(bool firstPass, SkOpSpanBase** startPtr, SkOpSpanBase** endPtr, |
- bool* unsortable, SkChunkAlloc* allocator) { |
- // iterate through T intersections and return topmost |
- // topmost tangent from y-min to first pt is closer to horizontal |
- SkASSERT(!done()); |
- SkOpSpanBase* firstT = NULL; |
- (void) this->activeLeftTop(&firstT); |
- if (!firstT) { |
- *unsortable = !firstPass; |
- firstT = &fHead; |
- while (firstT->upCast()->done()) { |
- firstT = firstT->upCast()->next(); |
- } |
- *startPtr = firstT; |
- *endPtr = firstT->upCast()->next(); |
- return this; |
- } |
- // sort the edges to find the leftmost |
- int step = 1; |
- SkOpSpanBase* end; |
- if (firstT->final() || firstT->upCast()->done()) { |
- step = -1; |
- end = firstT->prev(); |
- SkASSERT(end); |
- } else { |
- end = firstT->upCast()->next(); |
- } |
- // if the topmost T is not on end, or is three-way or more, find left |
- // look for left-ness from tLeft to firstT (matching y of other) |
- SkASSERT(firstT != end); |
- SkOpAngle* markAngle = spanToAngle(firstT, end); |
- if (!markAngle) { |
- markAngle = addSingletonAngles(step, allocator); |
- } |
- if (!markAngle) { |
- return NULL; |
- } |
- if (!markAngle->markStops()) { |
- return NULL; |
- } |
- const SkOpAngle* baseAngle = markAngle->next() == markAngle && !isVertical() ? markAngle |
- : markAngle->findFirst(); |
- if (!baseAngle) { |
- return NULL; // nothing to do |
- } |
- SkScalar top = SK_ScalarMax; |
- const SkOpAngle* firstAngle = NULL; |
- const SkOpAngle* angle = baseAngle; |
-#if DEBUG_SWAP_TOP |
- SkDebugf("-%s- baseAngle\n", __FUNCTION__); |
- baseAngle->debugLoop(); |
-#endif |
- do { |
- if (!angle->unorderable()) { |
- const SkOpSegment* next = angle->segment(); |
- SkPathOpsBounds bounds; |
- next->subDivideBounds(angle->end(), angle->start(), &bounds); |
- if (top > bounds.fTop) { |
- top = bounds.fTop; |
- firstAngle = angle; |
- } |
- } |
- angle = angle->next(); |
- } while (angle != baseAngle); |
- if (!firstAngle) { |
- return NULL; // if all are unorderable, give up |
- } |
-#if DEBUG_SWAP_TOP |
- SkDebugf("-%s- firstAngle\n", __FUNCTION__); |
- firstAngle->debugLoop(); |
-#endif |
- // skip edges that have already been processed |
- angle = firstAngle; |
- SkOpSegment* leftSegment = NULL; |
- bool looped = false; |
- do { |
- *unsortable = angle->unorderable(); |
- if (firstPass || !*unsortable) { |
- leftSegment = angle->segment(); |
- *startPtr = angle->end(); |
- *endPtr = angle->start(); |
- const SkOpSpan* firstSpan = (*startPtr)->starter(*endPtr); |
- if (!firstSpan->done()) { |
- break; |
- } |
- } |
- angle = angle->next(); |
- looped = true; |
- } while (angle != firstAngle); |
- if (angle == firstAngle && looped) { |
- return NULL; |
- } |
- if (leftSegment->verb() >= SkPath::kQuad_Verb) { |
- SkOpSpanBase* start = *startPtr; |
- SkOpSpanBase* end = *endPtr; |
- bool swap; |
- bool cw = leftSegment->clockwise(start, end, &swap); |
-#if DEBUG_SWAP_TOP |
- SkDebugf("%s id=%d s=%1.9g e=%1.9g (%c) cw=%d swap=%d inflections=%d monotonic=%d\n", |
- __FUNCTION__, leftSegment->debugID(), start->t(), end->t(), |
- start->t() < end->t() ? '-' : '+', cw, |
- swap, leftSegment->debugInflections(start, end), |
- leftSegment->monotonicInY(start, end)); |
-#endif |
- if (!cw && swap) { |
- // FIXME: I doubt it makes sense to (necessarily) swap if the edge was not the first |
- // sorted but merely the first not already processed (i.e., not done) |
- SkTSwap(*startPtr, *endPtr); |
- } |
- // FIXME: clockwise isn't reliable -- try computing swap from tangent ? |
- } else { |
-#if DEBUG_SWAP_TOP |
- SkDebugf("%s id=%d s=%1.9g e=%1.9g (%c) cw=%d swap=%d inflections=%d monotonic=%d\n", |
- __FUNCTION__, leftSegment->debugID(), (*startPtr)->t(), (*endPtr)->t(), |
- (*startPtr)->t() < (*endPtr)->t() ? '-' : '+', -1, -1, -1, 1); |
-#endif |
- } |
- return leftSegment; |
-} |
- |
SkOpGlobalState* SkOpSegment::globalState() const { |
return contour()->globalState(); |
} |
@@ -1169,6 +811,7 @@ void SkOpSegment::init(SkPoint pts[], SkScalar weight, SkOpContour* contour, SkP |
fCubicType = SkDCubic::kUnsplit_SkDCubicType; |
fCount = 0; |
fDoneCount = 0; |
+ fTopsFound = false; |
fVisited = false; |
SkOpSpan* zeroSpan = &fHead; |
zeroSpan->init(this, NULL, 0, fPts[0]); |
@@ -1178,68 +821,6 @@ void SkOpSegment::init(SkPoint pts[], SkScalar weight, SkOpContour* contour, SkP |
SkDEBUGCODE(fID = globalState()->nextSegmentID()); |
} |
-void SkOpSegment::initWinding(SkOpSpanBase* start, SkOpSpanBase* end, |
- SkOpAngle::IncludeType angleIncludeType) { |
- int local = SkOpSegment::SpanSign(start, end); |
- SkDEBUGCODE(bool success); |
- if (angleIncludeType == SkOpAngle::kBinarySingle) { |
- int oppLocal = SkOpSegment::OppSign(start, end); |
- SkDEBUGCODE(success =) markAndChaseWinding(start, end, local, oppLocal, NULL); |
- // OPTIMIZATION: the reverse mark and chase could skip the first marking |
- SkDEBUGCODE(success |=) markAndChaseWinding(end, start, local, oppLocal, NULL); |
- } else { |
- SkDEBUGCODE(success =) markAndChaseWinding(start, end, local, NULL); |
- // OPTIMIZATION: the reverse mark and chase could skip the first marking |
- SkDEBUGCODE(success |=) markAndChaseWinding(end, start, local, NULL); |
- } |
- SkASSERT(success); |
-} |
- |
-/* |
-when we start with a vertical intersect, we try to use the dx to determine if the edge is to |
-the left or the right of vertical. This determines if we need to add the span's |
-sign or not. However, this isn't enough. |
-If the supplied sign (winding) is zero, then we didn't hit another vertical span, so dx is needed. |
-If there was a winding, then it may or may not need adjusting. If the span the winding was borrowed |
-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(SkOpSpanBase* start, SkOpSpanBase* end, double tHit, |
- int winding, SkScalar hitDx, int oppWind, SkScalar hitOppDx) { |
- SkASSERT(this == start->segment()); |
- SkASSERT(hitDx || !winding); |
- SkScalar dx = (*CurveSlopeAtT[fVerb])(fPts, fWeight, tHit).fX; |
-// SkASSERT(dx); |
- int windVal = start->starter(end)->windValue(); |
-#if DEBUG_WINDING_AT_T |
- SkDebugf("%s id=%d oldWinding=%d hitDx=%c dx=%c windVal=%d", __FUNCTION__, debugID(), winding, |
- hitDx ? hitDx > 0 ? '+' : '-' : '0', dx > 0 ? '+' : '-', windVal); |
-#endif |
- int sideWind = winding + (dx < 0 ? windVal : -windVal); |
- if (abs(winding) < abs(sideWind)) { |
- winding = sideWind; |
- } |
- SkDEBUGCODE(int oppLocal = SkOpSegment::OppSign(start, end)); |
- SkASSERT(hitOppDx || !oppWind || !oppLocal); |
- int oppWindVal = start->starter(end)->oppValue(); |
- if (!oppWind) { |
- oppWind = dx < 0 ? oppWindVal : -oppWindVal; |
- } else if (hitOppDx * dx >= 0) { |
- int oppSideWind = oppWind + (dx < 0 ? oppWindVal : -oppWindVal); |
- if (abs(oppWind) < abs(oppSideWind)) { |
- oppWind = oppSideWind; |
- } |
- } |
-#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); |
- // OPTIMIZATION: the reverse mark and chase could skip the first marking |
- success |= markAndChaseWinding(end, start, winding, oppWind, NULL); |
- return success; |
-} |
- |
bool SkOpSegment::isClose(double t, const SkOpSegment* opp) const { |
SkDPoint cPt = this->dPtAtT(t); |
SkDVector dxdy = (*CurveDSlopeAtT[this->verb()])(this->pts(), this->weight(), t); |
@@ -1306,8 +887,7 @@ bool SkOpSegment::markAndChaseWinding(SkOpSpanBase* start, SkOpSpanBase* end, |
while ((other = other->nextChase(&start, &step, &spanStart, &last))) { |
if (spanStart->windSum() != SK_MinS32) { |
if (this->operand() == other->operand()) { |
- SkASSERT(spanStart->windSum() == winding); |
- if (spanStart->oppSum() != oppWinding) { |
+ if (spanStart->windSum() != winding || spanStart->oppSum() != oppWinding) { |
this->globalState()->setWindingFailed(); |
return false; |
} |
@@ -1438,39 +1018,6 @@ static SkOpSegment* set_last(SkOpSpanBase** last, SkOpSpanBase* endSpan) { |
return NULL; |
} |
-bool SkOpSegment::monotonicInY(const SkOpSpanBase* start, const SkOpSpanBase* end) const { |
- SkASSERT(fVerb != SkPath::kLine_Verb); |
- if (fVerb == SkPath::kQuad_Verb) { |
- SkDQuad dst = SkDQuad::SubDivide(fPts, start->t(), end->t()); |
- return dst.monotonicInY(); |
- } |
- if (fVerb == SkPath::kConic_Verb) { |
- SkDConic dst = SkDConic::SubDivide(fPts, fWeight, start->t(), end->t()); |
- return dst.monotonicInY(); |
- } |
- SkASSERT(fVerb == SkPath::kCubic_Verb); |
- SkDCubic dst = SkDCubic::SubDivide(fPts, start->t(), end->t()); |
- if (dst.monotonicInY()) { |
- return true; |
- } |
- SkDCubic whole; |
- whole.set(fPts); |
- return whole.monotonicInY(); |
-} |
- |
-bool SkOpSegment::NextCandidate(SkOpSpanBase* span, SkOpSpanBase** start, |
- SkOpSpanBase** end) { |
- while (span->final() || span->upCast()->done()) { |
- if (span->final()) { |
- return false; |
- } |
- span = span->upCast()->next(); |
- } |
- *start = span; |
- *end = span->upCast()->next(); |
- return true; |
-} |
- |
SkOpSegment* SkOpSegment::nextChase(SkOpSpanBase** startPtr, int* stepPtr, SkOpSpan** minPtr, |
SkOpSpanBase** last) const { |
SkOpSpanBase* origStart = *startPtr; |
@@ -1499,7 +1046,7 @@ SkOpSegment* SkOpSegment::nextChase(SkOpSpanBase** startPtr, int* stepPtr, SkOpS |
return NULL; |
} |
#if DEBUG_WINDING |
- if (angle->sign() != next->sign() && !angle->segment()->contour()->isXor() |
+ if (angle->debugSign() != next->debugSign() && !angle->segment()->contour()->isXor() |
&& !next->segment()->contour()->isXor()) { |
SkDebugf("%s mismatched signs\n", __FUNCTION__); |
} |
@@ -1558,7 +1105,7 @@ void SkOpSegment::missingCoincidence(SkOpCoincidence* coincidences, SkChunkAlloc |
SkASSERT(ptT->span() == span); |
while ((ptT = ptT->next()) != spanStopPtT) { |
SkOpSegment* opp = ptT->span()->segment(); |
- if (opp->setVisited()) { |
+ if (!opp->setVisited()) { |
continue; |
} |
if (opp->verb() == SkPath::kLine_Verb) { |
@@ -2024,19 +1571,6 @@ bool SkOpSegment::subDivide(const SkOpSpanBase* start, const SkOpSpanBase* end, |
return true; |
} |
-void SkOpSegment::subDivideBounds(const SkOpSpanBase* start, const SkOpSpanBase* end, |
- SkPathOpsBounds* bounds) const { |
- SkDCurve edge; |
- subDivide(start, end, &edge); |
- (edge.*SetBounds[fVerb])(fPts, fWeight, start->t(), end->t(), bounds); |
-} |
- |
-SkDPoint SkOpSegment::top(const SkOpSpanBase* start, const SkOpSpanBase* end, double* topT) const { |
- SkDCurve edge; |
- subDivide(start, end, &edge); |
- return (edge.*Top[fVerb])(fPts, fWeight, start->t(), end->t(), topT); |
-} |
- |
void SkOpSegment::undoneSpan(SkOpSpanBase** start, SkOpSpanBase** end) { |
SkOpSpan* span = this->head(); |
do { |
@@ -2072,10 +1606,19 @@ int SkOpSegment::updateOppWindingReverse(const SkOpAngle* angle) const { |
return updateOppWinding(startSpan, endSpan); |
} |
-int SkOpSegment::updateWinding(const SkOpSpanBase* start, const SkOpSpanBase* end) const { |
- const SkOpSpan* lesser = start->starter(end); |
+int SkOpSegment::updateWinding(SkOpSpanBase* start, SkOpSpanBase* end) { |
+ SkOpSpan* lesser = start->starter(end); |
int winding = lesser->windSum(); |
if (winding == SK_MinS32) { |
+ SkOpGlobalState* globals = this->globalState(); |
+ SkOpContour* contourHead = globals->contourHead(); |
+ int windTry = 0; |
+ while (!lesser->sortableTop(contourHead) && ++windTry < SkOpGlobalState::kMaxWindingTries) { |
+ ; |
+ } |
+ winding = lesser->windSum(); |
+ } |
+ if (winding == SK_MinS32) { |
return winding; |
} |
int spanWinding = SkOpSegment::SpanSign(start, end); |
@@ -2086,15 +1629,15 @@ int SkOpSegment::updateWinding(const SkOpSpanBase* start, const SkOpSpanBase* en |
return winding; |
} |
-int SkOpSegment::updateWinding(const SkOpAngle* angle) const { |
- const SkOpSpanBase* startSpan = angle->start(); |
- const SkOpSpanBase* endSpan = angle->end(); |
+int SkOpSegment::updateWinding(SkOpAngle* angle) { |
+ SkOpSpanBase* startSpan = angle->start(); |
+ SkOpSpanBase* endSpan = angle->end(); |
return updateWinding(endSpan, startSpan); |
} |
-int SkOpSegment::updateWindingReverse(const SkOpAngle* angle) const { |
- const SkOpSpanBase* startSpan = angle->start(); |
- const SkOpSpanBase* endSpan = angle->end(); |
+int SkOpSegment::updateWindingReverse(const SkOpAngle* angle) { |
+ SkOpSpanBase* startSpan = angle->start(); |
+ SkOpSpanBase* endSpan = angle->end(); |
return updateWinding(startSpan, endSpan); |
} |
@@ -2110,41 +1653,6 @@ bool SkOpSegment::UseInnerWinding(int outerWinding, int innerWinding) { |
return result; |
} |
-int SkOpSegment::windingAtT(double tHit, const SkOpSpan* span, bool crossOpp, |
- SkScalar* dx) const { |
- if (approximately_zero(tHit - span->t())) { // if we hit the end of a span, disregard |
- return SK_MinS32; |
- } |
- int winding = crossOpp ? span->oppSum() : span->windSum(); |
- SkASSERT(winding != SK_MinS32); |
- int windVal = crossOpp ? span->oppValue() : span->windValue(); |
-#if DEBUG_WINDING_AT_T |
- SkDebugf("%s id=%d opp=%d tHit=%1.9g t=%1.9g oldWinding=%d windValue=%d", __FUNCTION__, |
- debugID(), crossOpp, tHit, span->t(), winding, windVal); |
-#endif |
- // see if a + change in T results in a +/- change in X (compute x'(T)) |
- *dx = (*CurveSlopeAtT[fVerb])(fPts, fWeight, tHit).fX; |
- if (fVerb > SkPath::kLine_Verb && approximately_zero(*dx)) { |
- *dx = fPts[2].fX - fPts[1].fX - *dx; |
- } |
- if (*dx == 0) { |
-#if DEBUG_WINDING_AT_T |
- SkDebugf(" dx=0 winding=SK_MinS32\n"); |
-#endif |
- return SK_MinS32; |
- } |
- if (windVal < 0) { // reverse sign if opp contour traveled in reverse |
- *dx = -*dx; |
- } |
- if (winding * *dx > 0) { // if same signs, result is negative |
- winding += *dx > 0 ? -windVal : windVal; |
- } |
-#if DEBUG_WINDING_AT_T |
- SkDebugf(" dx=%c winding=%d\n", *dx > 0 ? '+' : '-', winding); |
-#endif |
- return winding; |
-} |
- |
int SkOpSegment::windSum(const SkOpAngle* angle) const { |
const SkOpSpan* minSpan = angle->start()->starter(angle->end()); |
return minSpan->windSum(); |