diff options
author | caryclark <caryclark@google.com> | 2015-04-29 08:28:30 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-04-29 08:28:30 -0700 |
commit | aec251012542e971100e218bf463adbfb5d21d20 (patch) | |
tree | 16c2e84c2d59d94b75d7d2bc50fec53c0e38a898 | |
parent | 97fdea6c4393cf0102d7eee5790782509fb4f57b (diff) |
minor fixes to cubics code and overall alignment of how bounds and tops are computed for all curve types
All but 17 extended tests work.
A helper function is privately added to SkPath.h to permit a test to modify a given point in a path.
BUG=skia:3588
Review URL: https://codereview.chromium.org/1107353004
33 files changed, 1375 insertions, 653 deletions
diff --git a/gyp/core.gypi b/gyp/core.gypi index 190236f11b..1f062524ae 100644 --- a/gyp/core.gypi +++ b/gyp/core.gypi @@ -350,10 +350,10 @@ '<(skia_src_path)/pathops/SkOpEdgeBuilder.cpp', '<(skia_src_path)/pathops/SkOpSegment.cpp', '<(skia_src_path)/pathops/SkOpSpan.cpp', - '<(skia_src_path)/pathops/SkPathOpsBounds.cpp', '<(skia_src_path)/pathops/SkPathOpsCommon.cpp', '<(skia_src_path)/pathops/SkPathOpsConic.cpp', '<(skia_src_path)/pathops/SkPathOpsCubic.cpp', + '<(skia_src_path)/pathops/SkPathOpsCurve.cpp', '<(skia_src_path)/pathops/SkPathOpsDebug.cpp', '<(skia_src_path)/pathops/SkPathOpsLine.cpp', '<(skia_src_path)/pathops/SkPathOpsOp.cpp', diff --git a/include/core/SkPath.h b/include/core/SkPath.h index b5b95e15e7..c413560102 100644 --- a/include/core/SkPath.h +++ b/include/core/SkPath.h @@ -1034,6 +1034,8 @@ private: ed.setBounds(rect); } + void setPt(int index, SkScalar x, SkScalar y); + friend class SkAutoPathBoundsUpdate; friend class SkAutoDisableOvalCheck; friend class SkAutoDisableDirectionCheck; diff --git a/src/core/SkPath.cpp b/src/core/SkPath.cpp index 45429a6e12..aa99ce4f0e 100644 --- a/src/core/SkPath.cpp +++ b/src/core/SkPath.cpp @@ -631,6 +631,18 @@ bool SkPath::getLastPt(SkPoint* lastPt) const { return false; } +void SkPath::setPt(int index, SkScalar x, SkScalar y) { + SkDEBUGCODE(this->validate();) + + int count = fPathRef->countPoints(); + if (count <= index) { + return; + } else { + SkPathRef::Editor ed(&fPathRef); + ed.atPoint(index)->set(x, y); + } +} + void SkPath::setLastPt(SkScalar x, SkScalar y) { SkDEBUGCODE(this->validate();) diff --git a/src/pathops/SkDCubicLineIntersection.cpp b/src/pathops/SkDCubicLineIntersection.cpp index f5fe01503b..f658b09f0b 100644 --- a/src/pathops/SkDCubicLineIntersection.cpp +++ b/src/pathops/SkDCubicLineIntersection.cpp @@ -135,7 +135,7 @@ public: + (fCubic[n].fX - fLine[0].fX) * adj; } double extremeTs[6]; - int extrema = SkDCubic::FindExtrema(c[0].fX, c[1].fX, c[2].fX, c[3].fX, extremeTs); + int extrema = SkDCubic::FindExtrema(&c[0].fX, extremeTs); count = c.searchRoots(extremeTs, extrema, 0, SkDCubic::kXAxis, roots); break; } @@ -171,7 +171,7 @@ public: SkDPoint calcPt = c.ptAtT(roots[index]); if (!approximately_equal(calcPt.fY, axisIntercept)) { double extremeTs[6]; - int extrema = SkDCubic::FindExtrema(c[0].fY, c[1].fY, c[2].fY, c[3].fY, extremeTs); + int extrema = SkDCubic::FindExtrema(&c[0].fY, extremeTs); count = c.searchRoots(extremeTs, extrema, axisIntercept, SkDCubic::kYAxis, roots); break; } @@ -234,7 +234,7 @@ public: SkDPoint calcPt = c.ptAtT(roots[index]); if (!approximately_equal(calcPt.fX, axisIntercept)) { double extremeTs[6]; - int extrema = SkDCubic::FindExtrema(c[0].fX, c[1].fX, c[2].fX, c[3].fX, extremeTs); + int extrema = SkDCubic::FindExtrema(&c[0].fX, extremeTs); count = c.searchRoots(extremeTs, extrema, axisIntercept, SkDCubic::kXAxis, roots); break; } diff --git a/src/pathops/SkOpContour.cpp b/src/pathops/SkOpContour.cpp index ce9439ac26..107c83169b 100644 --- a/src/pathops/SkOpContour.cpp +++ b/src/pathops/SkOpContour.cpp @@ -69,7 +69,7 @@ void SkOpContour::toPath(SkPathWriter* path) const { path->close(); } -void SkOpContour::topSortableSegment(const SkPoint& topLeft, SkPoint* bestXY, +void SkOpContour::topSortableSegment(const SkDPoint& topLeft, SkDPoint* bestXY, SkOpSegment** topStart) { int segmentCount = fSortedSegments.count(); SkASSERT(segmentCount > 0); @@ -84,7 +84,7 @@ void SkOpContour::topSortableSegment(const SkPoint& topLeft, SkPoint* bestXY, continue; } fDone = false; - SkPoint testXY = testSegment->activeLeftTop(NULL); + SkDPoint testXY = testSegment->activeLeftTop(NULL); if (*topStart) { if (testXY.fY < topLeft.fY) { continue; diff --git a/src/pathops/SkOpContour.h b/src/pathops/SkOpContour.h index 3d26ae84c8..9abf38238b 100644 --- a/src/pathops/SkOpContour.h +++ b/src/pathops/SkOpContour.h @@ -344,7 +344,7 @@ public: } void toPath(SkPathWriter* path) const; - void topSortableSegment(const SkPoint& topLeft, SkPoint* bestXY, SkOpSegment** topStart); + void topSortableSegment(const SkDPoint& topLeft, SkDPoint* bestXY, SkOpSegment** topStart); SkOpSegment* undoneSegment(SkOpSpanBase** startPtr, SkOpSpanBase** endPtr); private: diff --git a/src/pathops/SkOpSegment.cpp b/src/pathops/SkOpSegment.cpp index a571609f53..ce35f846b3 100644 --- a/src/pathops/SkOpSegment.cpp +++ b/src/pathops/SkOpSegment.cpp @@ -102,9 +102,9 @@ SkOpAngle* SkOpSegment::activeAngleOther(SkOpSpanBase* start, SkOpSpanBase** sta return other->activeAngleInner(oSpan, startPtr, endPtr, done, sortable); } -SkPoint SkOpSegment::activeLeftTop(SkOpSpanBase** firstSpan) { +SkDPoint SkOpSegment::activeLeftTop(SkOpSpanBase** firstSpan) { SkASSERT(!done()); - SkPoint topPt = {SK_ScalarMax, SK_ScalarMax}; + 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; @@ -118,10 +118,11 @@ SkPoint SkOpSegment::activeLeftTop(SkOpSpanBase** firstSpan) { *firstSpan = span; } } - if (fVerb != SkPath::kLine_Verb && !lastDone - && fCubicType != SkDCubic::kSplitAtMaxCurvature_SkDCubicType) { + if (fVerb != SkPath::kLine_Verb && !lastDone) { double curveTopT; - SkPoint curveTop = (*CurveTop[fVerb])(fPts, fWeight, lastSpan->t(), span->t(), + 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; @@ -1092,10 +1093,7 @@ SkOpSegment* SkOpSegment::findTop(bool firstPass, SkOpSpanBase** startPtr, SkOpS const 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 (top > bounds.fTop) { top = bounds.fTop; firstAngle = angle; } @@ -1452,7 +1450,12 @@ bool SkOpSegment::monotonicInY(const SkOpSpanBase* start, const SkOpSpanBase* en } SkASSERT(fVerb == SkPath::kCubic_Verb); SkDCubic dst = SkDCubic::SubDivide(fPts, start->t(), end->t()); - return dst.monotonicInY(); + if (dst.monotonicInY()) { + return true; + } + SkDCubic whole; + whole.set(fPts); + return whole.monotonicInY(); } bool SkOpSegment::NextCandidate(SkOpSpanBase* span, SkOpSpanBase** start, @@ -2023,9 +2026,15 @@ bool SkOpSegment::subDivide(const SkOpSpanBase* start, const SkOpSpanBase* end, void SkOpSegment::subDivideBounds(const SkOpSpanBase* start, const SkOpSpanBase* end, SkPathOpsBounds* bounds) const { - SkOpCurve edge; + 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); - (bounds->*SetCurveBounds[fVerb])(edge.fPts, edge.fWeight); + return (edge.*Top[fVerb])(fPts, fWeight, start->t(), end->t(), topT); } void SkOpSegment::undoneSpan(SkOpSpanBase** start, SkOpSpanBase** end) { diff --git a/src/pathops/SkOpSegment.h b/src/pathops/SkOpSegment.h index 1e9e1c44be..a762a66a5a 100644 --- a/src/pathops/SkOpSegment.h +++ b/src/pathops/SkOpSegment.h @@ -41,20 +41,24 @@ public: bool activeOp(int xorMiMask, int xorSuMask, SkOpSpanBase* start, SkOpSpanBase* end, SkPathOp op, int* sumMiWinding, int* sumSuWinding); - SkPoint activeLeftTop(SkOpSpanBase** firstT); + SkDPoint activeLeftTop(SkOpSpanBase** firstT); bool activeWinding(SkOpSpanBase* start, SkOpSpanBase* end); bool activeWinding(SkOpSpanBase* start, SkOpSpanBase* end, int* sumWinding); SkOpSegment* addConic(SkPoint pts[3], SkScalar weight, SkOpContour* parent) { init(pts, weight, parent, SkPath::kConic_Verb); - fBounds.setConicBounds(pts, weight); + SkDCurve curve; + curve.fConic.set(pts, weight); + curve.setConicBounds(pts, weight, 0, 1, &fBounds); return this; } SkOpSegment* addCubic(SkPoint pts[4], SkOpContour* parent) { init(pts, 1, parent, SkPath::kCubic_Verb); - fBounds.setCubicBounds(pts, 1); + SkDCurve curve; + curve.fCubic.set(pts); + curve.setCubicBounds(pts, 1, 0, 1, &fBounds); return this; } @@ -88,7 +92,9 @@ public: SkOpSegment* addQuad(SkPoint pts[3], SkOpContour* parent) { init(pts, 1, parent, SkPath::kQuad_Verb); - fBounds.setQuadBounds(pts, 1); + SkDCurve curve; + curve.fQuad.set(pts); + curve.setQuadBounds(pts, 1, 0, 1, &fBounds); return this; } @@ -362,6 +368,8 @@ public: return start->t() * (1 - mid) + end->t() * mid; } + SkDPoint top(const SkOpSpanBase* start, const SkOpSpanBase* end, double* topT) const; + void undoneSpan(SkOpSpanBase** start, SkOpSpanBase** end); int updateOppWinding(const SkOpSpanBase* start, const SkOpSpanBase* end) const; int updateOppWinding(const SkOpAngle* angle) const; diff --git a/src/pathops/SkPathOpsBounds.cpp b/src/pathops/SkPathOpsBounds.cpp deleted file mode 100644 index ea13e2ed2c..0000000000 --- a/src/pathops/SkPathOpsBounds.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2012 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -#include "SkPathOpsBounds.h" -#include "SkPathOpsConic.h" -#include "SkPathOpsCubic.h" -#include "SkPathOpsLine.h" -#include "SkPathOpsQuad.h" - -void SkPathOpsBounds::setConicBounds(const SkPoint a[3], SkScalar weight) { - SkDConic conic; - conic.set(a, weight); - SkDRect dRect; - dRect.setBounds(conic); - set(SkDoubleToScalar(dRect.fLeft), SkDoubleToScalar(dRect.fTop), - SkDoubleToScalar(dRect.fRight), SkDoubleToScalar(dRect.fBottom)); -} - -void SkPathOpsBounds::setCubicBounds(const SkPoint a[4], SkScalar ) { - SkDCubic cubic; - cubic.set(a); - SkDRect dRect; - dRect.setBounds(cubic); - set(SkDoubleToScalar(dRect.fLeft), SkDoubleToScalar(dRect.fTop), - SkDoubleToScalar(dRect.fRight), SkDoubleToScalar(dRect.fBottom)); -} - -void SkPathOpsBounds::setLineBounds(const SkPoint a[2], SkScalar ) { - setPointBounds(a[0]); - add(a[1]); -} - -void SkPathOpsBounds::setQuadBounds(const SkPoint a[3], SkScalar ) { - SkDQuad quad; - quad.set(a); - SkDRect dRect; - dRect.setBounds(quad); - set(SkDoubleToScalar(dRect.fLeft), SkDoubleToScalar(dRect.fTop), - SkDoubleToScalar(dRect.fRight), SkDoubleToScalar(dRect.fBottom)); -} - -void (SkPathOpsBounds::* const SetCurveBounds[])(const SkPoint[], SkScalar weight) = { - NULL, - &SkPathOpsBounds::setLineBounds, - &SkPathOpsBounds::setQuadBounds, - &SkPathOpsBounds::setConicBounds, - &SkPathOpsBounds::setCubicBounds -}; diff --git a/src/pathops/SkPathOpsBounds.h b/src/pathops/SkPathOpsBounds.h index b65d3bea03..7b9daa3671 100644 --- a/src/pathops/SkPathOpsBounds.h +++ b/src/pathops/SkPathOpsBounds.h @@ -33,11 +33,11 @@ struct SkPathOpsBounds : public SkRect { add(toAdd.fLeft, toAdd.fTop, toAdd.fRight, toAdd.fBottom); } - void add(const SkPoint& pt) { - if (pt.fX < fLeft) fLeft = pt.fX; - if (pt.fY < fTop) fTop = pt.fY; - if (pt.fX > fRight) fRight = pt.fX; - if (pt.fY > fBottom) fBottom = pt.fY; + void add(const SkDPoint& pt) { + if (pt.fX < fLeft) fLeft = SkDoubleToScalar(pt.fX); + if (pt.fY < fTop) fTop = SkDoubleToScalar(pt.fY); + if (pt.fX > fRight) fRight = SkDoubleToScalar(pt.fX); + if (pt.fY > fBottom) fBottom = SkDoubleToScalar(pt.fY); } bool almostContains(const SkPoint& pt) { @@ -55,19 +55,12 @@ struct SkPathOpsBounds : public SkRect { || (fLeft == fRight && fTop == fBottom); } - void setConicBounds(const SkPoint a[3], SkScalar weight); - void setCubicBounds(const SkPoint a[4], SkScalar ); - void setLineBounds(const SkPoint a[2], SkScalar ); - void setQuadBounds(const SkPoint a[3], SkScalar ); - - void setPointBounds(const SkPoint& pt) { - fLeft = fRight = pt.fX; - fTop = fBottom = pt.fY; + void setPointBounds(const SkDPoint& pt) { + fLeft = fRight = SkDoubleToScalar(pt.fX); + fTop = fBottom = SkDoubleToScalar(pt.fY); } typedef SkRect INHERITED; }; -extern void (SkPathOpsBounds::* const SetCurveBounds[])(const SkPoint[], SkScalar weight); - #endif diff --git a/src/pathops/SkPathOpsCommon.cpp b/src/pathops/SkPathOpsCommon.cpp index 3496179e65..05b370a1df 100644 --- a/src/pathops/SkPathOpsCommon.cpp +++ b/src/pathops/SkPathOpsCommon.cpp @@ -205,13 +205,13 @@ void DebugShowActiveSpans(SkTDArray<SkOpContour* >& contourList) { #endif static SkOpSegment* findTopSegment(const SkTDArray<SkOpContour* >& contourList, - bool firstPass, SkOpSpanBase** start, SkOpSpanBase** end, SkPoint* topLeft, + bool firstPass, SkOpSpanBase** start, SkOpSpanBase** end, SkDPoint* topLeft, bool* unsortable, bool* done, SkChunkAlloc* allocator) { SkOpSegment* result; const SkOpSegment* lastTopStart = NULL; SkOpSpanBase* lastStart = NULL, * lastEnd = NULL; do { - SkPoint bestXY = {SK_ScalarMax, SK_ScalarMax}; + SkDPoint bestXY = {SK_ScalarMax, SK_ScalarMax}; int contourCount = contourList.count(); SkOpSegment* topStart = NULL; *done = true; @@ -300,7 +300,7 @@ struct SortableTop2 { // error if local in pre-C++11 SkOpSegment* FindSortableTop(const SkTDArray<SkOpContour* >& contourList, bool firstPass, SkOpAngle::IncludeType angleIncludeType, bool* firstContour, SkOpSpanBase** startPtr, - SkOpSpanBase** endPtr, SkPoint* topLeft, bool* unsortable, bool* done, bool* onlyVertical, + SkOpSpanBase** endPtr, SkDPoint* topLeft, bool* unsortable, bool* done, bool* onlyVertical, SkChunkAlloc* allocator) { SkOpSegment* current = findTopSegment(contourList, firstPass, startPtr, endPtr, topLeft, unsortable, done, allocator); diff --git a/src/pathops/SkPathOpsCommon.h b/src/pathops/SkPathOpsCommon.h index 1bf17919ad..82eb5da215 100644 --- a/src/pathops/SkPathOpsCommon.h +++ b/src/pathops/SkPathOpsCommon.h @@ -19,7 +19,7 @@ SkOpSegment* FindChase(SkTDArray<SkOpSpanBase*>* chase, SkOpSpanBase** startPtr, SkOpSpanBase** endPtr); SkOpSegment* FindSortableTop(const SkTDArray<SkOpContour*>& , bool firstPass, SkOpAngle::IncludeType , bool* firstContour, SkOpSpanBase** index, - SkOpSpanBase** endIndex, SkPoint* topLeft, bool* unsortable, + SkOpSpanBase** endIndex, SkDPoint* topLeft, bool* unsortable, bool* done, bool* onlyVertical, SkChunkAlloc* ); SkOpSegment* FindUndone(SkTDArray<SkOpContour*>& contourList, SkOpSpanBase** startPtr, SkOpSpanBase** endPtr); diff --git a/src/pathops/SkPathOpsConic.cpp b/src/pathops/SkPathOpsConic.cpp index 869a406dce..b9b0cda0d4 100644 --- a/src/pathops/SkPathOpsConic.cpp +++ b/src/pathops/SkPathOpsConic.cpp @@ -111,25 +111,3 @@ SkDPoint SkDConic::subDivide(const SkDPoint& a, const SkDPoint& c, double t1, do *weight = chopped.fWeight; return chopped[1]; } - -SkDPoint SkDConic::top(double startT, double endT, double* topT) const { - SkDConic sub = subDivide(startT, endT); - SkDPoint topPt = sub[0]; - *topT = startT; - if (topPt.fY > sub[2].fY || (topPt.fY == sub[2].fY && topPt.fX > sub[2].fX)) { - *topT = endT; - topPt = sub[2]; - } - if (!between(sub[0].fY, sub[1].fY, sub[2].fY)) { - double extremeT; - if (FindExtrema(&sub[0].fY, sub.fWeight, &extremeT)) { - extremeT = startT + (endT - startT) * extremeT; - SkDPoint test = ptAtT(extremeT); - if (topPt.fY > test.fY || (topPt.fY == test.fY && topPt.fX > test.fX)) { - *topT = extremeT; - topPt = test; - } - } - } - return topPt; -} diff --git a/src/pathops/SkPathOpsConic.h b/src/pathops/SkPathOpsConic.h index 8251901554..bc73049c46 100644 --- a/src/pathops/SkPathOpsConic.h +++ b/src/pathops/SkPathOpsConic.h @@ -72,6 +72,10 @@ struct SkDConic { return fPts.isLinear(startIndex, endIndex); } + bool monotonicInX() const { + return fPts.monotonicInX(); + } + bool monotonicInY() const { return fPts.monotonicInY(); } @@ -109,8 +113,6 @@ struct SkDConic { return conic.subDivide(a, c, t1, t2, newWeight); } - SkDPoint top(double startT, double endT, double* topT) const; - // utilities callable by the user from the debugger when the implementation code is linked in void dump() const; void dumpID(int id) const; diff --git a/src/pathops/SkPathOpsCubic.cpp b/src/pathops/SkPathOpsCubic.cpp index 63f828fb22..777298b297 100644 --- a/src/pathops/SkPathOpsCubic.cpp +++ b/src/pathops/SkPathOpsCubic.cpp @@ -75,7 +75,7 @@ double SkDCubic::calcPrecision() const { return (width > height ? width : height) / gPrecisionUnit; } -bool SkDCubic::clockwise(bool* swap) const { +bool SkDCubic::clockwise(const SkDCubic& whole, bool* swap) const { SkDPoint lastPt = fPts[kPointLast]; SkDPoint firstPt = fPts[0]; double sum = 0; @@ -105,34 +105,15 @@ bool SkDCubic::clockwise(bool* swap) const { lastPt = firstPt; firstPt = idx == 1 ? fPts[furthest] : fPts[kPointLast]; } - *swap = sum > 0 && !this->monotonicInY(); + *swap = sum > 0 && !this->monotonicInY() && !whole.monotonicInY(); return sum <= 0; } bool SkDCubic::Clockwise(const SkPoint* pts, double startT, double endT, bool* swap) { SkDCubic cubic; cubic.set(pts); -#if 0 - bool flip = startT > endT; - double inflectionTs[2]; - int inflections = cubic.findInflections(inflectionTs); - for (int index = 0; index < inflections; ++index) { - double inflectionT = inflectionTs[index]; - if (between(startT, inflectionT, endT)) { - if (flip) { - if (!roughly_equal(inflectionT, endT)) { - startT = inflectionT; - } - } else { - if (!roughly_equal(inflectionT, startT)) { - endT = inflectionT; - } - } - } - } -#endif SkDCubic part = cubic.subDivide(startT, endT); - return part.clockwise(swap); + return part.clockwise(cubic, swap); } void SkDCubic::Coefficients(const double* src, double* A, double* B, double* C, double* D) { @@ -301,9 +282,14 @@ bool SkDCubic::ComplexBreak(const SkPoint pointsPtr[4], SkScalar* t, CubicType* return false; } +bool SkDCubic::monotonicInX() const { + return precisely_between(fPts[0].fX, fPts[1].fX, fPts[3].fX) + && precisely_between(fPts[0].fX, fPts[2].fX, fPts[3].fX); +} + bool SkDCubic::monotonicInY() const { - return between(fPts[0].fY, fPts[1].fY, fPts[3].fY) - && between(fPts[0].fY, fPts[2].fY, fPts[3].fY); + return precisely_between(fPts[0].fY, fPts[1].fY, fPts[3].fY) + && precisely_between(fPts[0].fY, fPts[2].fY, fPts[3].fY); } void SkDCubic::otherPts(int index, const SkDPoint* o1Pts[kPointCount - 1]) const { @@ -343,6 +329,28 @@ int SkDCubic::RootsValidT(double A, double B, double C, double D, double t[3]) { double s[3]; int realRoots = RootsReal(A, B, C, D, s); int foundRoots = SkDQuad::AddValidTs(s, realRoots, t); + for (int index = 0; index < realRoots; ++index) { + double tValue = s[index]; + if (!approximately_one_or_less(tValue) && between(1, tValue, 1.00005)) { + for (int idx2 = 0; idx2 < foundRoots; ++idx2) { + if (approximately_equal(t[idx2], 1)) { + goto nextRoot; + } + } + SkASSERT(foundRoots < 3); + t[foundRoots++] = 1; + } else if (!approximately_zero_or_more(tValue) && between(-0.00005, tValue, 0)) { + for (int idx2 = 0; idx2 < foundRoots; ++idx2) { + if (approximately_equal(t[idx2], 0)) { + goto nextRoot; + } + } + SkASSERT(foundRoots < 3); + t[foundRoots++] = 0; + } +nextRoot: + ; + } return foundRoots; } @@ -487,10 +495,14 @@ static void formulate_F1DotF2(const double src[], double coeff[4]) { C = 3(b - a) Solve for t, keeping only those that fit between 0 < t < 1 */ -int SkDCubic::FindExtrema(double a, double b, double c, double d, double tValues[2]) { +int SkDCubic::FindExtrema(const double src[], double tValues[2]) { // we divide A,B,C by 3 to simplify - double A = d - a + 3*(b - c); - double B = 2*(a - b - b + c); + double a = src[0]; + double b = src[2]; + double c = src[4]; + double d = src[6]; + double A = d - a + 3 * (b - c); + double B = 2 * (a - b - b + c); double C = b - a; return SkDQuad::RootsValidT(A, B, C, tValues); @@ -519,29 +531,6 @@ int SkDCubic::findMaxCurvature(double tValues[]) const { return RootsValidT(coeffX[0], coeffX[1], coeffX[2], coeffX[3], tValues); } -SkDPoint SkDCubic::top(double startT, double endT, double* topT) const { - SkDCubic sub = subDivide(startT, endT); - SkDPoint topPt = sub[0]; - *topT = startT; - if (topPt.fY > sub[3].fY || (topPt.fY == sub[3].fY && topPt.fX > sub[3].fX)) { - *topT = endT; - topPt = sub[3]; - } - double extremeTs[2]; - if (!sub.monotonicInY()) { - int roots = FindExtrema(sub[0].fY, sub[1].fY, sub[2].fY, sub[3].fY, extremeTs); - for (int index = 0; index < roots; ++index) { - double t = startT + (endT - startT) * extremeTs[index]; - SkDPoint mid = ptAtT(t); - if (topPt.fY > mid.fY || (topPt.fY == mid.fY && topPt.fX > mid.fX)) { - *topT = t; - topPt = mid; - } - } - } - return topPt; -} - SkDPoint SkDCubic::ptAtT(double t) const { if (0 == t) { return fPts[0]; diff --git a/src/pathops/SkPathOpsCubic.h b/src/pathops/SkPathOpsCubic.h index 269073ca69..f9d291056e 100644 --- a/src/pathops/SkPathOpsCubic.h +++ b/src/pathops/SkPathOpsCubic.h @@ -57,7 +57,7 @@ struct SkDCubic { double binarySearch(double min, double max, double axisIntercept, SearchAxis xAxis) const; double calcPrecision() const; SkDCubicPair chopAt(double t) const; - bool clockwise(bool* swap) const; + bool clockwise(const SkDCubic& whole, bool* swap) const; static bool Clockwise(const SkPoint* pts, double startT, double endT, bool* swap); static void Coefficients(const double* cubic, double* A, double* B, double* C, double* D); static bool ComplexBreak(const SkPoint pts[4], SkScalar* t, CubicType* cubicType); @@ -72,7 +72,7 @@ struct SkDCubic { void dumpInner() const; SkDVector dxdyAtT(double t) const; bool endsAreExtremaInXOrY() const; - static int FindExtrema(double a, double b, double c, double d, double tValue[2]); + static int FindExtrema(const double src[], double tValue[2]); int findInflections(double tValues[2]) const; static int FindInflections(const SkPoint a[kPointCount], double tValues[2]) { @@ -87,6 +87,7 @@ struct SkDCubic { bool hullIntersects(const SkDQuad& c2, bool* isLinear) const; bool hullIntersects(const SkDPoint* pts, int ptCount, bool* isLinear) const; bool isLinear(int startIndex, int endIndex) const; + bool monotonicInX() const; bool monotonicInY() const; void otherPts(int index, const SkDPoint* o1Pts[kPointCount - 1]) const; SkDPoint ptAtT(double t) const; @@ -121,7 +122,6 @@ struct SkDCubic { cubic.subDivide(a, d, t1, t2, p); } - SkDPoint top(double startT, double endT, double* topT) const; SkDQuad toQuad() const; static const int gPrecisionUnit; diff --git a/src/pathops/SkPathOpsCurve.cpp b/src/pathops/SkPathOpsCurve.cpp new file mode 100644 index 0000000000..651e64a908 --- /dev/null +++ b/src/pathops/SkPathOpsCurve.cpp @@ -0,0 +1,146 @@ +/* + * Copyright 2015 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#include "SkPathOpsBounds.h" +#include "SkPathOpsRect.h" +#include "SkPathOpsCurve.h" + +SkDPoint SkDCurve::conicTop(const SkPoint curve[3], SkScalar curveWeight, + double startT, double endT, double* topT) { + SkDPoint topPt = fConic[0]; + *topT = startT; + if (topPt.fY > fConic[2].fY || (topPt.fY == fConic[2].fY && topPt.fX > fConic[2].fX)) { + *topT = endT; + topPt = fConic[2]; + } + if (!fConic.monotonicInY()) { + double extremeT; + if (SkDConic::FindExtrema(&fConic.fPts.fPts[0].fY, fConic.fWeight, &extremeT)) { + SkDConic dCurve; + dCurve.set(curve, curveWeight); + extremeT = startT + (endT - startT) * extremeT; + SkDPoint test = dCurve.ptAtT(extremeT); + if (topPt.fY > test.fY || (topPt.fY == test.fY && topPt.fX > test.fX)) { + *topT = extremeT; + topPt = test; + } + } + } + return topPt; +} + +SkDPoint SkDCurve::cubicTop(const SkPoint curve[4], SkScalar , + double startT, double endT, double* topT) { + SkDPoint topPt = fCubic[0]; + *topT = startT; + if (topPt.fY > fCubic[3].fY || (topPt.fY == fCubic[3].fY && topPt.fX > fCubic[3].fX)) { + *topT = endT; + topPt = fCubic[3]; + } + double extremeTs[2]; + if (!fCubic.monotonicInY()) { + int roots = SkDCubic::FindExtrema(&fCubic.fPts[0].fY, extremeTs); + SkDCubic dCurve; + dCurve.set(curve); + for (int index = 0; index < roots; ++index) { + double t = startT + (endT - startT) * extremeTs[index]; + SkDPoint mid = dCurve.ptAtT(t); + if (topPt.fY > mid.fY || (topPt.fY == mid.fY && topPt.fX > mid.fX)) { + *topT = t; + topPt = mid; + } + } + } + return topPt; +} + +SkDPoint SkDCurve::lineTop(const SkPoint[2], SkScalar , double startT, double endT, double* topT) { + SkDPoint topPt = fLine[0]; + *topT = startT; + if (topPt.fY > fLine[1].fY || (topPt.fY == fLine[1].fY && topPt.fX > fLine[1].fX)) { + *topT = endT; + topPt = fLine[1]; + } + return topPt; +} + +SkDPoint SkDCurve::quadTop(const SkPoint curve[3], SkScalar , + double startT, double endT, double* topT) { + SkDPoint topPt = fQuad[0]; + *topT = startT; + if (topPt.fY > fQuad[2].fY || (topPt.fY == fQuad[2].fY && topPt.fX > fQuad[2].fX)) { + *topT = endT; + topPt = fQuad[2]; + } + if (!fQuad.monotonicInY()) { + double extremeT; + if (SkDQuad::FindExtrema(&fQuad.fPts[0].fY, &extremeT)) { + SkDQuad dCurve; + dCurve.set(curve); + extremeT = startT + (endT - startT) * extremeT; + SkDPoint test = dCurve.ptAtT(extremeT); + if (topPt.fY > test.fY || (topPt.fY == test.fY && topPt.fX > test.fX)) { + *topT = extremeT; + topPt = test; + } + } + } + return topPt; +} + +SkDPoint (SkDCurve::* const Top[])(const SkPoint curve[], SkScalar curveWeight, + double tStart, double tEnd, double* topT) = { + NULL, + &SkDCurve::lineTop, + &SkDCurve::quadTop, + &SkDCurve::conicTop, + &SkDCurve::cubicTop +}; + +void SkDCurve::setConicBounds(const SkPoint curve[3], SkScalar curveWeight, + double tStart, double tEnd, SkPathOpsBounds* bounds) { + SkDConic dCurve; + dCurve.set(curve, curveWeight); + SkDRect dRect; + dRect.setBounds(dCurve, fConic, tStart, tEnd); + bounds->set(SkDoubleToScalar(dRect.fLeft), SkDoubleToScalar(dRect.fTop), + SkDoubleToScalar(dRect.fRight), SkDoubleToScalar(dRect.fBottom)); +} + +void SkDCurve::setCubicBounds(const SkPoint curve[4], SkScalar , + double tStart, double tEnd, SkPathOpsBounds* bounds) { + SkDCubic dCurve; + dCurve.set(curve); + SkDRect dRect; + dRect.setBounds(dCurve, fCubic, tStart, tEnd); + bounds->set(SkDoubleToScalar(dRect.fLeft), SkDoubleToScalar(dRect.fTop), + SkDoubleToScalar(dRect.fRight), SkDoubleToScalar(dRect.fBottom)); +} + +void SkDCurve::setLineBounds(const SkPoint[2], SkScalar , + double , double , SkPathOpsBounds* bounds) { + bounds->setPointBounds(fLine[0]); + bounds->add(fLine[1]); +} + +void SkDCurve::setQuadBounds(const SkPoint curve[3], SkScalar , + double tStart, double tEnd, SkPathOpsBounds* bounds) { + SkDQuad dCurve; + dCurve.set(curve); + SkDRect dRect; + dRect.setBounds(dCurve, fQuad, tStart, tEnd); + bounds->set(SkDoubleToScalar(dRect.fLeft), SkDoubleToScalar(dRect.fTop), + SkDoubleToScalar(dRect.fRight), SkDoubleToScalar(dRect.fBottom)); +} + +void (SkDCurve::* const SetBounds[])(const SkPoint curve[], SkScalar curveWeight, + double tStart, double tEnd, SkPathOpsBounds* bounds) = { + NULL, + &SkDCurve::setLineBounds, + &SkDCurve::setQuadBounds, + &SkDCurve::setConicBounds, + &SkDCurve::setCubicBounds +}; diff --git a/src/pathops/SkPathOpsCurve.h b/src/pathops/SkPathOpsCurve.h index 69af91cf34..bfbc515719 100644 --- a/src/pathops/SkPathOpsCurve.h +++ b/src/pathops/SkPathOpsCurve.h @@ -16,6 +16,8 @@ #include "SkPath.h" #endif +struct SkPathOpsBounds; + struct SkOpCurve { SkPoint fPts[4]; SkScalar fWeight; @@ -43,6 +45,7 @@ struct SkOpCurve { SkDEBUGCODE(fWeight = 1); SkDEBUGCODE(fVerb = SkPath::kCubic_Verb); } + }; struct SkDCurve { @@ -64,9 +67,29 @@ struct SkDCurve { return fCubic[n]; } + SkDPoint conicTop(const SkPoint curve[3], SkScalar curveWeight, + double s, double e, double* topT); + SkDPoint cubicTop(const SkPoint curve[4], SkScalar , double s, double e, double* topT); void dumpID(int ) const; + SkDPoint lineTop(const SkPoint[2], SkScalar , double , double , double* topT); + SkDPoint quadTop(const SkPoint curve[3], SkScalar , double s, double e, double* topT); + + void setConicBounds(const SkPoint curve[3], SkScalar curveWeight, + double s, double e, SkPathOpsBounds* ); + void setCubicBounds(const SkPoint curve[4], SkScalar , + double s, double e, SkPathOpsBounds* ); + void setLineBounds(const SkPoint[2], SkScalar , double , double , SkPathOpsBounds* ); + void setQuadBounds(const SkPoint curve[3], SkScalar , + double s, double e, SkPathOpsBounds*); }; + +extern void (SkDCurve::* const SetBounds[])(const SkPoint curve[], SkScalar cWeight, + double tStart, double tEnd, SkPathOpsBounds* ); + +extern SkDPoint (SkDCurve::* const Top[])(const SkPoint curve[], SkScalar cWeight, + double tStart, double tEnd, double* topT); + static SkDPoint dline_xy_at_t(const SkPoint a[2], SkScalar , double t) { SkDLine line; line.set(a); @@ -179,36 +202,6 @@ static SkVector (* const CurveSlopeAtT[])(const SkPoint[], SkScalar , double ) = fcubic_dxdy_at_t }; -static SkPoint quad_top(const SkPoint a[3], SkScalar , double startT, double endT, double* topT) { - SkDQuad quad; - quad.set(a); - SkDPoint topPt = quad.top(startT, endT, topT); - return topPt.asSkPoint(); -} - -static SkPoint conic_top(const SkPoint a[3], SkScalar weight, double startT, double endT, - double* topT) { - SkDConic conic; - conic.set(a, weight); - SkDPoint topPt = conic.top(startT, endT, topT); - return topPt.asSkPoint(); -} - -static SkPoint cubic_top(const SkPoint a[4], SkScalar , double startT, double endT, double* topT) { - SkDCubic cubic; - cubic.set(a); - SkDPoint topPt = cubic.top(startT, endT, topT); - return topPt.asSkPoint(); -} - -static SkPoint (* const CurveTop[])(const SkPoint[], SkScalar , double , double , double* ) = { - NULL, - NULL, - quad_top, - conic_top, - cubic_top -}; - static bool line_is_vertical(const SkPoint a[2], SkScalar , double startT, double endT) { SkDLine line; line.set(a); diff --git a/src/pathops/SkPathOpsDebug.h b/src/pathops/SkPathOpsDebug.h index 8473d66c70..0624ad687a 100644 --- a/src/pathops/SkPathOpsDebug.h +++ b/src/pathops/SkPathOpsDebug.h @@ -37,8 +37,6 @@ #if FORCE_RELEASE -#define DEBUG_CUBIC_SWAP_TOP 0 - #define DEBUG_ACTIVE_OP 0 #define DEBUG_ACTIVE_SPANS 0 #define DEBUG_ADD_INTERSECTING_TS 0 @@ -47,23 +45,21 @@ #define DEBUG_ASSEMBLE 0 #define DEBUG_CUBIC_BINARY_SEARCH 0 #define DEBUG_CUBIC_SPLIT 0 -#define DEBUG_DUMP_SEGMENTS DEBUG_CUBIC_SWAP_TOP +#define DEBUG_DUMP_SEGMENTS 0 // 1 #define DEBUG_FLOW 0 #define DEBUG_LIMIT_WIND_SUM 0 #define DEBUG_MARK_DONE 0 #define DEBUG_PATH_CONSTRUCTION 0 #define DEBUG_PERP 0 -#define DEBUG_SHOW_TEST_NAME DEBUG_CUBIC_SWAP_TOP +#define DEBUG_SHOW_TEST_NAME 0 // 1 #define DEBUG_SORT 0 -#define DEBUG_SWAP_TOP DEBUG_CUBIC_SWAP_TOP +#define DEBUG_SWAP_TOP 0 // 1 #define DEBUG_T_SECT 0 #define DEBUG_T_SECT_DUMP 0 #define DEBUG_VALIDATE 0 #define DEBUG_WINDING 0 #define DEBUG_WINDING_AT_T 0 -#undef DEBUG_CUBIC_SWAP_TOP - #else #define DEBUG_ACTIVE_OP 1 diff --git a/src/pathops/SkPathOpsOp.cpp b/src/pathops/SkPathOpsOp.cpp index 4e3ec4aad3..1105af5d70 100644 --- a/src/pathops/SkPathOpsOp.cpp +++ b/src/pathops/SkPathOpsOp.cpp @@ -104,8 +104,8 @@ static bool bridgeOp(SkTDArray<SkOpContour* >& contourList, const SkPathOp op, bool unsortable = false; bool topUnsortable = false; bool firstPass = true; - SkPoint lastTopLeft; - SkPoint topLeft = {SK_ScalarMin, SK_ScalarMin}; + SkDPoint lastTopLeft; + SkDPoint topLeft = {SK_ScalarMin, SK_ScalarMin}; do { SkOpSpanBase* start = NULL; SkOpSpanBase* end = NULL; diff --git a/src/pathops/SkPathOpsQuad.cpp b/src/pathops/SkPathOpsQuad.cpp index 397a3ce98a..66f191bb0e 100644 --- a/src/pathops/SkPathOpsQuad.cpp +++ b/src/pathops/SkPathOpsQuad.cpp @@ -240,6 +240,10 @@ static double interp_quad_coords(const double* src, double t) { return abc; } +bool SkDQuad::monotonicInX() const { + return between(fPts[0].fX, fPts[1].fX, fPts[2].fX); +} + bool SkDQuad::monotonicInY() const { return between(fPts[0].fY, fPts[1].fY, fPts[2].fY); } @@ -323,28 +327,6 @@ SkDPoint SkDQuad::subDivide(const SkDPoint& a, const SkDPoint& c, double t1, dou return b; } -SkDPoint SkDQuad::top(double startT, double endT, double* topT) const { - SkDQuad sub = subDivide(startT, endT); - SkDPoint topPt = sub[0]; - *topT = startT; - if (topPt.fY > sub[2].fY || (topPt.fY == sub[2].fY && topPt.fX > sub[2].fX)) { - *topT = endT; - topPt = sub[2]; - } - if (!between(sub[0].fY, sub[1].fY, sub[2].fY)) { - double extremeT; - if (FindExtrema(sub[0].fY, sub[1].fY, sub[2].fY, &extremeT)) { - extremeT = startT + (endT - startT) * extremeT; - SkDPoint test = ptAtT(extremeT); - if (topPt.fY > test.fY || (topPt.fY == test.fY && topPt.fX > test.fX)) { - *topT = extremeT; - topPt = test; - } - } - } - return topPt; -} - /* classic one t subdivision */ static void interp_quad_coords(const double* src, double* dst, double t) { double ab = SkDInterp(src[0], src[2], t); @@ -397,10 +379,13 @@ static int valid_unit_divide(double numer, double denom, double* ratio) B = 2(b - a) Solve for t, only if it fits between 0 < t < 1 */ -int SkDQuad::FindExtrema(double a, double b, double c, double tValue[1]) { +int SkDQuad::FindExtrema(const double src[], double tValue[1]) { /* At + B == 0 t = -B / A */ + double a = src[0]; + double b = src[2]; + double c = src[4]; return valid_unit_divide(a - b, a - b - b + c, tValue); } diff --git a/src/pathops/SkPathOpsQuad.h b/src/pathops/SkPathOpsQuad.h index b201860f98..de4ce4baa3 100644 --- a/src/pathops/SkPathOpsQuad.h +++ b/src/pathops/SkPathOpsQuad.h @@ -62,11 +62,12 @@ struct SkDQuad { SkDQuadPair chopAt(double t) const; static bool Clockwise(const SkOpCurve& edge, bool* swap); SkDVector dxdyAtT(double t) const; - static int FindExtrema(double a, double b, double c, double tValue[1]); + static int FindExtrema(const double src[], double tValue[1]); bool hullIntersects(const SkDQuad& , bool* isLinear) const; bool hullIntersects(const SkDConic& , bool* isLinear) const; bool hullIntersects(const SkDCubic& , bool* isLinear) const; bool isLinear(int startIndex, int endIndex) const; + bool monotonicInX() const; bool monotonicInY() const; double nearestT(const SkDPoint&) const; void otherPts(int oddMan, const SkDPoint* endPt[2]) const; @@ -89,7 +90,6 @@ struct SkDQuad { } SkDConic toConic() const; SkDCubic toCubic() const; - SkDPoint top(double startT, double endT, double* topT) const; // utilities callable by the user from the debugger when the implementation code is linked in void dump() const; diff --git a/src/pathops/SkPathOpsRect.cpp b/src/pathops/SkPathOpsRect.cpp index 540db16a0e..8c01153532 100644 --- a/src/pathops/SkPathOpsRect.cpp +++ b/src/pathops/SkPathOpsRect.cpp @@ -10,54 +10,53 @@ #include "SkPathOpsQuad.h" #include "SkPathOpsRect.h" -void SkDRect::setBounds(const SkDQuad& quad) { - set(quad[0]); - add(quad[2]); +void SkDRect::setBounds(const SkDQuad& curve, const SkDQuad& sub, double startT, double endT) { + set(sub[0]); + add(sub[2]); double tValues[2]; int roots = 0; - if (!between(quad[0].fX, quad[1].fX, quad[2].fX)) { - roots = SkDQuad::FindExtrema(quad[0].fX, quad[1].fX, quad[2].fX, tValues); + if (!sub.monotonicInX()) { + roots = SkDQuad::FindExtrema(&sub[0].fX, tValues); } - if (!between(quad[0].fY, quad[1].fY, quad[2].fY)) { - roots += SkDQuad::FindExtrema(quad[0].fY, quad[1].fY, quad[2].fY, &tValues[roots]); + if (!sub.monotonicInY()) { + roots += SkDQuad::FindExtrema(&sub[0].fY, &tValues[roots]); } - for (int x = 0; x < roots; ++x) { - add(quad.ptAtT(tValues[x])); + for (int index = 0; index < roots; ++index) { + double t = startT + (endT - startT) * tValues[index]; + add(curve.ptAtT(t)); } } -void SkDRect::setBounds(const SkDConic& conic) { - set(conic[0]); - add(conic[2]); +void SkDRect::setBounds(const SkDConic& curve, const SkDConic& sub, double startT, double endT) { + set(sub[0]); + add(sub[2]); double tValues[2]; int roots = 0; - if (!between(conic[0].fX, conic[1].fX, conic[2].fX)) { - roots = SkDConic::FindExtrema(&conic[0].fX, conic.fWeight, tValues); + if (!sub.monotonicInX()) { + roots = SkDConic::FindExtrema(&sub[0].fX, sub.fWeight, tValues); } - if (!between(conic[0].fY, conic[1].fY, conic[2].fY)) { - roots += SkDConic::FindExtrema(&conic[0].fY, conic.fWeight, &tValues[roots]); + if (!sub.monotonicInY()) { + roots += SkDConic::FindExtrema(&sub[0].fY, sub.fWeight, &tValues[roots]); } - for (int x = 0; x < roots; ++x) { - add(conic.ptAtT(tValues[x])); + for (int index = 0; index < roots; ++index) { + double t = startT + (endT - startT) * tValues[index]; + add(curve.ptAtT(t)); } } -static bool is_bounded_by_end_points(double a, double b, double c, double d) { - return between(a, b, d) && between(a, c, d); -} - -void SkDRect::setBounds(const SkDCubic& c) { - set(c[0]); - add(c[3]); +void SkDRect::setBounds(const SkDCubic& curve, const SkDCubic& sub, double startT, double endT) { + set(sub[0]); + add(sub[3]); double tValues[4]; int roots = 0; - if (!is_bounded_by_end_points(c[0].fX, c[1].fX, c[2].fX, c[3].fX)) { - roots = SkDCubic::FindExtrema(c[0].fX, c[1].fX, c[2].fX, c[3].fX, tValues); + if (!sub.monotonicInX()) { + roots = SkDCubic::FindExtrema(&sub[0].fX, tValues); } - if (!is_bounded_by_end_points(c[0].fY, c[1].fY, c[2].fY, c[3].fY)) { - roots += SkDCubic::FindExtrema(c[0].fY, c[1].fY, c[2].fY, c[3].fY, &tValues[roots]); + if (!sub.monotonicInY()) { + roots += SkDCubic::FindExtrema(&sub[0].fY, &tValues[roots]); } - for (int x = 0; x < roots; ++x) { - add(c.ptAtT(tValues[x])); + for (int index = 0; index < roots; ++index) { + double t = startT + (endT - startT) * tValues[index]; + add(curve.ptAtT(t)); } } diff --git a/src/pathops/SkPathOpsRect.h b/src/pathops/SkPathOpsRect.h index f783d96b99..7fec70a32a 100644 --- a/src/pathops/SkPathOpsRect.h +++ b/src/pathops/SkPathOpsRect.h @@ -48,9 +48,23 @@ struct SkDRect { return fBottom - fTop; } - void setBounds(const SkDConic&); - void setBounds(const SkDCubic&); - void setBounds(const SkDQuad&); + void setBounds(const SkDConic& curve) { + setBounds(curve, curve, 0, 1); + } + + void setBounds(const SkDConic& curve, const SkDConic& sub, double tStart, double tEnd); + + void setBounds(const SkDCubic& curve) { + setBounds(curve, curve, 0, 1); + } + + void setBounds(const SkDCubic& curve, const SkDCubic& sub, double tStart, double tEnd); + + void setBounds(const SkDQuad& curve) { + setBounds(curve, curve, 0, 1); + } + + void setBounds(const SkDQuad& curve, const SkDQuad& sub, double tStart, double tEnd); }; #endif diff --git a/src/pathops/SkPathOpsSimplify.cpp b/src/pathops/SkPathOpsSimplify.cpp index b4f8e22142..14c6837c1b 100644 --- a/src/pathops/SkPathOpsSimplify.cpp +++ b/src/pathops/SkPathOpsSimplify.cpp @@ -16,8 +16,8 @@ static bool bridgeWinding(SkTDArray<SkOpContour* >& contourList, SkPathWriter* s bool unsortable = false; bool topUnsortable = false; bool firstPass = true; - SkPoint lastTopLeft; - SkPoint topLeft = {SK_ScalarMin, SK_ScalarMin}; + SkDPoint lastTopLeft; + SkDPoint topLeft = {SK_ScalarMin, SK_ScalarMin}; do { SkOpSpanBase* start = NULL; SkOpSpanBase* end = NULL; diff --git a/tests/PathOpsBoundsTest.cpp b/tests/PathOpsBoundsTest.cpp index 1160ae66c1..0c74b69b12 100644 --- a/tests/PathOpsBoundsTest.cpp +++ b/tests/PathOpsBoundsTest.cpp @@ -6,6 +6,7 @@ */ #include "PathOpsTestCommon.h" #include "SkPathOpsBounds.h" +#include "SkPathOpsCurve.h" #include "Test.h" static const SkRect sectTests[][2] = { @@ -74,9 +75,9 @@ DEF_TEST(PathOpsBounds, reporter) { ordinal.set(1, 2, 3, 4); bounds.add(ordinal); REPORTER_ASSERT(reporter, bounds == expected); - SkPoint topLeft = {0, 0}; + SkDPoint topLeft = {0, 0}; bounds.setPointBounds(topLeft); - SkPoint botRight = {3, 4}; + SkDPoint botRight = {3, 4}; bounds.add(botRight); REPORTER_ASSERT(reporter, bounds == expected); for (size_t index = 0; index < emptyTestsCount; ++index) { @@ -92,19 +93,23 @@ DEF_TEST(PathOpsBounds, reporter) { REPORTER_ASSERT(reporter, !empty); } const SkPoint curvePts[] = {{0, 0}, {1, 2}, {3, 4}, {5, 6}}; - bounds.setLineBounds(curvePts, 1); + SkDCurve curve; + curve.fLine.set(curvePts); + curve.setLineBounds(curvePts, 1, 0, 1, &bounds); expected.set(0, 0, 1, 2); REPORTER_ASSERT(reporter, bounds == expected); - (bounds.*SetCurveBounds[SkPath::kLine_Verb])(curvePts, 1); + (curve.*SetBounds[SkPath::kLine_Verb])(curvePts, 1, 0, 1, &bounds); REPORTER_ASSERT(reporter, bounds == expected); - bounds.setQuadBounds(curvePts, 1); + curve.fQuad.set(curvePts); + curve.setQuadBounds(curvePts, 1, 0, 1, &bounds); expected.set(0, 0, 3, 4); REPORTER_ASSERT(reporter, bounds == expected); - (bounds.*SetCurveBounds[SkPath::kQuad_Verb])(curvePts, 1); + (curve.*SetBounds[SkPath::kQuad_Verb])(curvePts, 1, 0, 1, &bounds); REPORTER_ASSERT(reporter, bounds == expected); - bounds.setCubicBounds(curvePts, 1); + curve.fCubic.set(curvePts); + curve.setCubicBounds(curvePts, 1, 0, 1, &bounds); expected.set(0, 0, 5, 6); REPORTER_ASSERT(reporter, bounds == expected); - (bounds.*SetCurveBounds[SkPath::kCubic_Verb])(curvePts, 1); + (curve.*SetBounds[SkPath::kCubic_Verb])(curvePts, 1, 0, 1, &bounds); REPORTER_ASSERT(reporter, bounds == expected); } diff --git a/tests/PathOpsCubicLineIntersectionTest.cpp b/tests/PathOpsCubicLineIntersectionTest.cpp index 6fdce3cb18..a1f1d9f4f2 100644 --- a/tests/PathOpsCubicLineIntersectionTest.cpp +++ b/tests/PathOpsCubicLineIntersectionTest.cpp @@ -49,6 +49,9 @@ static void testFail(skiatest::Reporter* reporter, int iIndex) { } static lineCubic lineCubicTests[] = { + {{{{0, 6}, {1.0851458311080933, 4.3722810745239258}, {1.5815209150314331, 3.038947582244873}, {1.9683018922805786, 1.9999997615814209}}}, + {{{3,2}, {1,2}}}}, + {{{{0.468027353,4}, {1.06734705,1.33333337}, {1.36700678,0}, {3,0}}}, {{{2,1}, {0,1}}}}, diff --git a/tests/PathOpsDCubicTest.cpp b/tests/PathOpsDCubicTest.cpp index c7c9f2ab96..b5fe8f744b 100644 --- a/tests/PathOpsDCubicTest.cpp +++ b/tests/PathOpsDCubicTest.cpp @@ -21,7 +21,7 @@ DEF_TEST(PathOpsDCubic, reporter) { const SkDCubic& cubic = tests[index]; SkASSERT(ValidCubic(cubic)); bool skip; - bool result = cubic.clockwise(&skip); + bool result = cubic.clockwise(cubic, &skip); if (!result) { SkDebugf("%s [%d] expected clockwise\n", __FUNCTION__, index); REPORTER_ASSERT(reporter, 0); diff --git a/tests/PathOpsExtendedTest.cpp b/tests/PathOpsExtendedTest.cpp index 92b0e87465..9c57797987 100644 --- a/tests/PathOpsExtendedTest.cpp +++ b/tests/PathOpsExtendedTest.cpp @@ -289,7 +289,7 @@ int comparePaths(skiatest::Reporter* reporter, const char* filename, const SkPat return errors2x2 > MAX_ERRORS ? errors2x2 : 0; } -const int gTestFirst = 20; +const int gTestFirst = 41; static int gTestNo = gTestFirst; static SkTDArray<SkPathOp> gTestOp; @@ -309,7 +309,7 @@ static void showPathOpPath(const char* testName, const SkPath& one, const SkPath SkPathOpsDebug::ShowOnePath(b, "pathB", false); SkDebugf(" testPathOp(reporter, path, pathB, %s, filename);\n", opStrs[shapeOp]); SkDebugf("}\n"); - drawAsciiPaths(scaledOne, scaledTwo, true); + drawAsciiPaths(scaledOne, scaledTwo, false); } void ShowTestArray(const char* testName) { @@ -341,9 +341,10 @@ static int comparePaths(skiatest::Reporter* reporter, const char* testName, cons } if (errors2x2 > MAX_ERRORS) { SkAutoMutexAcquire autoM(compareDebugOut3); - SkDebugf("\n*** this test fails ***\n"); showPathOpPath(testName, one, two, a, b, scaledOne, scaledTwo, shapeOp, scale); + SkDebugf("\n/*"); REPORTER_ASSERT(reporter, 0); + SkDebugf(" */\n"); } else if (errors2x2 == MAX_ERRORS || errors2x2 == MAX_ERRORS - 1) { SkAutoMutexAcquire autoM(compareDebugOut4); showPathOpPath(testName, one, two, a, b, scaledOne, scaledTwo, shapeOp, scale); @@ -531,9 +532,6 @@ static bool innerPathOp(skiatest::Reporter* reporter, const SkPath& a, const SkP scaledOut.setFillType(out.getFillType()); int result = comparePaths(reporter, testName, pathOut, scaledPathOut, out, scaledOut, bitmap, a, b, shapeOp, scale, expectSuccess); - if (result) { - REPORTER_ASSERT(reporter, 0); - } reporter->bumpTestCount(); return result == 0; } diff --git a/tests/PathOpsOpTest.cpp b/tests/PathOpsOpTest.cpp index 993fdd9a23..f25ebc97a1 100644 --- a/tests/PathOpsOpTest.cpp +++ b/tests/PathOpsOpTest.cpp @@ -4478,11 +4478,747 @@ static void cubicOp157(skiatest::Reporter* reporter, const char* filename) { testPathOp(reporter, path, pathB, kDifference_SkPathOp, filename); } +static void cubics20d(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(1, 2); + path.cubicTo(0, 3, 6, 0, 3, 2); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(0, 6); + pathB.cubicTo(2, 3, 2, 1, 3, 0); + pathB.close(); + testPathOp(reporter, path, pathB, kDifference_SkPathOp, filename); +} + +static void loops20i(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(1, 2); + path.cubicTo(0, 2, 0.833333313f, 2, 1, 3.66666651f); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(0, 2); + pathB.cubicTo(0.833333313f, 2, 1, 3.66666651f, 1, 2); + pathB.close(); + testPathOp(reporter, path, pathB, kIntersect_SkPathOp, filename); +} + +static void loops21i(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(1, 2); + path.cubicTo(0, 2, 0.833333313f, 2, 1, 4); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(0, 2); + pathB.cubicTo(0.833333313f, 2, 1, 4, 1, 2); + pathB.close(); + testPathOp(reporter, path, pathB, kIntersect_SkPathOp, filename); +} + +static void loops22i(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(1, 3); + path.cubicTo(0, 3, 0.833333313f, 3, 1, 4.66666651f); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(0, 3); + pathB.cubicTo(0.833333313f, 3, 1, 4.66666651f, 1, 3); + pathB.close(); + testPathOp(reporter, path, pathB, kIntersect_SkPathOp, filename); +} + +static void loops23i(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(1, 5); + path.cubicTo(0, 1, 6.16666698f, 5.66666698f, -5.66666651f, 6.66666651f); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(0, 1); + pathB.cubicTo(6.16666698f, 5.66666698f, -5.66666651f, 6.66666651f, 1, 5); + pathB.close(); + testPathOpCheck(reporter, path, pathB, kIntersect_SkPathOp, filename, FLAGS_runFail); +} + +static void loops24i(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(1, 2); + path.cubicTo(0, 2, 0.833333313f, 2, 1, 3); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(0, 2); + pathB.cubicTo(0.833333313f, 2, 1, 3, 1, 2); + pathB.close(); + testPathOp(reporter, path, pathB, kIntersect_SkPathOp, filename); +} + +static void loops25i(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(1, 5); + path.cubicTo(0, 5, 0.833333313f, 5, 1, 7); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(0, 5); + pathB.cubicTo(0.833333313f, 5, 1, 7, 1, 5); + pathB.close(); + testPathOp(reporter, path, pathB, kIntersect_SkPathOp, filename); +} + +static void loops26i(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(1, 6); + path.cubicTo(0, 2, 6.16666698f, 6.66666698f, -5.66666651f, 7.66666651f); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(0, 2); + pathB.cubicTo(6.16666698f, 6.66666698f, -5.66666651f, 7.66666651f, 1, 6); + pathB.close(); + testPathOpCheck(reporter, path, pathB, kIntersect_SkPathOp, filename, FLAGS_runFail); +} + +static void loops27i(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(1, 3); + path.cubicTo(0, 3, 0.833333313f, 3, 1, 4.33333349f); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(0, 3); + pathB.cubicTo(0.833333313f, 3, 1, 4.33333349f, 1, 3); + pathB.close(); + testPathOp(reporter, path, pathB, kIntersect_SkPathOp, filename); +} + +static void loops28i(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(2, 3); + path.cubicTo(1, 3, 1.83333337f, 3, 2, 4.66666651f); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(1, 3); + pathB.cubicTo(1.83333337f, 3, 2, 4.66666651f, 2, 3); + pathB.close(); + testPathOp(reporter, path, pathB, kIntersect_SkPathOp, filename); +} + +static void loops29i(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(2, 4); + path.cubicTo(0, 4, 1.66666663f, 4, 2, 7.33333302f); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(0, 4); + pathB.cubicTo(1.66666663f, 4, 2, 7.33333302f, 2, 4); + pathB.close(); + testPathOp(reporter, path, pathB, kIntersect_SkPathOp, filename); +} + +static void loops30i(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(2, 4); + path.cubicTo(0, 4, 1.66666663f, 4, 2, 8); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(0, 4); + pathB.cubicTo(1.66666663f, 4, 2, 8, 2, 4); + pathB.close(); + testPathOp(reporter, path, pathB, kIntersect_SkPathOp, filename); +} + +static void loops31i(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(2, 5); + path.cubicTo(1, 5, 1.83333337f, 5, 2, 6.66666651f); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(1, 5); + pathB.cubicTo(1.83333337f, 5, 2, 6.66666651f, 2, 5); + pathB.close(); + testPathOp(reporter, path, pathB, kIntersect_SkPathOp, filename); +} + +static void loops32i(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(2, 6); + path.cubicTo(1, 6, 1.83333337f, 6, 2, 8); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(1, 6); + pathB.cubicTo(1.83333337f, 6, 2, 8, 2, 6); + pathB.close(); + testPathOp(reporter, path, pathB, kIntersect_SkPathOp, filename); +} + +static void loops33i(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(2, 6); + path.cubicTo(1, 2, 7.16666698f, 6.66666698f, -4.66666651f, 7.66666651f); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(1, 2); + pathB.cubicTo(7.16666698f, 6.66666698f, -4.66666651f, 7.66666651f, 2, 6); + pathB.close(); + testPathOpCheck(reporter, path, pathB, kIntersect_SkPathOp, filename, FLAGS_runFail); +} + +static void loops33iMod(skiatest::Reporter* reporter, const char* filename) { + SkPoint pts[] = {{2, 6}, {1, 2}, {7.16666698f, 6.66666698f}, {-4.66666651f, 7.66666651f}, + {1, 2}, {7.16666698f, 6.66666698f}, {-4.66666651f, 7.66666651f}, {2, 6}}; + bool up = false; + float offset = 0.0380172729f; + float step = 7.62939453e-006f; + bool lastResult = true; + // for (int i = 0; i < 30; ++i) { + SkString name(filename); + // name.appendS32(i); + // if (i > 0) { + // SkDebugf("\n\n<div id=\"%s\">\n", name.c_str()); + // } + pts[5].fY = 6.66666698f + offset; + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(pts[0]); + path.cubicTo(pts[1], pts[2], pts[3]); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(pts[4]); + pathB.cubicTo(pts[5], pts[6], pts[7]); + pathB.close(); + bool result = testPathOpCheck(reporter, path, pathB, kIntersect_SkPathOp, name.c_str(), + FLAGS_runFail); + if (lastResult != result) { + up = !up; + } + step /= 2; + offset += up ? step : -step; + lastResult = result; + // } +} + + +static void loops33iAsQuads(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(2, 6); + path.cubicTo(1, 2, 7.16666698f, 6.66666698f, -4.66666651f, 7.66666651f); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(1, 2); + pathB.cubicTo(7.16666698f, 6.66666698f, -4.66666651f, 7.66666651f, 2, 6); + pathB.close(); + SkPath qPath, qPathB; + CubicPathToQuads(path, &qPath); + CubicPathToQuads(pathB, &qPathB); + testPathOp(reporter, qPath, qPathB, kIntersect_SkPathOp, filename); +} + +static void loops34i(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(3, 4); + path.cubicTo(0, 4, 2.5f, 4, 3, 9); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(0, 4); + pathB.cubicTo(2.5f, 4, 3, 9, 3, 4); + pathB.close(); + testPathOp(reporter, path, pathB, kIntersect_SkPathOp, filename); +} + +static void loops35i(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(3, 4); + path.cubicTo(0, 4, 2.5f, 4, 3, 10); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(0, 4); + pathB.cubicTo(2.5f, 4, 3, 10, 3, 4); + pathB.close(); + testPathOp(reporter, path, pathB, kIntersect_SkPathOp, filename); +} + +static void loops36i(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(3, 4); + path.cubicTo(1, 4, 2.66666675f, 4, 3, 8); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(1, 4); + pathB.cubicTo(2.66666675f, 4, 3, 8, 3, 4); + pathB.close(); + testPathOp(reporter, path, pathB, kIntersect_SkPathOp, filename); +} + +static void loops37i(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(2, 4); + path.cubicTo(1, 4, 1.83333337f, 4, 2, 5.33333349f); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(1, 4); + pathB.cubicTo(1.83333337f, 4, 2, 5.33333349f, 2, 4); + pathB.close(); + testPathOp(reporter, path, pathB, kIntersect_SkPathOp, filename); +} + +static void loops38i(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(3, 4); + path.cubicTo(2, 4, 2.83333325f, 4, 3, 6); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(2, 4); + pathB.cubicTo(2.83333325f, 4, 3, 6, 3, 4); + pathB.close(); + testPathOp(reporter, path, pathB, kIntersect_SkPathOp, filename); +} + +static void loops39i(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(3, 5); + path.cubicTo(0, 5, 2.5f, 5, 3, 10); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(0, 5); + pathB.cubicTo(2.5f, 5, 3, 10, 3, 5); + pathB.close(); + testPathOp(reporter, path, pathB, kIntersect_SkPathOp, filename); +} + +static void loops40i(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(3, 5); + path.cubicTo(0, 5, 2.5f, 5, 3, 11); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(0, 5); + pathB.cubicTo(2.5f, 5, 3, 11, 3, 5); + pathB.close(); + testPathOp(reporter, path, pathB, kIntersect_SkPathOp, filename); +} + +static void loops40iAsQuads(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(3, 5); + path.cubicTo(0, 5, 2.5f, 5, 3, 11); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(0, 5); + pathB.cubicTo(2.5f, 5, 3, 11, 3, 5); + pathB.close(); + SkPath qPath, qPathB; + CubicPathToQuads(path, &qPath); + CubicPathToQuads(pathB, &qPathB); + testPathOp(reporter, qPath, qPathB, kIntersect_SkPathOp, filename); +} + +static void loops41i(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(1, 5); + path.cubicTo(0, 1, 6.16666698f, 5.66666698f, -5.66666651f, 6.66666651f); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(0, 1); + pathB.cubicTo(6.16666698f, 5.66666698f, -5.66666651f, 6.66666651f, 1, 5); + pathB.close(); + testPathOpCheck(reporter, path, pathB, kIntersect_SkPathOp, filename, FLAGS_runFail); +} + +/* +FAILED: d:\cygwin\puregit\tests\pathopsextendedtest.cpp:346 0 */ +static void loops42i(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(1, 6); + path.cubicTo(0, 2, 6.16666698f, 6.66666698f, -5.66666651f, 7.66666651f); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(0, 2); + pathB.cubicTo(6.16666698f, 6.66666698f, -5.66666651f, 7.66666651f, 1, 6); + pathB.close(); + testPathOpCheck(reporter, path, pathB, kIntersect_SkPathOp, filename, FLAGS_runFail); +} + +/* +FAILED: d:\cygwin\puregit\tests\pathopsextendedtest.cpp:346 0 */ +static void loops43i(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(2, 6); + path.cubicTo(1, 2, 7.16666698f, 6.66666698f, -4.66666651f, 7.66666651f); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(1, 2); + pathB.cubicTo(7.16666698f, 6.66666698f, -4.66666651f, 7.66666651f, 2, 6); + pathB.close(); + testPathOpCheck(reporter, path, pathB, kIntersect_SkPathOp, filename, FLAGS_runFail); +} + +/* +FAILED: d:\cygwin\puregit\tests\pathopsextendedtest.cpp:346 0 */ +static void loops44i(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(1, 5); + path.cubicTo(0, 1, 7.33333302f, 5.33333349f, -7, 7); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(0, 1); + pathB.cubicTo(7.33333302f, 5.33333349f, -7, 7, 1, 5); + pathB.close(); + testPathOpCheck(reporter, path, pathB, kIntersect_SkPathOp, filename, FLAGS_runFail); +} + +/* +FAILED: d:\cygwin\puregit\tests\pathopsextendedtest.cpp:346 0 */ +static void loops45i(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(1, 6); + path.cubicTo(0, 2, 7.33333302f, 6.33333302f, -7, 8); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(0, 2); + pathB.cubicTo(7.33333302f, 6.33333302f, -7, 8, 1, 6); + pathB.close(); + testPathOpCheck(reporter, path, pathB, kIntersect_SkPathOp, filename, FLAGS_runFail); +} + +/* +FAILED: d:\cygwin\puregit\tests\pathopsextendedtest.cpp:346 0 */ +static void loops46i(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(2, 6); + path.cubicTo(1, 2, 8.33333302f, 6.33333302f, -6, 8); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(1, 2); + pathB.cubicTo(8.33333302f, 6.33333302f, -6, 8, 2, 6); + pathB.close(); + testPathOpCheck(reporter, path, pathB, kIntersect_SkPathOp, filename, FLAGS_runFail); +} + +/* +FAILED: d:\cygwin\puregit\tests\pathopsextendedtest.cpp:346 0 */ +static void loops47i(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(2, 4); + path.cubicTo(0, 1, 6, 5.83333302f, -4, 8); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(0, 1); + pathB.cubicTo(6, 5.83333302f, -4, 8, 2, 4); + pathB.close(); + testPathOpCheck(reporter, path, pathB, kIntersect_SkPathOp, filename, FLAGS_runFail); +} + +/* +FAILED: d:\cygwin\puregit\tests\pathopsextendedtest.cpp:346 0 */ +static void loops48i(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(2, 6); + path.cubicTo(0, 1, 9.33333302f, 6.83333302f, -8.33333302f, 9.16666603f); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(0, 1); + pathB.cubicTo(9.33333302f, 6.83333302f, -8.33333302f, 9.16666603f, 2, 6); + pathB.close(); + testPathOpCheck(reporter, path, pathB, kIntersect_SkPathOp, filename, FLAGS_runFail); +} + +/* +FAILED: d:\cygwin\puregit\tests\pathopsextendedtest.cpp:346 0 */ +static void loops49i(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(0, 2); + path.cubicTo(1, 4, -0.166666687f, 2.66666675f, 1.66666675f, 2); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(1, 4); + pathB.cubicTo(-0.166666687f, 2.66666675f, 1.66666675f, 2, 0, 2); + pathB.close(); + testPathOpCheck(reporter, path, pathB, kIntersect_SkPathOp, filename, FLAGS_runFail); +} + +/* +FAILED: d:\cygwin\puregit\tests\pathopsextendedtest.cpp:346 0 */ +static void loops50i(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(0, 3); + path.cubicTo(1, 5, -0.166666687f, 3.66666675f, 1.66666675f, 3); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(1, 5); + pathB.cubicTo(-0.166666687f, 3.66666675f, 1.66666675f, 3, 0, 3); + pathB.close(); + testPathOpCheck(reporter, path, pathB, kIntersect_SkPathOp, filename, FLAGS_runFail); +} + +/* +FAILED: d:\cygwin\puregit\tests\pathopsextendedtest.cpp:346 0 */ +static void loops51i(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(1, 2); + path.cubicTo(2, 4, 0.833333313f, 2.66666675f, 2.66666675f, 2); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(2, 4); + pathB.cubicTo(0.833333313f, 2.66666675f, 2.66666675f, 2, 1, 2); + pathB.close(); + testPathOpCheck(reporter, path, pathB, kIntersect_SkPathOp, filename, FLAGS_runFail); +} + +/* +FAILED: d:\cygwin\puregit\tests\pathopsextendedtest.cpp:346 0 */ +static void loops52i(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(1, 3); + path.cubicTo(2, 5, 0.833333313f, 3.66666675f, 2.66666675f, 3); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(2, 5); + pathB.cubicTo(0.833333313f, 3.66666675f, 2.66666675f, 3, 1, 3); + pathB.close(); + testPathOpCheck(reporter, path, pathB, kIntersect_SkPathOp, filename, FLAGS_runFail); +} + +/* +FAILED: d:\cygwin\puregit\tests\pathopsextendedtest.cpp:346 0 */ +static void loops53i(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(2, 3); + path.cubicTo(3, 5, 1.83333325f, 3.66666675f, 3.66666651f, 3); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(3, 5); + pathB.cubicTo(1.83333325f, 3.66666675f, 3.66666651f, 3, 2, 3); + pathB.close(); + testPathOpCheck(reporter, path, pathB, kIntersect_SkPathOp, filename, FLAGS_runFail); +} + +/* +FAILED: d:\cygwin\puregit\tests\pathopsextendedtest.cpp:346 0 */ +static void loops54i(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(0, 2); + path.cubicTo(1, 4, 0, 3, 1.66666675f, 2); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(1, 4); + pathB.cubicTo(0, 3, 1.66666675f, 2, 0, 2); + pathB.close(); + testPathOpCheck(reporter, path, pathB, kIntersect_SkPathOp, filename, FLAGS_runFail); +} + +/* +FAILED: d:\cygwin\puregit\tests\pathopsextendedtest.cpp:346 0 */ +static void loops55i(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(0, 3); + path.cubicTo(1, 5, 0, 4, 1.66666675f, 3); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(1, 5); + pathB.cubicTo(0, 4, 1.66666675f, 3, 0, 3); + pathB.close(); + testPathOpCheck(reporter, path, pathB, kIntersect_SkPathOp, filename, FLAGS_runFail); +} + +/* +FAILED: d:\cygwin\puregit\tests\pathopsextendedtest.cpp:346 0 */ +static void loops56i(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(1, 2); + path.cubicTo(2, 4, 0.99999994f, 3, 2.66666675f, 2); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(2, 4); + pathB.cubicTo(0.99999994f, 3, 2.66666675f, 2, 1, 2); + pathB.close(); + testPathOpCheck(reporter, path, pathB, kIntersect_SkPathOp, filename, FLAGS_runFail); +} + +/* +FAILED: d:\cygwin\puregit\tests\pathopsextendedtest.cpp:346 0 */ +static void loops57i(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(1, 3); + path.cubicTo(2, 5, 0.99999994f, 4, 2.66666675f, 3); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(2, 5); + pathB.cubicTo(0.99999994f, 4, 2.66666675f, 3, 1, 3); + pathB.close(); + testPathOpCheck(reporter, path, pathB, kIntersect_SkPathOp, filename, FLAGS_runFail); +} + +/* +FAILED: d:\cygwin\puregit\tests\pathopsextendedtest.cpp:346 0 */ +static void loops58i(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(2, 3); + path.cubicTo(3, 5, 2, 4, 3.66666651f, 3); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(3, 5); + pathB.cubicTo(2, 4, 3.66666651f, 3, 2, 3); + pathB.close(); + testPathOpCheck(reporter, path, pathB, kIntersect_SkPathOp, filename, FLAGS_runFail); +} + +/* +FAILED: d:\cygwin\puregit\tests\pathopsextendedtest.cpp:346 0 */ +static void loops59i(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(0, 6); + path.cubicTo(1, 2, 7.33333302f, 1.66666663f, -7.5f, 2); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(1, 2); + pathB.cubicTo(7.33333302f, 1.66666663f, -7.5f, 2, 0, 6); + pathB.close(); + testPathOp(reporter, path, pathB, kIntersect_SkPathOp, filename); +} + +class PathTest_Private { +public: + PathTest_Private(SkPath* path) + : fPath(path) {} + + void setPt(int index, SkScalar x, SkScalar y) { + fPath->setPt(index, x, y); + } + + SkPath* fPath; +}; + +static void path_edit(const SkPoint& from, const SkPoint& to, SkPath* path) { + PathTest_Private testPath(path); + for (int index = 0; index < path->countPoints(); ++index) { + if (SkDPoint::ApproximatelyEqual(path->getPoint(index), from)) { + testPath.setPt(index, to.fX, to.fY); + return; + } + } +} + +static void loops59iasQuads(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(0, 6); + path.cubicTo(1, 2, 7.33333302f, 1.66666663f, -7.5f, 2); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(1, 2); + pathB.cubicTo(7.33333302f, 1.66666663f, -7.5f, 2, 0, 6); + pathB.close(); + SkPath qPath, qPathB; + CubicPathToQuads(path, &qPath); + CubicPathToQuads(pathB, &qPathB); + SkPoint from = {2.61714339f,1.90228665f}; + SkPoint to = {2.617045833359139f,1.9013528935803314f}; + path_edit(from, to, &qPathB); + testPathOp(reporter, qPath, qPathB, kIntersect_SkPathOp, filename); +} + +static void cubics41d(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(0, 1); + path.cubicTo(1, 4, 3, 0, 3, 1); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(0, 3); + pathB.cubicTo(1, 3, 1, 0, 4, 1); + pathB.close(); + testPathOp(reporter, path, pathB, kDifference_SkPathOp, filename); +} + static void (*skipTest)(skiatest::Reporter* , const char* filename) = 0; -static void (*firstTest)(skiatest::Reporter* , const char* filename) = cubicOp90u; +static void (*firstTest)(skiatest::Reporter* , const char* filename) = loops59i; static void (*stopTest)(skiatest::Reporter* , const char* filename) = 0; static struct TestDesc tests[] = { + TEST(cubics41d), + TEST(loops59iasQuads), + TEST(loops59i), + TEST(loops41i), + TEST(loops42i), + TEST(loops43i), + TEST(loops44i), + TEST(loops45i), + TEST(loops46i), + TEST(loops47i), + TEST(loops48i), + TEST(loops49i), + TEST(loops50i), + TEST(loops51i), + TEST(loops52i), + TEST(loops53i), + TEST(loops54i), + TEST(loops55i), + TEST(loops56i), + TEST(loops57i), + TEST(loops58i), + TEST(loops33iMod), + TEST(loops33iAsQuads), + TEST(loops33i), + TEST(loops40i), + TEST(loops40iAsQuads), + TEST(loops39i), + TEST(loops38i), + TEST(loops37i), + TEST(loops36i), + TEST(loops35i), + TEST(loops34i), + TEST(loops32i), + TEST(loops31i), + TEST(loops30i), + TEST(loops29i), + TEST(loops28i), + TEST(loops27i), + TEST(loops26i), + TEST(loops25i), + TEST(loops24i), + TEST(loops23i), + TEST(loops22i), + TEST(loops21i), + TEST(loops20i), + TEST(cubics20d), TEST(cubics6d), TEST(cubics7d), TEST(cubics8d), @@ -4773,84 +5509,51 @@ static struct TestDesc tests[] = { static const size_t testCount = SK_ARRAY_COUNT(tests); static struct TestDesc subTests[] = { - TEST(loop16), - TEST(loop15), - TEST(loop12), - TEST(cubicOp132), - TEST(loop11), - TEST(loop10), - TEST(circlesOp3), - TEST(loop9), - TEST(loop8), - TEST(rects5), - TEST(loop7), - TEST(cubicOp130a), - TEST(rRect1x), - TEST(circlesOp2), - TEST(circlesOp1), - TEST(cubicOp131), - TEST(cubicOp130), - TEST(cubicOp129), - TEST(cubicOp128), - TEST(cubicOp127), - TEST(cubicOp126), - TEST(cubicOp125), - TEST(cubicOp124), - TEST(loop6), - TEST(loop5), - TEST(cubicOp123), - TEST(cubicOp122), - TEST(cubicOp121), - TEST(cubicOp120), - TEST(cubicOp119), - TEST(loop4), - TEST(loop3), - TEST(loop2), - TEST(loop1asQuad), - TEST(loop1), - TEST(issue3517), - TEST(cubicOp118), - TEST(cubicOp117), - TEST(cubicOp116), - TEST(testRect2), - TEST(testRect1), - TEST(cubicOp115), - TEST(issue2753), - TEST(cubicOp114), - TEST(issue2808), - TEST(cubicOp114asQuad), - TEST(rects4), - TEST(rects3), - TEST(rects2), - TEST(rects1), - TEST(issue2540), - TEST(issue2504), - TEST(kari1), - TEST(quadOp10i), - TEST(cubicOp113), - TEST(skpcarrot_is24), - TEST(issue1417), - TEST(cubicOp112), - TEST(skpadspert_net23), - TEST(skpadspert_de11), - TEST(findFirst1), - TEST(xOp2i), - TEST(xOp3i), - TEST(xOp1u), - TEST(xOp1i), - TEST(cubicOp111), - TEST(cubicOp110), - TEST(cubicOp109), - TEST(cubicOp108), - TEST(cubicOp107), - TEST(cubicOp106), - TEST(cubicOp105), - TEST(cubicOp104), - TEST(cubicOp103), - TEST(cubicOp102), - TEST(cubicOp101), - TEST(cubicOp100), - TEST(cubicOp99), + TEST(loops40i), + TEST(loops39i), + TEST(loops38i), + TEST(loops37i), + TEST(loops36i), + TEST(loops35i), + TEST(loops34i), + TEST(loops33i), + TEST(loops32i), + TEST(loops31i), + TEST(loops30i), + TEST(loops29i), + TEST(loops28i), + TEST(loops27i), + TEST(loops26i), + TEST(loops25i), + TEST(loops24i), + TEST(loops23i), + TEST(loops22i), + TEST(loops21i), + TEST(loops20i), + TEST(cubics20d), + TEST(cubics6d), + TEST(cubics7d), + TEST(cubics8d), + TEST(cubics9d), + TEST(cubics10u), + TEST(cubics11i), + TEST(cubics12d), + TEST(cubics13d), + TEST(cubics14d), + TEST(cubics15d), + TEST(cubics16i), + TEST(cubics17d), + TEST(cubics18d), + TEST(cubics19d), + TEST(cubicOp157), + TEST(cubicOp142), + TEST(loops4i), + TEST(quadRect1), + TEST(quadRect2), + TEST(quadRect3), + TEST(quadRect4), + TEST(quadRect5), + TEST(quadRect6), }; static const size_t subTestCount = SK_ARRAY_COUNT(subTests); diff --git a/tests/PathOpsTestCommon.cpp b/tests/PathOpsTestCommon.cpp index d933115132..f6852254c0 100644 --- a/tests/PathOpsTestCommon.cpp +++ b/tests/PathOpsTestCommon.cpp @@ -141,8 +141,20 @@ void CubicToQuads(const SkDCubic& cubic, double precision, SkTArray<SkDQuad, tru double tStart = 0; for (int i1 = 0; i1 <= ts.count(); ++i1) { const double tEnd = i1 < ts.count() ? ts[i1] : 1; + SkDRect bounds; + bounds.setBounds(cubic); SkDCubic part = cubic.subDivide(tStart, tEnd); SkDQuad quad = part.toQuad(); + if (quad[1].fX < bounds.fLeft) { + quad[1].fX = bounds.fLeft; + } else if (quad[1].fX > bounds.fRight) { + quad[1].fX = bounds.fRight; + } + if (quad[1].fY < bounds.fTop) { + quad[1].fY = bounds.fTop; + } else if (quad[1].fY > bounds.fBottom) { + quad[1].fY = bounds.fBottom; + } quads.push_back(quad); tStart = tEnd; } diff --git a/tools/pathops_sorter.htm b/tools/pathops_sorter.htm index c6ec3d467e..c515fe9b87 100644 --- a/tools/pathops_sorter.htm +++ b/tools/pathops_sorter.htm @@ -7,8 +7,8 @@ <div style="height:0"> <div id="sect1"> -{{{2.0185184099245816, 2.3784720550756902}, {1.9467591438442469, 2.1736109238117933}, {1.8796295076608658, 1.9722220152616501}, {1.8148146867752075, 1.7777775526046753}}}, -{{{2.0185184099245816, 2.3784720550756902}, {1.9467591438442469, 2.1736109238117933}, {1.8796295076608658, 1.9722220152616501}, {1.8148146867752075, 1.7777775526046753}}}, +{{{2.18726921f, 2.37414956f}, {2.17974997f, 1.98023772f}, {0.0679920018f, 1.92180145f}}} +{{{1.58881736f, 3.34967732f}, {2.89432383f, 1.86175978f}, {2.97965813f, 1.76450205f}, {-7.5f, 2}}} </div> </div> diff --git a/tools/pathops_visualizer.htm b/tools/pathops_visualizer.htm index 5aa1068a0c..f1288f0fe8 100644 --- a/tools/pathops_visualizer.htm +++ b/tools/pathops_visualizer.htm @@ -2,300 +2,226 @@ <head> <div height="0" hidden="true"> -<div id="cubics6d"> -seg=1 {{{3, 5}, {1.8377223f, 5}, {2.36405635f, 3.98683286f}, {3.00889349f, 2.74555302f}}} -seg=2 {{{3.00889349f, 2.74555302f}, {3.47366595f, 1.85088933f}, {4, 0.837722301f}, {4, 0}}} -seg=3 {{{4, 0}, {3, 5}}} -op diff -seg=4 {{{2, 4}, {1.18350339f, 4}, {1.53367352f, 3.83333325f}, {2.2340138f, 3.5f}}} -seg=5 {{{2.2340138f, 3.5f}, {3.2491498f, 3.01683664f}, {5, 2.18350339f}, {5, 1}}} -seg=6 {{{5, 1}, {2, 4}}} -debugShowCubicIntersection wtTs[0]=1 {{{3,5}, {1.8377223,5}, {2.36405635,3.98683286}, {3.00889349,2.74555302}}} {{3.00889349,2.74555302}} wnTs[0]=0 {{{3.00889349,2.74555302}, {3.47366595,1.85088933}, {4,0.837722301}, {4,0}}} -debugShowCubicLineIntersection wtTs[0]=0 {{{3,5}, {1.8377223,5}, {2.36405635,3.98683286}, {3.00889349,2.74555302}}} {{3,5}} wnTs[0]=1 {{{4,0}, {3,5}}} -debugShowCubicLineIntersection wtTs[0]=0.602095725 {{{3.00889349,2.74555302}, {3.47366595,1.85088933}, {4,0.837722301}, {4,0}}} {{3.78703713,1.06481469}} wtTs[1]=1 {{4,0}} wnTs[0]=0.212963 {{{4,0}, {3,5}}} wnTs[1]=0 -SkOpSegment::addT insert t=0.602095725 segID=2 spanID=13 -SkOpSegment::addT insert t=0.212962933 segID=3 spanID=14 -debugShowCubicIntersection wtTs[0]=0.860380171 {{{3,5}, {1.8377223,5}, {2.36405635,3.98683286}, {3.00889349,2.74555302}}} {{2.75000095,3.24999785}} wnTs[0]=0.155051 {{{2.2340138,3.5}, {3.2491498,3.01683664}, {5,2.18350339}, {5,1}}} -SkOpSegment::addT insert t=0.860380171 segID=1 spanID=15 -SkOpSegment::addT insert t=0.155051471 segID=5 spanID=16 -debugShowCubicLineIntersection wtTs[0]=0.860379476 {{{3,5}, {1.8377223,5}, {2.36405635,3.98683286}, {3.00889349,2.74555302}}} {{2.74999976,3.25000024}} wnTs[0]=0.75 {{{5,1}, {2,4}}} -SkOpSegment::addT insert t=0.860379476 segID=1 spanID=17 -SkOpSegment::addT insert t=0.750000104 segID=6 spanID=18 -debugShowCubicIntersection no intersect {{{3.00889349,2.74555302}, {3.47366595,1.85088933}, {4,0.837722301}, {4,0}}} {{{2.2340138,3.5}, {3.2491498,3.01683664}, {5,2.18350339}, {5,1}}} -debugShowCubicLineIntersection no intersect {{{3.00889349,2.74555302}, {3.47366595,1.85088933}, {4,0.837722301}, {4,0}}} {{{5,1}, {2,4}}} -debugShowCubicLineIntersection wtTs[0]=0.338765871 {{{2.2340138,3.5}, {3.2491498,3.01683664}, {5,2.18350339}, {5,1}}} {{3.42231941,2.88840342}} wnTs[0]=0.577681 {{{4,0}, {3,5}}} -SkOpSegment::addT insert t=0.57768066 segID=3 spanID=19 -SkOpSegment::addT insert t=0.338765871 segID=5 spanID=20 -debugShowLineIntersection wtTs[0]=0.5 {{{4,0}, {3,5}}} {{3.5,2.5}} wnTs[0]=0.5 {{{5,1}, {2,4}}} -SkOpSegment::addT insert t=0.5 segID=3 spanID=21 -SkOpSegment::addT insert t=0.5 segID=6 spanID=22 -debugShowCubicIntersection wtTs[0]=1 {{{2,4}, {1.18350339,4}, {1.53367352,3.83333325}, {2.2340138,3.5}}} {{2.2340138,3.5}} wnTs[0]=0 {{{2.2340138,3.5}, {3.2491498,3.01683664}, {5,2.18350339}, {5,1}}} -debugShowCubicLineIntersection wtTs[0]=0 {{{2,4}, {1.18350339,4}, {1.53367352,3.83333325}, {2.2340138,3.5}}} {{2,4}} wnTs[0]=1 {{{5,1}, {2,4}}} -debugShowCubicLineIntersection wtTs[0]=0.155050964 {{{2.2340138,3.5}, {3.2491498,3.01683664}, {5,2.18350339}, {5,1}}} {{2.75,3.25}} wtTs[1]=1 {{5,1}} wnTs[0]=0.75 {{{5,1}, {2,4}}} wnTs[1]=0 -SkOpSegment::addT insert t=0.155050964 segID=5 spanID=23 -SkOpSegment::addT alias t=0.750000024 segID=6 spanID=18 -SkOpSegment::sortAngles [1] tStart=0.860379476 [17] -SkOpAngle::after [1/1] 21/25 tStart=0.860379476 tEnd=0 < [6/21] 3/3 tStart=0.750000104 tEnd=0.5 < [1/2] 3/3 tStart=0.860379476 tEnd=0.860380171 T 11 -SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2.24999996,4.25000007}, {2.00000012,5}, {3,5}}} id=1 -SkOpAngle::afterPart {{{2.74999976,3.25000024}, {3.5,2.5}}} id=6 -SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2.75000017,3.24999943}, {2.75000055,3.24999866}, {2.75000095,3.24999785}}} id=1 -SkOpAngle::after [1/1] 21/25 tStart=0.860379476 tEnd=0 < [6/22] 19/19 tStart=0.750000104 tEnd=1 < [6/21] 3/3 tStart=0.750000104 tEnd=0.5 F 4 -SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2.24999996,4.25000007}, {2.00000012,5}, {3,5}}} id=1 -SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2,4}}} id=6 -SkOpAngle::afterPart {{{2.74999976,3.25000024}, {3.5,2.5}}} id=6 -SkOpAngle::after [6/21] 3/3 tStart=0.750000104 tEnd=0.5 < [6/22] 19/19 tStart=0.750000104 tEnd=1 < [1/2] 3/3 tStart=0.860379476 tEnd=0.860380171 F 5 -SkOpAngle::afterPart {{{2.74999976,3.25000024}, {3.5,2.5}}} id=6 -SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2,4}}} id=6 -SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2.75000017,3.24999943}, {2.75000055,3.24999866}, {2.75000095,3.24999785}}} id=1 -SkOpAngle::after [1/2] 3/3 tStart=0.860379476 tEnd=0.860380171 < [6/22] 19/19 tStart=0.750000104 tEnd=1 < [1/1] 21/25 tStart=0.860379476 tEnd=0 T 4 -SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2.75000017,3.24999943}, {2.75000055,3.24999866}, {2.75000095,3.24999785}}} id=1 -SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2,4}}} id=6 -SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2.24999996,4.25000007}, {2.00000012,5}, {3,5}}} id=1 -SkOpAngle::after [1/1] 21/25 tStart=0.860379476 tEnd=0 < [5/13] 17/17 tStart=0.155050964 tEnd=0 < [6/21] 3/3 tStart=0.750000104 tEnd=0.5 F 4 -SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2.24999996,4.25000007}, {2.00000012,5}, {3,5}}} id=1 -SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2.56649642,3.34175191}, {2.39141161,3.42508506}, {2.2340138,3.5}}} id=5 -SkOpAngle::afterPart {{{2.74999976,3.25000024}, {3.5,2.5}}} id=6 -SkOpAngle::after [6/21] 3/3 tStart=0.750000104 tEnd=0.5 < [5/13] 17/17 tStart=0.155050964 tEnd=0 < [1/2] 3/3 tStart=0.860379476 tEnd=0.860380171 F 5 -SkOpAngle::afterPart {{{2.74999976,3.25000024}, {3.5,2.5}}} id=6 -SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2.56649642,3.34175191}, {2.39141161,3.42508506}, {2.2340138,3.5}}} id=5 -SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2.75000017,3.24999943}, {2.75000055,3.24999866}, {2.75000095,3.24999785}}} id=1 -SkOpAngle::after [1/2] 3/3 tStart=0.860379476 tEnd=0.860380171 < [5/13] 17/17 tStart=0.155050964 tEnd=0 < [6/22] 19/19 tStart=0.750000104 tEnd=1 T 4 -SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2.75000017,3.24999943}, {2.75000055,3.24999866}, {2.75000095,3.24999785}}} id=1 -SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2.56649642,3.34175191}, {2.39141161,3.42508506}, {2.2340138,3.5}}} id=5 -SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2,4}}} id=6 -SkOpAngle::after [1/1] 21/25 tStart=0.860379476 tEnd=0 < [5/14] 17/17 tStart=0.155050964 tEnd=0.155051471 < [6/21] 3/3 tStart=0.750000104 tEnd=0.5 F 4 -SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2.24999996,4.25000007}, {2.00000012,5}, {3,5}}} id=1 -SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2.75000036,3.25000024}, {2.75000035,3.24999785}, {2.75000095,3.24999785}}} id=5 -SkOpAngle::afterPart {{{2.74999976,3.25000024}, {3.5,2.5}}} id=6 -SkOpAngle::after [6/21] 3/3 tStart=0.750000104 tEnd=0.5 < [5/14] 17/17 tStart=0.155050964 tEnd=0.155051471 < [1/2] 3/3 tStart=0.860379476 tEnd=0.860380171 F 5 -SkOpAngle::afterPart {{{2.74999976,3.25000024}, {3.5,2.5}}} id=6 -SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2.56649642,3.34175191}, {2.39141161,3.42508506}, {2.2340138,3.5}}} id=5 -SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2.75000017,3.24999943}, {2.75000055,3.24999866}, {2.75000095,3.24999785}}} id=1 -SkOpAngle::after [1/2] 3/3 tStart=0.860379476 tEnd=0.860380171 < [5/14] 17/17 tStart=0.155050964 tEnd=0.155051471 < [5/13] 17/17 tStart=0.155050964 tEnd=0 T 11 -SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2.75000017,3.24999943}, {2.75000055,3.24999866}, {2.75000095,3.24999785}}} id=1 -SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2.56649642,3.34175191}, {2.39141161,3.42508506}, {2.2340138,3.5}}} id=5 -SkOpAngle::afterPart {{{2.74999976,3.25000024}, {2.56649642,3.34175191}, {2.39141161,3.42508506}, {2.2340138,3.5}}} id=5 -SkOpSegment::sortAngles [1] tStart=0.860380171 [15] -SkOpAngle::after [1/3] 19/19 tStart=0.860380171 tEnd=0.860379476 < [5/15] 1/2 tStart=0.155051471 tEnd=0.155050964 < [1/4] 5/5 tStart=0.860380171 tEnd=1 T 4 -SkOpAngle::afterPart {{{2.75000095,3.24999785}, {2.75000055,3.24999866}, {2.75000017,3.24999943}, {2.74999976,3.25000024}}} id=1 -SkOpAngle::afterPart {{{2.75000095,3.24999785}, {2.75000035,3.24999785}, {2.75000036,3.25000024}, {2.74999976,3.25000024}}} id=5 -SkOpAngle::afterPart {{{2.75000095,3.24999785}, {2.8311395,3.08772078}, {2.91886144,2.9188603}, {3.00889349,2.74555302}}} id=1 -SkOpAngle::after [1/3] 19/19 tStart=0.860380171 tEnd=0.860379476 < [5/16] 1/1 tStart=0.155051471 tEnd=0.338765871 < [5/15] 1/2 tStart=0.155051471 tEnd=0.155050964 T 11 -SkOpAngle::afterPart {{{2.75000095,3.24999785}, {2.75000055,3.24999866}, {2.75000017,3.24999943}, {2.74999976,3.25000024}}} id=1 -SkOpAngle::afterPart {{{2.75000095,3.24999785}, {2.96742763,3.14128448}, {3.1966737,3.02075395}, {3.42231941,2.88840342}}} id=5 -SkOpAngle::afterPart {{{2.75000095,3.24999785}, {3.75000071,2.74999781}, {5,1.99999945}, {5,1}}} id=5 -SkOpSegment::sortAngles [2] tStart=0.602095725 [13] -SkOpAngle::after [2/5] 21/21 tStart=0.602095725 tEnd=0 < [3/7] 5/5 tStart=0.212962933 tEnd=0 < [2/6] 5/5 tStart=0.602095725 tEnd=1 F 11 -SkOpAngle::afterPart {{{3.78703713,1.06481469}, {3.59088584,1.62524693}, {3.288731,2.20687983}, {3.00889349,2.74555302}}} id=2 -SkOpAngle::afterPart {{{3.78703713,1.06481469}, {4,0}}} id=3 -SkOpAngle::afterPart {{{3.78703713,1.06481469}, {3.91666675,0.694444369}, {4,0.333333285}, {4,0}}} id=2 -SkOpAngle::after [2/5] 21/21 tStart=0.602095725 tEnd=0 < [3/8] 21/21 tStart=0.212962933 tEnd=0.5 < [2/6] 5/5 tStart=0.602095725 tEnd=1 T 12 -SkOpAngle::afterPart {{{3.78703713,1.06481469}, {3.59088584,1.62524693}, {3.288731,2.20687983}, {3.00889349,2.74555302}}} id=2 -SkOpAngle::afterPart {{{3.78703713,1.06481469}, {3.5,2.5}}} id=3 -SkOpAngle::afterPart {{{3.78703713,1.06481469}, {3.91666675,0.694444369}, {4,0.333333285}, {4,0}}} id=2 -SkOpSegment::sortAngles [3] tStart=0.212962933 [14] -SkOpSegment::sortAngles [3] tStart=0.5 [21] -SkOpAngle::after [3/9] 5/5 tStart=0.5 tEnd=0.212962933 < [6/19] 3/3 tStart=0.5 tEnd=0 < [3/10] 21/21 tStart=0.5 tEnd=0.57768066 F 4 -SkOpAngle::afterPart {{{3.5,2.5}, {3.78703713,1.06481469}}} id=3 -SkOpAngle::afterPart {{{3.5,2.5}, {5,1}}} id=6 -SkOpAngle::afterPart {{{3.5,2.5}, {3.42231941,2.88840342}}} id=3 -SkOpAngle::after [3/9] 5/5 tStart=0.5 tEnd=0.212962933 < [6/20] 19/19 tStart=0.5 tEnd=0.750000104 < [3/10] 21/21 tStart=0.5 tEnd=0.57768066 T 4 -SkOpAngle::afterPart {{{3.5,2.5}, {3.78703713,1.06481469}}} id=3 -SkOpAngle::afterPart {{{3.5,2.5}, {2.74999976,3.25000024}}} id=6 -SkOpAngle::afterPart {{{3.5,2.5}, {3.42231941,2.88840342}}} id=3 -SkOpSegment::sortAngles [3] tStart=0.57768066 [19] -SkOpAngle::after [3/11] 5/5 tStart=0.57768066 tEnd=0.5 < [5/17] 17/17 tStart=0.338765871 tEnd=0.155051471 < [3/12] 21/21 tStart=0.57768066 tEnd=1 T 4 -SkOpAngle::afterPart {{{3.42231941,2.88840342}, {3.5,2.5}}} id=3 -SkOpAngle::afterPart {{{3.42231941,2.88840342}, {3.1966737,3.02075395}, {2.96742763,3.14128448}, {2.75000095,3.24999785}}} id=5 -SkOpAngle::afterPart {{{3.42231941,2.88840342}, {3,5}}} id=3 -SkOpAngle::after [3/11] 5/5 tStart=0.57768066 tEnd=0.5 < [5/18] 1/5 tStart=0.338765871 tEnd=1 < [5/17] 17/17 tStart=0.338765871 tEnd=0.155051471 F 12 -SkOpAngle::afterPart {{{3.42231941,2.88840342}, {3.5,2.5}}} id=3 -SkOpAngle::afterPart {{{3.42231941,2.88840342}, {4.23447483,2.41204069}, {5,1.78257283}, {5,1}}} id=5 -SkOpAngle::afterPart {{{3.42231941,2.88840342}, {3.1966737,3.02075395}, {2.96742763,3.14128448}, {2.75000095,3.24999785}}} id=5 -SkOpAngle::after [5/17] 17/17 tStart=0.338765871 tEnd=0.155051471 < [5/18] 1/5 tStart=0.338765871 tEnd=1 < [3/12] 21/21 tStart=0.57768066 tEnd=1 F 4 -SkOpAngle::afterPart {{{3.42231941,2.88840342}, {3.1966737,3.02075395}, {2.96742763,3.14128448}, {2.75000095,3.24999785}}} id=5 -SkOpAngle::afterPart {{{3.42231941,2.88840342}, {4.23447483,2.41204069}, {5,1.78257283}, {5,1}}} id=5 -SkOpAngle::afterPart {{{3.42231941,2.88840342}, {3,5}}} id=3 -SkOpAngle::after [3/12] 21/21 tStart=0.57768066 tEnd=1 < [5/18] 1/5 tStart=0.338765871 tEnd=1 < [3/11] 5/5 tStart=0.57768066 tEnd=0.5 T 11 -SkOpAngle::afterPart {{{3.42231941,2.88840342}, {3,5}}} id=3 -SkOpAngle::afterPart {{{3.42231941,2.88840342}, {4.23447483,2.41204069}, {5,1.78257283}, {5,1}}} id=5 -SkOpAngle::afterPart {{{3.42231941,2.88840342}, {3.5,2.5}}} id=3 -SkOpSegment::sortAngles [5] tStart=0.155050964 [23] -SkOpSegment::sortAngles [5] tStart=0.155051471 [16] -SkOpSegment::sortAngles [5] tStart=0.338765871 [20] -SkOpSegment::sortAngles [6] tStart=0.5 [22] -SkOpSegment::sortAngles [6] tStart=0.750000104 [18] -SkOpSegment::debugShowActiveSpans id=1 (3,5 1.8377223,5 2.36405635,3.98683286 3.00889349,2.74555302) t=0 (3,5) tEnd=0.860379476 windSum=? windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=1 (3,5 1.8377223,5 2.36405635,3.98683286 3.00889349,2.74555302) t=0.860379476 (2.74999976,3.25000024) tEnd=0.860380171 windSum=? windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=1 (3,5 1.8377223,5 2.36405635,3.98683286 3.00889349,2.74555302) t=0.860380171 (2.75000095,3.24999785) tEnd=1 windSum=? windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=2 (3.00889349,2.74555302 3.47366595,1.85088933 4,0.837722301 4,0) t=0 (3.00889349,2.74555302) tEnd=0.602095725 windSum=? windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=2 (3.00889349,2.74555302 3.47366595,1.85088933 4,0.837722301 4,0) t=0.602095725 (3.78703713,1.06481469) tEnd=1 windSum=? windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=3 (4,0 3,5) t=0 (4,0) tEnd=0.212962933 windSum=? windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=3 (4,0 3,5) t=0.212962933 (3.78703713,1.06481469) tEnd=0.5 windSum=? windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=3 (4,0 3,5) t=0.5 (3.5,2.5) tEnd=0.57768066 windSum=? windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=3 (4,0 3,5) t=0.57768066 (3.42231941,2.88840342) tEnd=1 windSum=? windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=4 (2,4 1.18350339,4 1.53367352,3.83333325 2.2340138,3.5) t=0 (2,4) tEnd=1 windSum=? windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0 (2.2340138,3.5) tEnd=0.155050964 windSum=? windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0.155050964 (2.74999976,3.25000024) tEnd=0.155051471 windSum=? windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0.155051471 (2.75000095,3.24999785) tEnd=0.338765871 windSum=? windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0.338765871 (3.42231941,2.88840342) tEnd=1 windSum=? windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=6 (5,1 2,4) t=0 (5,1) tEnd=0.5 windSum=? windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=6 (5,1 2,4) t=0.5 (3.5,2.5) tEnd=0.750000104 windSum=? windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=6 (5,1 2,4) t=0.750000104 (2.74999976,3.25000024) tEnd=1 windSum=? windValue=1 oppValue=0 +<div id="loops59i"> +SkDCubic::ComplexBreak +{{{1, 2}, {7.3333330154418945, 1.6666666269302368}, {-7.5, 2}, {0, 6}}}, +inflectionsTs[0]=0.22755391 {{{5.6899562470344014, 1.5351137489099846}, {-0.59395324579271769, 2.2875990427916371}}}, +inflectionsTs[1]=0.134608255 {{{-1.7562572007939035, 2.2074401507711405}, {6.7824037520473279, 1.6104549548102116}}}, +maxCurvature[0]=0.184583395 {{{2.612965320628251, 1.8574526830515183}, {2.6213210132912339, 1.9473982945574213}}}, +maxCurvature[1]=0.764880287 {{{-0.3599143419711428, -3.5772335093952985}, {-3.9435828934112642, 11.072562225478482}}}, +maxCurvature[2]=0.500240448 {{{11.93379531543474, -0.87734455447864557}, {-11.814505983496176, 5.6289081865421942}}}, +seg=1 {{{0, 6}, {0.293506175f, 4.82597542f}, {1.04645705f, 3.96781874f}, {1.58881736f, 3.34967732f}}} +seg=2 {{{1.58881736f, 3.34967732f}, {2.89432383f, 1.86175978f}, {2.97965813f, 1.76450205f}, {-7.5f, 2}}} +seg=3 {{{-7.5f, 2}, {0, 6}}} +op sect +seg=4 {{{1, 2}, {2.16902828f, 1.93847215f}, {2.61688614f, 1.89965844f}, {2.61714315f, 1.90242553f}}} +seg=5 {{{2.61714315f, 1.90242553f}, {2.61827874f, 1.91464937f}, {-6.11562443f, 2.7383337f}, {0, 6}}} +seg=6 {{{0, 6}, {1, 2}}} +debugShowCubicIntersection wtTs[0]=1 {{{0,6}, {0.293506175,4.82597542}, {1.04645705,3.96781874}, {1.58881736,3.34967732}}} {{1.58881736,3.34967732}} wnTs[0]=0 {{{1.58881736,3.34967732}, {2.89432383,1.86175978}, {2.97965813,1.76450205}, {-7.5,2}}} +debugShowCubicLineIntersection wtTs[0]=0 {{{0,6}, {0.293506175,4.82597542}, {1.04645705,3.96781874}, {1.58881736,3.34967732}}} {{0,6}} wnTs[0]=1 {{{-7.5,2}, {0,6}}} +debugShowCubicLineIntersection wtTs[0]=1 {{{1.58881736,3.34967732}, {2.89432383,1.86175978}, {2.97965813,1.76450205}, {-7.5,2}}} {{-7.5,2}} wnTs[0]=0 {{{-7.5,2}, {0,6}}} +debugShowCubicIntersection wtTs[0]=0 {{{0,6}, {0.293506175,4.82597542}, {1.04645705,3.96781874}, {1.58881736,3.34967732}}} {{0,6}} wnTs[0]=1 {{{2.61714315,1.90242553}, {2.61827874,1.91464937}, {-6.11562443,2.7383337}, {0,6}}} +debugShowCubicLineIntersection wtTs[0]=0 {{{0,6}, {0.293506175,4.82597542}, {1.04645705,3.96781874}, {1.58881736,3.34967732}}} {{0,6}} wnTs[0]=0 {{{0,6}, {1,2}}} +debugShowCubicIntersection wtTs[0]=0.538493706 {{{1.58881736,3.34967732}, {2.89432383,1.86175978}, {2.97965813,1.76450205}, {-7.5,2}}} {{1.17718506,1.99055469}} wnTs[0]=0.0521913 {{{1,2}, {2.16902828,1.93847215}, {2.61688614,1.89965844}, {2.61714315,1.90242553}}} +SkOpSegment::addT insert t=0.538493706 segID=2 spanID=13 +SkOpSegment::addT insert t=0.0521913275 segID=4 spanID=14 +debugShowCubicIntersection wtTs[0]=0.481912781 {{{1.58881736,3.34967732}, {2.89432383,1.86175978}, {2.97965813,1.76450205}, {-7.5,2}}} {{1.58025348,2.04903817}} wnTs[0]=0.222514 {{{2.61714315,1.90242553}, {2.61827874,1.91464937}, {-6.11562443,2.7383337}, {0,6}}} +SkOpSegment::addT insert t=0.481912781 segID=2 spanID=15 +SkOpSegment::addT insert t=0.222514468 segID=5 spanID=16 +debugShowCubicLineIntersection no intersect {{{1.58881736,3.34967732}, {2.89432383,1.86175978}, {2.97965813,1.76450205}, {-7.5,2}}} {{{0,6}, {1,2}}} +debugShowCubicLineIntersection wtTs[0]=1 {{{2.61714315,1.90242553}, {2.61827874,1.91464937}, {-6.11562443,2.7383337}, {0,6}}} {{0,6}} wnTs[0]=1 {{{-7.5,2}, {0,6}}} +debugShowLineIntersection wtTs[0]=1 {{{-7.5,2}, {0,6}}} {{0,6}} wnTs[0]=0 {{{0,6}, {1,2}}} +debugShowCubicIntersection wtTs[0]=1 {{{1,2}, {2.16902828,1.93847215}, {2.61688614,1.89965844}, {2.61714315,1.90242553}}} {{2.61714315,1.90242553}} wnTs[0]=0 {{{2.61714315,1.90242553}, {2.61827874,1.91464937}, {-6.11562443,2.7383337}, {0,6}}} +debugShowCubicLineIntersection wtTs[0]=0 {{{1,2}, {2.16902828,1.93847215}, {2.61688614,1.89965844}, {2.61714315,1.90242553}}} {{1,2}} wnTs[0]=1 {{{0,6}, {1,2}}} +debugShowCubicLineIntersection wtTs[0]=0.293280033 {{{2.61714315,1.90242553}, {2.61827874,1.91464937}, {-6.11562443,2.7383337}, {0,6}}} {{0.959100008,2.16359997}} wtTs[1]=1 {{0,6}} wnTs[0]=0.9591 {{{0,6}, {1,2}}} wnTs[1]=0 +SkOpSegment::addT insert t=0.293280033 segID=5 spanID=17 +SkOpSegment::addT insert t=0.959100004 segID=6 spanID=18 +SkOpSegment::sortAngles [1] tStart=0 [1] +SkOpAngle::after [1/1] 5/5 tStart=0 tEnd=1 < [5/13] 13/5 tStart=1 tEnd=0.293280033 < [6/14] 5/5 tStart=0 tEnd=0.959100004 F 7 +SkOpAngle::afterPart {{{0,6}, {0.293506175,4.82597542}, {1.04645705,3.96781874}, {1.58881736,3.34967732}}} id=1 +SkOpAngle::afterPart {{{0,6}, {-4.3220339,3.6949153}, {-1.22742501,2.60748826}, {0.959100008,2.16359997}}} id=5 +SkOpAngle::afterPart {{{0,6}, {0.959100008,2.16359997}}} id=6 +SkOpAngle::after [1/1] 5/5 tStart=0 tEnd=1 < [3/6] 13/13 tStart=1 tEnd=0 < [6/14] 5/5 tStart=0 tEnd=0.959100004 F 5 +SkOpAngle::afterPart {{{0,6}, {0.293506175,4.82597542}, {1.04645705,3.96781874}, {1.58881736,3.34967732}}} id=1 +SkOpAngle::afterPart {{{0,6}, {-7.5,2}}} id=3 +SkOpAngle::afterPart {{{0,6}, {0.959100008,2.16359997}}} id=6 +SkOpAngle::after [6/14] 5/5 tStart=0 tEnd=0.959100004 < [3/6] 13/13 tStart=1 tEnd=0 < [5/13] 13/5 tStart=1 tEnd=0.293280033 F 7 +SkOpAngle::afterPart {{{0,6}, {0.959100008,2.16359997}}} id=6 +SkOpAngle::afterPart {{{0,6}, {-7.5,2}}} id=3 +SkOpAngle::afterPart {{{0,6}, {-4.3220339,3.6949153}, {-1.22742501,2.60748826}, {0.959100008,2.16359997}}} id=5 +SkOpAngle::after [5/13] 13/5 tStart=1 tEnd=0.293280033 < [3/6] 13/13 tStart=1 tEnd=0 < [1/1] 5/5 tStart=0 tEnd=1 T 7 +SkOpAngle::afterPart {{{0,6}, {-4.3220339,3.6949153}, {-1.22742501,2.60748826}, {0.959100008,2.16359997}}} id=5 +SkOpAngle::afterPart {{{0,6}, {-7.5,2}}} id=3 +SkOpAngle::afterPart {{{0,6}, {0.293506175,4.82597542}, {1.04645705,3.96781874}, {1.58881736,3.34967732}}} id=1 +SkOpSegment::sortAngles [2] tStart=0.481912781 [15] +SkOpAngle::after [2/2] 29/25 tStart=0.481912781 tEnd=0 < [5/9] 1/1 tStart=0.222514468 tEnd=0 < [2/3] 13/13 tStart=0.481912781 tEnd=0.538493706 T 4 +SkOpAngle::afterPart {{{1.58025348,2.04903817}, {2.5637252,2.23855117}, {2.21795761,2.63263084}, {1.58881736,3.34967732}}} id=2 +SkOpAngle::afterPart {{{1.58025348,2.04903817}, {2.18515331,1.94804315}, {2.61739584,1.90514551}, {2.61714315,1.90242553}}} id=5 +SkOpAngle::afterPart {{{1.58025348,2.04903817}, {1.464785,2.02678763}, {1.33099307,2.007357}, {1.17718506,1.99055469}}} id=2 +SkOpAngle::after [2/2] 29/25 tStart=0.481912781 tEnd=0 < [5/10] 17/17 tStart=0.222514468 tEnd=0.293280033 < [5/9] 1/1 tStart=0.222514468 tEnd=0 F 4 +SkOpAngle::afterPart {{{1.58025348,2.04903817}, {2.5637252,2.23855117}, {2.21795761,2.63263084}, {1.58881736,3.34967732}}} id=2 +SkOpAngle::afterPart {{{1.58025348,2.04903817}, {1.38787913,2.0811573}, {1.178042,2.11915237}, {0.959100008,2.16359997}}} id=5 +SkOpAngle::afterPart {{{1.58025348,2.04903817}, {2.18515331,1.94804315}, {2.61739584,1.90514551}, {2.61714315,1.90242553}}} id=5 +SkOpAngle::after [5/9] 1/1 tStart=0.222514468 tEnd=0 < [5/10] 17/17 tStart=0.222514468 tEnd=0.293280033 < [2/3] 13/13 tStart=0.481912781 tEnd=0.538493706 F 4 +SkOpAngle::afterPart {{{1.58025348,2.04903817}, {2.18515331,1.94804315}, {2.61739584,1.90514551}, {2.61714315,1.90242553}}} id=5 +SkOpAngle::afterPart {{{1.58025348,2.04903817}, {1.38787913,2.0811573}, {1.178042,2.11915237}, {0.959100008,2.16359997}}} id=5 +SkOpAngle::afterPart {{{1.58025348,2.04903817}, {1.464785,2.02678763}, {1.33099307,2.007357}, {1.17718506,1.99055469}}} id=2 +SkOpAngle::after [2/3] 13/13 tStart=0.481912781 tEnd=0.538493706 < [5/10] 17/17 tStart=0.222514468 tEnd=0.293280033 < [2/2] 29/25 tStart=0.481912781 tEnd=0 T 4 +SkOpAngle::afterPart {{{1.58025348,2.04903817}, {1.464785,2.02678763}, {1.33099307,2.007357}, {1.17718506,1.99055469}}} id=2 +SkOpAngle::afterPart {{{1.58025348,2.04903817}, {1.38787913,2.0811573}, {1.178042,2.11915237}, {0.959100008,2.16359997}}} id=5 +SkOpAngle::afterPart {{{1.58025348,2.04903817}, {2.5637252,2.23855117}, {2.21795761,2.63263084}, {1.58881736,3.34967732}}} id=2 +SkOpSegment::sortAngles [2] tStart=0.538493706 [13] +SkOpAngle::after [2/4] 29/29 tStart=0.538493706 tEnd=0.481912781 < [4/7] 17/17 tStart=0.0521913275 tEnd=0 < [2/5] 13/17 tStart=0.538493706 tEnd=1 F 11 +SkOpAngle::afterPart {{{1.17718506,1.99055469}, {1.33099307,2.007357}, {1.464785,2.02678763}, {1.58025348,2.04903817}}} id=2 +SkOpAngle::afterPart {{{1.17718506,1.99055469}, {1.12006187,1.99363948}, {1.06101314,1.99678878}, {1,2}}} id=4 +SkOpAngle::afterPart {{{1.17718506,1.99055469}, {-0.0773608463,1.85350547}, {-2.66357181,1.89131621}, {-7.5,2}}} id=2 +SkOpAngle::after [2/4] 29/29 tStart=0.538493706 tEnd=0.481912781 < [4/8] 1/1 tStart=0.0521913275 tEnd=1 < [2/5] 13/17 tStart=0.538493706 tEnd=1 T 4 +SkOpAngle::afterPart {{{1.17718506,1.99055469}, {1.33099307,2.007357}, {1.464785,2.02678763}, {1.58025348,2.04903817}}} id=2 +SkOpAngle::afterPart {{{1.17718506,1.99055469}, {2.21455765,1.93453399}, {2.61689955,1.89980286}, {2.61714315,1.90242553}}} id=4 +SkOpAngle::afterPart {{{1.17718506,1.99055469}, {-0.0773608463,1.85350547}, {-2.66357181,1.89131621}, {-7.5,2}}} id=2 +SkOpSegment::sortAngles [3] tStart=1 [6] +SkOpSegment::sortAngles [4] tStart=0.0521913275 [14] +SkOpSegment::sortAngles [5] tStart=0.222514468 [16] +SkOpSegment::sortAngles [5] tStart=0.293280033 [17] +SkOpAngle::after [5/11] 1/1 tStart=0.293280033 tEnd=0.222514468 < [6/15] 21/21 tStart=0.959100004 tEnd=0 < [5/12] 17/21 tStart=0.293280033 tEnd=1 F 11 +SkOpAngle::afterPart {{{0.959100008,2.16359997}, {1.178042,2.11915237}, {1.38787913,2.0811573}, {1.58025348,2.04903817}}} id=5 +SkOpAngle::afterPart {{{0.959100008,2.16359997}, {0,6}}} id=6 +SkOpAngle::afterPart {{{0.959100008,2.16359997}, {-1.22742501,2.60748826}, {-4.3220339,3.6949153}, {0,6}}} id=5 +SkOpAngle::after [5/11] 1/1 tStart=0.293280033 tEnd=0.222514468 < [6/16] 5/5 tStart=0.959100004 tEnd=1 < [5/12] 17/21 tStart=0.293280033 tEnd=1 T 4 +SkOpAngle::afterPart {{{0.959100008,2.16359997}, {1.178042,2.11915237}, {1.38787913,2.0811573}, {1.58025348,2.04903817}}} id=5 +SkOpAngle::afterPart {{{0.959100008,2.16359997}, {1,2}}} id=6 +SkOpAngle::afterPart {{{0.959100008,2.16359997}, {-1.22742501,2.60748826}, {-4.3220339,3.6949153}, {0,6}}} id=5 +SkOpSegment::sortAngles [5] tStart=1 [10] +SkOpSegment::sortAngles [6] tStart=0 [11] +SkOpSegment::sortAngles [6] tStart=0.959100004 [18] +SkOpSegment::debugShowActiveSpans id=1 (0,6 0.293506175,4.82597542 1.04645705,3.96781874 1.58881736,3.34967732) t=0 (0,6) tEnd=1 windSum=? windValue=1 oppValue=0 +SkOpSegment::debugShowActiveSpans id=2 (1.58881736,3.34967732 2.89432383,1.86175978 2.97965813,1.76450205 -7.5,2) t=0 (1.58881736,3.34967732) tEnd=0.481912781 windSum=? windValue=1 oppValue=0 +SkOpSegment::debugShowActiveSpans id=2 (1.58881736,3.34967732 2.89432383,1.86175978 2.97965813,1.76450205 -7.5,2) t=0.481912781 (1.58025348,2.04903817) tEnd=0.538493706 windSum=? windValue=1 oppValue=0 +SkOpSegment::debugShowActiveSpans id=2 (1.58881736,3.34967732 2.89432383,1.86175978 2.97965813,1.76450205 -7.5,2) t=0.538493706 (1.17718506,1.99055469) tEnd=1 windSum=? windValue=1 oppValue=0 +SkOpSegment::debugShowActiveSpans id=3 (-7.5,2 0,6) t=0 (-7.5,2) tEnd=1 windSum=? windValue=1 oppValue=0 +SkOpSegment::debugShowActiveSpans id=4 (1,2 2.16902828,1.93847215 2.61688614,1.89965844 2.61714315,1.90242553) t=0 (1,2) tEnd=0.0521913275 windSum=? windValue=1 oppValue=0 +SkOpSegment::debugShowActiveSpans id=4 (1,2 2.16902828,1.93847215 2.61688614,1.89965844 2.61714315,1.90242553) t=0.0521913275 (1.17718506,1.99055469) tEnd=1 windSum=? windValue=1 oppValue=0 +SkOpSegment::debugShowActiveSpans id=5 (2.61714315,1.90242553 2.61827874,1.91464937 -6.11562443,2.7383337 0,6) t=0 (2.61714315,1.90242553) tEnd=0.222514468 windSum=? windValue=1 oppValue=0 +SkOpSegment::debugShowActiveSpans id=5 (2.61714315,1.90242553 2.61827874,1.91464937 -6.11562443,2.7383337 0,6) t=0.222514468 (1.58025348,2.04903817) tEnd=0.293280033 windSum=? windValue=1 oppValue=0 +SkOpSegment::debugShowActiveSpans id=5 (2.61714315,1.90242553 2.61827874,1.91464937 -6.11562443,2.7383337 0,6) t=0.293280033 (0.959100008,2.16359997) tEnd=1 windSum=? windValue=1 oppValue=0 +SkOpSegment::debugShowActiveSpans id=6 (0,6 1,2) t=0 (0,6) tEnd=0.959100004 windSum=? windValue=1 oppValue=0 +SkOpSegment::debugShowActiveSpans id=6 (0,6 1,2) t=0.959100004 (0.959100008,2.16359997) tEnd=1 windSum=? windValue=1 oppValue=0 -SkOpSegment::findTop- baseAngle -SkOpAngle::dumpOne [3/23] next=2/24 sect=21/21 s=0 [5] e=0.212962933 [14] sgn=-1 windVal=1 windSum=? -SkOpAngle::dumpOne [2/24] next=3/23 sect=22/21 s=1 [4] e=0.602095725 [13] sgn=1 windVal=1 windSum=? +SkOpAngle::dumpOne [4/8] next=2/5 sect=1/1 s=0.0521913275 [14] e=1 [8] sgn=-1 windVal=1 windSum=? operand +SkOpAngle::dumpOne [2/5] next=4/7 sect=13/17 s=0.538493706 [13] e=1 [4] sgn=-1 windVal=1 windSum=? stop +SkOpAngle::dumpOne [4/7] next=2/4 sect=17/17 s=0.0521913275 [14] e=0 [7] sgn=1 windVal=1 windSum=? operand +SkOpAngle::dumpOne [2/4] next=4/8 sect=29/29 s=0.538493706 [13] e=0.481912781 [15] sgn=1 windVal=1 windSum=? stop -SkOpSegment::findTop- firstAngle -SkOpAngle::dumpOne [3/23] next=2/24 sect=21/21 s=0 [5] e=0.212962933 [14] sgn=-1 windVal=1 windSum=? -SkOpAngle::dumpOne [2/24] next=3/23 sect=22/21 s=1 [4] e=0.602095725 [13] sgn=1 windVal=1 windSum=? -SkOpSegment::findTop id=3 s=0.212962933 e=0 (+) cw=-1 swap=-1 inflections=-1 monotonic=1 -SkOpSegment::markWinding id=3 (4,0 3,5) t=0 [5] (4,0) tEnd=0.212962933 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0 -SkOpSegment::nextChase mismatched signs -SkOpSegment::markWinding id=2 (3.00889349,2.74555302 3.47366595,1.85088933 4,0.837722301 4,0) t=0.602095725 [13] (3.78703713,1.06481469) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0 -SkOpSegment::markWinding id=3 (4,0 3,5) t=0 [5] (4,0) tEnd=0.212962933 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0 -SkOpSegment::activeOp id=3 t=0.212962933 tEnd=0 op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1 -SkOpSegment::nextChase mismatched signs +SkOpAngle::dumpOne [4/8] next=2/5 sect=1/1 s=0.0521913275 [14] e=1 [8] sgn=-1 windVal=1 windSum=? operand +SkOpAngle::dumpOne [2/5] next=4/7 sect=13/17 s=0.538493706 [13] e=1 [4] sgn=-1 windVal=1 windSum=? stop +SkOpAngle::dumpOne [4/7] next=2/4 sect=17/17 s=0.0521913275 [14] e=0 [7] sgn=1 windVal=1 windSum=? operand +SkOpAngle::dumpOne [2/4] next=4/8 sect=29/29 s=0.538493706 [13] e=0.481912781 [15] sgn=1 windVal=1 windSum=? stop +SkDCubic::clockwise pt1dist=0.00263265113 pt2dist=-0.00745519926 +SkOpSegment::findTop id=4 s=1 e=0.0521913275 (+) cw=1 swap=0 inflections=1 monotonic=0 +SkOpSegment::markWinding id=4 (1,2 2.16902828,1.93847215 2.61688614,1.89965844 2.61714315,1.90242553) t=0.0521913275 [14] (1.17718506,1.99055469) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0 +SkOpSegment::markWinding id=4 (1,2 2.16902828,1.93847215 2.61688614,1.89965844 2.61714315,1.90242553) t=0.0521913275 [14] (1.17718506,1.99055469) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0 +SkOpSegment::markWinding id=5 (2.61714315,1.90242553 2.61827874,1.91464937 -6.11562443,2.7383337 0,6) t=0 [9] (2.61714315,1.90242553) tEnd=0.222514468 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0 +SkOpSegment::activeOp id=4 t=1 tEnd=0.0521913275 op=sect miFrom=0 miTo=0 suFrom=1 suTo=0 result=0 +SkOpSegment::markDone id=4 (1,2 2.16902828,1.93847215 2.61688614,1.89965844 2.61714315,1.90242553) t=0.0521913275 [14] (1.17718506,1.99055469) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0 +bridgeOp chase.append id=4 windSum=1 +SkOpSegment::markWinding id=2 (1.58881736,3.34967732 2.89432383,1.86175978 2.97965813,1.76450205 -7.5,2) t=0.538493706 [13] (1.17718506,1.99055469) tEnd=1 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=0 +SkOpSegment::markWinding id=3 (-7.5,2 0,6) t=0 [5] (-7.5,2) tEnd=1 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=0 +SkOpSegment::markAngle last segment=3 span=6 +SkOpSegment::markWinding id=4 (1,2 2.16902828,1.93847215 2.61688614,1.89965844 2.61714315,1.90242553) t=0 [7] (1,2) tEnd=0.0521913275 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=0 +SkOpSegment::markWinding id=6 (0,6 1,2) t=0.959100004 [18] (0.959100008,2.16359997) tEnd=1 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=0 +SkOpSegment::markAngle last segment=6 span=18 windSum=1 +SkOpSegment::markWinding id=2 (1.58881736,3.34967732 2.89432383,1.86175978 2.97965813,1.76450205 -7.5,2) t=0.481912781 [15] (1.58025348,2.04903817) tEnd=0.538493706 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0 +SkOpSegment::markAngle last segment=2 span=15 windSum=1 +SkOpSegment::debugShowActiveSpans id=1 (0,6 0.293506175,4.82597542 1.04645705,3.96781874 1.58881736,3.34967732) t=0 (0,6) tEnd=1 windSum=? windValue=1 oppValue=0 +SkOpSegment::debugShowActiveSpans id=2 (1.58881736,3.34967732 2.89432383,1.86175978 2.97965813,1.76450205 -7.5,2) t=0 (1.58881736,3.34967732) tEnd=0.481912781 windSum=? windValue=1 oppValue=0 +SkOpSegment::debugShowActiveSpans id=2 (1.58881736,3.34967732 2.89432383,1.86175978 2.97965813,1.76450205 -7.5,2) t=0.481912781 (1.58025348,2.04903817) tEnd=0.538493706 windSum=1 windValue=1 oppValue=0 +SkOpSegment::debugShowActiveSpans id=2 (1.58881736,3.34967732 2.89432383,1.86175978 2.97965813,1.76450205 -7.5,2) t=0.538493706 (1.17718506,1.99055469) tEnd=1 windSum=1 windValue=1 oppValue=0 +SkOpSegment::debugShowActiveSpans id=3 (-7.5,2 0,6) t=0 (-7.5,2) tEnd=1 windSum=1 windValue=1 oppValue=0 +SkOpSegment::debugShowActiveSpans id=4 (1,2 2.16902828,1.93847215 2.61688614,1.89965844 2.61714315,1.90242553) t=0 (1,2) tEnd=0.0521913275 windSum=1 windValue=1 oppValue=0 +SkOpSegment::debugShowActiveSpans id=5 (2.61714315,1.90242553 2.61827874,1.91464937 -6.11562443,2.7383337 0,6) t=0 (2.61714315,1.90242553) tEnd=0.222514468 windSum=1 windValue=1 oppValue=0 +SkOpSegment::debugShowActiveSpans id=5 (2.61714315,1.90242553 2.61827874,1.91464937 -6.11562443,2.7383337 0,6) t=0.222514468 (1.58025348,2.04903817) tEnd=0.293280033 windSum=? windValue=1 oppValue=0 +SkOpSegment::debugShowActiveSpans id=5 (2.61714315,1.90242553 2.61827874,1.91464937 -6.11562443,2.7383337 0,6) t=0.293280033 (0.959100008,2.16359997) tEnd=1 windSum=? windValue=1 oppValue=0 +SkOpSegment::debugShowActiveSpans id=6 (0,6 1,2) t=0 (0,6) tEnd=0.959100004 windSum=? windValue=1 oppValue=0 +SkOpSegment::debugShowActiveSpans id=6 (0,6 1,2) t=0.959100004 (0.959100008,2.16359997) tEnd=1 windSum=1 windValue=1 oppValue=0 +SkOpSegment::activeOp id=2 t=0.538493706 tEnd=1 op=sect miFrom=0 miTo=1 suFrom=1 suTo=1 result=1 SkOpSegment::findNextOp simple -SkOpSegment::markDone id=3 (4,0 3,5) t=0 [5] (4,0) tEnd=0.212962933 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0 -bridgeOp current id=3 from=(3.78703713,1.06481469) to=(4,0) -SkOpSegment::markWinding id=2 (3.00889349,2.74555302 3.47366595,1.85088933 4,0.837722301 4,0) t=0 [3] (3.00889349,2.74555302) tEnd=0.602095725 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0 -SkOpSegment::markWinding id=1 (3,5 1.8377223,5 2.36405635,3.98683286 3.00889349,2.74555302) t=0.860380171 [15] (2.75000095,3.24999785) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0 -SkOpSegment::markAngle last segment=1 span=15 windSum=-1 -SkOpSegment::markWinding id=3 (4,0 3,5) t=0.212962933 [14] (3.78703713,1.06481469) tEnd=0.5 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0 -SkOpSegment::markAngle last segment=3 span=21 windSum=? +SkOpSegment::markDone id=2 (1.58881736,3.34967732 2.89432383,1.86175978 2.97965813,1.76450205 -7.5,2) t=0.538493706 [13] (1.17718506,1.99055469) tEnd=1 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1 oppValue=0 +bridgeOp current id=2 from=(1.17718506,1.99055469) to=(-7.5,2) +path.moveTo(1.17718506,1.99055469); +path.cubicTo(-0.0773608461,1.85350549, -2.66357183,1.89131618, -7.5,2); +SkOpSegment::markWinding id=1 (0,6 0.293506175,4.82597542 1.04645705,3.96781874 1.58881736,3.34967732) t=0 [1] (0,6) tEnd=1 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=0 +SkOpSegment::markWinding id=2 (1.58881736,3.34967732 2.89432383,1.86175978 2.97965813,1.76450205 -7.5,2) t=0 [3] (1.58881736,3.34967732) tEnd=0.481912781 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=0 +SkOpSegment::markAngle last segment=2 span=15 windSum=1 +SkOpSegment::markWinding id=6 (0,6 1,2) t=0 [11] (0,6) tEnd=0.959100004 newWindSum=2 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=0 +SkOpSegment::markAngle last segment=6 span=18 windSum=1 +SkOpSegment::markWinding id=5 (2.61714315,1.90242553 2.61827874,1.91464937 -6.11562443,2.7383337 0,6) t=0.293280033 [17] (0.959100008,2.16359997) tEnd=1 newWindSum=2 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=0 +SkOpSegment::markAngle last segment=5 span=17 windSum=2 SkOpSegment::findNextOp -SkOpAngle::dumpOne [2/6] next=3/7 sect=5/5 s=0.602095725 [13] e=1 [4] sgn=-1 windVal=1 windSum=1 oppVal=0 oppSum=0 -SkOpAngle::dumpOne [3/7] next=2/5 sect=5/5 s=0.212962933 [14] e=0 [5] sgn=1 windVal=1 windSum=1 oppVal=0 oppSum=0 done -SkOpAngle::dumpOne [2/5] next=3/8 sect=21/21 s=0.602095725 [13] e=0 [3] sgn=1 windVal=1 windSum=-1 oppVal=0 oppSum=0 -SkOpAngle::dumpOne [3/8] next=2/6 sect=21/21 s=0.212962933 [14] e=0.5 [21] sgn=-1 windVal=1 windSum=-1 oppVal=0 oppSum=0 -SkOpSegment::activeOp id=3 t=0.212962933 tEnd=0 op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1 -SkOpSegment::activeOp id=2 t=0.602095725 tEnd=0 op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1 -SkOpSegment::findNextOp chase.append segment=1 span=15 windSum=-1 -SkOpSegment::activeOp id=3 t=0.212962933 tEnd=0.5 op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1 -SkOpSegment::findNextOp chase.append segment=3 span=21 windSum=-2147483647 -SkOpSegment::markDone id=2 (3.00889349,2.74555302 3.47366595,1.85088933 4,0.837722301 4,0) t=0.602095725 [13] (3.78703713,1.06481469) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0 -SkOpSegment::findNextOp from:[2] to:[3] start=4807220 end=4807892 -bridgeOp current id=2 from=(4,0) to=(3.78703713,1.06481469) -path.moveTo(3.78703713,1.06481469); -path.lineTo(4,0); -path.cubicTo(4,0.333333284, 3.91666675,0.694444358, 3.78703713,1.06481469); -path.close(); -SkOpSegment::debugShowActiveSpans id=1 (3,5 1.8377223,5 2.36405635,3.98683286 3.00889349,2.74555302) t=0 (3,5) tEnd=0.860379476 windSum=? windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=1 (3,5 1.8377223,5 2.36405635,3.98683286 3.00889349,2.74555302) t=0.860379476 (2.74999976,3.25000024) tEnd=0.860380171 windSum=? windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=1 (3,5 1.8377223,5 2.36405635,3.98683286 3.00889349,2.74555302) t=0.860380171 (2.75000095,3.24999785) tEnd=1 windSum=-1 windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=2 (3.00889349,2.74555302 3.47366595,1.85088933 4,0.837722301 4,0) t=0 (3.00889349,2.74555302) tEnd=0.602095725 windSum=-1 windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=3 (4,0 3,5) t=0.212962933 (3.78703713,1.06481469) tEnd=0.5 windSum=-1 windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=3 (4,0 3,5) t=0.5 (3.5,2.5) tEnd=0.57768066 windSum=? windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=3 (4,0 3,5) t=0.57768066 (3.42231941,2.88840342) tEnd=1 windSum=? windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=4 (2,4 1.18350339,4 1.53367352,3.83333325 2.2340138,3.5) t=0 (2,4) tEnd=1 windSum=? windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0 (2.2340138,3.5) tEnd=0.155050964 windSum=? windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0.155050964 (2.74999976,3.25000024) tEnd=0.155051471 windSum=? windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0.155051471 (2.75000095,3.24999785) tEnd=0.338765871 windSum=? windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0.338765871 (3.42231941,2.88840342) tEnd=1 windSum=? windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=6 (5,1 2,4) t=0 (5,1) tEnd=0.5 windSum=? windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=6 (5,1 2,4) t=0.5 (3.5,2.5) tEnd=0.750000104 windSum=? windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=6 (5,1 2,4) t=0.750000104 (2.74999976,3.25000024) tEnd=1 windSum=? windValue=1 oppValue=0 -SkOpSegment::activeOp id=3 t=0.5 tEnd=0.212962933 op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1 -SkOpSegment::findNextOp -SkOpAngle::dumpOne [3/8] next=2/6 sect=21/21 s=0.212962933 [14] e=0.5 [21] sgn=-1 windVal=1 windSum=-1 oppVal=0 oppSum=0 -SkOpAngle::dumpOne [2/6] next=3/7 sect=5/5 s=0.602095725 [13] e=1 [4] sgn=-1 windVal=1 windSum=1 oppVal=0 oppSum=0 done -SkOpAngle::dumpOne [3/7] next=2/5 sect=5/5 s=0.212962933 [14] e=0 [5] sgn=1 windVal=1 windSum=1 oppVal=0 oppSum=0 done -SkOpAngle::dumpOne [2/5] next=3/8 sect=21/21 s=0.602095725 [13] e=0 [3] sgn=1 windVal=1 windSum=-1 oppVal=0 oppSum=0 -SkOpSegment::activeOp id=2 t=0.602095725 tEnd=1 op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1 -SkOpSegment::activeOp id=3 t=0.212962933 tEnd=0 op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1 -SkOpSegment::activeOp id=2 t=0.602095725 tEnd=0 op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1 -SkOpSegment::markDone id=3 (4,0 3,5) t=0.212962933 [14] (3.78703713,1.06481469) tEnd=0.5 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0 -SkOpSegment::findNextOp from:[3] to:[2] start=4807124 end=4805876 -bridgeOp current id=3 from=(3.5,2.5) to=(3.78703713,1.06481469) +SkOpAngle::dumpOne [3/6] next=1/1 sect=13/13 s=1 [6] e=0 [5] sgn=1 windVal=1 windSum=1 oppVal=0 oppSum=1 +SkOpAngle::dumpOne [1/1] next=6/14 sect=5/5 s=0 [1] e=1 [2] sgn=-1 windVal=1 windSum=1 oppVal=0 oppSum=1 +SkOpAngle::dumpOne [6/14] next=5/13 sect=5/5 s=0 [11] e=0.959100004 [18] sgn=-1 windVal=1 windSum=2 oppVal=0 oppSum=1 operand +SkOpAngle::dumpOne [5/13] next=3/6 sect=13/5 s=1 [10] e=0.293280033 [17] sgn=1 windVal=1 windSum=2 oppVal=0 oppSum=1 operand +SkOpSegment::activeOp id=1 t=0 tEnd=1 op=sect miFrom=0 miTo=1 suFrom=1 suTo=1 result=1 +SkOpSegment::findNextOp chase.append segment=2 span=15 windSum=1 +SkOpSegment::activeOp id=6 t=0 tEnd=0.959100004 op=sect miFrom=1 miTo=1 suFrom=1 suTo=1 result=0 +SkOpSegment::markDone id=6 (0,6 1,2) t=0 [11] (0,6) tEnd=0.959100004 newWindSum=2 newOppSum=1 oppSum=1 windSum=2 windValue=1 oppValue=0 +SkOpSegment::findNextOp chase.append segment=6 span=18 windSum=1 +SkOpSegment::activeOp id=5 t=1 tEnd=0.293280033 op=sect miFrom=1 miTo=1 suFrom=1 suTo=1 result=0 +SkOpSegment::markDone id=5 (2.61714315,1.90242553 2.61827874,1.91464937 -6.11562443,2.7383337 0,6) t=0.293280033 [17] (0.959100008,2.16359997) tEnd=1 newWindSum=2 newOppSum=1 oppSum=1 windSum=2 windValue=1 oppValue=0 +SkOpSegment::findNextOp chase.append segment=5 span=17 windSum=2 +SkOpSegment::markDone id=3 (-7.5,2 0,6) t=0 [5] (-7.5,2) tEnd=1 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1 oppValue=0 +SkOpSegment::findNextOp from:[3] to:[1] start=43971536 end=43971632 +bridgeOp current id=3 from=(-7.5,2) to=(0,6) SkOpSegment::findNextOp simple -SkOpSegment::markDone id=2 (3.00889349,2.74555302 3.47366595,1.85088933 4,0.837722301 4,0) t=0 [3] (3.00889349,2.74555302) tEnd=0.602095725 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0 -bridgeOp current id=2 from=(3.78703713,1.06481469) to=(3.00889349,2.74555302) -path.moveTo(3.5,2.5); -path.lineTo(3.78703713,1.06481469); -path.cubicTo(3.59088588,1.62524688, 3.2887311,2.20687985, 3.00889349,2.74555302); +SkOpSegment::markDone id=1 (0,6 0.293506175,4.82597542 1.04645705,3.96781874 1.58881736,3.34967732) t=0 [1] (0,6) tEnd=1 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1 oppValue=0 +bridgeOp current id=1 from=(0,6) to=(1.58881736,3.34967732) +path.lineTo(0,6); +path.cubicTo(0.293506175,4.82597542, 1.04645705,3.96781874, 1.58881736,3.34967732); +SkOpSegment::markWinding id=5 (2.61714315,1.90242553 2.61827874,1.91464937 -6.11562443,2.7383337 0,6) t=0.222514468 [16] (1.58025348,2.04903817) tEnd=0.293280033 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=0 +SkOpSegment::markAngle last segment=5 span=17 windSum=2 SkOpSegment::findNextOp -SkOpAngle::dumpOne [1/4] next=1/3 sect=5/5 s=0.860380171 [15] e=1 [2] sgn=-1 windVal=1 windSum=-1 oppVal=0 oppSum=0 -SkOpAngle::dumpOne [1/3] next=5/16 sect=19/19 s=0.860380171 [15] e=0.860379476 [17] sgn=1 windVal=1 windSum=? -SkOpAngle::dumpOne [5/16] next=5/15 sect=1/1 s=0.155051471 [16] e=0.338765871 [20] sgn=-1 windVal=1 windSum=? unorderable operand -SkOpAngle::dumpOne [5/15] next=1/4 sect=1/2 s=0.155051471 [16] e=0.155050964 [23] sgn=1 windVal=1 windSum=? unorderable operand -SkOpSegment::activeOp id=1 t=0.860380171 tEnd=0.860379476 op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1 -SkOpSegment::activeOp id=5 t=0.155051471 tEnd=0.338765871 op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1 -SkOpSegment::activeOp id=5 t=0.155051471 tEnd=0.155050964 op=diff miFrom=1 miTo=1 suFrom=1 suTo=0 result=1 -SkOpSegment::markDone id=1 (3,5 1.8377223,5 2.36405635,3.98683286 3.00889349,2.74555302) t=0.860380171 [15] (2.75000095,3.24999785) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0 -SkOpSegment::findNextOp from:[1] to:[1] start=4807316 end=4807508 -bridgeOp current id=1 from=(3.00889349,2.74555302) to=(2.75000095,3.24999785) -path.cubicTo(2.91886139,2.9188602, 2.83113956,3.08772087, 2.75000095,3.24999785); +SkOpAngle::dumpOne [2/2] next=5/9 sect=29/25 s=0.481912781 [15] e=0 [3] sgn=1 windVal=1 windSum=1 oppVal=0 oppSum=1 +SkOpAngle::dumpOne [5/9] next=2/3 sect=1/1 s=0.222514468 [16] e=0 [9] sgn=1 windVal=1 windSum=1 oppVal=0 oppSum=0 operand +SkOpAngle::dumpOne [2/3] next=5/10 sect=13/13 s=0.481912781 [15] e=0.538493706 [13] sgn=-1 windVal=1 windSum=1 oppVal=0 oppSum=0 +SkOpAngle::dumpOne [5/10] next=2/2 sect=17/17 s=0.222514468 [16] e=0.293280033 [17] sgn=-1 windVal=1 windSum=1 oppVal=0 oppSum=1 operand +SkOpSegment::activeOp id=5 t=0.222514468 tEnd=0 op=sect miFrom=0 miTo=0 suFrom=1 suTo=0 result=0 +SkOpSegment::markDone id=5 (2.61714315,1.90242553 2.61827874,1.91464937 -6.11562443,2.7383337 0,6) t=0 [9] (2.61714315,1.90242553) tEnd=0.222514468 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0 +SkOpSegment::activeOp id=2 t=0.481912781 tEnd=0.538493706 op=sect miFrom=0 miTo=1 suFrom=0 suTo=0 result=0 +SkOpSegment::markDone id=2 (1.58881736,3.34967732 2.89432383,1.86175978 2.97965813,1.76450205 -7.5,2) t=0.481912781 [15] (1.58025348,2.04903817) tEnd=0.538493706 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0 +SkOpSegment::activeOp id=5 t=0.222514468 tEnd=0.293280033 op=sect miFrom=1 miTo=1 suFrom=0 suTo=1 result=1 +SkOpSegment::markDone id=2 (1.58881736,3.34967732 2.89432383,1.86175978 2.97965813,1.76450205 -7.5,2) t=0 [3] (1.58881736,3.34967732) tEnd=0.481912781 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1 oppValue=0 +SkOpSegment::findNextOp from:[2] to:[5] start=2579180 end=2579276 +bridgeOp current id=2 from=(1.58881736,3.34967732) to=(1.58025348,2.04903817) +path.cubicTo(2.2179575,2.63263083, 2.56372523,2.23855114, 1.58025348,2.04903817); SkOpSegment::findNextOp -SkOpAngle::dumpOne [1/2] next=5/14 sect=3/3 s=0.860379476 [17] e=0.860380171 [15] sgn=-1 windVal=1 windSum=? -SkOpAngle::dumpOne [5/14] next=5/13 sect=17/17 s=0.155050964 [23] e=0.155051471 [16] sgn=-1 windVal=1 windSum=? unorderable operand -SkOpAngle::dumpOne [5/13] next=6/22 sect=17/17 s=0.155050964 [23] e=0 [9] sgn=1 windVal=1 windSum=? unorderable operand -SkOpAngle::dumpOne [6/22] next=1/1 sect=19/19 s=0.750000104 [18] e=1 [12] sgn=-1 windVal=1 windSum=? operand -SkOpAngle::dumpOne [1/1] next=6/21 sect=21/25 s=0.860379476 [17] e=0 [1] sgn=1 windVal=1 windSum=? -SkOpAngle::dumpOne [6/21] next=1/2 sect=3/3 s=0.750000104 [18] e=0.5 [22] sgn=1 windVal=1 windSum=? operand -SkOpSegment::markDone id=1 (3,5 1.8377223,5 2.36405635,3.98683286 3.00889349,2.74555302) t=0.860379476 [17] (2.74999976,3.25000024) tEnd=0.860380171 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=1 oppValue=0 -SkOpSegment::markWinding id=6 (5,1 2,4) t=0.5 [22] (3.5,2.5) tEnd=0.750000104 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=0 -SkOpSegment::markAngle last segment=6 span=18 windSum=? -SkOpSegment::markWinding id=3 (4,0 3,5) t=0.5 [21] (3.5,2.5) tEnd=0.57768066 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=0 -SkOpSegment::markAngle last segment=3 span=19 windSum=? -SkOpSegment::markWinding id=6 (5,1 2,4) t=0 [11] (5,1) tEnd=0.5 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0 -SkOpSegment::markWinding id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0.338765871 [20] (3.42231941,2.88840342) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0 -SkOpSegment::markAngle last segment=5 span=20 windSum=1 -SkOpSegment::debugShowActiveSpans id=1 (3,5 1.8377223,5 2.36405635,3.98683286 3.00889349,2.74555302) t=0 (3,5) tEnd=0.860379476 windSum=? windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=3 (4,0 3,5) t=0.5 (3.5,2.5) tEnd=0.57768066 windSum=-1 windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=3 (4,0 3,5) t=0.57768066 (3.42231941,2.88840342) tEnd=1 windSum=? windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=4 (2,4 1.18350339,4 1.53367352,3.83333325 2.2340138,3.5) t=0 (2,4) tEnd=1 windSum=? windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0 (2.2340138,3.5) tEnd=0.155050964 windSum=? windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0.155050964 (2.74999976,3.25000024) tEnd=0.155051471 windSum=? windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0.155051471 (2.75000095,3.24999785) tEnd=0.338765871 windSum=? windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0.338765871 (3.42231941,2.88840342) tEnd=1 windSum=1 windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=6 (5,1 2,4) t=0 (5,1) tEnd=0.5 windSum=1 windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=6 (5,1 2,4) t=0.5 (3.5,2.5) tEnd=0.750000104 windSum=1 windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=6 (5,1 2,4) t=0.750000104 (2.74999976,3.25000024) tEnd=1 windSum=? windValue=1 oppValue=0 -SkOpSegment::activeOp id=6 t=0.5 tEnd=0.750000104 op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1 -SkOpSegment::markWinding id=1 (3,5 1.8377223,5 2.36405635,3.98683286 3.00889349,2.74555302) t=0 [1] (3,5) tEnd=0.860379476 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=0 -SkOpSegment::markWinding id=3 (4,0 3,5) t=0.57768066 [19] (3.42231941,2.88840342) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=0 -SkOpSegment::markAngle last segment=3 span=19 windSum=-1 +SkOpAngle::dumpOne [5/11] next=6/16 sect=1/1 s=0.293280033 [17] e=0.222514468 [16] sgn=1 windVal=1 windSum=1 oppVal=0 oppSum=1 operand +SkOpAngle::dumpOne [6/16] next=5/12 sect=5/5 s=0.959100004 [18] e=1 [12] sgn=-1 windVal=1 windSum=1 oppVal=0 oppSum=1 operand +SkOpAngle::dumpOne [5/12] next=6/15 sect=17/21 s=0.293280033 [17] e=1 [10] sgn=-1 windVal=1 windSum=2 oppVal=0 oppSum=1 done operand +SkOpAngle::dumpOne [6/15] next=5/11 sect=21/21 s=0.959100004 [18] e=0 [11] sgn=1 windVal=1 windSum=2 oppVal=0 oppSum=1 done operand +SkOpSegment::activeOp id=6 t=0.959100004 tEnd=1 op=sect miFrom=1 miTo=1 suFrom=0 suTo=1 result=1 +SkOpSegment::activeOp id=5 t=0.293280033 tEnd=1 op=sect miFrom=1 miTo=1 suFrom=1 suTo=1 result=0 +SkOpSegment::activeOp id=6 t=0.959100004 tEnd=0 op=sect miFrom=1 miTo=1 suFrom=1 suTo=1 result=0 +SkOpSegment::markDone id=5 (2.61714315,1.90242553 2.61827874,1.91464937 -6.11562443,2.7383337 0,6) t=0.222514468 [16] (1.58025348,2.04903817) tEnd=0.293280033 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1 oppValue=0 +SkOpSegment::findNextOp from:[5] to:[6] start=2579372 end=2578764 +bridgeOp current id=5 from=(1.58025348,2.04903817) to=(0.959100008,2.16359997) +path.cubicTo(1.38787913,2.08115721, 1.17804205,2.11915231, 0.959100008,2.16359997); +SkOpSegment::findNextOp simple +SkOpSegment::markDone id=6 (0,6 1,2) t=0.959100004 [18] (0.959100008,2.16359997) tEnd=1 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1 oppValue=0 +bridgeOp current id=6 from=(0.959100008,2.16359997) to=(1,2) SkOpSegment::findNextOp -SkOpAngle::dumpOne [6/21] next=1/2 sect=3/3 s=0.750000104 [18] e=0.5 [22] sgn=1 windVal=1 windSum=1 oppVal=0 oppSum=-1 operand -SkOpAngle::dumpOne [1/2] next=5/14 sect=3/3 s=0.860379476 [17] e=0.860380171 [15] sgn=-1 windVal=1 windSum=? done -SkOpAngle::dumpOne [5/14] next=5/13 sect=17/17 s=0.155050964 [23] e=0.155051471 [16] sgn=-1 windVal=1 windSum=? unorderable operand -SkOpAngle::dumpOne [5/13] next=6/22 sect=17/17 s=0.155050964 [23] e=0 [9] sgn=1 windVal=1 windSum=? unorderable operand -SkOpAngle::dumpOne [6/22] next=1/1 sect=19/19 s=0.750000104 [18] e=1 [12] sgn=-1 windVal=1 windSum=? operand -SkOpAngle::dumpOne [1/1] next=6/21 sect=21/25 s=0.860379476 [17] e=0 [1] sgn=1 windVal=1 windSum=-1 oppVal=0 oppSum=1 -SkOpSegment::activeOp id=1 t=0.860379476 tEnd=0.860380171 op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1 -SkOpSegment::activeOp id=5 t=0.155050964 tEnd=0.155051471 op=diff miFrom=0 miTo=0 suFrom=0 suTo=1 result=0 -SkOpSegment::markDone id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0.155050964 [23] (2.74999976,3.25000024) tEnd=0.155051471 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=1 oppValue=0 -SkOpSegment::activeOp id=5 t=0.155050964 tEnd=0 op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0 -SkOpSegment::markDone id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0 [9] (2.2340138,3.5) tEnd=0.155050964 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=1 oppValue=0 -SkOpSegment::markDone id=4 (2,4 1.18350339,4 1.53367352,3.83333325 2.2340138,3.5) t=0 [7] (2,4) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=1 oppValue=0 -SkOpSegment::markDone id=6 (5,1 2,4) t=0.750000104 [18] (2.74999976,3.25000024) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=1 oppValue=0 -SkOpSegment::activeOp id=6 t=0.750000104 tEnd=1 op=diff miFrom=0 miTo=0 suFrom=0 suTo=1 result=0 -SkOpSegment::activeOp id=1 t=0.860379476 tEnd=0 op=diff miFrom=0 miTo=1 suFrom=1 suTo=1 result=0 -SkOpSegment::markDone id=1 (3,5 1.8377223,5 2.36405635,3.98683286 3.00889349,2.74555302) t=0 [1] (3,5) tEnd=0.860379476 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1 oppValue=0 -SkOpSegment::markDone id=3 (4,0 3,5) t=0.57768066 [19] (3.42231941,2.88840342) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1 oppValue=0 -SkOpSegment::findNextOp chase.append segment=3 span=19 windSum=-1 -SkOpSegment::markDone id=6 (5,1 2,4) t=0.5 [22] (3.5,2.5) tEnd=0.750000104 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1 oppValue=0 -SkOpSegment::findNextOp from:[6] to:[1] start=4807508 end=4807316 -bridgeOp current id=6 from=(3.5,2.5) to=(2.74999976,3.25000024) -path.moveTo(3.5,2.5); -path.lineTo(2.74999976,3.25000024); -SkOpSegment::debugShowActiveSpans id=3 (4,0 3,5) t=0.5 (3.5,2.5) tEnd=0.57768066 windSum=-1 windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0.155051471 (2.75000095,3.24999785) tEnd=0.338765871 windSum=? windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0.338765871 (3.42231941,2.88840342) tEnd=1 windSum=1 windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=6 (5,1 2,4) t=0 (5,1) tEnd=0.5 windSum=1 windValue=1 oppValue=0 -SkOpSegment::activeOp id=5 t=0.338765871 tEnd=1 op=diff miFrom=0 miTo=0 suFrom=0 suTo=1 result=0 -SkOpSegment::markDone id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0.338765871 [20] (3.42231941,2.88840342) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0 -SkOpSegment::markDone id=6 (5,1 2,4) t=0 [11] (5,1) tEnd=0.5 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0 -bridgeOp chase.append id=6 windSum=1 -SkOpSegment::debugShowActiveSpans id=3 (4,0 3,5) t=0.5 (3.5,2.5) tEnd=0.57768066 windSum=-1 windValue=1 oppValue=0 -SkOpSegment::debugShowActiveSpans id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0.155051471 (2.75000095,3.24999785) tEnd=0.338765871 windSum=? windValue=1 oppValue=0 -SkOpSegment::activeOp id=3 t=0.5 tEnd=0.57768066 op=diff miFrom=1 miTo=0 suFrom=1 suTo=1 result=0 -SkOpSegment::markDone id=3 (4,0 3,5) t=0.5 [21] (3.5,2.5) tEnd=0.57768066 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1 oppValue=0 -SkOpSegment::markWinding id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0.155051471 [16] (2.75000095,3.24999785) tEnd=0.338765871 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=0 -SkOpSegment::markAngle last segment=5 span=16 windSum=1 -SkOpSegment::debugShowActiveSpans id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0.155051471 (2.75000095,3.24999785) tEnd=0.338765871 windSum=1 windValue=1 oppValue=0 -SkOpSegment::activeOp id=5 t=0.338765871 tEnd=0.155051471 op=diff miFrom=1 miTo=1 suFrom=1 suTo=0 result=1 -SkOpSegment::markDone id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) t=0.155051471 [16] (2.75000095,3.24999785) tEnd=0.338765871 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1 oppValue=0 +SkOpAngle::dumpOne [4/7] next=2/4 sect=17/17 s=0.0521913275 [14] e=0 [7] sgn=1 windVal=1 windSum=1 oppVal=0 oppSum=1 operand +SkOpAngle::dumpOne [2/4] next=4/8 sect=29/29 s=0.538493706 [13] e=0.481912781 [15] sgn=1 windVal=1 windSum=1 oppVal=0 oppSum=0 done stop +SkOpAngle::dumpOne [4/8] next=2/5 sect=1/1 s=0.0521913275 [14] e=1 [8] sgn=-1 windVal=1 windSum=1 oppVal=0 oppSum=0 done operand +SkOpAngle::dumpOne [2/5] next=4/7 sect=13/17 s=0.538493706 [13] e=1 [4] sgn=-1 windVal=1 windSum=1 oppVal=0 oppSum=1 done stop +SkOpSegment::activeOp id=2 t=0.538493706 tEnd=0.481912781 op=sect miFrom=1 miTo=0 suFrom=0 suTo=0 result=0 +SkOpSegment::activeOp id=4 t=0.0521913275 tEnd=1 op=sect miFrom=0 miTo=0 suFrom=0 suTo=1 result=0 +SkOpSegment::activeOp id=2 t=0.538493706 tEnd=1 op=sect miFrom=0 miTo=1 suFrom=1 suTo=1 result=1 +SkOpSegment::markDone id=4 (1,2 2.16902828,1.93847215 2.61688614,1.89965844 2.61714315,1.90242553) t=0 [7] (1,2) tEnd=0.0521913275 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1 oppValue=0 +SkOpSegment::findNextOp from:[4] to:[2] start=2578892 end=2577740 +bridgeOp current id=4 from=(1,2) to=(1.17718506,1.99055469) +path.lineTo(1,2); +path.cubicTo(1.0610131,1.99678874, 1.12006187,1.99363947, 1.17718506,1.99055469); +path.close(); </div> </div> @@ -303,7 +229,7 @@ SkOpSegment::markDone id=5 (2.2340138,3.5 3.2491498,3.01683664 5,2.18350339 5,1) <script type="text/javascript"> var testDivs = [ - cubics6d, + loops59i, ]; var decimal_places = 3; // make this 3 to show more precision |