aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gyp/core.gypi2
-rw-r--r--include/core/SkPath.h2
-rw-r--r--src/core/SkPath.cpp12
-rw-r--r--src/pathops/SkDCubicLineIntersection.cpp6
-rw-r--r--src/pathops/SkOpContour.cpp4
-rw-r--r--src/pathops/SkOpContour.h2
-rw-r--r--src/pathops/SkOpSegment.cpp33
-rw-r--r--src/pathops/SkOpSegment.h16
-rw-r--r--src/pathops/SkPathOpsBounds.cpp51
-rw-r--r--src/pathops/SkPathOpsBounds.h23
-rw-r--r--src/pathops/SkPathOpsCommon.cpp6
-rw-r--r--src/pathops/SkPathOpsCommon.h2
-rw-r--r--src/pathops/SkPathOpsConic.cpp22
-rw-r--r--src/pathops/SkPathOpsConic.h6
-rw-r--r--src/pathops/SkPathOpsCubic.cpp89
-rw-r--r--src/pathops/SkPathOpsCubic.h6
-rw-r--r--src/pathops/SkPathOpsCurve.cpp146
-rw-r--r--src/pathops/SkPathOpsCurve.h53
-rw-r--r--src/pathops/SkPathOpsDebug.h10
-rw-r--r--src/pathops/SkPathOpsOp.cpp4
-rw-r--r--src/pathops/SkPathOpsQuad.cpp31
-rw-r--r--src/pathops/SkPathOpsQuad.h4
-rw-r--r--src/pathops/SkPathOpsRect.cpp61
-rw-r--r--src/pathops/SkPathOpsRect.h20
-rw-r--r--src/pathops/SkPathOpsSimplify.cpp4
-rw-r--r--tests/PathOpsBoundsTest.cpp21
-rw-r--r--tests/PathOpsCubicLineIntersectionTest.cpp3
-rw-r--r--tests/PathOpsDCubicTest.cpp2
-rw-r--r--tests/PathOpsExtendedTest.cpp10
-rw-r--r--tests/PathOpsOpTest.cpp861
-rw-r--r--tests/PathOpsTestCommon.cpp12
-rw-r--r--tools/pathops_sorter.htm4
-rw-r--r--tools/pathops_visualizer.htm500
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