aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/pathops/SkAddIntersections.cpp3
-rwxr-xr-xsrc/pathops/SkOpCoincidence.cpp3
-rw-r--r--src/pathops/SkOpContour.cpp6
-rw-r--r--src/pathops/SkOpContour.h2
-rw-r--r--src/pathops/SkOpEdgeBuilder.cpp140
-rw-r--r--src/pathops/SkOpSegment.cpp2
-rw-r--r--src/pathops/SkPathOpsDebug.cpp2
-rw-r--r--src/pathops/SkPathOpsDebug.h4
-rw-r--r--src/pathops/SkPathOpsOp.cpp2
-rw-r--r--src/pathops/SkPathOpsTSect.h3
-rw-r--r--src/pathops/SkReduceOrder.cpp7
-rw-r--r--src/pathops/SkReduceOrder.h4
-rw-r--r--tests/PathOpsConicLineIntersectionTest.cpp5
-rw-r--r--tests/PathOpsCubicIntersectionTest.cpp5
-rw-r--r--tests/PathOpsOpTest.cpp22
-rw-r--r--tests/PathOpsQuadIntersectionTest.cpp3
-rw-r--r--tests/PathOpsSimplifyFailTest.cpp2
-rw-r--r--tests/PathOpsSimplifyTest.cpp8
-rw-r--r--tests/PathOpsThreeWayTest.cpp2
-rw-r--r--tools/pathops_sorter.htm33
-rw-r--r--tools/pathops_visualizer.htm226
21 files changed, 329 insertions, 155 deletions
diff --git a/src/pathops/SkAddIntersections.cpp b/src/pathops/SkAddIntersections.cpp
index 2abf67a09d..b3a82cdeca 100644
--- a/src/pathops/SkAddIntersections.cpp
+++ b/src/pathops/SkAddIntersections.cpp
@@ -542,7 +542,8 @@ bool AddIntersectTs(SkOpContour* test, SkOpContour* next, SkOpCoincidence* coinc
SkTSwap(coinPtT[0], coinPtT[1]);
SkTSwap(testTAt, nextTAt);
}
- SkASSERT(coinPtT[0]->span()->t() < testTAt->span()->t());
+ SkASSERT(coincidence->globalState()->debugSkipAssert()
+ || coinPtT[0]->span()->t() < testTAt->span()->t());
if (coinPtT[0]->span()->deleted()) {
coinIndex = -1;
continue;
diff --git a/src/pathops/SkOpCoincidence.cpp b/src/pathops/SkOpCoincidence.cpp
index 1bbb82a9e0..d2874c3c5e 100755
--- a/src/pathops/SkOpCoincidence.cpp
+++ b/src/pathops/SkOpCoincidence.cpp
@@ -334,6 +334,9 @@ bool SkOpCoincidence::addEndMovedSpans(const SkOpSpan* base, const SkOpSpanBase*
}
SkOpSegment* writableSeg = const_cast<SkOpSegment*>(testSeg);
SkOpPtT* oppStart = writableSeg->addT(t);
+ if (oppStart == testPtT) {
+ continue;
+ }
SkOpSpan* writableBase = const_cast<SkOpSpan*>(base);
oppStart->span()->addOpp(writableBase);
if (oppStart->deleted()) {
diff --git a/src/pathops/SkOpContour.cpp b/src/pathops/SkOpContour.cpp
index 3b2318c306..981bd29573 100644
--- a/src/pathops/SkOpContour.cpp
+++ b/src/pathops/SkOpContour.cpp
@@ -10,7 +10,7 @@
#include "SkReduceOrder.h"
#include "SkTSort.h"
-SkOpSegment* SkOpContour::addCurve(SkPath::Verb verb, const SkPoint pts[4]) {
+SkOpSegment* SkOpContour::addCurve(SkPath::Verb verb, const SkPoint pts[4], SkScalar weight) {
SkChunkAlloc* allocator = this->globalState()->allocator();
switch (verb) {
case SkPath::kLine_Verb: {
@@ -24,7 +24,9 @@ SkOpSegment* SkOpContour::addCurve(SkPath::Verb verb, const SkPoint pts[4]) {
return appendSegment().addQuad(ptStorage, this);
} break;
case SkPath::kConic_Verb: {
- SkASSERT(0); // the original curve is a cubic, which will never reduce to a conic
+ SkPoint* ptStorage = SkOpTAllocator<SkPoint>::AllocateArray(allocator, 3);
+ memcpy(ptStorage, pts, sizeof(SkPoint) * 3);
+ return appendSegment().addConic(ptStorage, weight, this);
} break;
case SkPath::kCubic_Verb: {
SkPoint* ptStorage = SkOpTAllocator<SkPoint>::AllocateArray(allocator, 4);
diff --git a/src/pathops/SkOpContour.h b/src/pathops/SkOpContour.h
index acc6744f2a..4390fe4e1f 100644
--- a/src/pathops/SkOpContour.h
+++ b/src/pathops/SkOpContour.h
@@ -41,7 +41,7 @@ public:
appendSegment().addCubic(pts, this);
}
- SkOpSegment* addCurve(SkPath::Verb verb, const SkPoint pts[4]);
+ SkOpSegment* addCurve(SkPath::Verb verb, const SkPoint pts[4], SkScalar weight = 1);
SkOpSegment* addLine(SkPoint pts[2]) {
SkASSERT(pts[0] != pts[1]);
diff --git a/src/pathops/SkOpEdgeBuilder.cpp b/src/pathops/SkOpEdgeBuilder.cpp
index 36fc9ed161..d67ed44ddc 100644
--- a/src/pathops/SkOpEdgeBuilder.cpp
+++ b/src/pathops/SkOpEdgeBuilder.cpp
@@ -17,6 +17,26 @@ void SkOpEdgeBuilder::init() {
fSecondHalf = preFetch();
}
+// very tiny points cause numerical instability : don't allow them
+static void force_small_to_zero(SkPoint* pt) {
+ if (SkScalarAbs(pt->fX) < FLT_EPSILON_ORDERABLE_ERR) {
+ pt->fX = 0;
+ }
+ if (SkScalarAbs(pt->fY) < FLT_EPSILON_ORDERABLE_ERR) {
+ pt->fY = 0;
+ }
+}
+
+static bool can_add_curve(SkPath::Verb verb, SkPoint* curve) {
+ if (SkPath::kMove_Verb == verb) {
+ return false;
+ }
+ for (int index = 0; index < SkPathOpsVerbToPoints(verb); ++index) {
+ force_small_to_zero(&curve[index]);
+ }
+ return SkPath::kLine_Verb != verb || !SkDPoint::ApproximatelyEqual(curve[0], curve[1]);
+}
+
void SkOpEdgeBuilder::addOperand(const SkPath& path) {
SkASSERT(fPathVerbs.count() > 0 && fPathVerbs.end()[-1] == SkPath::kDone_Verb);
fPathVerbs.pop();
@@ -48,16 +68,6 @@ void SkOpEdgeBuilder::closeContour(const SkPoint& curveEnd, const SkPoint& curve
*fPathVerbs.append() = SkPath::kClose_Verb;
}
-// very tiny points cause numerical instability : don't allow them
-static void force_small_to_zero(SkPoint* pt) {
- if (SkScalarAbs(pt->fX) < FLT_EPSILON_ORDERABLE_ERR) {
- pt->fX = 0;
- }
- if (SkScalarAbs(pt->fY) < FLT_EPSILON_ORDERABLE_ERR) {
- pt->fY = 0;
- }
-}
-
int SkOpEdgeBuilder::preFetch() {
if (!fPath->isFinite()) {
fUnparseable = true;
@@ -107,8 +117,10 @@ int SkOpEdgeBuilder::preFetch() {
force_small_to_zero(&pts[2]);
curve[1] = pts[1];
curve[2] = pts[2];
- verb = SkReduceOrder::Conic(curve, iter.conicWeight(), pts);
- if (verb == SkPath::kMove_Verb) {
+ verb = SkReduceOrder::Quad(curve, pts);
+ if (SkPath::kQuad_Verb == verb && 1 != iter.conicWeight()) {
+ verb = SkPath::kConic_Verb;
+ } else if (verb == SkPath::kMove_Verb) {
continue; // skip degenerate points
}
break;
@@ -183,49 +195,83 @@ bool SkOpEdgeBuilder::walk() {
fCurrentContour->addLine(pointsPtr);
break;
case SkPath::kQuad_Verb:
- fCurrentContour->addQuad(pointsPtr);
- break;
- case SkPath::kConic_Verb:
- fCurrentContour->addConic(pointsPtr, *weightPtr++);
- break;
- case SkPath::kCubic_Verb: {
- // Split complex cubics (such as self-intersecting curves or
- // ones with difficult curvature) in two before proceeding.
- // This can be required for intersection to succeed.
- SkScalar splitT;
- if (SkDCubic::ComplexBreak(pointsPtr, &splitT)) {
- SkPoint cubicPair[7];
- SkChopCubicAt(pointsPtr, cubicPair, splitT);
- if (!SkScalarsAreFinite(&cubicPair[0].fX, SK_ARRAY_COUNT(cubicPair) * 2)) {
- return false;
- }
- SkPoint cStorage[2][4];
- SkPath::Verb v1 = SkReduceOrder::Cubic(&cubicPair[0], cStorage[0]);
- SkPath::Verb v2 = SkReduceOrder::Cubic(&cubicPair[3], cStorage[1]);
- if (v1 != SkPath::kMove_Verb && v2 != SkPath::kMove_Verb) {
- SkPoint* curve1 = v1 == SkPath::kCubic_Verb ? &cubicPair[0] : cStorage[0];
- SkPoint* curve2 = v2 == SkPath::kCubic_Verb ? &cubicPair[3] : cStorage[1];
- for (int index = 0; index < SkPathOpsVerbToPoints(v1); ++index) {
- force_small_to_zero(&curve1[index]);
+ {
+ SkVector v1 = pointsPtr[1] - pointsPtr[0];
+ SkVector v2 = pointsPtr[2] - pointsPtr[1];
+ if (v1.dot(v2) < 0) {
+ SkPoint pair[5];
+ if (SkChopQuadAtMaxCurvature(pointsPtr, pair) == 1) {
+ goto addOneQuad;
}
- for (int index = 0; index < SkPathOpsVerbToPoints(v2); ++index) {
- force_small_to_zero(&curve2[index]);
+ if (!SkScalarsAreFinite(&pair[0].fX, SK_ARRAY_COUNT(pair) * 2)) {
+ return false;
}
- if (SkPath::kLine_Verb != v1 ||
- !SkDPoint::ApproximatelyEqual(curve1[0], curve1[1])) {
+ SkPoint cStorage[2][2];
+ SkPath::Verb v1 = SkReduceOrder::Quad(&pair[0], cStorage[0]);
+ SkPath::Verb v2 = SkReduceOrder::Quad(&pair[2], cStorage[1]);
+ SkPoint* curve1 = v1 == SkPath::kQuad_Verb ? &pair[0] : cStorage[0];
+ SkPoint* curve2 = v2 == SkPath::kQuad_Verb ? &pair[2] : cStorage[1];
+ if (can_add_curve(v1, curve1) && can_add_curve(v2, curve2)) {
fCurrentContour->addCurve(v1, curve1);
- }
- if (SkPath::kLine_Verb != v2 ||
- !SkDPoint::ApproximatelyEqual(curve2[0], curve2[1])) {
fCurrentContour->addCurve(v2, curve2);
+ break;
}
- } else {
- fCurrentContour->addCubic(pointsPtr);
}
- } else {
- fCurrentContour->addCubic(pointsPtr);
}
+ addOneQuad:
+ fCurrentContour->addQuad(pointsPtr);
+ break;
+ case SkPath::kConic_Verb: {
+ SkVector v1 = pointsPtr[1] - pointsPtr[0];
+ SkVector v2 = pointsPtr[2] - pointsPtr[1];
+ SkScalar weight = *weightPtr++;
+ if (v1.dot(v2) < 0) {
+ // FIXME: max curvature for conics hasn't been implemented; use placeholder
+ SkScalar maxCurvature = SkFindQuadMaxCurvature(pointsPtr);
+ if (maxCurvature > 0) {
+ SkConic conic(pointsPtr, weight);
+ SkConic pair[2];
+ conic.chopAt(maxCurvature, pair);
+ SkPoint cStorage[2][3];
+ SkPath::Verb v1 = SkReduceOrder::Conic(pair[0], cStorage[0]);
+ SkPath::Verb v2 = SkReduceOrder::Conic(pair[1], cStorage[1]);
+ SkPoint* curve1 = v1 == SkPath::kConic_Verb ? pair[0].fPts : cStorage[0];
+ SkPoint* curve2 = v2 == SkPath::kConic_Verb ? pair[1].fPts : cStorage[1];
+ if (can_add_curve(v1, curve1) && can_add_curve(v2, curve2)) {
+ fCurrentContour->addCurve(v1, curve1, pair[0].fW);
+ fCurrentContour->addCurve(v2, curve2, pair[1].fW);
+ break;
+ }
+ }
+ }
+ fCurrentContour->addConic(pointsPtr, weight);
} break;
+ case SkPath::kCubic_Verb:
+ {
+ // Split complex cubics (such as self-intersecting curves or
+ // ones with difficult curvature) in two before proceeding.
+ // This can be required for intersection to succeed.
+ SkScalar splitT;
+ if (SkDCubic::ComplexBreak(pointsPtr, &splitT)) {
+ SkPoint pair[7];
+ SkChopCubicAt(pointsPtr, pair, splitT);
+ if (!SkScalarsAreFinite(&pair[0].fX, SK_ARRAY_COUNT(pair) * 2)) {
+ return false;
+ }
+ SkPoint cStorage[2][4];
+ SkPath::Verb v1 = SkReduceOrder::Cubic(&pair[0], cStorage[0]);
+ SkPath::Verb v2 = SkReduceOrder::Cubic(&pair[3], cStorage[1]);
+ SkPoint* curve1 = v1 == SkPath::kCubic_Verb ? &pair[0] : cStorage[0];
+ SkPoint* curve2 = v2 == SkPath::kCubic_Verb ? &pair[3] : cStorage[1];
+ if (can_add_curve(v1, curve1) && can_add_curve(v2, curve2)) {
+ fCurrentContour->addCurve(v1, curve1);
+ fCurrentContour->addCurve(v2, curve2);
+ break;
+ }
+ }
+ }
+ fCurrentContour->addCubic(pointsPtr);
+ break;
case SkPath::kClose_Verb:
SkASSERT(fCurrentContour);
if (!close()) {
diff --git a/src/pathops/SkOpSegment.cpp b/src/pathops/SkOpSegment.cpp
index 1a965c2474..9ab240d2cb 100644
--- a/src/pathops/SkOpSegment.cpp
+++ b/src/pathops/SkOpSegment.cpp
@@ -249,7 +249,7 @@ SkOpPtT* SkOpSegment::addT(double t) {
SkOpSpanBase* spanBase = &fHead;
do {
SkOpPtT* result = spanBase->ptT();
- if (t == result->fT || this->match(result, this, t, pt)) {
+ if (t == result->fT || (!zero_or_one(t) && this->match(result, this, t, pt))) {
spanBase->bumpSpanAdds();
return result;
}
diff --git a/src/pathops/SkPathOpsDebug.cpp b/src/pathops/SkPathOpsDebug.cpp
index 67bcee4070..5326addf8d 100644
--- a/src/pathops/SkPathOpsDebug.cpp
+++ b/src/pathops/SkPathOpsDebug.cpp
@@ -1876,7 +1876,7 @@ static void DebugValidate(const SkOpSpanBase* next, const SkOpSpanBase* end,
do {
const SkOpPtT* ptT = next->ptT();
int index = 0;
- bool somethingBetween;
+ bool somethingBetween = false;
do {
++index;
ptT = ptT->next();
diff --git a/src/pathops/SkPathOpsDebug.h b/src/pathops/SkPathOpsDebug.h
index e390b91b56..f0e384a7e3 100644
--- a/src/pathops/SkPathOpsDebug.h
+++ b/src/pathops/SkPathOpsDebug.h
@@ -19,6 +19,8 @@
#define FORCE_RELEASE 1 // set force release to 1 for multiple thread -- no debugging
#endif
+#define DEBUG_UNDER_DEVELOPMENT 1
+
#define ONE_OFF_DEBUG 0
#define ONE_OFF_DEBUG_MATHEMATICA 0
@@ -37,8 +39,6 @@
if (!SkPathOpsDebug::ValidWind(x)) strcpy(x##Str, "?"); \
else SK_SNPRINTF(x##Str, sizeof(x##Str), "%d", x)
-#define DEBUG_UNDER_DEVELOPMENT 1
-
#if FORCE_RELEASE
#define DEBUG_ACTIVE_OP 0
diff --git a/src/pathops/SkPathOpsOp.cpp b/src/pathops/SkPathOpsOp.cpp
index 0f4415bec1..d34c0579e4 100644
--- a/src/pathops/SkPathOpsOp.cpp
+++ b/src/pathops/SkPathOpsOp.cpp
@@ -207,7 +207,7 @@ static void dump_path(FILE* file, const SkPath& path, bool force, bool dumpAsHex
SkDynamicMemoryWStream wStream;
path.dump(&wStream, force, dumpAsHex);
sk_sp<SkData> data(wStream.detachAsData());
- fprintf(file, "%.*s\n", (int) data->size(), data->data());
+ fprintf(file, "%.*s\n", (int) data->size(), (char*) data->data());
}
static int dumpID = 0;
diff --git a/src/pathops/SkPathOpsTSect.h b/src/pathops/SkPathOpsTSect.h
index 6ae6ee528f..f84aaaa6b7 100644
--- a/src/pathops/SkPathOpsTSect.h
+++ b/src/pathops/SkPathOpsTSect.h
@@ -1531,7 +1531,8 @@ int SkTSect<TCurve, OppCurve>::linesIntersect(SkTSpan<TCurve, OppCurve>* span,
workT += tStep;
workPt = fCurve.ptAtT(workT);
coinW.setPerp(fCurve, workT, workPt, opp->fCurve);
- if (coinW.perpT() < 0) {
+ double perpT = coinW.perpT();
+ if (coinW.isCoincident() ? !between(oppSpan->fStartT, perpT, oppSpan->fEndT) : perpT < 0) {
continue;
}
SkDVector perpW = workPt - coinW.perpPt();
diff --git a/src/pathops/SkReduceOrder.cpp b/src/pathops/SkReduceOrder.cpp
index 48624baee9..7f7ea11d3b 100644
--- a/src/pathops/SkReduceOrder.cpp
+++ b/src/pathops/SkReduceOrder.cpp
@@ -4,6 +4,7 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
+#include "SkGeometry.h"
#include "SkReduceOrder.h"
int SkReduceOrder::reduce(const SkDLine& line) {
@@ -255,9 +256,9 @@ SkPath::Verb SkReduceOrder::Quad(const SkPoint a[3], SkPoint* reducePts) {
return SkPathOpsPointsToVerb(order - 1);
}
-SkPath::Verb SkReduceOrder::Conic(const SkPoint a[3], SkScalar weight, SkPoint* reducePts) {
- SkPath::Verb verb = SkReduceOrder::Quad(a, reducePts);
- if (verb > SkPath::kLine_Verb && weight == 1) {
+SkPath::Verb SkReduceOrder::Conic(const SkConic& c, SkPoint* reducePts) {
+ SkPath::Verb verb = SkReduceOrder::Quad(c.fPts, reducePts);
+ if (verb > SkPath::kLine_Verb && c.fW == 1) {
return SkPath::kQuad_Verb;
}
return verb == SkPath::kQuad_Verb ? SkPath::kConic_Verb : verb;
diff --git a/src/pathops/SkReduceOrder.h b/src/pathops/SkReduceOrder.h
index e9e4090deb..7efb71d4fe 100644
--- a/src/pathops/SkReduceOrder.h
+++ b/src/pathops/SkReduceOrder.h
@@ -11,6 +11,8 @@
#include "SkPathOpsLine.h"
#include "SkPathOpsQuad.h"
+struct SkConic;
+
union SkReduceOrder {
enum Quadratics {
kNo_Quadratics,
@@ -21,7 +23,7 @@ union SkReduceOrder {
int reduce(const SkDLine& line);
int reduce(const SkDQuad& quad);
- static SkPath::Verb Conic(const SkPoint pts[3], SkScalar weight, SkPoint* reducePts);
+ static SkPath::Verb Conic(const SkConic& conic, SkPoint* reducePts);
static SkPath::Verb Cubic(const SkPoint pts[4], SkPoint* reducePts);
static SkPath::Verb Quad(const SkPoint pts[3], SkPoint* reducePts);
diff --git a/tests/PathOpsConicLineIntersectionTest.cpp b/tests/PathOpsConicLineIntersectionTest.cpp
index 62195060e9..ecc4a47f17 100644
--- a/tests/PathOpsConicLineIntersectionTest.cpp
+++ b/tests/PathOpsConicLineIntersectionTest.cpp
@@ -6,6 +6,7 @@
*/
#include "PathOpsExtendedTest.h"
#include "PathOpsTestCommon.h"
+#include "SkGeometry.h"
#include "SkIntersections.h"
#include "SkPathOpsConic.h"
#include "SkPathOpsLine.h"
@@ -103,7 +104,9 @@ DEF_TEST(PathOpsConicLineIntersection, reporter) {
SkPoint pts[3] = { conic.fPts.fPts[0].asSkPoint(), conic.fPts.fPts[1].asSkPoint(),
conic.fPts.fPts[2].asSkPoint() };
SkPoint reduced[3];
- SkPath::Verb order1 = SkReduceOrder::Conic(pts, conic.fWeight, reduced);
+ SkConic floatConic;
+ floatConic.set(pts, conic.fWeight);
+ SkPath::Verb order1 = SkReduceOrder::Conic(floatConic, reduced);
if (order1 != SkPath::kConic_Verb) {
SkDebugf("%s [%d] conic verb=%d\n", __FUNCTION__, iIndex, order1);
REPORTER_ASSERT(reporter, 0);
diff --git a/tests/PathOpsCubicIntersectionTest.cpp b/tests/PathOpsCubicIntersectionTest.cpp
index dd7a7f7e2f..9bf60b7e39 100644
--- a/tests/PathOpsCubicIntersectionTest.cpp
+++ b/tests/PathOpsCubicIntersectionTest.cpp
@@ -165,6 +165,9 @@ static const SkDCubic testSet[] = {
const int testSetCount = (int) SK_ARRAY_COUNT(testSet);
static const SkDCubic newTestSet[] = {
+{ { { 130.0427549999999997, 11417.41309999999976 },{ 130.2331240000000037, 11418.3192999999992 },{ 131.0370790000000056, 11419 },{ 132, 11419 } } },
+{ { { 132, 11419 },{ 130.8954319999999996, 11419 },{ 130, 11418.10449999999946 },{ 130, 11417 } } },
+
{{{1,3}, {-1.0564518,1.79032254}, {1.45265341,0.229448318}, {1.45381773,0.22913377}}},
{{{1.45381773,0.22913377}, {1.45425761,0.229014933}, {1.0967741,0.451612949}, {0,1}}},
@@ -698,7 +701,7 @@ DEF_TEST(PathOpsCubicCoinOneOff, reporter) {
}
DEF_TEST(PathOpsCubicIntersectionOneOff, reporter) {
- newOneOff(reporter, 66, 70);
+ newOneOff(reporter, 0, 1);
}
DEF_TEST(PathOpsCubicIntersectionTestsOneOff, reporter) {
diff --git a/tests/PathOpsOpTest.cpp b/tests/PathOpsOpTest.cpp
index 8ff0079dd4..9bb3a0fbb6 100644
--- a/tests/PathOpsOpTest.cpp
+++ b/tests/PathOpsOpTest.cpp
@@ -5375,6 +5375,26 @@ static void cubicOp158(skiatest::Reporter* reporter, const char* filename) {
testPathOp(reporter, path, pathB, kDifference_SkPathOp, filename);
}
+static void loop17(skiatest::Reporter* reporter, const char* filename) {
+ SkPath path, pathB;
+ path.moveTo(1, 2);
+ path.cubicTo(0, 3, -0.333333343f, 3.33333325f, 0.833333373f, 3.5f);
+ path.close();
+ pathB.moveTo(0, 3);
+ pathB.cubicTo(-0.333333343f, 3.33333325f, 0.833333373f, 3.5f, 1, 2);
+ pathB.close();
+ testPathOp(reporter, path, pathB, kIntersect_SkPathOp, filename);
+}
+
+static void circlesOp4(skiatest::Reporter* reporter, const char* filename) {
+ SkPath path, pathB;
+ path.setFillType(SkPath::kWinding_FillType);
+ path.addCircle(0, 1, 5, SkPath::kCW_Direction);
+ pathB.setFillType(SkPath::kWinding_FillType);
+ pathB.addCircle(0, 1, 0, SkPath::kCW_Direction);
+ testPathOp(reporter, path, pathB, kDifference_SkPathOp, filename);
+}
+
static void (*skipTest)(skiatest::Reporter* , const char* filename) = 0;
static void (*firstTest)(skiatest::Reporter* , const char* filename) = 0;
static void (*stopTest)(skiatest::Reporter* , const char* filename) = 0;
@@ -5382,6 +5402,8 @@ static void (*stopTest)(skiatest::Reporter* , const char* filename) = 0;
#define TEST(name) { name, #name }
static struct TestDesc tests[] = {
+ TEST(circlesOp4),
+ TEST(loop17),
TEST(cubicOp158),
TEST(loops_i1),
TEST(loops_i2),
diff --git a/tests/PathOpsQuadIntersectionTest.cpp b/tests/PathOpsQuadIntersectionTest.cpp
index f01262201f..be3d5a86d1 100644
--- a/tests/PathOpsQuadIntersectionTest.cpp
+++ b/tests/PathOpsQuadIntersectionTest.cpp
@@ -53,6 +53,9 @@ static void standardTestCases(skiatest::Reporter* reporter) {
}
static const SkDQuad testSet[] = {
+{{{-0.001019871095195412636, -0.008523519150912761688}, {-0.005396408028900623322, -0.005396373569965362549}, {-0.02855382487177848816, -0.02855364233255386353}}},
+{{{-0.004567248281091451645, -0.01482933573424816132}, {-0.01142475008964538574, -0.01140109263360500336}, {-0.02852955088019371033, -0.02847047336399555206}}},
+
{{{1, 1}, {0, 2}, {3, 3}}},
{{{3, 0}, {0, 1}, {1, 2}}},
diff --git a/tests/PathOpsSimplifyFailTest.cpp b/tests/PathOpsSimplifyFailTest.cpp
index 4da43b8532..0166a841fa 100644
--- a/tests/PathOpsSimplifyFailTest.cpp
+++ b/tests/PathOpsSimplifyFailTest.cpp
@@ -154,7 +154,7 @@ path.quadTo(SkBits2Float(0xe93ae9e9), SkBits2Float(0xe964b6e9), SkBits2Float(0x0
path.moveTo(SkBits2Float(0x64b6b6b6), SkBits2Float(0xe9e9e900)); // 2.69638e+22f, -3.53475e+25f
path.quadTo(SkBits2Float(0xb6b6b6e9), SkBits2Float(0xb6b6b6b6), SkBits2Float(0xe9e9b6ce), SkBits2Float(0xe9e93ae9)); // -5.44532e-06f, -5.44529e-06f, -3.53179e+25f, -3.52447e+25f
- testSimplify(reporter, path, filename);
+ testSimplifyFuzz(reporter, path, filename);
}
diff --git a/tests/PathOpsSimplifyTest.cpp b/tests/PathOpsSimplifyTest.cpp
index 07e3720583..55f0447bae 100644
--- a/tests/PathOpsSimplifyTest.cpp
+++ b/tests/PathOpsSimplifyTest.cpp
@@ -5256,7 +5256,7 @@ static void tiger8a_h_1(skiatest::Reporter* reporter, const char* filename) {
#if DEBUG_UNDER_DEVELOPMENT // tiger
return;
#endif
- uint64_t testlines = 0x0000000a01900c00; // best so far: 0x0000001d14c14bb1;
+ uint64_t testlines = 0x0000000000002008; // best so far: 0x0000001d14c14bb1;
tiger8a_x(reporter, filename, testlines);
}
@@ -5331,7 +5331,7 @@ static void tiger8b_h_1(skiatest::Reporter* reporter, const char* filename) {
#if DEBUG_UNDER_DEVELOPMENT // tiger
return;
#endif
- uint64_t testlines = 0x0000001000350204; // best so far: 0x0000000104080223
+ uint64_t testlines = 0x000000201304b4a3; // best so far: 0x000000201304b4a3
tiger8b_x(reporter, filename, testlines);
}
@@ -5870,11 +5870,10 @@ static void testQuads73(skiatest::Reporter* reporter, const char* filename) {
}
static void (*skipTest)(skiatest::Reporter* , const char* filename) = 0;
-static void (*firstTest)(skiatest::Reporter* , const char* filename) = tiger8b_h_1;
+static void (*firstTest)(skiatest::Reporter* , const char* filename) = 0;
static void (*stopTest)(skiatest::Reporter* , const char* filename) = 0;
static TestDesc tests[] = {
- TEST(testQuads73),
TEST(tiger8a_h_1),
TEST(tiger8a_h),
TEST(tiger8a),
@@ -5882,6 +5881,7 @@ static TestDesc tests[] = {
TEST(tiger8b_h),
TEST(tiger8b),
TEST(tiger8),
+ TEST(testQuads73),
TEST(testQuads72),
TEST(testQuads71),
TEST(testQuads70),
diff --git a/tests/PathOpsThreeWayTest.cpp b/tests/PathOpsThreeWayTest.cpp
index bf634f9f7e..6a93bfbc59 100644
--- a/tests/PathOpsThreeWayTest.cpp
+++ b/tests/PathOpsThreeWayTest.cpp
@@ -75,6 +75,6 @@ DEF_TEST(PathOpsThreeWay, reporter) {
}
DEF_TEST(PathOpsThreeWayOneOff, reporter) {
- int index = 1;
+ int index = 0;
testSetTest(reporter, index);
}
diff --git a/tools/pathops_sorter.htm b/tools/pathops_sorter.htm
index 667e86dac4..0983b704dc 100644
--- a/tools/pathops_sorter.htm
+++ b/tools/pathops_sorter.htm
@@ -6,9 +6,30 @@
<title></title>
<div style="height:0">
-<div id="lineconic">
-{{{{494.348663330078125, 224.583770751953125}, {494.365142822265625, 224.6331939697265625}, {494.37640380859375, 224.6840667724609375}}}, 0.998645842f},
-{{{494.371185302734375, 224.66168212890625}, {494.375213623046875, 224.6787261962890625}}},
+<div id="perp">
+{{{130.0427549999999997, 11417.41309999999976}, {130.2331240000000037, 11418.3192999999992}, {131.0370790000000056, 11419}, {132, 11419}}},
+{{{132, 11419}, {130.8954319999999996, 11419}, {130, 11418.10449999999946}, {130, 11417}}},
+</div>
+
+<div id="quads">
+{{{-0.001019871095195412636, -0.008523519150912761688}, {-0.005396408028900623322, -0.005396373569965362549}, {-0.02855382487177848816, -0.02855364233255386353}}},
+{{{-0.004567248281091451645, -0.01482933573424816132}, {-0.01142475008964538574, -0.01140109263360500336}, {-0.02852955088019371033, -0.02847047336399555206}}},
+ </div>
+
+<div id="both">
+{{fX=0.000000000 fY=0.000000000 }, {fX=494.350159 fY=228.773712 }, {fX=493.191650 fY=226.887451 }}
+{{fX=0.000000000 fY=0.000000000 } {fX=492.680206 fY=228.000900 } {fX=493.193817 fY=226.897568 }
+{{fX=493.193817 fY=226.897568 } {fX=493.195557 fY=226.893829 } {fX=493.191650 fY=226.887451 }
+ </div>
+
+<div id="startguy">
+{{fX=0.000000000 fY=0.000000000 }, {fX=494.350159 fY=228.773712 }, {fX=493.191650 fY=226.887451 }}
+{{fX=0.000000000 fY=0.000000000 }, {fX=494.350159 fY=228.773712 }, {fX=493.191650 fY=226.887451 }}
+ </div>
+
+<div id="splitted">
+{{fX=0.000000000 fY=0.000000000 } {fX=492.680206 fY=228.000900 } {fX=493.193817 fY=226.897568 }
+{{fX=493.193817 fY=226.897568 } {fX=493.195557 fY=226.893829 } {fX=493.191650 fY=226.887451 }
</div>
</div>
@@ -16,7 +37,11 @@
<script type="text/javascript">
var testDivs = [
- lineconic,
+ perp,
+ quads,
+ both,
+ startguy,
+ splitted
];
var decimal_places = 3;
diff --git a/tools/pathops_visualizer.htm b/tools/pathops_visualizer.htm
index 945a6a9e6c..5cec64f5bf 100644
--- a/tools/pathops_visualizer.htm
+++ b/tools/pathops_visualizer.htm
@@ -2,88 +2,150 @@
<head>
<div height="0" hidden="true">
-<div id="tiger8b_h_1">
-seg=1 {{{{494.348663f, 224.583771f}, {494.365143f, 224.633194f}, {494.376404f, 224.684067f}}}, 0.998645842f}
-seg=2 {{{494.376404f, 224.684067f}, {492.527069f, 224.218475f}, {492.952789f, 224.005585f}}}
-seg=3 {{{492.952789f, 224.005585f}, {494.375336f, 224.679337f}, {494.376038f, 224.682449f}}}
-seg=4 {{{494.376038f, 224.682449f}, {494.37619f, 224.68309f}}}
-seg=5 {{{494.37619f, 224.68309f}, {494.634338f, 225.414886f}, {494.895874f, 225.840698f}}}
-seg=6 {{{494.895874f, 225.840698f}, {494.348663f, 224.583771f}}}
-debugShowConicQuadIntersection wtTs[0]=1 {{{{494.348663,224.583771}, {494.365143,224.633194}, {494.376404,224.684067}}}, 0.998645842} {{494.376404,224.684067}} wnTs[0]=0 {{{494.376404,224.684067}, {492.527069,224.218475}, {492.952789,224.005585}}}
-id=1 1=(0,1) [4] id=2 4=(0.5,1) [1]
-id=1 1=(0,1) [6] id=2 6=(0.75,1) [1]
-id=1 3=(0.5,1) [6] id=2 6=(0.75,1) [3]
-id=1 3=(0.5,1) [8] id=2 8=(0.875,1) [3]
-id=1 5=(0.75,1) [8] id=2 8=(0.875,1) [5]
-id=1 7=(0.875,1) [8] id=2 8=(0.875,1) [7]
-id=1 7=(0.875,1) [10] id=2 10=(0.9375,1) [7]
-id=1 (empty) id=2 (empty)
-debugShowConicQuadIntersection no intersect {{{{494.348663,224.583771}, {494.365143,224.633194}, {494.376404,224.684067}}}, 0.998645842} {{{492.952789,224.005585}, {494.375336,224.679337}, {494.376038,224.682449}}}
-debugShowConicLineIntersection wtTs[0]=0.988457533 {{{{494.348663,224.583771}, {494.365143,224.633194}, {494.376404,224.684067}}}, 0.998645842} {{494.376038,224.682449}} wnTs[0]=0 {{{494.376038,224.682449}, {494.37619,224.68309}}}
-SkOpSegment::addT insert t=0.988457533 segID=1 spanID=13
-debugShowConicQuadIntersection no intersect {{{{494.348663,224.583771}, {494.365143,224.633194}, {494.376404,224.684067}}}, 0.998645842} {{{494.37619,224.68309}, {494.634338,225.414886}, {494.895874,225.840698}}}
-debugShowConicLineIntersection wtTs[0]=0 {{{{494.348663,224.583771}, {494.365143,224.633194}, {494.376404,224.684067}}}, 0.998645842} {{494.348663,224.583771}} wnTs[0]=1 {{{494.895874,225.840698}, {494.348663,224.583771}}}
-debugShowQuadIntersection wtTs[0]=1 {{{494.376404,224.684067}, {492.527069,224.218475}, {492.952789,224.005585}}} {{492.952789,224.005585}} wnTs[0]=0 {{{492.952789,224.005585}, {494.375336,224.679337}, {494.376038,224.682449}}}
-debugShowQuadLineIntersection no intersect {{{494.376404,224.684067}, {492.527069,224.218475}, {492.952789,224.005585}}} {{{494.376038,224.682449}, {494.37619,224.68309}}}
-id=1 1=(0,0.5) [2] id=2 2=(0,1) [1]
-id=1 1=(0,0.25) [2] id=2 2=(0,1) [1]
-id=1 (empty) id=2 (empty)
-debugShowQuadIntersection no intersect {{{494.376404,224.684067}, {492.527069,224.218475}, {492.952789,224.005585}}} {{{494.37619,224.68309}, {494.634338,225.414886}, {494.895874,225.840698}}}
-debugShowQuadLineIntersection no intersect {{{494.376404,224.684067}, {492.527069,224.218475}, {492.952789,224.005585}}} {{{494.895874,225.840698}, {494.348663,224.583771}}}
-debugShowQuadLineIntersection wtTs[0]=1 {{{492.952789,224.005585}, {494.375336,224.679337}, {494.376038,224.682449}}} {{494.376038,224.682449}} wnTs[0]=0 {{{494.376038,224.682449}, {494.37619,224.68309}}}
-debugShowQuadLineIntersection no intersect {{{492.952789,224.005585}, {494.375336,224.679337}, {494.376038,224.682449}}} {{{494.895874,225.840698}, {494.348663,224.583771}}}
-debugShowQuadLineIntersection wtTs[0]=0 {{{494.37619,224.68309}, {494.634338,225.414886}, {494.895874,225.840698}}} {{494.37619,224.68309}} wnTs[0]=1 {{{494.376038,224.682449}, {494.37619,224.68309}}}
-debugShowLineIntersection no intersect {{{494.376038,224.682449}, {494.37619,224.68309}}} {{{494.895874,225.840698}, {494.348663,224.583771}}}
-debugShowQuadLineIntersection wtTs[0]=1 {{{494.37619,224.68309}, {494.634338,225.414886}, {494.895874,225.840698}}} {{494.895874,225.840698}} wnTs[0]=0 {{{494.895874,225.840698}, {494.348663,224.583771}}}
-SkOpSegment::markDone id=4 (494.376038,224.682449 494.37619,224.68309) t=0 [7] (494.376038,224.682449) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=0 oppValue=0
-SkOpSegment::sortAngles [1] tStart=0.988457533 [13]
-SkOpAngle::after [1/1] 9/9 tStart=0.988457533 tEnd=0 < [3/3] 13/13 tStart=1 tEnd=0 < [1/2] 25/25 tStart=0.988457533 tEnd=1 T 4
-SkOpAngle::afterPart {{{{494.376038,224.682449}, {494.364861,224.63218}, {494.348663,224.583771}}}, 0.998676896} id=1
-SkOpAngle::afterPart {{{494.376038,224.682449}, {492.952789,224.005585}, {492.952789,224.005585}}} id=3
-SkOpAngle::afterPart {{{{494.376038,224.682449}, {494.376312,224.683624}, {494.376404,224.684067}}}, 0.999999821} id=1
+<div id="loop17">
+seg=1 {{{1, 2}, {0, 3}, {-0.333333343f, 3.33333325f}, {0.833333373f, 3.5f}}}
+seg=2 {{{0.833333373f, 3.5f}, {1, 2}}}
+op sect
+seg=3 {{{0, 3}, {-0.333333343f, 3.33333325f}, {0.833333373f, 3.5f}, {1, 2}}}
+seg=4 {{{1, 2}, {0, 3}}}
+debugShowCubicLineIntersection wtTs[0]=0 {{{0,3}, {-0.333333343,3.33333325}, {0.833333373,3.5}, {1,2}}} {{0,3}} wtTs[1]=1 {{1,2}} wnTs[0]=1 {{{1,2}, {0,3}}} wnTs[1]=0
+id=1 1=(0,1) [4,2] id=2 2=(0,0.5) [1] 4=(0.5,1) [1]
+id=1 1=(0,0.5) [4] 3=(0.5,1) [2,4] id=2 2=(0,0) [3] 4=(0.5,1) [3,1]
+id=1 1=(0,0.5) [4] 3=(0.5,0.75) [4] 5=(1,1) [2] id=2 2=(0,0) [5] 4=(0.5,1) [3,1]
+id=1 1=(0,0.5) [4] 5=(1,1) [2] id=2 2=(0,0) [5] 4=(0.5,0.75) [1]
+id=1 7=(0.25,0.5) [4] 5=(1,1) [2] id=2 2=(0,0) [5] 4=(0.5,0.75) [7]
+id=1 7=(0.25,0.375) [4] 9=(0.375,0.5) [4] 5=(1,1) [2] id=2 2=(0,0) [5] 4=(0.5,0.75) [9,7]
+id=1 7=(0.25,0.375) [8,4] 5=(1,1) [2] id=2 2=(0,0) [5] 4=(0.5,0.625) [7] 8=(0.625,0.75) [7]
+id=1 7=(0.25,0.375) [10,8] 5=(1,1) [2] id=2 2=(0,0) [5] 10=(0.5625,0.625) [7] 8=(0.625,0.75) [7]
+id=1 11=(0.3125,0.375) [8] 5=(1,1) [2] id=2 2=(0,0) [5] 8=(0.625,0.75) [11]
+id=1 11=(0.3125,0.375) [8] 5=(1,1) [2] id=2 2=(0,0) [5] 8=(0.625,0.6875) [11]
+id=1 13=(0.34375,0.375) [8] 5=(1,1) [2] id=2 2=(0,0) [5] 8=(0.625,0.6875) [13]
+id=1 13=(0.34375,0.375) [8] 5=(1,1) [2] id=2 2=(0,0) [5] 8=(0.625,0.65625) [13]
+id=1 15=(0.359375,0.375) [8] 5=(1,1) [2] id=2 2=(0,0) [5] 8=(0.625,0.65625) [15]
+id=1 15=(0.359375,0.375) [8] 5=(1,1) [2] id=2 2=(0,0) [5] 8=(0.625,0.640625) [15]
+id=1 15=(0.359375,0.367188) [8] 17=(0.367188,0.375) [8] 5=(1,1) [2] id=2 2=(0,0) [5] 8=(0.625,0.640625) [17,15]
+id=1 15=(0.359375,0.367188) [18] 5=(1,1) [2] id=2 2=(0,0) [5] 18=(0.632813,0.640625) [15]
+id=1 19=(0.363281,0.367188) [18] 5=(1,1) [2] id=2 2=(0,0) [5] 18=(0.632813,0.640625) [19]
+setPerp t=0.36328125 cPt=(0.110739922,3.22537946) != oppT=0.627603681 fPerpPt=(0.110965509,3.21864052)
+setPerp t=0.3671875 cPt=(0.115765816,3.22551414) != oppT=0.636601379 fPerpPt=(0.115710094,3.22827643)
+setPerp t=0.6328125 cPt=(0.113641506,3.22423955) != oppT=0.363729545 fPerpPt=(0.111313976,3.22539824)
+setPerp t=0.63470694 cPt=(0.114662928,3.22626175) != oppT=0.367452497 fPerpPt=(0.116108709,3.2255209)
+setPerp t=0.635654159 cPt=(0.115183291,3.22727003) != oppT=0.369275918 fPerpPt=(0.118474752,3.22555923)
+setPerp t=0.636127769 cPt=(0.115445887,3.22777346) != oppT=0.370178237 fPerpPt=(0.119649848,3.22557288)
+setPerp t=0.636364574 cPt=(0.115577789,3.228025) != oppT=0.370627065 fPerpPt=(0.120235406,3.22557836)
+setPerp t=0.636482977 cPt=(0.115643891,3.22815073) != oppT=0.370850898 fPerpPt=(0.120527686,3.22558077)
+setPerp t=0.636542178 cPt=(0.11567698,3.22821358) != oppT=0.370962669 fPerpPt=(0.120673701,3.22558189)
+setPerp t=0.636571779 cPt=(0.115693534,3.22824501) != oppT=0.371018519 fPerpPt=(0.120746678,3.22558243)
+setPerp t=0.636586579 cPt=(0.115701813,3.22826072) != oppT=0.371046435 fPerpPt=(0.120783158,3.22558269)
+setPerp t=0.636593979 cPt=(0.115705954,3.22826857) != oppT=0.37106039 fPerpPt=(0.120801396,3.22558282)
+setPerp t=0.636597679 cPt=(0.115708024,3.2282725) != oppT=0.371067368 fPerpPt=(0.120810515,3.22558289)
+setPerp t=0.636599529 cPt=(0.115709059,3.22827446) != oppT=0.371070856 fPerpPt=(0.120815074,3.22558292)
+setPerp t=0.636600454 cPt=(0.115709577,3.22827545) != oppT=0.3710726 fPerpPt=(0.120817354,3.22558294)
+setPerp t=0.636600917 cPt=(0.115709835,3.22827594) != oppT=0.371073472 fPerpPt=(0.120818494,3.22558294)
+setPerp t=0.636601148 cPt=(0.115709965,3.22827618) != oppT=0.371073908 fPerpPt=(0.120819063,3.22558295)
+setPerp t=0.636601264 cPt=(0.11571003,3.2282763) != oppT=0.371074126 fPerpPt=(0.120819348,3.22558295)
+setPerp t=0.636601322 cPt=(0.115710062,3.22827637) != oppT=0.371074235 fPerpPt=(0.120819491,3.22558295)
+setPerp t=0.63660135 cPt=(0.115710078,3.2282764) != oppT=0.37107429 fPerpPt=(0.120819562,3.22558295)
+setPerp t=0.636601365 cPt=(0.115710086,3.22827641) != oppT=0.371074317 fPerpPt=(0.120819598,3.22558295)
+setPerp t=0.636601372 cPt=(0.11571009,3.22827642) != oppT=0.371074331 fPerpPt=(0.120819616,3.22558295)
+setPerp t=0.636601376 cPt=(0.115710092,3.22827642) != oppT=0.371074338 fPerpPt=(0.120819624,3.22558295)
+setPerp t=0.636601378 cPt=(0.115710093,3.22827643) != oppT=0.371074341 fPerpPt=(0.120819629,3.22558295)
+setPerp t=0.636601378 cPt=(0.115710094,3.22827643) != oppT=0.371074343 fPerpPt=(0.120819631,3.22558295)
+setPerp t=0.636601379 cPt=(0.115710094,3.22827643) != oppT=0.371074344 fPerpPt=(0.120819632,3.22558295)
+setPerp t=0.636601379 cPt=(0.115710094,3.22827643) != oppT=0.371074344 fPerpPt=(0.120819633,3.22558295)
+setPerp t=0.636601379 cPt=(0.115710094,3.22827643) != oppT=0.371074344 fPerpPt=(0.120819633,3.22558295)
+setPerp t=0.636601379 cPt=(0.115710094,3.22827643) != oppT=0.371074344 fPerpPt=(0.120819633,3.22558295)
+setPerp t=0.636601379 cPt=(0.115710094,3.22827643) != oppT=0.371074344 fPerpPt=(0.120819633,3.22558295)
+setPerp t=0.636601379 cPt=(0.115710094,3.22827643) != oppT=0.371074344 fPerpPt=(0.120819633,3.22558295)
+setPerp t=0.636601379 cPt=(0.115710094,3.22827643) != oppT=0.371074344 fPerpPt=(0.120819633,3.22558295)
+setPerp t=0.636601379 cPt=(0.115710094,3.22827643) != oppT=0.371074344 fPerpPt=(0.120819633,3.22558295)
+setPerp t=0.636601379 cPt=(0.115710094,3.22827643) != oppT=0.371074344 fPerpPt=(0.120819633,3.22558295)
+setPerp t=0.636601379 cPt=(0.115710094,3.22827643) != oppT=0.371074344 fPerpPt=(0.120819633,3.22558295)
+setPerp t=0.636601379 cPt=(0.115710094,3.22827643) != oppT=0.371074344 fPerpPt=(0.120819633,3.22558295)
+setPerp t=0.636601379 cPt=(0.115710094,3.22827643) != oppT=0.371074344 fPerpPt=(0.120819633,3.22558295)
+setPerp t=0.636601379 cPt=(0.115710094,3.22827643) != oppT=0.371074344 fPerpPt=(0.120819633,3.22558295)
+setPerp t=0.636601379 cPt=(0.115710094,3.22827643) != oppT=0.371074344 fPerpPt=(0.120819633,3.22558295)
+setPerp t=0.636601379 cPt=(0.115710094,3.22827643) != oppT=0.371074344 fPerpPt=(0.120819633,3.22558295)
+setPerp t=0.636601379 cPt=(0.115710094,3.22827643) != oppT=0.371074344 fPerpPt=(0.120819633,3.22558295)
+setPerp t=0.636601379 cPt=(0.115710094,3.22827643) != oppT=0.371074344 fPerpPt=(0.120819633,3.22558295)
+setPerp t=0.636601379 cPt=(0.115710094,3.22827643) != oppT=0.371074344 fPerpPt=(0.120819633,3.22558295)
+setPerp t=0.636601379 cPt=(0.115710094,3.22827643) != oppT=0.371074344 fPerpPt=(0.120819633,3.22558295)
+id=1 5=(1,1) [2] id=2 2=(0,0) [5]
+debugShowCubicIntersection wtTs[0]=1 {{{0,3}, {-0.333333343,3.33333325}, {0.833333373,3.5}, {1,2}}} {{1,2}} wnTs[0]=0 {{{1,2}, {0,3}, {-0.333333343,3.33333325}, {0.833333373,3.5}}}
+debugShowCubicLineIntersection wtTs[0]=1 {{{0,3}, {-0.333333343,3.33333325}, {0.833333373,3.5}, {1,2}}} {{1,2}} wnTs[0]=1 {{{0.833333373,3.5}, {1,2}}}
+debugShowCubicLineIntersection wtTs[0]=0 {{{1,2}, {0,3}, {-0.333333343,3.33333325}, {0.833333373,3.5}}} {{1,2}} wnTs[0]=0 {{{1,2}, {0,3}}}
+debugShowLineIntersection wtTs[0]=0 {{{1,2}, {0,3}}} {{1,2}} wnTs[0]=1 {{{0.833333373,3.5}, {1,2}}}
+debugShowCubicLineIntersection wtTs[0]=0 {{{1,2}, {0,3}, {-0.333333343,3.33333325}, {0.833333373,3.5}}} {{1,2}} wtTs[1]=1 {{0.833333373,3.5}} wnTs[0]=1 {{{0.833333373,3.5}, {1,2}}} wnTs[1]=0
+----------------------------------- start
+----------------------------------- addExpanded
+----------------------------------- moveMultiples
+----------------------------------- moveNearby
+----------------------------------- addEndMovedSpans
+----------------------------------- addMissing2
+----------------------------------- moveNearby2
+----------------------------------- expand2
+----------------------------------- addExpanded3
+----------------------------------- mark1
+----------------------------------- missingCoincidence2
+----------------------------------- missingCoincidence3
+----------------------------------- coincidence.reorder
+----------------------------------- pairs->apply
+----------------------------------- pairs->findOverlaps
SkOpSegment::sortAngles [3] tStart=1 [6]
-SkOpSegment::debugShowActiveSpans id=1 (494.348663,224.583771 494.364952,224.632623 494.376129,224.682892 0.998676896f) t=0 tEnd=0.988457533 windSum=? windValue=1
-SkOpSegment::debugShowActiveSpans id=1 (494.376129,224.682892 494.376274,224.68348 494.376404,224.684067 0.999999821f) t=0.988457533 tEnd=1 windSum=? windValue=1
-SkOpSegment::debugShowActiveSpans id=2 (494.376404,224.684067 492.527069,224.218475 492.952789,224.005585) t=0 tEnd=1 windSum=? windValue=1
-SkOpSegment::debugShowActiveSpans id=3 (492.952789,224.005585 494.375336,224.679337 494.376038,224.682449) t=0 tEnd=1 windSum=? windValue=1
-SkOpSegment::debugShowActiveSpans id=5 (494.37619,224.68309 494.634338,225.414886 494.895874,225.840698) t=0 tEnd=1 windSum=? windValue=1
-SkOpSegment::debugShowActiveSpans id=6 (494.895874,225.840698 494.348663,224.583771) t=0 tEnd=1 windSum=? windValue=1
-SkOpSpan::sortableTop dir=kLeft seg=1 t=0.494228767 pt=(494.363678,224.63298)
-SkOpSpan::sortableTop [0] valid=1 operand=0 span=3 ccw=1 seg=2 {{{494.376404f, 224.684067f}, {492.527069f, 224.218475f}, {492.952789f, 224.005585f}}} t=0.0557039225 pt=(494.177429,224.63298) slope=(-1.72260523,-0.451515005)
-SkOpSpan::sortableTop [1] valid=1 operand=0 span=5 ccw=0 seg=3 {{{492.952789f, 224.005585f}, {494.375336f, 224.679337f}, {494.376038f, 224.682449f}}} t=0.733006652 pt=(494.274292,224.63298) slope=(0.380324923,0.182168955)
-SkOpSpan::sortableTop [2] valid=1 operand=0 span=1 ccw=0 seg=1 {{{{494.348663f, 224.583771f}, {494.365143f, 224.633194f}, {494.376404f, 224.684067f}}}, 0.998645842f} t=0.494228767 pt=(494.363678,224.63298) slope=(0.0138909232,0.050105697)
-SkOpSegment::markWinding id=2 (494.376404,224.684067 492.527069,224.218475 492.952789,224.005585) t=0 [3] (494.376404,224.684067) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
-SkOpSegment::markWinding id=3 (492.952789,224.005585 494.375336,224.679337 494.376038,224.682449) t=0 [5] (492.952789,224.005585) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
-SkOpSegment::markWinding id=2 (494.376404,224.684067 492.527069,224.218475 492.952789,224.005585) t=0 [3] (494.376404,224.684067) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
-SkOpSegment::markWinding id=1 (494.348663,224.583771 494.365143,224.633194 494.376404,224.684067) t=0.988457533 [13] (494.376129,224.682892) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
-SkOpSegment::markWinding id=1 (494.348663,224.583771 494.365143,224.633194 494.376404,224.684067) t=0 [1] (494.348663,224.583771) tEnd=0.988457533 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
-SkOpSegment::markWinding id=1 (494.348663,224.583771 494.365143,224.633194 494.376404,224.684067) t=0 [1] (494.348663,224.583771) tEnd=0.988457533 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
-SkOpSegment::markWinding id=6 (494.895874,225.840698 494.348663,224.583771) t=0 [11] (494.895874,225.840698) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
-SkOpSegment::markWinding id=5 (494.37619,224.68309 494.634338,225.414886 494.895874,225.840698) t=0 [9] (494.37619,224.68309) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
-SkOpSegment::findNextWinding simple
-SkOpSegment::markDone id=1 (494.348663,224.583771 494.365143,224.633194 494.376404,224.684067) t=0 [1] (494.348663,224.583771) tEnd=0.988457533 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
-bridgeWinding current id=1 from=(494.376129,224.682892) to=(494.348663,224.583771)
-path.moveTo(494.376129,224.682892);
-path.conicTo(494.36496,224.632629, 494.348663,224.583771, 0.998676896);
-SkOpSegment::findNextWinding simple
-SkOpSegment::markDone id=6 (494.895874,225.840698 494.348663,224.583771) t=0 [11] (494.895874,225.840698) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
-bridgeWinding current id=6 from=(494.348663,224.583771) to=(494.895874,225.840698)
-SkOpSegment::markDone id=5 (494.37619,224.68309 494.634338,225.414886 494.895874,225.840698) t=0 [9] (494.37619,224.68309) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
-path.lineTo(494.895874,225.840698);
-SkOpSegment::debugShowActiveSpans id=1 (494.376129,224.682892 494.376274,224.68348 494.376404,224.684067 0.999999821f) t=0.988457533 tEnd=1 windSum=-1 oppSum=0 windValue=1 oppValue=0
-SkOpSegment::debugShowActiveSpans id=2 (494.376404,224.684067 492.527069,224.218475 492.952789,224.005585) t=0 tEnd=1 windSum=-1 oppSum=0 windValue=1 oppValue=0
-SkOpSegment::debugShowActiveSpans id=3 (492.952789,224.005585 494.375336,224.679337 494.376038,224.682449) t=0 tEnd=1 windSum=-1 oppSum=0 windValue=1 oppValue=0
-SkOpSegment::findNextWinding
-SkOpAngle::dumpOne [1/2] next=1/1 sect=25/25 s=0.988457533 [13] e=1 [2] sgn=-1 windVal=1 windSum=-1 oppVal=0 oppSum=0
-SkOpAngle::dumpOne [1/1] next=3/3 sect=9/9 s=0.988457533 [13] e=0 [1] sgn=1 windVal=1 windSum=1 oppVal=0 oppSum=0 done
-SkOpAngle::dumpOne [3/3] next=1/2 sect=13/13 s=1 [6] e=0 [5] sgn=1 windVal=1 windSum=-1 oppVal=0 oppSum=0
-SkOpSegment::markDone id=3 (492.952789,224.005585 494.375336,224.679337 494.376038,224.682449) t=0 [5] (492.952789,224.005585) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
-SkOpSegment::markDone id=2 (494.376404,224.684067 492.527069,224.218475 492.952789,224.005585) t=0 [3] (494.376404,224.684067) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
-SkOpSegment::markDone id=1 (494.348663,224.583771 494.365143,224.633194 494.376404,224.684067) t=0.988457533 [13] (494.376129,224.682892) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
-SkOpSegment::findNextWinding from:[1] to:[1] start=13259432 end=18937312
-bridgeWinding current id=1 from=(494.376404,224.684067) to=(494.376129,224.682892)
-path.moveTo(494.376404,224.684067);
-path.lineTo(494.376129,224.682892);
+SkOpAngle::after [3/1] 21/20 tStart=1 tEnd=0 < [1/3] 20/21 tStart=0 tEnd=1 < [2/4] 21/21 tStart=1 tEnd=0 F 7
+SkOpAngle::afterPart {{{1,2}, {0.833333373,3.5}, {-0.333333343,3.33333325}, {0,3}}} id=3
+SkOpAngle::afterPart {{{1,2}, {0,3}, {-0.333333343,3.33333325}, {0.833333373,3.5}}} id=1
+SkOpAngle::afterPart {{{1,2}, {0.833333373,3.5}}} id=2
+SkOpAngle::after [3/1] 21/20 tStart=1 tEnd=0 < [4/2] 19/19 tStart=0 tEnd=1 < [2/4] 21/21 tStart=1 tEnd=0 F 5
+SkOpAngle::afterPart {{{1,2}, {0.833333373,3.5}, {-0.333333343,3.33333325}, {0,3}}} id=3
+SkOpAngle::afterPart {{{1,2}, {0,3}}} id=4
+SkOpAngle::afterPart {{{1,2}, {0.833333373,3.5}}} id=2
+SkOpAngle::after [2/4] 21/21 tStart=1 tEnd=0 < [4/2] 19/19 tStart=0 tEnd=1 < [1/3] 20/21 tStart=0 tEnd=1 T 5
+SkOpAngle::afterPart {{{1,2}, {0.833333373,3.5}}} id=2
+SkOpAngle::afterPart {{{1,2}, {0,3}}} id=4
+SkOpAngle::afterPart {{{1,2}, {0,3}, {-0.333333343,3.33333325}, {0.833333373,3.5}}} id=1
+SkOpSegment::sortAngles [4] tStart=0 [7]
+SkOpSegment::sortAngles [1] tStart=0 [1]
+SkOpSegment::sortAngles [2] tStart=1 [4]
+SkOpSegment::debugShowActiveSpans id=3 (0,3 -0.333333343,3.33333325 0.833333373,3.5 1,2) t=0 tEnd=1 windSum=? windValue=1
+SkOpSegment::debugShowActiveSpans id=4 (1,2 0,3) t=0 tEnd=1 windSum=? windValue=1
+SkOpSegment::debugShowActiveSpans id=1 (1,2 0,3 -0.333333343,3.33333325 0.833333373,3.5) t=0 tEnd=1 windSum=? windValue=1
+SkOpSegment::debugShowActiveSpans id=2 (0.833333373,3.5 1,2) t=0 tEnd=1 windSum=? windValue=1
+SkOpSpan::sortableTop dir=kTop seg=3 t=0.5 pt=(0.3125,3.1875)
+SkOpSpan::sortableTop [0] valid=1 operand=1 span=7 ccw=0 seg=4 {{{1, 2}, {0, 3}}} t=0.6875 pt=(0.3125,2.6875) slope=(-1,1)
+SkOpSpan::sortableTop [1] valid=1 operand=0 span=1 ccw=0 seg=1 {{{1, 2}, {0, 3}, {-0.333333343f, 3.33333325f}, {0.833333373f, 3.5f}}} t=0.293719533 pt=(0.3125,2.72128606) slope=(-1.60944396,1.95452854)
+SkOpSpan::sortableTop [2] valid=1 operand=1 span=5 ccw=1 seg=3 {{{0, 3}, {-0.333333343f, 3.33333325f}, {0.833333373f, 3.5f}, {1, 2}}} t=0.5 pt=(0.3125,3.1875) slope=(1.62500004,-0.62499994)
+SkOpSegment::markWinding id=4 (1,2 0,3) t=0 [7] (1,2) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
+SkOpSegment::markWinding id=3 (0,3 -0.333333343,3.33333325 0.833333373,3.5 1,2) t=0 [5] (0,3) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
+SkOpSegment::markWinding id=4 (1,2 0,3) t=0 [7] (1,2) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
+SkOpSegment::markWinding id=1 (1,2 0,3 -0.333333343,3.33333325 0.833333373,3.5) t=0 [1] (1,2) tEnd=1 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1 oppValue=0
+SkOpSegment::markWinding id=2 (0.833333373,3.5 1,2) t=0 [3] (0.833333373,3.5) tEnd=1 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=0
+SkOpSegment::markWinding id=1 (1,2 0,3 -0.333333343,3.33333325 0.833333373,3.5) t=0 [1] (1,2) tEnd=1 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1 oppValue=0
+SkOpSegment::activeOp id=3 t=1 tEnd=0 op=sect miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
+SkOpSegment::markDone id=3 (0,3 -0.333333343,3.33333325 0.833333373,3.5 1,2) t=0 [5] (0,3) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
+SkOpSegment::markDone id=4 (1,2 0,3) t=0 [7] (1,2) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
+bridgeOp chase.append id=4 windSum=1
+SkOpSegment::debugShowActiveSpans id=1 (1,2 0,3 -0.333333343,3.33333325 0.833333373,3.5) t=0 tEnd=1 windSum=1 oppSum=1 windValue=1 oppValue=0
+SkOpSegment::debugShowActiveSpans id=2 (0.833333373,3.5 1,2) t=0 tEnd=1 windSum=1 oppSum=1 windValue=1 oppValue=0
+SkOpSegment::activeOp id=1 t=0 tEnd=1 op=sect miFrom=0 miTo=1 suFrom=1 suTo=1 result=1
+SkOpSegment::findNextOp simple
+SkOpSegment::markDone id=1 (1,2 0,3 -0.333333343,3.33333325 0.833333373,3.5) t=0 [1] (1,2) tEnd=1 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1 oppValue=0
+bridgeOp current id=1 from=(1,2) to=(0.833333373,3.5)
+path.moveTo(1,2);
+path.cubicTo(0,3, -0.333333343,3.33333325, 0.833333373,3.5);
+SkOpSegment::findNextOp
+SkOpAngle::dumpOne [2/4] next=4/2 sect=21/21 s=1 [4] e=0 [3] sgn=1 windVal=1 windSum=1 oppVal=0 oppSum=1
+SkOpAngle::dumpOne [4/2] next=1/3 sect=19/19 s=0 [7] e=1 [8] sgn=-1 windVal=1 windSum=1 oppVal=0 oppSum=0 done operand
+SkOpAngle::dumpOne [1/3] next=3/1 sect=20/21 s=0 [1] e=1 [2] sgn=-1 windVal=1 windSum=1 oppVal=0 oppSum=1 done
+SkOpAngle::dumpOne [3/1] next=2/4 sect=21/20 s=1 [6] e=0 [5] sgn=1 windVal=1 windSum=1 oppVal=0 oppSum=0 done operand
+SkOpSegment::activeOp id=4 t=0 tEnd=1 op=sect miFrom=0 miTo=0 suFrom=1 suTo=1 result=0
+SkOpSegment::activeOp id=1 t=0 tEnd=1 op=sect miFrom=0 miTo=1 suFrom=1 suTo=1 result=1
+SkOpSegment::activeOp id=3 t=1 tEnd=0 op=sect miFrom=1 miTo=1 suFrom=1 suTo=1 result=0
+SkOpSegment::markDone id=2 (0.833333373,3.5 1,2) t=0 [3] (0.833333373,3.5) tEnd=1 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1 oppValue=0
+SkOpSegment::findNextOp from:[2] to:[1] start=20180984 end=20181096
+bridgeOp current id=2 from=(0.833333373,3.5) to=(1,2)
+path.lineTo(1,2);
+path.close();
</div>
</div>
@@ -91,7 +153,7 @@ path.lineTo(494.376129,224.682892);
<script type="text/javascript">
var testDivs = [
- tiger8b_h_1,
+ loop17,
];
var decimal_places = 3; // make this 3 to show more precision