aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gyp/pathops_unittest.gypi3
-rw-r--r--src/pathops/SkOpContour.cpp4
-rw-r--r--src/pathops/SkOpContour.h4
-rw-r--r--src/pathops/SkOpSegment.cpp82
-rw-r--r--src/pathops/SkOpSegment.h3
-rwxr-xr-xsrc/pathops/SkOpSpan.cpp1
-rw-r--r--src/pathops/SkOpSpan.h9
-rw-r--r--src/pathops/SkPathOpsConic.cpp9
-rw-r--r--src/pathops/SkPathOpsOp.cpp12
-rw-r--r--src/pathops/SkPathOpsSimplify.cpp46
-rw-r--r--src/pathops/SkPathOpsTSect.h14
-rw-r--r--tests/PathOpsBuilderConicTest.cpp639
-rw-r--r--tests/PathOpsConicIntersectionTest.cpp276
-rw-r--r--tests/SubsetPath.cpp240
-rw-r--r--tests/SubsetPath.h66
-rw-r--r--tools/pathops_sorter.htm63
-rw-r--r--tools/pathops_visualizer.htm356
17 files changed, 1512 insertions, 315 deletions
diff --git a/gyp/pathops_unittest.gypi b/gyp/pathops_unittest.gypi
index 923a25a5b8..750a65a38a 100644
--- a/gyp/pathops_unittest.gypi
+++ b/gyp/pathops_unittest.gypi
@@ -24,6 +24,7 @@
'../tests/PathOpsAngleTest.cpp',
'../tests/PathOpsBoundsTest.cpp',
+ '../tests/PathOpsBuilderConicTest.cpp',
'../tests/PathOpsBuilderTest.cpp',
'../tests/PathOpsBuildUseTest.cpp',
'../tests/PathOpsConicIntersectionTest.cpp',
@@ -67,6 +68,7 @@
'../tests/PathOpsThreeWayTest.cpp',
'../tests/PathOpsTightBoundsTest.cpp',
'../tests/PathOpsTypesTest.cpp',
+ '../tests/SubsetPath.cpp',
'../tests/PathOpsCubicIntersectionTestData.h',
'../tests/PathOpsExtendedTest.h',
@@ -74,5 +76,6 @@
'../tests/PathOpsTestCommon.h',
'../tests/PathOpsThreadedCommon.h',
'../tests/PathOpsTSectDebug.h',
+ '../tests/SubsetPath.h',
],
}
diff --git a/src/pathops/SkOpContour.cpp b/src/pathops/SkOpContour.cpp
index 2e4b2ca56a..df65437c97 100644
--- a/src/pathops/SkOpContour.cpp
+++ b/src/pathops/SkOpContour.cpp
@@ -42,7 +42,7 @@ void SkOpContour::toPath(SkPathWriter* path) const {
path->deferredMove(pt);
const SkOpSegment* segment = &fHead;
do {
- segment->addCurveTo(segment->head(), segment->tail(), path, true);
+ SkAssertResult(segment->addCurveTo(segment->head(), segment->tail(), path));
} while ((segment = segment->next()));
path->close();
}
@@ -52,7 +52,7 @@ void SkOpContour::toReversePath(SkPathWriter* path) const {
path->deferredMove(pt);
const SkOpSegment* segment = fTail;
do {
- segment->addCurveTo(segment->tail(), segment->head(), path, true);
+ SkAssertResult(segment->addCurveTo(segment->tail(), segment->head(), path));
} while ((segment = segment->prev()));
path->close();
}
diff --git a/src/pathops/SkOpContour.h b/src/pathops/SkOpContour.h
index c6120089bd..d0e09a3a70 100644
--- a/src/pathops/SkOpContour.h
+++ b/src/pathops/SkOpContour.h
@@ -397,14 +397,14 @@ public:
void toPartialBackward(SkPathWriter* path) const {
const SkOpSegment* segment = fTail;
do {
- segment->addCurveTo(segment->tail(), segment->head(), path, true);
+ SkAssertResult(segment->addCurveTo(segment->tail(), segment->head(), path));
} while ((segment = segment->prev()));
}
void toPartialForward(SkPathWriter* path) const {
const SkOpSegment* segment = &fHead;
do {
- segment->addCurveTo(segment->head(), segment->tail(), path, true);
+ SkAssertResult(segment->addCurveTo(segment->head(), segment->tail(), path));
} while ((segment = segment->next()));
}
diff --git a/src/pathops/SkOpSegment.cpp b/src/pathops/SkOpSegment.cpp
index 76032aaf0c..3b81cf2eed 100644
--- a/src/pathops/SkOpSegment.cpp
+++ b/src/pathops/SkOpSegment.cpp
@@ -240,8 +240,11 @@ void SkOpSegment::addAlignIntersection(SkOpPtT& endPtT, SkPoint& oldPt,
} while ((current = current->next()));
}
-void SkOpSegment::addCurveTo(const SkOpSpanBase* start, const SkOpSpanBase* end,
- SkPathWriter* path, bool active) const {
+bool SkOpSegment::addCurveTo(const SkOpSpanBase* start, const SkOpSpanBase* end,
+ SkPathWriter* path) const {
+ if (start->starter(end)->alreadyAdded()) {
+ return false;
+ }
SkOpCurve edge;
const SkPoint* ePtr;
SkScalar eWeight;
@@ -254,46 +257,45 @@ void SkOpSegment::addCurveTo(const SkOpSpanBase* start, const SkOpSpanBase* end,
ePtr = edge.fPts;
eWeight = edge.fWeight;
}
- if (active) {
- bool reverse = ePtr == fPts && start != &fHead;
- if (reverse) {
- path->deferredMoveLine(ePtr[SkPathOpsVerbToPoints(fVerb)]);
- switch (fVerb) {
- case SkPath::kLine_Verb:
- path->deferredLine(ePtr[0]);
- break;
- case SkPath::kQuad_Verb:
- path->quadTo(ePtr[1], ePtr[0]);
- break;
- case SkPath::kConic_Verb:
- path->conicTo(ePtr[1], ePtr[0], eWeight);
- break;
- case SkPath::kCubic_Verb:
- path->cubicTo(ePtr[2], ePtr[1], ePtr[0]);
- break;
- default:
- SkASSERT(0);
- }
- } else {
- path->deferredMoveLine(ePtr[0]);
- switch (fVerb) {
- case SkPath::kLine_Verb:
- path->deferredLine(ePtr[1]);
- break;
- case SkPath::kQuad_Verb:
- path->quadTo(ePtr[1], ePtr[2]);
- break;
- case SkPath::kConic_Verb:
- path->conicTo(ePtr[1], ePtr[2], eWeight);
- break;
- case SkPath::kCubic_Verb:
- path->cubicTo(ePtr[1], ePtr[2], ePtr[3]);
- break;
- default:
- SkASSERT(0);
- }
+ bool reverse = ePtr == fPts && start != &fHead;
+ if (reverse) {
+ path->deferredMoveLine(ePtr[SkPathOpsVerbToPoints(fVerb)]);
+ switch (fVerb) {
+ case SkPath::kLine_Verb:
+ path->deferredLine(ePtr[0]);
+ break;
+ case SkPath::kQuad_Verb:
+ path->quadTo(ePtr[1], ePtr[0]);
+ break;
+ case SkPath::kConic_Verb:
+ path->conicTo(ePtr[1], ePtr[0], eWeight);
+ break;
+ case SkPath::kCubic_Verb:
+ path->cubicTo(ePtr[2], ePtr[1], ePtr[0]);
+ break;
+ default:
+ SkASSERT(0);
+ }
+ } else {
+ path->deferredMoveLine(ePtr[0]);
+ switch (fVerb) {
+ case SkPath::kLine_Verb:
+ path->deferredLine(ePtr[1]);
+ break;
+ case SkPath::kQuad_Verb:
+ path->quadTo(ePtr[1], ePtr[2]);
+ break;
+ case SkPath::kConic_Verb:
+ path->conicTo(ePtr[1], ePtr[2], eWeight);
+ break;
+ case SkPath::kCubic_Verb:
+ path->cubicTo(ePtr[1], ePtr[2], ePtr[3]);
+ break;
+ default:
+ SkASSERT(0);
}
}
+ return true;
}
SkOpPtT* SkOpSegment::addMissing(double t, SkOpSegment* opp, SkChunkAlloc* allocator) {
diff --git a/src/pathops/SkOpSegment.h b/src/pathops/SkOpSegment.h
index 98e140cba3..06649aa2be 100644
--- a/src/pathops/SkOpSegment.h
+++ b/src/pathops/SkOpSegment.h
@@ -69,8 +69,7 @@ public:
return this;
}
- void addCurveTo(const SkOpSpanBase* start, const SkOpSpanBase* end, SkPathWriter* path,
- bool active) const;
+ bool addCurveTo(const SkOpSpanBase* start, const SkOpSpanBase* end, SkPathWriter* path) const;
SkOpAngle* addEndSpan(SkChunkAlloc* allocator) {
SkOpAngle* angle = SkOpTAllocator<SkOpAngle>::Allocate(allocator);
diff --git a/src/pathops/SkOpSpan.cpp b/src/pathops/SkOpSpan.cpp
index 4d437f7f88..7c98e1dcc6 100755
--- a/src/pathops/SkOpSpan.cpp
+++ b/src/pathops/SkOpSpan.cpp
@@ -361,6 +361,7 @@ void SkOpSpan::init(SkOpSegment* segment, SkOpSpan* prev, double t, const SkPoin
fTopTTry = 0;
fChased = fDone = false;
segment->bumpCount();
+ fAlreadyAdded = false;
}
void SkOpSpan::setOppSum(int oppSum) {
diff --git a/src/pathops/SkOpSpan.h b/src/pathops/SkOpSpan.h
index dab0dfaf03..e512554cc6 100644
--- a/src/pathops/SkOpSpan.h
+++ b/src/pathops/SkOpSpan.h
@@ -372,6 +372,14 @@ protected: // no direct access to internals to avoid treating a span base as a
class SkOpSpan : public SkOpSpanBase {
public:
+ bool alreadyAdded() const {
+ if (fAlreadyAdded) {
+ return true;
+ }
+ fAlreadyAdded = true;
+ return false;
+ }
+
bool clearCoincident() {
SkASSERT(!final());
if (fCoincident == this) {
@@ -506,6 +514,7 @@ private: // no direct access to internals to avoid treating a span base as a sp
int fOppValue; // normally 0 -- when binary coincident edges combine, opp value goes here
int fTopTTry; // specifies direction and t value to try next
bool fDone; // if set, this span to next higher T has been processed
+ mutable bool fAlreadyAdded;
};
#endif
diff --git a/src/pathops/SkPathOpsConic.cpp b/src/pathops/SkPathOpsConic.cpp
index f80af036ee..86bad262e3 100644
--- a/src/pathops/SkPathOpsConic.cpp
+++ b/src/pathops/SkPathOpsConic.cpp
@@ -153,13 +153,8 @@ SkDConic SkDConic::subDivide(double t1, double t2) const {
double bx = 2 * dx - (ax + cx) / 2;
double by = 2 * dy - (ay + cy) / 2;
double bz = 2 * dz - (az + cz) / 2;
- SkDConic dst = {{{{ax / az, ay / az}, {bx / bz, by / bz}, {cx / cz, cy / cz}}}, 0 };
- SkDPoint dMidAC = { (dst.fPts[0].fX + dst.fPts[2].fX) / 2,
- (dst.fPts[0].fY + dst.fPts[2].fY) / 2 };
- SkDPoint dMid = { dx / dz, dy / dz };
- SkDVector dWNumer = dMidAC - dMid;
- SkDVector dWDenom = dMid - dst.fPts[1];
- dst.fWeight = dWNumer.length() / dWDenom.length();
+ SkDConic dst = {{{{ax / az, ay / az}, {bx / bz, by / bz}, {cx / cz, cy / cz}}},
+ SkDoubleToScalar(bz / sqrt(az * cz)) };
return dst;
}
diff --git a/src/pathops/SkPathOpsOp.cpp b/src/pathops/SkPathOpsOp.cpp
index b5e00908fd..257cb8ee69 100644
--- a/src/pathops/SkPathOpsOp.cpp
+++ b/src/pathops/SkPathOpsOp.cpp
@@ -111,7 +111,9 @@ static bool bridgeOp(SkOpContourHead* contourList, const SkPathOp op,
if (!unsortable && simple->hasMove()
&& current->verb() != SkPath::kLine_Verb
&& !simple->isClosed()) {
- current->addCurveTo(start, end, simple, true);
+ if (!current->addCurveTo(start, end, simple)) {
+ return false;
+ }
#if DEBUG_ACTIVE_SPANS
if (!simple->isClosed()) {
DebugShowActiveSpans(contourList);
@@ -125,7 +127,9 @@ static bool bridgeOp(SkOpContourHead* contourList, const SkPathOp op,
current->debugID(), start->pt().fX, start->pt().fY,
end->pt().fX, end->pt().fY);
#endif
- current->addCurveTo(start, end, simple, true);
+ if (!current->addCurveTo(start, end, simple)) {
+ return false;
+ }
current = next;
start = nextStart;
end = nextEnd;
@@ -133,7 +137,9 @@ static bool bridgeOp(SkOpContourHead* contourList, const SkPathOp op,
if (current->activeWinding(start, end) && !simple->isClosed()) {
SkOpSpan* spanStart = start->starter(end);
if (!spanStart->done()) {
- current->addCurveTo(start, end, simple, true);
+ if (!current->addCurveTo(start, end, simple)) {
+ return false;
+ }
current->markDone(spanStart);
}
}
diff --git a/src/pathops/SkPathOpsSimplify.cpp b/src/pathops/SkPathOpsSimplify.cpp
index 34b19d1fe2..08bb26d9a9 100644
--- a/src/pathops/SkPathOpsSimplify.cpp
+++ b/src/pathops/SkPathOpsSimplify.cpp
@@ -11,7 +11,7 @@
#include "SkPathWriter.h"
static bool bridgeWinding(SkOpContourHead* contourList, SkPathWriter* simple,
- SkChunkAlloc* allocator) {
+ SkChunkAlloc* allocator, bool* closable) {
bool unsortable = false;
do {
SkOpSpan* span = FindSortableTop(contourList);
@@ -37,7 +37,9 @@ static bool bridgeWinding(SkOpContourHead* contourList, SkPathWriter* simple,
if (!unsortable && simple->hasMove()
&& current->verb() != SkPath::kLine_Verb
&& !simple->isClosed()) {
- current->addCurveTo(start, end, simple, true);
+ if (!current->addCurveTo(start, end, simple)) {
+ return false;
+ }
#if DEBUG_ACTIVE_SPANS
if (!simple->isClosed()) {
DebugShowActiveSpans(contourList);
@@ -51,7 +53,9 @@ static bool bridgeWinding(SkOpContourHead* contourList, SkPathWriter* simple,
current->debugID(), start->pt().fX, start->pt().fY,
end->pt().fX, end->pt().fY);
#endif
- current->addCurveTo(start, end, simple, true);
+ if (!current->addCurveTo(start, end, simple)) {
+ return false;
+ }
current = next;
start = nextStart;
end = nextEnd;
@@ -59,7 +63,9 @@ static bool bridgeWinding(SkOpContourHead* contourList, SkPathWriter* simple,
if (current->activeWinding(start, end) && !simple->isClosed()) {
SkOpSpan* spanStart = start->starter(end);
if (!spanStart->done()) {
- current->addCurveTo(start, end, simple, true);
+ if (!current->addCurveTo(start, end, simple)) {
+ return false;
+ }
current->markDone(spanStart);
}
}
@@ -88,17 +94,18 @@ static bool bridgeWinding(SkOpContourHead* contourList, SkPathWriter* simple,
}
} while (true);
} while (true);
- return simple->someAssemblyRequired();
+ *closable = !simple->someAssemblyRequired();
+ return true;
}
// returns true if all edges were processed
static bool bridgeXor(SkOpContourHead* contourList, SkPathWriter* simple,
- SkChunkAlloc* allocator) {
+ SkChunkAlloc* allocator, bool* closable) {
SkOpSegment* current;
SkOpSpanBase* start;
SkOpSpanBase* end;
bool unsortable = false;
- bool closable = true;
+ *closable = true;
while ((current = FindUndone(contourList, &start, &end))) {
do {
#if DEBUG_ACTIVE_SPANS
@@ -114,7 +121,9 @@ static bool bridgeXor(SkOpContourHead* contourList, SkPathWriter* simple,
if (!unsortable && simple->hasMove()
&& current->verb() != SkPath::kLine_Verb
&& !simple->isClosed()) {
- current->addCurveTo(start, end, simple, true);
+ if (!current->addCurveTo(start, end, simple)) {
+ return false;
+ }
#if DEBUG_ACTIVE_SPANS
if (!simple->isClosed()) {
DebugShowActiveSpans(contourList);
@@ -128,7 +137,9 @@ static bool bridgeXor(SkOpContourHead* contourList, SkPathWriter* simple,
current->debugID(), start->pt().fX, start->pt().fY,
end->pt().fX, end->pt().fY);
#endif
- current->addCurveTo(start, end, simple, true);
+ if (!current->addCurveTo(start, end, simple)) {
+ return false;
+ }
current = next;
start = nextStart;
end = nextEnd;
@@ -137,17 +148,19 @@ static bool bridgeXor(SkOpContourHead* contourList, SkPathWriter* simple,
SkASSERT(unsortable);
SkOpSpan* spanStart = start->starter(end);
if (!spanStart->done()) {
- current->addCurveTo(start, end, simple, true);
+ if (!current->addCurveTo(start, end, simple)) {
+ return false;
+ }
current->markDone(spanStart);
}
- closable = false;
+ *closable = false;
}
simple->close();
#if DEBUG_ACTIVE_SPANS
DebugShowActiveSpans(contourList);
#endif
}
- return closable;
+ return true;
}
// FIXME : add this as a member of SkPath
@@ -203,8 +216,13 @@ bool Simplify(const SkPath& path, SkPath* result) {
result->reset();
result->setFillType(fillType);
SkPathWriter wrapper(*result);
- if (builder.xorMask() == kWinding_PathOpsMask ? bridgeWinding(contourList, &wrapper, &allocator)
- : !bridgeXor(contourList, &wrapper, &allocator))
+ bool closable;
+ if (builder.xorMask() == kWinding_PathOpsMask
+ ? !bridgeWinding(contourList, &wrapper, &allocator, &closable)
+ : !bridgeXor(contourList, &wrapper, &allocator, &closable)) {
+ return false;
+ }
+ if (!closable)
{ // if some edges could not be resolved, assemble remaining fragments
SkPath temp;
temp.setFillType(fillType);
diff --git a/src/pathops/SkPathOpsTSect.h b/src/pathops/SkPathOpsTSect.h
index 56a320aab2..bebdf40208 100644
--- a/src/pathops/SkPathOpsTSect.h
+++ b/src/pathops/SkPathOpsTSect.h
@@ -987,8 +987,8 @@ void SkTSect<TCurve, OppCurve>::coincidentForce(SkTSect<OppCurve, TCurve>* sect2
first->fCoinStart.setPerp(fCurve, start1s, fCurve[0], sect2->fCurve);
first->fCoinEnd.setPerp(fCurve, start1e, fCurve[TCurve::kPointLast], sect2->fCurve);
bool oppMatched = first->fCoinStart.perpT() < first->fCoinEnd.perpT();
- double oppStartT = SkTMax(0., first->fCoinStart.perpT());
- double oppEndT = SkTMin(1., first->fCoinEnd.perpT());
+ double oppStartT = first->fCoinStart.perpT() == -1 ? 0 : SkTMax(0., first->fCoinStart.perpT());
+ double oppEndT = first->fCoinEnd.perpT() == -1 ? 1 : SkTMin(1., first->fCoinEnd.perpT());
if (!oppMatched) {
SkTSwap(oppStartT, oppEndT);
}
@@ -2086,7 +2086,7 @@ void SkTSect<TCurve, OppCurve>::BinarySearch(SkTSect<TCurve, OppCurve>* sect1,
#if DEBUG_T_SECT_LOOP_COUNT
intersections->debugBumpLoopCount(SkIntersections::kCoinCheck_DebugLoop);
#endif
- if (!--coinLoopCount) {
+ if (!--coinLoopCount && sect1->fHead && sect2->fHead) {
/* All known working cases resolve in two tries. Sadly, cubicConicTests[0]
gets stuck in a loop. It adds an extension to allow a coincident end
perpendicular to track its intersection in the opposite curve. However,
@@ -2127,8 +2127,12 @@ void SkTSect<TCurve, OppCurve>::BinarySearch(SkTSect<TCurve, OppCurve>* sect1,
}
SkASSERT(sect2->fCoincident); // courtesy check : coincidence only looks at sect 1
do {
- SkASSERT(coincident->fCoinStart.isCoincident());
- SkASSERT(coincident->fCoinEnd.isCoincident());
+ if (!coincident->fCoinStart.isCoincident()) {
+ continue;
+ }
+ if (!coincident->fCoinEnd.isCoincident()) {
+ continue;
+ }
int index = intersections->insertCoincident(coincident->fStartT,
coincident->fCoinStart.perpT(), coincident->fPart[0]);
if ((intersections->insertCoincident(coincident->fEndT,
diff --git a/tests/PathOpsBuilderConicTest.cpp b/tests/PathOpsBuilderConicTest.cpp
new file mode 100644
index 0000000000..6bb5c70d36
--- /dev/null
+++ b/tests/PathOpsBuilderConicTest.cpp
@@ -0,0 +1,639 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "PathOpsExtendedTest.h"
+#include "SkRandom.h"
+#include "SkRegion.h"
+#include "SubsetPath.h"
+
+#define DEBUG_SIMPLIFY_FAILS 0
+
+struct OvalSet {
+ SkRect fBounds;
+ int fColumns;
+ int fRows;
+ int fRotations;
+ SkScalar fXSpacing;
+ SkScalar fYSpacing;
+};
+
+static void testOvalSet(const OvalSet& set, const SkPath& oval, SkOpBuilder* builder,
+ SkRegion* region, SkPath* result) {
+ for (int x = 0; x < set.fColumns; ++x) {
+ for (int y = 0; y < set.fRows; ++y) {
+ for (SkScalar r = 0; r < 360; r += 360.f / set.fRotations) {
+ SkPath rotated;
+ SkMatrix matrix;
+ matrix.reset();
+ matrix.postRotate(r, 0, 0);
+ matrix.postTranslate(x * set.fXSpacing, y * set.fYSpacing);
+ oval.transform(matrix, &rotated);
+ if (builder) {
+ builder->add(rotated, kUnion_SkPathOp);
+ } else if (!region) {
+ Op(*result, rotated, kUnion_SkPathOp, result);
+ } else {
+ SkRegion rgnB, openClip;
+ openClip.setRect(-16000, -16000, 16000, 16000);
+ rgnB.setPath(rotated, openClip);
+ region->op(rgnB, SkRegion::kUnion_Op);
+ }
+ }
+ }
+ }
+ if (builder) {
+ builder->resolve(result);
+ } else if (region) {
+ region->getBoundaryPath(result);
+ }
+}
+
+static void testOne(skiatest::Reporter* reporter, const OvalSet& set) {
+ SkPath oval, regionResult, builderResult, opResult;
+ oval.setFillType(SkPath::kWinding_FillType);
+ oval.addOval(set.fBounds);
+ SkOpBuilder builder;
+ SkRegion region;
+ testOvalSet(set, oval, nullptr, &region, &regionResult);
+ testOvalSet(set, oval, &builder, nullptr, &builderResult);
+ testOvalSet(set, oval, nullptr, nullptr, &opResult);
+ SkBitmap bitmap;
+ comparePaths(reporter, __FUNCTION__ , regionResult, builderResult, bitmap);
+ comparePaths(reporter, __FUNCTION__ , regionResult, opResult, bitmap);
+}
+
+struct OvalSetOneOff {
+ int fCol;
+ int fRow;
+ int fRot;
+ int fTrial;
+} oneOffs[] = {
+ { 2, 2, 9, 73 },
+ { 1, 2, 7, 93 }
+};
+
+static void setupOne(skiatest::Reporter* reporter, int col, int row, int rot, int trial) {
+ const int scale = 10;
+ SkRandom r;
+ r.setSeed(col * 100000000 + row * 10000000 + rot * 1000000 + trial);
+ SkScalar xOffset = r.nextRangeScalar(1, 40) * scale;
+ SkScalar yOffset = r.nextRangeScalar(1, 100) * scale;
+ OvalSet set = {{0, 0, 0, 0}, col, row, rot, xOffset, yOffset};
+ set.fBounds.setXYWH(5, 5,
+ r.nextRangeScalar(5, 50) * scale, r.nextRangeScalar(50, 90) * scale);
+ testOne(reporter, set);
+}
+
+DEFINE_int32(processOffset, 0, "Offset the test by this value. This permits multiple processes "
+ "to exercise the same test in parallel with different test values.");
+DEFINE_int32(processCount, 1, "Test iteration count. This permits multiple "
+ "processes "
+ "to exercise the same test in parallel with different test values.");
+DEFINE_int32(trialRuns, 100, "Run this many tests (defaults to 100).");
+
+DEF_TEST(SixtyOvals, reporter) {
+ bool skipOneOffs = false;
+ int trialRuns = FLAGS_trialRuns / FLAGS_processCount;
+ for (int col = 1; col <= 2; ++col) {
+ for (int row = 1; row <= 3; ++row) {
+ for (int rot = 2; rot <= 9; ++rot) {
+ for (int trial = FLAGS_processOffset * trialRuns; --trialRuns >= 0; ++trial) {
+ if (skipOneOffs) {
+ for (const OvalSetOneOff& oneOff : oneOffs) {
+ if (col == oneOff.fCol && row == oneOff.fRow && rot == oneOff.fRot
+ && trial == oneOff.fTrial) {
+ goto skipTest;
+ }
+ }
+ }
+ setupOne(reporter, col, row, rot, trial);
+ skipTest:
+ ;
+ }
+ }
+ }
+ }
+}
+
+DEF_TEST(SixtyOvalsOneOff, reporter) {
+ for (const OvalSetOneOff& oneOff : oneOffs) {
+ setupOne(reporter, oneOff.fCol, oneOff.fRow, oneOff.fRot, oneOff.fTrial);
+ }
+}
+
+#if DEBUG_SIMPLIFY_FAILS
+static bool simplify_fails(skiatest::Reporter* reporter, const SkPath& path) {
+ SkPath dummy;
+ bool failed = !Simplify(path, &dummy);
+ if (!failed) {
+ SkBitmap bitmap;
+ failed = !!comparePaths(reporter, __FUNCTION__, path, dummy, bitmap);
+ }
+ return failed;
+}
+
+static SkPath subset_simplify_fail(skiatest::Reporter* reporter, const SkPath& path) {
+ SubsetContours subsetContours(path);
+ bool failed = simplify_fails(reporter, path);
+ SkASSERT(failed);
+ SkPath lastFailed = path;
+ SkPath minimal;
+ while (subsetContours.subset(failed, &minimal)) {
+ failed = simplify_fails(reporter, minimal);
+ SkDebugf(" %s\n", failed ? "failed" : "");
+ if (failed) {
+ lastFailed = minimal;
+ }
+ }
+ failed = simplify_fails(reporter, lastFailed);
+ SkASSERT(failed);
+ SubsetVerbs subsetVerbs(lastFailed);
+ while (subsetVerbs.subset(failed, &minimal)) {
+ failed = simplify_fails(reporter, minimal);
+ SkDebugf(" %s\n", failed ? "failed" : "");
+ if (failed) {
+ lastFailed = minimal;
+ }
+ }
+ return lastFailed;
+}
+#endif
+
+DEF_TEST(SixtyOvals_2_2_9_73, reporter) {
+ SkPath path;
+ path.moveTo(SkBits2Float(0x434d53ca), SkBits2Float(0x43ad6ab0)); // 205.327f, 346.833f
+path.conicTo(SkBits2Float(0x434d53ca), SkBits2Float(0x40a00000), SkBits2Float(0x42d253ca), SkBits2Float(0x40a00000), SkBits2Float(0x3f3504f3)); // 205.327f, 5, 105.164f, 5, 0.707107f
+path.conicTo(SkBits2Float(0x40a00000), SkBits2Float(0x40a00000), SkBits2Float(0x40a00000), SkBits2Float(0x43ad6ab0), SkBits2Float(0x3f3504f3)); // 5, 5, 5, 346.833f, 0.707107f
+path.conicTo(SkBits2Float(0x40a00000), SkBits2Float(0x442c2ab0), SkBits2Float(0x42d253ca), SkBits2Float(0x442c2ab0), SkBits2Float(0x3f3504f3)); // 5, 688.667f, 105.164f, 688.667f, 0.707107f
+path.conicTo(SkBits2Float(0x434d53ca), SkBits2Float(0x442c2ab0), SkBits2Float(0x434d53ca), SkBits2Float(0x43ad6ab0), SkBits2Float(0x3f3504f3)); // 205.327f, 688.667f, 205.327f, 346.833f, 0.707107f
+path.close();
+path.moveTo(SkBits2Float(0xc2834d04), SkBits2Float(0x43c6d5fb)); // -65.6504f, 397.672f
+path.conicTo(SkBits2Float(0x431a136e), SkBits2Float(0x4307cfe3), SkBits2Float(0x429ab133), SkBits2Float(0x428edb31), SkBits2Float(0x3f3504f3)); // 154.076f, 135.812f, 77.3461f, 71.4281f, 0.707107f
+path.conicTo(SkBits2Float(0x3f1dc4d0), SkBits2Float(0x40e169c2), SkBits2Float(0xc35b1c2c), SkBits2Float(0x438673b0), SkBits2Float(0x3f3504f3)); // 0.616284f, 7.04416f, -219.11f, 268.904f, 0.707107f
+path.conicTo(SkBits2Float(0xc3db6b0e), SkBits2Float(0x4404b0dc), SkBits2Float(0xc3b50da4), SkBits2Float(0x4414c96f), SkBits2Float(0x3f3504f3)); // -438.836f, 530.763f, -362.107f, 595.147f, 0.707107f
+path.conicTo(SkBits2Float(0xc38eb03a), SkBits2Float(0x4424e202), SkBits2Float(0xc2834d04), SkBits2Float(0x43c6d5fb), SkBits2Float(0x3f3504f3)); // -285.377f, 659.531f, -65.6504f, 397.672f, 0.707107f
+path.close();
+path.moveTo(SkBits2Float(0xc398f46d), SkBits2Float(0x438337ac)); // -305.91f, 262.435f
+path.conicTo(SkBits2Float(0x41f5d870), SkBits2Float(0x434b137f), SkBits2Float(0x41556629), SkBits2Float(0x42d0de52), SkBits2Float(0x3f3504f3)); // 30.7307f, 203.076f, 13.3374f, 104.434f, 0.707107f
+path.conicTo(SkBits2Float(0xc081c918), SkBits2Float(0x40b95a5c), SkBits2Float(0xc3aa5918), SkBits2Float(0x42824d58), SkBits2Float(0x3f3504f3)); // -4.0558f, 5.79228f, -340.696f, 65.1511f, 0.707107f
+path.conicTo(SkBits2Float(0xc4295587), SkBits2Float(0x42f9050a), SkBits2Float(0xc424fc5c), SkBits2Float(0x435f26db), SkBits2Float(0x3f3504f3)); // -677.336f, 124.51f, -659.943f, 223.152f, 0.707107f
+path.conicTo(SkBits2Float(0xc420a331), SkBits2Float(0x43a0e598), SkBits2Float(0xc398f46d), SkBits2Float(0x438337ac), SkBits2Float(0x3f3504f3)); // -642.55f, 321.794f, -305.91f, 262.435f, 0.707107f
+path.close();
+path.moveTo(SkBits2Float(0xc3c983e0), SkBits2Float(0x408cdc40)); // -403.03f, 4.40189f
+path.conicTo(SkBits2Float(0xc2d5fcd2), SkBits2Float(0x432f5193), SkBits2Float(0xc263a5d9), SkBits2Float(0x42b12617), SkBits2Float(0x3f3504f3)); // -106.994f, 175.319f, -56.912f, 88.5744f, 0.707107f
+path.conicTo(SkBits2Float(0xc0da9066), SkBits2Float(0x3fea4196), SkBits2Float(0xc3976eed), SkBits2Float(0xc329162e), SkBits2Float(0x3f3504f3)); // -6.83013f, 1.83013f, -302.867f, -169.087f, 0.707107f
+path.conicTo(SkBits2Float(0xc415b9cc), SkBits2Float(0xc3aa006f), SkBits2Float(0xc4223f09), SkBits2Float(0xc37d4256), SkBits2Float(0x3f3504f3)); // -598.903f, -340.003f, -648.985f, -253.259f, 0.707107f
+path.conicTo(SkBits2Float(0xc42ec446), SkBits2Float(0xc32683cf), SkBits2Float(0xc3c983e0), SkBits2Float(0x408cdc40), SkBits2Float(0x3f3504f3)); // -699.067f, -166.515f, -403.03f, 4.40189f, 0.707107f
+path.close();
+path.moveTo(SkBits2Float(0xc39bc8c8), SkBits2Float(0xc37fb0d7)); // -311.569f, -255.691f
+path.conicTo(SkBits2Float(0xc342a797), SkBits2Float(0x42830e25), SkBits2Float(0xc2c9102e), SkBits2Float(0x41fa2834), SkBits2Float(0x3f3504f3)); // -194.655f, 65.5276f, -100.532f, 31.2696f, 0.707107f
+path.conicTo(SkBits2Float(0xc0cd12f5), SkBits2Float(0xc03f4152), SkBits2Float(0xc2f6a523), SkBits2Float(0xc3a21a77), SkBits2Float(0x3f3504f3)); // -6.40856f, -2.98836f, -123.323f, -324.207f, 0.707107f
+path.conicTo(SkBits2Float(0xc3703c8a), SkBits2Float(0xc4215b37), SkBits2Float(0xc3a72e05), SkBits2Float(0xc418cab4), SkBits2Float(0x3f3504f3)); // -240.236f, -645.425f, -334.36f, -611.167f, 0.707107f
+path.conicTo(SkBits2Float(0xc3d63dc5), SkBits2Float(0xc4103a31), SkBits2Float(0xc39bc8c8), SkBits2Float(0xc37fb0d7), SkBits2Float(0x3f3504f3)); // -428.483f, -576.909f, -311.569f, -255.691f, 0.707107f
+path.close();
+path.moveTo(SkBits2Float(0xc294a419), SkBits2Float(0xc3c6124c)); // -74.3205f, -396.143f
+path.conicTo(SkBits2Float(0xc33f3c05), SkBits2Float(0xc295d95d), SkBits2Float(0xc2c2390a), SkBits2Float(0xc222aa8c), SkBits2Float(0x3f3504f3)); // -191.234f, -74.9245f, -97.1114f, -40.6665f, 0.707107f
+path.conicTo(SkBits2Float(0xc03f4154), SkBits2Float(0xc0cd12f4), SkBits2Float(0x42e3d9e6), SkBits2Float(0xc3a3d041), SkBits2Float(0x3f3504f3)); // -2.98836f, -6.40856f, 113.926f, -327.627f, 0.707107f
+path.conicTo(SkBits2Float(0x4366d6ec), SkBits2Float(0xc422361b), SkBits2Float(0x4308b76c), SkBits2Float(0xc42ac69e), SkBits2Float(0x3f3504f3)); // 230.84f, -648.845f, 136.716f, -683.103f, 0.707107f
+path.conicTo(SkBits2Float(0x422a5fb0), SkBits2Float(0xc4335721), SkBits2Float(0xc294a419), SkBits2Float(0xc3c6124c), SkBits2Float(0x3f3504f3)); // 42.5934f, -717.361f, -74.3205f, -396.143f, 0.707107f
+path.close();
+path.moveTo(SkBits2Float(0x4345b3f8), SkBits2Float(0xc3af9e21)); // 197.703f, -351.235f
+path.conicTo(SkBits2Float(0xc2c4aac2), SkBits2Float(0xc3345194), SkBits2Float(0xc24101bb), SkBits2Float(0xc2bb2617), SkBits2Float(0x3f3504f3)); // -98.3335f, -180.319f, -48.2517f, -93.5744f, 0.707107f
+path.conicTo(SkBits2Float(0x3fea41a0), SkBits2Float(0xc0da9066), SkBits2Float(0x4394eeee), SkBits2Float(0xc331bf31), SkBits2Float(0x3f3504f3)); // 1.83013f, -6.83013f, 297.867f, -177.747f, 0.707107f
+path.conicTo(SkBits2Float(0x441479cd), SkBits2Float(0xc3ae54f0), SkBits2Float(0x4407f490), SkBits2Float(0xc3d9b434), SkBits2Float(0x3f3504f3)); // 593.903f, -348.664f, 543.821f, -435.408f, 0.707107f
+path.conicTo(SkBits2Float(0x43f6dea8), SkBits2Float(0xc40289bc), SkBits2Float(0x4345b3f8), SkBits2Float(0xc3af9e21), SkBits2Float(0x3f3504f3)); // 493.74f, -522.152f, 197.703f, -351.235f, 0.707107f
+path.close();
+path.moveTo(SkBits2Float(0x43bc9c08), SkBits2Float(0xc30dfb1e)); // 377.219f, -141.981f
+path.conicTo(SkBits2Float(0x422250a2), SkBits2Float(0xc34956f5), SkBits2Float(0x41b97bee), SkBits2Float(0xc2cd653e), SkBits2Float(0x3f3504f3)); // 40.5787f, -201.34f, 23.1855f, -102.698f, 0.707107f
+path.conicTo(SkBits2Float(0x40b95a5b), SkBits2Float(0xc081c919), SkBits2Float(0x43ab375e), SkBits2Float(0x425d363a), SkBits2Float(0x3f3504f3)); // 5.79228f, -4.0558f, 342.433f, 55.303f, 0.707107f
+path.conicTo(SkBits2Float(0x4429c4a9), SkBits2Float(0x42e552cb), SkBits2Float(0x442e1dd4), SkBits2Float(0x4180287c), SkBits2Float(0x3f3504f3)); // 679.073f, 114.662f, 696.466f, 16.0198f, 0.707107f
+path.conicTo(SkBits2Float(0x443276ff), SkBits2Float(0xc2a53e8d), SkBits2Float(0x43bc9c08), SkBits2Float(0xc30dfb1e), SkBits2Float(0x3f3504f3)); // 713.859f, -82.6222f, 377.219f, -141.981f, 0.707107f
+path.close();
+path.moveTo(SkBits2Float(0x43be1d75), SkBits2Float(0x4305b53c)); // 380.23f, 133.708f
+path.conicTo(SkBits2Float(0x432080f6), SkBits2Float(0xc30026d3), SkBits2Float(0x42a78c44), SkBits2Float(0xc27f121c), SkBits2Float(0x3f3504f3)); // 160.504f, -128.152f, 83.774f, -63.7677f, 0.707107f
+path.conicTo(SkBits2Float(0x40e169c3), SkBits2Float(0x3f1dc4b8), SkBits2Float(0x4362c542), SkBits2Float(0x43833cea), SkBits2Float(0x3f3504f3)); // 7.04416f, 0.616283f, 226.771f, 262.476f, 0.707107f
+path.conicTo(SkBits2Float(0x43df3f9c), SkBits2Float(0x44031579), SkBits2Float(0x4402ce83), SkBits2Float(0x43e5f9cc), SkBits2Float(0x3f3504f3)); // 446.497f, 524.336f, 523.227f, 459.952f, 0.707107f
+path.conicTo(SkBits2Float(0x4415fd38), SkBits2Float(0x43c5c8a6), SkBits2Float(0x43be1d75), SkBits2Float(0x4305b53c), SkBits2Float(0x3f3504f3)); // 599.957f, 395.568f, 380.23f, 133.708f, 0.707107f
+path.close();
+path.moveTo(SkBits2Float(0x434d53ca), SkBits2Float(0x44487cfb)); // 205.327f, 801.953f
+path.conicTo(SkBits2Float(0x434d53ca), SkBits2Float(0x43e60f46), SkBits2Float(0x42d253ca), SkBits2Float(0x43e60f46), SkBits2Float(0x3f3504f3)); // 205.327f, 460.119f, 105.164f, 460.119f, 0.707107f
+path.conicTo(SkBits2Float(0x40a00000), SkBits2Float(0x43e60f46), SkBits2Float(0x40a00000), SkBits2Float(0x44487cfb), SkBits2Float(0x3f3504f3)); // 5, 460.119f, 5, 801.953f, 0.707107f
+path.conicTo(SkBits2Float(0x40a00000), SkBits2Float(0x448ef92a), SkBits2Float(0x42d253ca), SkBits2Float(0x448ef92a), SkBits2Float(0x3f3504f3)); // 5, 1143.79f, 105.164f, 1143.79f, 0.707107f
+path.conicTo(SkBits2Float(0x434d53ca), SkBits2Float(0x448ef92a), SkBits2Float(0x434d53ca), SkBits2Float(0x44487cfb), SkBits2Float(0x3f3504f3)); // 205.327f, 1143.79f, 205.327f, 801.953f, 0.707107f
+path.close();
+path.moveTo(SkBits2Float(0xc2834d04), SkBits2Float(0x445532a0)); // -65.6504f, 852.791f
+path.conicTo(SkBits2Float(0x431a136e), SkBits2Float(0x4413bb9c), SkBits2Float(0x429ab133), SkBits2Float(0x4403a309), SkBits2Float(0x3f3504f3)); // 154.076f, 590.931f, 77.3461f, 526.547f, 0.707107f
+path.conicTo(SkBits2Float(0x3f1dc4d0), SkBits2Float(0x43e714ed), SkBits2Float(0xc35b1c2c), SkBits2Float(0x4435017b), SkBits2Float(0x3f3504f3)); // 0.616284f, 462.163f, -219.11f, 724.023f, 0.707107f
+path.conicTo(SkBits2Float(0xc3db6b0e), SkBits2Float(0x4476787f), SkBits2Float(0xc3b50da4), SkBits2Float(0x44834889), SkBits2Float(0x3f3504f3)); // -438.836f, 985.883f, -362.107f, 1050.27f, 0.707107f
+path.conicTo(SkBits2Float(0xc38eb03a), SkBits2Float(0x448b54d2), SkBits2Float(0xc2834d04), SkBits2Float(0x445532a0), SkBits2Float(0x3f3504f3)); // -285.377f, 1114.65f, -65.6504f, 852.791f, 0.707107f
+path.close();
+path.moveTo(SkBits2Float(0xc398f46d), SkBits2Float(0x44336379)); // -305.91f, 717.554f
+path.conicTo(SkBits2Float(0x41f5d870), SkBits2Float(0x44248c83), SkBits2Float(0x41556629), SkBits2Float(0x440be36d), SkBits2Float(0x3f3504f3)); // 30.7307f, 658.195f, 13.3374f, 559.554f, 0.707107f
+path.conicTo(SkBits2Float(0xc081c918), SkBits2Float(0x43e674af), SkBits2Float(0xc3aa5918), SkBits2Float(0x4402114e), SkBits2Float(0x3f3504f3)); // -4.0558f, 460.912f, -340.696f, 520.27f, 0.707107f
+path.conicTo(SkBits2Float(0xc4295587), SkBits2Float(0x4410e844), SkBits2Float(0xc424fc5c), SkBits2Float(0x4429915a), SkBits2Float(0x3f3504f3)); // -677.336f, 579.629f, -659.943f, 678.271f, 0.707107f
+path.conicTo(SkBits2Float(0xc420a331), SkBits2Float(0x44423a6f), SkBits2Float(0xc398f46d), SkBits2Float(0x44336379), SkBits2Float(0x3f3504f3)); // -642.55f, 776.913f, -305.91f, 717.554f, 0.707107f
+path.close();
+path.moveTo(SkBits2Float(0xc3c983e0), SkBits2Float(0x43e5c2b7)); // -403.03f, 459.521f
+path.conicTo(SkBits2Float(0xc2d5fcd2), SkBits2Float(0x441d9c08), SkBits2Float(0xc263a5d9), SkBits2Float(0x4407ec66), SkBits2Float(0x3f3504f3)); // -106.994f, 630.438f, -56.912f, 543.694f, 0.707107f
+path.conicTo(SkBits2Float(0xc0da9066), SkBits2Float(0x43e47988), SkBits2Float(0xc3976eed), SkBits2Float(0x438f042f), SkBits2Float(0x3f3504f3)); // -6.83013f, 456.949f, -302.867f, 286.033f, 0.707107f
+path.conicTo(SkBits2Float(0xc415b9cc), SkBits2Float(0x42e63b5c), SkBits2Float(0xc4223f09), SkBits2Float(0x4349dc36), SkBits2Float(0x3f3504f3)); // -598.903f, 115.116f, -648.985f, 201.86f, 0.707107f
+path.conicTo(SkBits2Float(0xc42ec446), SkBits2Float(0x43904d5e), SkBits2Float(0xc3c983e0), SkBits2Float(0x43e5c2b7), SkBits2Float(0x3f3504f3)); // -699.067f, 288.604f, -403.03f, 459.521f, 0.707107f
+path.close();
+path.moveTo(SkBits2Float(0xc39bc8c8), SkBits2Float(0x43476db5)); // -311.569f, 199.429f
+path.conicTo(SkBits2Float(0xc342a797), SkBits2Float(0x44022968), SkBits2Float(0xc2c9102e), SkBits2Float(0x43f331c9), SkBits2Float(0x3f3504f3)); // -194.655f, 520.647f, -100.532f, 486.389f, 0.707107f
+path.conicTo(SkBits2Float(0xc0cd12f5), SkBits2Float(0x43e210c3), SkBits2Float(0xc2f6a523), SkBits2Float(0x4302e99e), SkBits2Float(0x3f3504f3)); // -6.40856f, 452.131f, -123.323f, 130.913f, 0.707107f
+path.conicTo(SkBits2Float(0xc3703c8a), SkBits2Float(0xc33e4e50), SkBits2Float(0xc3a72e05), SkBits2Float(0xc31c0c44), SkBits2Float(0x3f3504f3)); // -240.236f, -190.306f, -334.36f, -156.048f, 0.707107f
+path.conicTo(SkBits2Float(0xc3d63dc5), SkBits2Float(0xc2f39470), SkBits2Float(0xc39bc8c8), SkBits2Float(0x43476db5), SkBits2Float(0x3f3504f3)); // -428.483f, -121.79f, -311.569f, 199.429f, 0.707107f
+path.close();
+path.moveTo(SkBits2Float(0xc294a419), SkBits2Float(0x426be7d0)); // -74.3205f, 58.9764f
+path.conicTo(SkBits2Float(0xc33f3c05), SkBits2Float(0x43be18ef), SkBits2Float(0xc2c2390a), SkBits2Float(0x43cf39f4), SkBits2Float(0x3f3504f3)); // -191.234f, 380.195f, -97.1114f, 414.453f, 0.707107f
+path.conicTo(SkBits2Float(0xc03f4154), SkBits2Float(0x43e05afa), SkBits2Float(0x42e3d9e6), SkBits2Float(0x42fefc14), SkBits2Float(0x3f3504f3)); // -2.98836f, 448.711f, 113.926f, 127.492f, 0.707107f
+path.conicTo(SkBits2Float(0x4366d6ec), SkBits2Float(0xc341b9e0), SkBits2Float(0x4308b76c), SkBits2Float(0xc363fbec), SkBits2Float(0x3f3504f3)); // 230.84f, -193.726f, 136.716f, -227.984f, 0.707107f
+path.conicTo(SkBits2Float(0x422a5fb0), SkBits2Float(0xc3831efc), SkBits2Float(0xc294a419), SkBits2Float(0x426be7d0), SkBits2Float(0x3f3504f3)); // 42.5934f, -262.242f, -74.3205f, 58.9764f, 0.707107f
+path.close();
+path.moveTo(SkBits2Float(0x4345b3f8), SkBits2Float(0x42cfc494)); // 197.703f, 103.884f
+path.conicTo(SkBits2Float(0xc2c4aac2), SkBits2Float(0x4389667c), SkBits2Float(0xc24101bb), SkBits2Float(0x43b4c5c0), SkBits2Float(0x3f3504f3)); // -98.3335f, 274.801f, -48.2517f, 361.545f, 0.707107f
+path.conicTo(SkBits2Float(0x3fea41a0), SkBits2Float(0x43e02504), SkBits2Float(0x4394eeee), SkBits2Float(0x438aafae), SkBits2Float(0x3f3504f3)); // 1.83013f, 448.289f, 297.867f, 277.372f, 0.707107f
+path.conicTo(SkBits2Float(0x441479cd), SkBits2Float(0x42d4e958), SkBits2Float(0x4407f490), SkBits2Float(0x419db120), SkBits2Float(0x3f3504f3)); // 593.903f, 106.456f, 543.821f, 19.7115f, 0.707107f
+path.conicTo(SkBits2Float(0x43f6dea8), SkBits2Float(0xc28610c8), SkBits2Float(0x4345b3f8), SkBits2Float(0x42cfc494), SkBits2Float(0x3f3504f3)); // 493.74f, -67.0328f, 197.703f, 103.884f, 0.707107f
+path.close();
+path.moveTo(SkBits2Float(0x43bc9c08), SkBits2Float(0x439c91b7)); // 377.219f, 313.138f
+path.conicTo(SkBits2Float(0x422250a2), SkBits2Float(0x437dc797), SkBits2Float(0x41b97bee), SkBits2Float(0x43b035f6), SkBits2Float(0x3f3504f3)); // 40.5787f, 253.78f, 23.1855f, 352.422f, 0.707107f
+path.conicTo(SkBits2Float(0x40b95a5b), SkBits2Float(0x43e18822), SkBits2Float(0x43ab375e), SkBits2Float(0x43ff360d), SkBits2Float(0x3f3504f3)); // 5.79228f, 451.064f, 342.433f, 510.422f, 0.707107f
+path.conicTo(SkBits2Float(0x4429c4a9), SkBits2Float(0x440e71fc), SkBits2Float(0x442e1dd4), SkBits2Float(0x43eb91ce), SkBits2Float(0x3f3504f3)); // 679.073f, 569.781f, 696.466f, 471.139f, 0.707107f
+path.conicTo(SkBits2Float(0x443276ff), SkBits2Float(0x43ba3fa3), SkBits2Float(0x43bc9c08), SkBits2Float(0x439c91b7), SkBits2Float(0x3f3504f3)); // 713.859f, 372.497f, 377.219f, 313.138f, 0.707107f
+path.close();
+path.moveTo(SkBits2Float(0x43be1d75), SkBits2Float(0x441334f2)); // 380.23f, 588.827f
+path.conicTo(SkBits2Float(0x432080f6), SkBits2Float(0x43a37bdc), SkBits2Float(0x42a78c44), SkBits2Float(0x43c3ad02), SkBits2Float(0x3f3504f3)); // 160.504f, 326.968f, 83.774f, 391.352f, 0.707107f
+path.conicTo(SkBits2Float(0x40e169c3), SkBits2Float(0x43e3de28), SkBits2Float(0x4362c542), SkBits2Float(0x44336618), SkBits2Float(0x3f3504f3)); // 7.04416f, 455.736f, 226.771f, 717.595f, 0.707107f
+path.conicTo(SkBits2Float(0x43df3f9c), SkBits2Float(0x4474dd1c), SkBits2Float(0x4402ce83), SkBits2Float(0x4464c489), SkBits2Float(0x3f3504f3)); // 446.497f, 979.455f, 523.227f, 915.071f, 0.707107f
+path.conicTo(SkBits2Float(0x4415fd38), SkBits2Float(0x4454abf6), SkBits2Float(0x43be1d75), SkBits2Float(0x441334f2), SkBits2Float(0x3f3504f3)); // 599.957f, 850.687f, 380.23f, 588.827f, 0.707107f
+path.close();
+path.moveTo(SkBits2Float(0x43bb9978), SkBits2Float(0x43ad6ab0)); // 375.199f, 346.833f
+path.conicTo(SkBits2Float(0x43bb9978), SkBits2Float(0x40a00000), SkBits2Float(0x43898486), SkBits2Float(0x40a00000), SkBits2Float(0x3f3504f3)); // 375.199f, 5, 275.035f, 5, 0.707107f
+path.conicTo(SkBits2Float(0x432edf26), SkBits2Float(0x40a00000), SkBits2Float(0x432edf26), SkBits2Float(0x43ad6ab0), SkBits2Float(0x3f3504f3)); // 174.872f, 5, 174.872f, 346.833f, 0.707107f
+path.conicTo(SkBits2Float(0x432edf26), SkBits2Float(0x442c2ab0), SkBits2Float(0x43898486), SkBits2Float(0x442c2ab0), SkBits2Float(0x3f3504f3)); // 174.872f, 688.667f, 275.035f, 688.667f, 0.707107f
+path.conicTo(SkBits2Float(0x43bb9978), SkBits2Float(0x442c2ab0), SkBits2Float(0x43bb9978), SkBits2Float(0x43ad6ab0), SkBits2Float(0x3f3504f3)); // 375.199f, 688.667f, 375.199f, 346.833f, 0.707107f
+path.close();
+path.moveTo(SkBits2Float(0x42d07148), SkBits2Float(0x43c6d5fb)); // 104.221f, 397.672f
+path.conicTo(SkBits2Float(0x43a1f94a), SkBits2Float(0x4307cfe3), SkBits2Float(0x437737c0), SkBits2Float(0x428edb31), SkBits2Float(0x3f3504f3)); // 323.948f, 135.812f, 247.218f, 71.4281f, 0.707107f
+path.conicTo(SkBits2Float(0x432a7ceb), SkBits2Float(0x40e169c2), SkBits2Float(0xc244f418), SkBits2Float(0x438673b0), SkBits2Float(0x3f3504f3)); // 170.488f, 7.04416f, -49.2384f, 268.904f, 0.707107f
+path.conicTo(SkBits2Float(0xc3867b7b), SkBits2Float(0x4404b0dc), SkBits2Float(0xc3403c22), SkBits2Float(0x4414c96f), SkBits2Float(0x3f3504f3)); // -268.965f, 530.763f, -192.235f, 595.147f, 0.707107f
+path.conicTo(SkBits2Float(0xc2e7029c), SkBits2Float(0x4424e202), SkBits2Float(0x42d07148), SkBits2Float(0x43c6d5fb), SkBits2Float(0x3f3504f3)); // -115.505f, 659.531f, 104.221f, 397.672f, 0.707107f
+path.close();
+path.moveTo(SkBits2Float(0xc30809b4), SkBits2Float(0x438337ac)); // -136.038f, 262.435f
+path.conicTo(SkBits2Float(0x43489a34), SkBits2Float(0x434b137f), SkBits2Float(0x43373589), SkBits2Float(0x42d0de52), SkBits2Float(0x3f3504f3)); // 200.602f, 203.076f, 183.209f, 104.434f, 0.707107f
+path.conicTo(SkBits2Float(0x4325d0dd), SkBits2Float(0x40b95a5c), SkBits2Float(0xc32ad30a), SkBits2Float(0x42824d58), SkBits2Float(0x3f3504f3)); // 165.816f, 5.79228f, -170.824f, 65.1511f, 0.707107f
+path.conicTo(SkBits2Float(0xc3fdbb7b), SkBits2Float(0x42f9050a), SkBits2Float(0xc3f50925), SkBits2Float(0x435f26db), SkBits2Float(0x3f3504f3)); // -507.465f, 124.51f, -490.071f, 223.152f, 0.707107f
+path.conicTo(SkBits2Float(0xc3ec56cf), SkBits2Float(0x43a0e598), SkBits2Float(0xc30809b4), SkBits2Float(0x438337ac), SkBits2Float(0x3f3504f3)); // -472.678f, 321.794f, -136.038f, 262.435f, 0.707107f
+path.close();
+path.moveTo(SkBits2Float(0xc369289a), SkBits2Float(0x408cdc40)); // -233.159f, 4.40189f
+path.conicTo(SkBits2Float(0x427b82f4), SkBits2Float(0x432f5193), SkBits2Float(0x42e1eb60), SkBits2Float(0x42b12617), SkBits2Float(0x3f3504f3)); // 62.8779f, 175.319f, 112.96f, 88.5744f, 0.707107f
+path.conicTo(SkBits2Float(0x43230aa3), SkBits2Float(0x3fea4196), SkBits2Float(0xc304feb4), SkBits2Float(0xc329162e), SkBits2Float(0x3f3504f3)); // 163.042f, 1.83013f, -132.995f, -169.087f, 0.707107f
+path.conicTo(SkBits2Float(0xc3d68405), SkBits2Float(0xc3aa006f), SkBits2Float(0xc3ef8e7f), SkBits2Float(0xc37d4256), SkBits2Float(0x3f3504f3)); // -429.031f, -340.003f, -479.113f, -253.259f, 0.707107f
+path.conicTo(SkBits2Float(0xc4044c7c), SkBits2Float(0xc32683cf), SkBits2Float(0xc369289a), SkBits2Float(0x408cdc40), SkBits2Float(0x3f3504f3)); // -529.195f, -166.515f, -233.159f, 4.40189f, 0.707107f
+path.close();
+path.moveTo(SkBits2Float(0xc30db26a), SkBits2Float(0xc37fb0d7)); // -141.697f, -255.691f
+path.conicTo(SkBits2Float(0xc1c64388), SkBits2Float(0x42830e25), SkBits2Float(0x428aae1e), SkBits2Float(0x41fa2834), SkBits2Float(0x3f3504f3)); // -24.783f, 65.5276f, 69.3401f, 31.2696f, 0.707107f
+path.conicTo(SkBits2Float(0x4323768e), SkBits2Float(0xc03f4152), SkBits2Float(0x423a3252), SkBits2Float(0xc3a21a77), SkBits2Float(0x3f3504f3)); // 163.463f, -2.98836f, 46.5491f, -324.207f, 0.707107f
+path.conicTo(SkBits2Float(0xc28cbac8), SkBits2Float(0xc4215b37), SkBits2Float(0xc3247ce4), SkBits2Float(0xc418cab4), SkBits2Float(0x3f3504f3)); // -70.3648f, -645.425f, -164.488f, -611.167f, 0.707107f
+path.conicTo(SkBits2Float(0xc3814e32), SkBits2Float(0xc4103a31), SkBits2Float(0xc30db26a), SkBits2Float(0xc37fb0d7), SkBits2Float(0x3f3504f3)); // -258.611f, -576.909f, -141.697f, -255.691f, 0.707107f
+path.close();
+path.moveTo(SkBits2Float(0x42bf1a33), SkBits2Float(0xc3c6124c)); // 95.5512f, -396.143f
+path.conicTo(SkBits2Float(0xc1aae6f8), SkBits2Float(0xc295d95d), SkBits2Float(0x42918542), SkBits2Float(0xc222aa8c), SkBits2Float(0x3f3504f3)); // -21.3628f, -74.9245f, 72.7603f, -40.6665f, 0.707107f
+path.conicTo(SkBits2Float(0x4326e221), SkBits2Float(0xc0cd12f4), SkBits2Float(0x438de60c), SkBits2Float(0xc3a3d041), SkBits2Float(0x3f3504f3)); // 166.883f, -6.40856f, 283.797f, -327.627f, 0.707107f
+path.conicTo(SkBits2Float(0x43c85b09), SkBits2Float(0xc422361b), SkBits2Float(0x43994b49), SkBits2Float(0xc42ac69e), SkBits2Float(0x3f3504f3)); // 400.711f, -648.845f, 306.588f, -683.103f, 0.707107f
+path.conicTo(SkBits2Float(0x43547712), SkBits2Float(0xc4335721), SkBits2Float(0x42bf1a33), SkBits2Float(0xc3c6124c), SkBits2Float(0x3f3504f3)); // 212.465f, -717.361f, 95.5512f, -396.143f, 0.707107f
+path.close();
+path.moveTo(SkBits2Float(0x43b7c98f), SkBits2Float(0xc3af9e21)); // 367.575f, -351.235f
+path.conicTo(SkBits2Float(0x428f138a), SkBits2Float(0xc3345194), SkBits2Float(0x42f33d6e), SkBits2Float(0xc2bb2617), SkBits2Float(0x3f3504f3)); // 71.5382f, -180.319f, 121.62f, -93.5744f, 0.707107f
+path.conicTo(SkBits2Float(0x432bb3a9), SkBits2Float(0xc0da9066), SkBits2Float(0x43e9de81), SkBits2Float(0xc331bf31), SkBits2Float(0x3f3504f3)); // 171.702f, -6.83013f, 467.738f, -177.747f, 0.707107f
+path.conicTo(SkBits2Float(0x443ef196), SkBits2Float(0xc3ae54f0), SkBits2Float(0x44326c5a), SkBits2Float(0xc3d9b434), SkBits2Float(0x3f3504f3)); // 763.775f, -348.664f, 713.693f, -435.408f, 0.707107f
+path.conicTo(SkBits2Float(0x4425e71e), SkBits2Float(0xc40289bc), SkBits2Float(0x43b7c98f), SkBits2Float(0xc3af9e21), SkBits2Float(0x3f3504f3)); // 663.611f, -522.152f, 367.575f, -351.235f, 0.707107f
+path.close();
+path.moveTo(SkBits2Float(0x4408c5ce), SkBits2Float(0xc30dfb1e)); // 547.091f, -141.981f
+path.conicTo(SkBits2Float(0x4352734e), SkBits2Float(0xc34956f5), SkBits2Float(0x43410ea4), SkBits2Float(0xc2cd653e), SkBits2Float(0x3f3504f3)); // 210.45f, -201.34f, 193.057f, -102.698f, 0.707107f
+path.conicTo(SkBits2Float(0x432fa9f9), SkBits2Float(0xc081c919), SkBits2Float(0x44001378), SkBits2Float(0x425d363a), SkBits2Float(0x3f3504f3)); // 175.664f, -4.0558f, 512.304f, 55.303f, 0.707107f
+path.conicTo(SkBits2Float(0x44543c72), SkBits2Float(0x42e552cb), SkBits2Float(0x4458959e), SkBits2Float(0x4180287c), SkBits2Float(0x3f3504f3)); // 848.944f, 114.662f, 866.338f, 16.0198f, 0.707107f
+path.conicTo(SkBits2Float(0x445ceec8), SkBits2Float(0xc2a53e8d), SkBits2Float(0x4408c5ce), SkBits2Float(0xc30dfb1e), SkBits2Float(0x3f3504f3)); // 883.731f, -82.6222f, 547.091f, -141.981f, 0.707107f
+path.close();
+path.moveTo(SkBits2Float(0x44098684), SkBits2Float(0x4305b53c)); // 550.102f, 133.708f
+path.conicTo(SkBits2Float(0x43a5300e), SkBits2Float(0xc30026d3), SkBits2Float(0x437da548), SkBits2Float(0xc27f121c), SkBits2Float(0x3f3504f3)); // 330.375f, -128.152f, 253.646f, -63.7677f, 0.707107f
+path.conicTo(SkBits2Float(0x4330ea74), SkBits2Float(0x3f1dc4b8), SkBits2Float(0x43c65234), SkBits2Float(0x43833cea), SkBits2Float(0x3f3504f3)); // 176.916f, 0.616283f, 396.642f, 262.476f, 0.707107f
+path.conicTo(SkBits2Float(0x441a1798), SkBits2Float(0x44031579), SkBits2Float(0x442d464c), SkBits2Float(0x43e5f9cc), SkBits2Float(0x3f3504f3)); // 616.369f, 524.336f, 693.098f, 459.952f, 0.707107f
+path.conicTo(SkBits2Float(0x44407502), SkBits2Float(0x43c5c8a6), SkBits2Float(0x44098684), SkBits2Float(0x4305b53c), SkBits2Float(0x3f3504f3)); // 769.828f, 395.568f, 550.102f, 133.708f, 0.707107f
+path.close();
+path.moveTo(SkBits2Float(0x43bb9978), SkBits2Float(0x44487cfb)); // 375.199f, 801.953f
+path.conicTo(SkBits2Float(0x43bb9978), SkBits2Float(0x43e60f46), SkBits2Float(0x43898486), SkBits2Float(0x43e60f46), SkBits2Float(0x3f3504f3)); // 375.199f, 460.119f, 275.035f, 460.119f, 0.707107f
+path.conicTo(SkBits2Float(0x432edf26), SkBits2Float(0x43e60f46), SkBits2Float(0x432edf26), SkBits2Float(0x44487cfb), SkBits2Float(0x3f3504f3)); // 174.872f, 460.119f, 174.872f, 801.953f, 0.707107f
+path.conicTo(SkBits2Float(0x432edf26), SkBits2Float(0x448ef92a), SkBits2Float(0x43898486), SkBits2Float(0x448ef92a), SkBits2Float(0x3f3504f3)); // 174.872f, 1143.79f, 275.035f, 1143.79f, 0.707107f
+path.conicTo(SkBits2Float(0x43bb9978), SkBits2Float(0x448ef92a), SkBits2Float(0x43bb9978), SkBits2Float(0x44487cfb), SkBits2Float(0x3f3504f3)); // 375.199f, 1143.79f, 375.199f, 801.953f, 0.707107f
+path.close();
+path.moveTo(SkBits2Float(0x42d07148), SkBits2Float(0x445532a0)); // 104.221f, 852.791f
+path.conicTo(SkBits2Float(0x43a1f94a), SkBits2Float(0x4413bb9c), SkBits2Float(0x437737c0), SkBits2Float(0x4403a309), SkBits2Float(0x3f3504f3)); // 323.948f, 590.931f, 247.218f, 526.547f, 0.707107f
+path.conicTo(SkBits2Float(0x432a7ceb), SkBits2Float(0x43e714ed), SkBits2Float(0xc244f418), SkBits2Float(0x4435017b), SkBits2Float(0x3f3504f3)); // 170.488f, 462.163f, -49.2384f, 724.023f, 0.707107f
+path.conicTo(SkBits2Float(0xc3867b7b), SkBits2Float(0x4476787f), SkBits2Float(0xc3403c22), SkBits2Float(0x44834889), SkBits2Float(0x3f3504f3)); // -268.965f, 985.883f, -192.235f, 1050.27f, 0.707107f
+path.conicTo(SkBits2Float(0xc2e7029c), SkBits2Float(0x448b54d2), SkBits2Float(0x42d07148), SkBits2Float(0x445532a0), SkBits2Float(0x3f3504f3)); // -115.505f, 1114.65f, 104.221f, 852.791f, 0.707107f
+path.close();
+path.moveTo(SkBits2Float(0xc30809b4), SkBits2Float(0x44336379)); // -136.038f, 717.554f
+path.conicTo(SkBits2Float(0x43489a34), SkBits2Float(0x44248c83), SkBits2Float(0x43373589), SkBits2Float(0x440be36d), SkBits2Float(0x3f3504f3)); // 200.602f, 658.195f, 183.209f, 559.554f, 0.707107f
+path.conicTo(SkBits2Float(0x4325d0dd), SkBits2Float(0x43e674af), SkBits2Float(0xc32ad30a), SkBits2Float(0x4402114e), SkBits2Float(0x3f3504f3)); // 165.816f, 460.912f, -170.824f, 520.27f, 0.707107f
+path.conicTo(SkBits2Float(0xc3fdbb7b), SkBits2Float(0x4410e844), SkBits2Float(0xc3f50925), SkBits2Float(0x4429915a), SkBits2Float(0x3f3504f3)); // -507.465f, 579.629f, -490.071f, 678.271f, 0.707107f
+path.conicTo(SkBits2Float(0xc3ec56cf), SkBits2Float(0x44423a6f), SkBits2Float(0xc30809b4), SkBits2Float(0x44336379), SkBits2Float(0x3f3504f3)); // -472.678f, 776.913f, -136.038f, 717.554f, 0.707107f
+path.close();
+path.moveTo(SkBits2Float(0xc369289a), SkBits2Float(0x43e5c2b7)); // -233.159f, 459.521f
+path.conicTo(SkBits2Float(0x427b82f4), SkBits2Float(0x441d9c08), SkBits2Float(0x42e1eb60), SkBits2Float(0x4407ec66), SkBits2Float(0x3f3504f3)); // 62.8779f, 630.438f, 112.96f, 543.694f, 0.707107f
+path.conicTo(SkBits2Float(0x43230aa3), SkBits2Float(0x43e47988), SkBits2Float(0xc304feb4), SkBits2Float(0x438f042f), SkBits2Float(0x3f3504f3)); // 163.042f, 456.949f, -132.995f, 286.033f, 0.707107f
+path.conicTo(SkBits2Float(0xc3d68405), SkBits2Float(0x42e63b5c), SkBits2Float(0xc3ef8e7f), SkBits2Float(0x4349dc36), SkBits2Float(0x3f3504f3)); // -429.031f, 115.116f, -479.113f, 201.86f, 0.707107f
+path.conicTo(SkBits2Float(0xc4044c7c), SkBits2Float(0x43904d5e), SkBits2Float(0xc369289a), SkBits2Float(0x43e5c2b7), SkBits2Float(0x3f3504f3)); // -529.195f, 288.604f, -233.159f, 459.521f, 0.707107f
+path.close();
+path.moveTo(SkBits2Float(0xc30db26a), SkBits2Float(0x43476db5)); // -141.697f, 199.429f
+path.conicTo(SkBits2Float(0xc1c64388), SkBits2Float(0x44022968), SkBits2Float(0x428aae1e), SkBits2Float(0x43f331c9), SkBits2Float(0x3f3504f3)); // -24.783f, 520.647f, 69.3401f, 486.389f, 0.707107f
+path.conicTo(SkBits2Float(0x4323768e), SkBits2Float(0x43e210c3), SkBits2Float(0x423a3252), SkBits2Float(0x4302e99e), SkBits2Float(0x3f3504f3)); // 163.463f, 452.131f, 46.5491f, 130.913f, 0.707107f
+path.conicTo(SkBits2Float(0xc28cbac8), SkBits2Float(0xc33e4e50), SkBits2Float(0xc3247ce4), SkBits2Float(0xc31c0c44), SkBits2Float(0x3f3504f3)); // -70.3648f, -190.306f, -164.488f, -156.048f, 0.707107f
+path.conicTo(SkBits2Float(0xc3814e32), SkBits2Float(0xc2f39470), SkBits2Float(0xc30db26a), SkBits2Float(0x43476db5), SkBits2Float(0x3f3504f3)); // -258.611f, -121.79f, -141.697f, 199.429f, 0.707107f
+path.close();
+path.moveTo(SkBits2Float(0x42bf1a33), SkBits2Float(0x426be7d0)); // 95.5512f, 58.9764f
+path.conicTo(SkBits2Float(0xc1aae6f8), SkBits2Float(0x43be18ef), SkBits2Float(0x42918542), SkBits2Float(0x43cf39f4), SkBits2Float(0x3f3504f3)); // -21.3628f, 380.195f, 72.7603f, 414.453f, 0.707107f
+path.conicTo(SkBits2Float(0x4326e221), SkBits2Float(0x43e05afa), SkBits2Float(0x438de60c), SkBits2Float(0x42fefc14), SkBits2Float(0x3f3504f3)); // 166.883f, 448.711f, 283.797f, 127.492f, 0.707107f
+path.conicTo(SkBits2Float(0x43c85b09), SkBits2Float(0xc341b9e0), SkBits2Float(0x43994b49), SkBits2Float(0xc363fbec), SkBits2Float(0x3f3504f3)); // 400.711f, -193.726f, 306.588f, -227.984f, 0.707107f
+path.conicTo(SkBits2Float(0x43547712), SkBits2Float(0xc3831efc), SkBits2Float(0x42bf1a33), SkBits2Float(0x426be7d0), SkBits2Float(0x3f3504f3)); // 212.465f, -262.242f, 95.5512f, 58.9764f, 0.707107f
+path.close();
+path.moveTo(SkBits2Float(0x43b7c98f), SkBits2Float(0x42cfc494)); // 367.575f, 103.884f
+path.conicTo(SkBits2Float(0x428f138a), SkBits2Float(0x4389667c), SkBits2Float(0x42f33d6e), SkBits2Float(0x43b4c5c0), SkBits2Float(0x3f3504f3)); // 71.5382f, 274.801f, 121.62f, 361.545f, 0.707107f
+path.conicTo(SkBits2Float(0x432bb3a9), SkBits2Float(0x43e02504), SkBits2Float(0x43e9de81), SkBits2Float(0x438aafae), SkBits2Float(0x3f3504f3)); // 171.702f, 448.289f, 467.738f, 277.372f, 0.707107f
+path.conicTo(SkBits2Float(0x443ef196), SkBits2Float(0x42d4e958), SkBits2Float(0x44326c5a), SkBits2Float(0x419db120), SkBits2Float(0x3f3504f3)); // 763.775f, 106.456f, 713.693f, 19.7115f, 0.707107f
+path.conicTo(SkBits2Float(0x4425e71e), SkBits2Float(0xc28610c8), SkBits2Float(0x43b7c98f), SkBits2Float(0x42cfc494), SkBits2Float(0x3f3504f3)); // 663.611f, -67.0328f, 367.575f, 103.884f, 0.707107f
+path.close();
+path.moveTo(SkBits2Float(0x4408c5ce), SkBits2Float(0x439c91b7)); // 547.091f, 313.138f
+path.conicTo(SkBits2Float(0x4352734e), SkBits2Float(0x437dc797), SkBits2Float(0x43410ea4), SkBits2Float(0x43b035f6), SkBits2Float(0x3f3504f3)); // 210.45f, 253.78f, 193.057f, 352.422f, 0.707107f
+path.conicTo(SkBits2Float(0x432fa9f9), SkBits2Float(0x43e18822), SkBits2Float(0x44001378), SkBits2Float(0x43ff360d), SkBits2Float(0x3f3504f3)); // 175.664f, 451.064f, 512.304f, 510.422f, 0.707107f
+path.conicTo(SkBits2Float(0x44543c72), SkBits2Float(0x440e71fc), SkBits2Float(0x4458959e), SkBits2Float(0x43eb91ce), SkBits2Float(0x3f3504f3)); // 848.944f, 569.781f, 866.338f, 471.139f, 0.707107f
+path.conicTo(SkBits2Float(0x445ceec8), SkBits2Float(0x43ba3fa3), SkBits2Float(0x4408c5ce), SkBits2Float(0x439c91b7), SkBits2Float(0x3f3504f3)); // 883.731f, 372.497f, 547.091f, 313.138f, 0.707107f
+path.close();
+path.moveTo(SkBits2Float(0x44098684), SkBits2Float(0x441334f2)); // 550.102f, 588.827f
+path.conicTo(SkBits2Float(0x43a5300e), SkBits2Float(0x43a37bdc), SkBits2Float(0x437da548), SkBits2Float(0x43c3ad02), SkBits2Float(0x3f3504f3)); // 330.375f, 326.968f, 253.646f, 391.352f, 0.707107f
+path.conicTo(SkBits2Float(0x4330ea74), SkBits2Float(0x43e3de28), SkBits2Float(0x43c65234), SkBits2Float(0x44336618), SkBits2Float(0x3f3504f3)); // 176.916f, 455.736f, 396.642f, 717.595f, 0.707107f
+path.conicTo(SkBits2Float(0x441a1798), SkBits2Float(0x4474dd1c), SkBits2Float(0x442d464c), SkBits2Float(0x4464c489), SkBits2Float(0x3f3504f3)); // 616.369f, 979.455f, 693.098f, 915.071f, 0.707107f
+path.conicTo(SkBits2Float(0x44407502), SkBits2Float(0x4454abf6), SkBits2Float(0x44098684), SkBits2Float(0x441334f2), SkBits2Float(0x3f3504f3)); // 769.828f, 850.687f, 550.102f, 588.827f, 0.707107f
+path.close();
+SkPath lastFailed = path;
+#if DEBUG_SIMPLIFY_FAILS
+ for (;;) {
+ SkPath failed = subset_simplify_fail(reporter, lastFailed);
+ if (failed == lastFailed) {
+ break;
+ }
+ lastFailed = failed;
+ }
+#endif
+ testSimplify(reporter, lastFailed, __FUNCTION__);
+}
+
+DEF_TEST(SixtyOvals_2_2_9_73_reduced, reporter) {
+ SkPath path;
+path.moveTo(377.219f, -141.981f);
+path.conicTo(40.5787f, -201.34f, 23.1855f, -102.698f, 0.707107f);
+path.lineTo(377.219f, -141.981f);
+path.close();
+path.moveTo(306.588f, -227.984f);
+path.conicTo(212.465f, -262.242f, 95.5512f, 58.9764f, 0.707107f);
+path.lineTo(306.588f, -227.984f);
+path.close();
+testSimplify(reporter, path, __FUNCTION__);
+}
+
+DEF_TEST(SixtyOvalsA, reporter) {
+SkPath path;
+path.setFillType(SkPath::kEvenOdd_FillType);
+path.moveTo(11.1722f, -8.10398f);
+path.conicTo(22.9143f, -10.3787f, 23.7764f, -7.72542f, 1.00863f);
+path.conicTo(24.6671f, -4.98406f, 13.8147f, 0.0166066f, 0.973016f);
+path.conicTo(24.6378f, 5.07425f, 23.7764f, 7.72542f, 1.00888f);
+path.conicTo(22.8777f, 10.4915f, 11.1648f, 8.13034f, 0.960143f);
+path.conicTo(16.9503f, 18.5866f, 14.6946f, 20.2254f, 1.00881f);
+path.conicTo(12.4417f, 21.8623f, 4.29722f, 13.1468f, 1.0092f);
+path.conicTo(2.92708f, 25, 0, 25, 0.955692f);
+path.conicTo(-2.79361f, 25, -4.258f, 13.1048f, 1.00818f);
+path.conicTo(-4.27813f, 13.1264f, -4.29822f, 13.1479f, 1.03158f);
+path.conicTo(-12.44f, 21.8635f, -14.6946f, 20.2254f, 1.00811f);
+path.conicTo(-16.9933f, 18.5554f, -11.1722f, 8.10398f, 0.989875f);
+path.conicTo(-22.9143f, 10.3787f, -23.7764f, 7.72542f, 1.00863f);
+path.conicTo(-24.6671f, 4.98406f, -13.8147f, -0.0166066f, 0.973016f);
+path.conicTo(-24.6378f, -5.07425f, -23.7764f, -7.72542f, 1.00888f);
+path.conicTo(-22.8777f, -10.4915f, -11.1648f, -8.13034f, 0.960143f);
+path.conicTo(-16.9503f, -18.5866f, -14.6946f, -20.2254f, 1.00881f);
+path.conicTo(-12.4417f, -21.8623f, -4.29722f, -13.1468f, 1.0092f);
+path.conicTo(-2.92708f, -25, 0, -25, 0.955692f);
+path.conicTo(2.79361f, -25, 4.258f, -13.1048f, 1.00818f);
+path.conicTo(4.27813f, -13.1264f, 4.29822f, -13.1479f, 1.03158f);
+path.conicTo(12.44f, -21.8635f, 14.6946f, -20.2254f, 1.00811f);
+path.conicTo(16.9933f, -18.5554f, 11.1722f, -8.10398f, 0.989875f);
+path.close();
+SkPath one(path);
+path.reset();
+path.setFillType(SkPath::kWinding_FillType);
+path.moveTo(-1.54509f, -4.75528f);
+path.conicTo(22.2313f, -12.4807f, 23.7764f, -7.72543f, 0.707107f);
+path.conicTo(25.3215f, -2.97014f, 1.54509f, 4.75528f, 0.707107f);
+path.conicTo(-22.2313f, 12.4807f, -23.7764f, 7.72543f, 0.707107f);
+path.conicTo(-25.3215f, 2.97014f, -1.54509f, -4.75528f, 0.707107f);
+path.close();
+SkPath two(path);
+SkPath result;
+Op(one, two, kUnion_SkPathOp, &result);
+}
+
+DEF_TEST(SixtyOvalsAX, reporter) {
+SkPath path;
+path.setFillType(SkPath::kEvenOdd_FillType);
+path.moveTo(SkBits2Float(0x4132c174), SkBits2Float(0xc101a9e5)); // 11.1722f, -8.10398f
+path.conicTo(SkBits2Float(0x41b7508a), SkBits2Float(0xc1260efe), SkBits2Float(0x41be3618), SkBits2Float(0xc0f736ad), SkBits2Float(0x3f811abd)); // 22.9143f, -10.3787f, 23.7764f, -7.72542f, 1.00863f
+path.conicTo(SkBits2Float(0x41c5564b), SkBits2Float(0xc09f7d6d), SkBits2Float(0x415d0934), SkBits2Float(0x3c880a93), SkBits2Float(0x3f79179a)); // 24.6671f, -4.98406f, 13.8147f, 0.0166066f, 0.973016f
+path.conicTo(SkBits2Float(0x41c51a48), SkBits2Float(0x40a2603c), SkBits2Float(0x41be3618), SkBits2Float(0x40f736ac), SkBits2Float(0x3f8122f3)); // 24.6378f, 5.07425f, 23.7764f, 7.72542f, 1.00888f
+path.conicTo(SkBits2Float(0x41b7056f), SkBits2Float(0x4127dd49), SkBits2Float(0x4132a328), SkBits2Float(0x410215e1), SkBits2Float(0x3f75cbec)); // 22.8777f, 10.4915f, 11.1648f, 8.13034f, 0.960143f
+path.conicTo(SkBits2Float(0x41879a3b), SkBits2Float(0x4194b151), SkBits2Float(0x416b1d34), SkBits2Float(0x41a1cdac), SkBits2Float(0x3f8120d4)); // 16.9503f, 18.5866f, 14.6946f, 20.2254f, 1.00881f
+path.conicTo(SkBits2Float(0x41471107), SkBits2Float(0x41aee601), SkBits2Float(0x408982d1), SkBits2Float(0x41525939), SkBits2Float(0x3f812d7f)); // 12.4417f, 21.8623f, 4.29722f, 13.1468f, 1.0092f
+path.conicTo(SkBits2Float(0x403b5543), SkBits2Float(0x41c80000), SkBits2Float(0x00000000), SkBits2Float(0x41c80000), SkBits2Float(0x3f74a837)); // 2.92708f, 25, 0, 25, 0.955692f
+path.conicTo(SkBits2Float(0xc032ca93), SkBits2Float(0x41c80000), SkBits2Float(0xc088418e), SkBits2Float(0x4151ad32), SkBits2Float(0x3f810c2d)); // -2.79361f, 25, -4.258f, 13.1048f, 1.00818f
+path.conicTo(SkBits2Float(0xc088e66c), SkBits2Float(0x4152058a), SkBits2Float(0xc0898afc), SkBits2Float(0x41525d9e), SkBits2Float(0x3f840adb)); // -4.27813f, 13.1264f, -4.29822f, 13.1479f, 1.03158f
+path.conicTo(SkBits2Float(0xc1470a56), SkBits2Float(0x41aee870), SkBits2Float(0xc16b1d36), SkBits2Float(0x41a1cdac), SkBits2Float(0x3f81099f)); // -12.44f, 21.8635f, -14.6946f, 20.2254f, 1.00811f
+path.conicTo(SkBits2Float(0xc187f23a), SkBits2Float(0x41947162), SkBits2Float(0xc132c174), SkBits2Float(0x4101a9e5), SkBits2Float(0x3f7d6873)); // -16.9933f, 18.5554f, -11.1722f, 8.10398f, 0.989875f
+path.conicTo(SkBits2Float(0xc1b7508a), SkBits2Float(0x41260efe), SkBits2Float(0xc1be3618), SkBits2Float(0x40f736ad), SkBits2Float(0x3f811abd)); // -22.9143f, 10.3787f, -23.7764f, 7.72542f, 1.00863f
+path.conicTo(SkBits2Float(0xc1c5564b), SkBits2Float(0x409f7d6d), SkBits2Float(0xc15d0934), SkBits2Float(0xbc880a93), SkBits2Float(0x3f79179a)); // -24.6671f, 4.98406f, -13.8147f, -0.0166066f, 0.973016f
+path.conicTo(SkBits2Float(0xc1c51a48), SkBits2Float(0xc0a2603c), SkBits2Float(0xc1be3618), SkBits2Float(0xc0f736ac), SkBits2Float(0x3f8122f3)); // -24.6378f, -5.07425f, -23.7764f, -7.72542f, 1.00888f
+path.conicTo(SkBits2Float(0xc1b7056f), SkBits2Float(0xc127dd49), SkBits2Float(0xc132a328), SkBits2Float(0xc10215e1), SkBits2Float(0x3f75cbec)); // -22.8777f, -10.4915f, -11.1648f, -8.13034f, 0.960143f
+path.conicTo(SkBits2Float(0xc1879a3b), SkBits2Float(0xc194b151), SkBits2Float(0xc16b1d34), SkBits2Float(0xc1a1cdac), SkBits2Float(0x3f8120d4)); // -16.9503f, -18.5866f, -14.6946f, -20.2254f, 1.00881f
+path.conicTo(SkBits2Float(0xc1471107), SkBits2Float(0xc1aee601), SkBits2Float(0xc08982d1), SkBits2Float(0xc1525939), SkBits2Float(0x3f812d7f)); // -12.4417f, -21.8623f, -4.29722f, -13.1468f, 1.0092f
+path.conicTo(SkBits2Float(0xc03b5543), SkBits2Float(0xc1c80000), SkBits2Float(0x00000000), SkBits2Float(0xc1c80000), SkBits2Float(0x3f74a837)); // -2.92708f, -25, 0, -25, 0.955692f
+path.conicTo(SkBits2Float(0x4032ca93), SkBits2Float(0xc1c80000), SkBits2Float(0x4088418e), SkBits2Float(0xc151ad32), SkBits2Float(0x3f810c2d)); // 2.79361f, -25, 4.258f, -13.1048f, 1.00818f
+path.conicTo(SkBits2Float(0x4088e66c), SkBits2Float(0xc152058a), SkBits2Float(0x40898afc), SkBits2Float(0xc1525d9e), SkBits2Float(0x3f840adb)); // 4.27813f, -13.1264f, 4.29822f, -13.1479f, 1.03158f
+path.conicTo(SkBits2Float(0x41470a56), SkBits2Float(0xc1aee870), SkBits2Float(0x416b1d36), SkBits2Float(0xc1a1cdac), SkBits2Float(0x3f81099f)); // 12.44f, -21.8635f, 14.6946f, -20.2254f, 1.00811f
+path.conicTo(SkBits2Float(0x4187f23a), SkBits2Float(0xc1947162), SkBits2Float(0x4132c174), SkBits2Float(0xc101a9e5), SkBits2Float(0x3f7d6873)); // 16.9933f, -18.5554f, 11.1722f, -8.10398f, 0.989875f
+path.close();
+path.close();
+SkPath one(path);
+path.reset();
+path.setFillType(SkPath::kWinding_FillType);
+path.moveTo(SkBits2Float(0xbfc5c55c), SkBits2Float(0xc0982b46)); // -1.54509f, -4.75528f
+path.conicTo(SkBits2Float(0x41b1d9c2), SkBits2Float(0xc147b0fc), SkBits2Float(0x41be3618), SkBits2Float(0xc0f736b3), SkBits2Float(0x3f3504f3)); // 22.2313f, -12.4807f, 23.7764f, -7.72543f, 0.707107f
+path.conicTo(SkBits2Float(0x41ca926e), SkBits2Float(0xc03e16da), SkBits2Float(0x3fc5c55c), SkBits2Float(0x40982b46), SkBits2Float(0x3f3504f3)); // 25.3215f, -2.97014f, 1.54509f, 4.75528f, 0.707107f
+path.conicTo(SkBits2Float(0xc1b1d9c2), SkBits2Float(0x4147b0fc), SkBits2Float(0xc1be3618), SkBits2Float(0x40f736b3), SkBits2Float(0x3f3504f3)); // -22.2313f, 12.4807f, -23.7764f, 7.72543f, 0.707107f
+path.conicTo(SkBits2Float(0xc1ca926e), SkBits2Float(0x403e16da), SkBits2Float(0xbfc5c55c), SkBits2Float(0xc0982b46), SkBits2Float(0x3f3504f3)); // -25.3215f, 2.97014f, -1.54509f, -4.75528f, 0.707107f
+path.close();
+SkPath two(path);
+SkPath result;
+Op(one, two, kUnion_SkPathOp, &result);
+}
+
+const char ovalsAsQuads[] = "M 146.4187316894531 136.5"
+" Q 146.4187316894531 139.8508911132812 146.4066772460938 143.19775390625"
+" Q 146.3946533203125 146.5446166992188 146.3705749511719 149.8793640136719"
+" Q 146.3465270996094 153.214111328125 146.3104858398438 156.5287170410156"
+" Q 146.2744750976562 159.8433227539062 146.2265930175781 163.1298217773438"
+" Q 146.1786804199219 166.4163208007812 146.1190490722656 169.6668090820312"
+" Q 146.0593872070312 172.9172973632812 145.9881286621094 176.1238708496094"
+" Q 145.9168701171875 179.3304443359375 145.8341674804688 182.4854736328125"
+" Q 145.75146484375 185.6404418945312 145.6575317382812 188.7362670898438"
+" Q 145.5635681152344 191.8320922851562 145.4586181640625 194.8612365722656"
+" Q 145.3536682128906 197.8904113769531 145.2379455566406 200.8456420898438"
+" Q 145.1222229003906 203.8008422851562 144.9960021972656 206.6750183105469"
+" Q 144.8698120117188 209.5491638183594 144.7334289550781 212.3353271484375"
+" Q 144.5970458984375 215.1214599609375 144.4508056640625 217.8129272460938"
+" Q 144.3045654296875 220.50439453125 144.1488342285156 223.0946655273438"
+" Q 143.9931030273438 225.6849365234375 143.8282470703125 228.1677856445312"
+" Q 143.6633911132812 230.650634765625 143.4898071289062 233.0200805664062"
+" Q 143.3162231445312 235.3894958496094 143.1343078613281 237.6398315429688"
+" Q 142.9524230957031 239.89013671875 142.7626647949219 242.0159301757812"
+" Q 142.5729064941406 244.1417236328125 142.375732421875 246.1378173828125"
+" Q 142.1785583496094 248.1339111328125 141.9744262695312 249.99560546875"
+" Q 141.7703247070312 251.8572387695312 141.5597534179688 253.5799255371094"
+" Q 141.3492126464844 255.3026428222656 141.1326904296875 256.8822326660156"
+" Q 140.9161987304688 258.4617919921875 140.6942749023438 259.8945007324219"
+" Q 140.4723510742188 261.3271789550781 140.2455749511719 262.6095275878906"
+" Q 140.0187683105469 263.8918762207031 139.7876281738281 265.020751953125"
+" Q 139.5564880371094 266.1496276855469 139.3215637207031 267.1223449707031"
+" Q 139.086669921875 268.0950622558594 138.8485412597656 268.9092712402344"
+" Q 138.6104125976562 269.7234497070312 138.36962890625 270.3771667480469"
+" Q 138.1288757324219 271.0308837890625 137.8860473632812 271.5225830078125"
+" Q 137.6432189941406 272.0142822265625 137.3988952636719 272.3427124023438"
+" Q 137.1546020507812 272.6711730957031 136.9093933105469 272.8355712890625"
+" Q 136.6642150878906 272.9999694824219 136.4187316894531 273"
+" Q 136.1732482910156 272.9999694824219 135.9280700683594 272.8355712890625"
+" Q 135.682861328125 272.6711730957031 135.4385681152344 272.3427124023438"
+" Q 135.1942443847656 272.0142822265625 134.951416015625 271.5225830078125"
+" Q 134.7085876464844 271.0308837890625 134.4678344726562 270.3771667480469"
+" Q 134.22705078125 269.7234497070312 133.9889221191406 268.9092407226562"
+" Q 133.7507934570312 268.0950622558594 133.5158996582031 267.122314453125"
+" Q 133.2809753417969 266.1495971679688 133.0498352050781 265.020751953125"
+" Q 132.8186950683594 263.8918762207031 132.5918884277344 262.6095275878906"
+" Q 132.3651123046875 261.3271789550781 132.1431884765625 259.8945007324219"
+" Q 131.9212646484375 258.4617919921875 131.7047729492188 256.8822326660156"
+" Q 131.4882507324219 255.3026428222656 131.2777099609375 253.5799560546875"
+" Q 131.067138671875 251.8572387695312 130.863037109375 249.99560546875"
+" Q 130.6589050292969 248.1339111328125 130.4617309570312 246.1378173828125"
+" Q 130.2645568847656 244.1417236328125 130.0747985839844 242.0159301757812"
+" Q 129.8850402832031 239.89013671875 129.7031555175781 237.6398315429688"
+" Q 129.521240234375 235.3894958496094 129.34765625 233.0200805664062"
+" Q 129.174072265625 230.650634765625 129.0092163085938 228.1677856445312"
+" Q 128.8443603515625 225.6849365234375 128.6886291503906 223.0946655273438"
+" Q 128.5328979492188 220.50439453125 128.3866577148438 217.8129272460938"
+" Q 128.2404174804688 215.1214599609375 128.1040344238281 212.3353271484375"
+" Q 127.9676513671875 209.5491333007812 127.8414306640625 206.6749877929688"
+" Q 127.7152404785156 203.8008422851562 127.5995178222656 200.8456420898438"
+" Q 127.4837951660156 197.8904113769531 127.3788452148438 194.8612365722656"
+" Q 127.2738647460938 191.8320922851562 127.179931640625 188.7362670898438"
+" Q 127.0859985351562 185.6404418945312 127.0032958984375 182.4854431152344"
+" Q 126.9205932617188 179.3304443359375 126.8493347167969 176.1238708496094"
+" Q 126.778076171875 172.9172973632812 126.7184143066406 169.6668090820312"
+" Q 126.6587829589844 166.4163208007812 126.6108703613281 163.1298217773438"
+" Q 126.56298828125 159.8433227539062 126.5269775390625 156.5287170410156"
+" Q 126.4909362792969 153.214111328125 126.4668884277344 149.8793640136719"
+" Q 126.4428100585938 146.5446166992188 126.4307861328125 143.19775390625"
+" Q 126.4187316894531 139.8508911132812 126.4187316894531 136.5"
+" Q 126.4187316894531 133.1491088867188 126.4307861328125 129.8022613525391"
+" Q 126.4428100585938 126.4554138183594 126.4668884277344 123.1206665039062"
+" Q 126.4909362792969 119.7859039306641 126.5269775390625 116.4712829589844"
+" Q 126.56298828125 113.1566619873047 126.6108703613281 109.8701629638672"
+" Q 126.6587829589844 106.5836639404297 126.7184143066406 103.3331909179688"
+" Q 126.778076171875 100.0827331542969 126.8493347167969 96.87612915039062"
+" Q 126.9205932617188 93.66952514648438 127.0032958984375 90.5145263671875"
+" Q 127.0859985351562 87.35951232910156 127.179931640625 84.26370239257812"
+" Q 127.2738647460938 81.16787719726562 127.3788452148438 78.13871765136719"
+" Q 127.4837951660156 75.10955810546875 127.5995178222656 72.15434265136719"
+" Q 127.7152404785156 69.19912719726562 127.8414306640625 66.32498168945312"
+" Q 127.9676513671875 63.45082092285156 128.1040344238281 60.66465759277344"
+" Q 128.2404174804688 57.87849426269531 128.3866577148438 55.18704223632812"
+" Q 128.5328979492188 52.49559020996094 128.6886291503906 49.90530395507812"
+" Q 128.8443603515625 47.31504821777344 129.0092163085938 44.83219909667969"
+" Q 129.174072265625 42.349365234375 129.34765625 39.97991943359375"
+" Q 129.521240234375 37.61048889160156 129.7031555175781 35.36016845703125"
+" Q 129.8850402832031 33.10984802246094 130.0747985839844 30.98406982421875"
+" Q 130.2645568847656 28.85829162597656 130.4617309570312 26.86216735839844"
+" Q 130.6589050292969 24.86604309082031 130.863037109375 23.00439453125"
+" Q 131.067138671875 21.14274597167969 131.2777099609375 19.4200439453125"
+" Q 131.4882507324219 17.69734191894531 131.7047729492188 16.11775207519531"
+" Q 131.9212646484375 14.53814697265625 132.1431884765625 13.10545349121094"
+" Q 132.3651123046875 11.67277526855469 132.5918884277344 10.39044189453125"
+" Q 132.8186950683594 9.108108520507812 133.0498352050781 7.979232788085938"
+" Q 133.2809753417969 6.850357055664062 133.5158996582031 5.877639770507812"
+" Q 133.7507934570312 4.904937744140625 133.9889221191406 4.090728759765625"
+" Q 134.22705078125 3.276535034179688 134.4678344726562 2.622810363769531"
+" Q 134.7085876464844 1.969085693359375 134.951416015625 1.477409362792969"
+" Q 135.1942443847656 0.9857254028320312 135.4385681152344 0.65728759765625"
+" Q 135.682861328125 0.3288421630859375 135.9280700683594 0.1644210815429688"
+" Q 136.1732482910156 0 136.4187316894531 0"
+" Q 136.6642150878906 0 136.9093933105469 0.1644210815429688"
+" Q 137.1546020507812 0.3288421630859375 137.3988952636719 0.65728759765625"
+" Q 137.6432189941406 0.9857254028320312 137.8860473632812 1.477409362792969"
+" Q 138.1288757324219 1.969085693359375 138.36962890625 2.622810363769531"
+" Q 138.6104125976562 3.276535034179688 138.8485412597656 4.090728759765625"
+" Q 139.086669921875 4.904937744140625 139.3215637207031 5.877639770507812"
+" Q 139.5564880371094 6.850357055664062 139.7876281738281 7.979232788085938"
+" Q 140.0187683105469 9.108108520507812 140.2455749511719 10.39044189453125"
+" Q 140.4723510742188 11.67277526855469 140.6942749023438 13.10545349121094"
+" Q 140.9161987304688 14.53814697265625 141.1326904296875 16.11775207519531"
+" Q 141.3492126464844 17.69734191894531 141.5597534179688 19.4200439453125"
+" Q 141.7703247070312 21.14274597167969 141.9744262695312 23.00439453125"
+" Q 142.1785583496094 24.86604309082031 142.375732421875 26.86216735839844"
+" Q 142.5729064941406 28.85829162597656 142.7626647949219 30.98406982421875"
+" Q 142.9524230957031 33.10984802246094 143.1343078613281 35.36016845703125"
+" Q 143.3162231445312 37.61048889160156 143.4898071289062 39.97991943359375"
+" Q 143.6633911132812 42.349365234375 143.8282470703125 44.83219909667969"
+" Q 143.9931030273438 47.31504821777344 144.1488342285156 49.90531921386719"
+" Q 144.3045654296875 52.49559020996094 144.4508056640625 55.18704223632812"
+" Q 144.5970458984375 57.87849426269531 144.7334289550781 60.66465759277344"
+" Q 144.8698120117188 63.45082092285156 144.9960021972656 66.32498168945312"
+" Q 145.1222229003906 69.19912719726562 145.2379455566406 72.15434265136719"
+" Q 145.3536682128906 75.10955810546875 145.4586181640625 78.13871765136719"
+" Q 145.5635681152344 81.16787719726562 145.6575317382812 84.26370239257812"
+" Q 145.75146484375 87.35951232910156 145.8341674804688 90.5145263671875"
+" Q 145.9168701171875 93.66952514648438 145.9881286621094 96.87614440917969"
+" Q 146.0593872070312 100.0827331542969 146.1190490722656 103.3332061767578"
+" Q 146.1786804199219 106.5836639404297 146.2265930175781 109.8701629638672"
+" Q 146.2744750976562 113.1566619873047 146.3104858398438 116.4712829589844"
+" Q 146.3465270996094 119.785888671875 146.3705749511719 123.1206665039062"
+" Q 146.3946533203125 126.4554138183594 146.4066772460938 129.8022613525391"
+" Q 146.4187316894531 133.1491088867188 146.4187316894531 136.5 Z";
+
+#include "SkParsePath.h"
+
+DEF_TEST(PathOpsOvalsAsQuads, reporter) {
+ return; // don't execute this for now
+ SkPath path;
+ SkParsePath::FromSVGString(ovalsAsQuads, &path);
+ Simplify(path, &path);
+}
+
+DEF_TEST(PathOps64OvalsAsQuads, reporter) {
+ return; // don't execute this for now
+ SkPath path, result;
+ SkOpBuilder builder;
+ SkParsePath::FromSVGString(ovalsAsQuads, &path);
+ OvalSet set = {{0, 0, 0, 0}, 2, 3, 9, 100, 100};
+ testOvalSet(set, path, &builder, nullptr, &result);
+}
diff --git a/tests/PathOpsConicIntersectionTest.cpp b/tests/PathOpsConicIntersectionTest.cpp
index 1c15255f35..889a41cc9d 100644
--- a/tests/PathOpsConicIntersectionTest.cpp
+++ b/tests/PathOpsConicIntersectionTest.cpp
@@ -17,17 +17,293 @@ manually compute the intersection of a pair of circles and see if the conic inte
*/
static const SkDConic testSet[] = {
+ {{{{306.588013,-227.983994}, {212.464996,-262.242004}, {95.5512009,58.9763985}}}, 0.707107008f},
+ {{{{377.218994,-141.981003}, {40.578701,-201.339996}, {23.1854992,-102.697998}}}, 0.707107008f},
+
+ {{{{5.1114602088928223, 628.77813720703125},
+ {10.834027290344238, 988.964111328125},
+ {163.40835571289062, 988.964111328125}}}, 0.72944212f},
+ {{{{163.40835571289062, 988.964111328125},
+ {5, 988.964111328125},
+ {5, 614.7423095703125}}}, 0.707106769f},
+
+ {{{{11.17222976684570312, -8.103978157043457031},
+ {22.91432571411132812, -10.37866020202636719},
+ {23.7764129638671875, -7.725424289703369141}}}, 1.00862849f},
+ {{{{-1.545085430145263672, -4.755282402038574219},
+ {22.23132705688476562, -12.48070907592773438},
+ {23.7764129638671875, -7.725427150726318359}}}, 0.707106769f},
+
{{{{-4,1}, {-4,5}, {0,5}}}, 0.707106769f},
{{{{-3,4}, {-3,1}, {0,1}}}, 0.707106769f},
{{{{0, 0}, {0, 1}, {1, 1}}}, 0.5f},
{{{{1, 0}, {0, 0}, {0, 1}}}, 0.5f},
+
};
const int testSetCount = (int) SK_ARRAY_COUNT(testSet);
+static void chopCompare(const SkConic chopped[2], const SkDConic dChopped[2]) {
+ SkASSERT(roughly_equal(chopped[0].fW, dChopped[0].fWeight));
+ SkASSERT(roughly_equal(chopped[1].fW, dChopped[1].fWeight));
+ for (int cIndex = 0; cIndex < 2; ++cIndex) {
+ for (int pIndex = 0; pIndex < 3; ++pIndex) {
+ SkDPoint up;
+ up.set(chopped[cIndex].fPts[pIndex]);
+ SkASSERT(dChopped[cIndex].fPts[pIndex].approximatelyEqual(up));
+ }
+ }
+#if DEBUG_VISUALIZE_CONICS
+ dChopped[0].dump();
+ dChopped[1].dump();
+#endif
+}
+
+#include "SkBitmap.h"
+#include "SkCanvas.h"
+#include "SkImageEncoder.h"
+#include "SkPathOpsRect.h"
+#include "SkPaint.h"
+#include "SkString.h"
+
+#define DEBUG_VISUALIZE_CONICS 0
+
+#if DEBUG_VISUALIZE_CONICS
+static void writePng(const SkConic& c, const SkConic ch[2], const char* name) {
+ const int scale = 10;
+ SkConic conic, chopped[2];
+ for (int index = 0; index < 3; ++index) {
+ conic.fPts[index].fX = c.fPts[index].fX * scale;
+ conic.fPts[index].fY = c.fPts[index].fY * scale;
+ for (int chIndex = 0; chIndex < 2; ++chIndex) {
+ chopped[chIndex].fPts[index].fX = ch[chIndex].fPts[index].fX * scale;
+ chopped[chIndex].fPts[index].fY = ch[chIndex].fPts[index].fY * scale;
+ }
+ }
+ conic.fW = c.fW;
+ chopped[0].fW = ch[0].fW;
+ chopped[1].fW = ch[1].fW;
+ SkBitmap bitmap;
+ SkRect bounds;
+ conic.computeTightBounds(&bounds);
+ bounds.outset(10, 10);
+ bitmap.tryAllocPixels(SkImageInfo::MakeN32Premul(
+ SkScalarRoundToInt(bounds.width()), SkScalarRoundToInt(bounds.height())));
+ SkCanvas canvas(bitmap);
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setStyle(SkPaint::kStroke_Style);
+ canvas.translate(-bounds.fLeft, -bounds.fTop);
+ canvas.drawColor(SK_ColorWHITE);
+ SkPath path;
+ path.moveTo(conic.fPts[0]);
+ path.conicTo(conic.fPts[1], conic.fPts[2], conic.fW);
+ paint.setARGB(0x80, 0xFF, 0, 0);
+ canvas.drawPath(path, paint);
+ path.reset();
+ path.moveTo(chopped[0].fPts[0]);
+ path.conicTo(chopped[0].fPts[1], chopped[0].fPts[2], chopped[0].fW);
+ path.moveTo(chopped[1].fPts[0]);
+ path.conicTo(chopped[1].fPts[1], chopped[1].fPts[2], chopped[1].fW);
+ paint.setARGB(0x80, 0, 0, 0xFF);
+ canvas.drawPath(path, paint);
+ SkString filename("c:\\Users\\caryclark\\Documents\\");
+ filename.appendf("%s.png", name);
+ SkImageEncoder::EncodeFile(filename.c_str(), bitmap,
+ SkImageEncoder::kPNG_Type, 100);
+}
+
+static void writeDPng(const SkDConic& dC, const char* name) {
+ const int scale = 5;
+ SkDConic dConic = {{{ {dC.fPts[0].fX * scale, dC.fPts[0].fY * scale },
+ {dC.fPts[1].fX * scale, dC.fPts[1].fY * scale },
+ {dC.fPts[2].fX * scale, dC.fPts[2].fY * scale }}}, dC.fWeight };
+ SkBitmap bitmap;
+ SkDRect bounds;
+ bounds.setBounds(dConic);
+ bounds.fLeft -= 10;
+ bounds.fTop -= 10;
+ bounds.fRight += 10;
+ bounds.fBottom += 10;
+ bitmap.tryAllocPixels(SkImageInfo::MakeN32Premul(
+ SkScalarRoundToInt(SkDoubleToScalar(bounds.width())),
+ SkScalarRoundToInt(SkDoubleToScalar(bounds.height()))));
+ SkCanvas canvas(bitmap);
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setStyle(SkPaint::kStroke_Style);
+ canvas.translate(SkDoubleToScalar(-bounds.fLeft), SkDoubleToScalar(-bounds.fTop));
+ canvas.drawColor(SK_ColorWHITE);
+ SkPath path;
+ path.moveTo(dConic.fPts[0].asSkPoint());
+ path.conicTo(dConic.fPts[1].asSkPoint(), dConic.fPts[2].asSkPoint(), dConic.fWeight);
+ paint.setARGB(0x80, 0xFF, 0, 0);
+ canvas.drawPath(path, paint);
+ path.reset();
+ const int chops = 2;
+ for (int tIndex = 0; tIndex < chops; ++tIndex) {
+ SkDConic chopped = dConic.subDivide(tIndex / (double) chops,
+ (tIndex + 1) / (double) chops);
+ path.moveTo(chopped.fPts[0].asSkPoint());
+ path.conicTo(chopped.fPts[1].asSkPoint(), chopped.fPts[2].asSkPoint(), chopped.fWeight);
+ }
+ paint.setARGB(0x80, 0, 0, 0xFF);
+ canvas.drawPath(path, paint);
+ SkString filename("c:\\Users\\caryclark\\Documents\\");
+ filename.appendf("%s.png", name);
+ SkImageEncoder::EncodeFile(filename.c_str(), bitmap,
+ SkImageEncoder::kPNG_Type, 100);
+}
+#endif
+
+static void chopBothWays(const SkDConic& dConic, double t, const char* name) {
+ SkConic conic;
+ for (int index = 0; index < 3; ++index) {
+ conic.fPts[index] = dConic.fPts[index].asSkPoint();
+ }
+ conic.fW = dConic.fWeight;
+ SkConic chopped[2];
+ SkDConic dChopped[2];
+ conic.chopAt(SkDoubleToScalar(t), chopped);
+ dChopped[0] = dConic.subDivide(0, t);
+ dChopped[1] = dConic.subDivide(t, 1);
+#if DEBUG_VISUALIZE_CONICS
+ dConic.dump();
+#endif
+ chopCompare(chopped, dChopped);
+#if DEBUG_VISUALIZE_CONICS
+ writePng(conic, chopped, name);
+#endif
+}
+
+#if DEBUG_VISUALIZE_CONICS
+const SkDConic frame0[] = {
+{{{{306.588013,-227.983994}, {212.464996,-262.242004}, {95.5512009,58.9763985}}}, 0.707107008f},
+{{{{377.218994,-141.981003}, {40.578701,-201.339996}, {23.1854992,-102.697998}}}, 0.707107008f},
+};
+
+const SkDConic frame1[] = {
+{{{{377.218994,-141.981003}, {40.578701,-201.339996}, {23.1854992,-102.697998}}}, 0.707107008f},
+{{{{306.58801299999999, -227.983994}, {212.46499600000001, -262.24200400000001}, {95.551200899999998, 58.976398500000002}}}, 0.707107008f},
+{{{{377.21899400000001, -141.98100299999999}, {237.77799285476553, -166.56830755921084}, {134.08399674208422, -155.06258330544892}}}, 0.788580656f},
+{{{{134.08399674208422, -155.06258330544892}, {30.390000629402859, -143.55685905168704}, {23.185499199999999, -102.697998}}}, 0.923879623f},
+};
+
+const SkDConic frame2[] = {
+{{{{306.588013,-227.983994}, {212.464996,-262.242004}, {95.5512009,58.9763985}}}, 0.707107008f},
+{{{{377.218994,-141.981003}, {40.578701,-201.339996}, {23.1854992,-102.697998}}}, 0.707107008f},
+{{{{205.78973252799028, -158.12538713371103}, {143.97848953841861, -74.076645245042371}, {95.551200899999998, 58.976398500000002}}}, 0.923879623f},
+{{{{377.21899400000001, -141.98100299999999}, {237.77799285476553, -166.56830755921084}, {134.08399674208422, -155.06258330544892}}}, 0.788580656f},
+};
+
+const SkDConic frame3[] = {
+{{{{306.588013,-227.983994}, {212.464996,-262.242004}, {95.5512009,58.9763985}}}, 0.707107008f},
+{{{{377.218994,-141.981003}, {40.578701,-201.339996}, {23.1854992,-102.697998}}}, 0.707107008f},
+{{{{205.78973252799028, -158.12538713371103}, {143.97848953841861, -74.076645245042371}, {95.551200899999998, 58.976398500000002}}}, 0.923879623f},
+{{{{252.08225670812539, -156.90491625851064}, {185.93099479842493, -160.81544543232982}, {134.08399674208422, -155.06258330544892}}}, 0.835816324f},
+};
+
+const SkDConic frame4[] = {
+{{{{306.588013,-227.983994}, {212.464996,-262.242004}, {95.5512009,58.9763985}}}, 0.707107008f},
+{{{{377.218994,-141.981003}, {40.578701,-201.339996}, {23.1854992,-102.697998}}}, 0.707107008f},
+{{{{205.78973252799028, -158.12538713371103}, {174.88411103320448, -116.10101618937664}, {145.19509369736275, -56.857102571363754}}}, 0.871667147f},
+{{{{252.08225670812539, -156.90491625851064}, {185.93099479842493, -160.81544543232982}, {134.08399674208422, -155.06258330544892}}}, 0.835816324f},
+};
+
+const SkDConic frame5[] = {
+{{{{306.588013,-227.983994}, {212.464996,-262.242004}, {95.5512009,58.9763985}}}, 0.707107008f},
+{{{{377.218994,-141.981003}, {40.578701,-201.339996}, {23.1854992,-102.697998}}}, 0.707107008f},
+{{{{205.78973252799028, -158.12538713371103}, {174.88411103320448, -116.10101618937664}, {145.19509369736275, -56.857102571363754}}}, 0.871667147f},
+{{{{252.08225670812539, -156.90491625851064}, {219.70109133058406, -158.81912754088933}, {190.17095392508796, -158.38373974664466}}}, 0.858306944f},
+};
+
+const SkDConic frame6[] = {
+{{{{306.588013,-227.983994}, {212.464996,-262.242004}, {95.5512009,58.9763985}}}, 0.707107008f},
+{{{{377.218994,-141.981003}, {40.578701,-201.339996}, {23.1854992,-102.697998}}}, 0.707107008f},
+{{{{205.78973252799028, -158.12538713371103}, {190.33692178059735, -137.11320166154385}, {174.87004877564593, -111.2132534799228}}}, 0.858117759f},
+{{{{252.08225670812539, -156.90491625851064}, {219.70109133058406, -158.81912754088933}, {190.17095392508796, -158.38373974664466}}}, 0.858306944f},
+};
+
+const SkDConic* frames[] = {
+ frame0, frame1, frame2, frame3, frame4, frame5, frame6
+};
+
+const int frameSizes[] = { (int) SK_ARRAY_COUNT(frame0), (int) SK_ARRAY_COUNT(frame1),
+ (int) SK_ARRAY_COUNT(frame2), (int) SK_ARRAY_COUNT(frame3),
+ (int) SK_ARRAY_COUNT(frame4), (int) SK_ARRAY_COUNT(frame5),
+ (int) SK_ARRAY_COUNT(frame6),
+};
+
+static void writeFrames() {
+ const int scale = 5;
+
+ for (int index = 0; index < (int) SK_ARRAY_COUNT(frameSizes); ++index) {
+ SkDRect bounds;
+ bool boundsSet = false;
+ int frameSize = frameSizes[index];
+ for (int fIndex = 0; fIndex < frameSize; ++fIndex) {
+ const SkDConic& dC = frames[index][fIndex];
+ SkDConic dConic = {{{ {dC.fPts[0].fX * scale, dC.fPts[0].fY * scale },
+ {dC.fPts[1].fX * scale, dC.fPts[1].fY * scale },
+ {dC.fPts[2].fX * scale, dC.fPts[2].fY * scale }}}, dC.fWeight };
+ SkDRect dBounds;
+ dBounds.setBounds(dConic);
+ if (!boundsSet) {
+ bounds = dBounds;
+ boundsSet = true;
+ } else {
+ bounds.add((SkDPoint&) dBounds.fLeft);
+ bounds.add((SkDPoint&) dBounds.fRight);
+ }
+ }
+ bounds.fLeft -= 10;
+ bounds.fTop -= 10;
+ bounds.fRight += 10;
+ bounds.fBottom += 10;
+ SkBitmap bitmap;
+ bitmap.tryAllocPixels(SkImageInfo::MakeN32Premul(
+ SkScalarRoundToInt(SkDoubleToScalar(bounds.width())),
+ SkScalarRoundToInt(SkDoubleToScalar(bounds.height()))));
+ SkCanvas canvas(bitmap);
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setStyle(SkPaint::kStroke_Style);
+ canvas.translate(SkDoubleToScalar(-bounds.fLeft), SkDoubleToScalar(-bounds.fTop));
+ canvas.drawColor(SK_ColorWHITE);
+ for (int fIndex = 0; fIndex < frameSize; ++fIndex) {
+ const SkDConic& dC = frames[index][fIndex];
+ SkDConic dConic = {{{ {dC.fPts[0].fX * scale, dC.fPts[0].fY * scale },
+ {dC.fPts[1].fX * scale, dC.fPts[1].fY * scale },
+ {dC.fPts[2].fX * scale, dC.fPts[2].fY * scale }}}, dC.fWeight };
+ SkPath path;
+ path.moveTo(dConic.fPts[0].asSkPoint());
+ path.conicTo(dConic.fPts[1].asSkPoint(), dConic.fPts[2].asSkPoint(), dConic.fWeight);
+ if (fIndex < 2) {
+ paint.setARGB(0x80, 0xFF, 0, 0);
+ } else {
+ paint.setARGB(0x80, 0, 0, 0xFF);
+ }
+ canvas.drawPath(path, paint);
+ }
+ SkString filename("c:\\Users\\caryclark\\Documents\\");
+ filename.appendf("f%d.png", index);
+ SkImageEncoder::EncodeFile(filename.c_str(), bitmap, SkImageEncoder::kPNG_Type, 100);
+ }
+}
+#endif
+
static void oneOff(skiatest::Reporter* reporter, const SkDConic& c1, const SkDConic& c2,
bool coin) {
+#if DEBUG_VISUALIZE_CONICS
+ writeFrames();
+#endif
+ chopBothWays(c1, 0.5, "c1");
+ chopBothWays(c2, 0.5, "c2");
+#if DEBUG_VISUALIZE_CONICS
+ writeDPng(c1, "d1");
+ writeDPng(c2, "d2");
+#endif
SkASSERT(ValidConic(c1));
SkASSERT(ValidConic(c2));
SkIntersections intersections;
diff --git a/tests/SubsetPath.cpp b/tests/SubsetPath.cpp
new file mode 100644
index 0000000000..e67df1210b
--- /dev/null
+++ b/tests/SubsetPath.cpp
@@ -0,0 +1,240 @@
+/*
+ * 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 "SubsetPath.h"
+
+SubsetPath::SubsetPath(const SkPath& path)
+ : fPath(path)
+ , fSubset(1) {
+}
+
+int SubsetPath::range(int* end) const {
+ int leadingZero = SkCLZ(fSubset);
+ int parts = 1 << (31 - leadingZero);
+ int partIndex = fSubset - parts;
+ SkASSERT(partIndex >= 0);
+ int count = fSelected.count();
+ int start = count * partIndex / parts;
+ *end = count * (partIndex + 1) / parts;
+ return start;
+}
+
+bool SubsetPath::subset(bool testFailed, SkPath* sub) {
+ int start, end;
+ if (!testFailed) {
+ start = range(&end);
+ for (; start < end; ++start) {
+ fSelected[start] = true;
+ }
+ }
+ do {
+ do {
+ ++fSubset;
+ start = range(&end);
+ // SkDebugf("%d s=%d e=%d t=%d\n", fSubset, start, end, fTries);
+ if (end - start > 1) {
+ fTries = fSelected.count();
+ } else if (end - start == 1) {
+ if (--fTries <= 0) {
+ return false;
+ }
+ }
+ } while (start == end);
+ } while (!fSelected[start]);
+ for (; start < end; ++start) {
+ fSelected[start] = false;
+ }
+#if 1
+ SkDebugf("selected: ");
+ for (int index = 0; index < fSelected.count(); ++index) {
+ SkDebugf("%c", fSelected[index] ? 'x' : '-');
+ }
+#endif
+ *sub = getSubsetPath();
+ return true;
+}
+
+SubsetContours::SubsetContours(const SkPath& path)
+ : SubsetPath(path) {
+ SkPath::RawIter iter(fPath);
+ uint8_t verb;
+ SkPoint pts[4];
+ bool foundCurve = false;
+ int contourCount = 0;
+ while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
+ switch (verb) {
+ case SkPath::kMove_Verb:
+ break;
+ case SkPath::kLine_Verb:
+ case SkPath::kQuad_Verb:
+ case SkPath::kConic_Verb:
+ case SkPath::kCubic_Verb:
+ foundCurve = true;
+ break;
+ case SkPath::kClose_Verb:
+ ++contourCount;
+ foundCurve = false;
+ break;
+ default:
+ SkDEBUGFAIL("bad verb");
+ return;
+ }
+ }
+ contourCount += foundCurve;
+ for (int index = 0; index < contourCount; ++index) {
+ *fSelected.append() = true;
+ }
+ fTries = contourCount;
+}
+
+SkPath SubsetContours::getSubsetPath() const {
+ SkPath result;
+ result.setFillType(fPath.getFillType());
+ if (!fSelected.count()) {
+ return result;
+ }
+ SkPath::RawIter iter(fPath);
+ uint8_t verb;
+ SkPoint pts[4];
+ int contourCount = 0;
+ bool enabled = fSelected[0];
+ bool addMoveTo = true;
+ while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
+ if (enabled && addMoveTo) {
+ result.moveTo(pts[0]);
+ addMoveTo = false;
+ }
+ switch (verb) {
+ case SkPath::kMove_Verb:
+ break;
+ case SkPath::kLine_Verb:
+ if (enabled) {
+ result.lineTo(pts[1]);
+ }
+ break;
+ case SkPath::kQuad_Verb:
+ if (enabled) {
+ result.quadTo(pts[1], pts[2]);
+ }
+ break;
+ case SkPath::kConic_Verb:
+ if (enabled) {
+ result.conicTo(pts[1], pts[2], iter.conicWeight());
+ }
+ break;
+ case SkPath::kCubic_Verb:
+ if (enabled) {
+ result.cubicTo(pts[1], pts[2], pts[3]);
+ }
+ break;
+ case SkPath::kClose_Verb:
+ if (enabled) {
+ result.close();
+ }
+ if (++contourCount >= fSelected.count()) {
+ break;
+ }
+ enabled = fSelected[contourCount];
+ addMoveTo = true;
+ continue;
+ default:
+ SkDEBUGFAIL("bad verb");
+ return result;
+ }
+ }
+ return result;
+}
+
+SubsetVerbs::SubsetVerbs(const SkPath& path)
+ : SubsetPath(path) {
+ SkPath::RawIter iter(fPath);
+ uint8_t verb;
+ SkPoint pts[4];
+ int verbCount = 0;
+ while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
+ switch (verb) {
+ case SkPath::kMove_Verb:
+ break;
+ case SkPath::kLine_Verb:
+ case SkPath::kQuad_Verb:
+ case SkPath::kConic_Verb:
+ case SkPath::kCubic_Verb:
+ ++verbCount;
+ break;
+ case SkPath::kClose_Verb:
+ break;
+ default:
+ SkDEBUGFAIL("bad verb");
+ return;
+ }
+ }
+ for (int index = 0; index < verbCount; ++index) {
+ *fSelected.append() = true;
+ }
+ fTries = verbCount;
+}
+
+SkPath SubsetVerbs::getSubsetPath() const {
+ SkPath result;
+ result.setFillType(fPath.getFillType());
+ if (!fSelected.count()) {
+ return result;
+ }
+ SkPath::RawIter iter(fPath);
+ uint8_t verb;
+ SkPoint pts[4];
+ int verbIndex = 0;
+ bool addMoveTo = true;
+ bool addLineTo = false;
+ while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
+ bool enabled = SkPath::kLine_Verb <= verb && verb <= SkPath::kCubic_Verb
+ ? fSelected[verbIndex++] : false;
+ if (enabled) {
+ if (addMoveTo) {
+ result.moveTo(pts[0]);
+ addMoveTo = false;
+ } else if (addLineTo) {
+ result.lineTo(pts[0]);
+ addLineTo = false;
+ }
+ }
+ switch (verb) {
+ case SkPath::kMove_Verb:
+ break;
+ case SkPath::kLine_Verb:
+ if (enabled) {
+ result.lineTo(pts[1]);
+ }
+ break;
+ case SkPath::kQuad_Verb:
+ if (enabled) {
+ result.quadTo(pts[1], pts[2]);
+ }
+ break;
+ case SkPath::kConic_Verb:
+ if (enabled) {
+ result.conicTo(pts[1], pts[2], iter.conicWeight());
+ }
+ break;
+ case SkPath::kCubic_Verb:
+ if (enabled) {
+ result.cubicTo(pts[1], pts[2], pts[3]);
+ }
+ break;
+ case SkPath::kClose_Verb:
+ result.close();
+ addMoveTo = true;
+ addLineTo = false;
+ continue;
+ default:
+ SkDEBUGFAIL("bad verb");
+ return result;
+ }
+ addLineTo = !enabled;
+ }
+ return result;
+}
diff --git a/tests/SubsetPath.h b/tests/SubsetPath.h
new file mode 100644
index 0000000000..65067d1b0b
--- /dev/null
+++ b/tests/SubsetPath.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef SubsetPath_DEFINED
+#define SubsetPath_DEFINED
+
+#include "SkPath.h"
+#include "SkTDArray.h"
+
+/* Given a path, generate a the desired minimal subset of the original.
+
+ This does a binary divide-and-conquer on the path, first splitting by
+ contours, and then by verbs. The caller passes whether the previous subset
+ behaved the same as the original. If not, the subset() call restores the
+ prior state before returning a new subset.
+
+ If a path fails a local test, this reduces the data to the
+ minimal set that fails using a pattern like:
+
+ bool testFailed = true;
+ SkPath minimal;
+ SubsetContours subsetContours(testPath);
+ while (subsetContours.subset(testFailed, &minimal)) {
+ testFailed = myPathTest(minimal);
+ }
+ testFailed = true;
+ SubsetVerbs subsetVerbs(testPath);
+ while (subsetVerbs.subset(testFailed, &minimal)) {
+ testFailed = myPathTest(minimal);
+ }
+*/
+
+class SubsetPath {
+public:
+ SubsetPath(const SkPath& path);
+ virtual ~SubsetPath() {}
+ bool subset(bool testFailed, SkPath* sub);
+protected:
+ int range(int* end) const;
+ virtual SkPath getSubsetPath() const = 0;
+
+ const SkPath& fPath;
+ SkTDArray<bool> fSelected;
+ int fSubset;
+ int fTries;
+
+};
+
+class SubsetContours : public SubsetPath {
+public:
+ SubsetContours(const SkPath& path);
+protected:
+ SkPath getSubsetPath() const override;
+};
+
+class SubsetVerbs : public SubsetPath {
+public:
+ SubsetVerbs(const SkPath& path);
+protected:
+ SkPath getSubsetPath() const override;
+};
+
+#endif
diff --git a/tools/pathops_sorter.htm b/tools/pathops_sorter.htm
index a86353b5f9..3c24aeb138 100644
--- a/tools/pathops_sorter.htm
+++ b/tools/pathops_sorter.htm
@@ -6,22 +6,51 @@
<title></title>
<div style="height:0">
-<div id="conics">
-{{{78.000016756859424, 4590.0127645689281}, {78, 4590.005859375}}},
-{{{78.000022914349017, 4590.0165822692597}, {78.000005725317905, 4590.0082887743229}}},
-{{{{83, 4595}, {78.008674621582031, 4595}, {78, 4590.005859375}}}, 0.707720578f},
-{{{{84, 4596}, {78, 4596}, {78, 4590}}}, 0.707106769f},
+<div id="sect0">
+{{{{306.588013,-227.983994}, {212.464996,-262.242004}, {95.5512009,58.9763985}}}, 0.707107008f},
+{{{{377.218994,-141.981003}, {40.578701,-201.339996}, {23.1854992,-102.697998}}}, 0.707107008f},
</div>
-<div id="conicLines">
-{{{78.000016756859424, 4590.0127645689281}, {78, 4590.005859375}}},
-{{{78.000022914349017, 4590.0165822692597}, {78.000005725317905, 4590.0082887743229}}},
+<div id="sect1">
+{{{{377.218994,-141.981003}, {40.578701,-201.339996}, {23.1854992,-102.697998}}}, 0.707107008f},
+{{{{306.58801299999999, -227.983994}, {212.46499600000001, -262.24200400000001}, {95.551200899999998, 58.976398500000002}}}, 0.707107008f} id=1
+{{{{377.21899400000001, -141.98100299999999}, {237.77799285476553, -166.56830755921084}, {134.08399674208422, -155.06258330544892}}}, 0.788580656f} id=2
+{{{{134.08399674208422, -155.06258330544892}, {30.390000629402859, -143.55685905168704}, {23.185499199999999, -102.697998}}}, 0.923879623f} id=4
</div>
-<div id="thisopp">
-{{{78.000016756859424, 4590.0127645689281}, {78, 4590.005859375}}},
-{{{{84, 4596}, {78, 4596}, {78, 4590}}}, 0.707106769f},
-{{{78.0000055,4590.00813) (78.0000367,4590.02099
+<div id="sect2">
+{{{{306.588013,-227.983994}, {212.464996,-262.242004}, {95.5512009,58.9763985}}}, 0.707107008f},
+{{{{377.218994,-141.981003}, {40.578701,-201.339996}, {23.1854992,-102.697998}}}, 0.707107008f},
+{{{{205.78973252799028, -158.12538713371103}, {143.97848953841861, -74.076645245042371}, {95.551200899999998, 58.976398500000002}}}, 0.923879623f} id=3
+{{{{377.21899400000001, -141.98100299999999}, {237.77799285476553, -166.56830755921084}, {134.08399674208422, -155.06258330544892}}}, 0.788580656f} id=2
+</div>
+
+<div id="sect3">
+{{{{306.588013,-227.983994}, {212.464996,-262.242004}, {95.5512009,58.9763985}}}, 0.707107008f},
+{{{{377.218994,-141.981003}, {40.578701,-201.339996}, {23.1854992,-102.697998}}}, 0.707107008f},
+{{{{205.78973252799028, -158.12538713371103}, {143.97848953841861, -74.076645245042371}, {95.551200899999998, 58.976398500000002}}}, 0.923879623f} id=3
+{{{{252.08225670812539, -156.90491625851064}, {185.93099479842493, -160.81544543232982}, {134.08399674208422, -155.06258330544892}}}, 0.835816324f} id=6
+</div>
+
+<div id="sect4">
+{{{{306.588013,-227.983994}, {212.464996,-262.242004}, {95.5512009,58.9763985}}}, 0.707107008f},
+{{{{377.218994,-141.981003}, {40.578701,-201.339996}, {23.1854992,-102.697998}}}, 0.707107008f},
+{{{{205.78973252799028, -158.12538713371103}, {174.88411103320448, -116.10101618937664}, {145.19509369736275, -56.857102571363754}}}, 0.871667147f} id=3
+{{{{252.08225670812539, -156.90491625851064}, {185.93099479842493, -160.81544543232982}, {134.08399674208422, -155.06258330544892}}}, 0.835816324f} id=6
+</div>
+
+<div id="sect5">
+{{{{306.588013,-227.983994}, {212.464996,-262.242004}, {95.5512009,58.9763985}}}, 0.707107008f},
+{{{{377.218994,-141.981003}, {40.578701,-201.339996}, {23.1854992,-102.697998}}}, 0.707107008f},
+{{{{205.78973252799028, -158.12538713371103}, {174.88411103320448, -116.10101618937664}, {145.19509369736275, -56.857102571363754}}}, 0.871667147f} id=3
+{{{{252.08225670812539, -156.90491625851064}, {219.70109133058406, -158.81912754088933}, {190.17095392508796, -158.38373974664466}}}, 0.858306944f} id=6
+</div>
+
+<div id="sect6">
+{{{{306.588013,-227.983994}, {212.464996,-262.242004}, {95.5512009,58.9763985}}}, 0.707107008f},
+{{{{377.218994,-141.981003}, {40.578701,-201.339996}, {23.1854992,-102.697998}}}, 0.707107008f},
+{{{{205.78973252799028, -158.12538713371103}, {190.33692178059735, -137.11320166154385}, {174.87004877564593, -111.2132534799228}}}, 0.858117759f} id=3
+{{{{252.08225670812539, -156.90491625851064}, {219.70109133058406, -158.81912754088933}, {190.17095392508796, -158.38373974664466}}}, 0.858306944f} id=6
</div>
</div>
@@ -29,9 +58,13 @@
<script type="text/javascript">
var testDivs = [
-conics,
-conicLines,
-thisopp,
+sect0,
+sect1,
+sect2,
+sect3,
+sect4,
+sect5,
+sect6,
];
var decimal_places = 3;
diff --git a/tools/pathops_visualizer.htm b/tools/pathops_visualizer.htm
index 67552a5085..aa442c9b9f 100644
--- a/tools/pathops_visualizer.htm
+++ b/tools/pathops_visualizer.htm
@@ -4,238 +4,144 @@
Skia UnitTests: --match PathOpsSkp$ --resourcePath resources\ SK_DEBUG
-<div id="skpwww_gorcraft_ru_1">
-seg=1 {{{{1170, 4559}, {1176, 4559}, {1176, 4565}}}, 0.707106769f}
-seg=2 {{{1176, 4565}, {1176, 4590}}}
-seg=3 {{{{1176, 4590}, {1176, 4595}, {1171, 4595}}}, 0.707106769f}
-seg=4 {{{1171, 4595}, {83, 4595}}}
-seg=5 {{{{83, 4595}, {78.0086746f, 4595}, {78, 4590.00586f}}}, 0.707720578f}
-seg=6 {{{78, 4590.00586f}, {78, 4565}}}
-seg=7 {{{{78, 4565}, {78, 4559}, {84, 4559}}}, 0.707106769f}
-seg=8 {{{84, 4559}, {1170, 4559}}}
-op union
-seg=9 {{{78, 4590}, {78, 4565}}}
-seg=10 {{{{78, 4565}, {78, 4559}, {84, 4559}}}, 0.707106769f}
-seg=11 {{{84, 4559}, {158, 4559}}}
-seg=12 {{{158, 4559}, {158, 4596}}}
-seg=13 {{{158, 4596}, {84, 4596}}}
-seg=14 {{{{84, 4596}, {78, 4596}, {78, 4590}}}, 0.707106769f}
-debugShowConicLineIntersection wtTs[0]=1 {{{{1170,4559}, {1176,4559}, {1176,4565}}}, 0.707106769} {{1176,4565}} wnTs[0]=0 {{{1176,4565}, {1176,4590}}}
-debugShowConicLineIntersection wtTs[0]=0 {{{{1170,4559}, {1176,4559}, {1176,4565}}}, 0.707106769} {{1170,4559}} wnTs[0]=1 {{{84,4559}, {1170,4559}}}
-debugShowConicLineIntersection wtTs[0]=0 {{{{1176,4590}, {1176,4595}, {1171,4595}}}, 0.707106769} {{1176,4590}} wnTs[0]=1 {{{1176,4565}, {1176,4590}}}
-debugShowConicLineIntersection wtTs[0]=1 {{{{1176,4590}, {1176,4595}, {1171,4595}}}, 0.707106769} {{1171,4595}} wnTs[0]=0 {{{1171,4595}, {83,4595}}}
-debugShowConicLineIntersection wtTs[0]=0 {{{{83,4595}, {78.0086746,4595}, {78,4590.00586}}}, 0.707720578} {{83,4595}} wnTs[0]=1 {{{1171,4595}, {83,4595}}}
-debugShowConicLineIntersection wtTs[0]=1 {{{{83,4595}, {78.0086746,4595}, {78,4590.00586}}}, 0.707720578} {{78,4590.00586}} wnTs[0]=0 {{{78,4590.00586}, {78,4565}}}
-debugShowConicLineIntersection wtTs[0]=0 {{{{78,4565}, {78,4559}, {84,4559}}}, 0.707106769} {{78,4565}} wnTs[0]=1 {{{78,4590.00586}, {78,4565}}}
-debugShowConicLineIntersection wtTs[0]=1 {{{{78,4565}, {78,4559}, {84,4559}}}, 0.707106769} {{84,4559}} wnTs[0]=0 {{{84,4559}, {1170,4559}}}
-debugShowLineIntersection wtTs[0]=0.972972973 {{{158,4559}, {158,4596}}} {{158,4595}} wnTs[0]=0.931066 {{{1171,4595}, {83,4595}}}
-SkOpSegment::addT insert t=0.931066176 segID=4 spanID=29
-SkOpSegment::addT insert t=0.972972973 segID=12 spanID=30
-debugShowConicLineIntersection no intersect {{{{84,4596}, {78,4596}, {78,4590}}}, 0.707106769} {{{1171,4595}, {83,4595}}}
-debugShowConicLineIntersection no intersect {{{{83,4595}, {78.0086746,4595}, {78,4590.00586}}}, 0.707720578} {{{78,4590}, {78,4565}}}
-debugShowConicIntersection wtTs[0]=0.999339899 {{{{83,4595}, {78.0086746,4595}, {78,4590.00586}}}, 0.707720578} {{78.0000076,4590.01074}} wnTs[0]=0.99876 {{{{84,4596}, {78,4596}, {78,4590}}}, 0.707106769}
-SkOpSegment::addT insert t=0.999339899 segID=5 spanID=31
-SkOpSegment::addT insert t=0.998759893 segID=14 spanID=32
-debugShowLineIntersection wtTs[0]=0 {{{78,4590}, {78,4565}}} {{78,4590}} wtTs[1]=1 {{78,4565}} wnTs[0]=0.00023432 {{{78,4590.00586}, {78,4565}}} wnTs[1]=1
-SkOpSegment::addT insert t=0.000234320081 segID=6 spanID=33
-debugShowConicLineIntersection wtTs[0]=0 {{{{78,4565}, {78,4559}, {84,4559}}}, 0.707106769} {{78,4565}} wnTs[0]=1 {{{78,4590.00586}, {78,4565}}}
-debugShowConicLineIntersection wtTs[0]=1 {{{{84,4596}, {78,4596}, {78,4590}}}, 0.707106769} {{78,4590}} wnTs[0]=0.00023432 {{{78,4590.00586}, {78,4565}}}
-debugShowConicLineIntersection wtTs[0]=0 {{{{78,4565}, {78,4559}, {84,4559}}}, 0.707106769} {{78,4565}} wnTs[0]=1 {{{78,4590}, {78,4565}}}
-debugShowConicIntersection wtTs[0]=0 {{{{78,4565}, {78,4559}, {84,4559}}}, 0.707106769} {{78,4565}} wtTs[1]=1 {{84,4559}} wnTs[0]=0 {{{{78,4565}, {78,4559}, {84,4559}}}, 0.707106769} wnTs[1]=1
-debugShowConicLineIntersection wtTs[0]=1 {{{{78,4565}, {78,4559}, {84,4559}}}, 0.707106769} {{84,4559}} wnTs[0]=0 {{{84,4559}, {158,4559}}}
-debugShowConicLineIntersection wtTs[0]=1 {{{{78,4565}, {78,4559}, {84,4559}}}, 0.707106769} {{84,4559}} wnTs[0]=0 {{{84,4559}, {1170,4559}}}
-debugShowLineIntersection wtTs[0]=0 {{{84,4559}, {158,4559}}} {{84,4559}} wtTs[1]=1 {{158,4559}} wnTs[0]=0 {{{84,4559}, {1170,4559}}} wnTs[1]=0.0681399632
-SkOpSegment::addT insert t=0.0681399632 segID=8 spanID=34
-debugShowLineIntersection wtTs[0]=0 {{{158,4559}, {158,4596}}} {{158,4559}} wnTs[0]=0.06814 {{{84,4559}, {1170,4559}}}
-debugShowConicLineIntersection wtTs[0]=0 {{{{78,4565}, {78,4559}, {84,4559}}}, 0.707106769} {{78,4565}} wnTs[0]=1 {{{78,4590}, {78,4565}}}
-debugShowConicLineIntersection wtTs[0]=1 {{{{84,4596}, {78,4596}, {78,4590}}}, 0.707106769} {{78,4590}} wnTs[0]=0 {{{78,4590}, {78,4565}}}
-debugShowConicLineIntersection wtTs[0]=1 {{{{78,4565}, {78,4559}, {84,4559}}}, 0.707106769} {{84,4559}} wnTs[0]=0 {{{84,4559}, {158,4559}}}
-debugShowLineIntersection wtTs[0]=0 {{{158,4559}, {158,4596}}} {{158,4559}} wnTs[0]=1 {{{84,4559}, {158,4559}}}
-debugShowLineIntersection wtTs[0]=0 {{{158,4596}, {84,4596}}} {{158,4596}} wnTs[0]=1 {{{158,4559}, {158,4596}}}
-debugShowConicLineIntersection wtTs[0]=0 {{{{84,4596}, {78,4596}, {78,4590}}}, 0.707106769} {{84,4596}} wnTs[0]=1 {{{158,4596}, {84,4596}}}
-SkOpSegment::markDone id=8 (84,4559 1170,4559) t=0 [15] (84,4559) tEnd=0.0681399632 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=0 oppValue=0
-SkOpSegment::markDone id=10 (78,4565 78,4559 84,4559) t=0 [19] (78,4565) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=0 oppValue=0
-SkOpSegment::markDone id=6 (78,4590.00586 78,4565) t=0.000234320081 [33] (78,4590) tEnd=1 newWindSum=? newOppSum=? oppSum=? windSum=? windValue=0 oppValue=0
-SkOpSegment::sortAngles [4] tStart=0.931066176 [29]
-SkOpAngle::after [4/1] 31/31 tStart=0.931066176 tEnd=0 < [12/14] 7/7 tStart=0.972972973 tEnd=0 < [4/2] 15/15 tStart=0.931066176 tEnd=1 T 4
-SkOpAngle::afterPart {{{158,4595}, {1171,4595}}} id=4
-SkOpAngle::afterPart {{{158,4595}, {158,4559}}} id=12
-SkOpAngle::afterPart {{{158,4595}, {83,4595}}} id=4
-SkOpAngle::after [4/1] 31/31 tStart=0.931066176 tEnd=0 < [12/15] 23/23 tStart=0.972972973 tEnd=1 < [12/14] 7/7 tStart=0.972972973 tEnd=0 F 4
-SkOpAngle::afterPart {{{158,4595}, {1171,4595}}} id=4
-SkOpAngle::afterPart {{{158,4595}, {158,4596}}} id=12
-SkOpAngle::afterPart {{{158,4595}, {158,4559}}} id=12
-SkOpAngle::after [12/14] 7/7 tStart=0.972972973 tEnd=0 < [12/15] 23/23 tStart=0.972972973 tEnd=1 < [4/2] 15/15 tStart=0.931066176 tEnd=1 F 4
-SkOpAngle::afterPart {{{158,4595}, {158,4559}}} id=12
-SkOpAngle::afterPart {{{158,4595}, {158,4596}}} id=12
-SkOpAngle::afterPart {{{158,4595}, {83,4595}}} id=4
-SkOpAngle::after [4/2] 15/15 tStart=0.931066176 tEnd=1 < [12/15] 23/23 tStart=0.972972973 tEnd=1 < [4/1] 31/31 tStart=0.931066176 tEnd=0 T 4
-SkOpAngle::afterPart {{{158,4595}, {83,4595}}} id=4
-SkOpAngle::afterPart {{{158,4595}, {158,4596}}} id=12
-SkOpAngle::afterPart {{{158,4595}, {1171,4595}}} id=4
-SkOpSegment::sortAngles [5] tStart=0.999339899 [31]
-SkOpAngle::after [5/3] 25/29 tStart=0.999339899 tEnd=0 < [14/16] 25/29 tStart=0.998759893 tEnd=0 < [5/4] 9/9 tStart=0.999339899 tEnd=1 F 12
-SkOpAngle::afterPart {{{{78.0000076,4590.01074}, {78.0133288,4595}, {83,4595}}}, 0.708050251} id=5
-SkOpAngle::afterPart {{{{78.0000076,4590.01074}, {78.0105173,4596}, {84,4596}}}, 0.707726777} id=14
-SkOpAngle::afterPart {{{{78.0000076,4590.01074}, {78.0000041,4590.00819}, {78,4590.00586}}}, 1} id=5
-SkOpAngle::after [5/3] 25/29 tStart=0.999339899 tEnd=0 < [14/17] 9/9 tStart=0.998759893 tEnd=1 < [5/4] 9/9 tStart=0.999339899 tEnd=1 T 11
-SkOpAngle::afterPart {{{{78.0000076,4590.01074}, {78.0133288,4595}, {83,4595}}}, 0.708050251} id=5
-SkOpAngle::afterPart {{{{78.0000076,4590.01074}, {78,4590.00526}, {78,4590}}}, 0.999999642} id=14
-SkOpAngle::afterPart {{{{78.0000076,4590.01074}, {78.0000041,4590.00819}, {78,4590.00586}}}, 1} id=5
-SkOpSegment::sortAngles [6] tStart=0.000234320081 [33]
-SkOpAngle::after [6/5] 23/23 tStart=0.000234320081 tEnd=0 < [9/9] 7/7 tStart=0 tEnd=1 < [14/18] 21/21 tStart=1 tEnd=0.998759893 T 4
-SkOpAngle::afterPart {{{78,4590}, {78,4590.00586}}} id=6
-SkOpAngle::afterPart {{{78,4590}, {78,4565}}} id=9
-SkOpAngle::afterPart {{{{78,4590}, {78,4590.00526}, {78.0000076,4590.01074}}}, 0.999999642} id=14
-SkOpSegment::sortAngles [7] tStart=0 [13]
-SkOpSegment::sortAngles [7] tStart=1 [14]
-SkOpSegment::sortAngles [8] tStart=0.0681399632 [34]
-SkOpAngle::after [8/8] 31/31 tStart=0.0681399632 tEnd=1 < [11/12] 15/15 tStart=1 tEnd=0 < [12/13] 23/23 tStart=0 tEnd=0.972972973 T 4
-SkOpAngle::afterPart {{{158,4559}, {1170,4559}}} id=8
-SkOpAngle::afterPart {{{158,4559}, {84,4559}}} id=11
-SkOpAngle::afterPart {{{158,4559}, {158,4595}}} id=12
-SkOpSegment::sortAngles [9] tStart=0 [17]
-SkOpSegment::sortAngles [9] tStart=1 [18]
-SkOpSegment::sortAngles [11] tStart=0 [21]
-SkOpSegment::sortAngles [11] tStart=1 [22]
-SkOpSegment::sortAngles [12] tStart=0 [23]
-SkOpSegment::sortAngles [12] tStart=0.972972973 [30]
-SkOpSegment::sortAngles [14] tStart=0.998759893 [32]
-SkOpSegment::sortAngles [14] tStart=1 [28]
-SkOpCoincidence::debugShowCoincidence - id=11 t=0 tEnd=1
-SkOpCoincidence::debugShowCoincidence + id=8 t=0 tEnd=0.0681399632
-SkOpCoincidence::debugShowCoincidence - id=7 t=0 tEnd=1
-SkOpCoincidence::debugShowCoincidence + id=10 t=0 tEnd=1
-SkOpCoincidence::debugShowCoincidence - id=9 t=0 tEnd=1
-SkOpCoincidence::debugShowCoincidence + id=6 t=0.000234320081 tEnd=1
-SkOpSegment::debugShowActiveSpans id=1 (1170,4559 1176,4559 1176,4565 0.707106769f) t=0 (1170,4559) tEnd=1 windSum=? windValue=1
-SkOpSegment::debugShowActiveSpans id=2 (1176,4565 1176,4590) t=0 (1176,4565) tEnd=1 windSum=? windValue=1
-SkOpSegment::debugShowActiveSpans id=3 (1176,4590 1176,4595 1171,4595 0.707106769f) t=0 (1176,4590) tEnd=1 windSum=? windValue=1
-SkOpSegment::debugShowActiveSpans id=4 (1171,4595 83,4595) t=0 (1171,4595) tEnd=0.931066176 windSum=? windValue=1
-SkOpSegment::debugShowActiveSpans id=4 (1171,4595 83,4595) t=0.931066176 (158,4595) tEnd=1 windSum=? windValue=1
-SkOpSegment::debugShowActiveSpans id=5 (83,4595 78.0086746,4595 78,4590.00586 0.707720578f) t=0 (83,4595) tEnd=0.999339899 windSum=? windValue=1
-SkOpSegment::debugShowActiveSpans id=5 (83,4595 78.0086746,4595 78,4590.00586 0.707720578f) t=0.999339899 (78.0000076,4590.01074) tEnd=1 windSum=? windValue=1
-SkOpSegment::debugShowActiveSpans id=6 (78,4590.00586 78,4565) t=0 (78,4590.00586) tEnd=0.000234320081 windSum=? windValue=1
-SkOpSegment::debugShowActiveSpans id=7 (78,4565 78,4559 84,4559 0.707106769f) t=0 (78,4565) tEnd=1 windSum=? oppSum=? windValue=1 oppValue=1
-SkOpSegment::debugShowActiveSpans id=8 (84,4559 1170,4559) t=0.0681399632 (158,4559) tEnd=1 windSum=? windValue=1
-SkOpSegment::debugShowActiveSpans id=9 (78,4590 78,4565) t=0 (78,4590) tEnd=1 windSum=? oppSum=? windValue=1 oppValue=1
-SkOpSegment::debugShowActiveSpans id=11 (84,4559 158,4559) t=0 (84,4559) tEnd=1 windSum=? oppSum=? windValue=1 oppValue=1
-SkOpSegment::debugShowActiveSpans id=12 (158,4559 158,4596) t=0 (158,4559) tEnd=0.972972973 windSum=? windValue=1
-SkOpSegment::debugShowActiveSpans id=12 (158,4559 158,4596) t=0.972972973 (158,4595) tEnd=1 windSum=? windValue=1
-SkOpSegment::debugShowActiveSpans id=13 (158,4596 84,4596) t=0 (158,4596) tEnd=1 windSum=? windValue=1
-SkOpSegment::debugShowActiveSpans id=14 (84,4596 78,4596 78,4590 0.707106769f) t=0 (84,4596) tEnd=0.998759893 windSum=? windValue=1
-SkOpSegment::debugShowActiveSpans id=14 (84,4596 78,4596 78,4590 0.707106769f) t=0.998759893 (78.0000076,4590.01074) tEnd=1 windSum=? windValue=1
-SkOpSpan::sortableTop dir=kTop seg=1 t=0.5 pt=(1174.24268,4560.75732)
-SkOpSpan::sortableTop [0] valid=1 operand=0 span=1 ccw=1 seg=1 {{{{1170, 4559}, {1176, 4559}, {1176, 4565}}}, 0.707106769f} t=0.5 pt=(1174.24268,4560.75732) slope=(2.56066015,2.56066015)
-SkOpSegment::markWinding id=1 (1170,4559 1176,4559 1176,4565) t=0 [1] (1170,4559) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
-SkOpSegment::markWinding id=2 (1176,4565 1176,4590) t=0 [3] (1176,4565) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
-SkOpSegment::markWinding id=3 (1176,4590 1176,4595 1171,4595) t=0 [5] (1176,4590) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
-SkOpSegment::markWinding id=4 (1171,4595 83,4595) t=0 [7] (1171,4595) tEnd=0.931066176 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
-SkOpSegment::markWinding id=1 (1170,4559 1176,4559 1176,4565) t=0 [1] (1170,4559) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
-SkOpSegment::markWinding id=8 (84,4559 1170,4559) t=0.0681399632 [34] (158,4559) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
-SkOpSegment::activeOp id=1 t=1 tEnd=0 op=union miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-SkOpSegment::findNextOp simple
-SkOpSegment::markDone id=1 (1170,4559 1176,4559 1176,4565) t=0 [1] (1170,4559) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
-bridgeOp current id=1 from=(1176,4565) to=(1170,4559)
-path.moveTo(1176,4565);
-path.conicTo(1176,4559, 1170,4559, 0.707106769);
-SkOpSegment::markWinding id=11 (84,4559 158,4559) t=0 [21] (84,4559) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=1
-SkOpSegment::markWinding id=7 (78,4565 78,4559 84,4559) t=0 [13] (78,4565) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=1
-SkOpSegment::markWinding id=9 (78,4590 78,4565) t=0 [17] (78,4590) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=1
-SkOpSegment::markAngle last segment=9 span=17 windSum=-1
-SkOpSegment::markWinding id=12 (158,4559 158,4596) t=0 [23] (158,4559) tEnd=0.972972973 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=0
-SkOpSegment::markAngle last segment=12 span=30 windSum=?
-SkOpSegment::findNextOp
-SkOpAngle::dumpOne [8/8] next=11/12 sect=31/31 s=0.0681399632 [34] e=1 [16] sgn=-1 windVal=1 windSum=-1 oppVal=0 oppSum=0
-SkOpAngle::dumpOne [11/12] next=12/13 sect=15/15 s=1 [22] e=0 [21] sgn=1 windVal=1 windSum=-1 oppVal=1 oppSum=-1 operand
-SkOpAngle::dumpOne [12/13] next=8/8 sect=23/23 s=0 [23] e=0.972972973 [30] sgn=-1 windVal=1 windSum=-1 oppVal=0 oppSum=-1 operand
-SkOpSegment::activeOp id=11 t=1 tEnd=0 op=union miFrom=0 miTo=1 suFrom=0 suTo=1 result=1
-SkOpSegment::findNextOp chase.append segment=9 span=17 windSum=-1
-SkOpSegment::activeOp id=12 t=0 tEnd=0.972972973 op=union miFrom=1 miTo=1 suFrom=1 suTo=0 result=0
-SkOpSegment::markDone id=12 (158,4559 158,4596) t=0 [23] (158,4559) tEnd=0.972972973 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=0
-SkOpSegment::findNextOp chase.append segment=12 span=30 windSum=-2147483647
-SkOpSegment::markDone id=8 (84,4559 1170,4559) t=0.0681399632 [34] (158,4559) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
-SkOpSegment::findNextOp from:[8] to:[11] start=6561036 end=6560932
-bridgeOp current id=8 from=(1170,4559) to=(158,4559)
-SkOpSegment::findNextOp simple
-SkOpSegment::markDone id=11 (84,4559 158,4559) t=0 [21] (84,4559) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=1
-bridgeOp current id=11 from=(158,4559) to=(84,4559)
-SkOpSegment::findNextOp simple
-SkOpSegment::markDone id=7 (78,4565 78,4559 84,4559) t=0 [13] (78,4565) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=1
-bridgeOp current id=7 from=(84,4559) to=(78,4565)
-path.lineTo(84,4559);
-path.conicTo(78,4559, 78,4565, 0.707106769);
-SkOpSegment::markWinding id=14 (84,4596 78,4596 78,4590) t=0.998759893 [32] (78.0000076,4590.01074) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
-SkOpSegment::markAngle last segment=14 span=32 windSum=-1
-SkOpSegment::markWinding id=6 (78,4590.00586 78,4565) t=0 [11] (78,4590.00586) tEnd=0.000234320081 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=0
-SkOpSegment::markWinding id=5 (83,4595 78.0086746,4595 78,4590.00586) t=0.999339899 [31] (78.0000076,4590.01074) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=0
-SkOpSegment::markAngle last segment=5 span=31 windSum=-1
-SkOpSegment::findNextOp
-SkOpAngle::dumpOne [9/9] next=14/18 sect=7/7 s=0 [17] e=1 [18] sgn=-1 windVal=1 windSum=-1 oppVal=1 oppSum=-1 operand
-SkOpAngle::dumpOne [14/18] next=6/5 sect=21/21 s=1 [28] e=0.998759893 [32] sgn=1 windVal=1 windSum=-1 oppVal=0 oppSum=0 operand
-SkOpAngle::dumpOne [6/5] next=9/9 sect=23/23 s=0.000234320081 [33] e=0 [11] sgn=1 windVal=1 windSum=-1 oppVal=0 oppSum=-1
-SkOpSegment::activeOp id=14 t=1 tEnd=0.998759893 op=union miFrom=0 miTo=0 suFrom=0 suTo=1 result=1
-SkOpSegment::findNextOp chase.append segment=14 span=32 windSum=-1
-SkOpSegment::activeOp id=6 t=0.000234320081 tEnd=0 op=union miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-SkOpSegment::markDone id=6 (78,4590.00586 78,4565) t=0 [11] (78,4590.00586) tEnd=0.000234320081 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=0
-SkOpSegment::markDone id=5 (83,4595 78.0086746,4595 78,4590.00586) t=0.999339899 [31] (78.0000076,4590.01074) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=0
-SkOpSegment::findNextOp chase.append segment=5 span=31 windSum=-1
-SkOpSegment::markDone id=9 (78,4590 78,4565) t=0 [17] (78,4590) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=1
-SkOpSegment::findNextOp from:[9] to:[14] start=6561756 end=6562204
-bridgeOp current id=9 from=(78,4565) to=(78,4590)
-SkOpSegment::markWinding id=14 (84,4596 78,4596 78,4590) t=0 [27] (84,4596) tEnd=0.998759893 newWindSum=-2 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
-SkOpSegment::markWinding id=13 (158,4596 84,4596) t=0 [25] (158,4596) tEnd=1 newWindSum=-2 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
-SkOpSegment::markWinding id=12 (158,4559 158,4596) t=0.972972973 [30] (158,4595) tEnd=1 newWindSum=-2 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
-SkOpSegment::markAngle last segment=12 span=30 windSum=-2
-SkOpSegment::markWinding id=5 (83,4595 78.0086746,4595 78,4590.00586) t=0 [9] (83,4595) tEnd=0.999339899 newWindSum=-1 newOppSum=-2 oppSum=? windSum=? windValue=1 oppValue=0
-SkOpSegment::markWinding id=4 (1171,4595 83,4595) t=0.931066176 [29] (158,4595) tEnd=1 newWindSum=-1 newOppSum=-2 oppSum=? windSum=? windValue=1 oppValue=0
-SkOpSegment::markAngle last segment=4 span=29 windSum=-1
-SkOpSegment::findNextOp
-SkOpAngle::dumpOne [14/17] next=5/4 sect=9/9 s=0.998759893 [32] e=1 [28] sgn=-1 windVal=1 windSum=-1 oppVal=0 oppSum=0 operand
-SkOpAngle::dumpOne [5/4] next=14/16 sect=9/9 s=0.999339899 [31] e=1 [10] sgn=-1 windVal=1 windSum=-1 oppVal=0 oppSum=-1 done
-SkOpAngle::dumpOne [14/16] next=5/3 sect=25/29 s=0.998759893 [32] e=0 [27] sgn=1 windVal=1 windSum=-2 oppVal=0 oppSum=0 operand
-SkOpAngle::dumpOne [5/3] next=14/17 sect=25/29 s=0.999339899 [31] e=0 [9] sgn=1 windVal=1 windSum=-1 oppVal=0 oppSum=-2
-SkOpSegment::activeOp id=5 t=0.999339899 tEnd=1 op=union miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-SkOpSegment::activeOp id=14 t=0.998759893 tEnd=0 op=union miFrom=1 miTo=1 suFrom=0 suTo=1 result=0
-SkOpSegment::markDone id=14 (84,4596 78,4596 78,4590) t=0 [27] (84,4596) tEnd=0.998759893 newWindSum=-2 newOppSum=0 oppSum=0 windSum=-2 windValue=1 oppValue=0
-SkOpSegment::markDone id=13 (158,4596 84,4596) t=0 [25] (158,4596) tEnd=1 newWindSum=-2 newOppSum=0 oppSum=0 windSum=-2 windValue=1 oppValue=0
-SkOpSegment::markDone id=12 (158,4559 158,4596) t=0.972972973 [30] (158,4595) tEnd=1 newWindSum=-2 newOppSum=0 oppSum=0 windSum=-2 windValue=1 oppValue=0
-SkOpSegment::activeOp id=5 t=0.999339899 tEnd=0 op=union miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
-SkOpSegment::markDone id=5 (83,4595 78.0086746,4595 78,4590.00586) t=0 [9] (83,4595) tEnd=0.999339899 newWindSum=-1 newOppSum=-2 oppSum=-2 windSum=-1 windValue=1 oppValue=0
-SkOpSegment::markDone id=4 (1171,4595 83,4595) t=0.931066176 [29] (158,4595) tEnd=1 newWindSum=-1 newOppSum=-2 oppSum=-2 windSum=-1 windValue=1 oppValue=0
-SkOpSegment::findNextOp chase.append segment=4 span=29 windSum=-1
-SkOpSegment::markDone id=14 (84,4596 78,4596 78,4590) t=0.998759893 [32] (78.0000076,4590.01074) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
-SkOpSegment::findNextOp from:[14] to:[5] start=6562100 end=6559532
-bridgeOp current id=14 from=(78,4590) to=(78.0000076,4590.01074)
-path.lineTo(78,4590);
-path.conicTo(78,4590.00537, 78.0000076,4590.01074, 0.999999642);
-SkOpSegment::debugShowActiveSpans id=2 (1176,4565 1176,4590) t=0 (1176,4565) tEnd=1 windSum=-1 oppSum=0 windValue=1 oppValue=0
-SkOpSegment::debugShowActiveSpans id=3 (1176,4590 1176,4595 1171,4595 0.707106769f) t=0 (1176,4590) tEnd=1 windSum=-1 oppSum=0 windValue=1 oppValue=0
-SkOpSegment::debugShowActiveSpans id=4 (1171,4595 83,4595) t=0 (1171,4595) tEnd=0.931066176 windSum=-1 oppSum=0 windValue=1 oppValue=0
-SkOpSegment::activeOp id=4 t=0.931066176 tEnd=0 op=union miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-SkOpSegment::findNextOp simple
-SkOpSegment::markDone id=4 (1171,4595 83,4595) t=0 [7] (1171,4595) tEnd=0.931066176 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
-bridgeOp current id=4 from=(158,4595) to=(1171,4595)
-SkOpSegment::findNextOp simple
-SkOpSegment::markDone id=3 (1176,4590 1176,4595 1171,4595) t=0 [5] (1176,4590) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
-bridgeOp current id=3 from=(1171,4595) to=(1176,4590)
-path.moveTo(158,4595);
-path.lineTo(1171,4595);
-path.conicTo(1176,4595, 1176,4590, 0.707106769);
-SkOpSegment::findNextOp simple
-SkOpSegment::markDone id=2 (1176,4565 1176,4590) t=0 [3] (1176,4565) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0
-bridgeOp current id=2 from=(1176,4590) to=(1176,4565)
-path.lineTo(1176,4565);
+<div id="reduced">
+seg=1 {{{{377.218994f, -141.981003f}, {40.578701f, -201.339996f}, {23.1854992f, -102.697998f}}}, 0.707107008f}
+seg=2 {{{23.1854992f, -102.697998f}, {377.218994f, -141.981003f}}}
+seg=3 {{{{306.588013f, -227.983994f}, {212.464996f, -262.242004f}, {95.5512009f, 58.9763985f}}}, 0.707107008f}
+seg=4 {{{95.5512009f, 58.9763985f}, {306.588013f, -227.983994f}}}
+debugShowConicLineIntersection wtTs[0]=0 {{{{306.588013,-227.983994}, {212.464996,-262.242004}, {95.5512009,58.9763985}}}, 0.707107008} {{306.588013,-227.983994}} wtTs[1]=1 {{95.5512009,58.9763985}} wnTs[0]=1 {{{95.5512009,58.9763985}, {306.588013,-227.983994}}} wnTs[1]=0
+debugShowConicIntersection no intersect {{{{306.588013,-227.983994}, {212.464996,-262.242004}, {95.5512009,58.9763985}}}, 0.707107008} {{{{377.218994,-141.981003}, {40.578701,-201.339996}, {23.1854992,-102.697998}}}, 0.707107008}
+debugShowConicLineIntersection wtTs[0]=0.602960898 {{{{306.588013,-227.983994}, {212.464996,-262.242004}, {95.5512009,58.9763985}}}, 0.707107008} {{180.284241,-120.129433}} wnTs[0]=0.44374 {{{23.1854992,-102.697998}, {377.218994,-141.981003}}}
+addT insert t=0.602960898 segID=3 spanID=9
+addT insert t=0.443739761 segID=2 spanID=10
+debugShowConicLineIntersection wtTs[0]=0.245788566 {{{{377.218994,-141.981003}, {40.578701,-201.339996}, {23.1854992,-102.697998}}}, 0.707107008} {{254.22023,-156.776138}} wnTs[0]=0.751855 {{{95.5512009,58.9763985}, {306.588013,-227.983994}}}
+addT insert t=0.751854746 segID=4 spanID=11
+addT insert t=0.245788566 segID=1 spanID=12
+debugShowLineIntersection wtTs[0]=0.64393017 {{{95.5512009,58.9763985}, {306.588013,-227.983994}}} {{231.444168,-125.806053}} wnTs[0]=0.588246 {{{23.1854992,-102.697998}, {377.218994,-141.981003}}}
+addT insert t=0.64393017 segID=4 spanID=13
+addT insert t=0.588245674 segID=2 spanID=14
+debugShowConicLineIntersection wtTs[0]=0 {{{{377.218994,-141.981003}, {40.578701,-201.339996}, {23.1854992,-102.697998}}}, 0.707107008} {{377.218994,-141.981003}} wtTs[1]=1 {{23.1854992,-102.697998}} wnTs[0]=1 {{{23.1854992,-102.697998}, {377.218994,-141.981003}}} wnTs[1]=0
+sortAngles [3] tStart=0.602960898 [9]
+after [3/1] 5/1 tStart=0.602960898 tEnd=0 < [2/9] 17/17 tStart=0.443739761 tEnd=0 < [3/2] 21/21 tStart=0.602960898 tEnd=1 T 4
+afterPart {{{{180.284241,-120.129433}, {257.850781,-245.722913}, {306.588013,-227.983994}}}, 1.02163982} id=3
+afterPart {{{180.284241,-120.129433}, {23.1854992,-102.697998}}} id=2
+afterPart {{{{180.284241,-120.129433}, {132.69398,-43.0726727}, {95.5512009,58.9763985}}}, 0.497736931} id=3
+after [3/1] 5/1 tStart=0.602960898 tEnd=0 < [2/10] 1/1 tStart=0.443739761 tEnd=0.588245674 < [2/9] 17/17 tStart=0.443739761 tEnd=0 F 12
+afterPart {{{{180.284241,-120.129433}, {257.850781,-245.722913}, {306.588013,-227.983994}}}, 1.02163982} id=3
+afterPart {{{180.284241,-120.129433}, {231.444168,-125.806053}}} id=2
+afterPart {{{180.284241,-120.129433}, {23.1854992,-102.697998}}} id=2
+after [2/9] 17/17 tStart=0.443739761 tEnd=0 < [2/10] 1/1 tStart=0.443739761 tEnd=0.588245674 < [3/2] 21/21 tStart=0.602960898 tEnd=1 F 4
+afterPart {{{180.284241,-120.129433}, {23.1854992,-102.697998}}} id=2
+afterPart {{{180.284241,-120.129433}, {231.444168,-125.806053}}} id=2
+afterPart {{{{180.284241,-120.129433}, {132.69398,-43.0726727}, {95.5512009,58.9763985}}}, 0.497736931} id=3
+after [3/2] 21/21 tStart=0.602960898 tEnd=1 < [2/10] 1/1 tStart=0.443739761 tEnd=0.588245674 < [3/1] 5/1 tStart=0.602960898 tEnd=0 T 11
+afterPart {{{{180.284241,-120.129433}, {132.69398,-43.0726727}, {95.5512009,58.9763985}}}, 0.497736931} id=3
+afterPart {{{180.284241,-120.129433}, {231.444168,-125.806053}}} id=2
+afterPart {{{{180.284241,-120.129433}, {257.850781,-245.722913}, {306.588013,-227.983994}}}, 1.02163982} id=3
+sortAngles [4] tStart=0.64393017 [13]
+after [4/3] 21/21 tStart=0.64393017 tEnd=0 < [2/11] 17/17 tStart=0.588245674 tEnd=0.443739761 < [4/4] 5/5 tStart=0.64393017 tEnd=0.751854746 F 4
+afterPart {{{231.444168,-125.806053}, {95.5512009,58.9763985}}} id=4
+afterPart {{{231.444168,-125.806053}, {180.284241,-120.129433}}} id=2
+afterPart {{{231.444168,-125.806053}, {254.22023,-156.776138}}} id=4
+after [4/3] 21/21 tStart=0.64393017 tEnd=0 < [2/12] 1/1 tStart=0.588245674 tEnd=1 < [4/4] 5/5 tStart=0.64393017 tEnd=0.751854746 T 4
+afterPart {{{231.444168,-125.806053}, {95.5512009,58.9763985}}} id=4
+afterPart {{{231.444168,-125.806053}, {377.218994,-141.981003}}} id=2
+afterPart {{{231.444168,-125.806053}, {254.22023,-156.776138}}} id=4
+sortAngles [4] tStart=0.751854746 [11]
+after [4/5] 21/21 tStart=0.751854746 tEnd=0.64393017 < [1/7] 29/29 tStart=0.245788566 tEnd=0 < [4/6] 5/5 tStart=0.751854746 tEnd=1 T 4
+afterPart {{{254.22023,-156.776138}, {231.444168,-125.806053}}} id=4
+afterPart {{{{254.22023,-156.776138}, {314.172616,-153.097823}, {377.218994,-141.981003}}}, 0.580018938} id=1
+afterPart {{{254.22023,-156.776138}, {306.588013,-227.983994}}} id=4
+after [4/5] 21/21 tStart=0.751854746 tEnd=0.64393017 < [1/8] 13/17 tStart=0.245788566 tEnd=1 < [1/7] 29/29 tStart=0.245788566 tEnd=0 F 4
+afterPart {{{254.22023,-156.776138}, {231.444168,-125.806053}}} id=4
+afterPart {{{{254.22023,-156.776138}, {35.0915133,-170.22053}, {23.1854992,-102.697998}}}, 0.920844734} id=1
+afterPart {{{{254.22023,-156.776138}, {314.172616,-153.097823}, {377.218994,-141.981003}}}, 0.580018938} id=1
+after [1/7] 29/29 tStart=0.245788566 tEnd=0 < [1/8] 13/17 tStart=0.245788566 tEnd=1 < [4/6] 5/5 tStart=0.751854746 tEnd=1 F 4
+afterPart {{{{254.22023,-156.776138}, {314.172616,-153.097823}, {377.218994,-141.981003}}}, 0.580018938} id=1
+afterPart {{{{254.22023,-156.776138}, {35.0915133,-170.22053}, {23.1854992,-102.697998}}}, 0.920844734} id=1
+afterPart {{{254.22023,-156.776138}, {306.588013,-227.983994}}} id=4
+after [4/6] 5/5 tStart=0.751854746 tEnd=1 < [1/8] 13/17 tStart=0.245788566 tEnd=1 < [4/5] 21/21 tStart=0.751854746 tEnd=0.64393017 T 4
+afterPart {{{254.22023,-156.776138}, {306.588013,-227.983994}}} id=4
+afterPart {{{{254.22023,-156.776138}, {35.0915133,-170.22053}, {23.1854992,-102.697998}}}, 0.920844734} id=1
+afterPart {{{254.22023,-156.776138}, {231.444168,-125.806053}}} id=4
+sortAngles [1] tStart=0.245788566 [12]
+sortAngles [2] tStart=0.443739761 [10]
+sortAngles [2] tStart=0.588245674 [14]
+sortableTop dir=kTop seg=3 t=0.301480449 pt=(252.731339,-209.870193)
+sortableTop [0] valid=1 operand=0 span=5 ccw=0 seg=3 {{{{306.588013f, -227.983994f}, {212.464996f, -262.242004f}, {95.5512009f, 58.9763985f}}}, 0.707107008f} t=0.301480449 pt=(252.731339,-209.870193) slope=(-84.4303791,69.255817)
+markWinding id=3 (306.588013,-227.983994 212.464996,-262.242004 95.5512009,58.9763985) t=0 [5] (306.588013,-227.983994) tEnd=0.602960898 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
+markWinding id=3 (306.588013,-227.983994 212.464996,-262.242004 95.5512009,58.9763985) t=0 [5] (306.588013,-227.983994) tEnd=0.602960898 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
+markWinding id=4 (95.5512009,58.9763985 306.588013,-227.983994) t=0.751854746 [11] (254.22023,-156.776138) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0
+findNextWinding simple
+markDone id=3 (306.588013,-227.983994 212.464996,-262.242004 95.5512009,58.9763985) t=0 [5] (306.588013,-227.983994) tEnd=0.602960898 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
+bridgeWinding current id=3 from=(180.284241,-120.129433) to=(306.588013,-227.983994)
+path.moveTo(180.284241,-120.129433);
+path.conicTo(257.850769,-245.722916, 306.588013,-227.983994, 1.02163982);
+markWinding id=1 (377.218994,-141.981003 40.578701,-201.339996 23.1854992,-102.697998) t=0.245788566 [12] (254.22023,-156.776138) tEnd=1 newWindSum=2 windSum=? windValue=1
+markWinding id=2 (23.1854992,-102.697998 377.218994,-141.981003) t=0 [3] (23.1854992,-102.697998) tEnd=0.443739761 newWindSum=2 windSum=? windValue=1
+markAngle last seg=2 span=10 windSum=?
+markWinding id=4 (95.5512009,58.9763985 306.588013,-227.983994) t=0.64393017 [13] (231.444168,-125.806053) tEnd=0.751854746 newWindSum=2 windSum=? windValue=1
+markAngle last seg=4 span=13 windSum=2
+markWinding id=1 (377.218994,-141.981003 40.578701,-201.339996 23.1854992,-102.697998) t=0 [1] (377.218994,-141.981003) tEnd=0.245788566 newWindSum=1 windSum=? windValue=1
+markWinding id=2 (23.1854992,-102.697998 377.218994,-141.981003) t=0.588245674 [14] (231.444168,-125.806053) tEnd=1 newWindSum=1 windSum=? windValue=1
+markAngle last seg=2 span=14 windSum=1
+findNextWinding
+dumpOne [4/6] next=1/8 sect=5/5 s=0.751854746 [11] e=1 [8] sgn=-1 windVal=1 windSum=1 oppVal=0 oppSum=0
+dumpOne [1/8] next=4/5 sect=13/17 s=0.245788566 [12] e=1 [2] sgn=-1 windVal=1 windSum=2
+dumpOne [4/5] next=1/7 sect=21/21 s=0.751854746 [11] e=0.64393017 [13] sgn=1 windVal=1 windSum=2
+dumpOne [1/7] next=4/6 sect=29/29 s=0.245788566 [12] e=0 [1] sgn=1 windVal=1 windSum=1
+markDone id=1 (377.218994,-141.981003 40.578701,-201.339996 23.1854992,-102.697998) t=0.245788566 [12] (254.22023,-156.776138) tEnd=1 newWindSum=2 newOppSum=? oppSum=? windSum=2 windValue=1 oppValue=0
+markDone id=2 (23.1854992,-102.697998 377.218994,-141.981003) t=0 [3] (23.1854992,-102.697998) tEnd=0.443739761 newWindSum=2 newOppSum=? oppSum=? windSum=2 windValue=1 oppValue=0
+findNextWinding chase.append segment=2 span=10 windSum=-2147483647
+markDone id=4 (95.5512009,58.9763985 306.588013,-227.983994) t=0.64393017 [13] (231.444168,-125.806053) tEnd=0.751854746 newWindSum=2 newOppSum=? oppSum=? windSum=2 windValue=1 oppValue=0
+findNextWinding chase.append segment=4 span=13 windSum=2
+findNextWinding chase.append segment=2 span=14 windSum=1
+markDone id=4 (95.5512009,58.9763985 306.588013,-227.983994) t=0.751854746 [11] (254.22023,-156.776138) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1 oppValue=0
+findNextWinding from:[4] to:[1] start=50334624 end=1606415336
+bridgeWinding current id=4 from=(306.588013,-227.983994) to=(254.22023,-156.776138)
+findNextWinding simple
+markDone id=1 (377.218994,-141.981003 40.578701,-201.339996 23.1854992,-102.697998) t=0 [1] (377.218994,-141.981003) tEnd=0.245788566 newWindSum=1 newOppSum=? oppSum=? windSum=1 windValue=1 oppValue=0
+bridgeWinding current id=1 from=(254.22023,-156.776138) to=(377.218994,-141.981003)
+path.lineTo(254.22023,-156.776138);
+path.conicTo(314.172607,-153.097824, 377.218994,-141.981003, 0.580018938);
+markWinding id=2 (23.1854992,-102.697998 377.218994,-141.981003) t=0.443739761 [10] (180.284241,-120.129433) tEnd=0.588245674 newWindSum=2 windSum=? windValue=1
+markAngle last seg=2 span=10 windSum=2
+markWinding id=4 (95.5512009,58.9763985 306.588013,-227.983994) t=0 [7] (95.5512009,58.9763985) tEnd=0.64393017 newWindSum=1 windSum=? windValue=1
+markWinding id=3 (306.588013,-227.983994 212.464996,-262.242004 95.5512009,58.9763985) t=0.602960898 [9] (180.284241,-120.129433) tEnd=1 newWindSum=1 windSum=? windValue=1
+markAngle last seg=3 span=9 windSum=1
+findNextWinding
+dumpOne [2/12] next=4/4 sect=1/1 s=0.588245674 [14] e=1 [4] sgn=-1 windVal=1 windSum=1
+dumpOne [4/4] next=2/11 sect=5/5 s=0.64393017 [13] e=0.751854746 [11] sgn=-1 windVal=1 windSum=2 done
+dumpOne [2/11] next=4/3 sect=17/17 s=0.588245674 [14] e=0.443739761 [10] sgn=1 windVal=1 windSum=2
+dumpOne [4/3] next=2/12 sect=21/21 s=0.64393017 [13] e=0 [7] sgn=1 windVal=1 windSum=1
+markDone id=2 (23.1854992,-102.697998 377.218994,-141.981003) t=0.443739761 [10] (180.284241,-120.129433) tEnd=0.588245674 newWindSum=2 newOppSum=? oppSum=? windSum=2 windValue=1 oppValue=0
+findNextWinding chase.append segment=3 span=9 windSum=1
+markDone id=2 (23.1854992,-102.697998 377.218994,-141.981003) t=0.588245674 [14] (231.444168,-125.806053) tEnd=1 newWindSum=1 newOppSum=? oppSum=? windSum=1 windValue=1 oppValue=0
+findNextWinding from:[2] to:[4] start=50334760 end=50333904
+bridgeWinding current id=2 from=(377.218994,-141.981003) to=(231.444168,-125.806053)
+findNextWinding simple
+markDone id=4 (95.5512009,58.9763985 306.588013,-227.983994) t=0 [7] (95.5512009,58.9763985) tEnd=0.64393017 newWindSum=1 newOppSum=? oppSum=? windSum=1 windValue=1 oppValue=0
+bridgeWinding current id=4 from=(231.444168,-125.806053) to=(95.5512009,58.9763985)
+path.lineTo(231.444168,-125.806053);
+findNextWinding
+dumpOne [3/2] next=2/10 sect=21/21 s=0.602960898 [9] e=1 [6] sgn=-1 windVal=1 windSum=1
+dumpOne [2/10] next=3/1 sect=1/1 s=0.443739761 [10] e=0.588245674 [14] sgn=-1 windVal=1 windSum=2 done
+dumpOne [3/1] next=2/9 sect=5/1 s=0.602960898 [9] e=0 [5] sgn=1 windVal=1 windSum=1 oppVal=0 oppSum=0 done
+dumpOne [2/9] next=3/2 sect=17/17 s=0.443739761 [10] e=0 [3] sgn=1 windVal=1 windSum=2 done
+markDone id=3 (306.588013,-227.983994 212.464996,-262.242004 95.5512009,58.9763985) t=0.602960898 [9] (180.284241,-120.129433) tEnd=1 newWindSum=1 newOppSum=? oppSum=? windSum=1 windValue=1 oppValue=0
+findNextWinding from:[3] to:[2] start=50334352 end=50333208
+bridgeWinding current id=3 from=(95.5512009,58.9763985) to=(180.284241,-120.129433)
+path.lineTo(95.5512009,58.9763985);
+path.conicTo(132.693985,-43.0726738, 180.284241,-120.129433, 0.497736931);
+path.close();
</div>
-
-
</div>
<script type="text/javascript">
var testDivs = [
- skpwww_gorcraft_ru_1,
+ reduced,
];
var decimal_places = 3; // make this 3 to show more precision