| Index: src/pathops/SkOpSegment.cpp
 | 
| diff --git a/src/pathops/SkOpSegment.cpp b/src/pathops/SkOpSegment.cpp
 | 
| index c233c0f9b671e954bac223dcbf82576af189ef6f..95046e2fd2d3da7b8b1aafc085392c5a26f16707 100644
 | 
| --- a/src/pathops/SkOpSegment.cpp
 | 
| +++ b/src/pathops/SkOpSegment.cpp
 | 
| @@ -160,10 +160,6 @@
 | 
|  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 @@
 | 
|      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 @@
 | 
|          --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 @@
 | 
|              ++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 @@
 | 
|      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 @@
 | 
|  // 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 @@
 | 
|          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 @@
 | 
|          }
 | 
|  
 | 
|          // 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 @@
 | 
|                  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];
 | 
| @@ -1581,9 +1350,6 @@
 | 
|          oTest = &other->fTs[oIndex];
 | 
|          oTestPt = &oTest->fPt;
 | 
|          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));
 | 
| @@ -1598,7 +1364,6 @@
 | 
|                  test->fWindValue = lastWind;
 | 
|                  test->fOppValue = lastOpp;
 | 
|                  if (zero) {
 | 
| -                    SkASSERT(!test->fDone);
 | 
|                      test->fDone = true;
 | 
|                      ++fDoneSpans;
 | 
|                  }
 | 
| @@ -1637,9 +1402,7 @@
 | 
|          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 @@
 | 
|      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 @@
 | 
|          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 @@
 | 
|          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 @@
 | 
|  }
 | 
|  
 | 
|  // 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 @@
 | 
|                  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 @@
 | 
|      }
 | 
|      if (missingSpans.count() == 0) {
 | 
|          debugValidate();
 | 
| -        return true;
 | 
| +        return;
 | 
|      }
 | 
|      debugValidate();
 | 
|      int missingCount = missingSpans.count();
 | 
| @@ -2499,7 +2236,6 @@
 | 
|          missingSpans[index].fOther->fixOtherTIndex();
 | 
|      }
 | 
|      debugValidate();
 | 
| -    return true;
 | 
|  }
 | 
|  
 | 
|  void SkOpSegment::checkLinks(const SkOpSpan* base,
 | 
| @@ -2521,7 +2257,7 @@
 | 
|      }
 | 
|      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 @@
 | 
|      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* 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 @@
 | 
|      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::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);
 | 
| -    }
 | 
| -    SkASSERT(success);
 | 
| +        (void) markAndChaseWinding(end, start, local);
 | 
| +    }
 | 
|  }
 | 
|  
 | 
|  /*
 | 
| @@ -3672,7 +3333,7 @@
 | 
|  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 @@
 | 
|  #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 @@
 | 
|      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 @@
 | 
|              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 @@
 | 
|      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);
 | 
| -}
 | 
| -
 | 
| -bool SkOpSegment::markAndChaseWinding(int index, int endIndex, int winding, SkOpSpan** 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;
 | 
| +}
 | 
| +
 | 
| +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 @@
 | 
|              SkASSERT(!last);
 | 
|              break;
 | 
|          }
 | 
| -        (void) other->markWinding(min, winding);
 | 
| -    }
 | 
| -    if (lastPtr) {
 | 
| -        *lastPtr = last;
 | 
| -    }
 | 
| -    return success;
 | 
| -}
 | 
| -
 | 
| -bool SkOpSegment::markAndChaseWinding(int index, int endIndex, int winding, int oppWinding,
 | 
| -        SkOpSpan** lastPtr) {
 | 
| +        other->markWinding(min, winding);
 | 
| +    }
 | 
| +    return last;
 | 
| +}
 | 
| +
 | 
| +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 @@
 | 
|              break;
 | 
|          }
 | 
|          if (fOperand == other->fOperand) {
 | 
| -            (void) other->markWinding(min, winding, oppWinding);
 | 
| +            other->markWinding(min, winding, oppWinding);
 | 
|          } else {
 | 
| -            (void) other->markWinding(min, oppWinding, winding);
 | 
| -        }
 | 
| -    }
 | 
| -    if (lastPtr) {
 | 
| -        *lastPtr = last;
 | 
| -    }
 | 
| -    return success;
 | 
| -}
 | 
| -
 | 
| -bool SkOpSegment::markAndChaseWinding(const SkOpAngle* angle, int winding, int oppWinding,
 | 
| -        SkOpSpan** lastPtr) {
 | 
| +            other->markWinding(min, oppWinding, winding);
 | 
| +        }
 | 
| +    }
 | 
| +    return last;
 | 
| +}
 | 
| +
 | 
| +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 @@
 | 
|      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 @@
 | 
|      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 @@
 | 
|      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::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 @@
 | 
|      }
 | 
|      SkASSERT(!span->fDone);
 | 
|      span->fDone = true;
 | 
| -    ++fDoneSpans;
 | 
| +    fDoneSpans++;
 | 
|  }
 | 
|  
 | 
|  void SkOpSegment::markOneDoneUnary(const char* funName, int tIndex) {
 | 
| @@ -4038,52 +3673,46 @@
 | 
|      }
 | 
|      SkASSERT(!span->fDone);
 | 
|      span->fDone = true;
 | 
| -    ++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;
 | 
| +    fDoneSpans++;
 | 
| +}
 | 
| +
 | 
| +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);
 | 
| -#endif
 | 
| -    SkASSERT(span->fWindSum == SK_MinS32 || span->fWindSum == winding);
 | 
| +    debugShowNewWinding(funName, span, winding);
 | 
| +#endif
 | 
| +    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;
 | 
| -}
 | 
| -
 | 
| -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;
 | 
| +    span.fWindSum = winding;
 | 
| +    return &span;
 | 
| +}
 | 
| +
 | 
| +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);
 | 
| -#endif
 | 
| -    SkASSERT(span->fWindSum == SK_MinS32 || span->fWindSum == winding);
 | 
| +    debugShowNewWinding(funName, span, winding, oppWinding);
 | 
| +#endif
 | 
| +    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 @@
 | 
|      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 @@
 | 
|      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;
 | 
| 
 |