aboutsummaryrefslogtreecommitdiffhomepage
path: root/experimental
diff options
context:
space:
mode:
authorGravatar caryclark <caryclark@google.com>2015-01-29 10:43:09 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2015-01-29 10:43:09 -0800
commit17a2b5473d0144d10749ef8d26a10fbdab580226 (patch)
tree6e1d4b8db55db4dedb6d28f975eef294bd7ab1a8 /experimental
parentf75a130c459596c23595d1bf0654863ab5fe3541 (diff)
The original instantiation of pathops was in the experimental/Intersection directory. Anything of value has been copied into the mainline.
The obsolete gyp files are also included, along with a pixman test that never functioned but accidentally referenced some of these deleted files. Review URL: https://codereview.chromium.org/867213004
Diffstat (limited to 'experimental')
-rwxr-xr-xexperimental/Intersection/ActiveEdge_Test.cpp83
-rw-r--r--experimental/Intersection/AddTestOutput/main.cpp115
-rw-r--r--experimental/Intersection/ConvexHull.cpp143
-rw-r--r--experimental/Intersection/ConvexHull_Test.cpp468
-rw-r--r--experimental/Intersection/CubeRoot.cpp400
-rw-r--r--experimental/Intersection/CubicBezierClip.cpp89
-rw-r--r--experimental/Intersection/CubicBezierClip_Test.cpp32
-rw-r--r--experimental/Intersection/CubicBounds.cpp66
-rw-r--r--experimental/Intersection/CubicConvexHull.cpp165
-rw-r--r--experimental/Intersection/CubicIntersection.cpp471
-rw-r--r--experimental/Intersection/CubicIntersection_Test.cpp778
-rw-r--r--experimental/Intersection/CubicIntersection_TestData.cpp310
-rw-r--r--experimental/Intersection/CubicIntersection_TestData.h31
-rw-r--r--experimental/Intersection/CubicLineSegments.cpp38
-rw-r--r--experimental/Intersection/CubicLineSegments.h12
-rw-r--r--experimental/Intersection/CubicParameterization.cpp518
-rw-r--r--experimental/Intersection/CubicParameterizationCode.cpp405
-rw-r--r--experimental/Intersection/CubicParameterization_Test.cpp113
-rw-r--r--experimental/Intersection/CubicParameterization_TestUtility.cpp53
-rw-r--r--experimental/Intersection/CubicReduceOrder.cpp254
-rw-r--r--experimental/Intersection/CubicReduceOrder_Test.cpp154
-rw-r--r--experimental/Intersection/CubicSubDivide.cpp147
-rw-r--r--experimental/Intersection/CubicToQuadratics.cpp217
-rw-r--r--experimental/Intersection/CubicToQuadratics_Test.cpp269
-rw-r--r--experimental/Intersection/CubicUtilities.cpp424
-rw-r--r--experimental/Intersection/CubicUtilities.h46
-rw-r--r--experimental/Intersection/CubicUtilities_Test.cpp28
-rw-r--r--experimental/Intersection/CurveIntersection.h80
-rw-r--r--experimental/Intersection/CurveUtilities.h15
-rw-r--r--experimental/Intersection/DataTypes.cpp108
-rw-r--r--experimental/Intersection/DataTypes.h418
-rw-r--r--experimental/Intersection/DataTypes_Test.h7
-rw-r--r--experimental/Intersection/EdgeDemo.cpp347
-rw-r--r--experimental/Intersection/EdgeDemo.h3
-rw-r--r--experimental/Intersection/EdgeDemoApp-Info.plist32
-rw-r--r--experimental/Intersection/EdgeDemoApp.mm94
-rw-r--r--experimental/Intersection/EdgeDemoApp.xib3115
-rw-r--r--experimental/Intersection/EdgeMain.cpp13
-rw-r--r--experimental/Intersection/EdgeWalker.cpp2705
-rwxr-xr-xexperimental/Intersection/EdgeWalkerPolygon4x4_Test.cpp290
-rw-r--r--experimental/Intersection/EdgeWalkerPolygons_Mismatches.cpp1622
-rw-r--r--experimental/Intersection/EdgeWalkerPolygons_Test.cpp790
-rw-r--r--experimental/Intersection/EdgeWalkerQuadralaterals_Test.cpp126
-rw-r--r--experimental/Intersection/EdgeWalkerQuadratic4x4_Test.cpp106
-rw-r--r--experimental/Intersection/EdgeWalkerQuadratics_Test.cpp284
-rw-r--r--experimental/Intersection/EdgeWalkerRectangles_Test.cpp469
-rw-r--r--experimental/Intersection/EdgeWalker_Test.h59
-rw-r--r--experimental/Intersection/EdgeWalker_TestUtility.cpp761
-rw-r--r--experimental/Intersection/English.lproj/InfoPlist.strings2
-rw-r--r--experimental/Intersection/English.lproj/MainMenu.xib4119
-rw-r--r--experimental/Intersection/Extrema.cpp81
-rw-r--r--experimental/Intersection/Extrema.h8
-rw-r--r--experimental/Intersection/Inline_Tests.cpp54
-rw-r--r--experimental/Intersection/IntersectionUtilities.cpp48
-rw-r--r--experimental/Intersection/IntersectionUtilities.h47
-rw-r--r--experimental/Intersection/Intersection_Tests.cpp84
-rw-r--r--experimental/Intersection/Intersection_Tests.h61
-rw-r--r--experimental/Intersection/Intersections.cpp158
-rw-r--r--experimental/Intersection/Intersections.h144
-rw-r--r--experimental/Intersection/LineCubicIntersection.cpp296
-rw-r--r--experimental/Intersection/LineCubicIntersection_Test.cpp62
-rw-r--r--experimental/Intersection/LineIntersection.cpp338
-rw-r--r--experimental/Intersection/LineIntersection.h21
-rw-r--r--experimental/Intersection/LineIntersection_Test.cpp72
-rw-r--r--experimental/Intersection/LineParameterization.cpp63
-rw-r--r--experimental/Intersection/LineParameters.h108
-rw-r--r--experimental/Intersection/LineParameteters_Test.cpp79
-rw-r--r--experimental/Intersection/LineQuadraticIntersection.cpp369
-rw-r--r--experimental/Intersection/LineQuadraticIntersection_Test.cpp235
-rw-r--r--experimental/Intersection/LineUtilities.cpp133
-rw-r--r--experimental/Intersection/LineUtilities.h25
-rw-r--r--experimental/Intersection/LogoPlay.cpp353
-rw-r--r--experimental/Intersection/MiniSimplify_Test.cpp99
-rw-r--r--experimental/Intersection/NearestPoint.cpp473
-rw-r--r--experimental/Intersection/Parameterization_Test.h12
-rw-r--r--experimental/Intersection/QuadraticBezierClip.cpp82
-rw-r--r--experimental/Intersection/QuadraticBezierClip_Test.cpp70
-rw-r--r--experimental/Intersection/QuadraticBounds.cpp47
-rw-r--r--experimental/Intersection/QuadraticImplicit.cpp572
-rw-r--r--experimental/Intersection/QuadraticIntersection.cpp403
-rw-r--r--experimental/Intersection/QuadraticIntersection_Test.cpp436
-rw-r--r--experimental/Intersection/QuadraticIntersection_TestData.cpp98
-rw-r--r--experimental/Intersection/QuadraticIntersection_TestData.h16
-rw-r--r--experimental/Intersection/QuadraticLineSegments.cpp34
-rw-r--r--experimental/Intersection/QuadraticLineSegments.h12
-rw-r--r--experimental/Intersection/QuadraticParameterization.cpp135
-rw-r--r--experimental/Intersection/QuadraticParameterization.h27
-rw-r--r--experimental/Intersection/QuadraticParameterization_Test.cpp48
-rw-r--r--experimental/Intersection/QuadraticParameterization_TestUtility.cpp16
-rw-r--r--experimental/Intersection/QuadraticReduceOrder.cpp184
-rw-r--r--experimental/Intersection/QuadraticReduceOrder_Test.cpp67
-rw-r--r--experimental/Intersection/QuadraticSubDivide.cpp79
-rw-r--r--experimental/Intersection/QuadraticUtilities.cpp255
-rw-r--r--experimental/Intersection/QuadraticUtilities.h47
-rw-r--r--experimental/Intersection/QuarticRoot.cpp236
-rw-r--r--experimental/Intersection/QuarticRoot.h5
-rw-r--r--experimental/Intersection/QuarticRoot_Test.cpp195
-rw-r--r--experimental/Intersection/ShapeOpCubic4x4_Test.cpp106
-rw-r--r--experimental/Intersection/ShapeOpRect4x4_Test.cpp94
-rw-r--r--experimental/Intersection/ShapeOps.cpp279
-rw-r--r--experimental/Intersection/ShapeOps.h40
-rw-r--r--experimental/Intersection/Simplify.cpp6608
-rw-r--r--experimental/Intersection/Simplify.h17
-rw-r--r--experimental/Intersection/SimplifyAddIntersectingTs_Test.cpp135
-rw-r--r--experimental/Intersection/SimplifyAngle_Test.cpp342
-rw-r--r--experimental/Intersection/SimplifyFindNext_Test.cpp153
-rw-r--r--experimental/Intersection/SimplifyFindTop_Test.cpp222
-rw-r--r--experimental/Intersection/SimplifyNew_Test.cpp5194
-rw-r--r--experimental/Intersection/SimplifyRect4x4_Test.cpp200
-rw-r--r--experimental/Intersection/SkAntiEdge.cpp1086
-rw-r--r--experimental/Intersection/SkAntiEdge.h76
-rw-r--r--experimental/Intersection/TSearch.h101
-rw-r--r--experimental/Intersection/TestUtilities.cpp65
-rw-r--r--experimental/Intersection/TestUtilities.h11
-rw-r--r--experimental/Intersection/TriangleUtilities.cpp31
-rw-r--r--experimental/Intersection/TriangleUtilities.h10
-rw-r--r--experimental/Intersection/as.htm7027
-rw-r--r--experimental/Intersection/bc.htm455
-rw-r--r--experimental/Intersection/cd.htm517
-rw-r--r--experimental/Intersection/edge_Prefix.pch5
-rw-r--r--experimental/Intersection/hg.htm649
-rw-r--r--experimental/Intersection/op.htm4806
-rw-r--r--experimental/Intersection/qc.htm2883
-rw-r--r--experimental/Intersection/thingsToDo.txt525
124 files changed, 0 insertions, 59518 deletions
diff --git a/experimental/Intersection/ActiveEdge_Test.cpp b/experimental/Intersection/ActiveEdge_Test.cpp
deleted file mode 100755
index 1c82f1cb69..0000000000
--- a/experimental/Intersection/ActiveEdge_Test.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "Simplify.h"
-
-namespace UnitTest {
-
-#include "EdgeWalker.cpp"
-
-} // end of UnitTest namespace
-
-#include "Intersection_Tests.h"
-
-SkPoint leftRight[][4] = {
-// equal length
- {{10, 10}, {10, 50}, {20, 10}, {20, 50}},
- {{10, 10}, {10, 50}, {10, 10}, {20, 50}},
- {{10, 10}, {10, 50}, {20, 10}, {10, 50}},
-// left top higher
- {{10, 0}, {10, 50}, {20, 10}, {20, 50}},
- {{10, 0}, {10, 50}, {10, 10}, {20, 50}},
- {{10, 0}, {10, 50}, {20, 10}, {10, 50}},
- {{10, 0}, {10, 50}, {20, 10}, {10 + 0.000001f, 40}},
-// left top lower
- {{10, 20}, {10, 50}, {20, 10}, {20, 50}},
- {{10, 20}, {10, 50}, {10, 10}, {20, 50}},
- {{10, 20}, {10, 50}, {20, 10}, {10, 50}},
- {{10, 20}, {10, 50}, {20, 10}, {10 + 0.000001f, 40}},
- {{10, 20}, {10, 50}, { 0, 0}, {50, 50}},
-// left bottom higher
- {{10, 10}, {10, 40}, {20, 10}, {20, 50}},
- {{10, 10}, {10, 40}, {10, 10}, {20, 50}},
- {{10, 10}, {10, 40}, {20, 10}, {10, 50}},
- {{10, 10}, {10, 40}, {20, 10}, { 0 + 0.000001f, 70}},
-// left bottom lower
- {{10, 10}, {10, 60}, {20, 10}, {20, 50}},
- {{10, 10}, {10, 60}, {10, 10}, {20, 50}},
- {{10, 10}, {10, 60}, {20, 10}, {10 + 0.000001f, 50}},
- {{10, 10}, {10, 60}, {20, 10}, {10 + 0.000001f, 40}},
- {{10, 10}, {10, 60}, { 0, 0}, {20 + 0.000001f, 20}},
-};
-
-size_t leftRightCount = sizeof(leftRight) / sizeof(leftRight[0]);
-
-// older code that worked mostly
-static bool operator_less_than(const UnitTest::ActiveEdge& lh,
- const UnitTest::ActiveEdge& rh) {
- if ((rh.fAbove.fY - lh.fAbove.fY > lh.fBelow.fY - rh.fAbove.fY
- && lh.fBelow.fY < rh.fBelow.fY)
- || (lh.fAbove.fY - rh.fAbove.fY < rh.fBelow.fY - lh.fAbove.fY
- && rh.fBelow.fY < lh.fBelow.fY)) {
- const SkPoint& check = rh.fBelow.fY <= lh.fBelow.fY
- && lh.fBelow != rh.fBelow ? rh.fBelow :
- rh.fAbove;
- return (check.fY - lh.fAbove.fY) * (lh.fBelow.fX - lh.fAbove.fX)
- < (lh.fBelow.fY - lh.fAbove.fY) * (check.fX - lh.fAbove.fX);
- }
- const SkPoint& check = lh.fBelow.fY <= rh.fBelow.fY
- && lh.fBelow != rh.fBelow ? lh.fBelow : lh.fAbove;
- return (rh.fBelow.fY - rh.fAbove.fY) * (check.fX - rh.fAbove.fX)
- < (check.fY - rh.fAbove.fY) * (rh.fBelow.fX - rh.fAbove.fX);
-}
-
-
-void ActiveEdge_Test() {
- UnitTest::InEdge leftIn, rightIn;
- UnitTest::ActiveEdge left, right;
- left.fWorkEdge.fEdge = &leftIn;
- right.fWorkEdge.fEdge = &rightIn;
- for (size_t x = 0; x < leftRightCount; ++x) {
- left.fAbove = leftRight[x][0];
- left.fTangent = left.fBelow = leftRight[x][1];
- right.fAbove = leftRight[x][2];
- right.fTangent = right.fBelow = leftRight[x][3];
- SkASSERT(left < right);
- SkASSERT(operator_less_than(left, right));
- SkASSERT(!(right < left));
- SkASSERT(!operator_less_than(right, left));
- }
-}
diff --git a/experimental/Intersection/AddTestOutput/main.cpp b/experimental/Intersection/AddTestOutput/main.cpp
deleted file mode 100644
index 1058bfceec..0000000000
--- a/experimental/Intersection/AddTestOutput/main.cpp
+++ /dev/null
@@ -1,115 +0,0 @@
-#include "SkStream.h"
-#include "SkString.h"
-#include "SkTDArray.h"
-#include <stdio.h>
-
-static bool replace(const char* fun, const char* dir, const char* filename, const char* marker,
- const char* marker2, const char* replace, size_t replaceLen) {
- SkString outFileStr(dir);
- outFileStr.append(filename);
- SkFILEStream opStreamIn(outFileStr.c_str());
- if (!opStreamIn.isValid()) {
- SkDebugf("%s couldn't find %s\n", fun, outFileStr.c_str());
- return false;
- }
- SkTDArray<char> opData;
- opData.setCount(opStreamIn.getLength());
- size_t opLen = opData.count();
- opStreamIn.read(opData.begin(), opLen);
- opStreamIn.setPath(NULL);
- SkFILEWStream opStreamOut(outFileStr.c_str());
- if (!opStreamOut.isValid()) {
- SkDebugf("%s couldn't open for writing %s\n", fun, outFileStr.c_str());
- return false;
- }
-
- char* opInsert = strstr(opData.begin(), marker);
- if (!opInsert) {
- SkDebugf("%s missing marker in %s\n", fun, outFileStr.c_str());
- opStreamOut.write(opData.begin(), opLen);
- opStreamOut.flush();
- return false;
- }
- const char* opInsertEnd = opInsert + strlen(marker);
- if (marker2) {
- char* opInsert2 = strstr(opInsert, marker2);
- if (!opInsert2) {
- SkDebugf("%s missing marker second half in %s\n", fun, outFileStr.c_str());
- opStreamOut.write(opData.begin(), opLen);
- opStreamOut.flush();
- return false;
- }
- opInsertEnd = opInsert2 + strlen(marker2);
- }
- opStreamOut.write(opData.begin(), opInsert - opData.begin());
- opStreamOut.write(replace, replaceLen);
- opStreamOut.write(opInsertEnd, opLen - (opInsertEnd - opData.begin()));
- opStreamOut.flush();
- return true;
-}
-
-int main (int argc, char * const argv[]) {
- if (argc != 2) {
- SkDebugf("%s expected filename\n", argv[0]);
- return 0;
- }
- const char* dir = "../../experimental/Intersection/";
- SkString inFileStr;
- if (argv[1][0] != '/') {
- inFileStr.append(dir);
- }
- inFileStr.append(argv[1]);
- SkFILEStream inFile(inFileStr.c_str());
- if (!inFile.isValid()) {
- SkDebugf("%s couldn't find %s\n", argv[0], argv[1]);
- return 0;
- }
- SkTDArray<char> inData;
- inData.setCount(inFile.getLength());
- size_t inLen = inData.count();
- inFile.read(inData.begin(), inLen);
- inFile.setPath(NULL);
- char* insert = strstr(inData.begin(), "\n\n\n");
- if (!insert) {
- SkDebugf("%s missing two blank line delimiter in %s\n", argv[0], argv[1]);
- return 0;
- }
- insert += 1; // include first blank line
- const char opMarker[] =
- "</div>" "\n"
- "\n"
- "<script type=\"text/javascript\">" "\n"
- "\n"
- "var testDivs = [" "\n"
- ;
- if (!replace(argv[0], dir, "op.htm", opMarker, NULL, inData.begin(),
- insert - inData.begin())) {
- return 0;
- }
- const char newMarker[] =
- "static void (*firstTest)() = "
- ;
- const char newMarker2[] =
- ";" "\n"
- "\n"
- "static struct {" "\n"
- " void (*fun)();" "\n"
- " const char* str;" "\n"
- "} tests[] = {" "\n"
- ;
- if (!replace(argv[0], dir, "SimplifyNew_Test.cpp", newMarker, newMarker2, insert + 2,
- inLen - (insert - inData.begin()) - 2)) {
- return 0;
- }
- const char forceReleaseMarker[] =
- "#define FORCE_RELEASE 1 // set force release to 1 for multiple thread -- no debugging"
- ;
- const char forceReleaseReplace[] =
- "#define FORCE_RELEASE 0 // set force release to 1 for multiple thread -- no debugging"
- ;
- if (!replace(argv[0], dir, "DataTypes.h", forceReleaseMarker, NULL, forceReleaseReplace,
- sizeof(forceReleaseReplace) - 1)) {
- return 0;
- }
- return 0;
-}
diff --git a/experimental/Intersection/ConvexHull.cpp b/experimental/Intersection/ConvexHull.cpp
deleted file mode 100644
index 86cb2dc6f5..0000000000
--- a/experimental/Intersection/ConvexHull.cpp
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "CurveIntersection.h"
-#include "CurveUtilities.h"
-#include "IntersectionUtilities.h"
-
-/* Given a cubic, find the convex hull described by the end and control points.
- The hull may have 3 or 4 points. Cubics that degenerate into a point or line
- are not considered.
-
- The hull is computed by assuming that three points, if unique and non-linear,
- form a triangle. The fourth point may replace one of the first three, may be
- discarded if in the triangle or on an edge, or may be inserted between any of
- the three to form a convex quadralateral.
-
- The indices returned in order describe the convex hull.
-*/
-int convex_hull(const Cubic& cubic, char order[4]) {
- size_t index;
- // find top point
- size_t yMin = 0;
- for (index = 1; index < 4; ++index) {
- if (cubic[yMin].y > cubic[index].y || (cubic[yMin].y == cubic[index].y
- && cubic[yMin].x > cubic[index].x)) {
- yMin = index;
- }
- }
- order[0] = yMin;
- int midX = -1;
- int backupYMin = -1;
- for (int pass = 0; pass < 2; ++pass) {
- for (index = 0; index < 4; ++index) {
- if (index == yMin) {
- continue;
- }
- // rotate line from (yMin, index) to axis
- // see if remaining two points are both above or below
- // use this to find mid
- int mask = other_two(yMin, index);
- int side1 = yMin ^ mask;
- int side2 = index ^ mask;
- Cubic rotPath;
- if (!rotate(cubic, yMin, index, rotPath)) { // ! if cbc[yMin]==cbc[idx]
- order[1] = side1;
- order[2] = side2;
- return 3;
- }
- int sides = side(rotPath[side1].y - rotPath[yMin].y);
- sides ^= side(rotPath[side2].y - rotPath[yMin].y);
- if (sides == 2) { // '2' means one remaining point <0, one >0
- if (midX >= 0) {
- printf("%s unexpected mid\n", __FUNCTION__); // there can be only one mid
- }
- midX = index;
- } else if (sides == 0) { // '0' means both to one side or the other
- backupYMin = index;
- }
- }
- if (midX >= 0) {
- break;
- }
- if (backupYMin < 0) {
- break;
- }
- yMin = backupYMin;
- backupYMin = -1;
- }
- if (midX < 0) {
- midX = yMin ^ 3; // choose any other point
- }
- int mask = other_two(yMin, midX);
- int least = yMin ^ mask;
- int most = midX ^ mask;
- order[0] = yMin;
- order[1] = least;
-
- // see if mid value is on same side of line (least, most) as yMin
- Cubic midPath;
- if (!rotate(cubic, least, most, midPath)) { // ! if cbc[least]==cbc[most]
- order[2] = midX;
- return 3;
- }
- int midSides = side(midPath[yMin].y - midPath[least].y);
- midSides ^= side(midPath[midX].y - midPath[least].y);
- if (midSides != 2) { // if mid point is not between
- order[2] = most;
- return 3; // result is a triangle
- }
- order[2] = midX;
- order[3] = most;
- return 4; // result is a quadralateral
-}
-
-/* Find the convex hull for cubics with the x-axis interval regularly spaced.
- Cubics computed as distance functions are formed this way.
-
- connectTo0[0], connectTo0[1] are the point indices that cubic[0] connects to.
- connectTo3[0], connectTo3[1] are the point indices that cubic[3] connects to.
-
- Returns true if cubic[1] to cubic[2] also forms part of the hull.
-*/
-bool convex_x_hull(const Cubic& cubic, char connectTo0[2], char connectTo3[2]) {
- double projectedY[4];
- projectedY[0] = 0;
- int index;
- for (index = 1; index < 4; ++index) {
- projectedY[index] = (cubic[index].y - cubic[0].y) * (3.0 / index);
- }
- int lower0Index = 1;
- int upper0Index = 1;
- for (index = 2; index < 4; ++index) {
- if (approximately_greater_or_equal(projectedY[lower0Index], projectedY[index])) {
- lower0Index = index;
- }
- if (approximately_lesser_or_equal(projectedY[upper0Index], projectedY[index])) {
- upper0Index = index;
- }
- }
- connectTo0[0] = lower0Index;
- connectTo0[1] = upper0Index;
- for (index = 0; index < 3; ++index) {
- projectedY[index] = (cubic[3].y - cubic[index].y) * (3.0 / (3 - index));
- }
- projectedY[3] = 0;
- int lower3Index = 2;
- int upper3Index = 2;
- for (index = 1; index > -1; --index) {
- if (approximately_greater_or_equal(projectedY[lower3Index], projectedY[index])) {
- lower3Index = index;
- }
- if (approximately_lesser_or_equal(projectedY[upper3Index], projectedY[index])) {
- upper3Index = index;
- }
- }
- connectTo3[0] = lower3Index;
- connectTo3[1] = upper3Index;
- return (1 << lower0Index | 1 << upper0Index
- | 1 << lower3Index | 1 << upper3Index) == 0x0F;
-}
diff --git a/experimental/Intersection/ConvexHull_Test.cpp b/experimental/Intersection/ConvexHull_Test.cpp
deleted file mode 100644
index 3979b1ebca..0000000000
--- a/experimental/Intersection/ConvexHull_Test.cpp
+++ /dev/null
@@ -1,468 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "CurveIntersection.h"
-#include "Intersection_Tests.h"
-#include "IntersectionUtilities.h"
-
-const Cubic convex[] = {
- {{0, 0}, {2, 0}, {2, 1}, {0, 1}},
- {{1, 0}, {1, 1}, {0, 1}, {0, 0}},
- {{1, 1}, {0, 1}, {0, 0}, {1, 0}},
- {{0, 1}, {0, 0}, {1, 0}, {1, 1}},
- {{0, 0}, {10, 0}, {10, 10}, {5, 6}},
-};
-
-size_t convex_count = sizeof(convex) / sizeof(convex[0]);
-
-const Cubic bowtie[] = {
- {{0, 0}, {1, 1}, {1, 0}, {0, 1}},
- {{1, 0}, {0, 1}, {1, 1}, {0, 0}},
- {{1, 1}, {0, 0}, {0, 1}, {1, 0}},
- {{0, 1}, {1, 0}, {0, 0}, {1, 1}},
-};
-
-size_t bowtie_count = sizeof(bowtie) / sizeof(bowtie[0]);
-
-const Cubic arrow[] = {
- {{0, 0}, {10, 0}, {10, 10}, {5, 4}},
- {{10, 0}, {10, 10}, {5, 4}, {0, 0}},
- {{10, 10}, {5, 4}, {0, 0}, {10, 0}},
- {{5, 4}, {0, 0}, {10, 0}, {10, 10}},
-};
-
-size_t arrow_count = sizeof(arrow) / sizeof(arrow[0]);
-
-const Cubic three[] = {
- {{1, 0}, {1, 0}, {1, 1}, {0, 1}}, // 0 == 1
- {{0, 0}, {1, 1}, {1, 1}, {0, 1}}, // 1 == 2
- {{0, 0}, {1, 0}, {0, 1}, {0, 1}}, // 2 == 3
- {{1, 0}, {1, 1}, {1, 0}, {0, 1}}, // 0 == 2
- {{1, 0}, {1, 1}, {0, 1}, {1, 0}}, // 0 == 3
- {{0, 0}, {1, 0}, {1, 1}, {1, 0}}, // 1 == 3
-};
-
-size_t three_count = sizeof(three) / sizeof(three[0]);
-
-const Cubic triangle[] = {
- {{0, 0}, {1, 0}, {2, 0}, {0, 1}}, // extra point on horz
- {{1, 0}, {2, 0}, {0, 1}, {0, 0}},
- {{2, 0}, {0, 1}, {0, 0}, {1, 0}},
- {{0, 1}, {0, 0}, {1, 0}, {2, 0}},
-
- {{0, 0}, {0, 1}, {0, 2}, {1, 1}}, // extra point on vert
- {{0, 1}, {0, 2}, {1, 1}, {0, 0}},
- {{0, 2}, {1, 1}, {0, 0}, {0, 1}},
- {{1, 1}, {0, 0}, {0, 1}, {0, 2}},
-
- {{0, 0}, {1, 1}, {2, 2}, {2, 0}}, // extra point on diag
- {{1, 1}, {2, 2}, {2, 0}, {0, 0}},
- {{2, 2}, {2, 0}, {0, 0}, {1, 1}},
- {{2, 0}, {0, 0}, {1, 1}, {2, 2}},
-
- {{0, 0}, {2, 0}, {2, 2}, {1, 1}}, // extra point on diag
- {{2, 0}, {2, 2}, {1, 1}, {0, 0}},
- {{2, 2}, {1, 1}, {0, 0}, {2, 0}},
- {{1, 1}, {0, 0}, {2, 0}, {2, 2}},
-};
-
-size_t triangle_count = sizeof(triangle) / sizeof(triangle[0]);
-
-const struct CubicDataSet {
- const Cubic* data;
- size_t size;
-} cubicDataSet[] = {
- { three, three_count },
- { convex, convex_count },
- { bowtie, bowtie_count },
- { arrow, arrow_count },
- { triangle, triangle_count },
-};
-
-size_t cubicDataSet_count = sizeof(cubicDataSet) / sizeof(cubicDataSet[0]);
-
-typedef double Matrix3x2[3][2];
-
-static bool rotateToAxis(const _Point& a, const _Point& b, Matrix3x2& matrix) {
- double dx = b.x - a.x;
- double dy = b.y - a.y;
- double length = sqrt(dx * dx + dy * dy);
- if (length == 0) {
- return false;
- }
- double invLength = 1 / length;
- matrix[0][0] = dx * invLength;
- matrix[1][0] = dy * invLength;
- matrix[2][0] = 0;
- matrix[0][1] = -dy * invLength;
- matrix[1][1] = dx * invLength;
- matrix[2][1] = 0;
- return true;
-}
-
-static void transform(const Cubic& cubic, const Matrix3x2& matrix, Cubic& rotPath) {
- for (int index = 0; index < 4; ++index) {
- rotPath[index].x = cubic[index].x * matrix[0][0]
- + cubic[index].y * matrix[1][0] + matrix[2][0];
- rotPath[index].y = cubic[index].x * matrix[0][1]
- + cubic[index].y * matrix[1][1] + matrix[2][1];
- }
-}
-
-// brute force way to find convex hull:
-// pick two points
-// rotate all four until the two points are horizontal
-// are the remaining two points both above or below the horizontal line?
-// if so, the two points must be an edge of the convex hull
-static int rotate_to_hull(const Cubic& cubic, char order[4], size_t idx, size_t inr) {
- bool debug_rotate_to_hull = false;
- int outsidePtSet[4];
- memset(outsidePtSet, -1, sizeof(outsidePtSet));
- for (int outer = 0; outer < 3; ++outer) {
- for (int priorOuter = 0; priorOuter < outer; ++priorOuter) {
- if (cubic[outer].approximatelyEqual(cubic[priorOuter])) {
- goto skip;
- }
- }
- for (int inner = outer + 1; inner < 4; ++inner) {
- for (int priorInner = outer + 1; priorInner < inner; ++priorInner) {
- if (cubic[inner].approximatelyEqual(cubic[priorInner])) {
- goto skipInner;
- }
- }
- if (cubic[outer].approximatelyEqual(cubic[inner])) {
- continue;
- }
- Matrix3x2 matrix;
- if (!rotateToAxis(cubic[outer], cubic[inner], matrix)) {
- continue;
- }
- Cubic rotPath;
- transform(cubic, matrix, rotPath);
- int sides[3];
- int zeroes;
- zeroes = -1;
- bzero(sides, sizeof(sides));
- if (debug_rotate_to_hull) SkDebugf("%s [%d,%d] [o=%d,i=%d] src=(%g,%g) rot=", __FUNCTION__,
- (int)idx, (int)inr, (int)outer, (int)inner,
- cubic[inner].x, cubic[inner].y);
- for (int index = 0; index < 4; ++index) {
- if (debug_rotate_to_hull) SkDebugf("(%g,%g) ", rotPath[index].x, rotPath[index].y);
- sides[side(rotPath[index].y - rotPath[inner].y)]++;
- if (index != outer && index != inner
- && side(rotPath[index].y - rotPath[inner].y) == 1)
- zeroes = index;
- }
- if (debug_rotate_to_hull) SkDebugf("sides=(%d,%d,%d)\n", sides[0], sides[1], sides[2]);
- if (sides[0] && sides[2]) {
- continue;
- }
- if (sides[1] == 3 && zeroes >= 0) {
- // verify that third point is between outer, inner
- // if either of remaining two equals outer or equal, pick lower
- if (rotPath[zeroes].approximatelyEqual(rotPath[inner])
- && zeroes < inner) {
- if (debug_rotate_to_hull) SkDebugf("%s [%d,%d] [o=%d,i=%d] zeroes < inner\n",
- __FUNCTION__, (int)idx, (int)inr, (int)outer, (int)inner);
- continue;
- }
- if (rotPath[zeroes].approximatelyEqual(rotPath[outer])
- && zeroes < outer) {
- if (debug_rotate_to_hull) SkDebugf("%s [%d,%d] [o=%d,i=%d] zeroes < outer\n",
- __FUNCTION__, (int)idx, (int)inr, (int)outer, (int)inner);
- continue;
- }
- if (rotPath[zeroes].x < rotPath[inner].x
- && rotPath[zeroes].x < rotPath[outer].x) {
- if (debug_rotate_to_hull) SkDebugf("%s [%d,%d] [o=%d,i=%d] zeroes < inner && outer\n",
- __FUNCTION__, (int)idx, (int)inr, (int)outer, (int)inner);
- continue;
- }
- if (rotPath[zeroes].x > rotPath[inner].x
- && rotPath[zeroes].x > rotPath[outer].x) {
- if (debug_rotate_to_hull) SkDebugf("%s [%d,%d] [o=%d,i=%d] zeroes > inner && outer\n",
- __FUNCTION__, (int)idx, (int)inr, (int)outer, (int)inner);
- continue;
- }
- }
- if (outsidePtSet[outer] < 0) {
- outsidePtSet[outer] = inner;
- } else {
- if (outsidePtSet[inner] > 0) {
- if (debug_rotate_to_hull) SkDebugf("%s [%d,%d] [o=%d,i=%d] too many rays from one point\n",
- __FUNCTION__, (int)idx, (int)inr, (int)outer, (int)inner);
- }
- outsidePtSet[inner] = outer;
- }
-skipInner:
- ;
- }
-skip:
- ;
- }
- int totalSides = 0;
- int first = 0;
- for (; first < 4; ++first) {
- if (outsidePtSet[first] >= 0) {
- break;
- }
- }
- if (first > 3) {
- order[0] = 0;
- return 1;
- }
- int next = first;
- do {
- order[totalSides++] = next;
- next = outsidePtSet[next];
- } while (next != -1 && next != first);
- return totalSides;
-}
-
-int firstIndex = 0;
-int firstInner = 0;
-
-void ConvexHull_Test() {
- for (size_t index = firstIndex; index < cubicDataSet_count; ++index) {
- const CubicDataSet& set = cubicDataSet[index];
- for (size_t inner = firstInner; inner < set.size; ++inner) {
- const Cubic& cubic = set.data[inner];
- char order[4], cmpOrder[4];
- int cmp = rotate_to_hull(cubic, cmpOrder, index, inner);
- if (cmp < 3) {
- continue;
- }
- int result = convex_hull(cubic, order);
- if (cmp != result) {
- SkDebugf("%s [%d,%d] result=%d cmp=%d\n", __FUNCTION__,
- (int)index, (int)inner, result, cmp);
- continue;
- }
- // check for same indices
- char pts = 0;
- char cmpPts = 0;
- int pt, bit;
- for (pt = 0; pt < cmp; ++pt) {
- if (pts & 1 << order[pt]) {
- SkDebugf("%s [%d,%d] duplicate index in order: %d,%d,%d",
- __FUNCTION__, (int)index, (int)inner,
- order[0], order[1], order[2]);
- if (cmp == 4) {
- SkDebugf(",%d", order[3]);
- }
- SkDebugf("\n");
- goto next;
- }
- if (cmpPts & 1 << cmpOrder[pt]) {
- SkDebugf("%s [%d,%d] duplicate index in order: %d,%d,%d",
- __FUNCTION__, (int)index, (int)inner,
- cmpOrder[0], cmpOrder[1], cmpOrder[2]);
- if (cmp == 4) {
- SkDebugf(",%d", cmpOrder[3]);
- }
- SkDebugf("\n");
- goto next;
- }
- pts |= 1 << order[pt];
- cmpPts |= 1 << cmpOrder[pt];
- }
- for (bit = 0; bit < 4; ++bit) {
- if (pts & 1 << bit) {
- continue;
- }
- for (pt = 0; pt < cmp; ++pt) {
- if (order[pt] == bit) {
- continue;
- }
- if (cubic[order[pt]] == cubic[bit]) {
- pts |= 1 << bit;
- }
- }
- }
- for (bit = 0; bit < 4; ++bit) {
- if (cmpPts & 1 << bit) {
- continue;
- }
- for (pt = 0; pt < cmp; ++pt) {
- if (cmpOrder[pt] == bit) {
- continue;
- }
- if (cubic[cmpOrder[pt]] == cubic[bit]) {
- cmpPts |= 1 << bit;
- }
- }
- }
- if (pts != cmpPts) {
- SkDebugf("%s [%d,%d] mismatch indices: order=%d,%d,%d",
- __FUNCTION__, (int)index, (int)inner,
- order[0], order[1], order[2]);
- if (cmp == 4) {
- SkDebugf(",%d", order[3]);
- }
- SkDebugf(" cmpOrder=%d,%d,%d", cmpOrder[0], cmpOrder[1], cmpOrder[2]);
- if (cmp == 4) {
- SkDebugf(",%d", cmpOrder[3]);
- }
- SkDebugf("\n");
- continue;
- }
- if (cmp == 4) { // check for bow ties
- int match = 0;
- while (cmpOrder[match] != order[0]) {
- ++match;
- }
- if (cmpOrder[match ^ 2] != order[2]) {
- SkDebugf("%s [%d,%d] bowtie mismatch: order=%d,%d,%d,%d"
- " cmpOrder=%d,%d,%d,%d\n",
- __FUNCTION__, (int)index, (int)inner,
- order[0], order[1], order[2], order[3],
- cmpOrder[0], cmpOrder[1], cmpOrder[2], cmpOrder[3]);
- }
- }
- next:
- ;
- }
- }
-}
-
-const double a = 1.0/3;
-const double b = 2.0/3;
-
-const Cubic x_cubic[] = {
- {{0, 0}, {a, 0}, {b, 0}, {1, 0}}, // 0
- {{0, 0}, {a, 0}, {b, 0}, {1, 1}}, // 1
- {{0, 0}, {a, 0}, {b, 1}, {1, 0}}, // 2
- {{0, 0}, {a, 0}, {b, 1}, {1, 1}}, // 3
- {{0, 0}, {a, 1}, {b, 0}, {1, 0}}, // 4
- {{0, 0}, {a, 1}, {b, 0}, {1, 1}}, // 5
- {{0, 0}, {a, 1}, {b, 1}, {1, 0}}, // 6
- {{0, 0}, {a, 1}, {b, 1}, {1, 1}}, // 7
- {{0, 1}, {a, 0}, {b, 0}, {1, 0}}, // 8
- {{0, 1}, {a, 0}, {b, 0}, {1, 1}}, // 9
- {{0, 1}, {a, 0}, {b, 1}, {1, 0}}, // 10
- {{0, 1}, {a, 0}, {b, 1}, {1, 1}}, // 11
- {{0, 1}, {a, 1}, {b, 0}, {1, 0}}, // 12
- {{0, 1}, {a, 1}, {b, 0}, {1, 1}}, // 13
- {{0, 1}, {a, 1}, {b, 1}, {1, 0}}, // 14
- {{0, 1}, {a, 1}, {b, 1}, {1, 1}}, // 15
-};
-
-size_t x_cubic_count = sizeof(x_cubic) / sizeof(x_cubic[0]);
-
-static int first_x_test = 0;
-
-void ConvexHull_X_Test() {
- for (size_t index = first_x_test; index < x_cubic_count; ++index) {
- const Cubic& cubic = x_cubic[index];
- char connectTo0[2] = {-1, -1};
- char connectTo3[2] = {-1, -1};
- convex_x_hull(cubic, connectTo0, connectTo3);
- int idx, cmp;
- for (idx = 0; idx < 2; ++idx) {
- if (connectTo0[idx] >= 1 && connectTo0[idx] < 4) {
- continue;
- } else {
- SkDebugf("%s connectTo0[idx]=%d", __FUNCTION__, connectTo0[idx]);
- }
- if (connectTo3[idx] >= 0 && connectTo3[idx] < 3) {
- continue;
- } else {
- SkDebugf("%s connectTo3[idx]=%d", __FUNCTION__, connectTo3[idx]);
- }
- goto nextTest;
- }
- char rOrder[4];
- char cmpOrder[4];
- cmp = rotate_to_hull(cubic, cmpOrder, index, 0);
- if (index == 0 || index == 15) {
- // FIXME: make rotate_to_hull work for degenerate 2 edge hull cases
- cmpOrder[0] = 0;
- cmpOrder[1] = 3;
- cmp = 2;
- }
- if (cmp < 3) {
- // FIXME: make rotate_to_hull work for index == 3 etc
- continue;
- }
- for (idx = 0; idx < cmp; ++idx) {
- if (cmpOrder[idx] == 0) {
- rOrder[0] = cmpOrder[(idx + 1) % cmp];
- rOrder[1] = cmpOrder[(idx + cmp - 1) % cmp];
- } else if (cmpOrder[idx] == 3) {
- rOrder[2] = cmpOrder[(idx + 1) % cmp];
- rOrder[3] = cmpOrder[(idx + cmp - 1) % cmp];
- }
- }
- if (connectTo0[0] != connectTo0[1]) {
- if (rOrder[0] == rOrder[1]) {
- SkDebugf("%s [%d] (1) order=(%d,%d,%d,%d) r_order=(%d,%d,%d,%d)\n",
- __FUNCTION__, (int)index, connectTo0[0], connectTo0[1],
- connectTo3[0], connectTo3[1],
- rOrder[0], rOrder[1], rOrder[2], rOrder[3]);
- continue;
- }
- int unused = 6 - connectTo0[0] - connectTo0[1];
- int rUnused = 6 - rOrder[0] - rOrder[1];
- if (unused != rUnused) {
- SkDebugf("%s [%d] (2) order=(%d,%d,%d,%d) r_order=(%d,%d,%d,%d)\n",
- __FUNCTION__, (int)index, connectTo0[0], connectTo0[1],
- connectTo3[0], connectTo3[1],
- rOrder[0], rOrder[1], rOrder[2], rOrder[3]);
- continue;
- }
- } else {
- if (rOrder[0] != rOrder[1]) {
- SkDebugf("%s [%d] (3) order=(%d,%d,%d,%d) r_order=(%d,%d,%d,%d)\n",
- __FUNCTION__, (int)index, connectTo0[0], connectTo0[1],
- connectTo3[0], connectTo3[1],
- rOrder[0], rOrder[1], rOrder[2], rOrder[3]);
- continue;
- }
- if (connectTo0[0] != rOrder[0]) {
- SkDebugf("%s [%d] (4) order=(%d,%d,%d,%d) r_order=(%d,%d,%d,%d)\n",
- __FUNCTION__, (int)index, connectTo0[0], connectTo0[1],
- connectTo3[0], connectTo3[1],
- rOrder[0], rOrder[1], rOrder[2], rOrder[3]);
- continue;
- }
- }
- if (connectTo3[0] != connectTo3[1]) {
- if (rOrder[2] == rOrder[3]) {
- SkDebugf("%s [%d] (5) order=(%d,%d,%d,%d) r_order=(%d,%d,%d,%d)\n",
- __FUNCTION__, (int)index, connectTo0[0], connectTo0[1],
- connectTo3[0], connectTo3[1],
- rOrder[0], rOrder[1], rOrder[2], rOrder[3]);
- continue;
- }
- int unused = 6 - connectTo3[0] - connectTo3[1];
- int rUnused = 6 - rOrder[2] - rOrder[3];
- if (unused != rUnused) {
- SkDebugf("%s [%d] (6) order=(%d,%d,%d,%d) r_order=(%d,%d,%d,%d)\n",
- __FUNCTION__, (int)index, connectTo0[0], connectTo0[1],
- connectTo3[0], connectTo3[1],
- rOrder[0], rOrder[1], rOrder[2], rOrder[3]);
- continue;
- }
- } else {
- if (rOrder[2] != rOrder[3]) {
- SkDebugf("%s [%d] (7) order=(%d,%d,%d,%d) r_order=(%d,%d,%d,%d)\n",
- __FUNCTION__, (int)index, connectTo0[0], connectTo0[1],
- connectTo3[0], connectTo3[1],
- rOrder[0], rOrder[1], rOrder[2], rOrder[3]);
- continue;
- }
- if (connectTo3[1] != rOrder[3]) {
- SkDebugf("%s [%d] (8) order=(%d,%d,%d,%d) r_order=(%d,%d,%d,%d)\n",
- __FUNCTION__, (int)index, connectTo0[0], connectTo0[1],
- connectTo3[0], connectTo3[1],
- rOrder[0], rOrder[1], rOrder[2], rOrder[3]);
- continue;
- }
- }
-nextTest:
- ;
- }
-}
diff --git a/experimental/Intersection/CubeRoot.cpp b/experimental/Intersection/CubeRoot.cpp
deleted file mode 100644
index 5f785a0358..0000000000
--- a/experimental/Intersection/CubeRoot.cpp
+++ /dev/null
@@ -1,400 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-// http://metamerist.com/cbrt/CubeRoot.cpp
-//
-
-#include <math.h>
-#include "CubicUtilities.h"
-
-#define TEST_ALTERNATIVES 0
-#if TEST_ALTERNATIVES
-typedef float (*cuberootfnf) (float);
-typedef double (*cuberootfnd) (double);
-
-// estimate bits of precision (32-bit float case)
-inline int bits_of_precision(float a, float b)
-{
- const double kd = 1.0 / log(2.0);
-
- if (a==b)
- return 23;
-
- const double kdmin = pow(2.0, -23.0);
-
- double d = fabs(a-b);
- if (d < kdmin)
- return 23;
-
- return int(-log(d)*kd);
-}
-
-// estiamte bits of precision (64-bit double case)
-inline int bits_of_precision(double a, double b)
-{
- const double kd = 1.0 / log(2.0);
-
- if (a==b)
- return 52;
-
- const double kdmin = pow(2.0, -52.0);
-
- double d = fabs(a-b);
- if (d < kdmin)
- return 52;
-
- return int(-log(d)*kd);
-}
-
-// cube root via x^(1/3)
-static float pow_cbrtf(float x)
-{
- return (float) pow(x, 1.0f/3.0f);
-}
-
-// cube root via x^(1/3)
-static double pow_cbrtd(double x)
-{
- return pow(x, 1.0/3.0);
-}
-
-// cube root approximation using bit hack for 32-bit float
-static float cbrt_5f(float f)
-{
- unsigned int* p = (unsigned int *) &f;
- *p = *p/3 + 709921077;
- return f;
-}
-#endif
-
-// cube root approximation using bit hack for 64-bit float
-// adapted from Kahan's cbrt
-static double cbrt_5d(double d)
-{
- const unsigned int B1 = 715094163;
- double t = 0.0;
- unsigned int* pt = (unsigned int*) &t;
- unsigned int* px = (unsigned int*) &d;
- pt[1]=px[1]/3+B1;
- return t;
-}
-
-#if TEST_ALTERNATIVES
-// cube root approximation using bit hack for 64-bit float
-// adapted from Kahan's cbrt
-#if 0
-static double quint_5d(double d)
-{
- return sqrt(sqrt(d));
-
- const unsigned int B1 = 71509416*5/3;
- double t = 0.0;
- unsigned int* pt = (unsigned int*) &t;
- unsigned int* px = (unsigned int*) &d;
- pt[1]=px[1]/5+B1;
- return t;
-}
-#endif
-
-// iterative cube root approximation using Halley's method (float)
-static float cbrta_halleyf(const float a, const float R)
-{
- const float a3 = a*a*a;
- const float b= a * (a3 + R + R) / (a3 + a3 + R);
- return b;
-}
-#endif
-
-// iterative cube root approximation using Halley's method (double)
-static double cbrta_halleyd(const double a, const double R)
-{
- const double a3 = a*a*a;
- const double b= a * (a3 + R + R) / (a3 + a3 + R);
- return b;
-}
-
-#if TEST_ALTERNATIVES
-// iterative cube root approximation using Newton's method (float)
-static float cbrta_newtonf(const float a, const float x)
-{
-// return (1.0 / 3.0) * ((a + a) + x / (a * a));
- return a - (1.0f / 3.0f) * (a - x / (a*a));
-}
-
-// iterative cube root approximation using Newton's method (double)
-static double cbrta_newtond(const double a, const double x)
-{
- return (1.0/3.0) * (x / (a*a) + 2*a);
-}
-
-// cube root approximation using 1 iteration of Halley's method (double)
-static double halley_cbrt1d(double d)
-{
- double a = cbrt_5d(d);
- return cbrta_halleyd(a, d);
-}
-
-// cube root approximation using 1 iteration of Halley's method (float)
-static float halley_cbrt1f(float d)
-{
- float a = cbrt_5f(d);
- return cbrta_halleyf(a, d);
-}
-
-// cube root approximation using 2 iterations of Halley's method (double)
-static double halley_cbrt2d(double d)
-{
- double a = cbrt_5d(d);
- a = cbrta_halleyd(a, d);
- return cbrta_halleyd(a, d);
-}
-#endif
-
-// cube root approximation using 3 iterations of Halley's method (double)
-static double halley_cbrt3d(double d)
-{
- double a = cbrt_5d(d);
- a = cbrta_halleyd(a, d);
- a = cbrta_halleyd(a, d);
- return cbrta_halleyd(a, d);
-}
-
-#if TEST_ALTERNATIVES
-// cube root approximation using 2 iterations of Halley's method (float)
-static float halley_cbrt2f(float d)
-{
- float a = cbrt_5f(d);
- a = cbrta_halleyf(a, d);
- return cbrta_halleyf(a, d);
-}
-
-// cube root approximation using 1 iteration of Newton's method (double)
-static double newton_cbrt1d(double d)
-{
- double a = cbrt_5d(d);
- return cbrta_newtond(a, d);
-}
-
-// cube root approximation using 2 iterations of Newton's method (double)
-static double newton_cbrt2d(double d)
-{
- double a = cbrt_5d(d);
- a = cbrta_newtond(a, d);
- return cbrta_newtond(a, d);
-}
-
-// cube root approximation using 3 iterations of Newton's method (double)
-static double newton_cbrt3d(double d)
-{
- double a = cbrt_5d(d);
- a = cbrta_newtond(a, d);
- a = cbrta_newtond(a, d);
- return cbrta_newtond(a, d);
-}
-
-// cube root approximation using 4 iterations of Newton's method (double)
-static double newton_cbrt4d(double d)
-{
- double a = cbrt_5d(d);
- a = cbrta_newtond(a, d);
- a = cbrta_newtond(a, d);
- a = cbrta_newtond(a, d);
- return cbrta_newtond(a, d);
-}
-
-// cube root approximation using 2 iterations of Newton's method (float)
-static float newton_cbrt1f(float d)
-{
- float a = cbrt_5f(d);
- return cbrta_newtonf(a, d);
-}
-
-// cube root approximation using 2 iterations of Newton's method (float)
-static float newton_cbrt2f(float d)
-{
- float a = cbrt_5f(d);
- a = cbrta_newtonf(a, d);
- return cbrta_newtonf(a, d);
-}
-
-// cube root approximation using 3 iterations of Newton's method (float)
-static float newton_cbrt3f(float d)
-{
- float a = cbrt_5f(d);
- a = cbrta_newtonf(a, d);
- a = cbrta_newtonf(a, d);
- return cbrta_newtonf(a, d);
-}
-
-// cube root approximation using 4 iterations of Newton's method (float)
-static float newton_cbrt4f(float d)
-{
- float a = cbrt_5f(d);
- a = cbrta_newtonf(a, d);
- a = cbrta_newtonf(a, d);
- a = cbrta_newtonf(a, d);
- return cbrta_newtonf(a, d);
-}
-
-static double TestCubeRootf(const char* szName, cuberootfnf cbrt, double rA, double rB, int rN)
-{
- const int N = rN;
-
- float dd = float((rB-rA) / N);
-
- // calculate 1M numbers
- int i=0;
- float d = (float) rA;
-
- double s = 0.0;
-
- for(d=(float) rA, i=0; i<N; i++, d += dd)
- {
- s += cbrt(d);
- }
-
- double bits = 0.0;
- double worstx=0.0;
- double worsty=0.0;
- int minbits=64;
-
- for(d=(float) rA, i=0; i<N; i++, d += dd)
- {
- float a = cbrt((float) d);
- float b = (float) pow((double) d, 1.0/3.0);
-
- int bc = bits_of_precision(a, b);
- bits += bc;
-
- if (b > 1.0e-6)
- {
- if (bc < minbits)
- {
- minbits = bc;
- worstx = d;
- worsty = a;
- }
- }
- }
-
- bits /= N;
-
- printf(" %3d mbp %6.3f abp\n", minbits, bits);
-
- return s;
-}
-
-
-static double TestCubeRootd(const char* szName, cuberootfnd cbrt, double rA, double rB, int rN)
-{
- const int N = rN;
-
- double dd = (rB-rA) / N;
-
- int i=0;
-
- double s = 0.0;
- double d = 0.0;
-
- for(d=rA, i=0; i<N; i++, d += dd)
- {
- s += cbrt(d);
- }
-
-
- double bits = 0.0;
- double worstx = 0.0;
- double worsty = 0.0;
- int minbits = 64;
- for(d=rA, i=0; i<N; i++, d += dd)
- {
- double a = cbrt(d);
- double b = pow(d, 1.0/3.0);
-
- int bc = bits_of_precision(a, b); // min(53, count_matching_bitsd(a, b) - 12);
- bits += bc;
-
- if (b > 1.0e-6)
- {
- if (bc < minbits)
- {
- bits_of_precision(a, b);
- minbits = bc;
- worstx = d;
- worsty = a;
- }
- }
- }
-
- bits /= N;
-
- printf(" %3d mbp %6.3f abp\n", minbits, bits);
-
- return s;
-}
-
-static int _tmain()
-{
- // a million uniform steps through the range from 0.0 to 1.0
- // (doing uniform steps in the log scale would be better)
- double a = 0.0;
- double b = 1.0;
- int n = 1000000;
-
- printf("32-bit float tests\n");
- printf("----------------------------------------\n");
- TestCubeRootf("cbrt_5f", cbrt_5f, a, b, n);
- TestCubeRootf("pow", pow_cbrtf, a, b, n);
- TestCubeRootf("halley x 1", halley_cbrt1f, a, b, n);
- TestCubeRootf("halley x 2", halley_cbrt2f, a, b, n);
- TestCubeRootf("newton x 1", newton_cbrt1f, a, b, n);
- TestCubeRootf("newton x 2", newton_cbrt2f, a, b, n);
- TestCubeRootf("newton x 3", newton_cbrt3f, a, b, n);
- TestCubeRootf("newton x 4", newton_cbrt4f, a, b, n);
- printf("\n\n");
-
- printf("64-bit double tests\n");
- printf("----------------------------------------\n");
- TestCubeRootd("cbrt_5d", cbrt_5d, a, b, n);
- TestCubeRootd("pow", pow_cbrtd, a, b, n);
- TestCubeRootd("halley x 1", halley_cbrt1d, a, b, n);
- TestCubeRootd("halley x 2", halley_cbrt2d, a, b, n);
- TestCubeRootd("halley x 3", halley_cbrt3d, a, b, n);
- TestCubeRootd("newton x 1", newton_cbrt1d, a, b, n);
- TestCubeRootd("newton x 2", newton_cbrt2d, a, b, n);
- TestCubeRootd("newton x 3", newton_cbrt3d, a, b, n);
- TestCubeRootd("newton x 4", newton_cbrt4d, a, b, n);
- printf("\n\n");
-
- return 0;
-}
-#endif
-
-double cube_root(double x) {
- if (approximately_zero_cubed(x)) {
- return 0;
- }
- double result = halley_cbrt3d(fabs(x));
- if (x < 0) {
- result = -result;
- }
- return result;
-}
-
-#if TEST_ALTERNATIVES
-// http://bytes.com/topic/c/answers/754588-tips-find-cube-root-program-using-c
-/* cube root */
-int icbrt(int n) {
- int t=0, x=(n+2)/3; /* works for n=0 and n>=1 */
- for(; t!=x;) {
- int x3=x*x*x;
- t=x;
- x*=(2*n + x3);
- x/=(2*x3 + n);
- }
- return x ; /* always(?) equal to floor(n^(1/3)) */
-}
-#endif
diff --git a/experimental/Intersection/CubicBezierClip.cpp b/experimental/Intersection/CubicBezierClip.cpp
deleted file mode 100644
index d4c50fb41c..0000000000
--- a/experimental/Intersection/CubicBezierClip.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "CurveIntersection.h"
-#include "CurveUtilities.h"
-#include "LineParameters.h"
-
-// return false if unable to clip (e.g., unable to create implicit line)
-// caller should subdivide, or create degenerate if the values are too small
-bool bezier_clip(const Cubic& cubic1, const Cubic& cubic2, double& minT, double& maxT) {
- minT = 1;
- maxT = 0;
- // determine normalized implicit line equation for pt[0] to pt[3]
- // of the form ax + by + c = 0, where a*a + b*b == 1
-
- // find the implicit line equation parameters
- LineParameters endLine;
- endLine.cubicEndPoints(cubic1);
- if (!endLine.normalize()) {
- printf("line cannot be normalized: need more code here\n");
- return false;
- }
-
- double distance[2];
- distance[0] = endLine.controlPtDistance(cubic1, 1);
- distance[1] = endLine.controlPtDistance(cubic1, 2);
-
- // find fat line
- double top = distance[0];
- double bottom = distance[1];
- if (top > bottom) {
- SkTSwap(top, bottom);
- }
- if (top * bottom >= 0) {
- const double scale = 3/4.0; // http://cagd.cs.byu.edu/~tom/papers/bezclip.pdf (13)
- if (top < 0) {
- top *= scale;
- bottom = 0;
- } else {
- top = 0;
- bottom *= scale;
- }
- } else {
- const double scale = 4/9.0; // http://cagd.cs.byu.edu/~tom/papers/bezclip.pdf (15)
- top *= scale;
- bottom *= scale;
- }
-
- // compute intersecting candidate distance
- Cubic distance2y; // points with X of (0, 1/3, 2/3, 1)
- endLine.cubicDistanceY(cubic2, distance2y);
-
- int flags = 0;
- if (approximately_lesser_or_equal(distance2y[0].y, top)) {
- flags |= kFindTopMin;
- } else if (approximately_greater_or_equal(distance2y[0].y, bottom)) {
- flags |= kFindBottomMin;
- } else {
- minT = 0;
- }
-
- if (approximately_lesser_or_equal(distance2y[3].y, top)) {
- flags |= kFindTopMax;
- } else if (approximately_greater_or_equal(distance2y[3].y, bottom)) {
- flags |= kFindBottomMax;
- } else {
- maxT = 1;
- }
- // Find the intersection of distance convex hull and fat line.
- char to_0[2];
- char to_3[2];
- bool do_1_2_edge = convex_x_hull(distance2y, to_0, to_3);
- x_at(distance2y[0], distance2y[to_0[0]], top, bottom, flags, minT, maxT);
- if (to_0[0] != to_0[1]) {
- x_at(distance2y[0], distance2y[to_0[1]], top, bottom, flags, minT, maxT);
- }
- x_at(distance2y[to_3[0]], distance2y[3], top, bottom, flags, minT, maxT);
- if (to_3[0] != to_3[1]) {
- x_at(distance2y[to_3[1]], distance2y[3], top, bottom, flags, minT, maxT);
- }
- if (do_1_2_edge) {
- x_at(distance2y[1], distance2y[2], top, bottom, flags, minT, maxT);
- }
-
- return minT < maxT; // returns false if distance shows no intersection
-}
diff --git a/experimental/Intersection/CubicBezierClip_Test.cpp b/experimental/Intersection/CubicBezierClip_Test.cpp
deleted file mode 100644
index 9133980f58..0000000000
--- a/experimental/Intersection/CubicBezierClip_Test.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "CurveIntersection.h"
-#include "CubicIntersection_TestData.h"
-#include "Intersection_Tests.h"
-
-void CubicBezierClip_Test() {
- for (size_t index = 0; index < tests_count; ++index) {
- const Cubic& cubic1 = tests[index][0];
- const Cubic& cubic2 = tests[index][1];
- Cubic reduce1, reduce2;
- int order1 = reduceOrder(cubic1, reduce1, kReduceOrder_NoQuadraticsAllowed,
- kReduceOrder_TreatAsFill);
- int order2 = reduceOrder(cubic2, reduce2, kReduceOrder_NoQuadraticsAllowed,
- kReduceOrder_TreatAsFill);
- if (order1 < 4) {
- SkDebugf("%s [%d] cubic1 order=%d\n", __FUNCTION__, (int) index, order1);
- }
- if (order2 < 4) {
- SkDebugf("%s [%d] cubic2 order=%d\n", __FUNCTION__, (int) index, order2);
- }
- if (order1 == 4 && order2 == 4) {
- double minT = 0;
- double maxT = 1;
- bezier_clip(reduce1, reduce2, minT, maxT);
- }
- }
-}
diff --git a/experimental/Intersection/CubicBounds.cpp b/experimental/Intersection/CubicBounds.cpp
deleted file mode 100644
index 7fd9feff6f..0000000000
--- a/experimental/Intersection/CubicBounds.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "CurveIntersection.h"
-#include "CurveUtilities.h"
-#include "Extrema.h"
-
-static int isBoundedByEndPoints(double a, double b, double c, double d)
-{
- return between(a, b, d) && between(a, c, d);
-}
-
-double leftMostT(const Cubic& cubic, double startT, double endT) {
- double leftTs[2];
- _Point pt[2];
- int results = findExtrema(cubic[0].x, cubic[1].x, cubic[2].x, cubic[3].x, leftTs);
- int best = -1;
- for (int index = 0; index < results; ++index) {
- if (startT > leftTs[index] || leftTs[index] > endT) {
- continue;
- }
- if (best < 0) {
- best = index;
- continue;
- }
- xy_at_t(cubic, leftTs[0], pt[0].x, pt[0].y);
- xy_at_t(cubic, leftTs[1], pt[1].x, pt[1].y);
- if (pt[0].x > pt[1].x) {
- best = 1;
- }
- }
- if (best >= 0) {
- return leftTs[best];
- }
- xy_at_t(cubic, startT, pt[0].x, pt[0].y);
- xy_at_t(cubic, endT, pt[1].x, pt[1].y);
- return pt[0].x <= pt[1].x ? startT : endT;
-}
-
-void _Rect::setBounds(const Cubic& cubic) {
- set(cubic[0]);
- add(cubic[3]);
- double tValues[4];
- int roots = 0;
- if (!isBoundedByEndPoints(cubic[0].x, cubic[1].x, cubic[2].x, cubic[3].x)) {
- roots = findExtrema(cubic[0].x, cubic[1].x, cubic[2].x, cubic[3].x, tValues);
- }
- if (!isBoundedByEndPoints(cubic[0].y, cubic[1].y, cubic[2].y, cubic[3].y)) {
- roots += findExtrema(cubic[0].y, cubic[1].y, cubic[2].y, cubic[3].y, &tValues[roots]);
- }
- for (int x = 0; x < roots; ++x) {
- _Point result;
- xy_at_t(cubic, tValues[x], result.x, result.y);
- add(result);
- }
-}
-
-void _Rect::setRawBounds(const Cubic& cubic) {
- set(cubic[0]);
- for (int x = 1; x < 4; ++x) {
- add(cubic[x]);
- }
-}
diff --git a/experimental/Intersection/CubicConvexHull.cpp b/experimental/Intersection/CubicConvexHull.cpp
deleted file mode 100644
index 137b0d68d6..0000000000
--- a/experimental/Intersection/CubicConvexHull.cpp
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "CubicUtilities.h"
-#include "CurveIntersection.h"
-#include "Intersections.h"
-#include "IntersectionUtilities.h"
-#include "LineIntersection.h"
-
-static const double tClipLimit = 0.8; // http://cagd.cs.byu.edu/~tom/papers/bezclip.pdf see Multiple intersections
-
-class CubicIntersections : public Intersections {
-public:
-
-CubicIntersections(const Cubic& c1, const Cubic& c2, Intersections& i)
- : cubic1(c1)
- , cubic2(c2)
- , intersections(i)
- , depth(0)
- , splits(0) {
-}
-
-bool intersect() {
- double minT1, minT2, maxT1, maxT2;
- if (!bezier_clip(cubic2, cubic1, minT1, maxT1)) {
- return false;
- }
- if (!bezier_clip(cubic1, cubic2, minT2, maxT2)) {
- return false;
- }
- int split;
- if (maxT1 - minT1 < maxT2 - minT2) {
- intersections.swap();
- minT2 = 0;
- maxT2 = 1;
- split = maxT1 - minT1 > tClipLimit;
- } else {
- minT1 = 0;
- maxT1 = 1;
- split = (maxT2 - minT2 > tClipLimit) << 1;
- }
- return chop(minT1, maxT1, minT2, maxT2, split);
-}
-
-protected:
-
-bool intersect(double minT1, double maxT1, double minT2, double maxT2) {
- Cubic smaller, larger;
- // FIXME: carry last subdivide and reduceOrder result with cubic
- sub_divide(cubic1, minT1, maxT1, intersections.swapped() ? larger : smaller);
- sub_divide(cubic2, minT2, maxT2, intersections.swapped() ? smaller : larger);
- Cubic smallResult;
- if (reduceOrder(smaller, smallResult, kReduceOrder_NoQuadraticsAllowed,
- kReduceOrder_TreatAsFill) <= 2) {
- Cubic largeResult;
- if (reduceOrder(larger, largeResult, kReduceOrder_NoQuadraticsAllowed,
- kReduceOrder_TreatAsFill) <= 2) {
- const _Line& smallLine = (const _Line&) smallResult;
- const _Line& largeLine = (const _Line&) largeResult;
- Intersections lineTs;
- // FIXME: this doesn't detect or deal with coincident lines
- if (!::intersect(smallLine, largeLine, lineTs)) {
- return false;
- }
- if (intersections.swapped()) {
- lineTs.fT[0][0] = interp(minT2, maxT2, lineTs.fT[0][0]);
- lineTs.fT[1][0] = interp(minT1, maxT1, lineTs.fT[1][0]);
- } else {
- lineTs.fT[0][0] = interp(minT1, maxT1, lineTs.fT[0][0]);
- lineTs.fT[1][0] = interp(minT2, maxT2, lineTs.fT[1][0]);
- }
- _Point pt;
- xy_at_t(cubic1, lineTs.fT[0][0], pt.x, pt.y);
- intersections.insert(lineTs.fT[0][0], lineTs.fT[1][0], pt);
- return true;
- }
- }
- double minT, maxT;
- if (!bezier_clip(smaller, larger, minT, maxT)) {
- if (minT == maxT) {
- if (intersections.swapped()) {
- minT1 = (minT1 + maxT1) / 2;
- minT2 = interp(minT2, maxT2, minT);
- } else {
- minT1 = interp(minT1, maxT1, minT);
- minT2 = (minT2 + maxT2) / 2;
- }
- _Point pt;
- xy_at_t(cubic1, minT1, pt.x, pt.y);
- intersections.insert(minT1, minT2, pt);
- return true;
- }
- return false;
- }
-
- int split;
- if (intersections.swapped()) {
- double newMinT1 = interp(minT1, maxT1, minT);
- double newMaxT1 = interp(minT1, maxT1, maxT);
- split = (newMaxT1 - newMinT1 > (maxT1 - minT1) * tClipLimit) << 1;
-#define VERBOSE 0
-#if VERBOSE
- printf("%s d=%d s=%d new1=(%g,%g) old1=(%g,%g) split=%d\n",
- __FUNCTION__, depth, splits, newMinT1, newMaxT1, minT1, maxT1,
- split);
-#endif
- minT1 = newMinT1;
- maxT1 = newMaxT1;
- } else {
- double newMinT2 = interp(minT2, maxT2, minT);
- double newMaxT2 = interp(minT2, maxT2, maxT);
- split = newMaxT2 - newMinT2 > (maxT2 - minT2) * tClipLimit;
-#if VERBOSE
- printf("%s d=%d s=%d new2=(%g,%g) old2=(%g,%g) split=%d\n",
- __FUNCTION__, depth, splits, newMinT2, newMaxT2, minT2, maxT2,
- split);
-#endif
- minT2 = newMinT2;
- maxT2 = newMaxT2;
- }
- return chop(minT1, maxT1, minT2, maxT2, split);
-}
-
-bool chop(double minT1, double maxT1, double minT2, double maxT2, int split) {
- ++depth;
- intersections.swap();
- if (split) {
- ++splits;
- if (split & 2) {
- double middle1 = (maxT1 + minT1) / 2;
- intersect(minT1, middle1, minT2, maxT2);
- intersect(middle1, maxT1, minT2, maxT2);
- } else {
- double middle2 = (maxT2 + minT2) / 2;
- intersect(minT1, maxT1, minT2, middle2);
- intersect(minT1, maxT1, middle2, maxT2);
- }
- --splits;
- intersections.swap();
- --depth;
- return intersections.intersected();
- }
- bool result = intersect(minT1, maxT1, minT2, maxT2);
- intersections.swap();
- --depth;
- return result;
-}
-
-private:
-
-const Cubic& cubic1;
-const Cubic& cubic2;
-Intersections& intersections;
-int depth;
-int splits;
-};
-
-bool intersect(const Cubic& c1, const Cubic& c2, Intersections& i) {
- CubicIntersections c(c1, c2, i);
- return c.intersect();
-}
diff --git a/experimental/Intersection/CubicIntersection.cpp b/experimental/Intersection/CubicIntersection.cpp
deleted file mode 100644
index 175b7b7c46..0000000000
--- a/experimental/Intersection/CubicIntersection.cpp
+++ /dev/null
@@ -1,471 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "CubicUtilities.h"
-#include "CurveIntersection.h"
-#include "Intersections.h"
-#include "IntersectionUtilities.h"
-#include "LineIntersection.h"
-#include "LineUtilities.h"
-#include "QuadraticUtilities.h"
-#include "TSearch.h"
-
-#if 0
-#undef ONE_OFF_DEBUG
-#define ONE_OFF_DEBUG 0
-#endif
-
-#if ONE_OFF_DEBUG
-static const double tLimits1[2][2] = {{0.36, 0.37}, {0.63, 0.64}};
-static const double tLimits2[2][2] = {{-0.865211397, -0.865215212}, {-0.865207696, -0.865208078}};
-#endif
-
-#define DEBUG_QUAD_PART 0
-#define SWAP_TOP_DEBUG 0
-
-static int quadPart(const Cubic& cubic, double tStart, double tEnd, Quadratic& simple) {
- Cubic part;
- sub_divide(cubic, tStart, tEnd, part);
- Quadratic quad;
- demote_cubic_to_quad(part, quad);
- // FIXME: should reduceOrder be looser in this use case if quartic is going to blow up on an
- // extremely shallow quadratic?
- int order = reduceOrder(quad, simple, kReduceOrder_TreatAsFill);
-#if DEBUG_QUAD_PART
- SkDebugf("%s cubic=(%1.17g,%1.17g %1.17g,%1.17g %1.17g,%1.17g %1.17g,%1.17g) t=(%1.17g,%1.17g)\n",
- __FUNCTION__, cubic[0].x, cubic[0].y, cubic[1].x, cubic[1].y, cubic[2].x, cubic[2].y,
- cubic[3].x, cubic[3].y, tStart, tEnd);
- SkDebugf("%s part=(%1.17g,%1.17g %1.17g,%1.17g %1.17g,%1.17g %1.17g,%1.17g)"
- " quad=(%1.17g,%1.17g %1.17g,%1.17g %1.17g,%1.17g)\n", __FUNCTION__, part[0].x, part[0].y,
- part[1].x, part[1].y, part[2].x, part[2].y, part[3].x, part[3].y, quad[0].x, quad[0].y,
- quad[1].x, quad[1].y, quad[2].x, quad[2].y);
- SkDebugf("%s simple=(%1.17g,%1.17g", __FUNCTION__, simple[0].x, simple[0].y);
- if (order > 1) {
- SkDebugf(" %1.17g,%1.17g", simple[1].x, simple[1].y);
- }
- if (order > 2) {
- SkDebugf(" %1.17g,%1.17g", simple[2].x, simple[2].y);
- }
- SkDebugf(")\n");
- SkASSERT(order < 4 && order > 0);
-#endif
- return order;
-}
-
-static void intersectWithOrder(const Quadratic& simple1, int order1, const Quadratic& simple2,
- int order2, Intersections& i) {
- if (order1 == 3 && order2 == 3) {
- intersect2(simple1, simple2, i);
- } else if (order1 <= 2 && order2 <= 2) {
- intersect((const _Line&) simple1, (const _Line&) simple2, i);
- } else if (order1 == 3 && order2 <= 2) {
- intersect(simple1, (const _Line&) simple2, i);
- } else {
- SkASSERT(order1 <= 2 && order2 == 3);
- intersect(simple2, (const _Line&) simple1, i);
- for (int s = 0; s < i.fUsed; ++s) {
- SkTSwap(i.fT[0][s], i.fT[1][s]);
- }
- }
-}
-
-// this flavor centers potential intersections recursively. In contrast, '2' may inadvertently
-// chase intersections near quadratic ends, requiring odd hacks to find them.
-static bool intersect3(const Cubic& cubic1, double t1s, double t1e, const Cubic& cubic2,
- double t2s, double t2e, double precisionScale, Intersections& i) {
- i.upDepth();
- bool result = false;
- Cubic c1, c2;
- sub_divide(cubic1, t1s, t1e, c1);
- sub_divide(cubic2, t2s, t2e, c2);
- SkTDArray<double> ts1;
- // OPTIMIZE: if c1 == c2, call once (happens when detecting self-intersection)
- cubic_to_quadratics(c1, calcPrecision(c1) * precisionScale, ts1);
- SkTDArray<double> ts2;
- cubic_to_quadratics(c2, calcPrecision(c2) * precisionScale, ts2);
- double t1Start = t1s;
- int ts1Count = ts1.count();
- for (int i1 = 0; i1 <= ts1Count; ++i1) {
- const double tEnd1 = i1 < ts1Count ? ts1[i1] : 1;
- const double t1 = t1s + (t1e - t1s) * tEnd1;
- Quadratic s1;
- int o1 = quadPart(cubic1, t1Start, t1, s1);
- double t2Start = t2s;
- int ts2Count = ts2.count();
- for (int i2 = 0; i2 <= ts2Count; ++i2) {
- const double tEnd2 = i2 < ts2Count ? ts2[i2] : 1;
- const double t2 = t2s + (t2e - t2s) * tEnd2;
- if (cubic1 == cubic2 && t1Start >= t2Start) {
- t2Start = t2;
- continue;
- }
- Quadratic s2;
- int o2 = quadPart(cubic2, t2Start, t2, s2);
- #if ONE_OFF_DEBUG
- char tab[] = " ";
- if (tLimits1[0][0] >= t1Start && tLimits1[0][1] <= t1
- && tLimits1[1][0] >= t2Start && tLimits1[1][1] <= t2) {
- Cubic cSub1, cSub2;
- sub_divide(cubic1, t1Start, t1, cSub1);
- sub_divide(cubic2, t2Start, t2, cSub2);
- SkDebugf("%.*s %s t1=(%1.9g,%1.9g) t2=(%1.9g,%1.9g)", i.depth()*2, tab, __FUNCTION__,
- t1Start, t1, t2Start, t2);
- Intersections xlocals;
- intersectWithOrder(s1, o1, s2, o2, xlocals);
- SkDebugf(" xlocals.fUsed=%d\n", xlocals.used());
- }
- #endif
- Intersections locals;
- intersectWithOrder(s1, o1, s2, o2, locals);
- double coStart[2] = { -1 };
- _Point coPoint;
- int tCount = locals.used();
- for (int tIdx = 0; tIdx < tCount; ++tIdx) {
- double to1 = t1Start + (t1 - t1Start) * locals.fT[0][tIdx];
- double to2 = t2Start + (t2 - t2Start) * locals.fT[1][tIdx];
- // if the computed t is not sufficiently precise, iterate
- _Point p1 = xy_at_t(cubic1, to1);
- _Point p2 = xy_at_t(cubic2, to2);
- if (p1.approximatelyEqual(p2)) {
- if (locals.fIsCoincident[0] & 1 << tIdx) {
- if (coStart[0] < 0) {
- coStart[0] = to1;
- coStart[1] = to2;
- coPoint = p1;
- } else {
- i.insertCoincidentPair(coStart[0], to1, coStart[1], to2, coPoint, p1);
- coStart[0] = -1;
- }
- result = true;
- } else if (cubic1 != cubic2 || !approximately_equal(to1, to2)) {
- if (i.swapped()) { // FIXME: insert should respect swap
- i.insert(to2, to1, p1);
- } else {
- i.insert(to1, to2, p1);
- }
- result = true;
- }
- } else {
- double offset = precisionScale / 16; // FIME: const is arbitrary -- test & refine
-#if 1
- double c1Bottom = tIdx == 0 ? 0 :
- (t1Start + (t1 - t1Start) * locals.fT[0][tIdx - 1] + to1) / 2;
- double c1Min = SkTMax(c1Bottom, to1 - offset);
- double c1Top = tIdx == tCount - 1 ? 1 :
- (t1Start + (t1 - t1Start) * locals.fT[0][tIdx + 1] + to1) / 2;
- double c1Max = SkTMin(c1Top, to1 + offset);
- double c2Min = SkTMax(0., to2 - offset);
- double c2Max = SkTMin(1., to2 + offset);
- #if ONE_OFF_DEBUG
- SkDebugf("%.*s %s 1 contains1=%d/%d contains2=%d/%d\n", i.depth()*2, tab, __FUNCTION__,
- c1Min <= tLimits1[0][1] && tLimits1[0][0] <= c1Max
- && c2Min <= tLimits1[1][1] && tLimits1[1][0] <= c2Max,
- to1 - offset <= tLimits1[0][1] && tLimits1[0][0] <= to1 + offset
- && to2 - offset <= tLimits1[1][1] && tLimits1[1][0] <= to2 + offset,
- c1Min <= tLimits2[0][1] && tLimits2[0][0] <= c1Max
- && c2Min <= tLimits2[1][1] && tLimits2[1][0] <= c2Max,
- to1 - offset <= tLimits2[0][1] && tLimits2[0][0] <= to1 + offset
- && to2 - offset <= tLimits2[1][1] && tLimits2[1][0] <= to2 + offset);
- SkDebugf("%.*s %s 1 c1Bottom=%1.9g c1Top=%1.9g c2Bottom=%1.9g c2Top=%1.9g"
- " 1-o=%1.9g 1+o=%1.9g 2-o=%1.9g 2+o=%1.9g offset=%1.9g\n",
- i.depth()*2, tab, __FUNCTION__, c1Bottom, c1Top, 0., 1.,
- to1 - offset, to1 + offset, to2 - offset, to2 + offset, offset);
- SkDebugf("%.*s %s 1 to1=%1.9g to2=%1.9g c1Min=%1.9g c1Max=%1.9g c2Min=%1.9g"
- " c2Max=%1.9g\n", i.depth()*2, tab, __FUNCTION__, to1, to2, c1Min, c1Max, c2Min, c2Max);
- #endif
- intersect3(cubic1, c1Min, c1Max, cubic2, c2Min, c2Max, offset, i);
- #if ONE_OFF_DEBUG
- SkDebugf("%.*s %s 1 i.used=%d t=%1.9g\n", i.depth()*2, tab, __FUNCTION__, i.used(),
- i.used() > 0 ? i.fT[0][i.used() - 1] : -1);
- #endif
- if (tCount > 1) {
- c1Min = SkTMax(0., to1 - offset);
- c1Max = SkTMin(1., to1 + offset);
- double c2Bottom = tIdx == 0 ? to2 :
- (t2Start + (t2 - t2Start) * locals.fT[1][tIdx - 1] + to2) / 2;
- double c2Top = tIdx == tCount - 1 ? to2 :
- (t2Start + (t2 - t2Start) * locals.fT[1][tIdx + 1] + to2) / 2;
- if (c2Bottom > c2Top) {
- SkTSwap(c2Bottom, c2Top);
- }
- if (c2Bottom == to2) {
- c2Bottom = 0;
- }
- if (c2Top == to2) {
- c2Top = 1;
- }
- c2Min = SkTMax(c2Bottom, to2 - offset);
- c2Max = SkTMin(c2Top, to2 + offset);
- #if ONE_OFF_DEBUG
- SkDebugf("%.*s %s 2 contains1=%d/%d contains2=%d/%d\n", i.depth()*2, tab, __FUNCTION__,
- c1Min <= tLimits1[0][1] && tLimits1[0][0] <= c1Max
- && c2Min <= tLimits1[1][1] && tLimits1[1][0] <= c2Max,
- to1 - offset <= tLimits1[0][1] && tLimits1[0][0] <= to1 + offset
- && to2 - offset <= tLimits1[1][1] && tLimits1[1][0] <= to2 + offset,
- c1Min <= tLimits2[0][1] && tLimits2[0][0] <= c1Max
- && c2Min <= tLimits2[1][1] && tLimits2[1][0] <= c2Max,
- to1 - offset <= tLimits2[0][1] && tLimits2[0][0] <= to1 + offset
- && to2 - offset <= tLimits2[1][1] && tLimits2[1][0] <= to2 + offset);
- SkDebugf("%.*s %s 2 c1Bottom=%1.9g c1Top=%1.9g c2Bottom=%1.9g c2Top=%1.9g"
- " 1-o=%1.9g 1+o=%1.9g 2-o=%1.9g 2+o=%1.9g offset=%1.9g\n",
- i.depth()*2, tab, __FUNCTION__, 0., 1., c2Bottom, c2Top,
- to1 - offset, to1 + offset, to2 - offset, to2 + offset, offset);
- SkDebugf("%.*s %s 2 to1=%1.9g to2=%1.9g c1Min=%1.9g c1Max=%1.9g c2Min=%1.9g"
- " c2Max=%1.9g\n", i.depth()*2, tab, __FUNCTION__, to1, to2, c1Min, c1Max, c2Min, c2Max);
- #endif
- intersect3(cubic1, c1Min, c1Max, cubic2, c2Min, c2Max, offset, i);
- #if ONE_OFF_DEBUG
- SkDebugf("%.*s %s 2 i.used=%d t=%1.9g\n", i.depth()*2, tab, __FUNCTION__, i.used(),
- i.used() > 0 ? i.fT[0][i.used() - 1] : -1);
- #endif
- c1Min = SkTMax(c1Bottom, to1 - offset);
- c1Max = SkTMin(c1Top, to1 + offset);
- #if ONE_OFF_DEBUG
- SkDebugf("%.*s %s 3 contains1=%d/%d contains2=%d/%d\n", i.depth()*2, tab, __FUNCTION__,
- c1Min <= tLimits1[0][1] && tLimits1[0][0] <= c1Max
- && c2Min <= tLimits1[1][1] && tLimits1[1][0] <= c2Max,
- to1 - offset <= tLimits1[0][1] && tLimits1[0][0] <= to1 + offset
- && to2 - offset <= tLimits1[1][1] && tLimits1[1][0] <= to2 + offset,
- c1Min <= tLimits2[0][1] && tLimits2[0][0] <= c1Max
- && c2Min <= tLimits2[1][1] && tLimits2[1][0] <= c2Max,
- to1 - offset <= tLimits2[0][1] && tLimits2[0][0] <= to1 + offset
- && to2 - offset <= tLimits2[1][1] && tLimits2[1][0] <= to2 + offset);
- SkDebugf("%.*s %s 3 c1Bottom=%1.9g c1Top=%1.9g c2Bottom=%1.9g c2Top=%1.9g"
- " 1-o=%1.9g 1+o=%1.9g 2-o=%1.9g 2+o=%1.9g offset=%1.9g\n",
- i.depth()*2, tab, __FUNCTION__, 0., 1., c2Bottom, c2Top,
- to1 - offset, to1 + offset, to2 - offset, to2 + offset, offset);
- SkDebugf("%.*s %s 3 to1=%1.9g to2=%1.9g c1Min=%1.9g c1Max=%1.9g c2Min=%1.9g"
- " c2Max=%1.9g\n", i.depth()*2, tab, __FUNCTION__, to1, to2, c1Min, c1Max, c2Min, c2Max);
- #endif
- intersect3(cubic1, c1Min, c1Max, cubic2, c2Min, c2Max, offset, i);
- #if ONE_OFF_DEBUG
- SkDebugf("%.*s %s 3 i.used=%d t=%1.9g\n", i.depth()*2, tab, __FUNCTION__, i.used(),
- i.used() > 0 ? i.fT[0][i.used() - 1] : -1);
- #endif
- }
-#else
- double c1Bottom = tIdx == 0 ? 0 :
- (t1Start + (t1 - t1Start) * locals.fT[0][tIdx - 1] + to1) / 2;
- double c1Min = SkTMax(c1Bottom, to1 - offset);
- double c1Top = tIdx == tCount - 1 ? 1 :
- (t1Start + (t1 - t1Start) * locals.fT[0][tIdx + 1] + to1) / 2;
- double c1Max = SkTMin(c1Top, to1 + offset);
- double c2Bottom = tIdx == 0 ? to2 :
- (t2Start + (t2 - t2Start) * locals.fT[1][tIdx - 1] + to2) / 2;
- double c2Top = tIdx == tCount - 1 ? to2 :
- (t2Start + (t2 - t2Start) * locals.fT[1][tIdx + 1] + to2) / 2;
- if (c2Bottom > c2Top) {
- SkTSwap(c2Bottom, c2Top);
- }
- if (c2Bottom == to2) {
- c2Bottom = 0;
- }
- if (c2Top == to2) {
- c2Top = 1;
- }
- double c2Min = SkTMax(c2Bottom, to2 - offset);
- double c2Max = SkTMin(c2Top, to2 + offset);
- #if ONE_OFF_DEBUG
- SkDebugf("%s contains1=%d/%d contains2=%d/%d\n", __FUNCTION__,
- c1Min <= 0.210357794 && 0.210357794 <= c1Max
- && c2Min <= 0.223476406 && 0.223476406 <= c2Max,
- to1 - offset <= 0.210357794 && 0.210357794 <= to1 + offset
- && to2 - offset <= 0.223476406 && 0.223476406 <= to2 + offset,
- c1Min <= 0.211324707 && 0.211324707 <= c1Max
- && c2Min <= 0.211327209 && 0.211327209 <= c2Max,
- to1 - offset <= 0.211324707 && 0.211324707 <= to1 + offset
- && to2 - offset <= 0.211327209 && 0.211327209 <= to2 + offset);
- SkDebugf("%s c1Bottom=%1.9g c1Top=%1.9g c2Bottom=%1.9g c2Top=%1.9g"
- " 1-o=%1.9g 1+o=%1.9g 2-o=%1.9g 2+o=%1.9g offset=%1.9g\n",
- __FUNCTION__, c1Bottom, c1Top, c2Bottom, c2Top,
- to1 - offset, to1 + offset, to2 - offset, to2 + offset, offset);
- SkDebugf("%s to1=%1.9g to2=%1.9g c1Min=%1.9g c1Max=%1.9g c2Min=%1.9g"
- " c2Max=%1.9g\n", __FUNCTION__, to1, to2, c1Min, c1Max, c2Min, c2Max);
- #endif
-#endif
- intersect3(cubic1, c1Min, c1Max, cubic2, c2Min, c2Max, offset, i);
- // TODO: if no intersection is found, either quadratics intersected where
- // cubics did not, or the intersection was missed. In the former case, expect
- // the quadratics to be nearly parallel at the point of intersection, and check
- // for that.
- }
- }
- SkASSERT(coStart[0] == -1);
- t2Start = t2;
- }
- t1Start = t1;
- }
- i.downDepth();
- return result;
-}
-
-#if 0
-#define LINE_FRACTION (1.0 / gPrecisionUnit)
-#else
-#define LINE_FRACTION 0.1
-#endif
-
-// intersect the end of the cubic with the other. Try lines from the end to control and opposite
-// end to determine range of t on opposite cubic.
-static bool intersectEnd(const Cubic& cubic1, bool start, const Cubic& cubic2, const _Rect& bounds2,
- Intersections& i) {
- // bool selfIntersect = cubic1 == cubic2;
- _Line line;
- int t1Index = start ? 0 : 3;
- line[0] = cubic1[t1Index];
- // don't bother if the two cubics are connnected
-#if 0
- if (!selfIntersect && (line[0].approximatelyEqual(cubic2[0])
- || line[0].approximatelyEqual(cubic2[3]))) {
- return false;
- }
-#endif
- bool result = false;
- SkTDArray<double> tVals; // OPTIMIZE: replace with hard-sized array
- for (int index = 0; index < 4; ++index) {
- if (index == t1Index) {
- continue;
- }
- _Vector dxy1 = cubic1[index] - line[0];
- dxy1 /= gPrecisionUnit;
- line[1] = line[0] + dxy1;
- _Rect lineBounds;
- lineBounds.setBounds(line);
- if (!bounds2.intersects(lineBounds)) {
- continue;
- }
- Intersections local;
- if (!intersect(cubic2, line, local)) {
- continue;
- }
- for (int idx2 = 0; idx2 < local.used(); ++idx2) {
- double foundT = local.fT[0][idx2];
- if (approximately_less_than_zero(foundT)
- || approximately_greater_than_one(foundT)) {
- continue;
- }
- if (local.fPt[idx2].approximatelyEqual(line[0])) {
- if (i.swapped()) { // FIXME: insert should respect swap
- i.insert(foundT, start ? 0 : 1, line[0]);
- } else {
- i.insert(start ? 0 : 1, foundT, line[0]);
- }
- result = true;
- } else {
- *tVals.append() = local.fT[0][idx2];
- }
- }
- }
- if (tVals.count() == 0) {
- return result;
- }
- QSort<double>(tVals.begin(), tVals.end() - 1);
- double tMin1 = start ? 0 : 1 - LINE_FRACTION;
- double tMax1 = start ? LINE_FRACTION : 1;
- int tIdx = 0;
- do {
- int tLast = tIdx;
- while (tLast + 1 < tVals.count() && roughly_equal(tVals[tLast + 1], tVals[tIdx])) {
- ++tLast;
- }
- double tMin2 = SkTMax(tVals[tIdx] - LINE_FRACTION, 0.0);
- double tMax2 = SkTMin(tVals[tLast] + LINE_FRACTION, 1.0);
- int lastUsed = i.used();
- result |= intersect3(cubic1, tMin1, tMax1, cubic2, tMin2, tMax2, 1, i);
- if (lastUsed == i.used()) {
- tMin2 = SkTMax(tVals[tIdx] - (1.0 / gPrecisionUnit), 0.0);
- tMax2 = SkTMin(tVals[tLast] + (1.0 / gPrecisionUnit), 1.0);
- result |= intersect3(cubic1, tMin1, tMax1, cubic2, tMin2, tMax2, 1, i);
- }
- tIdx = tLast + 1;
- } while (tIdx < tVals.count());
- return result;
-}
-
-const double CLOSE_ENOUGH = 0.001;
-
-static bool closeStart(const Cubic& cubic, int cubicIndex, Intersections& i, _Point& pt) {
- if (i.fT[cubicIndex][0] != 0 || i.fT[cubicIndex][1] > CLOSE_ENOUGH) {
- return false;
- }
- pt = xy_at_t(cubic, (i.fT[cubicIndex][0] + i.fT[cubicIndex][1]) / 2);
- return true;
-}
-
-static bool closeEnd(const Cubic& cubic, int cubicIndex, Intersections& i, _Point& pt) {
- int last = i.used() - 1;
- if (i.fT[cubicIndex][last] != 1 || i.fT[cubicIndex][last - 1] < 1 - CLOSE_ENOUGH) {
- return false;
- }
- pt = xy_at_t(cubic, (i.fT[cubicIndex][last] + i.fT[cubicIndex][last - 1]) / 2);
- return true;
-}
-
-bool intersect3(const Cubic& c1, const Cubic& c2, Intersections& i) {
- bool result = intersect3(c1, 0, 1, c2, 0, 1, 1, i);
- // FIXME: pass in cached bounds from caller
- _Rect c1Bounds, c2Bounds;
- c1Bounds.setBounds(c1); // OPTIMIZE use setRawBounds ?
- c2Bounds.setBounds(c2);
- result |= intersectEnd(c1, false, c2, c2Bounds, i);
- result |= intersectEnd(c1, true, c2, c2Bounds, i);
- bool selfIntersect = c1 == c2;
- if (!selfIntersect) {
- i.swap();
- result |= intersectEnd(c2, false, c1, c1Bounds, i);
- result |= intersectEnd(c2, true, c1, c1Bounds, i);
- i.swap();
- }
- // If an end point and a second point very close to the end is returned, the second
- // point may have been detected because the approximate quads
- // intersected at the end and close to it. Verify that the second point is valid.
- if (i.used() <= 1 || i.coincidentUsed()) {
- return result;
- }
- _Point pt[2];
- if (closeStart(c1, 0, i, pt[0]) && closeStart(c2, 1, i, pt[1])
- && pt[0].approximatelyEqual(pt[1])) {
- i.removeOne(1);
- }
- if (closeEnd(c1, 0, i, pt[0]) && closeEnd(c2, 1, i, pt[1])
- && pt[0].approximatelyEqual(pt[1])) {
- i.removeOne(i.used() - 2);
- }
- return result;
-}
-
-// Up promote the quad to a cubic.
-// OPTIMIZATION If this is a common use case, optimize by duplicating
-// the intersect 3 loop to avoid the promotion / demotion code
-int intersect(const Cubic& cubic, const Quadratic& quad, Intersections& i) {
- Cubic up;
- toCubic(quad, up);
- (void) intersect3(cubic, up, i);
- return i.used();
-}
-
-/* http://www.ag.jku.at/compass/compasssample.pdf
-( Self-Intersection Problems and Approximate Implicitization by Jan B. Thomassen
-Centre of Mathematics for Applications, University of Oslo http://www.cma.uio.no janbth@math.uio.no
-SINTEF Applied Mathematics http://www.sintef.no )
-describes a method to find the self intersection of a cubic by taking the gradient of the implicit
-form dotted with the normal, and solving for the roots. My math foo is too poor to implement this.*/
-
-int intersect(const Cubic& c, Intersections& i) {
- // check to see if x or y end points are the extrema. Are other quick rejects possible?
- if (ends_are_extrema_in_x_or_y(c)) {
- return false;
- }
- (void) intersect3(c, c, i);
- if (i.used() > 0) {
- SkASSERT(i.used() == 1);
- if (i.fT[0][0] > i.fT[1][0]) {
- SkTSwap(i.fT[0][0], i.fT[1][0]);
- }
- }
- return i.used();
-}
diff --git a/experimental/Intersection/CubicIntersection_Test.cpp b/experimental/Intersection/CubicIntersection_Test.cpp
deleted file mode 100644
index b43001bcb8..0000000000
--- a/experimental/Intersection/CubicIntersection_Test.cpp
+++ /dev/null
@@ -1,778 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "CurveIntersection.h"
-#include "CurveUtilities.h"
-#include "CubicIntersection_TestData.h"
-#include "Intersection_Tests.h"
-#include "Intersections.h"
-#include "TestUtilities.h"
-
-#define SHOW_ORIGINAL 1
-
-const int firstCubicIntersectionTest = 9;
-
-static void standardTestCases() {
- for (size_t index = firstCubicIntersectionTest; index < tests_count; ++index) {
- const Cubic& cubic1 = tests[index][0];
- const Cubic& cubic2 = tests[index][1];
- Cubic reduce1, reduce2;
- int order1 = reduceOrder(cubic1, reduce1, kReduceOrder_NoQuadraticsAllowed,
- kReduceOrder_TreatAsFill);
- int order2 = reduceOrder(cubic2, reduce2, kReduceOrder_NoQuadraticsAllowed,
- kReduceOrder_TreatAsFill);
- if (order1 < 4) {
- printf("%s [%d] cubic1 order=%d\n", __FUNCTION__, (int) index, order1);
- continue;
- }
- if (order2 < 4) {
- printf("%s [%d] cubic2 order=%d\n", __FUNCTION__, (int) index, order2);
- continue;
- }
- if (implicit_matches(reduce1, reduce2)) {
- printf("%s [%d] coincident\n", __FUNCTION__, (int) index);
- continue;
- }
- Intersections tIntersections;
- intersect(reduce1, reduce2, tIntersections);
- if (!tIntersections.intersected()) {
- printf("%s [%d] no intersection\n", __FUNCTION__, (int) index);
- continue;
- }
- for (int pt = 0; pt < tIntersections.used(); ++pt) {
- double tt1 = tIntersections.fT[0][pt];
- double tx1, ty1;
- xy_at_t(cubic1, tt1, tx1, ty1);
- double tt2 = tIntersections.fT[1][pt];
- double tx2, ty2;
- xy_at_t(cubic2, tt2, tx2, ty2);
- if (!AlmostEqualUlps(tx1, tx2)) {
- printf("%s [%d,%d] x!= t1=%g (%g,%g) t2=%g (%g,%g)\n",
- __FUNCTION__, (int)index, pt, tt1, tx1, ty1, tt2, tx2, ty2);
- }
- if (!AlmostEqualUlps(ty1, ty2)) {
- printf("%s [%d,%d] y!= t1=%g (%g,%g) t2=%g (%g,%g)\n",
- __FUNCTION__, (int)index, pt, tt1, tx1, ty1, tt2, tx2, ty2);
- }
- }
- }
-}
-
-static const Cubic testSet[] = {
-{{67.426548091427676, 37.993772624988935}, {23.483695892376684, 90.476863174921306}, {35.597065061143162, 79.872482633158796}, {75.38634169631932, 18.244890038969412}},
-{{67.4265481, 37.9937726}, {23.4836959, 90.4768632}, {35.5970651, 79.8724826}, {75.3863417, 18.24489}},
-
-{{0, 0}, {0, 1}, {1, 1}, {1, 0}},
-{{1, 0}, {0, 0}, {0, 1}, {1, 1}},
-
-{{0,1}, {4,5}, {1,0}, {5,3}},
-{{0,1}, {3,5}, {1,0}, {5,4}},
-
-{{0, 1}, {1, 6}, {1, 0}, {1, 0}},
-{{0, 1}, {0, 1}, {1, 0}, {6, 1}},
-
-{{0,1}, {3,4}, {1,0}, {5,1}},
-{{0,1}, {1,5}, {1,0}, {4,3}},
-
-{{0,1}, {1,2}, {1,0}, {6,1}},
-{{0,1}, {1,6}, {1,0}, {2,1}},
-
-{{0,1}, {0,5}, {1,0}, {4,0}},
-{{0,1}, {0,4}, {1,0}, {5,0}},
-
-{{0,1}, {3,4}, {1,0}, {3,0}},
-{{0,1}, {0,3}, {1,0}, {4,3}},
-
-{{0, 0}, {1, 2}, {3, 4}, {4, 4}},
-{{0, 0}, {1, 2}, {3, 4}, {4, 4}},
-{{4, 4}, {3, 4}, {1, 2}, {0, 0}},
-
-{{0,1}, {2,3}, {1,0}, {1,0}},
-{{0,1}, {0,1}, {1,0}, {3,2}},
-
-{{0,2}, {0,1}, {1,0}, {1,0}},
-{{0,1}, {0,1}, {2,0}, {1,0}},
-
-{{0, 1}, {0, 2}, {1, 0}, {1, 0}},
-{{0, 1}, {0, 1}, {1, 0}, {2, 0}},
-
-{{0, 1}, {1, 6}, {1, 0}, {2, 0}},
-{{0, 1}, {0, 2}, {1, 0}, {6, 1}},
-
-{{0, 1}, {5, 6}, {1, 0}, {1, 0}},
-{{0, 1}, {0, 1}, {1, 0}, {6, 5}},
-
-{{95.837747722788592, 45.025976907939643}, {16.564570095652982, 0.72959763963222402}, {63.209855865319199, 68.047528419665767}, {57.640240647662544, 59.524565264361243}},
-{{51.593891741518817, 38.53849970667553}, {62.34752929878772, 74.924924725166022}, {74.810149322641152, 34.17966562983564}, {29.368398119401373, 94.66719277886078}},
-
-{{39.765160968417838, 33.060396198677083}, {5.1922921581157908, 66.854301452103215}, {31.619281802149157, 25.269248720849514}, {81.541621071073038, 70.025341524754353}},
-{{46.078911165743556, 48.259962651999651}, {20.24450549867214, 49.403916182650214}, {0.26325131778756683, 24.46489805563581}, {15.915006546264051, 83.515023059917155}},
-
-{{65.454505973241524, 93.881892270353575}, {45.867360264932437, 92.723972719499827}, {2.1464054482739447, 74.636369140183717}, {33.774068594804994, 40.770872887582925}},
-{{72.963387832494163, 95.659300729473728}, {11.809496633619768, 82.209921247423594}, {13.456139067865974, 57.329313623406605}, {36.060621606214262, 70.867335643091849}},
-
-{{32.484981432782945, 75.082940782924624}, {42.467313093350882, 48.131159948246157}, {3.5963115764764657, 43.208665839959245}, {79.442476890721579, 89.709102357602262}},
-{{18.98573861410177, 93.308887208490106}, {40.405250173250792, 91.039661826118675}, {8.0467721950480584, 42.100282172719147}, {40.883324221187891, 26.030185504830527}},
-
-{{7.5374809128872498, 82.441702896003477}, {22.444346930107265, 22.138854312775123}, {66.76091829629658, 50.753805856571446}, {78.193478508942519, 97.7932997968948}},
-{{97.700573130371311, 53.53260215070685}, {87.72443481149358, 84.575876772671876}, {19.215031396232092, 47.032676472809484}, {11.989686410869325, 10.659507480757082}},
-
-{{26.192053931854691, 9.8504326817814416}, {10.174241480498686, 98.476562741434464}, {21.177712558385782, 33.814968789841501}, {75.329030899018534, 55.02231980442177}},
-{{56.222082700683771, 24.54395039218662}, {95.589995289030483, 81.050822735322086}, {28.180450866082897, 28.837706255185282}, {60.128952916771617, 87.311672180570511}},
-
-{{42.449716172390481, 52.379709366885805}, {27.896043159019225, 48.797373636065686}, {92.770268299044233, 89.899302036454571}, {12.102066544863426, 99.43241951960718}},
-{{45.77532924980639, 45.958701495993274}, {37.458701356062065, 68.393691335056758}, {37.569326692060258, 27.673713456687381}, {60.674866037757539, 62.47349659096146}},
-
-{{67.426548091427676, 37.993772624988935}, {23.483695892376684, 90.476863174921306}, {35.597065061143162, 79.872482633158796}, {75.38634169631932, 18.244890038969412}},
-{{61.336508189019057, 82.693132843213675}, {44.639380902349664, 54.074825790745592}, {16.815615499771951, 20.049704667203923}, {41.866884958868326, 56.735503699973002}},
-
-{{67.4265481, 37.9937726}, {23.4836959, 90.4768632}, {35.5970651, 79.8724826}, {75.3863417, 18.24489}},
-{{61.3365082, 82.6931328}, {44.6393809, 54.0748258}, {16.8156155, 20.0497047}, {41.866885, 56.7355037}},
-
-{{18.1312339, 31.6473732}, {95.5711034, 63.5350219}, {92.3283165, 62.0158945}, {18.5656052, 32.1268808}},
-{{97.402018, 35.7169972}, {33.1127443, 25.8935163}, {1.13970027, 54.9424981}, {56.4860195, 60.529264}},
-};
-
-const size_t testSetCount = sizeof(testSet) / sizeof(testSet[0]);
-
-static const Cubic newTestSet[] = {
-{{1,3}, {5,6}, {5,3}, {5,4}},
-{{3,5}, {4,5}, {3,1}, {6,5}},
-
-{{0,5}, {0,5}, {5,4}, {6,4}},
-{{4,5}, {4,6}, {5,0}, {5,0}},
-
-{{0,4}, {1,3}, {5,4}, {4,2}},
-{{4,5}, {2,4}, {4,0}, {3,1}},
-
-{{0,2}, {1,5}, {3,2}, {4,1}},
-{{2,3}, {1,4}, {2,0}, {5,1}},
-
-{{0,2}, {2,3}, {5,1}, {3,2}},
-{{1,5}, {2,3}, {2,0}, {3,2}},
-
-{{2,6}, {4,5}, {1,0}, {6,1}},
-{{0,1}, {1,6}, {6,2}, {5,4}},
-
-{{0,1}, {1,2}, {6,5}, {5,4}},
-{{5,6}, {4,5}, {1,0}, {2,1}},
-
-{{2.5119999999999996, 1.5710000000000002}, {2.6399999999999983, 1.6599999999999997}, {2.8000000000000007, 1.8000000000000003}, {3, 2}},
-{{2.4181876227114887, 1.9849772580462195}, {2.8269904869227211, 2.009330650246834}, {3.2004679292461624, 1.9942047174679169}, {3.4986199496818058, 2.0035994597094731}},
-
-{{2,3}, {1,4}, {1,0}, {6,0}},
-{{0,1}, {0,6}, {3,2}, {4,1}},
-
-{{0,2}, {1,5}, {1,0}, {6,1}},
-{{0,1}, {1,6}, {2,0}, {5,1}},
-
-{{0,1}, {1,5}, {2,1}, {4,0}},
-{{1,2}, {0,4}, {1,0}, {5,1}},
-
-{{0,1}, {3,5}, {2,1}, {3,1}},
-{{1,2}, {1,3}, {1,0}, {5,3}},
-
-{{0,1}, {2,5}, {6,0}, {5,3}},
-{{0,6}, {3,5}, {1,0}, {5,2}},
-
-{{0,1}, {3,6}, {1,0}, {5,2}},
-{{0,1}, {2,5}, {1,0}, {6,3}},
-
-{{1,2},{5,6},{1,0},{1,0}},
-{{0,1},{0,1},{2,1},{6,5}},
-
-{{0,6},{1,2},{1,0},{1,0}},
-{{0,1},{0,1},{6,0},{2,1}},
-
-{{0,2},{0,1},{3,0},{1,0}},
-{{0,3},{0,1},{2,0},{1,0}},
-};
-
-const size_t newTestSetCount = sizeof(newTestSet) / sizeof(newTestSet[0]);
-
-#if 0
-static void oneOff(const Cubic& cubic1, const Cubic& cubic2) {
- SkTDArray<Quadratic> quads1;
- cubic_to_quadratics(cubic1, calcPrecision(cubic1), quads1);
-#if SHOW_ORIGINAL
- SkDebugf("computed quadratics given\n");
- SkDebugf(" {{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}}, {%1.9g,%1.9g}},\n",
- cubic1[0].x, cubic1[0].y, cubic1[1].x, cubic1[1].y,
- cubic1[2].x, cubic1[2].y, cubic1[3].x, cubic1[3].y));
- SkDebugf(" {{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}}, {%1.9g,%1.9g}},\n",
- cubic2[0].x, cubic2[0].y, cubic2[1].x, cubic2[1].y,
- cubic2[2].x, cubic2[2].y, cubic2[3].x, cubic2[3].y));
-#endif
-#if ONE_OFF_DEBUG
- SkDebugf("computed quadratics set 1\n");
- for (int index = 0; index < quads1.count(); ++index) {
- const Quadratic& q = quads1[index];
- SkDebugf(" {{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}},\n", q[0].x, q[0].y,
- q[1].x, q[1].y, q[2].x, q[2].y);
- }
-#endif
- SkTDArray<Quadratic> quads2;
- cubic_to_quadratics(cubic2, calcPrecision(cubic2), quads2);
-#if ONE_OFF_DEBUG
- SkDebugf("computed quadratics set 2\n");
- for (int index = 0; index < quads2.count(); ++index) {
- const Quadratic& q = quads2[index];
- SkDebugf(" {{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}},\n", q[0].x, q[0].y,
- q[1].x, q[1].y, q[2].x, q[2].y);
- }
-#endif
- Intersections intersections2, intersections3;
- intersect2(cubic1, cubic2, intersections2);
- intersect3(cubic1, cubic2, intersections3);
- int pt1, pt2, pt3;
- bool found;
- double tt1, tt2, last = -1;
- _Point xy1, xy2;
- for (pt1 = 0; pt1 < intersections2.used(); ++pt1) {
- tt1 = intersections2.fT[0][pt1];
- SkASSERT(!approximately_equal(last, tt1));
- last = tt1;
- xy_at_t(cubic1, tt1, xy1.x, xy1.y);
- pt2 = intersections2.fFlip ? intersections2.used() - pt1 - 1 : pt1;
- tt2 = intersections2.fT[1][pt2];
- xy_at_t(cubic2, tt2, xy2.x, xy2.y);
-#if ONE_OFF_DEBUG
- SkDebugf("%s t1=%1.9g (%1.9g, %1.9g) (%1.9g, %1.9g) (%1.9g, %1.9g) t2=%1.9g\n",
- __FUNCTION__, tt1, xy1.x, xy1.y, intersections2.fPt[pt1].x,
- intersections2.fPt[pt1].y, xy2.x, xy2.y, tt2);
-#endif
- SkASSERT(xy1.approximatelyEqual(xy2));
-#ifdef SK_DEBUG
- found = false;
- for (pt3 = 0; pt3 < intersections3.used(); ++pt3) {
- if (roughly_equal(tt1, intersections3.fT[0][pt3])) {
- found = true;
- break;
- }
- }
- SkASSERT(found);
-#endif
- }
- last = -1;
- for (pt3 = 0; pt3 < intersections3.used(); ++pt3) {
- found = false;
- double tt3 = intersections3.fT[0][pt3];
- SkASSERT(!approximately_equal(last, tt3));
- last = tt3;
- for (pt1 = 0; pt1 < intersections2.used(); ++pt1) {
- if (approximately_equal(tt3, intersections2.fT[0][pt1])) {
- found = true;
- break;
- }
- }
- if (!found) {
- tt1 = intersections3.fT[0][pt3];
- xy_at_t(cubic1, tt1, xy1.x, xy1.y);
- pt2 = intersections3.fFlip ? intersections3.used() - pt3 - 1 : pt3;
- tt2 = intersections3.fT[1][pt2];
- xy_at_t(cubic2, tt2, xy2.x, xy2.y);
- #if ONE_OFF_DEBUG
- SkDebugf("%s t1=%1.9g (%1.9g, %1.9g) (%1.9g, %1.9g) (%1.9g, %1.9g) t2=%1.9g\n",
- __FUNCTION__, tt1, xy1.x, xy1.y, intersections3.fPt[pt1].x,
- intersections3.fPt[pt1].y, xy2.x, xy2.y, tt2);
- #endif
- SkASSERT(xy1.approximatelyEqual(xy2));
- SkDebugf("%s missing in intersect2\n", __FUNCTION__);
- }
- }
-}
-#endif
-
-static void oneOff3(const Cubic& cubic1, const Cubic& cubic2) {
-#if ONE_OFF_DEBUG
- SkDebugf("computed quadratics given\n");
- SkDebugf(" {{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}},\n",
- cubic1[0].x, cubic1[0].y, cubic1[1].x, cubic1[1].y,
- cubic1[2].x, cubic1[2].y, cubic1[3].x, cubic1[3].y);
- SkDebugf(" {{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}},\n",
- cubic2[0].x, cubic2[0].y, cubic2[1].x, cubic2[1].y,
- cubic2[2].x, cubic2[2].y, cubic2[3].x, cubic2[3].y);
-#endif
- SkTDArray<Quadratic> quads1;
- cubic_to_quadratics(cubic1, calcPrecision(cubic1), quads1);
-#if ONE_OFF_DEBUG
- SkDebugf("computed quadratics set 1\n");
- for (int index = 0; index < quads1.count(); ++index) {
- const Quadratic& q = quads1[index];
- SkDebugf(" {{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}},\n", q[0].x, q[0].y,
- q[1].x, q[1].y, q[2].x, q[2].y);
- }
-#endif
- SkTDArray<Quadratic> quads2;
- cubic_to_quadratics(cubic2, calcPrecision(cubic2), quads2);
-#if ONE_OFF_DEBUG
- SkDebugf("computed quadratics set 2\n");
- for (int index = 0; index < quads2.count(); ++index) {
- const Quadratic& q = quads2[index];
- SkDebugf(" {{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}},\n", q[0].x, q[0].y,
- q[1].x, q[1].y, q[2].x, q[2].y);
- }
-#endif
- Intersections intersections3;
- intersect3(cubic1, cubic2, intersections3);
- int pt2, pt3;
- double tt1, tt2, last = -1;
- _Point xy1, xy2;
- for (pt3 = 0; pt3 < intersections3.used(); ++pt3) {
- double tt3 = intersections3.fT[0][pt3];
- // SkASSERT(!approximately_equal(last, tt3));
- last = tt3;
- tt1 = intersections3.fT[0][pt3];
- xy_at_t(cubic1, tt1, xy1.x, xy1.y);
- pt2 = intersections3.fFlip ? intersections3.used() - pt3 - 1 : pt3;
- tt2 = intersections3.fT[1][pt2];
- xy_at_t(cubic2, tt2, xy2.x, xy2.y);
-#if ONE_OFF_DEBUG
- SkDebugf("%s t1=%1.9g (%1.9g, %1.9g) (%1.9g, %1.9g) (%1.9g, %1.9g) t2=%1.9g\n",
- __FUNCTION__, tt1, xy1.x, xy1.y, intersections3.fPt[pt3].x,
- intersections3.fPt[pt3].y, xy2.x, xy2.y, tt2);
-#endif
- SkASSERT(xy1.approximatelyEqual(xy2));
- }
-}
-
-#if 0
-static int fails[][2] = { {0, 23}, // fails in intersect2 recursing
- {2, 7}, // answers differ, but neither is correct ('3' is closer)
- {3, 26}, // fails in intersect2 recursing
- {4, 9}, // fails in intersect2 recursing
- {4, 10}, // fails in intersect2 recursing
- {10, 17}, // fails in intersect2 recursing
- {12, 14}, // loops indefinitely
- {12, 21}, // fails in intersect2 recursing
- {13, 21}, // fails in intersect2 recursing
- {14, 21}, // fails in intersect2 recursing
- {17, 25}, // fails in intersect2 recursing
- {23, 25}, // fails in intersect2 recursing
-};
-
-static int failCount = sizeof(fails) / sizeof(fails[0]);
-#endif
-
-static void oneOff(int outer, int inner) {
- const Cubic& cubic1 = testSet[outer];
- const Cubic& cubic2 = testSet[inner];
-#if 0
- bool failing = false;
- for (int i = 0; i < failCount; ++i) {
- if ((fails[i][0] == outer && fails[i][1] == inner)
- || (fails[i][1] == outer && fails[i][0] == inner)) {
- failing = true;
- break;
- }
- }
- if (!failing) {
- oneOff(cubic1, cubic2);
- } else {
-#endif
- oneOff3(cubic1, cubic2);
-// }
-}
-
-void CubicIntersection_OneOffTest() {
- oneOff(0, 1);
-}
-
-static void newOneOff(int outer, int inner) {
- const Cubic& cubic1 = newTestSet[outer];
- const Cubic& cubic2 = newTestSet[inner];
- oneOff3(cubic1, cubic2);
-}
-
-void CubicIntersection_NewOneOffTest() {
- newOneOff(0, 1);
-}
-
-static void oneOffTests() {
- for (size_t outer = 0; outer < testSetCount - 1; ++outer) {
- for (size_t inner = outer + 1; inner < testSetCount; ++inner) {
- oneOff(outer, inner);
- }
- }
-}
-
-void CubicIntersection_OneOffTests() {
- oneOffTests();
-}
-
-#define DEBUG_CRASH 0
-
-class CubicChopper {
-public:
-
-// only finds one intersection
-CubicChopper(const Cubic& c1, const Cubic& c2)
- : cubic1(c1)
- , cubic2(c2)
- , depth(0) {
-}
-
-bool intersect(double minT1, double maxT1, double minT2, double maxT2) {
- Cubic sub1, sub2;
- // FIXME: carry last subdivide and reduceOrder result with cubic
- sub_divide(cubic1, minT1, maxT1, sub1);
- sub_divide(cubic2, minT2, maxT2, sub2);
- Intersections i;
- intersect3(sub1, sub2, i);
- if (i.used() == 0) {
- return false;
- }
- double x1, y1, x2, y2;
- t1 = minT1 + i.fT[0][0] * (maxT1 - minT1);
- t2 = minT2 + i.fT[1][0] * (maxT2 - minT2);
- xy_at_t(cubic1, t1, x1, y1);
- xy_at_t(cubic2, t2, x2, y2);
- if (AlmostEqualUlps(x1, x2) && AlmostEqualUlps(y1, y2)) {
- return true;
- }
- double half1 = (minT1 + maxT1) / 2;
- double half2 = (minT2 + maxT2) / 2;
- ++depth;
- bool result;
- if (depth & 1) {
- result = intersect(minT1, half1, minT2, maxT2) || intersect(half1, maxT1, minT2, maxT2)
- || intersect(minT1, maxT1, minT2, half2) || intersect(minT1, maxT1, half2, maxT2);
- } else {
- result = intersect(minT1, maxT1, minT2, half2) || intersect(minT1, maxT1, half2, maxT2)
- || intersect(minT1, half1, minT2, maxT2) || intersect(half1, maxT1, minT2, maxT2);
- }
- --depth;
- return result;
-}
-
-const Cubic& cubic1;
-const Cubic& cubic2;
-double t1;
-double t2;
-int depth;
-};
-
-#define TRY_OLD 0 // old way fails on test == 1
-
-void CubicIntersection_RandTestOld() {
- srand(0);
- const int tests = 1000000; // 10000000;
- double largestFactor = DBL_MAX;
- for (int test = 0; test < tests; ++test) {
- Cubic cubic1, cubic2;
- for (int i = 0; i < 4; ++i) {
- cubic1[i].x = (double) rand() / RAND_MAX * 100;
- cubic1[i].y = (double) rand() / RAND_MAX * 100;
- cubic2[i].x = (double) rand() / RAND_MAX * 100;
- cubic2[i].y = (double) rand() / RAND_MAX * 100;
- }
- if (test == 2513) { // the pair crosses three times, but the quadratic approximation
- continue; // only sees one -- should be OK to ignore the other two?
- }
- if (test == 12932) { // this exposes a weakness when one cubic touches the other but
- continue; // does not touch the quad approximation. Captured in qc.htm as cubic15
- }
- #if DEBUG_CRASH
- char str[1024];
- sprintf(str, "{{%1.9g, %1.9g}, {%1.9g, %1.9g}, {%1.9g, %1.9g}, {%1.9g, %1.9g}},\n"
- "{{%1.9g, %1.9g}, {%1.9g, %1.9g}, {%1.9g, %1.9g}, {%1.9g, %1.9g}},\n",
- cubic1[0].x, cubic1[0].y, cubic1[1].x, cubic1[1].y, cubic1[2].x, cubic1[2].y,
- cubic1[3].x, cubic1[3].y,
- cubic2[0].x, cubic2[0].y, cubic2[1].x, cubic2[1].y, cubic2[2].x, cubic2[2].y,
- cubic2[3].x, cubic2[3].y);
- #endif
- _Rect rect1, rect2;
- rect1.setBounds(cubic1);
- rect2.setBounds(cubic2);
- bool boundsIntersect = rect1.left <= rect2.right && rect2.left <= rect2.right
- && rect1.top <= rect2.bottom && rect2.top <= rect1.bottom;
- Intersections i1, i2;
- #if TRY_OLD
- bool oldIntersects = intersect(cubic1, cubic2, i1);
- #else
- bool oldIntersects = false;
- #endif
- if (test == -1) {
- SkDebugf("ready...\n");
- }
- bool newIntersects = intersect3(cubic1, cubic2, i2);
- if (!boundsIntersect && (oldIntersects || newIntersects)) {
- #if DEBUG_CRASH
- SkDebugf("%s %d unexpected intersection boundsIntersect=%d oldIntersects=%d"
- " newIntersects=%d\n%s %s\n", __FUNCTION__, test, boundsIntersect,
- oldIntersects, newIntersects, __FUNCTION__, str);
- #endif
- SkASSERT(0);
- }
- if (oldIntersects && !newIntersects) {
- #if DEBUG_CRASH
- SkDebugf("%s %d missing intersection oldIntersects=%d newIntersects=%d\n%s %s\n",
- __FUNCTION__, test, oldIntersects, newIntersects, __FUNCTION__, str);
- #endif
- SkASSERT(0);
- }
- if (!oldIntersects && !newIntersects) {
- continue;
- }
- if (i2.used() > 1) {
- continue;
- // just look at single intercepts for simplicity
- }
- Intersections self1, self2; // self-intersect checks
- if (intersect(cubic1, self1)) {
- continue;
- }
- if (intersect(cubic2, self2)) {
- continue;
- }
- // binary search for range necessary to enclose real intersection
- CubicChopper c(cubic1, cubic2);
- bool result = c.intersect(0, 1, 0, 1);
- if (!result) {
- // FIXME: a failure here probably means that a core routine used by CubicChopper is failing
- continue;
- }
- double delta1 = fabs(c.t1 - i2.fT[0][0]);
- double delta2 = fabs(c.t2 - i2.fT[1][0]);
- double calc1 = calcPrecision(cubic1);
- double calc2 = calcPrecision(cubic2);
- double factor1 = calc1 / delta1;
- double factor2 = calc2 / delta2;
- SkDebugf("%s %d calc1=%1.9g delta1=%1.9g factor1=%1.9g calc2=%1.9g delta2=%1.9g"
- " factor2=%1.9g\n", __FUNCTION__, test,
- calc1, delta1, factor1, calc2, delta2, factor2);
- if (factor1 < largestFactor) {
- SkDebugf("WE HAVE A WINNER! %1.9g\n", factor1);
- #if DEBUG_CRASH
- SkDebugf("%s\n", str);
- #endif
- oneOff3(cubic1, cubic2);
- largestFactor = factor1;
- }
- if (factor2 < largestFactor) {
- SkDebugf("WE HAVE A WINNER! %1.9g\n", factor2);
- #if DEBUG_CRASH
- SkDebugf("%s\n", str);
- #endif
- oneOff3(cubic1, cubic2);
- largestFactor = factor2;
- }
- }
-}
-
-void CubicIntersection_RandTest() {
- srand(0);
- const int tests = 10000000;
- for (int test = 0; test < tests; ++test) {
- Cubic cubic1, cubic2;
- for (int i = 0; i < 4; ++i) {
- cubic1[i].x = (double) rand() / RAND_MAX * 100;
- cubic1[i].y = (double) rand() / RAND_MAX * 100;
- cubic2[i].x = (double) rand() / RAND_MAX * 100;
- cubic2[i].y = (double) rand() / RAND_MAX * 100;
- }
- #if DEBUG_CRASH
- char str[1024];
- sprintf(str, "{{%1.9g, %1.9g}, {%1.9g, %1.9g}, {%1.9g, %1.9g}, {%1.9g, %1.9g}},\n"
- "{{%1.9g, %1.9g}, {%1.9g, %1.9g}, {%1.9g, %1.9g}, {%1.9g, %1.9g}},\n",
- cubic1[0].x, cubic1[0].y, cubic1[1].x, cubic1[1].y, cubic1[2].x, cubic1[2].y,
- cubic1[3].x, cubic1[3].y,
- cubic2[0].x, cubic2[0].y, cubic2[1].x, cubic2[1].y, cubic2[2].x, cubic2[2].y,
- cubic2[3].x, cubic2[3].y);
- #endif
- _Rect rect1, rect2;
- rect1.setBounds(cubic1);
- rect2.setBounds(cubic2);
- bool boundsIntersect = rect1.left <= rect2.right && rect2.left <= rect2.right
- && rect1.top <= rect2.bottom && rect2.top <= rect1.bottom;
- if (test == -1) {
- SkDebugf("ready...\n");
- }
- Intersections intersections2;
- bool newIntersects = intersect3(cubic1, cubic2, intersections2);
- if (!boundsIntersect && newIntersects) {
- #if DEBUG_CRASH
- SkDebugf("%s %d unexpected intersection boundsIntersect=%d "
- " newIntersects=%d\n%s %s\n", __FUNCTION__, test, boundsIntersect,
- newIntersects, __FUNCTION__, str);
- #endif
- SkASSERT(0);
- }
- for (int pt = 0; pt < intersections2.used(); ++pt) {
- double tt1 = intersections2.fT[0][pt];
- _Point xy1, xy2;
- xy_at_t(cubic1, tt1, xy1.x, xy1.y);
- int pt2 = intersections2.fFlip ? intersections2.used() - pt - 1 : pt;
- double tt2 = intersections2.fT[1][pt2];
- xy_at_t(cubic2, tt2, xy2.x, xy2.y);
- #if 0
- SkDebugf("%s t1=%1.9g (%1.9g, %1.9g) (%1.9g, %1.9g) t2=%1.9g\n", __FUNCTION__,
- tt1, xy1.x, xy1.y, xy2.x, xy2.y, tt2);
- #endif
- SkASSERT(xy1.approximatelyEqual(xy2));
- }
- }
-}
-
-static void intersectionFinder(int index0, int index1, double t1Seed, double t2Seed,
- double t1Step, double t2Step) {
- const Cubic& cubic1 = newTestSet[index0];
- const Cubic& cubic2 = newTestSet[index1];
- _Point t1[3], t2[3];
- bool toggle = true;
- do {
- xy_at_t(cubic1, t1Seed - t1Step, t1[0].x, t1[0].y);
- xy_at_t(cubic1, t1Seed, t1[1].x, t1[1].y);
- xy_at_t(cubic1, t1Seed + t1Step, t1[2].x, t1[2].y);
- xy_at_t(cubic2, t2Seed - t2Step, t2[0].x, t2[0].y);
- xy_at_t(cubic2, t2Seed, t2[1].x, t2[1].y);
- xy_at_t(cubic2, t2Seed + t2Step, t2[2].x, t2[2].y);
- double dist[3][3];
- dist[1][1] = t1[1].distance(t2[1]);
- int best_i = 1, best_j = 1;
- for (int i = 0; i < 3; ++i) {
- for (int j = 0; j < 3; ++j) {
- if (i == 1 && j == 1) {
- continue;
- }
- dist[i][j] = t1[i].distance(t2[j]);
- if (dist[best_i][best_j] > dist[i][j]) {
- best_i = i;
- best_j = j;
- }
- }
- }
- if (best_i == 0) {
- t1Seed -= t1Step;
- } else if (best_i == 2) {
- t1Seed += t1Step;
- }
- if (best_j == 0) {
- t2Seed -= t2Step;
- } else if (best_j == 2) {
- t2Seed += t2Step;
- }
- if (best_i == 1 && best_j == 1) {
- if ((toggle ^= true)) {
- t1Step /= 2;
- } else {
- t2Step /= 2;
- }
- }
- } while (!t1[1].approximatelyEqual(t2[1]));
- t1Step = t2Step = 0.1;
- double t10 = t1Seed - t1Step * 2;
- double t12 = t1Seed + t1Step * 2;
- double t20 = t2Seed - t2Step * 2;
- double t22 = t2Seed + t2Step * 2;
- _Point test;
- while (!approximately_zero(t1Step)) {
- xy_at_t(cubic1, t10, test.x, test.y);
- t10 += t1[1].approximatelyEqual(test) ? -t1Step : t1Step;
- t1Step /= 2;
- }
- t1Step = 0.1;
- while (!approximately_zero(t1Step)) {
- xy_at_t(cubic1, t12, test.x, test.y);
- t12 -= t1[1].approximatelyEqual(test) ? -t1Step : t1Step;
- t1Step /= 2;
- }
- while (!approximately_zero(t2Step)) {
- xy_at_t(cubic2, t20, test.x, test.y);
- t20 += t2[1].approximatelyEqual(test) ? -t2Step : t2Step;
- t2Step /= 2;
- }
- t2Step = 0.1;
- while (!approximately_zero(t2Step)) {
- xy_at_t(cubic2, t22, test.x, test.y);
- t22 -= t2[1].approximatelyEqual(test) ? -t2Step : t2Step;
- t2Step /= 2;
- }
-#if ONE_OFF_DEBUG
- SkDebugf("%s t1=(%1.9g<%1.9g<%1.9g) t2=(%1.9g<%1.9g<%1.9g)\n", __FUNCTION__,
- t10, t1Seed, t12, t20, t2Seed, t22);
- _Point p10 = xy_at_t(cubic1, t10);
- _Point p1Seed = xy_at_t(cubic1, t1Seed);
- _Point p12 = xy_at_t(cubic1, t12);
- SkDebugf("%s p1=(%1.9g,%1.9g)<(%1.9g,%1.9g)<(%1.9g,%1.9g)\n", __FUNCTION__,
- p10.x, p10.y, p1Seed.x, p1Seed.y, p12.x, p12.y);
- _Point p20 = xy_at_t(cubic2, t20);
- _Point p2Seed = xy_at_t(cubic2, t2Seed);
- _Point p22 = xy_at_t(cubic2, t22);
- SkDebugf("%s p2=(%1.9g,%1.9g)<(%1.9g,%1.9g)<(%1.9g,%1.9g)\n", __FUNCTION__,
- p20.x, p20.y, p2Seed.x, p2Seed.y, p22.x, p22.y);
-#endif
-}
-
-void CubicIntersection_IntersectionFinder() {
-
- // double t1Seed = 0.87;
- // double t2Seed = 0.87;
- double t1Step = 0.000001;
- double t2Step = 0.000001;
- intersectionFinder(0, 1, 0.855895664, 0.864850875, t1Step, t2Step);
- intersectionFinder(0, 1, 0.865207906, 0.865207887, t1Step, t2Step);
- intersectionFinder(0, 1, 0.865213351, 0.865208087, t1Step, t2Step);
-}
-
-static void coincidentTest() {
-#if 0
- Cubic cubic1 = {{0, 1}, {0, 2}, {1, 0}, {1, 0}};
- Cubic cubic2 = {{0, 1}, {0, 2}, {1, 0}, {6, 1}};
-#endif
-}
-
-void CubicIntersection_SelfTest() {
- const Cubic selfSet[] = {
- {{0,2}, {2,3}, {5,1}, {3,2}},
- {{0,2}, {3,5}, {5,0}, {4,2}},
- {{3.34,8.98}, {1.95,10.27}, {3.76,7.65}, {4.96,10.64}},
- {{3.13,2.74}, {1.08,4.62}, {3.71,0.94}, {2.01,3.81}},
- {{6.71,3.14}, {7.99,2.75}, {8.27,1.96}, {6.35,3.57}},
- {{12.81,7.27}, {7.22,6.98}, {12.49,8.97}, {11.42,6.18}},
- };
- size_t selfSetCount = sizeof(selfSet) / sizeof(selfSet[0]);
- size_t firstFail = 1;
- for (size_t index = firstFail; index < selfSetCount; ++index) {
- const Cubic& cubic = selfSet[index];
- #if ONE_OFF_DEBUG
- int idx2;
- double max[3];
- int ts = find_cubic_max_curvature(cubic, max);
- for (idx2 = 0; idx2 < ts; ++idx2) {
- SkDebugf("%s max[%d]=%1.9g (%1.9g, %1.9g)\n", __FUNCTION__, idx2,
- max[idx2], xy_at_t(cubic, max[idx2]).x, xy_at_t(cubic, max[idx2]).y);
- }
- SkTDArray<double> ts1;
- SkTDArray<Quadratic> quads1;
- cubic_to_quadratics(cubic, calcPrecision(cubic), ts1);
- for (idx2 = 0; idx2 < ts1.count(); ++idx2) {
- SkDebugf("%s t[%d]=%1.9g\n", __FUNCTION__, idx2, ts1[idx2]);
- }
- cubic_to_quadratics(cubic, calcPrecision(cubic), quads1);
- for (idx2 = 0; idx2 < quads1.count(); ++idx2) {
- const Quadratic& q = quads1[idx2];
- SkDebugf(" {{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}},\n",
- q[0].x, q[0].y, q[1].x, q[1].y, q[2].x, q[2].y);
- }
- SkDebugf("\n");
- #endif
- Intersections i;
- SkDEBUGCODE(int result = ) intersect(cubic, i);
- SkASSERT(result == 1);
- SkASSERT(i.used() == 1);
- SkASSERT(!approximately_equal(i.fT[0][0], i.fT[1][0]));
- _Point pt1 = xy_at_t(cubic, i.fT[0][0]);
- _Point pt2 = xy_at_t(cubic, i.fT[1][0]);
- SkASSERT(pt1.approximatelyEqual(pt2));
- }
-}
-
-void CubicIntersection_Test() {
- oneOffTests();
- coincidentTest();
- standardTestCases();
-}
diff --git a/experimental/Intersection/CubicIntersection_TestData.cpp b/experimental/Intersection/CubicIntersection_TestData.cpp
deleted file mode 100644
index c138a672da..0000000000
--- a/experimental/Intersection/CubicIntersection_TestData.cpp
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "CubicIntersection_TestData.h"
-#include <limits>
-
-const Cubic pointDegenerates[] = {
- {{0, 0}, {0, 0}, {0, 0}, {0, 0}},
- {{1, 1}, {1, 1}, {1, 1}, {1, 1}},
- {{1 + PointEpsilon - std::numeric_limits<double>::epsilon(), 1},
- {1, 1 + PointEpsilon - std::numeric_limits<double>::epsilon()}, {1, 1}, {1, 1}},
- {{1 + PointEpsilon/2 - std::numeric_limits<double>::epsilon(), 1},
- {1 - (PointEpsilon/2 - std::numeric_limits<double>::epsilon()), 1}, {1, 1}, {1, 1}}
-};
-
-const size_t pointDegenerates_count = sizeof(pointDegenerates) / sizeof(pointDegenerates[0]);
-
-const Cubic notPointDegenerates[] = {
- {{1 + PointEpsilon + std::numeric_limits<double>::epsilon(), 1}, {1, 1 + PointEpsilon}, {1, 1}, {1, 1}},
- {{1 + PointEpsilon/2 + std::numeric_limits<double>::epsilon(), 1}, {1 - PointEpsilon/2, 1}, {1, 1}, {1, 1}}
-};
-
-const size_t notPointDegenerates_count = sizeof(notPointDegenerates) / sizeof(notPointDegenerates[0]);
-
-// from http://www.truetex.com/bezint.htm
-const Cubic tests[][2] = {
- { // intersects in one place (data gives bezier clip fits
- {{0, 45},
- {6.0094158284751593, 51.610357411322688},
- {12.741093228940867, 55.981703949474607},
- {20.021417396476362, 58.652245509710262}},
- {{2.2070737699246674, 52.703494107327209},
- {31.591482272629477, 23.811002295222025},
- {76.824588616426425, 44.049473790502674},
- {119.25488947221436, 55.599248272955073}}
- },
- { // intersects in three places
- {{0, 45}, {50, 100}, {150, 0}, {200, 55}},
- {{0, 55}, {50, 0}, {150, 100}, {200, 45}}
- },
- { // intersects in one place, cross over is nearly parallel
- {{0, 0}, {0, 100}, {200, 0}, {200, 100}},
- {{0, 100}, {0, 0}, {200, 100}, {200, 0}}
- },
- { // intersects in two places
- {{0, 0}, {0, 100}, {200, 100}, {200, 0}},
- {{0, 100}, {0, 0}, {200, 0}, {200, 100}}
- },
- {
- {{150, 100}, {150 + 0.1, 150}, {150, 200}, {150, 250}},
- {{250, 150}, {200, 150 + 0.1}, {150, 150}, {100, 150}}
- },
- { // single intersection around 168,185
- {{200, 100}, {150, 100}, {150, 150}, {200, 150}},
- {{250, 150}, {250, 100}, {100, 100}, {100, 150}}
- },
- {
- {{1.0, 1.5}, {15.5, 0.5}, {-8.0, 3.5}, {5.0, 1.5}},
- {{4.0, 0.5}, {5.0, 15.0}, {2.0, -8.5}, {4.0, 4.5}}
- },
- {
- {{664.00168, 0}, {726.11545, 124.22757}, {736.89069, 267.89743}, {694.0017, 400.0002}},
- {{850.66843, 115.55563}, {728.515, 115.55563}, {725.21347, 275.15309}, {694.0017, 400.0002}}
- },
- {
- {{1, 1}, {12.5, 6.5}, {-4, 6.5}, {7.5, 1}},
- {{1, 6.5}, {12.5, 1}, {-4, 1}, {.5, 6}}
- },
- {
- {{315.748, 312.84}, {312.644, 318.134}, {305.836, 319.909}, {300.542, 316.804}},
- {{317.122, 309.05}, {316.112, 315.102}, {310.385, 319.19}, {304.332, 318.179}}
- },
- {
- {{1046.604051, 172.937967}, {1046.604051, 178.9763059}, {1041.76745, 183.9279165}, {1035.703842, 184.0432409}},
- {{1046.452235, 174.7640504}, {1045.544872, 180.1973817}, {1040.837966, 184.0469882}, {1035.505925, 184.0469882}}
- },
- {
- {{125.79356, 199.57382}, {51.16556, 128.93575}, {87.494, 16.67848}, {167.29361, 16.67848}},
- {{167.29361, 55.81876}, {100.36128, 55.81876}, {68.64099, 145.4755}, {125.7942, 199.57309}}
- }
-};
-
-const size_t tests_count = sizeof(tests) / sizeof(tests[0]);
-
-Cubic hexTests[][2] = {
- {
- {{0}} // placeholder for hex converted below
- }
-};
-
-const size_t hexTests_count = sizeof(hexTests) / sizeof(hexTests[0]);
-
-static const uint64_t testx[2][8] = {
- {
- 0xf0d0d1ca63075a40LLU, 0x9408ce996a237740LLU, 0x6d5675460fbe5e40LLU, 0x6ef501e1b7487940LLU,
- 0x9a71d2f8143d6540LLU, 0x6bc18bbe02907a40LLU, 0x5b94d92093aa6b40LLU, 0x6ac18bbe02907a40LLU
- },
- {
- 0x92c56ed7b6145d40LLU, 0xede4f1255edb7740LLU, 0x1138c1101af75940LLU, 0x42e4f1255edb7740LLU,
- 0x408e51603ad95640LLU, 0x1e2e8fe9dd927740LLU, 0x1cb4777cd3a75440LLU, 0x212e1390de017740LLU
- }
-};
-
-void convert_testx() {
- const uint64_t* inPtr = testx[0];
- double* outPtr = &hexTests[sizeof(tests) / sizeof(tests[0]) - 1][0][0].x;
- for (unsigned index = 0; index < sizeof(testx) / sizeof(testx[0][0]); ++index) {
- uint64_t input = *inPtr++;
- unsigned char* output = (unsigned char*) outPtr++;
- for (unsigned byte = 0; byte < sizeof(input); ++byte) {
- output[byte] = input >> (7 - byte) * 8;
- }
- }
-}
-
-const Cubic lines[] = {
- {{0, 0}, {0, 0}, {0, 0}, {1, 0}}, // 0: horizontal
- {{0, 0}, {0, 0}, {1, 0}, {0, 0}},
- {{0, 0}, {1, 0}, {0, 0}, {0, 0}},
- {{1, 0}, {0, 0}, {0, 0}, {0, 0}},
- {{1, 0}, {2, 0}, {3, 0}, {4, 0}},
- {{0, 0}, {0, 0}, {0, 0}, {0, 1}}, // 5: vertical
- {{0, 0}, {0, 0}, {0, 1}, {0, 0}},
- {{0, 0}, {0, 1}, {0, 0}, {0, 0}},
- {{0, 1}, {0, 0}, {0, 0}, {0, 0}},
- {{0, 1}, {0, 2}, {0, 3}, {0, 4}},
- {{0, 0}, {0, 0}, {0, 0}, {1, 1}}, // 10: 3 coincident
- {{0, 0}, {0, 0}, {1, 1}, {0, 0}},
- {{0, 0}, {1, 1}, {0, 0}, {0, 0}},
- {{1, 1}, {0, 0}, {0, 0}, {0, 0}},
- {{0, 0}, {0, 0}, {1, 1}, {2, 2}}, // 14: 2 coincident
- {{0, 0}, {1, 1}, {0, 0}, {2, 2}},
- {{0, 0}, {1, 1}, {2, 2}, {0, 0}},
- {{1, 1}, {0, 0}, {0, 0}, {2, 2}}, // 17:
- {{1, 1}, {0, 0}, {2, 2}, {0, 0}},
- {{1, 1}, {2, 2}, {0, 0}, {0, 0}},
- {{1, 1}, {2, 2}, {3, 3}, {2, 2}}, // middle-last coincident
- {{1, 1}, {2, 2}, {3, 3}, {3, 3}}, // middle-last coincident
- {{1, 1}, {1, 1}, {2, 2}, {2, 2}}, // 2 pairs coincident
- {{1, 1}, {2, 2}, {1, 1}, {2, 2}},
- {{1, 1}, {2, 2}, {2, 2}, {1, 1}},
- {{1, 1}, {1, 1}, {3, 3}, {3, 3}}, // first-middle middle-last coincident
- {{1, 1}, {2, 2}, {3, 3}, {4, 4}}, // no coincident
- {{1, 1}, {3, 3}, {2, 2}, {4, 4}},
- {{1, 1}, {2, 2}, {4, 4}, {3, 3}},
- {{1, 1}, {3, 3}, {4, 4}, {2, 2}},
- {{1, 1}, {4, 4}, {2, 2}, {3, 3}},
- {{1, 1}, {4, 4}, {3, 3}, {2, 2}},
- {{2, 2}, {1, 1}, {3, 3}, {4, 4}},
- {{2, 2}, {1, 1}, {4, 4}, {3, 3}},
- {{2, 2}, {3, 3}, {1, 1}, {4, 4}},
- {{2, 2}, {3, 3}, {4, 4}, {1, 1}},
- {{2, 2}, {4, 4}, {1, 1}, {3, 3}},
- {{2, 2}, {4, 4}, {3, 3}, {1, 1}},
-};
-
-const size_t lines_count = sizeof(lines) / sizeof(lines[0]);
-
-// 'not a line' tries to fool the line detection code
-const Cubic notLines[] = {
- {{0, 0}, {0, 0}, {0, 1}, {1, 0}},
- {{0, 0}, {0, 1}, {0, 0}, {1, 0}},
- {{0, 0}, {0, 1}, {1, 0}, {0, 0}},
- {{0, 1}, {0, 0}, {0, 0}, {1, 0}},
- {{0, 1}, {0, 0}, {1, 0}, {0, 0}},
- {{0, 1}, {1, 0}, {0, 0}, {0, 0}},
-};
-
-const size_t notLines_count = sizeof(notLines) / sizeof(notLines[0]);
-
-static const double E = PointEpsilon * 2;
-static const double F = PointEpsilon * 3;
-
-const Cubic modEpsilonLines[] = {
- {{0, E}, {0, 0}, {0, 0}, {1, 0}}, // horizontal
- {{0, 0}, {0, E}, {1, 0}, {0, 0}},
- {{0, 0}, {1, 0}, {0, E}, {0, 0}},
- {{1, 0}, {0, 0}, {0, 0}, {0, E}},
- {{1, E}, {2, 0}, {3, 0}, {4, 0}},
- {{E, 0}, {0, 0}, {0, 0}, {0, 1}}, // vertical
- {{0, 0}, {E, 0}, {0, 1}, {0, 0}},
- {{0, 0}, {0, 1}, {E, 0}, {0, 0}},
- {{0, 1}, {0, 0}, {0, 0}, {E, 0}},
- {{E, 1}, {0, 2}, {0, 3}, {0, 4}},
- {{E, 0}, {0, 0}, {0, 0}, {1, 1}}, // 3 coincident
- {{0, 0}, {E, 0}, {1, 1}, {0, 0}},
- {{0, 0}, {1, 1}, {E, 0}, {0, 0}},
- {{1, 1}, {0, 0}, {0, 0}, {E, 0}},
- {{0, E}, {0, 0}, {1, 1}, {2, 2}}, // 2 coincident
- {{0, 0}, {1, 1}, {0, E}, {2, 2}},
- {{0, 0}, {1, 1}, {2, 2}, {0, E}},
- {{1, 1}, {0, E}, {0, 0}, {2, 2}},
- {{1, 1}, {0, E}, {2, 2}, {0, 0}},
- {{1, 1}, {2, 2}, {E, 0}, {0, 0}},
- {{1, 1}, {2, 2+E}, {3, 3}, {2, 2}}, // middle-last coincident
- {{1, 1}, {2+E, 2}, {3, 3}, {3, 3}}, // middle-last coincident
- {{1, 1}, {1, 1}, {2, 2}, {2+E, 2}}, // 2 pairs coincident
- {{1, 1}, {2, 2}, {1, 1}, {2+E, 2}},
- {{1, 1}, {2, 2}, {2, 2+E}, {1, 1}},
- {{1, 1}, {1, 1+E}, {3, 3}, {3, 3}}, // first-middle middle-last coincident
- {{1, 1}, {2+E, 2}, {3, 3}, {4, 4}}, // no coincident
- {{1, 1}, {3, 3}, {2, 2}, {4, 4+F}}, // INVESTIGATE: why the epsilon is bigger
- {{1, 1+F}, {2, 2}, {4, 4}, {3, 3}}, // INVESTIGATE: why the epsilon is bigger
- {{1, 1}, {3, 3}, {4, 4+E}, {2, 2}},
- {{1, 1}, {4, 4}, {2, 2}, {3, 3+E}},
- {{1, 1}, {4, 4}, {3, 3}, {2+E, 2}},
- {{2, 2}, {1, 1}, {3+E, 3}, {4, 4}},
- {{2, 2}, {1+E, 1}, {4, 4}, {3, 3}},
- {{2, 2+E}, {3, 3}, {1, 1}, {4, 4}},
- {{2+E, 2}, {3, 3}, {4, 4}, {1, 1}},
- {{2, 2}, {4+E, 4}, {1, 1}, {3, 3}},
- {{2, 2}, {4, 4}, {3, 3}, {1, 1+E}},
-};
-
-const size_t modEpsilonLines_count = sizeof(modEpsilonLines) / sizeof(modEpsilonLines[0]);
-
-static const double D = PointEpsilon / 2;
-static const double G = PointEpsilon / 3;
-
-const Cubic lessEpsilonLines[] = {
- {{0, D}, {0, 0}, {0, 0}, {1, 0}}, // horizontal
- {{0, 0}, {0, D}, {1, 0}, {0, 0}},
- {{0, 0}, {1, 0}, {0, D}, {0, 0}},
- {{1, 0}, {0, 0}, {0, 0}, {0, D}},
- {{1, D}, {2, 0}, {3, 0}, {4, 0}},
- {{D, 0}, {0, 0}, {0, 0}, {0, 1}}, // vertical
- {{0, 0}, {D, 0}, {0, 1}, {0, 0}},
- {{0, 0}, {0, 1}, {D, 0}, {0, 0}},
- {{0, 1}, {0, 0}, {0, 0}, {D, 0}},
- {{D, 1}, {0, 2}, {0, 3}, {0, 4}},
- {{D, 0}, {0, 0}, {0, 0}, {1, 1}}, // 3 coincident
- {{0, 0}, {D, 0}, {1, 1}, {0, 0}},
- {{0, 0}, {1, 1}, {D, 0}, {0, 0}},
- {{1, 1}, {0, 0}, {0, 0}, {D, 0}},
- {{0, D}, {0, 0}, {1, 1}, {2, 2}}, // 2 coincident
- {{0, 0}, {1, 1}, {0, D}, {2, 2}},
- {{0, 0}, {1, 1}, {2, 2}, {0, D}},
- {{1, 1}, {0, D}, {0, 0}, {2, 2}},
- {{1, 1}, {0, D}, {2, 2}, {0, 0}},
- {{1, 1}, {2, 2}, {D, 0}, {0, 0}},
- {{1, 1}, {2, 2+D}, {3, 3}, {2, 2}}, // middle-last coincident
- {{1, 1}, {2+D, 2}, {3, 3}, {3, 3}}, // middle-last coincident
- {{1, 1}, {1, 1}, {2, 2}, {2+D, 2}}, // 2 pairs coincident
- {{1, 1}, {2, 2}, {1, 1}, {2+D, 2}},
- {{1, 1}, {2, 2}, {2, 2+D}, {1, 1}},
- {{1, 1}, {1, 1+D}, {3, 3}, {3, 3}}, // first-middle middle-last coincident
- {{1, 1}, {2+D/2, 2}, {3, 3}, {4, 4}}, // no coincident (FIXME: N as opposed to N/2 failed)
- {{1, 1}, {3, 3}, {2, 2}, {4, 4+D}},
- {{1, 1+D}, {2, 2}, {4, 4}, {3, 3}},
- {{1, 1}, {3, 3}, {4, 4+D}, {2, 2}},
- {{1, 1}, {4, 4}, {2, 2}, {3, 3+D}},
- {{1, 1}, {4, 4}, {3, 3}, {2+G, 2}}, // INVESTIGATE: why the epsilon is smaller
- {{2, 2}, {1, 1}, {3+D, 3}, {4, 4}},
- {{2, 2}, {1+D, 1}, {4, 4}, {3, 3}},
- {{2, 2+D}, {3, 3}, {1, 1}, {4, 4}},
- {{2+G, 2}, {3, 3}, {4, 4}, {1, 1}}, // INVESTIGATE: why the epsilon is smaller
- {{2, 2}, {4+D, 4}, {1, 1}, {3, 3}},
- {{2, 2}, {4, 4}, {3, 3}, {1, 1+D}},
-};
-
-const size_t lessEpsilonLines_count = sizeof(lessEpsilonLines) / sizeof(lessEpsilonLines[0]);
-
-static const double N = -PointEpsilon / 2;
-static const double M = -PointEpsilon / 3;
-
-const Cubic negEpsilonLines[] = {
- {{0, N}, {0, 0}, {0, 0}, {1, 0}}, // horizontal
- {{0, 0}, {0, N}, {1, 0}, {0, 0}},
- {{0, 0}, {1, 0}, {0, N}, {0, 0}},
- {{1, 0}, {0, 0}, {0, 0}, {0, N}},
- {{1, N}, {2, 0}, {3, 0}, {4, 0}},
- {{N, 0}, {0, 0}, {0, 0}, {0, 1}}, // vertical
- {{0, 0}, {N, 0}, {0, 1}, {0, 0}},
- {{0, 0}, {0, 1}, {N, 0}, {0, 0}},
- {{0, 1}, {0, 0}, {0, 0}, {N, 0}},
- {{N, 1}, {0, 2}, {0, 3}, {0, 4}},
- {{N, 0}, {0, 0}, {0, 0}, {1, 1}}, // 3 coincident
- {{0, 0}, {N, 0}, {1, 1}, {0, 0}},
- {{0, 0}, {1, 1}, {N, 0}, {0, 0}},
- {{1, 1}, {0, 0}, {0, 0}, {N, 0}},
- {{0, N}, {0, 0}, {1, 1}, {2, 2}}, // 2 coincident
- {{0, 0}, {1, 1}, {0, N}, {2, 2}},
- {{0, 0}, {1, 1}, {2, 2}, {0, N}},
- {{1, 1}, {0, N}, {0, 0}, {2, 2}},
- {{1, 1}, {0, N}, {2, 2}, {0, 0}},
- {{1, 1}, {2, 2}, {N, 0}, {0, 0}},
- {{1, 1}, {2, 2+N}, {3, 3}, {2, 2}}, // middle-last coincident
- {{1, 1}, {2+N, 2}, {3, 3}, {3, 3}}, // middle-last coincident
- {{1, 1}, {1, 1}, {2, 2}, {2+N, 2}}, // 2 pairs coincident
- {{1, 1}, {2, 2}, {1, 1}, {2+N, 2}},
- {{1, 1}, {2, 2}, {2, 2+N}, {1, 1}},
- {{1, 1}, {1, 1+N}, {3, 3}, {3, 3}}, // first-middle middle-last coincident
- {{1, 1}, {2+N/2, 2}, {3, 3}, {4, 4}}, // no coincident (FIXME: N as opposed to N/2 failed)
- {{1, 1}, {3, 3}, {2, 2}, {4, 4+N}},
- {{1, 1+N}, {2, 2}, {4, 4}, {3, 3}},
- {{1, 1}, {3, 3}, {4, 4+N}, {2, 2}},
- {{1, 1}, {4, 4}, {2, 2}, {3, 3+N}},
- {{1, 1}, {4, 4}, {3, 3}, {2+M, 2}}, // INVESTIGATE: why the epsilon is smaller
- {{2, 2}, {1, 1}, {3+N, 3}, {4, 4}},
- {{2, 2}, {1+N, 1}, {4, 4}, {3, 3}},
- {{2, 2+N}, {3, 3}, {1, 1}, {4, 4}},
- {{2+M, 2}, {3, 3}, {4, 4}, {1, 1}}, // INVESTIGATE: why the epsilon is smaller
- {{2, 2}, {4+N, 4}, {1, 1}, {3, 3}},
- {{2, 2}, {4, 4}, {3, 3}, {1, 1+N}},
-};
-
-const size_t negEpsilonLines_count = sizeof(negEpsilonLines) / sizeof(negEpsilonLines[0]);
diff --git a/experimental/Intersection/CubicIntersection_TestData.h b/experimental/Intersection/CubicIntersection_TestData.h
deleted file mode 100644
index 9893b3c1ac..0000000000
--- a/experimental/Intersection/CubicIntersection_TestData.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "DataTypes.h"
-#include "DataTypes_Test.h"
-
-extern const Cubic pointDegenerates[];
-extern const Cubic notPointDegenerates[];
-extern const Cubic tests[][2];
-extern Cubic hexTests[][2];
-
-extern void convert_testx();
-
-extern const Cubic lines[];
-extern const Cubic notLines[];
-extern const Cubic modEpsilonLines[];
-extern const Cubic lessEpsilonLines[];
-extern const Cubic negEpsilonLines[];
-
-extern const size_t pointDegenerates_count;
-extern const size_t notPointDegenerates_count;
-extern const size_t tests_count;
-extern const size_t hexTests_count;
-extern const size_t lines_count;
-extern const size_t notLines_count;
-extern const size_t modEpsilonLines_count;
-extern const size_t lessEpsilonLines_count;
-extern const size_t negEpsilonLines_count;
diff --git a/experimental/Intersection/CubicLineSegments.cpp b/experimental/Intersection/CubicLineSegments.cpp
deleted file mode 100644
index 58b7b85d49..0000000000
--- a/experimental/Intersection/CubicLineSegments.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "CubicLineSegments.h"
-#include "QuadraticLineSegments.h"
-
-// http://cagd.cs.byu.edu/~557/text/cagd.pdf 2.7
-// A hodograph is the first derivative curve
-void hodograph(const Cubic& cubic, Quadratic& hodo) {
- hodo[0].x = 3 * (cubic[1].x - cubic[0].x);
- hodo[0].y = 3 * (cubic[1].y - cubic[0].y);
- hodo[1].x = 3 * (cubic[2].x - cubic[1].x);
- hodo[1].y = 3 * (cubic[2].y - cubic[1].y);
- hodo[2].x = 3 * (cubic[3].x - cubic[2].x);
- hodo[2].y = 3 * (cubic[3].y - cubic[2].y);
-}
-
-// A 2nd hodograph is the second derivative curve
-void secondHodograph(const Cubic& cubic, _Line& hodo2) {
- Quadratic hodo;
- hodograph(cubic, hodo);
- hodograph(hodo, hodo2);
-}
-
-// The number of line segments required to approximate the cubic
-// see http://cagd.cs.byu.edu/~557/text/cagd.pdf 10.6
-double subDivisions(const Cubic& cubic) {
- _Line hodo2;
- secondHodograph(cubic, hodo2);
- double maxX = SkTMax(hodo2[1].x, hodo2[1].x);
- double maxY = SkTMax(hodo2[1].y, hodo2[1].y);
- double dist = sqrt(maxX * maxX + maxY * maxY);
- double segments = sqrt(dist / (8 * FLT_EPSILON));
- return segments;
-}
diff --git a/experimental/Intersection/CubicLineSegments.h b/experimental/Intersection/CubicLineSegments.h
deleted file mode 100644
index 0c80a640e7..0000000000
--- a/experimental/Intersection/CubicLineSegments.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "DataTypes.h"
-
-void hodograph(const Cubic& , Quadratic& hodo);
-void secondHodograph(const Cubic& , _Line& hodo2);
-double subDivisions(const Cubic& );
diff --git a/experimental/Intersection/CubicParameterization.cpp b/experimental/Intersection/CubicParameterization.cpp
deleted file mode 100644
index caa7c24dd8..0000000000
--- a/experimental/Intersection/CubicParameterization.cpp
+++ /dev/null
@@ -1,518 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "CurveIntersection.h"
-#include "CubicUtilities.h"
-
-/* from http://tom.cs.byu.edu/~tom/papers/cvgip84.pdf 4.1
- *
- * This paper proves that Syvester's method can compute the implicit form of
- * the quadratic from the parameterzied form.
- *
- * Given x = a*t*t*t + b*t*t + c*t + d (the parameterized form)
- * y = e*t*t*t + f*t*t + g*t + h
- *
- * we want to find an equation of the implicit form:
- *
- * A*x^3 + B*x*x*y + C*x*y*y + D*y^3 + E*x*x + F*x*y + G*y*y + H*x + I*y + J = 0
- *
- * The implicit form can be expressed as a 6x6 determinant, as shown.
- *
- * The resultant obtained by Syvester's method is
- *
- * | a b c (d - x) 0 0 |
- * | 0 a b c (d - x) 0 |
- * | 0 0 a b c (d - x) |
- * | e f g (h - y) 0 0 |
- * | 0 e f g (h - y) 0 |
- * | 0 0 e f g (h - y) |
- *
- * which, according to Mathematica, expands as shown below.
- *
- * Resultant[a*t^3 + b*t^2 + c*t + d - x, e*t^3 + f*t^2 + g*t + h - y, t]
- *
- * -d^3 e^3 + c d^2 e^2 f - b d^2 e f^2 + a d^2 f^3 - c^2 d e^2 g +
- * 2 b d^2 e^2 g + b c d e f g - 3 a d^2 e f g - a c d f^2 g -
- * b^2 d e g^2 + 2 a c d e g^2 + a b d f g^2 - a^2 d g^3 + c^3 e^2 h -
- * 3 b c d e^2 h + 3 a d^2 e^2 h - b c^2 e f h + 2 b^2 d e f h +
- * a c d e f h + a c^2 f^2 h - 2 a b d f^2 h + b^2 c e g h -
- * 2 a c^2 e g h - a b d e g h - a b c f g h + 3 a^2 d f g h +
- * a^2 c g^2 h - b^3 e h^2 + 3 a b c e h^2 - 3 a^2 d e h^2 +
- * a b^2 f h^2 - 2 a^2 c f h^2 - a^2 b g h^2 + a^3 h^3 + 3 d^2 e^3 x -
- * 2 c d e^2 f x + 2 b d e f^2 x - 2 a d f^3 x + c^2 e^2 g x -
- * 4 b d e^2 g x - b c e f g x + 6 a d e f g x + a c f^2 g x +
- * b^2 e g^2 x - 2 a c e g^2 x - a b f g^2 x + a^2 g^3 x +
- * 3 b c e^2 h x - 6 a d e^2 h x - 2 b^2 e f h x - a c e f h x +
- * 2 a b f^2 h x + a b e g h x - 3 a^2 f g h x + 3 a^2 e h^2 x -
- * 3 d e^3 x^2 + c e^2 f x^2 - b e f^2 x^2 + a f^3 x^2 +
- * 2 b e^2 g x^2 - 3 a e f g x^2 + 3 a e^2 h x^2 + e^3 x^3 -
- * c^3 e^2 y + 3 b c d e^2 y - 3 a d^2 e^2 y + b c^2 e f y -
- * 2 b^2 d e f y - a c d e f y - a c^2 f^2 y + 2 a b d f^2 y -
- * b^2 c e g y + 2 a c^2 e g y + a b d e g y + a b c f g y -
- * 3 a^2 d f g y - a^2 c g^2 y + 2 b^3 e h y - 6 a b c e h y +
- * 6 a^2 d e h y - 2 a b^2 f h y + 4 a^2 c f h y + 2 a^2 b g h y -
- * 3 a^3 h^2 y - 3 b c e^2 x y + 6 a d e^2 x y + 2 b^2 e f x y +
- * a c e f x y - 2 a b f^2 x y - a b e g x y + 3 a^2 f g x y -
- * 6 a^2 e h x y - 3 a e^2 x^2 y - b^3 e y^2 + 3 a b c e y^2 -
- * 3 a^2 d e y^2 + a b^2 f y^2 - 2 a^2 c f y^2 - a^2 b g y^2 +
- * 3 a^3 h y^2 + 3 a^2 e x y^2 - a^3 y^3
- */
-
-enum {
- xxx_coeff, // A
- xxy_coeff, // B
- xyy_coeff, // C
- yyy_coeff, // D
- xx_coeff,
- xy_coeff,
- yy_coeff,
- x_coeff,
- y_coeff,
- c_coeff,
- coeff_count
-};
-
-#define USE_SYVESTER 0 // if 0, use control-point base parametric form
-#if USE_SYVESTER
-
-// FIXME: factoring version unwritten
-// static bool straight_forward = true;
-
-/* from CubicParameterizationCode.cpp output:
- * double A = e * e * e;
- * double B = -3 * a * e * e;
- * double C = 3 * a * a * e;
- * double D = -a * a * a;
- */
-static void calc_ABCD(double a, double e, double p[coeff_count]) {
- double ee = e * e;
- p[xxx_coeff] = e * ee;
- p[xxy_coeff] = -3 * a * ee;
- double aa = a * a;
- p[xyy_coeff] = 3 * aa * e;
- p[yyy_coeff] = -aa * a;
-}
-
-/* CubicParameterizationCode.cpp turns Mathematica output into C.
- * Rather than edit the lines below, please edit the code there instead.
- */
-// start of generated code
-static double calc_xx(double a, double b, double c, double d,
- double e, double f, double g, double h) {
- return
- -3 * d * e * e * e
- + c * e * e * f
- - b * e * f * f
- + a * f * f * f
- + 2 * b * e * e * g
- - 3 * a * e * f * g
- + 3 * a * e * e * h;
-}
-
-static double calc_xy(double a, double b, double c, double d,
- double e, double f, double g, double h) {
- return
- -3 * b * c * e * e
- + 6 * a * d * e * e
- + 2 * b * b * e * f
- + a * c * e * f
- - 2 * a * b * f * f
- - a * b * e * g
- + 3 * a * a * f * g
- - 6 * a * a * e * h;
-}
-
-static double calc_yy(double a, double b, double c, double d,
- double e, double f, double g, double h) {
- return
- -b * b * b * e
- + 3 * a * b * c * e
- - 3 * a * a * d * e
- + a * b * b * f
- - 2 * a * a * c * f
- - a * a * b * g
- + 3 * a * a * a * h;
-}
-
-static double calc_x(double a, double b, double c, double d,
- double e, double f, double g, double h) {
- return
- 3 * d * d * e * e * e
- - 2 * c * d * e * e * f
- + 2 * b * d * e * f * f
- - 2 * a * d * f * f * f
- + c * c * e * e * g
- - 4 * b * d * e * e * g
- - b * c * e * f * g
- + 6 * a * d * e * f * g
- + a * c * f * f * g
- + b * b * e * g * g
- - 2 * a * c * e * g * g
- - a * b * f * g * g
- + a * a * g * g * g
- + 3 * b * c * e * e * h
- - 6 * a * d * e * e * h
- - 2 * b * b * e * f * h
- - a * c * e * f * h
- + 2 * a * b * f * f * h
- + a * b * e * g * h
- - 3 * a * a * f * g * h
- + 3 * a * a * e * h * h;
-}
-
-static double calc_y(double a, double b, double c, double d,
- double e, double f, double g, double h) {
- return
- -c * c * c * e * e
- + 3 * b * c * d * e * e
- - 3 * a * d * d * e * e
- + b * c * c * e * f
- - 2 * b * b * d * e * f
- - a * c * d * e * f
- - a * c * c * f * f
- + 2 * a * b * d * f * f
- - b * b * c * e * g
- + 2 * a * c * c * e * g
- + a * b * d * e * g
- + a * b * c * f * g
- - 3 * a * a * d * f * g
- - a * a * c * g * g
- + 2 * b * b * b * e * h
- - 6 * a * b * c * e * h
- + 6 * a * a * d * e * h
- - 2 * a * b * b * f * h
- + 4 * a * a * c * f * h
- + 2 * a * a * b * g * h
- - 3 * a * a * a * h * h;
-}
-
-static double calc_c(double a, double b, double c, double d,
- double e, double f, double g, double h) {
- return
- -d * d * d * e * e * e
- + c * d * d * e * e * f
- - b * d * d * e * f * f
- + a * d * d * f * f * f
- - c * c * d * e * e * g
- + 2 * b * d * d * e * e * g
- + b * c * d * e * f * g
- - 3 * a * d * d * e * f * g
- - a * c * d * f * f * g
- - b * b * d * e * g * g
- + 2 * a * c * d * e * g * g
- + a * b * d * f * g * g
- - a * a * d * g * g * g
- + c * c * c * e * e * h
- - 3 * b * c * d * e * e * h
- + 3 * a * d * d * e * e * h
- - b * c * c * e * f * h
- + 2 * b * b * d * e * f * h
- + a * c * d * e * f * h
- + a * c * c * f * f * h
- - 2 * a * b * d * f * f * h
- + b * b * c * e * g * h
- - 2 * a * c * c * e * g * h
- - a * b * d * e * g * h
- - a * b * c * f * g * h
- + 3 * a * a * d * f * g * h
- + a * a * c * g * g * h
- - b * b * b * e * h * h
- + 3 * a * b * c * e * h * h
- - 3 * a * a * d * e * h * h
- + a * b * b * f * h * h
- - 2 * a * a * c * f * h * h
- - a * a * b * g * h * h
- + a * a * a * h * h * h;
-}
-// end of generated code
-
-#else
-
-/* more Mathematica generated code. This takes a different tack, starting with
- the control-point based parametric formulas. The C code is unoptimized --
- in this form, this is a proof of concept (since the other code didn't work)
-*/
-static double calc_c(double a, double b, double c, double d,
- double e, double f, double g, double h) {
- return
-d*d*d*e*e*e - 3*d*d*(3*c*e*e*f + 3*b*e*(-3*f*f + 2*e*g) + a*(9*f*f*f - 9*e*f*g + e*e*h)) -
- h*(27*c*c*c*e*e - 27*c*c*(3*b*e*f - 3*a*f*f + 2*a*e*g) +
- h*(-27*b*b*b*e + 27*a*b*b*f - 9*a*a*b*g + a*a*a*h) +
- 9*c*(9*b*b*e*g + a*b*(-9*f*g + 3*e*h) + a*a*(3*g*g - 2*f*h))) +
- 3*d*(9*c*c*e*e*g + 9*b*b*e*(3*g*g - 2*f*h) + 3*a*b*(-9*f*g*g + 6*f*f*h + e*g*h) +
- a*a*(9*g*g*g - 9*f*g*h + e*h*h) + 3*c*(3*b*e*(-3*f*g + e*h) + a*(9*f*f*g - 6*e*g*g - e*f*h)))
- ;
-}
-
-// - Power(e - 3*f + 3*g - h,3)*Power(x,3)
-static double calc_xxx(double e3f3gh) {
- return -e3f3gh * e3f3gh * e3f3gh;
-}
-
-static double calc_y(double a, double b, double c, double d,
- double e, double f, double g, double h) {
- return
-+ 3*(6*b*d*d*e*e - d*d*d*e*e + 18*b*b*d*e*f - 18*b*d*d*e*f -
- 9*b*d*d*f*f - 54*b*b*d*e*g + 12*b*d*d*e*g - 27*b*b*d*g*g - 18*b*b*b*e*h + 18*b*b*d*e*h +
- 18*b*b*d*f*h + a*a*a*h*h - 9*b*b*b*h*h + 9*c*c*c*e*(e + 2*h) +
- a*a*(-3*b*h*(2*g + h) + d*(-27*g*g + 9*g*h - h*(2*e + h) + 9*f*(g + h))) +
- a*(9*b*b*h*(2*f + h) - 3*b*d*(6*f*f - 6*f*(3*g - 2*h) + g*(-9*g + h) + e*(g + h)) +
- d*d*(e*e + 9*f*(3*f - g) + e*(-9*f - 9*g + 2*h))) -
- 9*c*c*(d*e*(e + 2*g) + 3*b*(f*h + e*(f + h)) + a*(-3*f*f - 6*f*h + 2*(g*h + e*(g + h)))) +
- 3*c*(d*d*e*(e + 2*f) + a*a*(3*g*g + 6*g*h - 2*h*(2*f + h)) + 9*b*b*(g*h + e*(g + h)) +
- a*d*(-9*f*f - 18*f*g + 6*g*g + f*h + e*(f + 12*g + h)) +
- b*(d*(-3*e*e + 9*f*g + e*(9*f + 9*g - 6*h)) + 3*a*(h*(2*e - 3*g + h) - 3*f*(g + h))))) // *y
- ;
-}
-
-static double calc_yy(double a, double b, double c, double d,
- double e, double f, double g, double h) {
- return
-- 3*(18*c*c*c*e - 18*c*c*d*e + 6*c*d*d*e - d*d*d*e + 3*c*d*d*f - 9*c*c*d*g + a*a*a*h + 9*c*c*c*h -
- 9*b*b*b*(e + 2*h) - a*a*(d*(e - 9*f + 18*g - 7*h) + 3*c*(2*f - 6*g + h)) +
- a*(-9*c*c*(2*e - 6*f + 2*g - h) + d*d*(-7*e + 18*f - 9*g + h) + 3*c*d*(7*e - 17*f + 3*g + h)) +
- 9*b*b*(3*c*(e + g + h) + a*(f + 2*h) - d*(e - 2*(f - 3*g + h))) -
- 3*b*(-(d*d*(e - 6*f + 2*g)) - 3*c*d*(e + 3*f + 3*g - h) + 9*c*c*(e + f + h) + a*a*(g + 2*h) +
- a*(c*(-3*e + 9*f + 9*g + 3*h) + d*(e + 3*f - 17*g + 7*h)))) // *Power(y,2)
- ;
-}
-
-// + Power(a - 3*b + 3*c - d,3)*Power(y,3)
-static double calc_yyy(double a3b3cd) {
- return a3b3cd * a3b3cd * a3b3cd;
-}
-
-static double calc_xx(double a, double b, double c, double d,
- double e, double f, double g, double h) {
- return
-// + Power(x,2)*
-(-3*(-9*b*e*f*f + 9*a*f*f*f + 6*b*e*e*g - 9*a*e*f*g + 27*b*e*f*g - 27*a*f*f*g + 18*a*e*g*g - 54*b*e*g*g +
- 27*a*f*g*g + 27*b*f*g*g - 18*a*g*g*g + a*e*e*h - 9*b*e*e*h + 3*a*e*f*h + 9*b*e*f*h + 9*a*f*f*h -
- 18*b*f*f*h - 21*a*e*g*h + 51*b*e*g*h - 9*a*f*g*h - 27*b*f*g*h + 18*a*g*g*h + 7*a*e*h*h - 18*b*e*h*h - 3*a*f*h*h +
- 18*b*f*h*h - 6*a*g*h*h - 3*b*g*h*h + a*h*h*h +
- 3*c*(-9*f*f*(g - 2*h) + 3*g*g*h - f*h*(9*g + 2*h) + e*e*(f - 6*g + 6*h) +
- e*(9*f*g + 6*g*g - 17*f*h - 3*g*h + 3*h*h)) -
- d*(e*e*e + e*e*(-6*f - 3*g + 7*h) - 9*(2*f - g)*(f*f + g*g - f*(g + h)) +
- e*(18*f*f + 9*g*g + 3*g*h + h*h - 3*f*(3*g + 7*h)))) )
- ;
-}
-
-// + Power(x,2)*(3*(a - 3*b + 3*c - d)*Power(e - 3*f + 3*g - h,2)*y)
-static double calc_xxy(double a3b3cd, double e3f3gh) {
- return 3 * a3b3cd * e3f3gh * e3f3gh;
-}
-
-static double calc_x(double a, double b, double c, double d,
- double e, double f, double g, double h) {
- return
-// + x*
-(-3*(27*b*b*e*g*g - 27*a*b*f*g*g + 9*a*a*g*g*g - 18*b*b*e*f*h + 18*a*b*f*f*h + 3*a*b*e*g*h -
- 27*b*b*e*g*h - 9*a*a*f*g*h + 27*a*b*f*g*h - 9*a*a*g*g*h + a*a*e*h*h - 9*a*b*e*h*h +
- 27*b*b*e*h*h + 6*a*a*f*h*h - 18*a*b*f*h*h - 9*b*b*f*h*h + 3*a*a*g*h*h +
- 6*a*b*g*h*h - a*a*h*h*h + 9*c*c*(e*e*(g - 3*h) - 3*f*f*h + e*(3*f + 2*g)*h) +
- d*d*(e*e*e - 9*f*f*f + 9*e*f*(f + g) - e*e*(3*f + 6*g + h)) +
- d*(-3*c*(-9*f*f*g + e*e*(2*f - 6*g - 3*h) + e*(9*f*g + 6*g*g + f*h)) +
- a*(-18*f*f*f - 18*e*g*g + 18*g*g*g - 2*e*e*h + 3*e*g*h + 2*e*h*h + 9*f*f*(3*g + 2*h) +
- 3*f*(6*e*g - 9*g*g - e*h - 6*g*h)) - 3*b*(9*f*g*g + e*e*(4*g - 3*h) - 6*f*f*h -
- e*(6*f*f + g*(18*g + h) - 3*f*(3*g + 4*h)))) +
- 3*c*(3*b*(e*e*h + 3*f*g*h - e*(3*f*g - 6*f*h + 6*g*h + h*h)) +
- a*(9*f*f*(g - 2*h) + f*h*(-e + 9*g + 4*h) - 3*(2*g*g*h + e*(2*g*g - 4*g*h + h*h))))) )
- ;
-}
-
-static double calc_xy(double a, double b, double c, double d,
- double e, double f, double g, double h) {
- return
-// + x*3*
-(-2*a*d*e*e - 7*d*d*e*e + 15*a*d*e*f + 21*d*d*e*f - 9*a*d*f*f - 18*d*d*f*f - 15*a*d*e*g -
- 3*d*d*e*g - 9*a*a*f*g + 9*d*d*f*g + 18*a*a*g*g + 9*a*d*g*g + 2*a*a*e*h - 2*d*d*e*h +
- 3*a*a*f*h + 15*a*d*f*h - 21*a*a*g*h - 15*a*d*g*h + 7*a*a*h*h + 2*a*d*h*h -
- 9*c*c*(2*e*e + 3*f*f + 3*f*h - 2*g*h + e*(-3*f - 4*g + h)) +
- 9*b*b*(3*g*g - 3*g*h + 2*h*(-2*f + h) + e*(-2*f + 3*g + h)) +
- 3*b*(3*c*(e*e + 3*e*(f - 3*g) + (9*f - 3*g - h)*h) + a*(6*f*f + e*g - 9*f*g - 9*g*g - 5*e*h + 9*f*h + 14*g*h - 7*h*h) +
- d*(-e*e + 12*f*f - 27*f*g + e*(-9*f + 20*g - 5*h) + g*(9*g + h))) +
- 3*c*(a*(-(e*f) - 9*f*f + 27*f*g - 12*g*g + 5*e*h - 20*f*h + 9*g*h + h*h) +
- d*(7*e*e + 9*f*f + 9*f*g - 6*g*g - f*h + e*(-14*f - 9*g + 5*h)))) // *y
- ;
-}
-
-// - x*3*Power(a - 3*b + 3*c - d,2)*(e - 3*f + 3*g - h)*Power(y,2)
-static double calc_xyy(double a3b3cd, double e3f3gh) {
- return -3 * a3b3cd * a3b3cd * e3f3gh;
-}
-
-#endif
-
-static double (*calc_proc[])(double a, double b, double c, double d,
- double e, double f, double g, double h) = {
- calc_xx, calc_xy, calc_yy, calc_x, calc_y, calc_c
-};
-
-#if USE_SYVESTER
-/* Control points to parametric coefficients
- s = 1 - t
- Attt + 3Btts + 3Ctss + Dsss ==
- Attt + 3B(1 - t)tt + 3C(1 - t)(t - tt) + D(1 - t)(1 - 2t + tt) ==
- Attt + 3B(tt - ttt) + 3C(t - tt - tt + ttt) + D(1-2t+tt-t+2tt-ttt) ==
- Attt + 3Btt - 3Bttt + 3Ct - 6Ctt + 3Cttt + D - 3Dt + 3Dtt - Dttt ==
- D + (3C - 3D)t + (3B - 6C + 3D)tt + (A - 3B + 3C - D)ttt
- a = A - 3*B + 3*C - D
- b = 3*B - 6*C + 3*D
- c = 3*C - 3*D
- d = D
- */
-
- /* http://www.algorithmist.net/bezier3.html
- p = 3 * A
- q = 3 * B
- r = 3 * C
- a = A
- b = q - p
- c = p - 2 * q + r
- d = D - A + q - r
-
- B(t) = a + t * (b + t * (c + t * d))
-
- so
-
- B(t) = a + t*b + t*t*(c + t*d)
- = a + t*b + t*t*c + t*t*t*d
- */
-static void set_abcd(const double* cubic, double& a, double& b, double& c,
- double& d) {
- a = cubic[0]; // a = A
- b = 3 * cubic[2]; // b = 3*B (compute rest of b lazily)
- c = 3 * cubic[4]; // c = 3*C (compute rest of c lazily)
- d = cubic[6]; // d = D
- a += -b + c - d; // a = A - 3*B + 3*C - D
-}
-
-static void calc_bc(const double d, double& b, double& c) {
- b -= 3 * c; // b = 3*B - 3*C
- c -= 3 * d; // c = 3*C - 3*D
- b -= c; // b = 3*B - 6*C + 3*D
-}
-
-static void alt_set_abcd(const double* cubic, double& a, double& b, double& c,
- double& d) {
- a = cubic[0];
- double p = 3 * a;
- double q = 3 * cubic[2];
- double r = 3 * cubic[4];
- b = q - p;
- c = p - 2 * q + r;
- d = cubic[6] - a + q - r;
-}
-
-const bool try_alt = true;
-
-#else
-
-static void calc_ABCD(double a, double b, double c, double d,
- double e, double f, double g, double h,
- double p[coeff_count]) {
- double a3b3cd = a - 3 * (b - c) - d;
- double e3f3gh = e - 3 * (f - g) - h;
- p[xxx_coeff] = calc_xxx(e3f3gh);
- p[xxy_coeff] = calc_xxy(a3b3cd, e3f3gh);
- p[xyy_coeff] = calc_xyy(a3b3cd, e3f3gh);
- p[yyy_coeff] = calc_yyy(a3b3cd);
-}
-#endif
-
-bool implicit_matches(const Cubic& one, const Cubic& two) {
- double p1[coeff_count]; // a'xxx , b'xxy , c'xyy , d'xx , e'xy , f'yy, etc.
- double p2[coeff_count];
-#if USE_SYVESTER
- double a1, b1, c1, d1;
- if (try_alt)
- alt_set_abcd(&one[0].x, a1, b1, c1, d1);
- else
- set_abcd(&one[0].x, a1, b1, c1, d1);
- double e1, f1, g1, h1;
- if (try_alt)
- alt_set_abcd(&one[0].y, e1, f1, g1, h1);
- else
- set_abcd(&one[0].y, e1, f1, g1, h1);
- calc_ABCD(a1, e1, p1);
- double a2, b2, c2, d2;
- if (try_alt)
- alt_set_abcd(&two[0].x, a2, b2, c2, d2);
- else
- set_abcd(&two[0].x, a2, b2, c2, d2);
- double e2, f2, g2, h2;
- if (try_alt)
- alt_set_abcd(&two[0].y, e2, f2, g2, h2);
- else
- set_abcd(&two[0].y, e2, f2, g2, h2);
- calc_ABCD(a2, e2, p2);
-#else
- double a1 = one[0].x;
- double b1 = one[1].x;
- double c1 = one[2].x;
- double d1 = one[3].x;
- double e1 = one[0].y;
- double f1 = one[1].y;
- double g1 = one[2].y;
- double h1 = one[3].y;
- calc_ABCD(a1, b1, c1, d1, e1, f1, g1, h1, p1);
- double a2 = two[0].x;
- double b2 = two[1].x;
- double c2 = two[2].x;
- double d2 = two[3].x;
- double e2 = two[0].y;
- double f2 = two[1].y;
- double g2 = two[2].y;
- double h2 = two[3].y;
- calc_ABCD(a2, b2, c2, d2, e2, f2, g2, h2, p2);
-#endif
- int first = 0;
- for (int index = 0; index < coeff_count; ++index) {
-#if USE_SYVESTER
- if (!try_alt && index == xx_coeff) {
- calc_bc(d1, b1, c1);
- calc_bc(h1, f1, g1);
- calc_bc(d2, b2, c2);
- calc_bc(h2, f2, g2);
- }
-#endif
- if (index >= xx_coeff) {
- int procIndex = index - xx_coeff;
- p1[index] = (*calc_proc[procIndex])(a1, b1, c1, d1, e1, f1, g1, h1);
- p2[index] = (*calc_proc[procIndex])(a2, b2, c2, d2, e2, f2, g2, h2);
- }
- if (approximately_zero(p1[index]) || approximately_zero(p2[index])) {
- first += first == index;
- continue;
- }
- if (first == index) {
- continue;
- }
- if (!AlmostEqualUlps(p1[index] * p2[first], p1[first] * p2[index])) {
- return false;
- }
- }
- return true;
-}
-
-static double tangent(const double* cubic, double t) {
- double a, b, c, d;
-#if USE_SYVESTER
- set_abcd(cubic, a, b, c, d);
- calc_bc(d, b, c);
-#else
- coefficients(cubic, a, b, c, d);
-#endif
- return 3 * a * t * t + 2 * b * t + c;
-}
-
-void tangent(const Cubic& cubic, double t, _Point& result) {
- result.x = tangent(&cubic[0].x, t);
- result.y = tangent(&cubic[0].y, t);
-}
-
-// unit test to return and validate parametric coefficients
-#include "CubicParameterization_TestUtility.cpp"
diff --git a/experimental/Intersection/CubicParameterizationCode.cpp b/experimental/Intersection/CubicParameterizationCode.cpp
deleted file mode 100644
index 7a7908e67f..0000000000
--- a/experimental/Intersection/CubicParameterizationCode.cpp
+++ /dev/null
@@ -1,405 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include <vector>
-
-/* Given:
- * Resultant[a*t^3 + b*t^2 + c*t + d - x, e*t^3 + f*t^2 + g*t + h - y, t]
- */
-
-const char result1[] =
-"-d^3 e^3 + c d^2 e^2 f - b d^2 e f^2 + a d^2 f^3 - c^2 d e^2 g + "
-" 2 b d^2 e^2 g + b c d e f g - 3 a d^2 e f g - a c d f^2 g - "
-" b^2 d e g^2 + 2 a c d e g^2 + a b d f g^2 - a^2 d g^3 + c^3 e^2 h - "
-" 3 b c d e^2 h + 3 a d^2 e^2 h - b c^2 e f h + 2 b^2 d e f h + "
-" a c d e f h + a c^2 f^2 h - 2 a b d f^2 h + b^2 c e g h - "
-" 2 a c^2 e g h - a b d e g h - a b c f g h + 3 a^2 d f g h + "
-" a^2 c g^2 h - b^3 e h^2 + 3 a b c e h^2 - 3 a^2 d e h^2 + "
-" a b^2 f h^2 - 2 a^2 c f h^2 - a^2 b g h^2 + a^3 h^3 + 3 d^2 e^3 x - "
-" 2 c d e^2 f x + 2 b d e f^2 x - 2 a d f^3 x + c^2 e^2 g x - "
-" 4 b d e^2 g x - b c e f g x + 6 a d e f g x + a c f^2 g x + "
-" b^2 e g^2 x - 2 a c e g^2 x - a b f g^2 x + a^2 g^3 x + "
-" 3 b c e^2 h x - 6 a d e^2 h x - 2 b^2 e f h x - a c e f h x + "
-" 2 a b f^2 h x + a b e g h x - 3 a^2 f g h x + 3 a^2 e h^2 x - "
-" 3 d e^3 x^2 + c e^2 f x^2 - b e f^2 x^2 + a f^3 x^2 + "
-" 2 b e^2 g x^2 - 3 a e f g x^2 + 3 a e^2 h x^2 + e^3 x^3 - "
-" c^3 e^2 y + 3 b c d e^2 y - 3 a d^2 e^2 y + b c^2 e f y - "
-" 2 b^2 d e f y - a c d e f y - a c^2 f^2 y + 2 a b d f^2 y - "
-" b^2 c e g y + 2 a c^2 e g y + a b d e g y + a b c f g y - "
-" 3 a^2 d f g y - a^2 c g^2 y + 2 b^3 e h y - 6 a b c e h y + "
-" 6 a^2 d e h y - 2 a b^2 f h y + 4 a^2 c f h y + 2 a^2 b g h y - "
-" 3 a^3 h^2 y - 3 b c e^2 x y + 6 a d e^2 x y + 2 b^2 e f x y + "
-" a c e f x y - 2 a b f^2 x y - a b e g x y + 3 a^2 f g x y - "
-" 6 a^2 e h x y - 3 a e^2 x^2 y - b^3 e y^2 + 3 a b c e y^2 - "
-" 3 a^2 d e y^2 + a b^2 f y^2 - 2 a^2 c f y^2 - a^2 b g y^2 + "
-" 3 a^3 h y^2 + 3 a^2 e x y^2 - a^3 y^3";
-
-const size_t len1 = sizeof(result1) - 1;
-
-/* Given:
- * Expand[
- * Det[{{a, b, c, (d - x), 0, 0},
- * {0, a, b, c, (d - x), 0},
- * {0, 0, a, b, c, (d - x)},
- * {e, f, g, (h - y), 0, 0},
- * {0, e, f, g, (h - y), 0},
- * {0, 0, e, f, g, (h - y)}}]]
- */
- // result1 and result2 are the same. 102 factors:
-const char result2[] =
-"-d^3 e^3 + c d^2 e^2 f - b d^2 e f^2 + a d^2 f^3 - c^2 d e^2 g + "
-" 2 b d^2 e^2 g + b c d e f g - 3 a d^2 e f g - a c d f^2 g - "
-" b^2 d e g^2 + 2 a c d e g^2 + a b d f g^2 - a^2 d g^3 + c^3 e^2 h - "
-" 3 b c d e^2 h + 3 a d^2 e^2 h - b c^2 e f h + 2 b^2 d e f h + "
-" a c d e f h + a c^2 f^2 h - 2 a b d f^2 h + b^2 c e g h - "
-" 2 a c^2 e g h - a b d e g h - a b c f g h + 3 a^2 d f g h + "
-" a^2 c g^2 h - b^3 e h^2 + 3 a b c e h^2 - 3 a^2 d e h^2 + "
-" a b^2 f h^2 - 2 a^2 c f h^2 - a^2 b g h^2 + a^3 h^3 + 3 d^2 e^3 x - "
-" 2 c d e^2 f x + 2 b d e f^2 x - 2 a d f^3 x + c^2 e^2 g x - "
-" 4 b d e^2 g x - b c e f g x + 6 a d e f g x + a c f^2 g x + "
-" b^2 e g^2 x - 2 a c e g^2 x - a b f g^2 x + a^2 g^3 x + "
-" 3 b c e^2 h x - 6 a d e^2 h x - 2 b^2 e f h x - a c e f h x + "
-" 2 a b f^2 h x + a b e g h x - 3 a^2 f g h x + 3 a^2 e h^2 x - "
-" 3 d e^3 x^2 + c e^2 f x^2 - b e f^2 x^2 + a f^3 x^2 + "
-" 2 b e^2 g x^2 - 3 a e f g x^2 + 3 a e^2 h x^2 + e^3 x^3 - "
-" c^3 e^2 y + 3 b c d e^2 y - 3 a d^2 e^2 y + b c^2 e f y - "
-" 2 b^2 d e f y - a c d e f y - a c^2 f^2 y + 2 a b d f^2 y - "
-" b^2 c e g y + 2 a c^2 e g y + a b d e g y + a b c f g y - "
-" 3 a^2 d f g y - a^2 c g^2 y + 2 b^3 e h y - 6 a b c e h y + "
-" 6 a^2 d e h y - 2 a b^2 f h y + 4 a^2 c f h y + 2 a^2 b g h y - "
-" 3 a^3 h^2 y - 3 b c e^2 x y + 6 a d e^2 x y + 2 b^2 e f x y + "
-" a c e f x y - 2 a b f^2 x y - a b e g x y + 3 a^2 f g x y - "
-" 6 a^2 e h x y - 3 a e^2 x^2 y - b^3 e y^2 + 3 a b c e y^2 - "
-" 3 a^2 d e y^2 + a b^2 f y^2 - 2 a^2 c f y^2 - a^2 b g y^2 + "
-" 3 a^3 h y^2 + 3 a^2 e x y^2 - a^3 y^3";
-
-const size_t len2 = sizeof(result2) - 1;
-
-/* Given: r1 = Resultant[
- * a*(1 - t)^3 + 3*b*(1 - t)^2*t + 3*c*(1 - t)*t^2 + d*t^3 - x,
- * e*(1 - t)^3 + 3*f*(1 - t)^2*t + 3*g*(1 - t)*t^2 + h*t^3 - y, t]
- * Collect[r1, {x, y}, Simplify]
- * CForm[%]
- * then use regex to replace Power\(([a-h]),3\) with \1*\1*\1
- * and Power\(([a-h]),2\) with \1*\1
- * yields:
-
-d*d*d*e*e*e - 3*d*d*(3*c*e*e*f + 3*b*e*(-3*f*f + 2*e*g) + a*(9*f*f*f - 9*e*f*g + e*e*h)) -
- h*(27*c*c*c*e*e - 27*c*c*(3*b*e*f - 3*a*f*f + 2*a*e*g) +
- h*(-27*b*b*b*e + 27*a*b*b*f - 9*a*a*b*g + a*a*a*h) +
- 9*c*(9*b*b*e*g + a*b*(-9*f*g + 3*e*h) + a*a*(3*g*g - 2*f*h))) +
- 3*d*(9*c*c*e*e*g + 9*b*b*e*(3*g*g - 2*f*h) + 3*a*b*(-9*f*g*g + 6*f*f*h + e*g*h) +
- a*a*(9*g*g*g - 9*f*g*h + e*h*h) + 3*c*(3*b*e*(-3*f*g + e*h) + a*(9*f*f*g - 6*e*g*g - e*f*h)))
-
-- Power(e - 3*f + 3*g - h,3)*Power(x,3)
-
-+ 3*(6*b*d*d*e*e - d*d*d*e*e + 18*b*b*d*e*f - 18*b*d*d*e*f -
- 9*b*d*d*f*f - 54*b*b*d*e*g + 12*b*d*d*e*g - 27*b*b*d*g*g - 18*b*b*b*e*h + 18*b*b*d*e*h +
- 18*b*b*d*f*h + a*a*a*h*h - 9*b*b*b*h*h + 9*c*c*c*e*(e + 2*h) +
- a*a*(-3*b*h*(2*g + h) + d*(-27*g*g + 9*g*h - h*(2*e + h) + 9*f*(g + h))) +
- a*(9*b*b*h*(2*f + h) - 3*b*d*(6*f*f - 6*f*(3*g - 2*h) + g*(-9*g + h) + e*(g + h)) +
- d*d*(e*e + 9*f*(3*f - g) + e*(-9*f - 9*g + 2*h))) -
- 9*c*c*(d*e*(e + 2*g) + 3*b*(f*h + e*(f + h)) + a*(-3*f*f - 6*f*h + 2*(g*h + e*(g + h)))) +
- 3*c*(d*d*e*(e + 2*f) + a*a*(3*g*g + 6*g*h - 2*h*(2*f + h)) + 9*b*b*(g*h + e*(g + h)) +
- a*d*(-9*f*f - 18*f*g + 6*g*g + f*h + e*(f + 12*g + h)) +
- b*(d*(-3*e*e + 9*f*g + e*(9*f + 9*g - 6*h)) + 3*a*(h*(2*e - 3*g + h) - 3*f*(g + h)))))*y
-
-- 3*(18*c*c*c*e - 18*c*c*d*e + 6*c*d*d*e - d*d*d*e + 3*c*d*d*f - 9*c*c*d*g + a*a*a*h + 9*c*c*c*h -
- 9*b*b*b*(e + 2*h) - a*a*(d*(e - 9*f + 18*g - 7*h) + 3*c*(2*f - 6*g + h)) +
- a*(-9*c*c*(2*e - 6*f + 2*g - h) + d*d*(-7*e + 18*f - 9*g + h) + 3*c*d*(7*e - 17*f + 3*g + h)) +
- 9*b*b*(3*c*(e + g + h) + a*(f + 2*h) - d*(e - 2*(f - 3*g + h))) -
- 3*b*(-(d*d*(e - 6*f + 2*g)) - 3*c*d*(e + 3*f + 3*g - h) + 9*c*c*(e + f + h) + a*a*(g + 2*h) +
- a*(c*(-3*e + 9*f + 9*g + 3*h) + d*(e + 3*f - 17*g + 7*h))))*Power(y,2)
-
-+ Power(a - 3*b + 3*c - d,3)*Power(y,3)
-
-+ Power(x,2)*(-3*(-9*b*e*f*f + 9*a*f*f*f + 6*b*e*e*g - 9*a*e*f*g + 27*b*e*f*g - 27*a*f*f*g + 18*a*e*g*g - 54*b*e*g*g +
- 27*a*f*g*g + 27*b*f*g*g - 18*a*g*g*g + a*e*e*h - 9*b*e*e*h + 3*a*e*f*h + 9*b*e*f*h + 9*a*f*f*h -
- 18*b*f*f*h - 21*a*e*g*h + 51*b*e*g*h - 9*a*f*g*h - 27*b*f*g*h + 18*a*g*g*h + 7*a*e*h*h - 18*b*e*h*h - 3*a*f*h*h +
- 18*b*f*h*h - 6*a*g*h*h - 3*b*g*h*h + a*h*h*h +
- 3*c*(-9*f*f*(g - 2*h) + 3*g*g*h - f*h*(9*g + 2*h) + e*e*(f - 6*g + 6*h) +
- e*(9*f*g + 6*g*g - 17*f*h - 3*g*h + 3*h*h)) -
- d*(e*e*e + e*e*(-6*f - 3*g + 7*h) - 9*(2*f - g)*(f*f + g*g - f*(g + h)) +
- e*(18*f*f + 9*g*g + 3*g*h + h*h - 3*f*(3*g + 7*h)))) )
-
-+ Power(x,2)*(3*(a - 3*b + 3*c - d)*Power(e - 3*f + 3*g - h,2)*y)
-
-+ x*(-3*(27*b*b*e*g*g - 27*a*b*f*g*g + 9*a*a*g*g*g - 18*b*b*e*f*h + 18*a*b*f*f*h + 3*a*b*e*g*h -
- 27*b*b*e*g*h - 9*a*a*f*g*h + 27*a*b*f*g*h - 9*a*a*g*g*h + a*a*e*h*h - 9*a*b*e*h*h +
- 27*b*b*e*h*h + 6*a*a*f*h*h - 18*a*b*f*h*h - 9*b*b*f*h*h + 3*a*a*g*h*h +
- 6*a*b*g*h*h - a*a*h*h*h + 9*c*c*(e*e*(g - 3*h) - 3*f*f*h + e*(3*f + 2*g)*h) +
- d*d*(e*e*e - 9*f*f*f + 9*e*f*(f + g) - e*e*(3*f + 6*g + h)) +
- d*(-3*c*(-9*f*f*g + e*e*(2*f - 6*g - 3*h) + e*(9*f*g + 6*g*g + f*h)) +
- a*(-18*f*f*f - 18*e*g*g + 18*g*g*g - 2*e*e*h + 3*e*g*h + 2*e*h*h + 9*f*f*(3*g + 2*h) +
- 3*f*(6*e*g - 9*g*g - e*h - 6*g*h)) - 3*b*(9*f*g*g + e*e*(4*g - 3*h) - 6*f*f*h -
- e*(6*f*f + g*(18*g + h) - 3*f*(3*g + 4*h)))) +
- 3*c*(3*b*(e*e*h + 3*f*g*h - e*(3*f*g - 6*f*h + 6*g*h + h*h)) +
- a*(9*f*f*(g - 2*h) + f*h*(-e + 9*g + 4*h) - 3*(2*g*g*h + e*(2*g*g - 4*g*h + h*h))))) )
-
-+ x*3*(-2*a*d*e*e - 7*d*d*e*e + 15*a*d*e*f + 21*d*d*e*f - 9*a*d*f*f - 18*d*d*f*f - 15*a*d*e*g -
- 3*d*d*e*g - 9*a*a*f*g + 9*d*d*f*g + 18*a*a*g*g + 9*a*d*g*g + 2*a*a*e*h - 2*d*d*e*h +
- 3*a*a*f*h + 15*a*d*f*h - 21*a*a*g*h - 15*a*d*g*h + 7*a*a*h*h + 2*a*d*h*h -
- 9*c*c*(2*e*e + 3*f*f + 3*f*h - 2*g*h + e*(-3*f - 4*g + h)) +
- 9*b*b*(3*g*g - 3*g*h + 2*h*(-2*f + h) + e*(-2*f + 3*g + h)) +
- 3*b*(3*c*(e*e + 3*e*(f - 3*g) + (9*f - 3*g - h)*h) + a*(6*f*f + e*g - 9*f*g - 9*g*g - 5*e*h + 9*f*h + 14*g*h - 7*h*h) +
- d*(-e*e + 12*f*f - 27*f*g + e*(-9*f + 20*g - 5*h) + g*(9*g + h))) +
- 3*c*(a*(-(e*f) - 9*f*f + 27*f*g - 12*g*g + 5*e*h - 20*f*h + 9*g*h + h*h) +
- d*(7*e*e + 9*f*f + 9*f*g - 6*g*g - f*h + e*(-14*f - 9*g + 5*h))))*y
-
-- x*3*Power(a - 3*b + 3*c - d,2)*(e - 3*f + 3*g - h)*Power(y,2)
-
-*/
-
-const int factors = 8;
-
-struct coeff {
- int s; // constant and coefficient sign
- int n[factors]; // 0 or power of a (1, 2, or 3) for a through h
-};
-
-enum {
- xxx_coeff,
- xxy_coeff,
- xyy_coeff,
- yyy_coeff,
- xx_coeff,
- xy_coeff,
- yy_coeff,
- x_coeff,
- y_coeff,
- c_coeff,
- coeff_count
-};
-
-typedef std::vector<coeff> coeffs;
-typedef std::vector<coeffs> n_coeffs;
-
-static char skipSpace(const char* str, size_t& index) {
- do {
- ++index;
- } while (str[index] == ' ');
- return str[index];
-}
-
-static char backSkipSpace(const char* str, size_t& end) {
- while (str[end - 1] == ' ') {
- --end;
- }
- return str[end - 1];
-}
-
-static void match(const char* str, size_t len, coeffs& co, const char pattern[]) {
- size_t patternLen = strlen(pattern);
- size_t index = 0;
- while (index < len) {
- char ch = str[index];
- if (ch != '-' && ch != '+') {
- printf("missing sign\n");
- }
- size_t end = index + 1;
- while (str[end] != '+' && str[end] != '-' && ++end < len) {
- ;
- }
- backSkipSpace(str, end);
- size_t idx = index;
- index = end;
- skipSpace(str, index);
- if (!strncmp(&str[end - patternLen], pattern, patternLen) == 0) {
- continue;
- }
- size_t endCoeff = end - patternLen;
- char last = backSkipSpace(str, endCoeff);
- if (last == '2' || last == '3') {
- last = str[endCoeff - 3]; // skip ^2
- }
- if (last == 'x' || last == 'y') {
- continue;
- }
- coeff c;
- c.s = str[idx] == '-' ? -1 : 1;
- bzero(c.n, sizeof(c.n));
- ch = skipSpace(str, idx);
- if (ch >= '2' && ch <= '6') {
- c.s *= ch - '0';
- ch = skipSpace(str, idx);
- }
- while (idx < endCoeff) {
- char x = str[idx];
- if (x < 'a' || x > 'a' + factors) {
- printf("expected factor\n");
- }
- idx++;
- int pow = 1;
- if (str[idx] == '^') {
- idx++;
- char exp = str[idx];
- if (exp < '2' || exp > '3') {
- printf("expected exponent\n");
- }
- pow = exp - '0';
- }
- skipSpace(str, idx);
- c.n[x - 'a'] = pow;
- }
- co.push_back(c);
- }
-}
-
-void cubecode_test(int test);
-
-void cubecode_test(int test) {
- const char* str = test ? result2 : result1;
- size_t len = strlen(str);
- n_coeffs c(coeff_count);
- match(str, len, c[xxx_coeff], "x^3"); // 1 factor
- match(str, len, c[xxy_coeff], "x^2 y"); // 1 factor
- match(str, len, c[xyy_coeff], "x y^2"); // 1 factor
- match(str, len, c[yyy_coeff], "y^3"); // 1 factor
- match(str, len, c[xx_coeff], "x^2"); // 7 factors
- match(str, len, c[xy_coeff], "x y"); // 8 factors
- match(str, len, c[yy_coeff], "y^2"); // 7 factors
- match(str, len, c[x_coeff], "x"); // 21 factors
- match(str, len, c[y_coeff], "y"); // 21 factors
- match(str, len, c[c_coeff], ""); // 34 factors : total 102
-#define COMPUTE_MOST_FREQUENT_EXPRESSION_TRIPLETS 0
-#define WRITE_AS_NONOPTIMIZED_C_CODE 0
-#if COMPUTE_MOST_FREQUENT_EXPRESSION_TRIPLETS
- int count[factors][factors][factors];
- bzero(count, sizeof(count));
-#endif
-#if WRITE_AS_NONOPTIMIZED_C_CODE
- printf("// start of generated code");
-#endif
- for (n_coeffs::iterator it = c.begin(); it < c.end(); ++it) {
- coeffs& co = *it;
-#if WRITE_AS_NONOPTIMIZED_C_CODE
- printf("\nstatic double calc_%c(double a, double b, double c, double d,"
- "\n double e, double f, double g, double h) {"
- "\n return"
- "\n ", 'A' + (it - c.begin()));
- if (co[0].s > 0) {
- printf(" ");
- }
- if (abs(co[0].s) == 1) {
- printf(" ");
- }
-#endif
- for (coeffs::iterator ct = co.begin(); ct < co.end(); ++ct) {
- const coeff& cf = *ct;
-#if WRITE_AS_NONOPTIMIZED_C_CODE
- printf(" ");
- bool firstFactor = false;
- if (ct - co.begin() > 0 || cf.s < 0) {
- printf("%c", cf.s < 0 ? '-' : '+');
- }
- if (ct - co.begin() > 0) {
- printf(" ");
- }
- if (abs(cf.s) > 1) {
- printf("%d * ", abs(cf.s));
- } else {
- if (ct - co.begin() > 0) {
- printf(" ");
- }
- }
-#endif
- for (int x = 0; x < factors; ++x) {
- if (cf.n[x] == 0) {
- continue;
- }
-#if WRITE_AS_NONOPTIMIZED_C_CODE
- for (int y = 0 ; y < cf.n[x]; ++y) {
- if (y > 0 || firstFactor) {
- printf(" * ");
- }
- printf("%c", 'a' + x);
- }
- firstFactor = true;
-#endif
-#if COMPUTE_MOST_FREQUENT_EXPRESSION_TRIPLETS
- for (int y = x; y < factors; ++y) {
- if (cf.n[y] == 0) {
- continue;
- }
- if (x == y && cf.n[y] == 1) {
- continue;
- }
- for (int z = y; z < factors; ++z) {
- if (cf.n[z] == 0) {
- continue;
- }
- if ((x == z || y == z) && cf.n[z] == 1) {
- continue;
- }
- if (x == y && y == z && cf.n[z] == 2) {
- continue;
- }
- count[x][y][z]++;
- }
- }
-#endif
- }
-#if WRITE_AS_NONOPTIMIZED_C_CODE
- if (ct + 1 < co.end()) {
- printf("\n");
- }
-#endif
- }
-#if WRITE_AS_NONOPTIMIZED_C_CODE
- printf(";\n}\n");
-#endif
- }
-#if WRITE_AS_NONOPTIMIZED_C_CODE
- printf("// end of generated code\n");
-#endif
-#if COMPUTE_MOST_FREQUENT_EXPRESSION_TRIPLETS
- const int bestCount = 20;
- int best[bestCount][4];
- bzero(best, sizeof(best));
- for (int x = 0; x < factors; ++x) {
- for (int y = x; y < factors; ++y) {
- for (int z = y; z < factors; ++z) {
- if (!count[x][y][z]) {
- continue;
- }
- for (int w = 0; w < bestCount; ++w) {
- if (best[w][0] < count[x][y][z]) {
- best[w][0] = count[x][y][z];
- best[w][1] = x;
- best[w][2] = y;
- best[w][3] = z;
- break;
- }
- }
- }
- }
- }
- for (int w = 0; w < bestCount; ++w) {
- printf("%c%c%c=%d\n", 'a' + best[w][1], 'a' + best[w][2],
- 'a' + best[w][3], best[w][0]);
- }
-#endif
-#if WRITE_AS_NONOPTIMIZED_C_CODE
- printf("\n");
-#endif
-}
-
-/* results: variable triplets used 10 or more times:
-aah=14
-ade=14
-aeh=14
-dee=14
-bce=13
-beg=13
-beh=12
-bbe=11
-bef=11
-cee=11
-cef=11
-def=11
-ceh=10
-deg=10
-*/
diff --git a/experimental/Intersection/CubicParameterization_Test.cpp b/experimental/Intersection/CubicParameterization_Test.cpp
deleted file mode 100644
index cc095b60fd..0000000000
--- a/experimental/Intersection/CubicParameterization_Test.cpp
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "QuadraticUtilities.h"
-#include "CurveIntersection.h"
-#include "Intersection_Tests.h"
-#include "Parameterization_Test.h"
-#include "TestUtilities.h"
-
-const Quadratic quadratics[] = {
- {{0, 0}, {1, 0}, {1, 1}},
-};
-
-const size_t quadratics_count = sizeof(quadratics) / sizeof(quadratics[0]);
-
-int firstCubicCoincidenceTest = 0;
-
-void CubicCoincidence_Test() {
- // split large quadratic
- // upscale quadratics to cubics
- // compare original, parts, to see if the are coincident
- for (size_t index = firstCubicCoincidenceTest; index < quadratics_count; ++index) {
- const Quadratic& test = quadratics[index];
- QuadraticPair split;
- chop_at(test, split, 0.5);
- Quadratic midThird;
- sub_divide(test, 1.0/3, 2.0/3, midThird);
- Cubic whole, first, second, mid;
- quad_to_cubic(test, whole);
- quad_to_cubic(split.first(), first);
- quad_to_cubic(split.second(), second);
- quad_to_cubic(midThird, mid);
- if (!implicit_matches(whole, first)) {
- SkDebugf("%s-1 %d\n", __FUNCTION__, (int)index);
- }
- if (!implicit_matches(whole, second)) {
- SkDebugf("%s-2 %d\n", __FUNCTION__, (int)index);
- }
- if (!implicit_matches(mid, first)) {
- SkDebugf("%s-3 %d\n", __FUNCTION__, (int)index);
- }
- if (!implicit_matches(mid, second)) {
- SkDebugf("%s-4 %d\n", __FUNCTION__, (int)index);
- }
- if (!implicit_matches(first, second)) {
- SkDebugf("%s-5 %d\n", __FUNCTION__, (int)index);
- }
- }
-}
-
-// pairs of coincident cubics
-// The on curve points of each cubic should be on both parameterized cubics.
-const Cubic cubics[] = {
- {
- { 1, -1},
- { 1.0/3, 1},
- {-1.0/3, -1},
- {-1, 1}
- },
- {
- {-1, 1},
- {-1.0/3, -1},
- { 1.0/3, 1},
- { 1, -1}
- },
- {
- {0, 2},
- {0, 1},
- {1, 0},
- {2, 0}
- }, {
- {2, 0},
- {1, 0},
- {0, 1},
- {0, 2}
- },
- {
- {315.74799999999999, 312.83999999999997},
- {312.64400000000001, 318.13400000000001},
- {305.83600000000001, 319.90899999999999},
- {300.54199999999997, 316.80399999999997}
- }, {
- {317.12200000000001, 309.05000000000001},
- {316.11200000000002, 315.10199999999998},
- {310.38499999999999, 319.19},
- {304.33199999999999, 318.17899999999997}
- }
-};
-
-const size_t cubics_count = sizeof(cubics) / sizeof(cubics[0]);
-
-int firstCubicParameterizationTest = 0;
-
-void CubicParameterization_Test() {
- for (size_t index = firstCubicParameterizationTest; index < cubics_count; ++index) {
- for (size_t inner = 0; inner < 4; inner += 3) {
- if (!point_on_parameterized_curve(cubics[index], cubics[index][inner])) {
- SkDebugf("%s [%zu,%zu] 1 parameterization failed\n",
- __FUNCTION__, index, inner);
- }
- if (!point_on_parameterized_curve(cubics[index], cubics[index ^ 1][inner])) {
- SkDebugf("%s [%zu,%zu] 2 parameterization failed\n",
- __FUNCTION__, index, inner);
- }
- }
- if (!implicit_matches(cubics[index], cubics[index ^ 1])) {
- SkDebugf("%s %d\n", __FUNCTION__, (int)index);
- }
- }
-}
diff --git a/experimental/Intersection/CubicParameterization_TestUtility.cpp b/experimental/Intersection/CubicParameterization_TestUtility.cpp
deleted file mode 100644
index 356ca88f85..0000000000
--- a/experimental/Intersection/CubicParameterization_TestUtility.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-// included by CubicParameterization.cpp
-// accesses internal functions to validate parameterized coefficients
-
-#include "Parameterization_Test.h"
-
-static void parameter_coeffs(const Cubic& cubic, double coeffs[coeff_count]) {
-#if USE_SYVESTER
- double ax, bx, cx, dx;
- if (try_alt)
- alt_set_abcd(&cubic[0].x, ax, bx, cx, dx);
- else
- set_abcd(&cubic[0].x, ax, bx, cx, dx);
- double ay, by, cy, dy;
- if (try_alt)
- alt_set_abcd(&cubic[0].y, ay, by, cy, dy);
- else
- set_abcd(&cubic[0].y, ay, by, cy, dy);
- calc_ABCD(ax, ay, coeffs);
- if (!try_alt) calc_bc(dx, bx, cx);
- if (!try_alt) calc_bc(dy, by, cy);
-#else
- double ax = cubic[0].x;
- double bx = cubic[1].x;
- double cx = cubic[2].x;
- double dx = cubic[3].x;
- double ay = cubic[0].y;
- double by = cubic[1].y;
- double cy = cubic[2].y;
- double dy = cubic[3].y;
- calc_ABCD(ax, bx, cx, dx, ay, by, cy, dy, coeffs);
-#endif
- for (int index = xx_coeff; index < coeff_count; ++index) {
- int procIndex = index - xx_coeff;
- coeffs[index] = (*calc_proc[procIndex])(ax, bx, cx, dx, ay, by, cy, dy);
- }
-}
-
-bool point_on_parameterized_curve(const Cubic& cubic, const _Point& point) {
- double coeffs[coeff_count];
- parameter_coeffs(cubic, coeffs);
- double xxx = coeffs[xxx_coeff] * point.x * point.x * point.x;
- double xxy = coeffs[xxy_coeff] * point.x * point.x * point.y;
- double xyy = coeffs[xyy_coeff] * point.x * point.y * point.y;
- double yyy = coeffs[yyy_coeff] * point.y * point.y * point.y;
- double xx = coeffs[ xx_coeff] * point.x * point.x;
- double xy = coeffs[ xy_coeff] * point.x * point.y;
- double yy = coeffs[ yy_coeff] * point.y * point.y;
- double x = coeffs[ x_coeff] * point.x;
- double y = coeffs[ y_coeff] * point.y;
- double c = coeffs[ c_coeff];
- double sum = xxx + xxy + xyy + yyy + xx + xy + yy + x + y + c;
- return approximately_zero(sum);
-}
diff --git a/experimental/Intersection/CubicReduceOrder.cpp b/experimental/Intersection/CubicReduceOrder.cpp
deleted file mode 100644
index f7c0c12d4c..0000000000
--- a/experimental/Intersection/CubicReduceOrder.cpp
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "CurveIntersection.h"
-#include "Extrema.h"
-#include "IntersectionUtilities.h"
-#include "LineParameters.h"
-
-static double interp_cubic_coords(const double* src, double t)
-{
- double ab = interp(src[0], src[2], t);
- double bc = interp(src[2], src[4], t);
- double cd = interp(src[4], src[6], t);
- double abc = interp(ab, bc, t);
- double bcd = interp(bc, cd, t);
- return interp(abc, bcd, t);
-}
-
-static int coincident_line(const Cubic& cubic, Cubic& reduction) {
- reduction[0] = reduction[1] = cubic[0];
- return 1;
-}
-
-static int vertical_line(const Cubic& cubic, ReduceOrder_Styles reduceStyle, Cubic& reduction) {
- double tValues[2];
- reduction[0] = cubic[0];
- reduction[1] = cubic[3];
- if (reduceStyle == kReduceOrder_TreatAsFill) {
- return 2;
- }
- int smaller = reduction[1].y > reduction[0].y;
- int larger = smaller ^ 1;
- int roots = findExtrema(cubic[0].y, cubic[1].y, cubic[2].y, cubic[3].y, tValues);
- for (int index = 0; index < roots; ++index) {
- double yExtrema = interp_cubic_coords(&cubic[0].y, tValues[index]);
- if (reduction[smaller].y > yExtrema) {
- reduction[smaller].y = yExtrema;
- continue;
- }
- if (reduction[larger].y < yExtrema) {
- reduction[larger].y = yExtrema;
- }
- }
- return 2;
-}
-
-static int horizontal_line(const Cubic& cubic, ReduceOrder_Styles reduceStyle, Cubic& reduction) {
- double tValues[2];
- reduction[0] = cubic[0];
- reduction[1] = cubic[3];
- if (reduceStyle == kReduceOrder_TreatAsFill) {
- return 2;
- }
- int smaller = reduction[1].x > reduction[0].x;
- int larger = smaller ^ 1;
- int roots = findExtrema(cubic[0].x, cubic[1].x, cubic[2].x, cubic[3].x, tValues);
- for (int index = 0; index < roots; ++index) {
- double xExtrema = interp_cubic_coords(&cubic[0].x, tValues[index]);
- if (reduction[smaller].x > xExtrema) {
- reduction[smaller].x = xExtrema;
- continue;
- }
- if (reduction[larger].x < xExtrema) {
- reduction[larger].x = xExtrema;
- }
- }
- return 2;
-}
-
-// check to see if it is a quadratic or a line
-static int check_quadratic(const Cubic& cubic, Cubic& reduction) {
- double dx10 = cubic[1].x - cubic[0].x;
- double dx23 = cubic[2].x - cubic[3].x;
- double midX = cubic[0].x + dx10 * 3 / 2;
- if (!AlmostEqualUlps(midX - cubic[3].x, dx23 * 3 / 2)) {
- return 0;
- }
- double dy10 = cubic[1].y - cubic[0].y;
- double dy23 = cubic[2].y - cubic[3].y;
- double midY = cubic[0].y + dy10 * 3 / 2;
- if (!AlmostEqualUlps(midY - cubic[3].y, dy23 * 3 / 2)) {
- return 0;
- }
- reduction[0] = cubic[0];
- reduction[1].x = midX;
- reduction[1].y = midY;
- reduction[2] = cubic[3];
- return 3;
-}
-
-static int check_linear(const Cubic& cubic, ReduceOrder_Styles reduceStyle,
- int minX, int maxX, int minY, int maxY, Cubic& reduction) {
- int startIndex = 0;
- int endIndex = 3;
- while (cubic[startIndex].approximatelyEqual(cubic[endIndex])) {
- --endIndex;
- if (endIndex == 0) {
- printf("%s shouldn't get here if all four points are about equal\n", __FUNCTION__);
- SkASSERT(0);
- }
- }
- if (!isLinear(cubic, startIndex, endIndex)) {
- return 0;
- }
- // four are colinear: return line formed by outside
- reduction[0] = cubic[0];
- reduction[1] = cubic[3];
- if (reduceStyle == kReduceOrder_TreatAsFill) {
- return 2;
- }
- int sameSide1;
- int sameSide2;
- bool useX = cubic[maxX].x - cubic[minX].x >= cubic[maxY].y - cubic[minY].y;
- if (useX) {
- sameSide1 = sign(cubic[0].x - cubic[1].x) + sign(cubic[3].x - cubic[1].x);
- sameSide2 = sign(cubic[0].x - cubic[2].x) + sign(cubic[3].x - cubic[2].x);
- } else {
- sameSide1 = sign(cubic[0].y - cubic[1].y) + sign(cubic[3].y - cubic[1].y);
- sameSide2 = sign(cubic[0].y - cubic[2].y) + sign(cubic[3].y - cubic[2].y);
- }
- if (sameSide1 == sameSide2 && (sameSide1 & 3) != 2) {
- return 2;
- }
- double tValues[2];
- int roots;
- if (useX) {
- roots = findExtrema(cubic[0].x, cubic[1].x, cubic[2].x, cubic[3].x, tValues);
- } else {
- roots = findExtrema(cubic[0].y, cubic[1].y, cubic[2].y, cubic[3].y, tValues);
- }
- for (int index = 0; index < roots; ++index) {
- _Point extrema;
- extrema.x = interp_cubic_coords(&cubic[0].x, tValues[index]);
- extrema.y = interp_cubic_coords(&cubic[0].y, tValues[index]);
- // sameSide > 0 means mid is smaller than either [0] or [3], so replace smaller
- int replace;
- if (useX) {
- if (extrema.x < cubic[0].x ^ extrema.x < cubic[3].x) {
- continue;
- }
- replace = (extrema.x < cubic[0].x | extrema.x < cubic[3].x)
- ^ (cubic[0].x < cubic[3].x);
- } else {
- if (extrema.y < cubic[0].y ^ extrema.y < cubic[3].y) {
- continue;
- }
- replace = (extrema.y < cubic[0].y | extrema.y < cubic[3].y)
- ^ (cubic[0].y < cubic[3].y);
- }
- reduction[replace] = extrema;
- }
- return 2;
-}
-
-bool isLinear(const Cubic& cubic, int startIndex, int endIndex) {
- LineParameters lineParameters;
- lineParameters.cubicEndPoints(cubic, startIndex, endIndex);
- // FIXME: maybe it's possible to avoid this and compare non-normalized
- lineParameters.normalize();
- double distance = lineParameters.controlPtDistance(cubic, 1);
- if (!approximately_zero(distance)) {
- return false;
- }
- distance = lineParameters.controlPtDistance(cubic, 2);
- return approximately_zero(distance);
-}
-
-/* food for thought:
-http://objectmix.com/graphics/132906-fast-precision-driven-cubic-quadratic-piecewise-degree-reduction-algos-2-a.html
-
-Given points c1, c2, c3 and c4 of a cubic Bezier, the points of the
-corresponding quadratic Bezier are (given in convex combinations of
-points):
-
-q1 = (11/13)c1 + (3/13)c2 -(3/13)c3 + (2/13)c4
-q2 = -c1 + (3/2)c2 + (3/2)c3 - c4
-q3 = (2/13)c1 - (3/13)c2 + (3/13)c3 + (11/13)c4
-
-Of course, this curve does not interpolate the end-points, but it would
-be interesting to see the behaviour of such a curve in an applet.
-
---
-Kalle Rutanen
-http://kaba.hilvi.org
-
-*/
-
-// reduce to a quadratic or smaller
-// look for identical points
-// look for all four points in a line
- // note that three points in a line doesn't simplify a cubic
-// look for approximation with single quadratic
- // save approximation with multiple quadratics for later
-int reduceOrder(const Cubic& cubic, Cubic& reduction, ReduceOrder_Quadratics allowQuadratics,
- ReduceOrder_Styles reduceStyle) {
- int index, minX, maxX, minY, maxY;
- int minXSet, minYSet;
- minX = maxX = minY = maxY = 0;
- minXSet = minYSet = 0;
- for (index = 1; index < 4; ++index) {
- if (cubic[minX].x > cubic[index].x) {
- minX = index;
- }
- if (cubic[minY].y > cubic[index].y) {
- minY = index;
- }
- if (cubic[maxX].x < cubic[index].x) {
- maxX = index;
- }
- if (cubic[maxY].y < cubic[index].y) {
- maxY = index;
- }
- }
- for (index = 0; index < 4; ++index) {
- double cx = cubic[index].x;
- double cy = cubic[index].y;
- double denom = SkTMax(fabs(cx), SkTMax(fabs(cy),
- SkTMax(fabs(cubic[minX].x), fabs(cubic[minY].y))));
- if (denom == 0) {
- minXSet |= 1 << index;
- minYSet |= 1 << index;
- continue;
- }
- double inv = 1 / denom;
- if (approximately_equal_half(cx * inv, cubic[minX].x * inv)) {
- minXSet |= 1 << index;
- }
- if (approximately_equal_half(cy * inv, cubic[minY].y * inv)) {
- minYSet |= 1 << index;
- }
- }
- if (minXSet == 0xF) { // test for vertical line
- if (minYSet == 0xF) { // return 1 if all four are coincident
- return coincident_line(cubic, reduction);
- }
- return vertical_line(cubic, reduceStyle, reduction);
- }
- if (minYSet == 0xF) { // test for horizontal line
- return horizontal_line(cubic, reduceStyle, reduction);
- }
- int result = check_linear(cubic, reduceStyle, minX, maxX, minY, maxY, reduction);
- if (result) {
- return result;
- }
- if (allowQuadratics == kReduceOrder_QuadraticsAllowed
- && (result = check_quadratic(cubic, reduction))) {
- return result;
- }
- memcpy(reduction, cubic, sizeof(Cubic));
- return 4;
-}
diff --git a/experimental/Intersection/CubicReduceOrder_Test.cpp b/experimental/Intersection/CubicReduceOrder_Test.cpp
deleted file mode 100644
index 79b34288d3..0000000000
--- a/experimental/Intersection/CubicReduceOrder_Test.cpp
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "CurveIntersection.h"
-#include "CubicIntersection_TestData.h"
-#include "Intersection_Tests.h"
-#include "QuadraticIntersection_TestData.h"
-#include "TestUtilities.h"
-
-void CubicReduceOrder_Test() {
- size_t index;
- Cubic reduce;
- int order;
- enum {
- RunAll,
- RunPointDegenerates,
- RunNotPointDegenerates,
- RunLines,
- RunNotLines,
- RunModEpsilonLines,
- RunLessEpsilonLines,
- RunNegEpsilonLines,
- RunQuadraticLines,
- RunQuadraticModLines,
- RunComputedLines,
- RunNone
- } run = RunAll;
- int firstTestIndex = 0;
-#if 0
- run = RunComputedLines;
- firstTestIndex = 18;
-#endif
- int firstPointDegeneratesTest = run == RunAll ? 0 : run == RunPointDegenerates ? firstTestIndex : SK_MaxS32;
- int firstNotPointDegeneratesTest = run == RunAll ? 0 : run == RunNotPointDegenerates ? firstTestIndex : SK_MaxS32;
- int firstLinesTest = run == RunAll ? 0 : run == RunLines ? firstTestIndex : SK_MaxS32;
- int firstNotLinesTest = run == RunAll ? 0 : run == RunNotLines ? firstTestIndex : SK_MaxS32;
- int firstModEpsilonTest = run == RunAll ? 0 : run == RunModEpsilonLines ? firstTestIndex : SK_MaxS32;
- int firstLessEpsilonTest = run == RunAll ? 0 : run == RunLessEpsilonLines ? firstTestIndex : SK_MaxS32;
- int firstNegEpsilonTest = run == RunAll ? 0 : run == RunNegEpsilonLines ? firstTestIndex : SK_MaxS32;
- int firstQuadraticLineTest = run == RunAll ? 0 : run == RunQuadraticLines ? firstTestIndex : SK_MaxS32;
- int firstQuadraticModLineTest = run == RunAll ? 0 : run == RunQuadraticModLines ? firstTestIndex : SK_MaxS32;
- int firstComputedLinesTest = run == RunAll ? 0 : run == RunComputedLines ? firstTestIndex : SK_MaxS32;
-
- for (index = firstPointDegeneratesTest; index < pointDegenerates_count; ++index) {
- const Cubic& cubic = pointDegenerates[index];
- order = reduceOrder(cubic, reduce, kReduceOrder_QuadraticsAllowed,
- kReduceOrder_TreatAsFill);
- if (order != 1) {
- SkDebugf("[%d] pointDegenerates order=%d\n", (int) index, order);
- }
- }
- for (index = firstNotPointDegeneratesTest; index < notPointDegenerates_count; ++index) {
- const Cubic& cubic = notPointDegenerates[index];
- order = reduceOrder(cubic, reduce, kReduceOrder_QuadraticsAllowed,
- kReduceOrder_TreatAsFill);
- if (order == 1) {
- SkDebugf("[%d] notPointDegenerates order=%d\n", (int) index, order);
- }
- }
- for (index = firstLinesTest; index < lines_count; ++index) {
- const Cubic& cubic = lines[index];
- order = reduceOrder(cubic, reduce, kReduceOrder_QuadraticsAllowed,
- kReduceOrder_TreatAsFill);
- if (order != 2) {
- SkDebugf("[%d] lines order=%d\n", (int) index, order);
- }
- }
- for (index = firstNotLinesTest; index < notLines_count; ++index) {
- const Cubic& cubic = notLines[index];
- order = reduceOrder(cubic, reduce, kReduceOrder_QuadraticsAllowed,
- kReduceOrder_TreatAsFill);
- if (order == 2) {
- SkDebugf("[%d] notLines order=%d\n", (int) index, order);
- }
- }
- for (index = firstModEpsilonTest; index < modEpsilonLines_count; ++index) {
- const Cubic& cubic = modEpsilonLines[index];
- order = reduceOrder(cubic, reduce, kReduceOrder_QuadraticsAllowed,
- kReduceOrder_TreatAsFill);
- if (order == 2) {
- SkDebugf("[%d] line mod by epsilon order=%d\n", (int) index, order);
- }
- }
- for (index = firstLessEpsilonTest; index < lessEpsilonLines_count; ++index) {
- const Cubic& cubic = lessEpsilonLines[index];
- order = reduceOrder(cubic, reduce, kReduceOrder_QuadraticsAllowed,
- kReduceOrder_TreatAsFill);
- if (order != 2) {
- SkDebugf("[%d] line less by epsilon/2 order=%d\n", (int) index, order);
- }
- }
- for (index = firstNegEpsilonTest; index < negEpsilonLines_count; ++index) {
- const Cubic& cubic = negEpsilonLines[index];
- order = reduceOrder(cubic, reduce, kReduceOrder_QuadraticsAllowed,
- kReduceOrder_TreatAsFill);
- if (order != 2) {
- SkDebugf("[%d] line neg by epsilon/2 order=%d\n", (int) index, order);
- }
- }
- for (index = firstQuadraticLineTest; index < quadraticLines_count; ++index) {
- const Quadratic& quad = quadraticLines[index];
- Cubic cubic;
- quad_to_cubic(quad, cubic);
- order = reduceOrder(cubic, reduce, kReduceOrder_QuadraticsAllowed,
- kReduceOrder_TreatAsFill);
- if (order != 2) {
- SkDebugf("[%d] line quad order=%d\n", (int) index, order);
- }
- }
- for (index = firstQuadraticModLineTest; index < quadraticModEpsilonLines_count; ++index) {
- const Quadratic& quad = quadraticModEpsilonLines[index];
- Cubic cubic;
- quad_to_cubic(quad, cubic);
- order = reduceOrder(cubic, reduce, kReduceOrder_QuadraticsAllowed,
- kReduceOrder_TreatAsFill);
- if (order != 3) {
- SkDebugf("[%d] line mod quad order=%d\n", (int) index, order);
- }
- }
-
- // test if computed line end points are valid
- for (index = firstComputedLinesTest; index < lines_count; ++index) {
- const Cubic& cubic = lines[index];
- bool controlsInside = controls_inside(cubic);
- order = reduceOrder(cubic, reduce, kReduceOrder_QuadraticsAllowed,
- kReduceOrder_TreatAsFill);
- if (reduce[0].x == reduce[1].x && reduce[0].y == reduce[1].y) {
- SkDebugf("[%d] line computed ends match order=%d\n", (int) index, order);
- }
- if (controlsInside) {
- if ( (reduce[0].x != cubic[0].x && reduce[0].x != cubic[3].x)
- || (reduce[0].y != cubic[0].y && reduce[0].y != cubic[3].y)
- || (reduce[1].x != cubic[0].x && reduce[1].x != cubic[3].x)
- || (reduce[1].y != cubic[0].y && reduce[1].y != cubic[3].y)) {
- SkDebugf("[%d] line computed ends order=%d\n", (int) index, order);
- }
- } else {
- // binary search for extrema, compare against actual results
- // while a control point is outside of bounding box formed by end points, split
- _Rect bounds = {DBL_MAX, DBL_MAX, -DBL_MAX, -DBL_MAX};
- find_tight_bounds(cubic, bounds);
- if ( (!AlmostEqualUlps(reduce[0].x, bounds.left) && !AlmostEqualUlps(reduce[0].x, bounds.right))
- || (!AlmostEqualUlps(reduce[0].y, bounds.top) && !AlmostEqualUlps(reduce[0].y, bounds.bottom))
- || (!AlmostEqualUlps(reduce[1].x, bounds.left) && !AlmostEqualUlps(reduce[1].x, bounds.right))
- || (!AlmostEqualUlps(reduce[1].y, bounds.top) && !AlmostEqualUlps(reduce[1].y, bounds.bottom))) {
- SkDebugf("[%d] line computed tight bounds order=%d\n", (int) index, order);
- }
-
- }
- }
-}
diff --git a/experimental/Intersection/CubicSubDivide.cpp b/experimental/Intersection/CubicSubDivide.cpp
deleted file mode 100644
index ddf63cdc2a..0000000000
--- a/experimental/Intersection/CubicSubDivide.cpp
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "CubicUtilities.h"
-#include "IntersectionUtilities.h"
-
-/*
- Given a cubic c, t1, and t2, find a small cubic segment.
-
- The new cubic is defined as points A, B, C, and D, where
- s1 = 1 - t1
- s2 = 1 - t2
- A = c[0]*s1*s1*s1 + 3*c[1]*s1*s1*t1 + 3*c[2]*s1*t1*t1 + c[3]*t1*t1*t1
- D = c[0]*s2*s2*s2 + 3*c[1]*s2*s2*t2 + 3*c[2]*s2*t2*t2 + c[3]*t2*t2*t2
-
- We don't have B or C. So We define two equations to isolate them.
- First, compute two reference T values 1/3 and 2/3 from t1 to t2:
-
- c(at (2*t1 + t2)/3) == E
- c(at (t1 + 2*t2)/3) == F
-
- Next, compute where those values must be if we know the values of B and C:
-
- _12 = A*2/3 + B*1/3
- 12_ = A*1/3 + B*2/3
- _23 = B*2/3 + C*1/3
- 23_ = B*1/3 + C*2/3
- _34 = C*2/3 + D*1/3
- 34_ = C*1/3 + D*2/3
- _123 = (A*2/3 + B*1/3)*2/3 + (B*2/3 + C*1/3)*1/3 = A*4/9 + B*4/9 + C*1/9
- 123_ = (A*1/3 + B*2/3)*1/3 + (B*1/3 + C*2/3)*2/3 = A*1/9 + B*4/9 + C*4/9
- _234 = (B*2/3 + C*1/3)*2/3 + (C*2/3 + D*1/3)*1/3 = B*4/9 + C*4/9 + D*1/9
- 234_ = (B*1/3 + C*2/3)*1/3 + (C*1/3 + D*2/3)*2/3 = B*1/9 + C*4/9 + D*4/9
- _1234 = (A*4/9 + B*4/9 + C*1/9)*2/3 + (B*4/9 + C*4/9 + D*1/9)*1/3
- = A*8/27 + B*12/27 + C*6/27 + D*1/27
- = E
- 1234_ = (A*1/9 + B*4/9 + C*4/9)*1/3 + (B*1/9 + C*4/9 + D*4/9)*2/3
- = A*1/27 + B*6/27 + C*12/27 + D*8/27
- = F
- E*27 = A*8 + B*12 + C*6 + D
- F*27 = A + B*6 + C*12 + D*8
-
-Group the known values on one side:
-
- M = E*27 - A*8 - D = B*12 + C* 6
- N = F*27 - A - D*8 = B* 6 + C*12
- M*2 - N = B*18
- N*2 - M = C*18
- B = (M*2 - N)/18
- C = (N*2 - M)/18
- */
-
-static double interp_cubic_coords(const double* src, double t)
-{
- double ab = interp(src[0], src[2], t);
- double bc = interp(src[2], src[4], t);
- double cd = interp(src[4], src[6], t);
- double abc = interp(ab, bc, t);
- double bcd = interp(bc, cd, t);
- double abcd = interp(abc, bcd, t);
- return abcd;
-}
-
-void sub_divide(const Cubic& src, double t1, double t2, Cubic& dst) {
- if (t1 == 0 && t2 == 1) {
- dst[0] = src[0];
- dst[1] = src[1];
- dst[2] = src[2];
- dst[3] = src[3];
- return;
- }
- double ax = dst[0].x = interp_cubic_coords(&src[0].x, t1);
- double ay = dst[0].y = interp_cubic_coords(&src[0].y, t1);
- double ex = interp_cubic_coords(&src[0].x, (t1*2+t2)/3);
- double ey = interp_cubic_coords(&src[0].y, (t1*2+t2)/3);
- double fx = interp_cubic_coords(&src[0].x, (t1+t2*2)/3);
- double fy = interp_cubic_coords(&src[0].y, (t1+t2*2)/3);
- double dx = dst[3].x = interp_cubic_coords(&src[0].x, t2);
- double dy = dst[3].y = interp_cubic_coords(&src[0].y, t2);
- double mx = ex * 27 - ax * 8 - dx;
- double my = ey * 27 - ay * 8 - dy;
- double nx = fx * 27 - ax - dx * 8;
- double ny = fy * 27 - ay - dy * 8;
- /* bx = */ dst[1].x = (mx * 2 - nx) / 18;
- /* by = */ dst[1].y = (my * 2 - ny) / 18;
- /* cx = */ dst[2].x = (nx * 2 - mx) / 18;
- /* cy = */ dst[2].y = (ny * 2 - my) / 18;
-}
-
-void sub_divide(const Cubic& src, const _Point& a, const _Point& d,
- double t1, double t2, _Point dst[2]) {
- double ex = interp_cubic_coords(&src[0].x, (t1 * 2 + t2) / 3);
- double ey = interp_cubic_coords(&src[0].y, (t1 * 2 + t2) / 3);
- double fx = interp_cubic_coords(&src[0].x, (t1 + t2 * 2) / 3);
- double fy = interp_cubic_coords(&src[0].y, (t1 + t2 * 2) / 3);
- double mx = ex * 27 - a.x * 8 - d.x;
- double my = ey * 27 - a.y * 8 - d.y;
- double nx = fx * 27 - a.x - d.x * 8;
- double ny = fy * 27 - a.y - d.y * 8;
- /* bx = */ dst[0].x = (mx * 2 - nx) / 18;
- /* by = */ dst[0].y = (my * 2 - ny) / 18;
- /* cx = */ dst[1].x = (nx * 2 - mx) / 18;
- /* cy = */ dst[1].y = (ny * 2 - my) / 18;
-}
-
-/* classic one t subdivision */
-static void interp_cubic_coords(const double* src, double* dst, double t)
-{
- double ab = interp(src[0], src[2], t);
- double bc = interp(src[2], src[4], t);
- double cd = interp(src[4], src[6], t);
- double abc = interp(ab, bc, t);
- double bcd = interp(bc, cd, t);
- double abcd = interp(abc, bcd, t);
-
- dst[0] = src[0];
- dst[2] = ab;
- dst[4] = abc;
- dst[6] = abcd;
- dst[8] = bcd;
- dst[10] = cd;
- dst[12] = src[6];
-}
-
-void chop_at(const Cubic& src, CubicPair& dst, double t)
-{
- if (t == 0.5) {
- dst.pts[0] = src[0];
- dst.pts[1].x = (src[0].x + src[1].x) / 2;
- dst.pts[1].y = (src[0].y + src[1].y) / 2;
- dst.pts[2].x = (src[0].x + 2 * src[1].x + src[2].x) / 4;
- dst.pts[2].y = (src[0].y + 2 * src[1].y + src[2].y) / 4;
- dst.pts[3].x = (src[0].x + 3 * (src[1].x + src[2].x) + src[3].x) / 8;
- dst.pts[3].y = (src[0].y + 3 * (src[1].y + src[2].y) + src[3].y) / 8;
- dst.pts[4].x = (src[1].x + 2 * src[2].x + src[3].x) / 4;
- dst.pts[4].y = (src[1].y + 2 * src[2].y + src[3].y) / 4;
- dst.pts[5].x = (src[2].x + src[3].x) / 2;
- dst.pts[5].y = (src[2].y + src[3].y) / 2;
- dst.pts[6] = src[3];
- return;
- }
- interp_cubic_coords(&src[0].x, &dst.pts[0].x, t);
- interp_cubic_coords(&src[0].y, &dst.pts[0].y, t);
-}
diff --git a/experimental/Intersection/CubicToQuadratics.cpp b/experimental/Intersection/CubicToQuadratics.cpp
deleted file mode 100644
index 5eeaf19c9f..0000000000
--- a/experimental/Intersection/CubicToQuadratics.cpp
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
-http://stackoverflow.com/questions/2009160/how-do-i-convert-the-2-control-points-of-a-cubic-curve-to-the-single-control-poi
-*/
-
-/*
-Let's call the control points of the cubic Q0..Q3 and the control points of the quadratic P0..P2.
-Then for degree elevation, the equations are:
-
-Q0 = P0
-Q1 = 1/3 P0 + 2/3 P1
-Q2 = 2/3 P1 + 1/3 P2
-Q3 = P2
-In your case you have Q0..Q3 and you're solving for P0..P2. There are two ways to compute P1 from
- the equations above:
-
-P1 = 3/2 Q1 - 1/2 Q0
-P1 = 3/2 Q2 - 1/2 Q3
-If this is a degree-elevated cubic, then both equations will give the same answer for P1. Since
- it's likely not, your best bet is to average them. So,
-
-P1 = -1/4 Q0 + 3/4 Q1 + 3/4 Q2 - 1/4 Q3
-
-
-Cubic defined by: P1/2 - anchor points, C1/C2 control points
-|x| is the euclidean norm of x
-mid-point approx of cubic: a quad that shares the same anchors with the cubic and has the
- control point at C = (3·C2 - P2 + 3·C1 - P1)/4
-
-Algorithm
-
-pick an absolute precision (prec)
-Compute the Tdiv as the root of (cubic) equation
-sqrt(3)/18 · |P2 - 3·C2 + 3·C1 - P1|/2 · Tdiv ^ 3 = prec
-if Tdiv < 0.5 divide the cubic at Tdiv. First segment [0..Tdiv] can be approximated with by a
- quadratic, with a defect less than prec, by the mid-point approximation.
- Repeat from step 2 with the second resulted segment (corresponding to 1-Tdiv)
-0.5<=Tdiv<1 - simply divide the cubic in two. The two halves can be approximated by the mid-point
- approximation
-Tdiv>=1 - the entire cubic can be approximated by the mid-point approximation
-
-confirmed by (maybe stolen from)
-http://www.caffeineowl.com/graphics/2d/vectorial/cubic2quad01.html
-// maybe in turn derived from http://www.cccg.ca/proceedings/2004/36.pdf
-// also stored at http://www.cis.usouthal.edu/~hain/general/Publications/Bezier/bezier%20cccg04%20paper.pdf
-
-*/
-
-#include "CubicUtilities.h"
-#include "CurveIntersection.h"
-#include "LineIntersection.h"
-#include "TSearch.h"
-
-const bool AVERAGE_END_POINTS = true; // results in better fitting curves
-
-#define USE_CUBIC_END_POINTS 1
-
-static double calcTDiv(const Cubic& cubic, double precision, double start) {
- const double adjust = sqrt(3) / 36;
- Cubic sub;
- const Cubic* cPtr;
- if (start == 0) {
- cPtr = &cubic;
- } else {
- // OPTIMIZE: special-case half-split ?
- sub_divide(cubic, start, 1, sub);
- cPtr = &sub;
- }
- const Cubic& c = *cPtr;
- double dx = c[3].x - 3 * (c[2].x - c[1].x) - c[0].x;
- double dy = c[3].y - 3 * (c[2].y - c[1].y) - c[0].y;
- double dist = sqrt(dx * dx + dy * dy);
- double tDiv3 = precision / (adjust * dist);
- double t = cube_root(tDiv3);
- if (start > 0) {
- t = start + (1 - start) * t;
- }
- return t;
-}
-
-void demote_cubic_to_quad(const Cubic& cubic, Quadratic& quad) {
- quad[0] = cubic[0];
-if (AVERAGE_END_POINTS) {
- const _Point fromC1 = { (3 * cubic[1].x - cubic[0].x) / 2, (3 * cubic[1].y - cubic[0].y) / 2 };
- const _Point fromC2 = { (3 * cubic[2].x - cubic[3].x) / 2, (3 * cubic[2].y - cubic[3].y) / 2 };
- quad[1].x = (fromC1.x + fromC2.x) / 2;
- quad[1].y = (fromC1.y + fromC2.y) / 2;
-} else {
- lineIntersect((const _Line&) cubic[0], (const _Line&) cubic[2], quad[1]);
-}
- quad[2] = cubic[3];
-}
-
-int cubic_to_quadratics(const Cubic& cubic, double precision, SkTDArray<Quadratic>& quadratics) {
- SkTDArray<double> ts;
- cubic_to_quadratics(cubic, precision, ts);
- int tsCount = ts.count();
- double t1Start = 0;
- int order = 0;
- for (int idx = 0; idx <= tsCount; ++idx) {
- double t1 = idx < tsCount ? ts[idx] : 1;
- Cubic part;
- sub_divide(cubic, t1Start, t1, part);
- Quadratic q1;
- demote_cubic_to_quad(part, q1);
- Quadratic s1;
- int o1 = reduceOrder(q1, s1, kReduceOrder_TreatAsFill);
- if (order < o1) {
- order = o1;
- }
- memcpy(quadratics.append(), o1 < 2 ? s1 : q1, sizeof(Quadratic));
- t1Start = t1;
- }
- return order;
-}
-
-static bool addSimpleTs(const Cubic& cubic, double precision, SkTDArray<double>& ts) {
- double tDiv = calcTDiv(cubic, precision, 0);
- if (tDiv >= 1) {
- return true;
- }
- if (tDiv >= 0.5) {
- *ts.append() = 0.5;
- return true;
- }
- return false;
-}
-
-static void addTs(const Cubic& cubic, double precision, double start, double end,
- SkTDArray<double>& ts) {
- double tDiv = calcTDiv(cubic, precision, 0);
- double parts = ceil(1.0 / tDiv);
- for (double index = 0; index < parts; ++index) {
- double newT = start + (index / parts) * (end - start);
- if (newT > 0 && newT < 1) {
- *ts.append() = newT;
- }
- }
-}
-
-// flavor that returns T values only, deferring computing the quads until they are needed
-// FIXME: when called from recursive intersect 2, this could take the original cubic
-// and do a more precise job when calling chop at and sub divide by computing the fractional ts.
-// it would still take the prechopped cubic for reduce order and find cubic inflections
-void cubic_to_quadratics(const Cubic& cubic, double precision, SkTDArray<double>& ts) {
- Cubic reduced;
- int order = reduceOrder(cubic, reduced, kReduceOrder_QuadraticsAllowed,
- kReduceOrder_TreatAsFill);
- if (order < 3) {
- return;
- }
- double inflectT[5];
- int inflections = find_cubic_inflections(cubic, inflectT);
- SkASSERT(inflections <= 2);
- if (!ends_are_extrema_in_x_or_y(cubic)) {
- inflections += find_cubic_max_curvature(cubic, &inflectT[inflections]);
- SkASSERT(inflections <= 5);
- }
- QSort<double>(inflectT, &inflectT[inflections - 1]);
- // OPTIMIZATION: is this filtering common enough that it needs to be pulled out into its
- // own subroutine?
- while (inflections && approximately_less_than_zero(inflectT[0])) {
- memcpy(inflectT, &inflectT[1], sizeof(inflectT[0]) * --inflections);
- }
- int start = 0;
- do {
- int next = start + 1;
- if (next >= inflections) {
- break;
- }
- if (!approximately_equal(inflectT[start], inflectT[next])) {
- ++start;
- continue;
- }
- memcpy(&inflectT[start], &inflectT[next], sizeof(inflectT[0]) * (--inflections - start));
- } while (true);
- while (inflections && approximately_greater_than_one(inflectT[inflections - 1])) {
- --inflections;
- }
- CubicPair pair;
- if (inflections == 1) {
- chop_at(cubic, pair, inflectT[0]);
- int orderP1 = reduceOrder(pair.first(), reduced, kReduceOrder_NoQuadraticsAllowed,
- kReduceOrder_TreatAsFill);
- if (orderP1 < 2) {
- --inflections;
- } else {
- int orderP2 = reduceOrder(pair.second(), reduced, kReduceOrder_NoQuadraticsAllowed,
- kReduceOrder_TreatAsFill);
- if (orderP2 < 2) {
- --inflections;
- }
- }
- }
- if (inflections == 0 && addSimpleTs(cubic, precision, ts)) {
- return;
- }
- if (inflections == 1) {
- chop_at(cubic, pair, inflectT[0]);
- addTs(pair.first(), precision, 0, inflectT[0], ts);
- addTs(pair.second(), precision, inflectT[0], 1, ts);
- return;
- }
- if (inflections > 1) {
- Cubic part;
- sub_divide(cubic, 0, inflectT[0], part);
- addTs(part, precision, 0, inflectT[0], ts);
- int last = inflections - 1;
- for (int idx = 0; idx < last; ++idx) {
- sub_divide(cubic, inflectT[idx], inflectT[idx + 1], part);
- addTs(part, precision, inflectT[idx], inflectT[idx + 1], ts);
- }
- sub_divide(cubic, inflectT[last], 1, part);
- addTs(part, precision, inflectT[last], 1, ts);
- return;
- }
- addTs(cubic, precision, 0, 1, ts);
-}
diff --git a/experimental/Intersection/CubicToQuadratics_Test.cpp b/experimental/Intersection/CubicToQuadratics_Test.cpp
deleted file mode 100644
index b7e1252a46..0000000000
--- a/experimental/Intersection/CubicToQuadratics_Test.cpp
+++ /dev/null
@@ -1,269 +0,0 @@
-#include "CubicIntersection_TestData.h"
-#include "CubicUtilities.h"
-#include "Intersection_Tests.h"
-#include "QuadraticIntersection_TestData.h"
-#include "TestUtilities.h"
-#include "SkGeometry.h"
-
-static void test(const Cubic* cubics, const char* name, int firstTest, size_t testCount) {
- SkTDArray<Quadratic> quads;
- for (size_t index = firstTest; index < testCount; ++index) {
- const Cubic& cubic = cubics[index];
- double precision = calcPrecision(cubic);
- (void) cubic_to_quadratics(cubic, precision, quads);
- if (quads.count() != 1) {
- printf("%s [%d] cubic to quadratics failed count=%d\n", name, (int) index,
- quads.count());
- }
- }
-}
-
-static void test(const Quadratic* quadTests, const char* name, int firstTest, size_t testCount) {
- SkTDArray<Quadratic> quads;
- for (size_t index = firstTest; index < testCount; ++index) {
- const Quadratic& quad = quadTests[index];
- Cubic cubic;
- quad_to_cubic(quad, cubic);
- double precision = calcPrecision(cubic);
- (void) cubic_to_quadratics(cubic, precision, quads);
- if (quads.count() != 1) {
- printf("%s [%d] cubic to quadratics failed count=%d\n", name, (int) index,
- quads.count());
- }
- }
-}
-
-static void testC(const Cubic* cubics, const char* name, int firstTest, size_t testCount) {
- SkTDArray<Quadratic> quads;
- // test if computed line end points are valid
- for (size_t index = firstTest; index < testCount; ++index) {
- const Cubic& cubic = cubics[index];
- double precision = calcPrecision(cubic);
- int order = cubic_to_quadratics(cubic, precision, quads);
- SkASSERT(order != 4);
- if (order < 3) {
- continue;
- }
- if (!AlmostEqualUlps(cubic[0].x, quads[0][0].x)
- || !AlmostEqualUlps(cubic[0].y, quads[0][0].y)) {
- printf("[%d] unmatched start\n", (int) index);
- }
- int last = quads.count() - 1;
- if (!AlmostEqualUlps(cubic[3].x, quads[last][2].x)
- || !AlmostEqualUlps(cubic[3].y, quads[last][2].y)) {
- printf("[%d] unmatched end\n", (int) index);
- }
- }
-}
-
-static void testC(const Cubic(* cubics)[2], const char* name, int firstTest, size_t testCount) {
- SkTDArray<Quadratic> quads;
- for (size_t index = firstTest; index < testCount; ++index) {
- for (int idx2 = 0; idx2 < 2; ++idx2) {
- const Cubic& cubic = cubics[index][idx2];
- double precision = calcPrecision(cubic);
- int order = cubic_to_quadratics(cubic, precision, quads);
- SkASSERT(order != 4);
- if (order < 3) {
- continue;
- }
- if (!AlmostEqualUlps(cubic[0].x, quads[0][0].x)
- || !AlmostEqualUlps(cubic[0].y, quads[0][0].y)) {
- printf("[%d][%d] unmatched start\n", (int) index, idx2);
- }
- int last = quads.count() - 1;
- if (!AlmostEqualUlps(cubic[3].x, quads[last][2].x)
- || !AlmostEqualUlps(cubic[3].y, quads[last][2].y)) {
- printf("[%d][%d] unmatched end\n", (int) index, idx2);
- }
- }
- }
-}
-
-void CubicToQuadratics_Test() {
- enum {
- RunAll,
- RunPointDegenerates,
- RunNotPointDegenerates,
- RunLines,
- RunNotLines,
- RunModEpsilonLines,
- RunLessEpsilonLines,
- RunNegEpsilonLines,
- RunQuadraticLines,
- RunQuadraticModLines,
- RunComputedLines,
- RunComputedTests,
- RunNone
- } run = RunAll;
- int firstTestIndex = 0;
-#if 0
- run = RunComputedLines;
- firstTestIndex = 18;
-#endif
- int firstPointDegeneratesTest = run == RunAll ? 0 : run == RunPointDegenerates ? firstTestIndex : SK_MaxS32;
- int firstNotPointDegeneratesTest = run == RunAll ? 0 : run == RunNotPointDegenerates ? firstTestIndex : SK_MaxS32;
- int firstLinesTest = run == RunAll ? 0 : run == RunLines ? firstTestIndex : SK_MaxS32;
- int firstNotLinesTest = run == RunAll ? 0 : run == RunNotLines ? firstTestIndex : SK_MaxS32;
- int firstModEpsilonTest = run == RunAll ? 0 : run == RunModEpsilonLines ? firstTestIndex : SK_MaxS32;
- int firstLessEpsilonTest = run == RunAll ? 0 : run == RunLessEpsilonLines ? firstTestIndex : SK_MaxS32;
- int firstNegEpsilonTest = run == RunAll ? 0 : run == RunNegEpsilonLines ? firstTestIndex : SK_MaxS32;
- int firstQuadraticLineTest = run == RunAll ? 0 : run == RunQuadraticLines ? firstTestIndex : SK_MaxS32;
- int firstQuadraticModLineTest = run == RunAll ? 0 : run == RunQuadraticModLines ? firstTestIndex : SK_MaxS32;
- int firstComputedLinesTest = run == RunAll ? 0 : run == RunComputedLines ? firstTestIndex : SK_MaxS32;
- int firstComputedCubicsTest = run == RunAll ? 0 : run == RunComputedTests ? firstTestIndex : SK_MaxS32;
-
- test(pointDegenerates, "pointDegenerates", firstPointDegeneratesTest, pointDegenerates_count);
- test(notPointDegenerates, "notPointDegenerates", firstNotPointDegeneratesTest, notPointDegenerates_count);
- test(lines, "lines", firstLinesTest, lines_count);
- test(notLines, "notLines", firstNotLinesTest, notLines_count);
- test(modEpsilonLines, "modEpsilonLines", firstModEpsilonTest, modEpsilonLines_count);
- test(lessEpsilonLines, "lessEpsilonLines", firstLessEpsilonTest, lessEpsilonLines_count);
- test(negEpsilonLines, "negEpsilonLines", firstNegEpsilonTest, negEpsilonLines_count);
- test(quadraticLines, "quadraticLines", firstQuadraticLineTest, quadraticLines_count);
- test(quadraticModEpsilonLines, "quadraticModEpsilonLines", firstQuadraticModLineTest,
- quadraticModEpsilonLines_count);
- testC(lines, "computed lines", firstComputedLinesTest, lines_count);
- testC(tests, "computed tests", firstComputedCubicsTest, tests_count);
- printf("%s end\n", __FUNCTION__);
-}
-
-static Cubic locals[] = {
-{{0, 1}, {1.9274705288631189e-19, 1.0000000000000002}, {0.0017190297609673323, 0.99828097023903239},
- {0.0053709083094631276, 0.99505672974365911}},
-
- {{14.5975863, 41.632436}, {16.3518929, 26.2639684}, {18.5165519, 7.68775139}, {8.03767257, 89.1628526}},
- {{69.7292014, 38.6877352}, {24.7648688, 23.1501713}, {84.9283191, 90.2588441}, {80.392774, 61.3533852}},
- {{
- 60.776536520932126,
- 71.249307306133829
- }, {
- 87.107894191103014,
- 22.377669868235323
- }, {
- 1.4974754310666936,
- 68.069569937917208
- }, {
- 45.261946574441133,
- 17.536076632112298
- }},
-};
-
-static size_t localsCount = sizeof(locals) / sizeof(locals[0]);
-
-#define DEBUG_CRASH 0
-#define TEST_AVERAGE_END_POINTS 0 // must take const off to test
-extern const bool AVERAGE_END_POINTS;
-
-static void oneOff(size_t x) {
- const Cubic& cubic = locals[x];
- const SkPoint skcubic[4] = {{(float) cubic[0].x, (float) cubic[0].y},
- {(float) cubic[1].x, (float) cubic[1].y}, {(float) cubic[2].x, (float) cubic[2].y},
- {(float) cubic[3].x, (float) cubic[3].y}};
- SkScalar skinflect[2];
- int skin = SkFindCubicInflections(skcubic, skinflect);
- SkDebugf("%s %d %1.9g\n", __FUNCTION__, skin, skinflect[0]);
- SkTDArray<Quadratic> quads;
- double precision = calcPrecision(cubic);
- (void) cubic_to_quadratics(cubic, precision, quads);
- SkDebugf("%s quads=%d\n", __FUNCTION__, quads.count());
-}
-
-void CubicsToQuadratics_OneOffTests() {
- for (size_t x = 0; x < localsCount; ++x) {
- oneOff(x);
- }
-}
-
-void CubicsToQuadratics_OneOffTest() {
- oneOff(0);
-}
-
-void CubicsToQuadratics_RandTest() {
- srand(0);
- const int arrayMax = 8;
- const int sampleMax = 10;
- const int tests = 1000000; // 10000000;
- int quadDist[arrayMax];
- bzero(quadDist, sizeof(quadDist));
- Cubic samples[arrayMax][sampleMax];
- int sampleCount[arrayMax];
- bzero(sampleCount, sizeof(sampleCount));
- for (int x = 0; x < tests; ++x) {
- Cubic cubic;
- for (int i = 0; i < 4; ++i) {
- cubic[i].x = (double) rand() / RAND_MAX * 100;
- cubic[i].y = (double) rand() / RAND_MAX * 100;
- }
- #if DEBUG_CRASH
- char str[1024];
- sprintf(str, "{{%1.9g, %1.9g}, {%1.9g, %1.9g}, {%1.9g, %1.9g}, {%1.9g, %1.9g}},\n",
- cubic[0].x, cubic[0].y, cubic[1].x, cubic[1].y, cubic[2].x, cubic[2].y,
- cubic[3].x, cubic[3].y);
- #endif
- SkTDArray<Quadratic> quads;
- double precision = calcPrecision(cubic);
- (void) cubic_to_quadratics(cubic, precision, quads);
- int count = quads.count();
- SkASSERT(count > 0);
- SkASSERT(--count < arrayMax);
- quadDist[count]++;
- int sCount = sampleCount[count];
- if (sCount < sampleMax) {
- memcpy(samples[count][sCount], cubic, sizeof(Cubic));
- sampleCount[count]++;
- }
- }
- for (int x = 0; x < arrayMax; ++x) {
- if (!quadDist[x]) {
- continue;
- }
- SkDebugf("%d %1.9g%%\n", x + 1, (double) quadDist[x] / tests * 100);
- }
- SkDebugf("\n");
- for (int x = 0; x < arrayMax; ++x) {
- for (int y = 0; y < sampleCount[x]; ++y) {
-#if TEST_AVERAGE_END_POINTS
- for (int w = 0; w < 2; ++w) {
- AVERAGE_END_POINTS = w;
-#else
- int w = 0;
-#endif
- SkDebugf("<div id=\"cubic%dx%d%s\">\n", x + 1, y, w ? "x" : "");
- const Cubic& cubic = samples[x][y];
- SkDebugf("{{%1.9g, %1.9g}, {%1.9g, %1.9g}, {%1.9g, %1.9g}, {%1.9g, %1.9g}},\n",
- cubic[0].x, cubic[0].y, cubic[1].x, cubic[1].y, cubic[2].x, cubic[2].y,
- cubic[3].x, cubic[3].y);
- SkTDArray<Quadratic> quads;
- double precision = calcPrecision(cubic);
- (void) cubic_to_quadratics(cubic, precision, quads);
- for (int z = 0; z < quads.count(); ++z) {
- const Quadratic& quad = quads[z];
- SkDebugf("{{%1.9g, %1.9g}, {%1.9g, %1.9g}, {%1.9g, %1.9g}},\n",
- quad[0].x, quad[0].y, quad[1].x, quad[1].y, quad[2].x, quad[2].y);
- }
- SkDebugf("</div>\n\n");
-#if TEST_AVERAGE_END_POINTS
- }
-#endif
- }
- }
- SkDebugf("</div>\n\n");
- SkDebugf("<script type=\"text/javascript\">\n\n");
- SkDebugf("var testDivs = [\n");
- for (int x = 0; x < arrayMax; ++x) {
- for (int y = 0; y < sampleCount[x]; ++y) {
-#if TEST_AVERAGE_END_POINTS
- for (int w = 0; w < 2; ++w) {
-#else
- int w = 0;
-#endif
- SkDebugf(" cubic%dx%d%s,\n", x + 1, y, w ? "x" : "");
-#if TEST_AVERAGE_END_POINTS
- }
-#endif
- }
- }
- SkDebugf("\n\n\n");
- SkDebugf("%s end\n", __FUNCTION__);
-}
diff --git a/experimental/Intersection/CubicUtilities.cpp b/experimental/Intersection/CubicUtilities.cpp
deleted file mode 100644
index 474dc5e526..0000000000
--- a/experimental/Intersection/CubicUtilities.cpp
+++ /dev/null
@@ -1,424 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "CubicUtilities.h"
-#include "Extrema.h"
-#include "LineUtilities.h"
-#include "QuadraticUtilities.h"
-
-const int gPrecisionUnit = 256; // FIXME: arbitrary -- should try different values in test framework
-
-// FIXME: cache keep the bounds and/or precision with the caller?
-double calcPrecision(const Cubic& cubic) {
- _Rect dRect;
- dRect.setBounds(cubic); // OPTIMIZATION: just use setRawBounds ?
- double width = dRect.right - dRect.left;
- double height = dRect.bottom - dRect.top;
- return (width > height ? width : height) / gPrecisionUnit;
-}
-
-#ifdef SK_DEBUG
-double calcPrecision(const Cubic& cubic, double t, double scale) {
- Cubic part;
- sub_divide(cubic, SkTMax(0., t - scale), SkTMin(1., t + scale), part);
- return calcPrecision(part);
-}
-#endif
-
-bool clockwise(const Cubic& c) {
- double sum = (c[0].x - c[3].x) * (c[0].y + c[3].y);
- for (int idx = 0; idx < 3; ++idx){
- sum += (c[idx + 1].x - c[idx].x) * (c[idx + 1].y + c[idx].y);
- }
- return sum <= 0;
-}
-
-void coefficients(const double* cubic, double& A, double& B, double& C, double& D) {
- A = cubic[6]; // d
- B = cubic[4] * 3; // 3*c
- C = cubic[2] * 3; // 3*b
- D = cubic[0]; // a
- A -= D - C + B; // A = -a + 3*b - 3*c + d
- B += 3 * D - 2 * C; // B = 3*a - 6*b + 3*c
- C -= 3 * D; // C = -3*a + 3*b
-}
-
-bool controls_contained_by_ends(const Cubic& c) {
- _Vector startTan = c[1] - c[0];
- if (startTan.x == 0 && startTan.y == 0) {
- startTan = c[2] - c[0];
- }
- _Vector endTan = c[2] - c[3];
- if (endTan.x == 0 && endTan.y == 0) {
- endTan = c[1] - c[3];
- }
- if (startTan.dot(endTan) >= 0) {
- return false;
- }
- _Line startEdge = {c[0], c[0]};
- startEdge[1].x -= startTan.y;
- startEdge[1].y += startTan.x;
- _Line endEdge = {c[3], c[3]};
- endEdge[1].x -= endTan.y;
- endEdge[1].y += endTan.x;
- double leftStart1 = is_left(startEdge, c[1]);
- if (leftStart1 * is_left(startEdge, c[2]) < 0) {
- return false;
- }
- double leftEnd1 = is_left(endEdge, c[1]);
- if (leftEnd1 * is_left(endEdge, c[2]) < 0) {
- return false;
- }
- return leftStart1 * leftEnd1 >= 0;
-}
-
-bool ends_are_extrema_in_x_or_y(const Cubic& c) {
- return (between(c[0].x, c[1].x, c[3].x) && between(c[0].x, c[2].x, c[3].x))
- || (between(c[0].y, c[1].y, c[3].y) && between(c[0].y, c[2].y, c[3].y));
-}
-
-bool monotonic_in_y(const Cubic& c) {
- return between(c[0].y, c[1].y, c[3].y) && between(c[0].y, c[2].y, c[3].y);
-}
-
-bool serpentine(const Cubic& c) {
- if (!controls_contained_by_ends(c)) {
- return false;
- }
- double wiggle = (c[0].x - c[2].x) * (c[0].y + c[2].y);
- for (int idx = 0; idx < 2; ++idx){
- wiggle += (c[idx + 1].x - c[idx].x) * (c[idx + 1].y + c[idx].y);
- }
- double waggle = (c[1].x - c[3].x) * (c[1].y + c[3].y);
- for (int idx = 1; idx < 3; ++idx){
- waggle += (c[idx + 1].x - c[idx].x) * (c[idx + 1].y + c[idx].y);
- }
- return wiggle * waggle < 0;
-}
-
-// cubic roots
-
-const double PI = 4 * atan(1);
-
-// from SkGeometry.cpp (and Numeric Solutions, 5.6)
-int cubicRootsValidT(double A, double B, double C, double D, double t[3]) {
-#if 0
- if (approximately_zero(A)) { // we're just a quadratic
- return quadraticRootsValidT(B, C, D, t);
- }
- double a, b, c;
- {
- double invA = 1 / A;
- a = B * invA;
- b = C * invA;
- c = D * invA;
- }
- double a2 = a * a;
- double Q = (a2 - b * 3) / 9;
- double R = (2 * a2 * a - 9 * a * b + 27 * c) / 54;
- double Q3 = Q * Q * Q;
- double R2MinusQ3 = R * R - Q3;
- double adiv3 = a / 3;
- double* roots = t;
- double r;
-
- if (R2MinusQ3 < 0) // we have 3 real roots
- {
- double theta = acos(R / sqrt(Q3));
- double neg2RootQ = -2 * sqrt(Q);
-
- r = neg2RootQ * cos(theta / 3) - adiv3;
- if (is_unit_interval(r))
- *roots++ = r;
-
- r = neg2RootQ * cos((theta + 2 * PI) / 3) - adiv3;
- if (is_unit_interval(r))
- *roots++ = r;
-
- r = neg2RootQ * cos((theta - 2 * PI) / 3) - adiv3;
- if (is_unit_interval(r))
- *roots++ = r;
- }
- else // we have 1 real root
- {
- double A = fabs(R) + sqrt(R2MinusQ3);
- A = cube_root(A);
- if (R > 0) {
- A = -A;
- }
- if (A != 0) {
- A += Q / A;
- }
- r = A - adiv3;
- if (is_unit_interval(r))
- *roots++ = r;
- }
- return (int)(roots - t);
-#else
- double s[3];
- int realRoots = cubicRootsReal(A, B, C, D, s);
- int foundRoots = add_valid_ts(s, realRoots, t);
- return foundRoots;
-#endif
-}
-
-int cubicRootsReal(double A, double B, double C, double D, double s[3]) {
-#ifdef SK_DEBUG
- // create a string mathematica understands
- // GDB set print repe 15 # if repeated digits is a bother
- // set print elements 400 # if line doesn't fit
- char str[1024];
- bzero(str, sizeof(str));
- sprintf(str, "Solve[%1.19g x^3 + %1.19g x^2 + %1.19g x + %1.19g == 0, x]", A, B, C, D);
- mathematica_ize(str, sizeof(str));
-#if ONE_OFF_DEBUG && ONE_OFF_DEBUG_MATHEMATICA
- SkDebugf("%s\n", str);
-#endif
-#endif
- if (approximately_zero(A)
- && approximately_zero_when_compared_to(A, B)
- && approximately_zero_when_compared_to(A, C)
- && approximately_zero_when_compared_to(A, D)) { // we're just a quadratic
- return quadraticRootsReal(B, C, D, s);
- }
- if (approximately_zero_when_compared_to(D, A)
- && approximately_zero_when_compared_to(D, B)
- && approximately_zero_when_compared_to(D, C)) { // 0 is one root
- int num = quadraticRootsReal(A, B, C, s);
- for (int i = 0; i < num; ++i) {
- if (approximately_zero(s[i])) {
- return num;
- }
- }
- s[num++] = 0;
- return num;
- }
- if (approximately_zero(A + B + C + D)) { // 1 is one root
- int num = quadraticRootsReal(A, A + B, -D, s);
- for (int i = 0; i < num; ++i) {
- if (AlmostEqualUlps(s[i], 1)) {
- return num;
- }
- }
- s[num++] = 1;
- return num;
- }
- double a, b, c;
- {
- double invA = 1 / A;
- a = B * invA;
- b = C * invA;
- c = D * invA;
- }
- double a2 = a * a;
- double Q = (a2 - b * 3) / 9;
- double R = (2 * a2 * a - 9 * a * b + 27 * c) / 54;
- double R2 = R * R;
- double Q3 = Q * Q * Q;
- double R2MinusQ3 = R2 - Q3;
- double adiv3 = a / 3;
- double r;
- double* roots = s;
-#if 0
- if (approximately_zero_squared(R2MinusQ3) && AlmostEqualUlps(R2, Q3)) {
- if (approximately_zero_squared(R)) {/* one triple solution */
- *roots++ = -adiv3;
- } else { /* one single and one double solution */
-
- double u = cube_root(-R);
- *roots++ = 2 * u - adiv3;
- *roots++ = -u - adiv3;
- }
- }
- else
-#endif
- if (R2MinusQ3 < 0) // we have 3 real roots
- {
- double theta = acos(R / sqrt(Q3));
- double neg2RootQ = -2 * sqrt(Q);
-
- r = neg2RootQ * cos(theta / 3) - adiv3;
- *roots++ = r;
-
- r = neg2RootQ * cos((theta + 2 * PI) / 3) - adiv3;
- if (!AlmostEqualUlps(s[0], r)) {
- *roots++ = r;
- }
- r = neg2RootQ * cos((theta - 2 * PI) / 3) - adiv3;
- if (!AlmostEqualUlps(s[0], r) && (roots - s == 1 || !AlmostEqualUlps(s[1], r))) {
- *roots++ = r;
- }
- }
- else // we have 1 real root
- {
- double sqrtR2MinusQ3 = sqrt(R2MinusQ3);
- double A = fabs(R) + sqrtR2MinusQ3;
- A = cube_root(A);
- if (R > 0) {
- A = -A;
- }
- if (A != 0) {
- A += Q / A;
- }
- r = A - adiv3;
- *roots++ = r;
- if (AlmostEqualUlps(R2, Q3)) {
- r = -A / 2 - adiv3;
- if (!AlmostEqualUlps(s[0], r)) {
- *roots++ = r;
- }
- }
- }
- return (int)(roots - s);
-}
-
-// from http://www.cs.sunysb.edu/~qin/courses/geometry/4.pdf
-// c(t) = a(1-t)^3 + 3bt(1-t)^2 + 3c(1-t)t^2 + dt^3
-// c'(t) = -3a(1-t)^2 + 3b((1-t)^2 - 2t(1-t)) + 3c(2t(1-t) - t^2) + 3dt^2
-// = 3(b-a)(1-t)^2 + 6(c-b)t(1-t) + 3(d-c)t^2
-static double derivativeAtT(const double* cubic, double t) {
- double one_t = 1 - t;
- double a = cubic[0];
- double b = cubic[2];
- double c = cubic[4];
- double d = cubic[6];
- return 3 * ((b - a) * one_t * one_t + 2 * (c - b) * t * one_t + (d - c) * t * t);
-}
-
-double dx_at_t(const Cubic& cubic, double t) {
- return derivativeAtT(&cubic[0].x, t);
-}
-
-double dy_at_t(const Cubic& cubic, double t) {
- return derivativeAtT(&cubic[0].y, t);
-}
-
-// OPTIMIZE? compute t^2, t(1-t), and (1-t)^2 and pass them to another version of derivative at t?
-_Vector dxdy_at_t(const Cubic& cubic, double t) {
- _Vector result = { derivativeAtT(&cubic[0].x, t), derivativeAtT(&cubic[0].y, t) };
- return result;
-}
-
-// OPTIMIZE? share code with formulate_F1DotF2
-int find_cubic_inflections(const Cubic& src, double tValues[])
-{
- double Ax = src[1].x - src[0].x;
- double Ay = src[1].y - src[0].y;
- double Bx = src[2].x - 2 * src[1].x + src[0].x;
- double By = src[2].y - 2 * src[1].y + src[0].y;
- double Cx = src[3].x + 3 * (src[1].x - src[2].x) - src[0].x;
- double Cy = src[3].y + 3 * (src[1].y - src[2].y) - src[0].y;
- return quadraticRootsValidT(Bx * Cy - By * Cx, Ax * Cy - Ay * Cx, Ax * By - Ay * Bx, tValues);
-}
-
-static void formulate_F1DotF2(const double src[], double coeff[4])
-{
- double a = src[2] - src[0];
- double b = src[4] - 2 * src[2] + src[0];
- double c = src[6] + 3 * (src[2] - src[4]) - src[0];
- coeff[0] = c * c;
- coeff[1] = 3 * b * c;
- coeff[2] = 2 * b * b + c * a;
- coeff[3] = a * b;
-}
-
-/* from SkGeometry.cpp
- Looking for F' dot F'' == 0
-
- A = b - a
- B = c - 2b + a
- C = d - 3c + 3b - a
-
- F' = 3Ct^2 + 6Bt + 3A
- F'' = 6Ct + 6B
-
- F' dot F'' -> CCt^3 + 3BCt^2 + (2BB + CA)t + AB
-*/
-int find_cubic_max_curvature(const Cubic& src, double tValues[])
-{
- double coeffX[4], coeffY[4];
- int i;
- formulate_F1DotF2(&src[0].x, coeffX);
- formulate_F1DotF2(&src[0].y, coeffY);
- for (i = 0; i < 4; i++) {
- coeffX[i] = coeffX[i] + coeffY[i];
- }
- return cubicRootsValidT(coeffX[0], coeffX[1], coeffX[2], coeffX[3], tValues);
-}
-
-
-bool rotate(const Cubic& cubic, int zero, int index, Cubic& rotPath) {
- double dy = cubic[index].y - cubic[zero].y;
- double dx = cubic[index].x - cubic[zero].x;
- if (approximately_zero(dy)) {
- if (approximately_zero(dx)) {
- return false;
- }
- memcpy(rotPath, cubic, sizeof(Cubic));
- return true;
- }
- for (int index = 0; index < 4; ++index) {
- rotPath[index].x = cubic[index].x * dx + cubic[index].y * dy;
- rotPath[index].y = cubic[index].y * dx - cubic[index].x * dy;
- }
- return true;
-}
-
-#if 0 // unused for now
-double secondDerivativeAtT(const double* cubic, double t) {
- double a = cubic[0];
- double b = cubic[2];
- double c = cubic[4];
- double d = cubic[6];
- return (c - 2 * b + a) * (1 - t) + (d - 2 * c + b) * t;
-}
-#endif
-
-_Point top(const Cubic& cubic, double startT, double endT) {
- Cubic sub;
- sub_divide(cubic, startT, endT, sub);
- _Point topPt = sub[0];
- if (topPt.y > sub[3].y || (topPt.y == sub[3].y && topPt.x > sub[3].x)) {
- topPt = sub[3];
- }
- double extremeTs[2];
- if (!monotonic_in_y(sub)) {
- int roots = findExtrema(sub[0].y, sub[1].y, sub[2].y, sub[3].y, extremeTs);
- for (int index = 0; index < roots; ++index) {
- _Point mid;
- double t = startT + (endT - startT) * extremeTs[index];
- xy_at_t(cubic, t, mid.x, mid.y);
- if (topPt.y > mid.y || (topPt.y == mid.y && topPt.x > mid.x)) {
- topPt = mid;
- }
- }
- }
- return topPt;
-}
-
-// OPTIMIZE: avoid computing the unused half
-void xy_at_t(const Cubic& cubic, double t, double& x, double& y) {
- _Point xy = xy_at_t(cubic, t);
- if (&x) {
- x = xy.x;
- }
- if (&y) {
- y = xy.y;
- }
-}
-
-_Point xy_at_t(const Cubic& cubic, double t) {
- double one_t = 1 - t;
- double one_t2 = one_t * one_t;
- double a = one_t2 * one_t;
- double b = 3 * one_t2 * t;
- double t2 = t * t;
- double c = 3 * one_t * t2;
- double d = t2 * t;
- _Point result = {a * cubic[0].x + b * cubic[1].x + c * cubic[2].x + d * cubic[3].x,
- a * cubic[0].y + b * cubic[1].y + c * cubic[2].y + d * cubic[3].y};
- return result;
-}
diff --git a/experimental/Intersection/CubicUtilities.h b/experimental/Intersection/CubicUtilities.h
deleted file mode 100644
index eaf16a42c4..0000000000
--- a/experimental/Intersection/CubicUtilities.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#if !defined CUBIC_UTILITIES_H
-#define CUBIC_UTILITIES_H
-
-#include "DataTypes.h"
-#include "SkTDArray.h"
-
-double calcPrecision(const Cubic& cubic);
-#ifdef SK_DEBUG
-double calcPrecision(const Cubic& cubic, double t, double scale);
-#endif
-void chop_at(const Cubic& src, CubicPair& dst, double t);
-bool clockwise(const Cubic& c);
-double cube_root(double x);
-int cubic_to_quadratics(const Cubic& cubic, double precision,
- SkTDArray<Quadratic>& quadratics);
-void cubic_to_quadratics(const Cubic& cubic, double precision, SkTDArray<double>& ts);
-void coefficients(const double* cubic, double& A, double& B, double& C, double& D);
-bool controls_contained_by_ends(const Cubic& c);
-int cubicRootsValidT(double A, double B, double C, double D, double t[3]);
-int cubicRootsReal(double A, double B, double C, double D, double s[3]);
-void demote_cubic_to_quad(const Cubic& cubic, Quadratic& quad);
-double dx_at_t(const Cubic& , double t);
-double dy_at_t(const Cubic& , double t);
-//void dxdy_at_t(const Cubic& , double t, _Point& y);
-_Vector dxdy_at_t(const Cubic& cubic, double t);
-bool ends_are_extrema_in_x_or_y(const Cubic& );
-int find_cubic_inflections(const Cubic& src, double tValues[]);
-int find_cubic_max_curvature(const Cubic& src, double tValues[]);
-bool monotonic_in_y(const Cubic& c);
-bool rotate(const Cubic& cubic, int zero, int index, Cubic& rotPath);
-bool serpentine(const Cubic& c);
-void sub_divide(const Cubic& src, double t1, double t2, Cubic& dst);
-void sub_divide(const Cubic& , const _Point& a, const _Point& d, double t1, double t2, _Point [2]);
-_Point top(const Cubic& , double startT, double endT);
-void xy_at_t(const Cubic& , double t, double& x, double& y);
-_Point xy_at_t(const Cubic& , double t);
-
-extern const int gPrecisionUnit;
-
-#endif
diff --git a/experimental/Intersection/CubicUtilities_Test.cpp b/experimental/Intersection/CubicUtilities_Test.cpp
deleted file mode 100644
index ee278c108e..0000000000
--- a/experimental/Intersection/CubicUtilities_Test.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "Intersection_Tests.h"
-#include "CubicUtilities.h"
-
-const Cubic tests[] = {
- {{2, 0}, {3, 1}, {2, 2}, {1, 1}},
- {{3, 1}, {2, 2}, {1, 1}, {2, 0}},
- {{3, 0}, {2, 1}, {3, 2}, {1, 1}},
-};
-
-const size_t tests_count = sizeof(tests) / sizeof(tests[0]);
-static size_t firstLineParameterTest = 0;
-
-void CubicUtilities_Test() {
- for (size_t index = firstLineParameterTest; index < tests_count; ++index) {
- const Cubic& cubic = tests[index];
- bool result = clockwise(cubic);
- if (!result) {
- SkDebugf("%s [%d] expected clockwise\n", __FUNCTION__, index);
- SkASSERT(0);
- }
- }
-}
diff --git a/experimental/Intersection/CurveIntersection.h b/experimental/Intersection/CurveIntersection.h
deleted file mode 100644
index cbcda76452..0000000000
--- a/experimental/Intersection/CurveIntersection.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#ifndef CurveIntersection_DEFINE
-#define CurveIntersection_DEFINE
-
-#include "DataTypes.h"
-
-class Intersections;
-
-// unit-testable utilities
-double axialIntersect(const Quadratic& q1, const _Point& p, bool vert);
-bool bezier_clip(const Cubic& cubic1, const Cubic& cubic2, double& minT, double& maxT);
-bool bezier_clip(const Quadratic& q1, const Quadratic& q2, double& minT, double& maxT);
-int convex_hull(const Cubic& cubic, char order[4]);
-bool convex_x_hull(const Cubic& cubic, char connectTo0[2], char connectTo3[2]);
-bool implicit_matches(const Cubic& cubic1, const Cubic& cubic2);
-bool implicit_matches(const _Line& line1, const _Line& line2);
-bool implicit_matches_ulps(const _Line& one, const _Line& two, int ulps);
-bool implicit_matches(const Quadratic& quad1, const Quadratic& quad2);
-void tangent(const Cubic& cubic, double t, _Point& result);
-void tangent(const _Line& line, _Point& result);
-void tangent(const Quadratic& quad, double t, _Point& result);
-
-// main functions
-enum ReduceOrder_Quadratics {
- kReduceOrder_NoQuadraticsAllowed,
- kReduceOrder_QuadraticsAllowed
-};
-enum ReduceOrder_Styles {
- kReduceOrder_TreatAsStroke,
- kReduceOrder_TreatAsFill
-};
-int reduceOrder(const Cubic& cubic, Cubic& reduction, ReduceOrder_Quadratics ,
- ReduceOrder_Styles );
-int reduceOrder(const _Line& line, _Line& reduction);
-int reduceOrder(const Quadratic& quad, Quadratic& reduction, ReduceOrder_Styles );
-int horizontalIntersect(const Cubic& cubic, double y, double tRange[3]);
-int horizontalIntersect(const Cubic& cubic, double left, double right, double y,
- double tRange[3]);
-int horizontalIntersect(const Cubic& cubic, double left, double right, double y,
- bool flipped, Intersections&);
-int horizontalIntersect(const _Line& line, double left, double right,
- double y, bool flipped, Intersections& );
-int horizontalIntersect(const Quadratic& quad, double left, double right,
- double y, double tRange[2]);
-int horizontalIntersect(const Quadratic& quad, double left, double right,
- double y, bool flipped, Intersections& );
-bool intersect(const Cubic& cubic1, const Cubic& cubic2, Intersections& );
-// the following flavor uses quadratic approximation instead of convex hulls
-//bool intersect2(const Cubic& cubic1, const Cubic& cubic2, Intersections& );
-// like '2', but iterates on centers instead of possible edges
-bool intersect3(const Cubic& cubic1, const Cubic& cubic2, Intersections& );
-int intersect(const Cubic& cubic, Intersections& i); // return true if cubic self-intersects
-int intersect(const Cubic& cubic, const Quadratic& quad, Intersections& );
-int intersect(const Cubic& cubic, const _Line& line, Intersections& );
-int intersectRay(const Cubic& quad, const _Line& line, Intersections& i);
-bool intersect(const Quadratic& q1, const Quadratic& q2, Intersections& );
-int intersect(const Quadratic& quad, const _Line& line, Intersections& );
-// the following flavor uses the implicit form instead of convex hulls
-bool intersect2(const Quadratic& q1, const Quadratic& q2, Intersections& i);
-int intersectRay(const Quadratic& quad, const _Line& line, Intersections& i);
-
-
-bool isLinear(const Quadratic& quad, int startIndex, int endIndex);
-bool isLinear(const Cubic& cubic, int startIndex, int endIndex);
-double leftMostT(const Cubic& , double startT, double endT);
-double leftMostT(const _Line& , double startT, double endT);
-double leftMostT(const Quadratic& , double startT, double endT);
-int verticalIntersect(const Cubic& cubic, double top, double bottom, double x,
- bool flipped, Intersections& );
-int verticalIntersect(const _Line& line, double top, double bottom, double x,
- bool flipped, Intersections& );
-int verticalIntersect(const Quadratic& quad, double top, double bottom,
- double x, bool flipped, Intersections& );
-
-#endif
diff --git a/experimental/Intersection/CurveUtilities.h b/experimental/Intersection/CurveUtilities.h
deleted file mode 100644
index 4d346327eb..0000000000
--- a/experimental/Intersection/CurveUtilities.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef CurveUtilities_DEFINE
-#define CurveUtilities_DEFINE
-
-#include "CubicUtilities.h"
-#include "LineUtilities.h"
-#include "QuadraticUtilities.h"
-
-#endif
diff --git a/experimental/Intersection/DataTypes.cpp b/experimental/Intersection/DataTypes.cpp
deleted file mode 100644
index 3425ea9576..0000000000
--- a/experimental/Intersection/DataTypes.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "DataTypes.h"
-
-#include <sys/types.h>
-#include <stdlib.h>
-
-#if USE_EPSILON
-const double PointEpsilon = 0.000001;
-const double SquaredEpsilon = PointEpsilon * PointEpsilon;
-#endif
-
-const int UlpsEpsilon = 16;
-
-_Vector operator-(const _Point& a, const _Point& b) {
- _Vector v = {a.x - b.x, a.y - b.y};
- return v;
-}
-
-_Point operator+(const _Point& a, const _Vector& b) {
- _Point v = {a.x + b.x, a.y + b.y};
- return v;
-}
-
-// from http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
-union Float_t
-{
- Float_t(float num = 0.0f) : f(num) {}
- // Portable extraction of components.
- bool negative() const { return (i >> 31) != 0; }
-#if 0 // unused
- int32_t RawMantissa() const { return i & ((1 << 23) - 1); }
- int32_t RawExponent() const { return (i >> 23) & 0xFF; }
-#endif
- int32_t i;
- float f;
-#ifdef SK_DEBUG
- struct
- { // Bitfields for exploration. Do not use in production code.
- uint32_t mantissa : 23;
- uint32_t exponent : 8;
- uint32_t sign : 1;
- } parts;
-#endif
-};
-
-bool AlmostEqualUlps(float A, float B)
-{
- Float_t uA(A);
- Float_t uB(B);
-
- // Different signs means they do not match.
- if (uA.negative() != uB.negative())
- {
- // Check for equality to make sure +0==-0
- return A == B;
- }
-
- // Find the difference in ULPs.
- int ulpsDiff = abs(uA.i - uB.i);
- return ulpsDiff <= UlpsEpsilon;
-}
-
-// FIXME: obsolete, delete
-#if 1
-int UlpsDiff(float A, float B)
-{
- Float_t uA(A);
- Float_t uB(B);
-
- return abs(uA.i - uB.i);
-}
-#endif
-
-#ifdef SK_DEBUG
-void mathematica_ize(char* str, size_t bufferLen) {
- size_t len = strlen(str);
- bool num = false;
- for (size_t idx = 0; idx < len; ++idx) {
- if (num && str[idx] == 'e') {
- if (len + 2 >= bufferLen) {
- return;
- }
- memmove(&str[idx + 2], &str[idx + 1], len - idx);
- str[idx] = '*';
- str[idx + 1] = '^';
- ++len;
- }
- num = str[idx] >= '0' && str[idx] <= '9';
- }
-}
-
-bool valid_wind(int wind) {
- return wind > SK_MinS32 + 0xFFFF && wind < SK_MaxS32 - 0xFFFF;
-}
-
-void winding_printf(int wind) {
- if (wind == SK_MinS32) {
- SkDebugf("?");
- } else {
- SkDebugf("%d", wind);
- }
-}
-#endif
diff --git a/experimental/Intersection/DataTypes.h b/experimental/Intersection/DataTypes.h
deleted file mode 100644
index 870a6de765..0000000000
--- a/experimental/Intersection/DataTypes.h
+++ /dev/null
@@ -1,418 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#ifndef __DataTypes_h__
-#define __DataTypes_h__
-
-#include <float.h> // for FLT_EPSILON
-#include <math.h> // for fabs, sqrt
-
-#include "SkPoint.h"
-
-#define FORCE_RELEASE 0 // set force release to 1 for multiple thread -- no debugging
-#define ONE_OFF_DEBUG 1
-#define ONE_OFF_DEBUG_MATHEMATICA 0
-
-// FIXME: move these into SkTypes.h
-template <typename T> inline T SkTMax(T a, T b) {
- if (a < b)
- a = b;
- return a;
-}
-
-template <typename T> inline T SkTMin(T a, T b) {
- if (a > b)
- a = b;
- return a;
-}
-
-extern bool AlmostEqualUlps(float A, float B);
-inline bool AlmostEqualUlps(double A, double B) { return AlmostEqualUlps((float) A, (float) B); }
-
-// FIXME: delete
-int UlpsDiff(float A, float B);
-
-// FLT_EPSILON == 1.19209290E-07 == 1 / (2 ^ 23)
-// DBL_EPSILON == 2.22045e-16
-const double FLT_EPSILON_CUBED = FLT_EPSILON * FLT_EPSILON * FLT_EPSILON;
-const double FLT_EPSILON_HALF = FLT_EPSILON / 2;
-const double FLT_EPSILON_SQUARED = FLT_EPSILON * FLT_EPSILON;
-const double FLT_EPSILON_SQRT = sqrt(FLT_EPSILON);
-const double FLT_EPSILON_INVERSE = 1 / FLT_EPSILON;
-const double DBL_EPSILON_ERR = DBL_EPSILON * 4; // tune -- allow a few bits of error
-const double ROUGH_EPSILON = FLT_EPSILON * 64;
-const double MORE_ROUGH_EPSILON = FLT_EPSILON * 256;
-
-inline bool approximately_zero(double x) {
- return fabs(x) < FLT_EPSILON;
-}
-
-inline bool precisely_zero(double x) {
- return fabs(x) < DBL_EPSILON_ERR;
-}
-
-inline bool approximately_zero(float x) {
- return fabs(x) < FLT_EPSILON;
-}
-
-inline bool approximately_zero_cubed(double x) {
- return fabs(x) < FLT_EPSILON_CUBED;
-}
-
-inline bool approximately_zero_half(double x) {
- return fabs(x) < FLT_EPSILON_HALF;
-}
-
-inline bool approximately_zero_squared(double x) {
- return fabs(x) < FLT_EPSILON_SQUARED;
-}
-
-inline bool approximately_zero_sqrt(double x) {
- return fabs(x) < FLT_EPSILON_SQRT;
-}
-
-inline bool approximately_zero_inverse(double x) {
- return fabs(x) > FLT_EPSILON_INVERSE;
-}
-
-// FIXME: if called multiple times with the same denom, we want to pass 1/y instead
-inline bool approximately_zero_when_compared_to(double x, double y) {
- return x == 0 || fabs(x / y) < FLT_EPSILON;
-}
-
-// Use this for comparing Ts in the range of 0 to 1. For general numbers (larger and smaller) use
-// AlmostEqualUlps instead.
-inline bool approximately_equal(double x, double y) {
-#if 1
- return approximately_zero(x - y);
-#else
-// see http://visualstudiomagazine.com/blogs/tool-tracker/2011/11/compare-floating-point-numbers.aspx
-// this allows very small (e.g. degenerate) values to compare unequally, but in this case,
-// AlmostEqualUlps should be used instead.
- if (x == y) {
- return true;
- }
- double absY = fabs(y);
- if (x == 0) {
- return absY < FLT_EPSILON;
- }
- double absX = fabs(x);
- if (y == 0) {
- return absX < FLT_EPSILON;
- }
- return fabs(x - y) < (absX > absY ? absX : absY) * FLT_EPSILON;
-#endif
-}
-
-inline bool precisely_equal(double x, double y) {
- return precisely_zero(x - y);
-}
-
-inline bool approximately_equal_half(double x, double y) {
- return approximately_zero_half(x - y);
-}
-
-inline bool approximately_equal_squared(double x, double y) {
- return approximately_equal(x, y);
-}
-
-inline bool approximately_greater(double x, double y) {
- return x - FLT_EPSILON >= y;
-}
-
-inline bool approximately_greater_or_equal(double x, double y) {
- return x + FLT_EPSILON > y;
-}
-
-inline bool approximately_lesser(double x, double y) {
- return x + FLT_EPSILON <= y;
-}
-
-inline bool approximately_lesser_or_equal(double x, double y) {
- return x - FLT_EPSILON < y;
-}
-
-inline double approximately_pin(double x) {
- return approximately_zero(x) ? 0 : x;
-}
-
-inline float approximately_pin(float x) {
- return approximately_zero(x) ? 0 : x;
-}
-
-inline bool approximately_greater_than_one(double x) {
- return x > 1 - FLT_EPSILON;
-}
-
-inline bool precisely_greater_than_one(double x) {
- return x > 1 - DBL_EPSILON_ERR;
-}
-
-inline bool approximately_less_than_zero(double x) {
- return x < FLT_EPSILON;
-}
-
-inline bool precisely_less_than_zero(double x) {
- return x < DBL_EPSILON_ERR;
-}
-
-inline bool approximately_negative(double x) {
- return x < FLT_EPSILON;
-}
-
-inline bool precisely_negative(double x) {
- return x < DBL_EPSILON_ERR;
-}
-
-inline bool approximately_one_or_less(double x) {
- return x < 1 + FLT_EPSILON;
-}
-
-inline bool approximately_positive(double x) {
- return x > -FLT_EPSILON;
-}
-
-inline bool approximately_positive_squared(double x) {
- return x > -(FLT_EPSILON_SQUARED);
-}
-
-inline bool approximately_zero_or_more(double x) {
- return x > -FLT_EPSILON;
-}
-
-inline bool approximately_between(double a, double b, double c) {
- return a <= c ? approximately_negative(a - b) && approximately_negative(b - c)
- : approximately_negative(b - a) && approximately_negative(c - b);
-}
-
-// returns true if (a <= b <= c) || (a >= b >= c)
-inline bool between(double a, double b, double c) {
- SkASSERT(((a <= b && b <= c) || (a >= b && b >= c)) == ((a - b) * (c - b) <= 0));
- return (a - b) * (c - b) <= 0;
-}
-
-inline bool more_roughly_equal(double x, double y) {
- return fabs(x - y) < MORE_ROUGH_EPSILON;
-}
-
-inline bool roughly_equal(double x, double y) {
- return fabs(x - y) < ROUGH_EPSILON;
-}
-
-struct _Point;
-
-struct _Vector {
- double x;
- double y;
-
- friend _Point operator+(const _Point& a, const _Vector& b);
-
- void operator+=(const _Vector& v) {
- x += v.x;
- y += v.y;
- }
-
- void operator-=(const _Vector& v) {
- x -= v.x;
- y -= v.y;
- }
-
- void operator/=(const double s) {
- x /= s;
- y /= s;
- }
-
- void operator*=(const double s) {
- x *= s;
- y *= s;
- }
-
- double cross(const _Vector& a) const {
- return x * a.y - y * a.x;
- }
-
- double dot(const _Vector& a) const {
- return x * a.x + y * a.y;
- }
-
- double length() const {
- return sqrt(lengthSquared());
- }
-
- double lengthSquared() const {
- return x * x + y * y;
- }
-
- SkVector asSkVector() const {
- SkVector v = {SkDoubleToScalar(x), SkDoubleToScalar(y)};
- return v;
- }
-};
-
-struct _Point {
- double x;
- double y;
-
- friend _Vector operator-(const _Point& a, const _Point& b);
-
- void operator+=(const _Vector& v) {
- x += v.x;
- y += v.y;
- }
-
- void operator-=(const _Vector& v) {
- x -= v.x;
- y -= v.y;
- }
-
- friend bool operator==(const _Point& a, const _Point& b) {
- return a.x == b.x && a.y == b.y;
- }
-
- friend bool operator!=(const _Point& a, const _Point& b) {
- return a.x != b.x || a.y != b.y;
- }
-
- // note: this can not be implemented with
- // return approximately_equal(a.y, y) && approximately_equal(a.x, x);
- // because that will not take the magnitude of the values
- bool approximatelyEqual(const _Point& a) const {
- double denom = SkTMax(fabs(x), SkTMax(fabs(y), SkTMax(fabs(a.x), fabs(a.y))));
- if (denom == 0) {
- return true;
- }
- double inv = 1 / denom;
- return approximately_equal(x * inv, a.x * inv) && approximately_equal(y * inv, a.y * inv);
- }
-
- bool approximatelyEqual(const SkPoint& a) const {
- double denom = SkTMax(fabs(x), SkTMax(fabs(y), SkTMax(fabs(a.fX), fabs(a.fY))));
- if (denom == 0) {
- return true;
- }
- double inv = 1 / denom;
- return approximately_equal(x * inv, a.fX * inv) && approximately_equal(y * inv, a.fY * inv);
- }
-
- bool approximatelyEqualHalf(const _Point& a) const {
- double denom = SkTMax(fabs(x), SkTMax(fabs(y), SkTMax(fabs(a.x), fabs(a.y))));
- if (denom == 0) {
- return true;
- }
- double inv = 1 / denom;
- return approximately_equal_half(x * inv, a.x * inv)
- && approximately_equal_half(y * inv, a.y * inv);
- }
-
- bool approximatelyZero() const {
- return approximately_zero(x) && approximately_zero(y);
- }
-
- SkPoint asSkPoint() const {
- SkPoint pt = {SkDoubleToScalar(x), SkDoubleToScalar(y)};
- return pt;
- }
-
- double distance(const _Point& a) const {
- _Vector temp = *this - a;
- return temp.length();
- }
-
- double distanceSquared(const _Point& a) const {
- _Vector temp = *this - a;
- return temp.lengthSquared();
- }
-
- double moreRoughlyEqual(const _Point& a) const {
- return more_roughly_equal(a.y, y) && more_roughly_equal(a.x, x);
- }
-
- double roughlyEqual(const _Point& a) const {
- return roughly_equal(a.y, y) && roughly_equal(a.x, x);
- }
-};
-
-typedef _Point _Line[2];
-typedef _Point Quadratic[3];
-typedef _Point Triangle[3];
-typedef _Point Cubic[4];
-
-struct _Rect {
- double left;
- double top;
- double right;
- double bottom;
-
- void add(const _Point& pt) {
- if (left > pt.x) {
- left = pt.x;
- }
- if (top > pt.y) {
- top = pt.y;
- }
- if (right < pt.x) {
- right = pt.x;
- }
- if (bottom < pt.y) {
- bottom = pt.y;
- }
- }
-
- // FIXME: used by debugging only ?
- bool contains(const _Point& pt) const {
- return approximately_between(left, pt.x, right)
- && approximately_between(top, pt.y, bottom);
- }
-
- bool intersects(_Rect& r) const {
- SkASSERT(left <= right);
- SkASSERT(top <= bottom);
- SkASSERT(r.left <= r.right);
- SkASSERT(r.top <= r.bottom);
- return r.left <= right && left <= r.right && r.top <= bottom && top <= r.bottom;
- }
-
- void set(const _Point& pt) {
- left = right = pt.x;
- top = bottom = pt.y;
- }
-
- void setBounds(const _Line& line) {
- set(line[0]);
- add(line[1]);
- }
-
- void setBounds(const Cubic& );
- void setBounds(const Quadratic& );
- void setRawBounds(const Cubic& );
- void setRawBounds(const Quadratic& );
-};
-
-struct CubicPair {
- const Cubic& first() const { return (const Cubic&) pts[0]; }
- const Cubic& second() const { return (const Cubic&) pts[3]; }
- _Point pts[7];
-};
-
-struct QuadraticPair {
- const Quadratic& first() const { return (const Quadratic&) pts[0]; }
- const Quadratic& second() const { return (const Quadratic&) pts[2]; }
- _Point pts[5];
-};
-
-// FIXME: move these into SkFloatingPoint.h
-#include "SkFloatingPoint.h"
-
-#define sk_double_isnan(a) sk_float_isnan(a)
-
-// FIXME: move these to debugging file
-#ifdef SK_DEBUG
-void mathematica_ize(char* str, size_t bufferSize);
-bool valid_wind(int winding);
-void winding_printf(int winding);
-#endif
-
-#endif // __DataTypes_h__
diff --git a/experimental/Intersection/DataTypes_Test.h b/experimental/Intersection/DataTypes_Test.h
deleted file mode 100644
index a8f14fa112..0000000000
--- a/experimental/Intersection/DataTypes_Test.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __DataTypes_Test_h__
-#define __DataTypes_Test_h__
-
-const double PointEpsilon = 0.000001;
-const double SquaredEpsilon = PointEpsilon * PointEpsilon;
-
-#endif
diff --git a/experimental/Intersection/EdgeDemo.cpp b/experimental/Intersection/EdgeDemo.cpp
deleted file mode 100644
index 684dfd99b7..0000000000
--- a/experimental/Intersection/EdgeDemo.cpp
+++ /dev/null
@@ -1,347 +0,0 @@
-#include "EdgeDemo.h"
-#include "EdgeWalker_Test.h"
-#include "ShapeOps.h"
-#import "SkCanvas.h"
-#import "SkPaint.h"
-
-extern void showPath(const SkPath& path, const char* str);
-
-static bool drawPaths(SkCanvas* canvas, const SkPath& path, bool useOld)
-{
- SkPath out;
-#define SHOW_PATH 0
-#if SHOW_PATH
- showPath(path, "original:");
-#endif
- if (useOld) {
- simplify(path, true, out);
- } else {
- simplifyx(path, out);
- }
-#if SHOW_PATH
- showPath(out, "simplified:");
-#endif
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setStyle(SkPaint::kStroke_Style);
-// paint.setStrokeWidth(6);
- // paint.setColor(0x1F003f7f);
- // canvas->drawPath(path, paint);
- paint.setColor(0xFF305F00);
- paint.setStrokeWidth(1);
- canvas->drawPath(out, paint);
- return true;
-}
-
-// Three circles bounce inside a rectangle. The circles describe three, four
-// or five points which in turn describe a polygon. The polygon points
-// bounce inside the circles. The circles rotate and scale over time. The
-// polygons are combined into a single path, simplified, and stroked.
-static bool drawCircles(SkCanvas* canvas, int step, bool useOld)
-{
- const int circles = 3;
- int scales[circles];
- int angles[circles];
- int locs[circles * 2];
- int pts[circles * 2 * 4];
- int c, p;
- for (c = 0; c < circles; ++c) {
- scales[c] = abs(10 - (step + c * 4) % 21);
- angles[c] = (step + c * 6) % 600;
- locs[c * 2] = abs(130 - (step + c * 9) % 261);
- locs[c * 2 + 1] = abs(170 - (step + c * 11) % 341);
- for (p = 0; p < 4; ++p) {
- pts[c * 8 + p * 2] = abs(90 - ((step + c * 121 + p * 13) % 190));
- pts[c * 8 + p * 2 + 1] = abs(110 - ((step + c * 223 + p * 17) % 230));
- }
- }
- SkPath path;
- for (c = 0; c < circles; ++c) {
- for (p = 0; p < 4; ++p) {
- SkScalar x = pts[c * 8 + p * 2];
- SkScalar y = pts[c * 8 + p * 2 + 1];
- x *= 3 + scales[c] / 10.0f;
- y *= 3 + scales[c] / 10.0f;
- SkScalar angle = angles[c] * 3.1415f * 2 / 600;
- SkScalar temp = (SkScalar) (x * cos(angle) - y * sin(angle));
- y = (SkScalar) (x * sin(angle) + y * cos(angle));
- x = temp;
- x += locs[c * 2] * 200 / 130.0f;
- y += locs[c * 2 + 1] * 200 / 170.0f;
- x += 50;
- // y += 200;
- if (p == 0) {
- path.moveTo(x, y);
- } else {
- path.lineTo(x, y);
- }
- }
- path.close();
- }
- return drawPaths(canvas, path, useOld);
-}
-
-static void createStar(SkPath& path, SkScalar innerRadius, SkScalar outerRadius,
- SkScalar startAngle, int points, SkPoint center) {
- SkScalar angle = startAngle;
- for (int index = 0; index < points * 2; ++index) {
- SkScalar radius = index & 1 ? outerRadius : innerRadius;
- SkScalar x = (SkScalar) (radius * cos(angle));
- SkScalar y = (SkScalar) (radius * sin(angle));
- x += center.fX;
- y += center.fY;
- if (index == 0) {
- path.moveTo(x, y);
- } else {
- path.lineTo(x, y);
- }
- angle += 3.1415f / points;
- }
- path.close();
-}
-
-static bool drawStars(SkCanvas* canvas, int step, bool useOld)
-{
- SkPath path;
- const int stars = 25;
- int pts[stars];
- // static bool initialize = true;
- int s;
- for (s = 0; s < stars; ++s) {
- pts[s] = 4 + (s % 7);
- }
- SkPoint locs[stars];
- SkScalar angles[stars];
- SkScalar innerRadius[stars];
- SkScalar outerRadius[stars];
- const int width = 640;
- const int height = 480;
- const int margin = 30;
- const int minRadius = 120;
- const int maxInner = 800;
- const int maxOuter = 1153;
- for (s = 0; s < stars; ++s) {
- int starW = (int) (width - margin * 2 + (SkScalar) s * (stars - s) / stars);
- locs[s].fX = (int) (step * (1.3f * (s + 1) / stars) + s * 121) % (starW * 2);
- if (locs[s].fX > starW) {
- locs[s].fX = starW * 2 - locs[s].fX;
- }
- locs[s].fX += margin;
- int starH = (int) (height - margin * 2 + (SkScalar) s * s / stars);
- locs[s].fY = (int) (step * (1.7f * (s + 1) / stars) + s * 183) % (starH * 2);
- if (locs[s].fY > starH) {
- locs[s].fY = starH * 2 - locs[s].fY;
- }
- locs[s].fY += margin;
- angles[s] = ((step + s * 47) % (360 * 4)) * 3.1415f / 180 / 4;
- innerRadius[s] = (step + s * 30) % (maxInner * 2);
- if (innerRadius[s] > maxInner) {
- innerRadius[s] = (maxInner * 2) - innerRadius[s];
- }
- innerRadius[s] = innerRadius[s] / 4 + minRadius;
- outerRadius[s] = (step + s * 70) % (maxOuter * 2);
- if (outerRadius[s] > maxOuter) {
- outerRadius[s] = (maxOuter * 2) - outerRadius[s];
- }
- outerRadius[s] = outerRadius[s] / 4 + minRadius;
- createStar(path, innerRadius[s] / 4.0f, outerRadius[s] / 4.0f,
- angles[s], pts[s], locs[s]);
- }
- return drawPaths(canvas, path, useOld);
-}
-
-#if 0
-static void tryRoncoOnce(const SkPath& path, const SkRect& target, bool show) {
- // capture everything in a desired rectangle
- SkPath tiny;
- bool closed = true;
- SkPath::Iter iter(path, false);
- SkPoint pts[4];
- SkPath::Verb verb;
- int count = 0;
- SkPoint lastPt;
- while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
- switch (verb) {
- case SkPath::kMove_Verb:
- count = 0;
- break;
- case SkPath::kLine_Verb:
- count = 1;
- break;
- case SkPath::kQuad_Verb:
- count = 2;
- break;
- case SkPath::kCubic_Verb:
- count = 3;
- break;
- case SkPath::kClose_Verb:
- if (!closed) {
- tiny.close();
- closed = true;
- }
- count = 0;
- break;
- default:
- SkDEBUGFAIL("bad verb");
- }
- if (!count) {
- continue;
- }
- SkRect bounds;
- bounds.set(pts[0].fX, pts[0].fY, pts[0].fX, pts[0].fY);
- for (int i = 1; i <= count; ++i) {
- bounds.growToInclude(pts[i].fX + 0.1f, pts[i].fY + 0.1f);
- }
- if (!SkRect::Intersects(target, bounds)) {
- continue;
- }
- if (closed) {
- tiny.moveTo(pts[0].fX, pts[0].fY);
- closed = false;
- } else if (pts[0] != lastPt) {
- tiny.lineTo(pts[0].fX, pts[0].fY);
- }
- switch (verb) {
- case SkPath::kLine_Verb:
- tiny.lineTo(pts[1].fX, pts[1].fY);
- lastPt = pts[1];
- break;
- case SkPath::kQuad_Verb:
- tiny.quadTo(pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY);
- lastPt = pts[2];
- break;
- case SkPath::kCubic_Verb:
- tiny.cubicTo(pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY, pts[3].fX, pts[3].fY);
- lastPt = pts[3];
- break;
- default:
- SkDEBUGFAIL("bad verb");
- }
- }
- if (!closed) {
- tiny.close();
- }
- if (show) {
- showPath(tiny, NULL);
- SkDebugf("simplified:\n");
- }
- testSimplifyx(tiny);
-}
-#endif
-
-#if 0
-static void tryRonco(const SkPath& path) {
- int divMax = 64;
- int divMin = 1;
- int xDivMin = 0;
- int yDivMin = 0;
- bool allYs = true;
- bool allXs = true;
- if (1) {
- divMax = divMin = 64;
- xDivMin = 11;
- yDivMin = 0;
- allXs = true;
- allYs = true;
- }
- for (int divs = divMax; divs >= divMin; divs /= 2) {
- SkDebugf("divs=%d\n",divs);
- const SkRect& overall = path.getBounds();
- SkScalar cellWidth = overall.width() / divs * 2;
- SkScalar cellHeight = overall.height() / divs * 2;
- SkRect target;
- int xDivMax = divMax == divMin && !allXs ? xDivMin + 1 : divs;
- int yDivMax = divMax == divMin && !allYs ? yDivMin + 1 : divs;
- for (int xDiv = xDivMin; xDiv < xDivMax; ++xDiv) {
- SkDebugf("xDiv=%d\n",xDiv);
- for (int yDiv = yDivMin; yDiv < yDivMax; ++yDiv) {
- SkDebugf("yDiv=%d\n",yDiv);
- target.setXYWH(overall.fLeft + (overall.width() - cellWidth) * xDiv / divs,
- overall.fTop + (overall.height() - cellHeight) * yDiv / divs,
- cellWidth, cellHeight);
- tryRoncoOnce(path, target, divMax == divMin);
- }
- }
- }
-}
-#endif
-
-static bool drawLetters(SkCanvas* canvas, int step, bool useOld)
-{
- SkPath path;
- const int width = 640;
- const int height = 480;
- const char testStr[] = "Merge";
- const int testStrLen = sizeof(testStr) - 1;
- SkPoint textPos[testStrLen];
- SkScalar widths[testStrLen];
- SkPaint paint;
- paint.setTextSize(40);
- paint.setAntiAlias(true);
- paint.getTextWidths(testStr, testStrLen, widths, NULL);
- SkScalar running = 0;
- for (int x = 0; x < testStrLen; ++x) {
- SkScalar width = widths[x];
- widths[x] = running;
- running += width;
- }
- SkScalar bias = (width - widths[testStrLen - 1]) / 2;
- for (int x = 0; x < testStrLen; ++x) {
- textPos[x].fX = bias + widths[x];
- textPos[x].fY = height / 2;
- }
- paint.setTextSize(40 + step / 100.0f);
-#if 0
- bool oneShot = false;
- for (int mask = 0; mask < 1 << testStrLen; ++mask) {
- char maskStr[testStrLen];
-#if 1
- mask = 12;
- oneShot = true;
-#endif
- SkDebugf("mask=%d\n", mask);
- for (int letter = 0; letter < testStrLen; ++letter) {
- maskStr[letter] = mask & (1 << letter) ? testStr[letter] : ' ';
- }
- paint.getPosTextPath(maskStr, testStrLen, textPos, &path);
- // showPath(path, NULL);
- // SkDebugf("%d simplified:\n", mask);
- tryRonco(path);
- // testSimplifyx(path);
- if (oneShot) {
- break;
- }
- }
-#endif
- paint.getPosTextPath(testStr, testStrLen, textPos, &path);
-#if 0
- tryRonco(path);
- SkDebugf("RoncoDone!\n");
-#endif
-#if 0
- showPath(path, NULL);
- SkDebugf("simplified:\n");
-#endif
- return drawPaths(canvas, path, false);
-}
-
-static bool (*drawDemos[])(SkCanvas* , int , bool ) = {
- drawStars,
- drawCircles,
- drawLetters,
-};
-
-static size_t drawDemosCount = sizeof(drawDemos) / sizeof(drawDemos[0]);
-
-static bool (*firstTest)(SkCanvas* , int , bool) = drawStars;
-
-
-bool DrawEdgeDemo(SkCanvas* canvas, int step, bool useOld) {
- size_t index = 0;
- if (firstTest) {
- while (index < drawDemosCount && drawDemos[index] != firstTest) {
- ++index;
- }
- }
- return (*drawDemos[index])(canvas, step, useOld);
-}
diff --git a/experimental/Intersection/EdgeDemo.h b/experimental/Intersection/EdgeDemo.h
deleted file mode 100644
index 934e546efe..0000000000
--- a/experimental/Intersection/EdgeDemo.h
+++ /dev/null
@@ -1,3 +0,0 @@
-class SkCanvas;
-
-bool DrawEdgeDemo(SkCanvas* canvas, int step, bool useOld);
diff --git a/experimental/Intersection/EdgeDemoApp-Info.plist b/experimental/Intersection/EdgeDemoApp-Info.plist
deleted file mode 100644
index 8e102020bc..0000000000
--- a/experimental/Intersection/EdgeDemoApp-Info.plist
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>CFBundleDevelopmentRegion</key>
- <string>English</string>
- <key>CFBundleExecutable</key>
- <string>${EXECUTABLE_NAME}</string>
- <key>CFBundleIconFile</key>
- <string></string>
- <key>CFBundleIdentifier</key>
- <string>com.googlecode.skia.${PRODUCT_NAME:rfc1034identifier}</string>
- <key>CFBundleInfoDictionaryVersion</key>
- <string>6.0</string>
- <key>CFBundleName</key>
- <string>${PRODUCT_NAME}</string>
- <key>CFBundlePackageType</key>
- <string>APPL</string>
- <key>CFBundleShortVersionString</key>
- <string>1.0</string>
- <key>CFBundleSignature</key>
- <string>????</string>
- <key>CFBundleVersion</key>
- <string>1</string>
- <key>LSMinimumSystemVersion</key>
- <string>${MACOSX_DEPLOYMENT_TARGET}</string>
- <key>NSMainNibFile</key>
- <string>EdgeDemoApp</string>
- <key>NSPrincipalClass</key>
- <string>NSApplication</string>
-</dict>
-</plist>
diff --git a/experimental/Intersection/EdgeDemoApp.mm b/experimental/Intersection/EdgeDemoApp.mm
deleted file mode 100644
index 7c50fea617..0000000000
--- a/experimental/Intersection/EdgeDemoApp.mm
+++ /dev/null
@@ -1,94 +0,0 @@
-#include "EdgeDemo.h"
-#import "SkCanvas.h"
-#import "SkWindow.h"
-#include "SkGraphics.h"
-#include "SkCGUtils.h"
-
-#include <time.h>
-#include <sys/time.h>
-
-class SkSampleView : public SkView {
-public:
- SkSampleView() {
- this->setVisibleP(true);
- this->setClipToBounds(false);
- useOld = false;
- };
-protected:
- virtual void onDraw(SkCanvas* canvas) {
- static int step = 0; // 17907 drawLetters first error
- // drawStars triggers error at 33348
- // drawStars error not easy to debug last time I checked
- static double seconds;
- if (step == -1) {
- timeval t;
- gettimeofday(&t, NULL);
- seconds = t.tv_sec+t.tv_usec/1000000.0;
- step = 0;
- }
- canvas->drawColor(SK_ColorWHITE);
- if (DrawEdgeDemo(canvas, step, useOld)) {
- ++step;
- if (step == -1) {
- timeval t;
- gettimeofday(&t, NULL);
- double last = seconds;
- seconds = t.tv_sec+t.tv_usec/1000000.0;
- SkDebugf("old=%d seconds=%g\n", useOld, seconds - last);
- useOld ^= true;
- step = 0;
- }
- inval(NULL);
- }
- }
-
- virtual Click* onFindClickHandler(SkScalar , SkScalar ) {
- useOld ^= true;
- return NULL;
- }
-
-private:
- bool useOld;
- typedef SkView INHERITED;
-};
-
-void application_init();
-void application_term();
-
-void application_init() {
- SkGraphics::Init();
- SkEvent::Init();
-}
-
-void application_term() {
- SkGraphics::Term();
- SkEvent::Term();
-}
-
-class FillLayout : public SkView::Layout {
-protected:
- virtual void onLayoutChildren(SkView* parent) {
- SkView* view = SkView::F2BIter(parent).next();
- view->setSize(parent->width(), parent->height());
- }
-};
-
-#import "SimpleApp.h"
-
-@implementation SimpleNSView
-
-- (id)initWithDefaults {
- if ((self = [super initWithDefaults])) {
- fWind = new SkOSWindow(self);
- fWind->setLayout(new FillLayout, false);
- fWind->attachChildToFront(new SkSampleView)->unref();
- }
- return self;
-}
-
-- (void)drawRect:(NSRect)dirtyRect {
- CGContextRef ctx = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
- SkCGDrawBitmap(ctx, fWind->getBitmap(), 0, 0);
-}
-
-@end
diff --git a/experimental/Intersection/EdgeDemoApp.xib b/experimental/Intersection/EdgeDemoApp.xib
deleted file mode 100644
index 863ead1eaa..0000000000
--- a/experimental/Intersection/EdgeDemoApp.xib
+++ /dev/null
@@ -1,3115 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
- <data>
- <int key="IBDocument.SystemTarget">1060</int>
- <string key="IBDocument.SystemVersion">10K549</string>
- <string key="IBDocument.InterfaceBuilderVersion">851</string>
- <string key="IBDocument.AppKitVersion">1038.36</string>
- <string key="IBDocument.HIToolboxVersion">461.00</string>
- <object class="NSMutableDictionary" key="IBDocument.PluginVersions">
- <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="NS.object.0">851</string>
- </object>
- <object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <integer value="261"/>
- </object>
- <object class="NSArray" key="IBDocument.PluginDependencies">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- </object>
- <object class="NSMutableDictionary" key="IBDocument.Metadata">
- <string key="NS.key.0">PluginDependencyRecalculationVersion</string>
- <integer value="1" key="NS.object.0"/>
- </object>
- <object class="NSMutableArray" key="IBDocument.RootObjects" id="110858478">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSCustomObject" id="762632889">
- <string key="NSClassName">IBInspector</string>
- </object>
- <object class="NSCustomObject" id="932410077">
- <string key="NSClassName">FirstResponder</string>
- </object>
- <object class="NSCustomObject" id="858592610">
- <string key="NSClassName">NSApplication</string>
- </object>
- <object class="NSMenu" id="403715256">
- <string key="NSTitle">AMainMenu</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSMenuItem" id="65739106">
- <reference key="NSMenu" ref="403715256"/>
- <string key="NSTitle">hello</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <object class="NSCustomResource" key="NSOnImage" id="573986354">
- <string key="NSClassName">NSImage</string>
- <string key="NSResourceName">NSMenuCheckmark</string>
- </object>
- <object class="NSCustomResource" key="NSMixedImage" id="622334842">
- <string key="NSClassName">NSImage</string>
- <string key="NSResourceName">NSMenuMixedState</string>
- </object>
- <string key="NSAction">submenuAction:</string>
- <object class="NSMenu" key="NSSubmenu" id="964556876">
- <string key="NSTitle">hello</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSMenuItem" id="627636549">
- <reference key="NSMenu" ref="964556876"/>
- <string key="NSTitle">About hello</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="938722355">
- <reference key="NSMenu" ref="964556876"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="1026802975">
- <reference key="NSMenu" ref="964556876"/>
- <string key="NSTitle">Preferences…</string>
- <string key="NSKeyEquiv">,</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="200976220">
- <reference key="NSMenu" ref="964556876"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="226934908">
- <reference key="NSMenu" ref="964556876"/>
- <string key="NSTitle">Services</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- <string key="NSAction">submenuAction:</string>
- <object class="NSMenu" key="NSSubmenu" id="785419060">
- <string key="NSTitle">Services</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- </object>
- <string key="NSName">_NSServicesMenu</string>
- </object>
- </object>
- <object class="NSMenuItem" id="1031569584">
- <reference key="NSMenu" ref="964556876"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="650251791">
- <reference key="NSMenu" ref="964556876"/>
- <string key="NSTitle">Hide hello</string>
- <string key="NSKeyEquiv">h</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="890704348">
- <reference key="NSMenu" ref="964556876"/>
- <string key="NSTitle">Hide Others</string>
- <string key="NSKeyEquiv">h</string>
- <int key="NSKeyEquivModMask">1572864</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="373184661">
- <reference key="NSMenu" ref="964556876"/>
- <string key="NSTitle">Show All</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="140060996">
- <reference key="NSMenu" ref="964556876"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="674334250">
- <reference key="NSMenu" ref="964556876"/>
- <string key="NSTitle">Quit hello</string>
- <string key="NSKeyEquiv">q</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- </object>
- <string key="NSName">_NSAppleMenu</string>
- </object>
- </object>
- <object class="NSMenuItem" id="849503563">
- <reference key="NSMenu" ref="403715256"/>
- <string key="NSTitle">File</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- <string key="NSAction">submenuAction:</string>
- <object class="NSMenu" key="NSSubmenu" id="899147076">
- <string key="NSTitle">File</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSMenuItem" id="940143719">
- <reference key="NSMenu" ref="899147076"/>
- <string key="NSTitle">New</string>
- <string key="NSKeyEquiv">n</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="416202392">
- <reference key="NSMenu" ref="899147076"/>
- <string key="NSTitle">Open…</string>
- <string key="NSKeyEquiv">o</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="802841280">
- <reference key="NSMenu" ref="899147076"/>
- <string key="NSTitle">Open Recent</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- <string key="NSAction">submenuAction:</string>
- <object class="NSMenu" key="NSSubmenu" id="250982885">
- <string key="NSTitle">Open Recent</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSMenuItem" id="940066582">
- <reference key="NSMenu" ref="250982885"/>
- <string key="NSTitle">Clear Menu</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- </object>
- <string key="NSName">_NSRecentDocumentsMenu</string>
- </object>
- </object>
- <object class="NSMenuItem" id="646964482">
- <reference key="NSMenu" ref="899147076"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="113331390">
- <reference key="NSMenu" ref="899147076"/>
- <string key="NSTitle">Close</string>
- <string key="NSKeyEquiv">w</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="717042078">
- <reference key="NSMenu" ref="899147076"/>
- <string key="NSTitle">Save</string>
- <string key="NSKeyEquiv">s</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="259193863">
- <reference key="NSMenu" ref="899147076"/>
- <string key="NSTitle">Save As…</string>
- <string key="NSKeyEquiv">S</string>
- <int key="NSKeyEquivModMask">1179648</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="523869872">
- <reference key="NSMenu" ref="899147076"/>
- <string key="NSTitle">Revert to Saved</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="425999990">
- <reference key="NSMenu" ref="899147076"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="917170545">
- <reference key="NSMenu" ref="899147076"/>
- <string key="NSTitle">Page Setup...</string>
- <string key="NSKeyEquiv">P</string>
- <int key="NSKeyEquivModMask">1179648</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- <string key="NSToolTip"/>
- </object>
- <object class="NSMenuItem" id="600825955">
- <reference key="NSMenu" ref="899147076"/>
- <string key="NSTitle">Print…</string>
- <string key="NSKeyEquiv">p</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- </object>
- </object>
- </object>
- <object class="NSMenuItem" id="825040645">
- <reference key="NSMenu" ref="403715256"/>
- <string key="NSTitle">Edit</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- <string key="NSAction">submenuAction:</string>
- <object class="NSMenu" key="NSSubmenu" id="411995980">
- <string key="NSTitle">Edit</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSMenuItem" id="155877797">
- <reference key="NSMenu" ref="411995980"/>
- <string key="NSTitle">Undo</string>
- <string key="NSKeyEquiv">z</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="278282207">
- <reference key="NSMenu" ref="411995980"/>
- <string key="NSTitle">Redo</string>
- <string key="NSKeyEquiv">Z</string>
- <int key="NSKeyEquivModMask">1179648</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="287041942">
- <reference key="NSMenu" ref="411995980"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="761075222">
- <reference key="NSMenu" ref="411995980"/>
- <string key="NSTitle">Cut</string>
- <string key="NSKeyEquiv">x</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="617541932">
- <reference key="NSMenu" ref="411995980"/>
- <string key="NSTitle">Copy</string>
- <string key="NSKeyEquiv">c</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="404580975">
- <reference key="NSMenu" ref="411995980"/>
- <string key="NSTitle">Paste</string>
- <string key="NSKeyEquiv">v</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="890043556">
- <reference key="NSMenu" ref="411995980"/>
- <string key="NSTitle">Paste and Match Style</string>
- <string key="NSKeyEquiv">V</string>
- <int key="NSKeyEquivModMask">1572864</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="572775670">
- <reference key="NSMenu" ref="411995980"/>
- <string key="NSTitle">Delete</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="826813329">
- <reference key="NSMenu" ref="411995980"/>
- <string key="NSTitle">Select All</string>
- <string key="NSKeyEquiv">a</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="393301673">
- <reference key="NSMenu" ref="411995980"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="726470551">
- <reference key="NSMenu" ref="411995980"/>
- <string key="NSTitle">Find</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- <string key="NSAction">submenuAction:</string>
- <object class="NSMenu" key="NSSubmenu" id="759421779">
- <string key="NSTitle">Find</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSMenuItem" id="871728498">
- <reference key="NSMenu" ref="759421779"/>
- <string key="NSTitle">Find…</string>
- <string key="NSKeyEquiv">f</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- <int key="NSTag">1</int>
- </object>
- <object class="NSMenuItem" id="392793967">
- <reference key="NSMenu" ref="759421779"/>
- <string key="NSTitle">Find Next</string>
- <string key="NSKeyEquiv">g</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- <int key="NSTag">2</int>
- </object>
- <object class="NSMenuItem" id="209754492">
- <reference key="NSMenu" ref="759421779"/>
- <string key="NSTitle">Find Previous</string>
- <string key="NSKeyEquiv">G</string>
- <int key="NSKeyEquivModMask">1179648</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- <int key="NSTag">3</int>
- </object>
- <object class="NSMenuItem" id="300840686">
- <reference key="NSMenu" ref="759421779"/>
- <string key="NSTitle">Use Selection for Find</string>
- <string key="NSKeyEquiv">e</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- <int key="NSTag">7</int>
- </object>
- <object class="NSMenuItem" id="339241627">
- <reference key="NSMenu" ref="759421779"/>
- <string key="NSTitle">Jump to Selection</string>
- <string key="NSKeyEquiv">j</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- </object>
- </object>
- </object>
- <object class="NSMenuItem" id="394001634">
- <reference key="NSMenu" ref="411995980"/>
- <string key="NSTitle">Spelling and Grammar</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- <string key="NSAction">submenuAction:</string>
- <object class="NSMenu" key="NSSubmenu" id="48019006">
- <string key="NSTitle">Spelling and Grammar</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSMenuItem" id="641875902">
- <reference key="NSMenu" ref="48019006"/>
- <string key="NSTitle">Show Spelling and Grammar</string>
- <string key="NSKeyEquiv">:</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="519234687">
- <reference key="NSMenu" ref="48019006"/>
- <string key="NSTitle">Check Document Now</string>
- <string key="NSKeyEquiv">;</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="566175535">
- <reference key="NSMenu" ref="48019006"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="32560783">
- <reference key="NSMenu" ref="48019006"/>
- <string key="NSTitle">Check Spelling While Typing</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="74735022">
- <reference key="NSMenu" ref="48019006"/>
- <string key="NSTitle">Check Grammar With Spelling</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="440900682">
- <reference key="NSMenu" ref="48019006"/>
- <string key="NSTitle">Correct Spelling Automatically</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- </object>
- </object>
- </object>
- <object class="NSMenuItem" id="723250450">
- <reference key="NSMenu" ref="411995980"/>
- <string key="NSTitle">Substitutions</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- <string key="NSAction">submenuAction:</string>
- <object class="NSMenu" key="NSSubmenu" id="60916223">
- <string key="NSTitle">Substitutions</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSMenuItem" id="499113305">
- <reference key="NSMenu" ref="60916223"/>
- <string key="NSTitle">Show Substitutions</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="604095584">
- <reference key="NSMenu" ref="60916223"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="1037848121">
- <reference key="NSMenu" ref="60916223"/>
- <string key="NSTitle">Smart Copy/Paste</string>
- <string key="NSKeyEquiv">f</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- <int key="NSTag">1</int>
- </object>
- <object class="NSMenuItem" id="253602211">
- <reference key="NSMenu" ref="60916223"/>
- <string key="NSTitle">Smart Quotes</string>
- <string key="NSKeyEquiv">g</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- <int key="NSTag">2</int>
- </object>
- <object class="NSMenuItem" id="870101879">
- <reference key="NSMenu" ref="60916223"/>
- <string key="NSTitle">Smart Dashes</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="818701236">
- <reference key="NSMenu" ref="60916223"/>
- <string key="NSTitle">Smart Links</string>
- <string key="NSKeyEquiv">G</string>
- <int key="NSKeyEquivModMask">1179648</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- <int key="NSTag">3</int>
- </object>
- <object class="NSMenuItem" id="682811574">
- <reference key="NSMenu" ref="60916223"/>
- <string key="NSTitle">Text Replacement</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- </object>
- </object>
- </object>
- <object class="NSMenuItem" id="1022343180">
- <reference key="NSMenu" ref="411995980"/>
- <string key="NSTitle">Transformations</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- <string key="NSAction">submenuAction:</string>
- <object class="NSMenu" key="NSSubmenu" id="799869067">
- <string key="NSTitle">Transformations</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSMenuItem" id="242386505">
- <reference key="NSMenu" ref="799869067"/>
- <string key="NSTitle">Make Upper Case</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="980071763">
- <reference key="NSMenu" ref="799869067"/>
- <string key="NSTitle">Make Lower Case</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="138959048">
- <reference key="NSMenu" ref="799869067"/>
- <string key="NSTitle">Capitalize</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- </object>
- </object>
- </object>
- <object class="NSMenuItem" id="538735815">
- <reference key="NSMenu" ref="411995980"/>
- <string key="NSTitle">Speech</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- <string key="NSAction">submenuAction:</string>
- <object class="NSMenu" key="NSSubmenu" id="92848229">
- <string key="NSTitle">Speech</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSMenuItem" id="242466330">
- <reference key="NSMenu" ref="92848229"/>
- <string key="NSTitle">Start Speaking</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="892418348">
- <reference key="NSMenu" ref="92848229"/>
- <string key="NSTitle">Stop Speaking</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- <object class="NSMenuItem" id="126299768">
- <reference key="NSMenu" ref="403715256"/>
- <string key="NSTitle">Format</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- <string key="NSAction">submenuAction:</string>
- <object class="NSMenu" key="NSSubmenu" id="473359030">
- <string key="NSTitle">Format</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSMenuItem" id="543679380">
- <reference key="NSMenu" ref="473359030"/>
- <string key="NSTitle">Font</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- <string key="NSAction">submenuAction:</string>
- <object class="NSMenu" key="NSSubmenu" id="420125509">
- <string key="NSTitle">Font</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSMenuItem" id="1066858">
- <reference key="NSMenu" ref="420125509"/>
- <string key="NSTitle">Show Fonts</string>
- <string key="NSKeyEquiv">t</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="890909023">
- <reference key="NSMenu" ref="420125509"/>
- <string key="NSTitle">Bold</string>
- <string key="NSKeyEquiv">b</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- <int key="NSTag">2</int>
- </object>
- <object class="NSMenuItem" id="460689417">
- <reference key="NSMenu" ref="420125509"/>
- <string key="NSTitle">Italic</string>
- <string key="NSKeyEquiv">i</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- <int key="NSTag">1</int>
- </object>
- <object class="NSMenuItem" id="648810690">
- <reference key="NSMenu" ref="420125509"/>
- <string key="NSTitle">Underline</string>
- <string key="NSKeyEquiv">u</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="648523518">
- <reference key="NSMenu" ref="420125509"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="554361477">
- <reference key="NSMenu" ref="420125509"/>
- <string key="NSTitle">Bigger</string>
- <string key="NSKeyEquiv">+</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- <int key="NSTag">3</int>
- </object>
- <object class="NSMenuItem" id="509852642">
- <reference key="NSMenu" ref="420125509"/>
- <string key="NSTitle">Smaller</string>
- <string key="NSKeyEquiv">-</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- <int key="NSTag">4</int>
- </object>
- <object class="NSMenuItem" id="684419220">
- <reference key="NSMenu" ref="420125509"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="300760265">
- <reference key="NSMenu" ref="420125509"/>
- <string key="NSTitle">Kern</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- <string key="NSAction">submenuAction:</string>
- <object class="NSMenu" key="NSSubmenu" id="692426030">
- <string key="NSTitle">Kern</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSMenuItem" id="827985012">
- <reference key="NSMenu" ref="692426030"/>
- <string key="NSTitle">Use Default</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="114397248">
- <reference key="NSMenu" ref="692426030"/>
- <string key="NSTitle">Use None</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="464129683">
- <reference key="NSMenu" ref="692426030"/>
- <string key="NSTitle">Tighten</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="984558289">
- <reference key="NSMenu" ref="692426030"/>
- <string key="NSTitle">Loosen</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- </object>
- </object>
- </object>
- <object class="NSMenuItem" id="764895229">
- <reference key="NSMenu" ref="420125509"/>
- <string key="NSTitle">Ligature</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- <string key="NSAction">submenuAction:</string>
- <object class="NSMenu" key="NSSubmenu" id="1027046122">
- <string key="NSTitle">Ligature</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSMenuItem" id="170445579">
- <reference key="NSMenu" ref="1027046122"/>
- <string key="NSTitle">Use Default</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="1054539967">
- <reference key="NSMenu" ref="1027046122"/>
- <string key="NSTitle">Use None</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="193227140">
- <reference key="NSMenu" ref="1027046122"/>
- <string key="NSTitle">Use All</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- </object>
- </object>
- </object>
- <object class="NSMenuItem" id="185308913">
- <reference key="NSMenu" ref="420125509"/>
- <string key="NSTitle">Baseline</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- <string key="NSAction">submenuAction:</string>
- <object class="NSMenu" key="NSSubmenu" id="412235399">
- <string key="NSTitle">Baseline</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSMenuItem" id="708934364">
- <reference key="NSMenu" ref="412235399"/>
- <string key="NSTitle">Use Default</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="660376852">
- <reference key="NSMenu" ref="412235399"/>
- <string key="NSTitle">Superscript</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="887484660">
- <reference key="NSMenu" ref="412235399"/>
- <string key="NSTitle">Subscript</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="239990007">
- <reference key="NSMenu" ref="412235399"/>
- <string key="NSTitle">Raise</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="794052095">
- <reference key="NSMenu" ref="412235399"/>
- <string key="NSTitle">Lower</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- </object>
- </object>
- </object>
- <object class="NSMenuItem" id="770408504">
- <reference key="NSMenu" ref="420125509"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="968537172">
- <reference key="NSMenu" ref="420125509"/>
- <string key="NSTitle">Show Colors</string>
- <string key="NSKeyEquiv">C</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="576239163">
- <reference key="NSMenu" ref="420125509"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="951733979">
- <reference key="NSMenu" ref="420125509"/>
- <string key="NSTitle">Copy Style</string>
- <string key="NSKeyEquiv">c</string>
- <int key="NSKeyEquivModMask">1572864</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="726071842">
- <reference key="NSMenu" ref="420125509"/>
- <string key="NSTitle">Paste Style</string>
- <string key="NSKeyEquiv">v</string>
- <int key="NSKeyEquivModMask">1572864</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- </object>
- <string key="NSName">_NSFontMenu</string>
- </object>
- </object>
- <object class="NSMenuItem" id="432500292">
- <reference key="NSMenu" ref="473359030"/>
- <string key="NSTitle">Text</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- <string key="NSAction">submenuAction:</string>
- <object class="NSMenu" key="NSSubmenu" id="239792765">
- <string key="NSTitle">Text</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSMenuItem" id="209955373">
- <reference key="NSMenu" ref="239792765"/>
- <string key="NSTitle">Align Left</string>
- <string key="NSKeyEquiv">{</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="940415998">
- <reference key="NSMenu" ref="239792765"/>
- <string key="NSTitle">Center</string>
- <string key="NSKeyEquiv">|</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="667530981">
- <reference key="NSMenu" ref="239792765"/>
- <string key="NSTitle">Justify</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="518803967">
- <reference key="NSMenu" ref="239792765"/>
- <string key="NSTitle">Align Right</string>
- <string key="NSKeyEquiv">}</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="755110083">
- <reference key="NSMenu" ref="239792765"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="970864302">
- <reference key="NSMenu" ref="239792765"/>
- <string key="NSTitle">Writing Direction</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- <string key="NSAction">submenuAction:</string>
- <object class="NSMenu" key="NSSubmenu" id="394707630">
- <string key="NSTitle">Writing Direction</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSMenuItem" id="295941739">
- <reference key="NSMenu" ref="394707630"/>
- <bool key="NSIsDisabled">YES</bool>
- <string key="NSTitle">Paragraph</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="1016781112">
- <reference key="NSMenu" ref="394707630"/>
- <string type="base64-UTF8" key="NSTitle">CURlZmF1bHQ</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="909594320">
- <reference key="NSMenu" ref="394707630"/>
- <string type="base64-UTF8" key="NSTitle">CUxlZnQgdG8gUmlnaHQ</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="294875881">
- <reference key="NSMenu" ref="394707630"/>
- <string type="base64-UTF8" key="NSTitle">CVJpZ2h0IHRvIExlZnQ</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="125873089">
- <reference key="NSMenu" ref="394707630"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="448907901">
- <reference key="NSMenu" ref="394707630"/>
- <bool key="NSIsDisabled">YES</bool>
- <string key="NSTitle">Selection</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="719807015">
- <reference key="NSMenu" ref="394707630"/>
- <string type="base64-UTF8" key="NSTitle">CURlZmF1bHQ</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="551093393">
- <reference key="NSMenu" ref="394707630"/>
- <string type="base64-UTF8" key="NSTitle">CUxlZnQgdG8gUmlnaHQ</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="968290247">
- <reference key="NSMenu" ref="394707630"/>
- <string type="base64-UTF8" key="NSTitle">CVJpZ2h0IHRvIExlZnQ</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- </object>
- </object>
- </object>
- <object class="NSMenuItem" id="624010617">
- <reference key="NSMenu" ref="239792765"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="178871919">
- <reference key="NSMenu" ref="239792765"/>
- <string key="NSTitle">Show Ruler</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="19133321">
- <reference key="NSMenu" ref="239792765"/>
- <string key="NSTitle">Copy Ruler</string>
- <string key="NSKeyEquiv">c</string>
- <int key="NSKeyEquivModMask">1310720</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="971682598">
- <reference key="NSMenu" ref="239792765"/>
- <string key="NSTitle">Paste Ruler</string>
- <string key="NSKeyEquiv">v</string>
- <int key="NSKeyEquivModMask">1310720</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- <object class="NSMenuItem" id="474036278">
- <reference key="NSMenu" ref="403715256"/>
- <string key="NSTitle">View</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- <string key="NSAction">submenuAction:</string>
- <object class="NSMenu" key="NSSubmenu" id="1011573215">
- <string key="NSTitle">View</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSMenuItem" id="84198938">
- <reference key="NSMenu" ref="1011573215"/>
- <string key="NSTitle">Show Toolbar</string>
- <string key="NSKeyEquiv">t</string>
- <int key="NSKeyEquivModMask">1572864</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="468947355">
- <reference key="NSMenu" ref="1011573215"/>
- <string key="NSTitle">Customize Toolbar…</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- </object>
- </object>
- </object>
- <object class="NSMenuItem" id="179474997">
- <reference key="NSMenu" ref="403715256"/>
- <string key="NSTitle">Window</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- <string key="NSAction">submenuAction:</string>
- <object class="NSMenu" key="NSSubmenu" id="722436082">
- <string key="NSTitle">Window</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSMenuItem" id="715853698">
- <reference key="NSMenu" ref="722436082"/>
- <string key="NSTitle">Minimize</string>
- <string key="NSKeyEquiv">m</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="639724461">
- <reference key="NSMenu" ref="722436082"/>
- <string key="NSTitle">Zoom</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="541256952">
- <reference key="NSMenu" ref="722436082"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- <object class="NSMenuItem" id="801808839">
- <reference key="NSMenu" ref="722436082"/>
- <string key="NSTitle">Bring All to Front</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- </object>
- <string key="NSName">_NSWindowsMenu</string>
- </object>
- </object>
- <object class="NSMenuItem" id="964815204">
- <reference key="NSMenu" ref="403715256"/>
- <string key="NSTitle">Help</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- <string key="NSAction">submenuAction:</string>
- <object class="NSMenu" key="NSSubmenu" id="445400279">
- <string key="NSTitle">Help</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSMenuItem" id="820408786">
- <reference key="NSMenu" ref="445400279"/>
- <string key="NSTitle">hello Help</string>
- <string key="NSKeyEquiv">?</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="573986354"/>
- <reference key="NSMixedImage" ref="622334842"/>
- </object>
- </object>
- <string key="NSName">_NSHelpMenu</string>
- </object>
- </object>
- </object>
- <string key="NSName">_NSMainMenu</string>
- </object>
- <object class="NSWindowTemplate" id="407166972">
- <int key="NSWindowStyleMask">15</int>
- <int key="NSWindowBacking">2</int>
- <string key="NSWindowRect">{{335, 289}, {640, 461}}</string>
- <int key="NSWTFlags">1954021376</int>
- <string key="NSWindowTitle">hello</string>
- <string key="NSWindowClass">NSWindow</string>
- <nil key="NSViewClass"/>
- <string key="NSWindowContentMaxSize">{1.79769e+308, 1.79769e+308}</string>
- <object class="NSView" key="NSWindowView" id="813288216">
- <reference key="NSNextResponder"/>
- <int key="NSvFlags">256</int>
- <object class="NSMutableArray" key="NSSubviews">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSCustomView" id="410337987">
- <reference key="NSNextResponder" ref="813288216"/>
- <int key="NSvFlags">286</int>
- <string key="NSFrameSize">{640, 480}</string>
- <reference key="NSSuperview" ref="813288216"/>
- <string key="NSClassName">SimpleNSView</string>
- </object>
- </object>
- <string key="NSFrameSize">{640, 461}</string>
- <reference key="NSSuperview"/>
- </object>
- <string key="NSScreenRect">{{0, 0}, {1600, 2538}}</string>
- <string key="NSMaxSize">{1.79769e+308, 1.79769e+308}</string>
- </object>
- </object>
- <object class="IBObjectContainer" key="IBDocument.Objects">
- <object class="NSMutableArray" key="connectionRecords">
- <bool key="EncodedWithXMLCoder">YES</bool>
- </object>
- <object class="IBMutableOrderedSet" key="objectRecords">
- <object class="NSArray" key="orderedObjects">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="IBObjectRecord">
- <int key="objectID">0</int>
- <object class="NSArray" key="object" id="485438096">
- <bool key="EncodedWithXMLCoder">YES</bool>
- </object>
- <reference key="children" ref="110858478"/>
- <nil key="parent"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">-2</int>
- <reference key="object" ref="762632889"/>
- <reference key="parent" ref="485438096"/>
- <string key="objectName">File's Owner</string>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">-1</int>
- <reference key="object" ref="932410077"/>
- <reference key="parent" ref="485438096"/>
- <string key="objectName">First Responder</string>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">-3</int>
- <reference key="object" ref="858592610"/>
- <reference key="parent" ref="485438096"/>
- <string key="objectName">Application</string>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">114</int>
- <reference key="object" ref="403715256"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="964815204"/>
- <reference ref="126299768"/>
- <reference ref="474036278"/>
- <reference ref="849503563"/>
- <reference ref="825040645"/>
- <reference ref="65739106"/>
- <reference ref="179474997"/>
- </object>
- <reference key="parent" ref="485438096"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">115</int>
- <reference key="object" ref="964815204"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="445400279"/>
- </object>
- <reference key="parent" ref="403715256"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">116</int>
- <reference key="object" ref="126299768"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="473359030"/>
- </object>
- <reference key="parent" ref="403715256"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">117</int>
- <reference key="object" ref="474036278"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="1011573215"/>
- </object>
- <reference key="parent" ref="403715256"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">118</int>
- <reference key="object" ref="849503563"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="899147076"/>
- </object>
- <reference key="parent" ref="403715256"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">119</int>
- <reference key="object" ref="825040645"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="411995980"/>
- </object>
- <reference key="parent" ref="403715256"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">120</int>
- <reference key="object" ref="65739106"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="964556876"/>
- </object>
- <reference key="parent" ref="403715256"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">121</int>
- <reference key="object" ref="179474997"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="722436082"/>
- </object>
- <reference key="parent" ref="403715256"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">122</int>
- <reference key="object" ref="722436082"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="715853698"/>
- <reference ref="639724461"/>
- <reference ref="801808839"/>
- <reference ref="541256952"/>
- </object>
- <reference key="parent" ref="179474997"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">123</int>
- <reference key="object" ref="715853698"/>
- <reference key="parent" ref="722436082"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">124</int>
- <reference key="object" ref="639724461"/>
- <reference key="parent" ref="722436082"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">125</int>
- <reference key="object" ref="801808839"/>
- <reference key="parent" ref="722436082"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">126</int>
- <reference key="object" ref="541256952"/>
- <reference key="parent" ref="722436082"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">127</int>
- <reference key="object" ref="964556876"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="890704348"/>
- <reference ref="140060996"/>
- <reference ref="226934908"/>
- <reference ref="938722355"/>
- <reference ref="200976220"/>
- <reference ref="1026802975"/>
- <reference ref="1031569584"/>
- <reference ref="674334250"/>
- <reference ref="373184661"/>
- <reference ref="650251791"/>
- <reference ref="627636549"/>
- </object>
- <reference key="parent" ref="65739106"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">128</int>
- <reference key="object" ref="890704348"/>
- <reference key="parent" ref="964556876"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">129</int>
- <reference key="object" ref="140060996"/>
- <reference key="parent" ref="964556876"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">130</int>
- <reference key="object" ref="226934908"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="785419060"/>
- </object>
- <reference key="parent" ref="964556876"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">131</int>
- <reference key="object" ref="938722355"/>
- <reference key="parent" ref="964556876"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">132</int>
- <reference key="object" ref="200976220"/>
- <reference key="parent" ref="964556876"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">133</int>
- <reference key="object" ref="1026802975"/>
- <reference key="parent" ref="964556876"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">134</int>
- <reference key="object" ref="1031569584"/>
- <reference key="parent" ref="964556876"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">135</int>
- <reference key="object" ref="674334250"/>
- <reference key="parent" ref="964556876"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">136</int>
- <reference key="object" ref="373184661"/>
- <reference key="parent" ref="964556876"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">137</int>
- <reference key="object" ref="650251791"/>
- <reference key="parent" ref="964556876"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">138</int>
- <reference key="object" ref="627636549"/>
- <reference key="parent" ref="964556876"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">139</int>
- <reference key="object" ref="785419060"/>
- <reference key="parent" ref="226934908"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">140</int>
- <reference key="object" ref="411995980"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="890043556"/>
- <reference ref="1022343180"/>
- <reference ref="723250450"/>
- <reference ref="538735815"/>
- <reference ref="394001634"/>
- <reference ref="726470551"/>
- <reference ref="278282207"/>
- <reference ref="287041942"/>
- <reference ref="617541932"/>
- <reference ref="404580975"/>
- <reference ref="761075222"/>
- <reference ref="393301673"/>
- <reference ref="155877797"/>
- <reference ref="826813329"/>
- <reference ref="572775670"/>
- </object>
- <reference key="parent" ref="825040645"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">141</int>
- <reference key="object" ref="890043556"/>
- <reference key="parent" ref="411995980"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">142</int>
- <reference key="object" ref="1022343180"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="799869067"/>
- </object>
- <reference key="parent" ref="411995980"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">143</int>
- <reference key="object" ref="723250450"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="60916223"/>
- </object>
- <reference key="parent" ref="411995980"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">144</int>
- <reference key="object" ref="538735815"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="92848229"/>
- </object>
- <reference key="parent" ref="411995980"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">145</int>
- <reference key="object" ref="394001634"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="48019006"/>
- </object>
- <reference key="parent" ref="411995980"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">146</int>
- <reference key="object" ref="726470551"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="759421779"/>
- </object>
- <reference key="parent" ref="411995980"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">147</int>
- <reference key="object" ref="278282207"/>
- <reference key="parent" ref="411995980"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">148</int>
- <reference key="object" ref="287041942"/>
- <reference key="parent" ref="411995980"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">149</int>
- <reference key="object" ref="617541932"/>
- <reference key="parent" ref="411995980"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">150</int>
- <reference key="object" ref="404580975"/>
- <reference key="parent" ref="411995980"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">151</int>
- <reference key="object" ref="761075222"/>
- <reference key="parent" ref="411995980"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">152</int>
- <reference key="object" ref="393301673"/>
- <reference key="parent" ref="411995980"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">153</int>
- <reference key="object" ref="155877797"/>
- <reference key="parent" ref="411995980"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">154</int>
- <reference key="object" ref="826813329"/>
- <reference key="parent" ref="411995980"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">155</int>
- <reference key="object" ref="572775670"/>
- <reference key="parent" ref="411995980"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">156</int>
- <reference key="object" ref="759421779"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="871728498"/>
- <reference ref="392793967"/>
- <reference ref="300840686"/>
- <reference ref="339241627"/>
- <reference ref="209754492"/>
- </object>
- <reference key="parent" ref="726470551"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">157</int>
- <reference key="object" ref="871728498"/>
- <reference key="parent" ref="759421779"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">158</int>
- <reference key="object" ref="392793967"/>
- <reference key="parent" ref="759421779"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">159</int>
- <reference key="object" ref="300840686"/>
- <reference key="parent" ref="759421779"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">160</int>
- <reference key="object" ref="339241627"/>
- <reference key="parent" ref="759421779"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">161</int>
- <reference key="object" ref="209754492"/>
- <reference key="parent" ref="759421779"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">162</int>
- <reference key="object" ref="48019006"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="440900682"/>
- <reference ref="566175535"/>
- <reference ref="74735022"/>
- <reference ref="641875902"/>
- <reference ref="519234687"/>
- <reference ref="32560783"/>
- </object>
- <reference key="parent" ref="394001634"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">163</int>
- <reference key="object" ref="440900682"/>
- <reference key="parent" ref="48019006"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">164</int>
- <reference key="object" ref="566175535"/>
- <reference key="parent" ref="48019006"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">165</int>
- <reference key="object" ref="74735022"/>
- <reference key="parent" ref="48019006"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">166</int>
- <reference key="object" ref="641875902"/>
- <reference key="parent" ref="48019006"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">167</int>
- <reference key="object" ref="519234687"/>
- <reference key="parent" ref="48019006"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">168</int>
- <reference key="object" ref="32560783"/>
- <reference key="parent" ref="48019006"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">169</int>
- <reference key="object" ref="92848229"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="242466330"/>
- <reference ref="892418348"/>
- </object>
- <reference key="parent" ref="538735815"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">170</int>
- <reference key="object" ref="242466330"/>
- <reference key="parent" ref="92848229"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">171</int>
- <reference key="object" ref="892418348"/>
- <reference key="parent" ref="92848229"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">172</int>
- <reference key="object" ref="60916223"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="682811574"/>
- <reference ref="870101879"/>
- <reference ref="604095584"/>
- <reference ref="499113305"/>
- <reference ref="818701236"/>
- <reference ref="253602211"/>
- <reference ref="1037848121"/>
- </object>
- <reference key="parent" ref="723250450"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">173</int>
- <reference key="object" ref="682811574"/>
- <reference key="parent" ref="60916223"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">174</int>
- <reference key="object" ref="870101879"/>
- <reference key="parent" ref="60916223"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">175</int>
- <reference key="object" ref="604095584"/>
- <reference key="parent" ref="60916223"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">176</int>
- <reference key="object" ref="499113305"/>
- <reference key="parent" ref="60916223"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">177</int>
- <reference key="object" ref="818701236"/>
- <reference key="parent" ref="60916223"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">178</int>
- <reference key="object" ref="253602211"/>
- <reference key="parent" ref="60916223"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">179</int>
- <reference key="object" ref="1037848121"/>
- <reference key="parent" ref="60916223"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">180</int>
- <reference key="object" ref="799869067"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="138959048"/>
- <reference ref="980071763"/>
- <reference ref="242386505"/>
- </object>
- <reference key="parent" ref="1022343180"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">181</int>
- <reference key="object" ref="138959048"/>
- <reference key="parent" ref="799869067"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">182</int>
- <reference key="object" ref="980071763"/>
- <reference key="parent" ref="799869067"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">183</int>
- <reference key="object" ref="242386505"/>
- <reference key="parent" ref="799869067"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">184</int>
- <reference key="object" ref="899147076"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="425999990"/>
- <reference ref="523869872"/>
- <reference ref="646964482"/>
- <reference ref="113331390"/>
- <reference ref="917170545"/>
- <reference ref="802841280"/>
- <reference ref="940143719"/>
- <reference ref="416202392"/>
- <reference ref="600825955"/>
- <reference ref="259193863"/>
- <reference ref="717042078"/>
- </object>
- <reference key="parent" ref="849503563"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">185</int>
- <reference key="object" ref="425999990"/>
- <reference key="parent" ref="899147076"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">186</int>
- <reference key="object" ref="523869872"/>
- <reference key="parent" ref="899147076"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">187</int>
- <reference key="object" ref="646964482"/>
- <reference key="parent" ref="899147076"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">188</int>
- <reference key="object" ref="113331390"/>
- <reference key="parent" ref="899147076"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">189</int>
- <reference key="object" ref="917170545"/>
- <reference key="parent" ref="899147076"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">190</int>
- <reference key="object" ref="802841280"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="250982885"/>
- </object>
- <reference key="parent" ref="899147076"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">191</int>
- <reference key="object" ref="940143719"/>
- <reference key="parent" ref="899147076"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">192</int>
- <reference key="object" ref="416202392"/>
- <reference key="parent" ref="899147076"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">193</int>
- <reference key="object" ref="600825955"/>
- <reference key="parent" ref="899147076"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">194</int>
- <reference key="object" ref="259193863"/>
- <reference key="parent" ref="899147076"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">195</int>
- <reference key="object" ref="717042078"/>
- <reference key="parent" ref="899147076"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">196</int>
- <reference key="object" ref="250982885"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="940066582"/>
- </object>
- <reference key="parent" ref="802841280"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">197</int>
- <reference key="object" ref="940066582"/>
- <reference key="parent" ref="250982885"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">198</int>
- <reference key="object" ref="1011573215"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="468947355"/>
- <reference ref="84198938"/>
- </object>
- <reference key="parent" ref="474036278"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">199</int>
- <reference key="object" ref="468947355"/>
- <reference key="parent" ref="1011573215"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">200</int>
- <reference key="object" ref="84198938"/>
- <reference key="parent" ref="1011573215"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">201</int>
- <reference key="object" ref="473359030"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="432500292"/>
- <reference ref="543679380"/>
- </object>
- <reference key="parent" ref="126299768"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">202</int>
- <reference key="object" ref="432500292"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="239792765"/>
- </object>
- <reference key="parent" ref="473359030"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">203</int>
- <reference key="object" ref="543679380"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="420125509"/>
- </object>
- <reference key="parent" ref="473359030"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">204</int>
- <reference key="object" ref="420125509"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="726071842"/>
- <reference ref="951733979"/>
- <reference ref="576239163"/>
- <reference ref="968537172"/>
- <reference ref="770408504"/>
- <reference ref="185308913"/>
- <reference ref="764895229"/>
- <reference ref="300760265"/>
- <reference ref="684419220"/>
- <reference ref="509852642"/>
- <reference ref="554361477"/>
- <reference ref="648523518"/>
- <reference ref="648810690"/>
- <reference ref="460689417"/>
- <reference ref="890909023"/>
- <reference ref="1066858"/>
- </object>
- <reference key="parent" ref="543679380"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">205</int>
- <reference key="object" ref="726071842"/>
- <reference key="parent" ref="420125509"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">206</int>
- <reference key="object" ref="951733979"/>
- <reference key="parent" ref="420125509"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">207</int>
- <reference key="object" ref="576239163"/>
- <reference key="parent" ref="420125509"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">208</int>
- <reference key="object" ref="968537172"/>
- <reference key="parent" ref="420125509"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">209</int>
- <reference key="object" ref="770408504"/>
- <reference key="parent" ref="420125509"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">210</int>
- <reference key="object" ref="185308913"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="412235399"/>
- </object>
- <reference key="parent" ref="420125509"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">211</int>
- <reference key="object" ref="764895229"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="1027046122"/>
- </object>
- <reference key="parent" ref="420125509"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">212</int>
- <reference key="object" ref="300760265"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="692426030"/>
- </object>
- <reference key="parent" ref="420125509"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">213</int>
- <reference key="object" ref="684419220"/>
- <reference key="parent" ref="420125509"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">214</int>
- <reference key="object" ref="509852642"/>
- <reference key="parent" ref="420125509"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">215</int>
- <reference key="object" ref="554361477"/>
- <reference key="parent" ref="420125509"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">216</int>
- <reference key="object" ref="648523518"/>
- <reference key="parent" ref="420125509"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">217</int>
- <reference key="object" ref="648810690"/>
- <reference key="parent" ref="420125509"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">218</int>
- <reference key="object" ref="460689417"/>
- <reference key="parent" ref="420125509"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">219</int>
- <reference key="object" ref="890909023"/>
- <reference key="parent" ref="420125509"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">220</int>
- <reference key="object" ref="1066858"/>
- <reference key="parent" ref="420125509"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">221</int>
- <reference key="object" ref="692426030"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="984558289"/>
- <reference ref="464129683"/>
- <reference ref="114397248"/>
- <reference ref="827985012"/>
- </object>
- <reference key="parent" ref="300760265"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">222</int>
- <reference key="object" ref="984558289"/>
- <reference key="parent" ref="692426030"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">223</int>
- <reference key="object" ref="464129683"/>
- <reference key="parent" ref="692426030"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">224</int>
- <reference key="object" ref="114397248"/>
- <reference key="parent" ref="692426030"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">225</int>
- <reference key="object" ref="827985012"/>
- <reference key="parent" ref="692426030"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">226</int>
- <reference key="object" ref="1027046122"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="193227140"/>
- <reference ref="1054539967"/>
- <reference ref="170445579"/>
- </object>
- <reference key="parent" ref="764895229"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">227</int>
- <reference key="object" ref="193227140"/>
- <reference key="parent" ref="1027046122"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">228</int>
- <reference key="object" ref="1054539967"/>
- <reference key="parent" ref="1027046122"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">229</int>
- <reference key="object" ref="170445579"/>
- <reference key="parent" ref="1027046122"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">230</int>
- <reference key="object" ref="412235399"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="794052095"/>
- <reference ref="239990007"/>
- <reference ref="887484660"/>
- <reference ref="660376852"/>
- <reference ref="708934364"/>
- </object>
- <reference key="parent" ref="185308913"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">231</int>
- <reference key="object" ref="794052095"/>
- <reference key="parent" ref="412235399"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">232</int>
- <reference key="object" ref="239990007"/>
- <reference key="parent" ref="412235399"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">233</int>
- <reference key="object" ref="887484660"/>
- <reference key="parent" ref="412235399"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">234</int>
- <reference key="object" ref="660376852"/>
- <reference key="parent" ref="412235399"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">235</int>
- <reference key="object" ref="708934364"/>
- <reference key="parent" ref="412235399"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">236</int>
- <reference key="object" ref="239792765"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="971682598"/>
- <reference ref="19133321"/>
- <reference ref="178871919"/>
- <reference ref="624010617"/>
- <reference ref="970864302"/>
- <reference ref="755110083"/>
- <reference ref="518803967"/>
- <reference ref="667530981"/>
- <reference ref="940415998"/>
- <reference ref="209955373"/>
- </object>
- <reference key="parent" ref="432500292"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">237</int>
- <reference key="object" ref="971682598"/>
- <reference key="parent" ref="239792765"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">238</int>
- <reference key="object" ref="19133321"/>
- <reference key="parent" ref="239792765"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">239</int>
- <reference key="object" ref="178871919"/>
- <reference key="parent" ref="239792765"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">240</int>
- <reference key="object" ref="624010617"/>
- <reference key="parent" ref="239792765"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">241</int>
- <reference key="object" ref="970864302"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="394707630"/>
- </object>
- <reference key="parent" ref="239792765"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">242</int>
- <reference key="object" ref="755110083"/>
- <reference key="parent" ref="239792765"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">243</int>
- <reference key="object" ref="518803967"/>
- <reference key="parent" ref="239792765"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">244</int>
- <reference key="object" ref="667530981"/>
- <reference key="parent" ref="239792765"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">245</int>
- <reference key="object" ref="940415998"/>
- <reference key="parent" ref="239792765"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">246</int>
- <reference key="object" ref="209955373"/>
- <reference key="parent" ref="239792765"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">247</int>
- <reference key="object" ref="394707630"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="968290247"/>
- <reference ref="551093393"/>
- <reference ref="719807015"/>
- <reference ref="448907901"/>
- <reference ref="125873089"/>
- <reference ref="294875881"/>
- <reference ref="909594320"/>
- <reference ref="1016781112"/>
- <reference ref="295941739"/>
- </object>
- <reference key="parent" ref="970864302"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">248</int>
- <reference key="object" ref="968290247"/>
- <reference key="parent" ref="394707630"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">249</int>
- <reference key="object" ref="551093393"/>
- <reference key="parent" ref="394707630"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">250</int>
- <reference key="object" ref="719807015"/>
- <reference key="parent" ref="394707630"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">251</int>
- <reference key="object" ref="448907901"/>
- <reference key="parent" ref="394707630"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">252</int>
- <reference key="object" ref="125873089"/>
- <reference key="parent" ref="394707630"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">253</int>
- <reference key="object" ref="294875881"/>
- <reference key="parent" ref="394707630"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">254</int>
- <reference key="object" ref="909594320"/>
- <reference key="parent" ref="394707630"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">255</int>
- <reference key="object" ref="1016781112"/>
- <reference key="parent" ref="394707630"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">256</int>
- <reference key="object" ref="295941739"/>
- <reference key="parent" ref="394707630"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">257</int>
- <reference key="object" ref="445400279"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="820408786"/>
- </object>
- <reference key="parent" ref="964815204"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">258</int>
- <reference key="object" ref="820408786"/>
- <reference key="parent" ref="445400279"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">259</int>
- <reference key="object" ref="407166972"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="813288216"/>
- </object>
- <reference key="parent" ref="485438096"/>
- <string key="objectName">Window (SimpleApp)</string>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">260</int>
- <reference key="object" ref="813288216"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="410337987"/>
- </object>
- <reference key="parent" ref="407166972"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">261</int>
- <reference key="object" ref="410337987"/>
- <reference key="parent" ref="813288216"/>
- </object>
- </object>
- </object>
- <object class="NSMutableDictionary" key="flattenedProperties">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSArray" key="dict.sortedKeys">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <string>-3.IBPluginDependency</string>
- <string>-3.ImportedFromIB2</string>
- <string>114.IBEditorWindowLastContentRect</string>
- <string>114.IBPluginDependency</string>
- <string>114.ImportedFromIB2</string>
- <string>114.WindowOrigin</string>
- <string>114.editorWindowContentRectSynchronizationRect</string>
- <string>115.IBPluginDependency</string>
- <string>116.IBPluginDependency</string>
- <string>117.IBPluginDependency</string>
- <string>118.IBPluginDependency</string>
- <string>118.ImportedFromIB2</string>
- <string>119.IBPluginDependency</string>
- <string>119.ImportedFromIB2</string>
- <string>120.IBPluginDependency</string>
- <string>120.ImportedFromIB2</string>
- <string>121.IBPluginDependency</string>
- <string>121.ImportedFromIB2</string>
- <string>122.IBEditorWindowLastContentRect</string>
- <string>122.IBPluginDependency</string>
- <string>122.ImportedFromIB2</string>
- <string>122.editorWindowContentRectSynchronizationRect</string>
- <string>123.IBPluginDependency</string>
- <string>123.ImportedFromIB2</string>
- <string>124.IBPluginDependency</string>
- <string>124.ImportedFromIB2</string>
- <string>125.IBPluginDependency</string>
- <string>125.ImportedFromIB2</string>
- <string>126.IBPluginDependency</string>
- <string>126.ImportedFromIB2</string>
- <string>127.IBEditorWindowLastContentRect</string>
- <string>127.IBPluginDependency</string>
- <string>127.ImportedFromIB2</string>
- <string>127.editorWindowContentRectSynchronizationRect</string>
- <string>128.IBPluginDependency</string>
- <string>128.ImportedFromIB2</string>
- <string>129.IBPluginDependency</string>
- <string>129.ImportedFromIB2</string>
- <string>130.IBPluginDependency</string>
- <string>130.ImportedFromIB2</string>
- <string>131.IBPluginDependency</string>
- <string>131.ImportedFromIB2</string>
- <string>132.IBPluginDependency</string>
- <string>132.ImportedFromIB2</string>
- <string>133.IBPluginDependency</string>
- <string>133.ImportedFromIB2</string>
- <string>134.IBPluginDependency</string>
- <string>134.ImportedFromIB2</string>
- <string>135.IBPluginDependency</string>
- <string>135.ImportedFromIB2</string>
- <string>136.IBPluginDependency</string>
- <string>136.ImportedFromIB2</string>
- <string>137.IBPluginDependency</string>
- <string>137.ImportedFromIB2</string>
- <string>138.IBPluginDependency</string>
- <string>138.ImportedFromIB2</string>
- <string>139.IBPluginDependency</string>
- <string>139.ImportedFromIB2</string>
- <string>139.editorWindowContentRectSynchronizationRect</string>
- <string>140.IBEditorWindowLastContentRect</string>
- <string>140.IBPluginDependency</string>
- <string>140.ImportedFromIB2</string>
- <string>140.editorWindowContentRectSynchronizationRect</string>
- <string>141.IBPluginDependency</string>
- <string>142.IBPluginDependency</string>
- <string>143.IBPluginDependency</string>
- <string>143.ImportedFromIB2</string>
- <string>144.IBPluginDependency</string>
- <string>144.ImportedFromIB2</string>
- <string>145.IBPluginDependency</string>
- <string>145.ImportedFromIB2</string>
- <string>146.IBPluginDependency</string>
- <string>146.ImportedFromIB2</string>
- <string>147.IBPluginDependency</string>
- <string>147.ImportedFromIB2</string>
- <string>148.IBPluginDependency</string>
- <string>148.ImportedFromIB2</string>
- <string>149.IBPluginDependency</string>
- <string>149.ImportedFromIB2</string>
- <string>150.IBPluginDependency</string>
- <string>150.ImportedFromIB2</string>
- <string>151.IBPluginDependency</string>
- <string>151.ImportedFromIB2</string>
- <string>152.IBPluginDependency</string>
- <string>152.ImportedFromIB2</string>
- <string>153.IBPluginDependency</string>
- <string>153.ImportedFromIB2</string>
- <string>154.IBPluginDependency</string>
- <string>154.ImportedFromIB2</string>
- <string>155.IBPluginDependency</string>
- <string>155.ImportedFromIB2</string>
- <string>156.IBEditorWindowLastContentRect</string>
- <string>156.IBPluginDependency</string>
- <string>156.ImportedFromIB2</string>
- <string>156.editorWindowContentRectSynchronizationRect</string>
- <string>157.IBPluginDependency</string>
- <string>157.ImportedFromIB2</string>
- <string>158.IBPluginDependency</string>
- <string>158.ImportedFromIB2</string>
- <string>159.IBPluginDependency</string>
- <string>159.ImportedFromIB2</string>
- <string>160.IBPluginDependency</string>
- <string>160.ImportedFromIB2</string>
- <string>161.IBPluginDependency</string>
- <string>161.ImportedFromIB2</string>
- <string>162.IBEditorWindowLastContentRect</string>
- <string>162.IBPluginDependency</string>
- <string>162.ImportedFromIB2</string>
- <string>162.editorWindowContentRectSynchronizationRect</string>
- <string>163.IBPluginDependency</string>
- <string>164.IBPluginDependency</string>
- <string>165.IBPluginDependency</string>
- <string>165.ImportedFromIB2</string>
- <string>166.IBPluginDependency</string>
- <string>166.ImportedFromIB2</string>
- <string>167.IBPluginDependency</string>
- <string>167.ImportedFromIB2</string>
- <string>168.IBPluginDependency</string>
- <string>168.ImportedFromIB2</string>
- <string>169.IBPluginDependency</string>
- <string>169.ImportedFromIB2</string>
- <string>169.editorWindowContentRectSynchronizationRect</string>
- <string>170.IBPluginDependency</string>
- <string>170.ImportedFromIB2</string>
- <string>171.IBPluginDependency</string>
- <string>171.ImportedFromIB2</string>
- <string>172.IBEditorWindowLastContentRect</string>
- <string>172.IBPluginDependency</string>
- <string>172.ImportedFromIB2</string>
- <string>172.editorWindowContentRectSynchronizationRect</string>
- <string>173.IBPluginDependency</string>
- <string>174.IBPluginDependency</string>
- <string>175.IBPluginDependency</string>
- <string>176.IBPluginDependency</string>
- <string>177.IBPluginDependency</string>
- <string>177.ImportedFromIB2</string>
- <string>178.IBPluginDependency</string>
- <string>178.ImportedFromIB2</string>
- <string>179.IBPluginDependency</string>
- <string>179.ImportedFromIB2</string>
- <string>180.IBEditorWindowLastContentRect</string>
- <string>180.IBPluginDependency</string>
- <string>181.IBPluginDependency</string>
- <string>182.IBPluginDependency</string>
- <string>183.IBPluginDependency</string>
- <string>184.IBEditorWindowLastContentRect</string>
- <string>184.IBPluginDependency</string>
- <string>184.ImportedFromIB2</string>
- <string>184.editorWindowContentRectSynchronizationRect</string>
- <string>185.IBPluginDependency</string>
- <string>185.ImportedFromIB2</string>
- <string>186.IBPluginDependency</string>
- <string>186.ImportedFromIB2</string>
- <string>187.IBPluginDependency</string>
- <string>187.ImportedFromIB2</string>
- <string>188.IBPluginDependency</string>
- <string>188.ImportedFromIB2</string>
- <string>189.IBPluginDependency</string>
- <string>189.ImportedFromIB2</string>
- <string>190.IBPluginDependency</string>
- <string>190.ImportedFromIB2</string>
- <string>191.IBPluginDependency</string>
- <string>191.ImportedFromIB2</string>
- <string>192.IBPluginDependency</string>
- <string>192.ImportedFromIB2</string>
- <string>193.IBPluginDependency</string>
- <string>193.ImportedFromIB2</string>
- <string>194.IBPluginDependency</string>
- <string>194.ImportedFromIB2</string>
- <string>195.IBPluginDependency</string>
- <string>195.ImportedFromIB2</string>
- <string>196.IBPluginDependency</string>
- <string>196.ImportedFromIB2</string>
- <string>196.editorWindowContentRectSynchronizationRect</string>
- <string>197.IBPluginDependency</string>
- <string>197.ImportedFromIB2</string>
- <string>198.IBEditorWindowLastContentRect</string>
- <string>198.IBPluginDependency</string>
- <string>198.editorWindowContentRectSynchronizationRect</string>
- <string>199.IBPluginDependency</string>
- <string>200.IBPluginDependency</string>
- <string>201.IBEditorWindowLastContentRect</string>
- <string>201.IBPluginDependency</string>
- <string>202.IBPluginDependency</string>
- <string>203.IBPluginDependency</string>
- <string>204.IBEditorWindowLastContentRect</string>
- <string>204.IBPluginDependency</string>
- <string>205.IBPluginDependency</string>
- <string>206.IBPluginDependency</string>
- <string>207.IBPluginDependency</string>
- <string>208.IBPluginDependency</string>
- <string>209.IBPluginDependency</string>
- <string>210.IBPluginDependency</string>
- <string>211.IBPluginDependency</string>
- <string>212.IBPluginDependency</string>
- <string>213.IBPluginDependency</string>
- <string>214.IBPluginDependency</string>
- <string>215.IBPluginDependency</string>
- <string>216.IBPluginDependency</string>
- <string>217.IBPluginDependency</string>
- <string>218.IBPluginDependency</string>
- <string>219.IBPluginDependency</string>
- <string>220.IBPluginDependency</string>
- <string>221.IBPluginDependency</string>
- <string>222.IBPluginDependency</string>
- <string>223.IBPluginDependency</string>
- <string>224.IBPluginDependency</string>
- <string>225.IBPluginDependency</string>
- <string>226.IBPluginDependency</string>
- <string>227.IBPluginDependency</string>
- <string>228.IBPluginDependency</string>
- <string>229.IBPluginDependency</string>
- <string>230.IBPluginDependency</string>
- <string>231.IBPluginDependency</string>
- <string>232.IBPluginDependency</string>
- <string>233.IBPluginDependency</string>
- <string>234.IBPluginDependency</string>
- <string>235.IBPluginDependency</string>
- <string>236.IBEditorWindowLastContentRect</string>
- <string>236.IBPluginDependency</string>
- <string>237.IBPluginDependency</string>
- <string>238.IBPluginDependency</string>
- <string>239.IBPluginDependency</string>
- <string>240.IBPluginDependency</string>
- <string>241.IBPluginDependency</string>
- <string>242.IBPluginDependency</string>
- <string>243.IBPluginDependency</string>
- <string>244.IBPluginDependency</string>
- <string>245.IBPluginDependency</string>
- <string>246.IBPluginDependency</string>
- <string>247.IBEditorWindowLastContentRect</string>
- <string>247.IBPluginDependency</string>
- <string>248.IBPluginDependency</string>
- <string>249.IBPluginDependency</string>
- <string>250.IBPluginDependency</string>
- <string>251.IBPluginDependency</string>
- <string>252.IBPluginDependency</string>
- <string>253.IBPluginDependency</string>
- <string>254.IBPluginDependency</string>
- <string>255.IBPluginDependency</string>
- <string>256.IBPluginDependency</string>
- <string>257.IBEditorWindowLastContentRect</string>
- <string>257.IBPluginDependency</string>
- <string>258.IBPluginDependency</string>
- <string>259.IBEditorWindowLastContentRect</string>
- <string>259.IBPluginDependency</string>
- <string>259.IBWindowTemplateEditedContentRect</string>
- <string>259.NSWindowTemplate.visibleAtLaunch</string>
- <string>259.editorWindowContentRectSynchronizationRect</string>
- <string>259.windowTemplate.maxSize</string>
- <string>260.IBPluginDependency</string>
- <string>261.IBPluginDependency</string>
- <string>261.IBViewBoundsToFrameTransform</string>
- </object>
- <object class="NSMutableArray" key="dict.values">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>{{380, 836}, {400, 20}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>{74, 862}</string>
- <string>{{6, 978}, {478, 20}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>{{654, 239}, {194, 73}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>{{525, 802}, {197, 73}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>{{286, 129}, {275, 183}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>{{23, 794}, {245, 183}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>{{436, 809}, {64, 6}}</string>
- <string>{{547, 180}, {254, 283}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>{{187, 434}, {243, 243}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>{{753, 217}, {238, 103}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>{{608, 612}, {241, 103}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>{{753, 187}, {275, 113}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>{{608, 612}, {275, 83}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>{{608, 612}, {167, 43}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>{{746, 287}, {220, 133}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>{{608, 612}, {215, 63}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>{{753, 197}, {170, 63}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>{{452, 109}, {196, 203}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>{{145, 474}, {199, 203}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>{{522, 812}, {146, 23}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>{{604, 269}, {231, 43}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>{{475, 832}, {234, 43}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>{{591, 420}, {83, 43}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>{{523, 2}, {178, 283}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>{{674, 260}, {204, 183}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>{{878, 180}, {164, 173}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>{{725, 289}, {246, 23}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>{{451, 1180}, {640, 461}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>{{451, 1180}, {640, 461}}</string>
- <integer value="1"/>
- <string>{{33, 99}, {480, 360}}</string>
- <string>{3.40282e+38, 3.40282e+38}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <object class="NSAffineTransform"/>
- </object>
- </object>
- <object class="NSMutableDictionary" key="unlocalizedProperties">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference key="dict.sortedKeys" ref="485438096"/>
- <object class="NSMutableArray" key="dict.values">
- <bool key="EncodedWithXMLCoder">YES</bool>
- </object>
- </object>
- <nil key="activeLocalization"/>
- <object class="NSMutableDictionary" key="localizations">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference key="dict.sortedKeys" ref="485438096"/>
- <object class="NSMutableArray" key="dict.values">
- <bool key="EncodedWithXMLCoder">YES</bool>
- </object>
- </object>
- <nil key="sourceID"/>
- <int key="maxID">263</int>
- </object>
- <object class="IBClassDescriber" key="IBDocument.Classes">
- <object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">Foundation.framework/Headers/NSArchiver.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">Foundation.framework/Headers/NSClassDescription.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">Foundation.framework/Headers/NSError.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">Foundation.framework/Headers/NSFileManager.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">Foundation.framework/Headers/NSKeyValueCoding.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">Foundation.framework/Headers/NSKeyValueObserving.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">Foundation.framework/Headers/NSKeyedArchiver.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">Foundation.framework/Headers/NSObject.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">Foundation.framework/Headers/NSObjectScripting.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">Foundation.framework/Headers/NSPortCoder.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">Foundation.framework/Headers/NSRunLoop.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">Foundation.framework/Headers/NSScriptClassDescription.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">Foundation.framework/Headers/NSScriptKeyValueCoding.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">Foundation.framework/Headers/NSScriptObjectSpecifiers.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">Foundation.framework/Headers/NSScriptWhoseTests.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">Foundation.framework/Headers/NSThread.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">Foundation.framework/Headers/NSURL.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">Foundation.framework/Headers/NSURLConnection.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">Foundation.framework/Headers/NSURLDownload.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">PrintCore.framework/Headers/PDEPluginInterface.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">QuartzCore.framework/Headers/CAAnimation.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">QuartzCore.framework/Headers/CALayer.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">QuartzCore.framework/Headers/CIImageProvider.h</string>
- </object>
- </object>
- </object>
- </object>
- <int key="IBDocument.localizationMode">0</int>
- <string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
- <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults">
- <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.macosx</string>
- <integer value="1060" key="NS.object.0"/>
- </object>
- <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
- <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3</string>
- <integer value="3000" key="NS.object.0"/>
- </object>
- <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
- <string key="IBDocument.LastKnownRelativeProjectPath">../../out/gyp/shapeops_demo.xcodeproj</string>
- <int key="IBDocument.defaultPropertyAccessControl">3</int>
- <object class="NSMutableDictionary" key="IBDocument.LastKnownImageSizes">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSArray" key="dict.sortedKeys">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <string>NSMenuCheckmark</string>
- <string>NSMenuMixedState</string>
- </object>
- <object class="NSMutableArray" key="dict.values">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <string>{9, 8}</string>
- <string>{7, 2}</string>
- </object>
- </object>
- </data>
-</archive>
diff --git a/experimental/Intersection/EdgeMain.cpp b/experimental/Intersection/EdgeMain.cpp
deleted file mode 100644
index 442c629c1a..0000000000
--- a/experimental/Intersection/EdgeMain.cpp
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "Intersection_Tests.h"
-
-int main(int /*argc*/, char** /*argv*/) {
- Intersection_Tests();
- return 0;
-}
diff --git a/experimental/Intersection/EdgeWalker.cpp b/experimental/Intersection/EdgeWalker.cpp
deleted file mode 100644
index be3f57fcdb..0000000000
--- a/experimental/Intersection/EdgeWalker.cpp
+++ /dev/null
@@ -1,2705 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "Simplify.h"
-
-#undef SkASSERT
-#define SkASSERT(cond) while (!(cond)) { sk_throw(); }
-
-// FIXME: remove once debugging is complete
-#if 01 // set to 1 for no debugging whatsoever
-
-//const bool gRunTestsInOneThread = false;
-
-#define DEBUG_ACTIVE_LESS_THAN 0
-#define DEBUG_ADD 0
-#define DEBUG_ADD_BOTTOM_TS 0
-#define DEBUG_ADD_INTERSECTING_TS 0
-#define DEBUG_ADJUST_COINCIDENT 0
-#define DEBUG_ASSEMBLE 0
-#define DEBUG_BOTTOM 0
-#define DEBUG_BRIDGE 0
-#define DEBUG_DUMP 0
-#define DEBUG_SORT_HORIZONTAL 0
-#define DEBUG_OUT 0
-#define DEBUG_OUT_LESS_THAN 0
-#define DEBUG_SPLIT 0
-#define DEBUG_STITCH_EDGE 0
-#define DEBUG_TRIM_LINE 0
-
-#else
-
-//const bool gRunTestsInOneThread = true;
-
-#define DEBUG_ACTIVE_LESS_THAN 0
-#define DEBUG_ADD 01
-#define DEBUG_ADD_BOTTOM_TS 0
-#define DEBUG_ADD_INTERSECTING_TS 0
-#define DEBUG_ADJUST_COINCIDENT 1
-#define DEBUG_ASSEMBLE 1
-#define DEBUG_BOTTOM 0
-#define DEBUG_BRIDGE 1
-#define DEBUG_DUMP 1
-#define DEBUG_SORT_HORIZONTAL 01
-#define DEBUG_OUT 01
-#define DEBUG_OUT_LESS_THAN 0
-#define DEBUG_SPLIT 1
-#define DEBUG_STITCH_EDGE 1
-#define DEBUG_TRIM_LINE 1
-
-#endif
-
-#if DEBUG_ASSEMBLE || DEBUG_BRIDGE
-static const char* kLVerbStr[] = {"", "line", "quad", "cubic"};
-#endif
-#if DEBUG_STITCH_EDGE
-static const char* kUVerbStr[] = {"", "Line", "Quad", "Cubic"};
-#endif
-
-static int LineIntersect(const SkPoint a[2], const SkPoint b[2],
- Intersections& intersections) {
- const _Line aLine = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}};
- const _Line bLine = {{b[0].fX, b[0].fY}, {b[1].fX, b[1].fY}};
- return intersect(aLine, bLine, intersections);
-}
-
-static int QuadLineIntersect(const SkPoint a[3], const SkPoint b[2],
- Intersections& intersections) {
- const Quadratic aQuad = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY}};
- const _Line bLine = {{b[0].fX, b[0].fY}, {b[1].fX, b[1].fY}};
- intersect(aQuad, bLine, intersections);
- return intersections.fUsed;
-}
-
-static int CubicLineIntersect(const SkPoint a[2], const SkPoint b[3],
- Intersections& intersections) {
- const Cubic aCubic = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY},
- {a[3].fX, a[3].fY}};
- const _Line bLine = {{b[0].fX, b[0].fY}, {b[1].fX, b[1].fY}};
- return intersect(aCubic, bLine, intersections);
-}
-
-static int QuadIntersect(const SkPoint a[3], const SkPoint b[3],
- Intersections& intersections) {
- const Quadratic aQuad = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY}};
- const Quadratic bQuad = {{b[0].fX, b[0].fY}, {b[1].fX, b[1].fY}, {b[2].fX, b[2].fY}};
- intersect2(aQuad, bQuad, intersections);
- return intersections.fUsed;
-}
-
-static int CubicIntersect(const SkPoint a[4], const SkPoint b[4],
- Intersections& intersections) {
- const Cubic aCubic = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY},
- {a[3].fX, a[3].fY}};
- const Cubic bCubic = {{b[0].fX, b[0].fY}, {b[1].fX, b[1].fY}, {b[2].fX, b[2].fY},
- {b[3].fX, b[3].fY}};
- intersect(aCubic, bCubic, intersections);
- return intersections.fUsed;
-}
-
-static int LineIntersect(const SkPoint a[2], SkScalar left, SkScalar right,
- SkScalar y, double aRange[2]) {
- const _Line aLine = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}};
- return horizontalLineIntersect(aLine, left, right, y, aRange);
-}
-
-static int QuadIntersect(const SkPoint a[3], SkScalar left, SkScalar right,
- SkScalar y, double aRange[3]) {
- const Quadratic aQuad = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY}};
- return horizontalIntersect(aQuad, left, right, y, aRange);
-}
-
-static int CubicIntersect(const SkPoint a[4], SkScalar left, SkScalar right,
- SkScalar y, double aRange[4]) {
- const Cubic aCubic = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY},
- {a[3].fX, a[3].fY}};
- return horizontalIntersect(aCubic, left, right, y, aRange);
-}
-
-static void LineXYAtT(const SkPoint a[2], double t, SkPoint* out) {
- const _Line line = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}};
- double x, y;
- xy_at_t(line, t, x, y);
- out->fX = SkDoubleToScalar(x);
- out->fY = SkDoubleToScalar(y);
-}
-
-static void QuadXYAtT(const SkPoint a[3], double t, SkPoint* out) {
- const Quadratic quad = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY}};
- double x, y;
- xy_at_t(quad, t, x, y);
- out->fX = SkDoubleToScalar(x);
- out->fY = SkDoubleToScalar(y);
-}
-
-static void CubicXYAtT(const SkPoint a[4], double t, SkPoint* out) {
- const Cubic cubic = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY},
- {a[3].fX, a[3].fY}};
- double x, y;
- xy_at_t(cubic, t, x, y);
- out->fX = SkDoubleToScalar(x);
- out->fY = SkDoubleToScalar(y);
-}
-
-static SkScalar LineYAtT(const SkPoint a[2], double t) {
- const _Line aLine = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}};
- double y;
- xy_at_t(aLine, t, *(double*) 0, y);
- return SkDoubleToScalar(y);
-}
-
-static SkScalar QuadYAtT(const SkPoint a[3], double t) {
- const Quadratic quad = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY}};
- double y;
- xy_at_t(quad, t, *(double*) 0, y);
- return SkDoubleToScalar(y);
-}
-
-static SkScalar CubicYAtT(const SkPoint a[4], double t) {
- const Cubic cubic = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}, {a[2].fX, a[2].fY},
- {a[3].fX, a[3].fY}};
- double y;
- xy_at_t(cubic, t, *(double*) 0, y);
- return SkDoubleToScalar(y);
-}
-
-static void LineSubDivide(const SkPoint a[2], double startT, double endT,
- SkPoint sub[2]) {
- const _Line aLine = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}};
- _Line dst;
- sub_divide(aLine, startT, endT, dst);
- sub[0].fX = SkDoubleToScalar(dst[0].x);
- sub[0].fY = SkDoubleToScalar(dst[0].y);
- sub[1].fX = SkDoubleToScalar(dst[1].x);
- sub[1].fY = SkDoubleToScalar(dst[1].y);
-}
-
-static void QuadSubDivide(const SkPoint a[3], double startT, double endT,
- SkPoint sub[3]) {
- const Quadratic aQuad = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY},
- {a[2].fX, a[2].fY}};
- Quadratic dst;
- sub_divide(aQuad, startT, endT, dst);
- sub[0].fX = SkDoubleToScalar(dst[0].x);
- sub[0].fY = SkDoubleToScalar(dst[0].y);
- sub[1].fX = SkDoubleToScalar(dst[1].x);
- sub[1].fY = SkDoubleToScalar(dst[1].y);
- sub[2].fX = SkDoubleToScalar(dst[2].x);
- sub[2].fY = SkDoubleToScalar(dst[2].y);
-}
-
-static void CubicSubDivide(const SkPoint a[4], double startT, double endT,
- SkPoint sub[4]) {
- const Cubic aCubic = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY},
- {a[2].fX, a[2].fY}, {a[3].fX, a[3].fY}};
- Cubic dst;
- sub_divide(aCubic, startT, endT, dst);
- sub[0].fX = SkDoubleToScalar(dst[0].x);
- sub[0].fY = SkDoubleToScalar(dst[0].y);
- sub[1].fX = SkDoubleToScalar(dst[1].x);
- sub[1].fY = SkDoubleToScalar(dst[1].y);
- sub[2].fX = SkDoubleToScalar(dst[2].x);
- sub[2].fY = SkDoubleToScalar(dst[2].y);
- sub[3].fX = SkDoubleToScalar(dst[3].x);
- sub[3].fY = SkDoubleToScalar(dst[3].y);
-}
-
-static void QuadSubBounds(const SkPoint a[3], double startT, double endT,
- SkRect& bounds) {
- SkPoint dst[3];
- QuadSubDivide(a, startT, endT, dst);
- bounds.fLeft = bounds.fRight = dst[0].fX;
- bounds.fTop = bounds.fBottom = dst[0].fY;
- for (int index = 1; index < 3; ++index) {
- bounds.growToInclude(dst[index].fX, dst[index].fY);
- }
-}
-
-static void CubicSubBounds(const SkPoint a[4], double startT, double endT,
- SkRect& bounds) {
- SkPoint dst[4];
- CubicSubDivide(a, startT, endT, dst);
- bounds.fLeft = bounds.fRight = dst[0].fX;
- bounds.fTop = bounds.fBottom = dst[0].fY;
- for (int index = 1; index < 4; ++index) {
- bounds.growToInclude(dst[index].fX, dst[index].fY);
- }
-}
-
-static SkPath::Verb QuadReduceOrder(SkPoint a[4]) {
- const Quadratic aQuad = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY},
- {a[2].fX, a[2].fY}};
- Quadratic dst;
- int order = reduceOrder(aQuad, dst, kReduceOrder_TreatAsFill);
- for (int index = 0; index < order; ++index) {
- a[index].fX = SkDoubleToScalar(dst[index].x);
- a[index].fY = SkDoubleToScalar(dst[index].y);
- }
- if (order == 1) { // FIXME: allow returning points, caller should discard
- a[1] = a[0];
- return (SkPath::Verb) order;
- }
- return (SkPath::Verb) (order - 1);
-}
-
-static SkPath::Verb CubicReduceOrder(SkPoint a[4]) {
- const Cubic aCubic = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY},
- {a[2].fX, a[2].fY}, {a[3].fX, a[3].fY}};
- Cubic dst;
- int order = reduceOrder(aCubic, dst, kReduceOrder_QuadraticsAllowed, kReduceOrder_TreatAsFill);
- for (int index = 0; index < order; ++index) {
- a[index].fX = SkDoubleToScalar(dst[index].x);
- a[index].fY = SkDoubleToScalar(dst[index].y);
- }
- if (order == 1) { // FIXME: allow returning points, caller should discard
- a[1] = a[0];
- return (SkPath::Verb) order;
- }
- return (SkPath::Verb) (order - 1);
-}
-
-static bool IsCoincident(const SkPoint a[2], const SkPoint& above,
- const SkPoint& below) {
- const _Line aLine = {{a[0].fX, a[0].fY}, {a[1].fX, a[1].fY}};
- const _Line bLine = {{above.fX, above.fY}, {below.fX, below.fY}};
- return implicit_matches_ulps(aLine, bLine, 32);
-}
-
-/*
-list of edges
-bounds for edge
-sort
-active T
-
-if a contour's bounds is outside of the active area, no need to create edges
-*/
-
-/* given one or more paths,
- find the bounds of each contour, select the active contours
- for each active contour, compute a set of edges
- each edge corresponds to one or more lines and curves
- leave edges unbroken as long as possible
- when breaking edges, compute the t at the break but leave the control points alone
-
- */
-
-void contourBounds(const SkPath& path, SkTDArray<SkRect>& boundsArray) {
- SkPath::Iter iter(path, false);
- SkPoint pts[4];
- SkPath::Verb verb;
- SkRect bounds;
- bounds.setEmpty();
- int count = 0;
- while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
- switch (verb) {
- case SkPath::kMove_Verb:
- if (!bounds.isEmpty()) {
- *boundsArray.append() = bounds;
- }
- bounds.set(pts[0].fX, pts[0].fY, pts[0].fX, pts[0].fY);
- count = 0;
- break;
- case SkPath::kLine_Verb:
- count = 1;
- break;
- case SkPath::kQuad_Verb:
- count = 2;
- break;
- case SkPath::kCubic_Verb:
- count = 3;
- break;
- case SkPath::kClose_Verb:
- count = 0;
- break;
- default:
- SkDEBUGFAIL("bad verb");
- return;
- }
- for (int i = 1; i <= count; ++i) {
- bounds.growToInclude(pts[i].fX, pts[i].fY);
- }
- }
-}
-
-static bool extendLine(const SkPoint line[2], const SkPoint& add) {
- // FIXME: allow this to extend lines that have slopes that are nearly equal
- SkScalar dx1 = line[1].fX - line[0].fX;
- SkScalar dy1 = line[1].fY - line[0].fY;
- SkScalar dx2 = add.fX - line[0].fX;
- SkScalar dy2 = add.fY - line[0].fY;
- return dx1 * dy2 == dx2 * dy1;
-}
-
-// OPTIMIZATION: this should point to a list of input data rather than duplicating
-// the line data here. This would reduce the need to assemble the results.
-struct OutEdge {
- bool operator<(const OutEdge& rh) const {
- const SkPoint& first = fPts[0];
- const SkPoint& rhFirst = rh.fPts[0];
- return first.fY == rhFirst.fY
- ? first.fX < rhFirst.fX
- : first.fY < rhFirst.fY;
- }
-
- SkPoint fPts[4];
- int fID; // id of edge generating data
- uint8_t fVerb; // FIXME: not read from everywhere
- bool fCloseCall; // edge is trimmable if not originally coincident
-};
-
-class OutEdgeBuilder {
-public:
- OutEdgeBuilder(bool fill)
- : fFill(fill) {
- }
-
- void addCurve(const SkPoint line[4], SkPath::Verb verb, int id,
- bool closeCall) {
- OutEdge& newEdge = fEdges.push_back();
- memcpy(newEdge.fPts, line, (verb + 1) * sizeof(SkPoint));
- newEdge.fVerb = verb;
- newEdge.fID = id;
- newEdge.fCloseCall = closeCall;
- }
-
- bool trimLine(SkScalar y, int id) {
- size_t count = fEdges.count();
- while (count-- != 0) {
- OutEdge& edge = fEdges[count];
- if (edge.fID != id) {
- continue;
- }
- if (edge.fCloseCall) {
- return false;
- }
- SkASSERT(edge.fPts[0].fY <= y);
- if (edge.fPts[1].fY <= y) {
- continue;
- }
- edge.fPts[1].fX = edge.fPts[0].fX + (y - edge.fPts[0].fY)
- * (edge.fPts[1].fX - edge.fPts[0].fX)
- / (edge.fPts[1].fY - edge.fPts[0].fY);
- edge.fPts[1].fY = y;
-#if DEBUG_TRIM_LINE
- SkDebugf("%s edge=%d %1.9g,%1.9g\n", __FUNCTION__, id,
- edge.fPts[1].fX, y);
-#endif
- return true;
- }
- return false;
- }
-
- void assemble(SkPath& simple) {
- size_t listCount = fEdges.count();
- if (listCount == 0) {
- return;
- }
- do {
- size_t listIndex = 0;
- int advance = 1;
- while (listIndex < listCount && fTops[listIndex] == 0) {
- ++listIndex;
- }
- if (listIndex >= listCount) {
- break;
- }
- int closeEdgeIndex = -listIndex - 1;
- // the curve is deferred and not added right away because the
- // following edge may extend the first curve.
- SkPoint firstPt, lastCurve[4];
- uint8_t lastVerb;
-#if DEBUG_ASSEMBLE
- int firstIndex, lastIndex;
- const int tab = 8;
-#endif
- bool doMove = true;
- int edgeIndex;
- do {
- SkPoint* ptArray = fEdges[listIndex].fPts;
- uint8_t verb = fEdges[listIndex].fVerb;
- SkPoint* curve[4];
- if (advance < 0) {
- curve[0] = &ptArray[verb];
- if (verb == SkPath::kCubic_Verb) {
- curve[1] = &ptArray[2];
- curve[2] = &ptArray[1];
- }
- curve[verb] = &ptArray[0];
- } else {
- curve[0] = &ptArray[0];
- if (verb == SkPath::kCubic_Verb) {
- curve[1] = &ptArray[1];
- curve[2] = &ptArray[2];
- }
- curve[verb] = &ptArray[verb];
- }
- if (verb == SkPath::kQuad_Verb) {
- curve[1] = &ptArray[1];
- }
- if (doMove) {
- firstPt = *curve[0];
- simple.moveTo(curve[0]->fX, curve[0]->fY);
-#if DEBUG_ASSEMBLE
- SkDebugf("%s %d moveTo (%g,%g)\n", __FUNCTION__,
- listIndex + 1, curve[0]->fX, curve[0]->fY);
- firstIndex = listIndex;
-#endif
- for (int index = 0; index <= verb; ++index) {
- lastCurve[index] = *curve[index];
- }
- doMove = false;
- } else {
- bool gap = lastCurve[lastVerb] != *curve[0];
- if (gap || lastVerb != SkPath::kLine_Verb) { // output the accumulated curve before the gap
- // FIXME: see comment in bridge -- this probably
- // conceals errors
- SkASSERT(fFill && UlpsDiff(lastCurve[lastVerb].fY,
- curve[0]->fY) <= 10);
- switch (lastVerb) {
- case SkPath::kLine_Verb:
- simple.lineTo(lastCurve[1].fX, lastCurve[1].fY);
- break;
- case SkPath::kQuad_Verb:
- simple.quadTo(lastCurve[1].fX, lastCurve[1].fY,
- lastCurve[2].fX, lastCurve[2].fY);
- break;
- case SkPath::kCubic_Verb:
- simple.cubicTo(lastCurve[1].fX, lastCurve[1].fY,
- lastCurve[2].fX, lastCurve[2].fY,
- lastCurve[3].fX, lastCurve[3].fY);
- break;
- }
-#if DEBUG_ASSEMBLE
- SkDebugf("%*s %d %sTo (%g,%g)\n", tab, "", lastIndex + 1,
- kLVerbStr[lastVerb], lastCurve[lastVerb].fX,
- lastCurve[lastVerb].fY);
-#endif
- }
- int firstCopy = 1;
- if (gap || (lastVerb == SkPath::kLine_Verb
- && (verb != SkPath::kLine_Verb
- || !extendLine(lastCurve, *curve[verb])))) {
- // FIXME: see comment in bridge -- this probably
- // conceals errors
- SkASSERT(lastCurve[lastVerb] == *curve[0] ||
- (fFill && UlpsDiff(lastCurve[lastVerb].fY,
- curve[0]->fY) <= 10));
- simple.lineTo(curve[0]->fX, curve[0]->fY);
-#if DEBUG_ASSEMBLE
- SkDebugf("%*s %d gap lineTo (%g,%g)\n", tab, "",
- lastIndex + 1, curve[0]->fX, curve[0]->fY);
-#endif
- firstCopy = 0;
- } else if (lastVerb != SkPath::kLine_Verb) {
- firstCopy = 0;
- }
- for (int index = firstCopy; index <= verb; ++index) {
- lastCurve[index] = *curve[index];
- }
- }
- lastVerb = verb;
-#if DEBUG_ASSEMBLE
- lastIndex = listIndex;
-#endif
- if (advance < 0) {
- edgeIndex = fTops[listIndex];
- fTops[listIndex] = 0;
- } else {
- edgeIndex = fBottoms[listIndex];
- fBottoms[listIndex] = 0;
- }
- if (edgeIndex) {
- listIndex = abs(edgeIndex) - 1;
- if (edgeIndex < 0) {
- fTops[listIndex] = 0;
- } else {
- fBottoms[listIndex] = 0;
- }
- }
- if (edgeIndex == closeEdgeIndex || edgeIndex == 0) {
- switch (lastVerb) {
- case SkPath::kLine_Verb:
- simple.lineTo(lastCurve[1].fX, lastCurve[1].fY);
- break;
- case SkPath::kQuad_Verb:
- simple.quadTo(lastCurve[1].fX, lastCurve[1].fY,
- lastCurve[2].fX, lastCurve[2].fY);
- break;
- case SkPath::kCubic_Verb:
- simple.cubicTo(lastCurve[1].fX, lastCurve[1].fY,
- lastCurve[2].fX, lastCurve[2].fY,
- lastCurve[3].fX, lastCurve[3].fY);
- break;
- }
-#if DEBUG_ASSEMBLE
- SkDebugf("%*s %d %sTo last (%g, %g)\n", tab, "",
- lastIndex + 1, kLVerbStr[lastVerb],
- lastCurve[lastVerb].fX, lastCurve[lastVerb].fY);
-#endif
- if (lastCurve[lastVerb] != firstPt) {
- simple.lineTo(firstPt.fX, firstPt.fY);
-#if DEBUG_ASSEMBLE
- SkDebugf("%*s %d final line (%g, %g)\n", tab, "",
- firstIndex + 1, firstPt.fX, firstPt.fY);
-#endif
- }
- simple.close();
-#if DEBUG_ASSEMBLE
- SkDebugf("%*s close\n", tab, "");
-#endif
- break;
- }
- // if this and next edge go different directions
-#if DEBUG_ASSEMBLE
- SkDebugf("%*s advance=%d edgeIndex=%d flip=%s\n", tab, "",
- advance, edgeIndex, advance > 0 ^ edgeIndex < 0 ?
- "true" : "false");
-#endif
- if (advance > 0 ^ edgeIndex < 0) {
- advance = -advance;
- }
- } while (edgeIndex);
- } while (true);
- }
-
- // sort points by y, then x
- // if x/y is identical, sort bottoms before tops
- // if identical and both tops/bottoms, sort by angle
- static bool lessThan(SkTArray<OutEdge>& edges, const int one,
- const int two) {
- const OutEdge& oneEdge = edges[abs(one) - 1];
- int oneIndex = one < 0 ? 0 : oneEdge.fVerb;
- const SkPoint& startPt1 = oneEdge.fPts[oneIndex];
- const OutEdge& twoEdge = edges[abs(two) - 1];
- int twoIndex = two < 0 ? 0 : twoEdge.fVerb;
- const SkPoint& startPt2 = twoEdge.fPts[twoIndex];
- if (startPt1.fY != startPt2.fY) {
- #if DEBUG_OUT_LESS_THAN
- SkDebugf("%s %d<%d (%g,%g) %s startPt1.fY < startPt2.fY\n", __FUNCTION__,
- one, two, startPt1.fY, startPt2.fY,
- startPt1.fY < startPt2.fY ? "true" : "false");
- #endif
- return startPt1.fY < startPt2.fY;
- }
- if (startPt1.fX != startPt2.fX) {
- #if DEBUG_OUT_LESS_THAN
- SkDebugf("%s %d<%d (%g,%g) %s startPt1.fX < startPt2.fX\n", __FUNCTION__,
- one, two, startPt1.fX, startPt2.fX,
- startPt1.fX < startPt2.fX ? "true" : "false");
- #endif
- return startPt1.fX < startPt2.fX;
- }
- const SkPoint& endPt1 = oneEdge.fPts[oneIndex ^ oneEdge.fVerb];
- const SkPoint& endPt2 = twoEdge.fPts[twoIndex ^ twoEdge.fVerb];
- SkScalar dy1 = startPt1.fY - endPt1.fY;
- SkScalar dy2 = startPt2.fY - endPt2.fY;
- SkScalar dy1y2 = dy1 * dy2;
- if (dy1y2 < 0) { // different signs
- #if DEBUG_OUT_LESS_THAN
- SkDebugf("%s %d<%d %s dy1 > 0\n", __FUNCTION__, one, two,
- dy1 > 0 ? "true" : "false");
- #endif
- return dy1 > 0; // one < two if one goes up and two goes down
- }
- if (dy1y2 == 0) {
- #if DEBUG_OUT_LESS_THAN
- SkDebugf("%s %d<%d %s endPt1.fX < endPt2.fX\n", __FUNCTION__,
- one, two, endPt1.fX < endPt2.fX ? "true" : "false");
- #endif
- return endPt1.fX < endPt2.fX;
- }
- SkScalar dx1y2 = (startPt1.fX - endPt1.fX) * dy2;
- SkScalar dx2y1 = (startPt2.fX - endPt2.fX) * dy1;
- #if DEBUG_OUT_LESS_THAN
- SkDebugf("%s %d<%d %s dy2 < 0 ^ dx1y2 < dx2y1\n", __FUNCTION__,
- one, two, dy2 < 0 ^ dx1y2 < dx2y1 ? "true" : "false");
- #endif
- return dy2 > 0 ^ dx1y2 < dx2y1;
- }
-
- // Sort the indices of paired points and then create more indices so
- // assemble() can find the next edge and connect the top or bottom
- void bridge() {
- size_t index;
- size_t count = fEdges.count();
- if (!count) {
- return;
- }
- SkASSERT(!fFill || count > 1);
- fTops.setCount(count);
- sk_bzero(fTops.begin(), sizeof(fTops[0]) * count);
- fBottoms.setCount(count);
- sk_bzero(fBottoms.begin(), sizeof(fBottoms[0]) * count);
- SkTDArray<int> order;
- for (index = 1; index <= count; ++index) {
- *order.append() = -index;
- }
- for (index = 1; index <= count; ++index) {
- *order.append() = index;
- }
- QSort<SkTArray<OutEdge>, int>(fEdges, order.begin(), order.end() - 1, lessThan);
- int* lastPtr = order.end() - 1;
- int* leftPtr = order.begin();
- while (leftPtr < lastPtr) {
- int leftIndex = *leftPtr;
- int leftOutIndex = abs(leftIndex) - 1;
- const OutEdge& left = fEdges[leftOutIndex];
- int* rightPtr = leftPtr + 1;
- int rightIndex = *rightPtr;
- int rightOutIndex = abs(rightIndex) - 1;
- const OutEdge& right = fEdges[rightOutIndex];
- bool pairUp = fFill;
- if (!pairUp) {
- const SkPoint& leftMatch =
- left.fPts[leftIndex < 0 ? 0 : left.fVerb];
- const SkPoint& rightMatch =
- right.fPts[rightIndex < 0 ? 0 : right.fVerb];
- pairUp = leftMatch == rightMatch;
- } else {
- #if DEBUG_OUT
- // FIXME : not happy that error in low bit is allowed
- // this probably conceals error elsewhere
- if (UlpsDiff(left.fPts[leftIndex < 0 ? 0 : left.fVerb].fY,
- right.fPts[rightIndex < 0 ? 0 : right.fVerb].fY) > 1) {
- *fMismatches.append() = leftIndex;
- if (rightPtr == lastPtr) {
- *fMismatches.append() = rightIndex;
- }
- pairUp = false;
- }
- #else
- SkASSERT(UlpsDiff(left.fPts[leftIndex < 0 ? 0 : left.fVerb].fY,
- right.fPts[rightIndex < 0 ? 0 : right.fVerb].fY) <= 10);
- #endif
- }
- if (pairUp) {
- if (leftIndex < 0) {
- fTops[leftOutIndex] = rightIndex;
- } else {
- fBottoms[leftOutIndex] = rightIndex;
- }
- if (rightIndex < 0) {
- fTops[rightOutIndex] = leftIndex;
- } else {
- fBottoms[rightOutIndex] = leftIndex;
- }
- ++rightPtr;
- }
- leftPtr = rightPtr;
- }
-#if DEBUG_OUT
- int* mismatch = fMismatches.begin();
- while (mismatch != fMismatches.end()) {
- int leftIndex = *mismatch++;
- int leftOutIndex = abs(leftIndex) - 1;
- const OutEdge& left = fEdges[leftOutIndex];
- const SkPoint& leftPt = left.fPts[leftIndex < 0 ? 0 : left.fVerb];
- SkDebugf("%s left=%d %s (%1.9g,%1.9g)\n",
- __FUNCTION__, left.fID, leftIndex < 0 ? "top" : "bot",
- leftPt.fX, leftPt.fY);
- }
- SkASSERT(fMismatches.count() == 0);
-#endif
-#if DEBUG_BRIDGE
- for (index = 0; index < count; ++index) {
- const OutEdge& edge = fEdges[index];
- uint8_t verb = edge.fVerb;
- SkDebugf("%s %d edge=%d %s (%1.9g,%1.9g) (%1.9g,%1.9g)\n",
- index == 0 ? __FUNCTION__ : " ",
- index + 1, edge.fID, kLVerbStr[verb], edge.fPts[0].fX,
- edge.fPts[0].fY, edge.fPts[verb].fX, edge.fPts[verb].fY);
- }
- for (index = 0; index < count; ++index) {
- SkDebugf(" top of % 2d connects to %s of % 2d\n", index + 1,
- fTops[index] < 0 ? "top " : "bottom", abs(fTops[index]));
- SkDebugf(" bottom of % 2d connects to %s of % 2d\n", index + 1,
- fBottoms[index] < 0 ? "top " : "bottom", abs(fBottoms[index]));
- }
-#endif
- }
-
-protected:
- SkTArray<OutEdge> fEdges;
- SkTDArray<int> fTops;
- SkTDArray<int> fBottoms;
- bool fFill;
-#if DEBUG_OUT
- SkTDArray<int> fMismatches;
-#endif
-};
-
-// Bounds, unlike Rect, does not consider a vertical line to be empty.
-struct Bounds : public SkRect {
- static bool Intersects(const Bounds& a, const Bounds& b) {
- return a.fLeft <= b.fRight && b.fLeft <= a.fRight &&
- a.fTop <= b.fBottom && b.fTop <= a.fBottom;
- }
-
- bool isEmpty() {
- return fLeft > fRight || fTop > fBottom
- || (fLeft == fRight && fTop == fBottom)
- || isnan(fLeft) || isnan(fRight)
- || isnan(fTop) || isnan(fBottom);
- }
-};
-
-class Intercepts {
-public:
- Intercepts()
- : fTopIntercepts(0)
- , fBottomIntercepts(0)
- , fExplicit(false) {
- }
-
- Intercepts& operator=(const Intercepts& src) {
- fTs = src.fTs;
- fTopIntercepts = src.fTopIntercepts;
- fBottomIntercepts = src.fBottomIntercepts;
- return *this;
- }
-
- // OPTIMIZATION: remove this function if it's never called
- double t(int tIndex) const {
- if (tIndex == 0) {
- return 0;
- }
- if (tIndex > fTs.count()) {
- return 1;
- }
- return fTs[tIndex - 1];
- }
-
-#if DEBUG_DUMP
- void dump(const SkPoint* pts, SkPath::Verb verb) {
- const char className[] = "Intercepts";
- const int tab = 8;
- for (int i = 0; i < fTs.count(); ++i) {
- SkPoint out;
- switch (verb) {
- case SkPath::kLine_Verb:
- LineXYAtT(pts, fTs[i], &out);
- break;
- case SkPath::kQuad_Verb:
- QuadXYAtT(pts, fTs[i], &out);
- break;
- case SkPath::kCubic_Verb:
- CubicXYAtT(pts, fTs[i], &out);
- break;
- default:
- SkASSERT(0);
- }
- SkDebugf("%*s.fTs[%d]=%1.9g (%1.9g,%1.9g)\n", tab + sizeof(className),
- className, i, fTs[i], out.fX, out.fY);
- }
- SkDebugf("%*s.fTopIntercepts=%u\n", tab + sizeof(className),
- className, fTopIntercepts);
- SkDebugf("%*s.fBottomIntercepts=%u\n", tab + sizeof(className),
- className, fBottomIntercepts);
- SkDebugf("%*s.fExplicit=%d\n", tab + sizeof(className),
- className, fExplicit);
- }
-#endif
-
- SkTDArray<double> fTs;
- unsigned char fTopIntercepts; // 0=init state 1=1 edge >1=multiple edges
- unsigned char fBottomIntercepts;
- bool fExplicit; // if set, suppress 0 and 1
-
-};
-
-struct HorizontalEdge {
- bool operator<(const HorizontalEdge& rh) const {
- return fY == rh.fY ? fLeft == rh.fLeft ? fRight < rh.fRight
- : fLeft < rh.fLeft : fY < rh.fY;
- }
-
-#if DEBUG_DUMP
- void dump() {
- const char className[] = "HorizontalEdge";
- const int tab = 4;
- SkDebugf("%*s.fLeft=%1.9g\n", tab + sizeof(className), className, fLeft);
- SkDebugf("%*s.fRight=%1.9g\n", tab + sizeof(className), className, fRight);
- SkDebugf("%*s.fY=%1.9g\n", tab + sizeof(className), className, fY);
- }
-#endif
-
- SkScalar fLeft;
- SkScalar fRight;
- SkScalar fY;
-};
-
-struct InEdge {
- bool operator<(const InEdge& rh) const {
- return fBounds.fTop == rh.fBounds.fTop
- ? fBounds.fLeft < rh.fBounds.fLeft
- : fBounds.fTop < rh.fBounds.fTop;
- }
-
- // Avoid collapsing t values that are close to the same since
- // we walk ts to describe consecutive intersections. Since a pair of ts can
- // be nearly equal, any problems caused by this should be taken care
- // of later.
- int add(double* ts, size_t count, ptrdiff_t verbIndex) {
- // FIXME: in the pathological case where there is a ton of intercepts, binary search?
- bool foundIntercept = false;
- int insertedAt = -1;
- Intercepts& intercepts = fIntercepts[verbIndex];
- for (size_t index = 0; index < count; ++index) {
- double t = ts[index];
- if (t <= 0) {
- intercepts.fTopIntercepts <<= 1;
- fContainsIntercepts |= ++intercepts.fTopIntercepts > 1;
- continue;
- }
- if (t >= 1) {
- intercepts.fBottomIntercepts <<= 1;
- fContainsIntercepts |= ++intercepts.fBottomIntercepts > 1;
- continue;
- }
- fIntersected = true;
- foundIntercept = true;
- size_t tCount = intercepts.fTs.count();
- double delta;
- for (size_t idx2 = 0; idx2 < tCount; ++idx2) {
- if (t <= intercepts.fTs[idx2]) {
- // FIXME: ? if (t < intercepts.fTs[idx2]) // failed
- delta = intercepts.fTs[idx2] - t;
- if (delta > 0) {
- insertedAt = idx2;
- *intercepts.fTs.insert(idx2) = t;
- }
- goto nextPt;
- }
- }
- if (tCount == 0 || (delta = t - intercepts.fTs[tCount - 1]) > 0) {
- insertedAt = tCount;
- *intercepts.fTs.append() = t;
- }
- nextPt:
- ;
- }
- fContainsIntercepts |= foundIntercept;
- return insertedAt;
- }
-
- void addPartial(SkTArray<InEdge>& edges, int ptStart, int ptEnd,
- int verbStart, int verbEnd) {
- InEdge* edge = edges.push_back_n(1);
- int verbCount = verbEnd - verbStart;
- edge->fIntercepts.push_back_n(verbCount);
- // uint8_t* verbs = &fVerbs[verbStart];
- for (int ceptIdx = 0; ceptIdx < verbCount; ++ceptIdx) {
- edge->fIntercepts[ceptIdx] = fIntercepts[verbStart + ceptIdx];
- }
- edge->fPts.append(ptEnd - ptStart, &fPts[ptStart]);
- edge->fVerbs.append(verbCount, &fVerbs[verbStart]);
- edge->setBounds();
- edge->fWinding = fWinding;
- edge->fContainsIntercepts = fContainsIntercepts; // FIXME: may not be correct -- but do we need to know?
- }
-
- void addSplit(SkTArray<InEdge>& edges, SkPoint* pts, uint8_t verb,
- Intercepts& intercepts, int firstT, int lastT, bool flipped) {
- InEdge* edge = edges.push_back_n(1);
- edge->fIntercepts.push_back_n(1);
- if (firstT == 0) {
- *edge->fIntercepts[0].fTs.append() = 0;
- } else {
- *edge->fIntercepts[0].fTs.append() = intercepts.fTs[firstT - 1];
- }
- bool add1 = lastT == intercepts.fTs.count();
- edge->fIntercepts[0].fTs.append(lastT - firstT, &intercepts.fTs[firstT]);
- if (add1) {
- *edge->fIntercepts[0].fTs.append() = 1;
- }
- edge->fIntercepts[0].fExplicit = true;
- edge->fPts.append(verb + 1, pts);
- edge->fVerbs.append(1, &verb);
- // FIXME: bounds could be better for partial Ts
- edge->setSubBounds();
- edge->fContainsIntercepts = fContainsIntercepts; // FIXME: may not be correct -- but do we need to know?
- if (flipped) {
- edge->flipTs();
- edge->fWinding = -fWinding;
- } else {
- edge->fWinding = fWinding;
- }
- }
-
- bool cached(const InEdge* edge) {
- // FIXME: in the pathological case where there is a ton of edges, binary search?
- size_t count = fCached.count();
- for (size_t index = 0; index < count; ++index) {
- if (edge == fCached[index]) {
- return true;
- }
- if (edge < fCached[index]) {
- *fCached.insert(index) = edge;
- return false;
- }
- }
- *fCached.append() = edge;
- return false;
- }
-
- void complete(signed char winding) {
- setBounds();
- fIntercepts.push_back_n(fVerbs.count());
- if ((fWinding = winding) < 0) { // reverse verbs, pts, if bottom to top
- flip();
- }
- fContainsIntercepts = fIntersected = false;
- }
-
- void flip() {
- size_t index;
- size_t last = fPts.count() - 1;
- for (index = 0; index < last; ++index, --last) {
- SkTSwap<SkPoint>(fPts[index], fPts[last]);
- }
- last = fVerbs.count() - 1;
- for (index = 0; index < last; ++index, --last) {
- SkTSwap<uint8_t>(fVerbs[index], fVerbs[last]);
- }
- }
-
- void flipTs() {
- SkASSERT(fIntercepts.count() == 1);
- Intercepts& intercepts = fIntercepts[0];
- SkASSERT(intercepts.fExplicit);
- SkTDArray<double>& ts = intercepts.fTs;
- size_t index;
- size_t last = ts.count() - 1;
- for (index = 0; index < last; ++index, --last) {
- SkTSwap<double>(ts[index], ts[last]);
- }
- }
-
- void reset() {
- fCached.reset();
- fIntercepts.reset();
- fPts.reset();
- fVerbs.reset();
- fBounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, SK_ScalarMax);
- fWinding = 0;
- fContainsIntercepts = false;
- fIntersected = false;
- }
-
- void setBounds() {
- SkPoint* ptPtr = fPts.begin();
- SkPoint* ptLast = fPts.end();
- if (ptPtr == ptLast) {
- SkDebugf("%s empty edge\n", __FUNCTION__);
- SkASSERT(0);
- // FIXME: delete empty edge?
- return;
- }
- fBounds.set(ptPtr->fX, ptPtr->fY, ptPtr->fX, ptPtr->fY);
- ++ptPtr;
- while (ptPtr != ptLast) {
- fBounds.growToInclude(ptPtr->fX, ptPtr->fY);
- ++ptPtr;
- }
- }
-
- // recompute bounds based on subrange of T values
- void setSubBounds() {
- SkASSERT(fIntercepts.count() == 1);
- Intercepts& intercepts = fIntercepts[0];
- SkASSERT(intercepts.fExplicit);
- SkASSERT(fVerbs.count() == 1);
- SkTDArray<double>& ts = intercepts.fTs;
- if (fVerbs[0] == SkPath::kQuad_Verb) {
- SkASSERT(fPts.count() == 3);
- QuadSubBounds(fPts.begin(), ts[0], ts[ts.count() - 1], fBounds);
- } else {
- SkASSERT(fVerbs[0] == SkPath::kCubic_Verb);
- SkASSERT(fPts.count() == 4);
- CubicSubBounds(fPts.begin(), ts[0], ts[ts.count() - 1], fBounds);
- }
- }
-
- void splitInflectionPts(SkTArray<InEdge>& edges) {
- if (!fIntersected) {
- return;
- }
- uint8_t* verbs = fVerbs.begin();
- SkPoint* pts = fPts.begin();
- int lastVerb = 0;
- int lastPt = 0;
- uint8_t verb;
- bool edgeSplit = false;
- for (int ceptIdx = 0; ceptIdx < fIntercepts.count(); ++ceptIdx, pts += verb) {
- Intercepts& intercepts = fIntercepts[ceptIdx];
- verb = *verbs++;
- if (verb <= SkPath::kLine_Verb) {
- continue;
- }
- size_t tCount = intercepts.fTs.count();
- if (!tCount) {
- continue;
- }
- size_t tIndex = (size_t) -1;
- SkScalar y = pts[0].fY;
- int lastSplit = 0;
- int firstSplit = -1;
- bool curveSplit = false;
- while (++tIndex < tCount) {
- double nextT = intercepts.fTs[tIndex];
- SkScalar nextY = verb == SkPath::kQuad_Verb
- ? QuadYAtT(pts, nextT) : CubicYAtT(pts, nextT);
- if (nextY < y) {
- edgeSplit = curveSplit = true;
- if (firstSplit < 0) {
- firstSplit = tIndex;
- int nextPt = pts - fPts.begin();
- int nextVerb = verbs - 1 - fVerbs.begin();
- if (lastVerb < nextVerb) {
- addPartial(edges, lastPt, nextPt, lastVerb, nextVerb);
- #if DEBUG_SPLIT
- SkDebugf("%s addPartial 1\n", __FUNCTION__);
- #endif
- }
- lastPt = nextPt;
- lastVerb = nextVerb;
- }
- } else {
- if (firstSplit >= 0) {
- if (lastSplit < firstSplit) {
- addSplit(edges, pts, verb, intercepts,
- lastSplit, firstSplit, false);
- #if DEBUG_SPLIT
- SkDebugf("%s addSplit 1 tIndex=%d,%d\n",
- __FUNCTION__, lastSplit, firstSplit);
- #endif
- }
- addSplit(edges, pts, verb, intercepts,
- firstSplit, tIndex, true);
- #if DEBUG_SPLIT
- SkDebugf("%s addSplit 2 tIndex=%d,%d flip\n",
- __FUNCTION__, firstSplit, tIndex);
- #endif
- lastSplit = tIndex;
- firstSplit = -1;
- }
- }
- y = nextY;
- }
- if (curveSplit) {
- if (firstSplit < 0) {
- firstSplit = lastSplit;
- } else {
- addSplit(edges, pts, verb, intercepts, lastSplit,
- firstSplit, false);
- #if DEBUG_SPLIT
- SkDebugf("%s addSplit 3 tIndex=%d,%d\n", __FUNCTION__,
- lastSplit, firstSplit);
- #endif
- }
- addSplit(edges, pts, verb, intercepts, firstSplit,
- tIndex, pts[verb].fY < y);
- #if DEBUG_SPLIT
- SkDebugf("%s addSplit 4 tIndex=%d,%d %s\n", __FUNCTION__,
- firstSplit, tIndex, pts[verb].fY < y ? "flip" : "");
- #endif
- }
- }
- // collapse remainder -- if there's nothing left, clear it somehow?
- if (edgeSplit) {
- int nextVerb = verbs - 1 - fVerbs.begin();
- if (lastVerb < nextVerb) {
- int nextPt = pts - fPts.begin();
- addPartial(edges, lastPt, nextPt, lastVerb, nextVerb);
- #if DEBUG_SPLIT
- SkDebugf("%s addPartial 2\n", __FUNCTION__);
- #endif
- }
- // OPTIMIZATION: reuse the edge instead of marking it empty
- reset();
- }
- }
-
-#if DEBUG_DUMP
- void dump() {
- int i;
- const char className[] = "InEdge";
- const int tab = 4;
- SkDebugf("InEdge %p (edge=%d)\n", this, fID);
- for (i = 0; i < fCached.count(); ++i) {
- SkDebugf("%*s.fCached[%d]=0x%08x\n", tab + sizeof(className),
- className, i, fCached[i]);
- }
- uint8_t* verbs = fVerbs.begin();
- SkPoint* pts = fPts.begin();
- for (i = 0; i < fIntercepts.count(); ++i) {
- SkDebugf("%*s.fIntercepts[%d]:\n", tab + sizeof(className),
- className, i);
- fIntercepts[i].dump(pts, (SkPath::Verb) *verbs);
- pts += *verbs++;
- }
- for (i = 0; i < fPts.count(); ++i) {
- SkDebugf("%*s.fPts[%d]=(%1.9g,%1.9g)\n", tab + sizeof(className),
- className, i, fPts[i].fX, fPts[i].fY);
- }
- for (i = 0; i < fVerbs.count(); ++i) {
- SkDebugf("%*s.fVerbs[%d]=%d\n", tab + sizeof(className),
- className, i, fVerbs[i]);
- }
- SkDebugf("%*s.fBounds=(%1.9g, %1.9g, %1.9g, %1.9g)\n", tab + sizeof(className),
- className, fBounds.fLeft, fBounds.fTop,
- fBounds.fRight, fBounds.fBottom);
- SkDebugf("%*s.fWinding=%d\n", tab + sizeof(className), className,
- fWinding);
- SkDebugf("%*s.fContainsIntercepts=%d\n", tab + sizeof(className),
- className, fContainsIntercepts);
- SkDebugf("%*s.fIntersected=%d\n", tab + sizeof(className),
- className, fIntersected);
- }
-#endif
-
- // FIXME: temporary data : move this to a separate struct?
- SkTDArray<const InEdge*> fCached; // list of edges already intercepted
- SkTArray<Intercepts> fIntercepts; // one per verb
-
- // persistent data
- SkTDArray<SkPoint> fPts;
- SkTDArray<uint8_t> fVerbs;
- Bounds fBounds;
- int fID;
- signed char fWinding;
- bool fContainsIntercepts;
- bool fIntersected;
-};
-
-class InEdgeBuilder {
-public:
-
-InEdgeBuilder(const SkPath& path, bool ignoreHorizontal, SkTArray<InEdge>& edges,
- SkTDArray<HorizontalEdge>& horizontalEdges)
- : fPath(path)
- , fCurrentEdge(NULL)
- , fEdges(edges)
- , fHorizontalEdges(horizontalEdges)
- , fIgnoreHorizontal(ignoreHorizontal)
- , fContainsCurves(false)
-{
- walk();
-}
-
-bool containsCurves() const {
- return fContainsCurves;
-}
-
-protected:
-
-void addEdge() {
- SkASSERT(fCurrentEdge);
- fCurrentEdge->fPts.append(fPtCount - fPtOffset, &fPts[fPtOffset]);
- fPtOffset = 1;
- *fCurrentEdge->fVerbs.append() = fVerb;
-}
-
-bool complete() {
- if (fCurrentEdge && fCurrentEdge->fVerbs.count()) {
- fCurrentEdge->complete(fWinding);
- fCurrentEdge = NULL;
- return true;
- }
- return false;
-}
-
-int direction(SkPath::Verb verb) {
- fPtCount = verb + 1;
- if (fIgnoreHorizontal && isHorizontal()) {
- return 0;
- }
- return fPts[0].fY == fPts[verb].fY
- ? fPts[0].fX == fPts[verb].fX ? 0 : fPts[0].fX < fPts[verb].fX
- ? 1 : -1 : fPts[0].fY < fPts[verb].fY ? 1 : -1;
-}
-
-bool isHorizontal() {
- SkScalar y = fPts[0].fY;
- for (int i = 1; i < fPtCount; ++i) {
- if (fPts[i].fY != y) {
- return false;
- }
- }
- return true;
-}
-
-void startEdge() {
- if (!fCurrentEdge) {
- fCurrentEdge = fEdges.push_back_n(1);
- }
- fWinding = 0;
- fPtOffset = 0;
-}
-
-void walk() {
- SkPath::Iter iter(fPath, true);
- int winding = 0;
- while ((fVerb = iter.next(fPts)) != SkPath::kDone_Verb) {
- switch (fVerb) {
- case SkPath::kMove_Verb:
- startEdge();
- continue;
- case SkPath::kLine_Verb:
- winding = direction(SkPath::kLine_Verb);
- break;
- case SkPath::kQuad_Verb:
- fVerb = QuadReduceOrder(fPts);
- winding = direction(fVerb);
- fContainsCurves |= fVerb == SkPath::kQuad_Verb;
- break;
- case SkPath::kCubic_Verb:
- fVerb = CubicReduceOrder(fPts);
- winding = direction(fVerb);
- fContainsCurves |= fVerb >= SkPath::kQuad_Verb;
- break;
- case SkPath::kClose_Verb:
- SkASSERT(fCurrentEdge);
- complete();
- continue;
- default:
- SkDEBUGFAIL("bad verb");
- return;
- }
- if (winding == 0) {
- HorizontalEdge* horizontalEdge = fHorizontalEdges.append();
- // FIXME: for degenerate quads and cubics, compute x extremes
- horizontalEdge->fLeft = fPts[0].fX;
- horizontalEdge->fRight = fPts[fVerb].fX;
- horizontalEdge->fY = fPts[0].fY;
- if (horizontalEdge->fLeft > horizontalEdge->fRight) {
- SkTSwap<SkScalar>(horizontalEdge->fLeft, horizontalEdge->fRight);
- }
- if (complete()) {
- startEdge();
- }
- continue;
- }
- if (fWinding + winding == 0) {
- // FIXME: if prior verb or this verb is a horizontal line, reverse
- // it instead of starting a new edge
- SkASSERT(fCurrentEdge);
- if (complete()) {
- startEdge();
- }
- }
- fWinding = winding;
- addEdge();
- }
- if (!complete()) {
- if (fCurrentEdge) {
- fEdges.pop_back();
- }
- }
-}
-
-private:
- const SkPath& fPath;
- InEdge* fCurrentEdge;
- SkTArray<InEdge>& fEdges;
- SkTDArray<HorizontalEdge>& fHorizontalEdges;
- SkPoint fPts[4];
- SkPath::Verb fVerb;
- int fPtCount;
- int fPtOffset;
- int8_t fWinding;
- bool fIgnoreHorizontal;
- bool fContainsCurves;
-};
-
-struct WorkEdge {
- SkScalar bottom() const {
- return fPts[verb()].fY;
- }
-
- void init(const InEdge* edge) {
- fEdge = edge;
- fPts = edge->fPts.begin();
- fVerb = edge->fVerbs.begin();
- }
-
- bool advance() {
- SkASSERT(fVerb < fEdge->fVerbs.end());
- fPts += *fVerb++;
- return fVerb != fEdge->fVerbs.end();
- }
-
- const SkPoint* lastPoints() const {
- SkASSERT(fPts >= fEdge->fPts.begin() + lastVerb());
- return &fPts[-lastVerb()];
- }
-
- SkPath::Verb lastVerb() const {
- SkASSERT(fVerb > fEdge->fVerbs.begin());
- return (SkPath::Verb) fVerb[-1];
- }
-
- const SkPoint* points() const {
- return fPts;
- }
-
- SkPath::Verb verb() const {
- return (SkPath::Verb) *fVerb;
- }
-
- ptrdiff_t verbIndex() const {
- return fVerb - fEdge->fVerbs.begin();
- }
-
- int winding() const {
- return fEdge->fWinding;
- }
-
- const InEdge* fEdge;
- const SkPoint* fPts;
- const uint8_t* fVerb;
-};
-
-// always constructed with SkTDArray because new edges are inserted
-// this may be a inappropriate optimization, suggesting that a separate array of
-// ActiveEdge* may be faster to insert and search
-
-// OPTIMIZATION: Brian suggests that global sorting should be unnecessary, since
-// as active edges are introduced, only local sorting should be required
-class ActiveEdge {
-public:
- // this logic must be kept in sync with tooCloseToCall
- // callers expect this to only read fAbove, fTangent
- bool operator<(const ActiveEdge& rh) const {
- if (fVerb == rh.fVerb) {
- // FIXME: don't know what to do if verb is quad, cubic
- return abCompare(fAbove, fBelow, rh.fAbove, rh.fBelow);
- }
- // figure out which is quad, line
- // if cached data says line did not intersect quad, use top/bottom
- if (fVerb != SkPath::kLine_Verb ? noIntersect(rh) : rh.noIntersect(*this)) {
- return abCompare(fAbove, fBelow, rh.fAbove, rh.fBelow);
- }
- // use whichever of top/tangent tangent/bottom overlaps more
- // with line top/bot
- // assumes quad/cubic can already be upconverted to cubic/cubic
- const SkPoint* line[2];
- const SkPoint* curve[4];
- if (fVerb != SkPath::kLine_Verb) {
- line[0] = &rh.fAbove;
- line[1] = &rh.fBelow;
- curve[0] = &fAbove;
- curve[1] = &fTangent;
- curve[2] = &fBelow;
- } else {
- line[0] = &fAbove;
- line[1] = &fBelow;
- curve[0] = &rh.fAbove;
- curve[1] = &rh.fTangent;
- curve[2] = &rh.fBelow;
- }
- // FIXME: code has been abandoned, incomplete....
- return false;
- }
-
- bool abCompare(const SkPoint& a1, const SkPoint& a2, const SkPoint& b1,
- const SkPoint& b2) const {
- double topD = a1.fX - b1.fX;
- if (b1.fY < a1.fY) {
- topD = (b2.fY - b1.fY) * topD - (a1.fY - b1.fY) * (b2.fX - b1.fX);
- } else if (b1.fY > a1.fY) {
- topD = (a2.fY - a1.fY) * topD + (b1.fY - a1.fY) * (a2.fX - a1.fX);
- }
- double botD = a2.fX - b2.fX;
- if (b2.fY > a2.fY) {
- botD = (b2.fY - b1.fY) * botD - (a2.fY - b2.fY) * (b2.fX - b1.fX);
- } else if (b2.fY < a2.fY) {
- botD = (a2.fY - a1.fY) * botD + (b2.fY - a2.fY) * (a2.fX - a1.fX);
- }
- // return sign of greater absolute value
- return (fabs(topD) > fabs(botD) ? topD : botD) < 0;
- }
-
- // If a pair of edges are nearly coincident for some span, add a T in the
- // edge so it can be shortened to match the other edge. Note that another
- // approach is to trim the edge after it is added to the OutBuilder list --
- // FIXME: since this has no effect if the edge is already done (i.e.,
- // fYBottom >= y) maybe this can only be done by calling trimLine later.
- void addTatYBelow(SkScalar y) {
- if (fBelow.fY <= y || fYBottom >= y) {
- return;
- }
- addTatYInner(y);
- fFixBelow = true;
- }
-
- void addTatYAbove(SkScalar y) {
- if (fBelow.fY <= y) {
- return;
- }
- addTatYInner(y);
- }
-
- void addTatYInner(SkScalar y) {
- if (fWorkEdge.fPts[0].fY > y) {
- backup(y);
- }
- SkScalar left = fWorkEdge.fPts[0].fX;
- SkScalar right = fWorkEdge.fPts[1].fX;
- if (left > right) {
- SkTSwap(left, right);
- }
- double ts[2];
- SkASSERT(fWorkEdge.fVerb[0] == SkPath::kLine_Verb);
- int pts = LineIntersect(fWorkEdge.fPts, left, right, y, ts);
- SkASSERT(pts == 1);
- // An ActiveEdge or WorkEdge has no need to modify the T values computed
- // in the InEdge, except in the following case. If a pair of edges are
- // nearly coincident, this may not be detected when the edges are
- // intersected. Later, when sorted, and this near-coincidence is found,
- // an additional t value must be added, requiring the cast below.
- InEdge* writable = const_cast<InEdge*>(fWorkEdge.fEdge);
- int insertedAt = writable->add(ts, pts, fWorkEdge.verbIndex());
- #if DEBUG_ADJUST_COINCIDENT
- SkDebugf("%s edge=%d y=%1.9g t=%1.9g\n", __FUNCTION__, ID(), y, ts[0]);
- #endif
- if (insertedAt >= 0) {
- if (insertedAt + 1 < fTIndex) {
- SkASSERT(insertedAt + 2 == fTIndex);
- --fTIndex;
- }
- }
- }
-
- bool advanceT() {
- SkASSERT(fTIndex <= fTs->count() - fExplicitTs);
- return ++fTIndex <= fTs->count() - fExplicitTs;
- }
-
- bool advance() {
- // FIXME: flip sense of next
- bool result = fWorkEdge.advance();
- fDone = !result;
- initT();
- return result;
- }
-
- void backup(SkScalar y) {
- do {
- SkASSERT(fWorkEdge.fEdge->fVerbs.begin() < fWorkEdge.fVerb);
- fWorkEdge.fPts -= *--fWorkEdge.fVerb;
- SkASSERT(fWorkEdge.fEdge->fPts.begin() <= fWorkEdge.fPts);
- } while (fWorkEdge.fPts[0].fY >= y);
- initT();
- SkASSERT(!fExplicitTs);
- fTIndex = fTs->count() + 1;
- }
-
- void calcAboveBelow(double tAbove, double tBelow) {
- fVerb = fWorkEdge.verb();
- switch (fVerb) {
- case SkPath::kLine_Verb:
- LineXYAtT(fWorkEdge.fPts, tAbove, &fAbove);
- LineXYAtT(fWorkEdge.fPts, tBelow, &fTangent);
- fBelow = fTangent;
- break;
- case SkPath::kQuad_Verb:
- // FIXME: put array in struct to avoid copy?
- SkPoint quad[3];
- QuadSubDivide(fWorkEdge.fPts, tAbove, tBelow, quad);
- fAbove = quad[0];
- fTangent = quad[0] != quad[1] ? quad[1] : quad[2];
- fBelow = quad[2];
- break;
- case SkPath::kCubic_Verb:
- SkPoint cubic[3];
- CubicSubDivide(fWorkEdge.fPts, tAbove, tBelow, cubic);
- fAbove = cubic[0];
- // FIXME: can't see how quad logic for how tangent is used
- // extends to cubic
- fTangent = cubic[0] != cubic[1] ? cubic[1]
- : cubic[0] != cubic[2] ? cubic[2] : cubic[3];
- fBelow = cubic[3];
- break;
- default:
- SkASSERT(0);
- }
- }
-
- void calcLeft(SkScalar y) {
- // OPTIMIZE: put a kDone_Verb at the end of the verb list?
- if (fDone || fBelow.fY > y) {
- return; // nothing to do; use last
- }
- calcLeft();
- if (fAbove.fY == fBelow.fY) {
- SkDebugf("%s edge=%d fAbove.fY != fBelow.fY %1.9g\n", __FUNCTION__,
- ID(), fAbove.fY);
- }
- }
-
- void calcLeft() {
- int add = (fTIndex <= fTs->count() - fExplicitTs) - 1;
- double tAbove = t(fTIndex + add);
- double tBelow = t(fTIndex - ~add);
- // OPTIMIZATION: if fAbove, fBelow have already been computed
- // for the fTIndex, don't do it again
- calcAboveBelow(tAbove, tBelow);
- // For identical x, this lets us know which edge is first.
- // If both edges have T values < 1, check x at next T (fBelow).
- SkASSERT(tAbove != tBelow);
- // FIXME: this can loop forever
- // need a break if we hit the end
- // FIXME: in unit test, figure out how explicit Ts work as well
- while (fAbove.fY == fBelow.fY) {
- if (add < 0 || fTIndex == fTs->count()) {
- add -= 1;
- SkASSERT(fTIndex + add >= 0);
- tAbove = t(fTIndex + add);
- } else {
- add += 1;
- SkASSERT(fTIndex - ~add <= fTs->count() + 1);
- tBelow = t(fTIndex - ~add);
- }
- calcAboveBelow(tAbove, tBelow);
- }
- fTAbove = tAbove;
- fTBelow = tBelow;
- }
-
- bool done(SkScalar bottom) const {
- return fDone || fYBottom >= bottom;
- }
-
- void fixBelow() {
- if (fFixBelow) {
- fTBelow = nextT();
- calcAboveBelow(fTAbove, fTBelow);
- fFixBelow = false;
- }
- }
-
- void init(const InEdge* edge) {
- fWorkEdge.init(edge);
- fDone = false;
- initT();
- fBelow.fY = SK_ScalarMin;
- fYBottom = SK_ScalarMin;
- }
-
- void initT() {
- const Intercepts& intercepts = fWorkEdge.fEdge->fIntercepts.front();
- SkASSERT(fWorkEdge.verbIndex() <= fWorkEdge.fEdge->fIntercepts.count());
- const Intercepts* interceptPtr = &intercepts + fWorkEdge.verbIndex();
- fTs = &interceptPtr->fTs;
- fExplicitTs = interceptPtr->fExplicit;
- // the above is conceptually the same as
- // fTs = &fWorkEdge.fEdge->fIntercepts[fWorkEdge.verbIndex()].fTs;
- // but templated arrays don't allow returning a pointer to the end() element
- fTIndex = 0;
- if (!fDone) {
- fVerb = fWorkEdge.verb();
- }
- SkASSERT(fVerb > SkPath::kMove_Verb);
- }
-
- // OPTIMIZATION: record if two edges are coincident when the are intersected
- // It's unclear how to do this -- seems more complicated than recording the
- // t values, since the same t values could exist intersecting non-coincident
- // edges.
- bool isCoincidentWith(const ActiveEdge* edge) const {
- if (fAbove != edge->fAbove || fBelow != edge->fBelow) {
- return false;
- }
- if (fVerb != edge->fVerb) {
- return false;
- }
- switch (fVerb) {
- case SkPath::kLine_Verb:
- return true;
- default:
- // FIXME: add support for quads, cubics
- SkASSERT(0);
- return false;
- }
- return false;
- }
-
- bool isUnordered(const ActiveEdge* edge) const {
- return fAbove == edge->fAbove && fBelow == edge->fBelow;
- }
-
-// SkPath::Verb lastVerb() const {
-// return fDone ? fWorkEdge.lastVerb() : fWorkEdge.verb();
-// }
-
- const SkPoint* lastPoints() const {
- return fDone ? fWorkEdge.lastPoints() : fWorkEdge.points();
- }
-
- bool noIntersect(const ActiveEdge& ) const {
- // incomplete
- return false;
- }
-
- // The shortest close call edge should be moved into a position where
- // it contributes if the winding is transitioning to or from zero.
- bool swapClose(const ActiveEdge* next, int prev, int wind, int mask) const {
-#if DEBUG_ADJUST_COINCIDENT
- SkDebugf("%s edge=%d (%g) next=%d (%g) prev=%d wind=%d nextWind=%d\n",
- __FUNCTION__, ID(), fBelow.fY, next->ID(), next->fBelow.fY,
- prev, wind, wind + next->fWorkEdge.winding());
-#endif
- if ((prev & mask) == 0 || (wind & mask) == 0) {
- return next->fBelow.fY < fBelow.fY;
- }
- int nextWinding = wind + next->fWorkEdge.winding();
- if ((nextWinding & mask) == 0) {
- return fBelow.fY < next->fBelow.fY;
- }
- return false;
- }
-
- bool swapCoincident(const ActiveEdge* edge, SkScalar bottom) const {
- if (fBelow.fY >= bottom || fDone || edge->fDone) {
- return false;
- }
- ActiveEdge thisWork = *this;
- ActiveEdge edgeWork = *edge;
- while ((thisWork.advanceT() || thisWork.advance())
- && (edgeWork.advanceT() || edgeWork.advance())) {
- thisWork.calcLeft();
- edgeWork.calcLeft();
- if (thisWork < edgeWork) {
- return false;
- }
- if (edgeWork < thisWork) {
- return true;
- }
- }
- return false;
- }
-
- bool swapUnordered(const ActiveEdge* edge, SkScalar /* bottom */) const {
- SkASSERT(fVerb != SkPath::kLine_Verb
- || edge->fVerb != SkPath::kLine_Verb);
- if (fDone || edge->fDone) {
- return false;
- }
- ActiveEdge thisWork, edgeWork;
- extractAboveBelow(thisWork);
- edge->extractAboveBelow(edgeWork);
- return edgeWork < thisWork;
- }
-
- bool tooCloseToCall(const ActiveEdge* edge) const {
- int ulps;
- double t1, t2, b1, b2;
- // This logic must be kept in sync with operator <
- if (edge->fAbove.fY < fAbove.fY) {
- t1 = (edge->fTangent.fY - edge->fAbove.fY) * (fAbove.fX - edge->fAbove.fX);
- t2 = (fAbove.fY - edge->fAbove.fY) * (edge->fTangent.fX - edge->fAbove.fX);
- } else if (edge->fAbove.fY > fAbove.fY) {
- t1 = (fTangent.fY - fAbove.fY) * (fAbove.fX - edge->fAbove.fX);
- t2 = (fAbove.fY - edge->fAbove.fY) * (fTangent.fX - fAbove.fX);
- } else {
- t1 = fAbove.fX;
- t2 = edge->fAbove.fX;
- }
- if (edge->fTangent.fY > fTangent.fY) {
- b1 = (edge->fTangent.fY - edge->fAbove.fY) * (fTangent.fX - edge->fTangent.fX);
- b2 = (fTangent.fY - edge->fTangent.fY) * (edge->fTangent.fX - edge->fAbove.fX);
- } else if (edge->fTangent.fY < fTangent.fY) {
- b1 = (fTangent.fY - fAbove.fY) * (fTangent.fX - edge->fTangent.fX);
- b2 = (fTangent.fY - edge->fTangent.fY) * (fTangent.fX - fAbove.fX);
- } else {
- b1 = fTangent.fX;
- b2 = edge->fTangent.fX;
- }
- if (fabs(t1 - t2) > fabs(b1 - b2)) {
- ulps = UlpsDiff((float) t1, (float) t2);
- } else {
- ulps = UlpsDiff((float) b1, (float) b2);
- }
-#if DEBUG_ADJUST_COINCIDENT
- SkDebugf("%s this=%d edge=%d ulps=%d\n", __FUNCTION__, ID(), edge->ID(),
- ulps);
-#endif
- if (ulps < 0 || ulps > 32) {
- return false;
- }
- if (fVerb == SkPath::kLine_Verb && edge->fVerb == SkPath::kLine_Verb) {
- return true;
- }
- if (fVerb != SkPath::kLine_Verb && edge->fVerb != SkPath::kLine_Verb) {
- return false;
- }
-
- double ts[2];
- bool isLine = true;
- bool curveQuad = true;
- if (fVerb == SkPath::kCubic_Verb) {
- ts[0] = (fTAbove * 2 + fTBelow) / 3;
- ts[1] = (fTAbove + fTBelow * 2) / 3;
- curveQuad = isLine = false;
- } else if (edge->fVerb == SkPath::kCubic_Verb) {
- ts[0] = (edge->fTAbove * 2 + edge->fTBelow) / 3;
- ts[1] = (edge->fTAbove + edge->fTBelow * 2) / 3;
- curveQuad = false;
- } else if (fVerb == SkPath::kQuad_Verb) {
- ts[0] = fTAbove;
- ts[1] = (fTAbove + fTBelow) / 2;
- isLine = false;
- } else {
- SkASSERT(edge->fVerb == SkPath::kQuad_Verb);
- ts[0] = edge->fTAbove;
- ts[1] = (edge->fTAbove + edge->fTBelow) / 2;
- }
- const SkPoint* curvePts = isLine ? edge->lastPoints() : lastPoints();
- const ActiveEdge* lineEdge = isLine ? this : edge;
- SkPoint curveSample[2];
- for (int index = 0; index < 2; ++index) {
- if (curveQuad) {
- QuadXYAtT(curvePts, ts[index], &curveSample[index]);
- } else {
- CubicXYAtT(curvePts, ts[index], &curveSample[index]);
- }
- }
- return IsCoincident(curveSample, lineEdge->fAbove, lineEdge->fBelow);
- }
-
- double nextT() const {
- SkASSERT(fTIndex <= fTs->count() - fExplicitTs);
- return t(fTIndex + 1);
- }
-
- double t() const {
- return t(fTIndex);
- }
-
- double t(int tIndex) const {
- if (fExplicitTs) {
- SkASSERT(tIndex < fTs->count());
- return (*fTs)[tIndex];
- }
- if (tIndex == 0) {
- return 0;
- }
- if (tIndex > fTs->count()) {
- return 1;
- }
- return (*fTs)[tIndex - 1];
- }
-
- // FIXME: debugging only
- int ID() const {
- return fWorkEdge.fEdge->fID;
- }
-
-private:
- // utility used only by swapUnordered
- void extractAboveBelow(ActiveEdge& extracted) const {
- SkPoint curve[4];
- switch (fVerb) {
- case SkPath::kLine_Verb:
- extracted.fAbove = fAbove;
- extracted.fTangent = fTangent;
- return;
- case SkPath::kQuad_Verb:
- QuadSubDivide(lastPoints(), fTAbove, fTBelow, curve);
- break;
- case SkPath::kCubic_Verb:
- CubicSubDivide(lastPoints(), fTAbove, fTBelow, curve);
- break;
- default:
- SkASSERT(0);
- }
- extracted.fAbove = curve[0];
- extracted.fTangent = curve[1];
- }
-
-public:
- WorkEdge fWorkEdge;
- const SkTDArray<double>* fTs;
- SkPoint fAbove;
- SkPoint fTangent;
- SkPoint fBelow;
- double fTAbove; // OPTIMIZATION: only required if edge has quads or cubics
- double fTBelow;
- SkScalar fYBottom;
- int fCoincident;
- int fTIndex;
- SkPath::Verb fVerb;
- bool fSkip; // OPTIMIZATION: use bitfields?
- bool fCloseCall;
- bool fDone;
- bool fFixBelow;
- bool fExplicitTs;
-};
-
-static void addToActive(SkTDArray<ActiveEdge>& activeEdges, const InEdge* edge) {
- size_t count = activeEdges.count();
- for (size_t index = 0; index < count; ++index) {
- if (edge == activeEdges[index].fWorkEdge.fEdge) {
- return;
- }
- }
- ActiveEdge* active = activeEdges.append();
- active->init(edge);
-}
-
-// Find any intersections in the range of active edges. A pair of edges, on
-// either side of another edge, may change the winding contribution for part of
-// the edge.
-// Keep horizontal edges just for
-// the purpose of computing when edges change their winding contribution, since
-// this is essentially computing the horizontal intersection.
-static void addBottomT(InEdge** currentPtr, InEdge** lastPtr,
- HorizontalEdge** horizontal) {
- InEdge** testPtr = currentPtr - 1;
- HorizontalEdge* horzEdge = *horizontal;
- SkScalar left = horzEdge->fLeft;
- SkScalar bottom = horzEdge->fY;
- while (++testPtr != lastPtr) {
- InEdge* test = *testPtr;
- if (test->fBounds.fBottom <= bottom || test->fBounds.fRight <= left) {
- continue;
- }
- WorkEdge wt;
- wt.init(test);
- do {
- HorizontalEdge** sorted = horizontal;
- horzEdge = *sorted;
- do {
- double wtTs[4];
- int pts;
- uint8_t verb = wt.verb();
- switch (verb) {
- case SkPath::kLine_Verb:
- pts = LineIntersect(wt.fPts, horzEdge->fLeft,
- horzEdge->fRight, horzEdge->fY, wtTs);
- break;
- case SkPath::kQuad_Verb:
- pts = QuadIntersect(wt.fPts, horzEdge->fLeft,
- horzEdge->fRight, horzEdge->fY, wtTs);
- break;
- case SkPath::kCubic_Verb:
- pts = CubicIntersect(wt.fPts, horzEdge->fLeft,
- horzEdge->fRight, horzEdge->fY, wtTs);
- break;
- }
- if (pts) {
-#if DEBUG_ADD_BOTTOM_TS
- for (int x = 0; x < pts; ++x) {
- SkDebugf("%s y=%g wtTs[0]=%g (%g,%g", __FUNCTION__,
- horzEdge->fY, wtTs[x], wt.fPts[0].fX, wt.fPts[0].fY);
- for (int y = 0; y < verb; ++y) {
- SkDebugf(" %g,%g", wt.fPts[y + 1].fX, wt.fPts[y + 1].fY));
- }
- SkDebugf(")\n");
- }
- if (pts > verb) {
- SkASSERT(0); // FIXME ? should this work?
- SkDebugf("%s wtTs[1]=%g\n", __FUNCTION__, wtTs[1]);
- }
-#endif
- test->add(wtTs, pts, wt.verbIndex());
- }
- horzEdge = *++sorted;
- } while (horzEdge->fY == bottom
- && horzEdge->fLeft <= test->fBounds.fRight);
- } while (wt.advance());
- }
-}
-
-#if DEBUG_ADD_INTERSECTING_TS
-static void debugShowLineIntersection(int pts, const WorkEdge& wt,
- const WorkEdge& wn, const double wtTs[2], const double wnTs[2]) {
- if (!pts) {
- return;
- }
- SkPoint wtOutPt, wnOutPt;
- LineXYAtT(wt.fPts, wtTs[0], &wtOutPt);
- LineXYAtT(wn.fPts, wnTs[0], &wnOutPt);
- SkDebugf("%s wtTs[0]=%g (%g,%g, %g,%g) (%g,%g)\n",
- __FUNCTION__,
- wtTs[0], wt.fPts[0].fX, wt.fPts[0].fY,
- wt.fPts[1].fX, wt.fPts[1].fY, wtOutPt.fX, wtOutPt.fY);
- if (pts == 2) {
- SkDebugf("%s wtTs[1]=%g\n", __FUNCTION__, wtTs[1]);
- }
- SkDebugf("%s wnTs[0]=%g (%g,%g, %g,%g) (%g,%g)\n",
- __FUNCTION__,
- wnTs[0], wn.fPts[0].fX, wn.fPts[0].fY,
- wn.fPts[1].fX, wn.fPts[1].fY, wnOutPt.fX, wnOutPt.fY);
- if (pts == 2) {
- SkDebugf("%s wnTs[1]=%g\n", __FUNCTION__, wnTs[1]);
- }
-}
-#else
-static void debugShowLineIntersection(int , const WorkEdge& ,
- const WorkEdge& , const double [2], const double [2]) {
-}
-#endif
-
-static void addIntersectingTs(InEdge** currentPtr, InEdge** lastPtr) {
- InEdge** testPtr = currentPtr - 1;
- // FIXME: lastPtr should be past the point of interest, so
- // test below should be lastPtr - 2
- // that breaks testSimplifyTriangle22, so further investigation is needed
- while (++testPtr != lastPtr - 1) {
- InEdge* test = *testPtr;
- InEdge** nextPtr = testPtr;
- do {
- InEdge* next = *++nextPtr;
- // FIXME: this compares against the sentinel sometimes
- // OPTIMIZATION: this may never be needed since this gets called
- // in two passes now. Verify that double hits are appropriate.
- if (test->cached(next)) {
- continue;
- }
- if (!Bounds::Intersects(test->fBounds, next->fBounds)) {
- continue;
- }
- WorkEdge wt, wn;
- wt.init(test);
- wn.init(next);
- do {
- int pts;
- Intersections ts;
- bool swap = false;
- switch (wt.verb()) {
- case SkPath::kLine_Verb:
- switch (wn.verb()) {
- case SkPath::kLine_Verb: {
- pts = LineIntersect(wt.fPts, wn.fPts, ts);
- debugShowLineIntersection(pts, wt, wn,
- ts.fT[0], ts.fT[1]);
- break;
- }
- case SkPath::kQuad_Verb: {
- swap = true;
- pts = QuadLineIntersect(wn.fPts, wt.fPts, ts);
- break;
- }
- case SkPath::kCubic_Verb: {
- swap = true;
- pts = CubicLineIntersect(wn.fPts, wt.fPts, ts);
- break;
- }
- default:
- SkASSERT(0);
- }
- break;
- case SkPath::kQuad_Verb:
- switch (wn.verb()) {
- case SkPath::kLine_Verb: {
- pts = QuadLineIntersect(wt.fPts, wn.fPts, ts);
- break;
- }
- case SkPath::kQuad_Verb: {
- pts = QuadIntersect(wt.fPts, wn.fPts, ts);
- break;
- }
- case SkPath::kCubic_Verb: {
- // FIXME: promote quad to cubic
- pts = CubicIntersect(wt.fPts, wn.fPts, ts);
- break;
- }
- default:
- SkASSERT(0);
- }
- break;
- case SkPath::kCubic_Verb:
- switch (wn.verb()) {
- case SkPath::kLine_Verb: {
- pts = CubicLineIntersect(wt.fPts, wn.fPts, ts);
- break;
- }
- case SkPath::kQuad_Verb: {
- // FIXME: promote quad to cubic
- pts = CubicIntersect(wt.fPts, wn.fPts, ts);
- break;
- }
- case SkPath::kCubic_Verb: {
- pts = CubicIntersect(wt.fPts, wn.fPts, ts);
- break;
- }
- default:
- SkASSERT(0);
- }
- break;
- default:
- SkASSERT(0);
- }
- test->add(ts.fT[swap], pts, wt.verbIndex());
- next->add(ts.fT[!swap], pts, wn.verbIndex());
- } while (wt.bottom() <= wn.bottom() ? wt.advance() : wn.advance());
- } while (nextPtr != lastPtr);
- }
-}
-
-static InEdge** advanceEdges(SkTDArray<ActiveEdge>* activeEdges,
- InEdge** currentPtr, InEdge** lastPtr, SkScalar y) {
- InEdge** testPtr = currentPtr - 1;
- while (++testPtr != lastPtr) {
- if ((*testPtr)->fBounds.fBottom > y) {
- continue;
- }
- if (activeEdges) {
- InEdge* test = *testPtr;
- ActiveEdge* activePtr = activeEdges->begin() - 1;
- ActiveEdge* lastActive = activeEdges->end();
- while (++activePtr != lastActive) {
- if (activePtr->fWorkEdge.fEdge == test) {
- activeEdges->remove(activePtr - activeEdges->begin());
- break;
- }
- }
- }
- if (testPtr == currentPtr) {
- ++currentPtr;
- }
- }
- return currentPtr;
-}
-
-// OPTIMIZE: inline?
-static HorizontalEdge** advanceHorizontal(HorizontalEdge** edge, SkScalar y) {
- while ((*edge)->fY < y) {
- ++edge;
- }
- return edge;
-}
-
-// compute bottom taking into account any intersected edges
-static SkScalar computeInterceptBottom(SkTDArray<ActiveEdge>& activeEdges,
- SkScalar y, SkScalar bottom) {
- ActiveEdge* activePtr = activeEdges.begin() - 1;
- ActiveEdge* lastActive = activeEdges.end();
- while (++activePtr != lastActive) {
- const InEdge* test = activePtr->fWorkEdge.fEdge;
- if (!test->fContainsIntercepts) {
- continue;
- }
- WorkEdge wt;
- wt.init(test);
- do {
- const Intercepts& intercepts = test->fIntercepts[wt.verbIndex()];
- if (intercepts.fTopIntercepts > 1) {
- SkScalar yTop = wt.fPts[0].fY;
- if (yTop > y && bottom > yTop) {
- bottom = yTop;
- }
- }
- if (intercepts.fBottomIntercepts > 1) {
- SkScalar yBottom = wt.fPts[wt.verb()].fY;
- if (yBottom > y && bottom > yBottom) {
- bottom = yBottom;
- }
- }
- const SkTDArray<double>& fTs = intercepts.fTs;
- size_t count = fTs.count();
- for (size_t index = 0; index < count; ++index) {
- SkScalar yIntercept;
- switch (wt.verb()) {
- case SkPath::kLine_Verb: {
- yIntercept = LineYAtT(wt.fPts, fTs[index]);
- break;
- }
- case SkPath::kQuad_Verb: {
- yIntercept = QuadYAtT(wt.fPts, fTs[index]);
- break;
- }
- case SkPath::kCubic_Verb: {
- yIntercept = CubicYAtT(wt.fPts, fTs[index]);
- break;
- }
- default:
- SkASSERT(0); // should never get here
- }
- if (yIntercept > y && bottom > yIntercept) {
- bottom = yIntercept;
- }
- }
- } while (wt.advance());
- }
-#if DEBUG_BOTTOM
- SkDebugf("%s bottom=%1.9g\n", __FUNCTION__, bottom);
-#endif
- return bottom;
-}
-
-static SkScalar findBottom(InEdge** currentPtr,
- InEdge** edgeListEnd, SkTDArray<ActiveEdge>* activeEdges, SkScalar y,
- bool /*asFill*/, InEdge**& testPtr) {
- InEdge* current = *currentPtr;
- SkScalar bottom = current->fBounds.fBottom;
-
- // find the list of edges that cross y
- InEdge* test = *testPtr;
- while (testPtr != edgeListEnd) {
- SkScalar testTop = test->fBounds.fTop;
- if (bottom <= testTop) {
- break;
- }
- SkScalar testBottom = test->fBounds.fBottom;
- // OPTIMIZATION: Shortening the bottom is only interesting when filling
- // and when the edge is to the left of a longer edge. If it's a framing
- // edge, or part of the right, it won't effect the longer edges.
- if (testTop > y) {
- bottom = testTop;
- break;
- }
- if (y < testBottom) {
- if (bottom > testBottom) {
- bottom = testBottom;
- }
- if (activeEdges) {
- addToActive(*activeEdges, test);
- }
- }
- test = *++testPtr;
- }
-#if DEBUG_BOTTOM
- SkDebugf("%s %d bottom=%1.9g\n", __FUNCTION__, activeEdges ? 2 : 1, bottom);
-#endif
- return bottom;
-}
-
-static void makeEdgeList(SkTArray<InEdge>& edges, InEdge& edgeSentinel,
- SkTDArray<InEdge*>& edgeList) {
- size_t edgeCount = edges.count();
- if (edgeCount == 0) {
- return;
- }
- int id = 0;
- for (size_t index = 0; index < edgeCount; ++index) {
- InEdge& edge = edges[index];
- if (!edge.fWinding) {
- continue;
- }
- edge.fID = ++id;
- *edgeList.append() = &edge;
- }
- *edgeList.append() = &edgeSentinel;
- QSort<InEdge>(edgeList.begin(), edgeList.end() - 1);
-}
-
-static void makeHorizontalList(SkTDArray<HorizontalEdge>& edges,
- HorizontalEdge& edgeSentinel, SkTDArray<HorizontalEdge*>& edgeList) {
- size_t edgeCount = edges.count();
- if (edgeCount == 0) {
- return;
- }
- for (size_t index = 0; index < edgeCount; ++index) {
- *edgeList.append() = &edges[index];
- }
- edgeSentinel.fLeft = edgeSentinel.fRight = edgeSentinel.fY = SK_ScalarMax;
- *edgeList.append() = &edgeSentinel;
- QSort<HorizontalEdge>(edgeList.begin(), edgeList.end() - 1);
-}
-
-static void skipCoincidence(int lastWinding, int winding, int windingMask,
- ActiveEdge* activePtr, ActiveEdge* firstCoincident) {
- if (((lastWinding & windingMask) == 0) ^ ((winding & windingMask) != 0)) {
- return;
- }
- // FIXME: ? shouldn't this be if (lastWinding & windingMask) ?
- if (lastWinding) {
-#if DEBUG_ADJUST_COINCIDENT
- SkDebugf("%s edge=%d 1 set skip=false\n", __FUNCTION__, activePtr->ID());
-#endif
- activePtr->fSkip = false;
- } else {
-#if DEBUG_ADJUST_COINCIDENT
- SkDebugf("%s edge=%d 2 set skip=false\n", __FUNCTION__, firstCoincident->ID());
-#endif
- firstCoincident->fSkip = false;
- }
-}
-
-static void sortHorizontal(SkTDArray<ActiveEdge>& activeEdges,
- SkTDArray<ActiveEdge*>& edgeList, SkScalar y) {
- size_t edgeCount = activeEdges.count();
- if (edgeCount == 0) {
- return;
- }
-#if DEBUG_SORT_HORIZONTAL
- const int tab = 3; // FIXME: debugging only
- SkDebugf("%s y=%1.9g\n", __FUNCTION__, y);
-#endif
- size_t index;
- for (index = 0; index < edgeCount; ++index) {
- ActiveEdge& activeEdge = activeEdges[index];
- do {
- activeEdge.calcLeft(y);
- // skip segments that don't span y
- if (activeEdge.fAbove != activeEdge.fBelow) {
- break;
- }
- if (activeEdge.fDone) {
-#if DEBUG_SORT_HORIZONTAL
- SkDebugf("%*s edge=%d done\n", tab, "", activeEdge.ID());
-#endif
- goto nextEdge;
- }
-#if DEBUG_SORT_HORIZONTAL
- SkDebugf("%*s edge=%d above==below\n", tab, "", activeEdge.ID());
-#endif
- } while (activeEdge.advanceT() || activeEdge.advance());
-#if DEBUG_SORT_HORIZONTAL
- SkDebugf("%*s edge=%d above=(%1.9g,%1.9g) (%1.9g) below=(%1.9g,%1.9g)"
- " (%1.9g)\n", tab, "", activeEdge.ID(),
- activeEdge.fAbove.fX, activeEdge.fAbove.fY, activeEdge.fTAbove,
- activeEdge.fBelow.fX, activeEdge.fBelow.fY, activeEdge.fTBelow);
-#endif
- activeEdge.fSkip = activeEdge.fCloseCall = activeEdge.fFixBelow = false;
- *edgeList.append() = &activeEdge;
-nextEdge:
- ;
- }
- QSort<ActiveEdge>(edgeList.begin(), edgeList.end() - 1);
-}
-
-// remove coincident edges
-// OPTIMIZE: remove edges? This is tricky because the current logic expects
-// the winding count to be maintained while skipping coincident edges. In
-// addition to removing the coincident edges, the remaining edges would need
-// to have a different winding value, possibly different per intercept span.
-static SkScalar adjustCoincident(SkTDArray<ActiveEdge*>& edgeList,
- int windingMask, SkScalar y, SkScalar bottom, OutEdgeBuilder& outBuilder)
-{
-#if DEBUG_ADJUST_COINCIDENT
- SkDebugf("%s y=%1.9g bottom=%1.9g\n", __FUNCTION__, y, bottom);
-#endif
- size_t edgeCount = edgeList.count();
- if (edgeCount == 0) {
- return bottom;
- }
- ActiveEdge* activePtr, * nextPtr = edgeList[0];
- size_t index;
- bool foundCoincident = false;
- size_t firstIndex = 0;
- for (index = 1; index < edgeCount; ++index) {
- activePtr = nextPtr;
- nextPtr = edgeList[index];
- if (firstIndex != index - 1 && activePtr->fVerb > SkPath::kLine_Verb
- && nextPtr->fVerb == SkPath::kLine_Verb
- && activePtr->isUnordered(nextPtr)) {
- // swap the line with the curve
- // back up to the previous edge and retest
- SkTSwap<ActiveEdge*>(edgeList[index - 1], edgeList[index]);
- SkASSERT(index > 1);
- index -= 2;
- nextPtr = edgeList[index];
- continue;
- }
- bool closeCall = false;
- activePtr->fCoincident = firstIndex;
- if (activePtr->isCoincidentWith(nextPtr)
- || (closeCall = activePtr->tooCloseToCall(nextPtr))) {
- activePtr->fSkip = nextPtr->fSkip = foundCoincident = true;
- activePtr->fCloseCall = nextPtr->fCloseCall = closeCall;
- } else if (activePtr->isUnordered(nextPtr)) {
- foundCoincident = true;
- } else {
- firstIndex = index;
- }
- }
- nextPtr->fCoincident = firstIndex;
- if (!foundCoincident) {
- return bottom;
- }
- int winding = 0;
- nextPtr = edgeList[0];
- for (index = 1; index < edgeCount; ++index) {
- int priorWinding = winding;
- winding += activePtr->fWorkEdge.winding();
- activePtr = nextPtr;
- nextPtr = edgeList[index];
- SkASSERT(activePtr == edgeList[index - 1]);
- SkASSERT(nextPtr == edgeList[index]);
- if (activePtr->fCoincident != nextPtr->fCoincident) {
- continue;
- }
- // the coincident edges may not have been sorted above -- advance
- // the edges and resort if needed
- // OPTIMIZE: if sorting is done incrementally as new edges are added
- // and not all at once as is done here, fold this test into the
- // current less than test.
- while ((!activePtr->fSkip || !nextPtr->fSkip)
- && activePtr->fCoincident == nextPtr->fCoincident) {
- if (activePtr->swapUnordered(nextPtr, bottom)) {
- winding -= activePtr->fWorkEdge.winding();
- SkASSERT(activePtr == edgeList[index - 1]);
- SkASSERT(nextPtr == edgeList[index]);
- SkTSwap<ActiveEdge*>(edgeList[index - 1], edgeList[index]);
- if (--index == 0) {
- winding += activePtr->fWorkEdge.winding();
- break;
- }
- // back up one
- activePtr = edgeList[index - 1];
- continue;
- }
- SkASSERT(activePtr == edgeList[index - 1]);
- SkASSERT(nextPtr == edgeList[index]);
- break;
- }
- if (activePtr->fSkip && nextPtr->fSkip) {
- if (activePtr->fCloseCall ? activePtr->swapClose(nextPtr,
- priorWinding, winding, windingMask)
- : activePtr->swapCoincident(nextPtr, bottom)) {
- winding -= activePtr->fWorkEdge.winding();
- SkASSERT(activePtr == edgeList[index - 1]);
- SkASSERT(nextPtr == edgeList[index]);
- SkTSwap<ActiveEdge*>(edgeList[index - 1], edgeList[index]);
- SkTSwap<ActiveEdge*>(activePtr, nextPtr);
- winding += activePtr->fWorkEdge.winding();
- SkASSERT(activePtr == edgeList[index - 1]);
- SkASSERT(nextPtr == edgeList[index]);
- }
- }
- }
- int firstCoincidentWinding = 0;
- ActiveEdge* firstCoincident = NULL;
- winding = 0;
- activePtr = edgeList[0];
- for (index = 1; index < edgeCount; ++index) {
- int priorWinding = winding;
- winding += activePtr->fWorkEdge.winding();
- nextPtr = edgeList[index];
- if (activePtr->fSkip && nextPtr->fSkip
- && activePtr->fCoincident == nextPtr->fCoincident) {
- if (!firstCoincident) {
- firstCoincident = activePtr;
- firstCoincidentWinding = priorWinding;
- }
- if (activePtr->fCloseCall) {
- // If one of the edges has already been added to out as a non
- // coincident edge, trim it back to the top of this span
- if (outBuilder.trimLine(y, activePtr->ID())) {
- activePtr->addTatYAbove(y);
- #if DEBUG_ADJUST_COINCIDENT
- SkDebugf("%s 1 edge=%d y=%1.9g (was fYBottom=%1.9g)\n",
- __FUNCTION__, activePtr->ID(), y, activePtr->fYBottom);
- #endif
- activePtr->fYBottom = y;
- }
- if (outBuilder.trimLine(y, nextPtr->ID())) {
- nextPtr->addTatYAbove(y);
- #if DEBUG_ADJUST_COINCIDENT
- SkDebugf("%s 2 edge=%d y=%1.9g (was fYBottom=%1.9g)\n",
- __FUNCTION__, nextPtr->ID(), y, nextPtr->fYBottom);
- #endif
- nextPtr->fYBottom = y;
- }
- // add missing t values so edges can be the same length
- SkScalar testY = activePtr->fBelow.fY;
- nextPtr->addTatYBelow(testY);
- if (bottom > testY && testY > y) {
- #if DEBUG_ADJUST_COINCIDENT
- SkDebugf("%s 3 edge=%d bottom=%1.9g (was bottom=%1.9g)\n",
- __FUNCTION__, activePtr->ID(), testY, bottom);
- #endif
- bottom = testY;
- }
- testY = nextPtr->fBelow.fY;
- activePtr->addTatYBelow(testY);
- if (bottom > testY && testY > y) {
- #if DEBUG_ADJUST_COINCIDENT
- SkDebugf("%s 4 edge=%d bottom=%1.9g (was bottom=%1.9g)\n",
- __FUNCTION__, nextPtr->ID(), testY, bottom);
- #endif
- bottom = testY;
- }
- }
- } else if (firstCoincident) {
- skipCoincidence(firstCoincidentWinding, winding, windingMask,
- activePtr, firstCoincident);
- firstCoincident = NULL;
- }
- activePtr = nextPtr;
- }
- if (firstCoincident) {
- winding += activePtr->fWorkEdge.winding();
- skipCoincidence(firstCoincidentWinding, winding, windingMask, activePtr,
- firstCoincident);
- }
- // fix up the bottom for close call edges. OPTIMIZATION: maybe this could
- // be in the loop above, but moved here since loop above reads fBelow and
- // it felt unsafe to write it in that loop
- for (index = 0; index < edgeCount; ++index) {
- (edgeList[index])->fixBelow();
- }
- return bottom;
-}
-
-// stitch edge and t range that satisfies operation
-static void stitchEdge(SkTDArray<ActiveEdge*>& edgeList, SkScalar
-#if DEBUG_STITCH_EDGE
-y
-#endif
-,
- SkScalar bottom, int windingMask, bool fill, OutEdgeBuilder& outBuilder) {
- int winding = 0;
- ActiveEdge** activeHandle = edgeList.begin() - 1;
- ActiveEdge** lastActive = edgeList.end();
-#if DEBUG_STITCH_EDGE
- const int tab = 7; // FIXME: debugging only
- SkDebugf("%s y=%1.9g bottom=%1.9g\n", __FUNCTION__, y, bottom);
-#endif
- while (++activeHandle != lastActive) {
- ActiveEdge* activePtr = *activeHandle;
- const WorkEdge& wt = activePtr->fWorkEdge;
- int lastWinding = winding;
- winding += wt.winding();
-#if DEBUG_STITCH_EDGE
- SkDebugf("%*s edge=%d lastWinding=%d winding=%d skip=%d close=%d"
- " above=%1.9g below=%1.9g\n",
- tab-4, "", activePtr->ID(), lastWinding,
- winding, activePtr->fSkip, activePtr->fCloseCall,
- activePtr->fTAbove, activePtr->fTBelow);
-#endif
- if (activePtr->done(bottom)) {
-#if DEBUG_STITCH_EDGE
- SkDebugf("%*s fDone=%d || fYBottom=%1.9g >= bottom\n", tab, "",
- activePtr->fDone, activePtr->fYBottom);
-#endif
- continue;
- }
- int opener = (lastWinding & windingMask) == 0;
- bool closer = (winding & windingMask) == 0;
- SkASSERT(!opener | !closer);
- bool inWinding = opener | closer;
- SkPoint clippedPts[4];
- const SkPoint* clipped = NULL;
- bool moreToDo, aboveBottom;
- do {
- double currentT = activePtr->t();
- const SkPoint* points = wt.fPts;
- double nextT;
- SkPath::Verb verb = activePtr->fVerb;
- do {
- nextT = activePtr->nextT();
- // FIXME: obtuse: want efficient way to say
- // !currentT && currentT != 1 || !nextT && nextT != 1
- if (currentT * nextT != 0 || currentT + nextT != 1) {
- // OPTIMIZATION: if !inWinding, we only need
- // clipped[1].fY
- switch (verb) {
- case SkPath::kLine_Verb:
- LineSubDivide(points, currentT, nextT, clippedPts);
- break;
- case SkPath::kQuad_Verb:
- QuadSubDivide(points, currentT, nextT, clippedPts);
- break;
- case SkPath::kCubic_Verb:
- CubicSubDivide(points, currentT, nextT, clippedPts);
- break;
- default:
- SkASSERT(0);
- break;
- }
- clipped = clippedPts;
- } else {
- clipped = points;
- }
- if (inWinding && !activePtr->fSkip && (fill ? clipped[0].fY
- != clipped[verb].fY : clipped[0] != clipped[verb])) {
-#if DEBUG_STITCH_EDGE
- SkDebugf("%*s add%s %1.9g,%1.9g %1.9g,%1.9g edge=%d"
- " v=%d t=(%1.9g,%1.9g)\n", tab, "",
- kUVerbStr[verb], clipped[0].fX, clipped[0].fY,
- clipped[verb].fX, clipped[verb].fY,
- activePtr->ID(),
- activePtr->fWorkEdge.fVerb
- - activePtr->fWorkEdge.fEdge->fVerbs.begin(),
- currentT, nextT);
-#endif
- outBuilder.addCurve(clipped, (SkPath::Verb) verb,
- activePtr->fWorkEdge.fEdge->fID,
- activePtr->fCloseCall);
- } else {
-#if DEBUG_STITCH_EDGE
- SkDebugf("%*s skip%s %1.9g,%1.9g %1.9g,%1.9g"
- " edge=%d v=%d t=(%1.9g,%1.9g)\n", tab, "",
- kUVerbStr[verb], clipped[0].fX, clipped[0].fY,
- clipped[verb].fX, clipped[verb].fY,
- activePtr->ID(),
- activePtr->fWorkEdge.fVerb
- - activePtr->fWorkEdge.fEdge->fVerbs.begin(),
- currentT, nextT);
-#endif
- }
- // by advancing fAbove/fBelow, the next call to sortHorizontal
- // will use these values if they're still valid instead of
- // recomputing
- if (clipped[verb].fY > activePtr->fBelow.fY
- && bottom >= activePtr->fBelow.fY
- && verb == SkPath::kLine_Verb) {
- activePtr->fAbove = activePtr->fBelow;
- activePtr->fBelow = activePtr->fTangent = clipped[verb];
- activePtr->fTAbove = activePtr->fTBelow < 1
- ? activePtr->fTBelow : 0;
- activePtr->fTBelow = nextT;
- }
- currentT = nextT;
- moreToDo = activePtr->advanceT();
- activePtr->fYBottom = clipped[verb].fY; // was activePtr->fCloseCall ? bottom :
-
- // clearing the fSkip/fCloseCall bit here means that trailing edges
- // fall out of sync, if one edge is long and another is a series of short pieces
- // if fSkip/fCloseCall is set, need to recompute coincidence/too-close-to-call
- // after advancing
- // another approach would be to restrict bottom to smaller part of close call
- // maybe this is already happening with coincidence when intersection is computed,
- // and needs to be added to the close call computation as well
- // this is hard to do because that the bottom is important is not known when
- // the lines are intersected; only when the computation for edge sorting is done
- // does the need for new bottoms become apparent.
- // maybe this is good incentive to scrap the current sort and do an insertion
- // sort that can take this into consideration when the x value is computed
-
- // FIXME: initialized in sortHorizontal, cleared here as well so
- // that next edge is not skipped -- but should skipped edges ever
- // continue? (probably not)
- aboveBottom = clipped[verb].fY < bottom;
- if (clipped[0].fY != clipped[verb].fY) {
- activePtr->fSkip = false;
- activePtr->fCloseCall = false;
- aboveBottom &= !activePtr->fCloseCall;
- }
-#if DEBUG_STITCH_EDGE
- else {
- if (activePtr->fSkip || activePtr->fCloseCall) {
- SkDebugf("%s skip or close == %1.9g\n", __FUNCTION__,
- clippedPts[0].fY);
- }
- }
-#endif
- } while (moreToDo & aboveBottom);
- } while ((moreToDo || activePtr->advance()) & aboveBottom);
- }
-}
-
-#if DEBUG_DUMP
-static void dumpEdgeList(const SkTDArray<InEdge*>& edgeList,
- const InEdge& edgeSentinel) {
- InEdge** debugPtr = edgeList.begin();
- do {
- (*debugPtr++)->dump();
- } while (*debugPtr != &edgeSentinel);
-}
-#else
-static void dumpEdgeList(const SkTDArray<InEdge*>& ,
- const InEdge& ) {
-}
-#endif
-
-void simplify(const SkPath& path, bool asFill, SkPath& simple) {
- // returns 1 for evenodd, -1 for winding, regardless of inverse-ness
- int windingMask = (path.getFillType() & 1) ? 1 : -1;
- simple.reset();
- simple.setFillType(SkPath::kEvenOdd_FillType);
- // turn path into list of edges increasing in y
- // if an edge is a quad or a cubic with a y extrema, note it, but leave it
- // unbroken. Once we have a list, sort it, then walk the list (walk edges
- // twice that have y extrema's on top) and detect crossings -- look for raw
- // bounds that cross over, then tight bounds that cross
- SkTArray<InEdge> edges;
- SkTDArray<HorizontalEdge> horizontalEdges;
- InEdgeBuilder builder(path, asFill, edges, horizontalEdges);
- SkTDArray<InEdge*> edgeList;
- InEdge edgeSentinel;
- edgeSentinel.reset();
- makeEdgeList(edges, edgeSentinel, edgeList);
- SkTDArray<HorizontalEdge*> horizontalList;
- HorizontalEdge horizontalSentinel;
- makeHorizontalList(horizontalEdges, horizontalSentinel, horizontalList);
- InEdge** currentPtr = edgeList.begin();
- if (!currentPtr) {
- return;
- }
- // find all intersections between edges
-// beyond looking for horizontal intercepts, we need to know if any active edges
-// intersect edges below 'bottom', but above the active edge segment.
-// maybe it makes more sense to compute all intercepts before doing anything
-// else, since the intercept list is long-lived, at least in the current design.
- SkScalar y = (*currentPtr)->fBounds.fTop;
- HorizontalEdge** currentHorizontal = horizontalList.begin();
- do {
- InEdge** lastPtr = currentPtr; // find the edge below the bottom of the first set
- SkScalar bottom = findBottom(currentPtr, edgeList.end(),
- NULL, y, asFill, lastPtr);
- if (lastPtr > currentPtr) {
- if (currentHorizontal) {
- if ((*currentHorizontal)->fY < SK_ScalarMax) {
- addBottomT(currentPtr, lastPtr, currentHorizontal);
- }
- currentHorizontal = advanceHorizontal(currentHorizontal, bottom);
- }
- addIntersectingTs(currentPtr, lastPtr);
- }
- y = bottom;
- currentPtr = advanceEdges(NULL, currentPtr, lastPtr, y);
- } while (*currentPtr != &edgeSentinel);
- // if a quadratic or cubic now has an intermediate T value, see if the Ts
- // on either side cause the Y values to monotonically increase. If not, split
- // the curve at the new T.
-
- // try an alternate approach which does not split curves or stitch edges
- // (may still need adjustCoincident, though)
- // the idea is to output non-intersecting contours, then figure out their
- // respective winding contribution
- // each contour will need to know whether it is CW or CCW, and then whether
- // a ray from that contour hits any a contour that contains it. The ray can
- // move to the left and then arbitrarily move up or down (as long as it never
- // moves to the right) to find a reference sibling contour or containing
- // contour. If the contour is part of an intersection, the companion contour
- // that is part of the intersection can determine the containership.
- if (builder.containsCurves()) {
- currentPtr = edgeList.begin();
- SkTArray<InEdge> splits;
- do {
- (*currentPtr)->splitInflectionPts(splits);
- } while (*++currentPtr != &edgeSentinel);
- if (splits.count()) {
- for (int index = 0; index < splits.count(); ++index) {
- edges.push_back(splits[index]);
- }
- edgeList.reset();
- makeEdgeList(edges, edgeSentinel, edgeList);
- }
- }
- dumpEdgeList(edgeList, edgeSentinel);
- // walk the sorted edges from top to bottom, computing accumulated winding
- SkTDArray<ActiveEdge> activeEdges;
- OutEdgeBuilder outBuilder(asFill);
- currentPtr = edgeList.begin();
- y = (*currentPtr)->fBounds.fTop;
- do {
- InEdge** lastPtr = currentPtr; // find the edge below the bottom of the first set
- SkScalar bottom = findBottom(currentPtr, edgeList.end(),
- &activeEdges, y, asFill, lastPtr);
- if (lastPtr > currentPtr) {
- bottom = computeInterceptBottom(activeEdges, y, bottom);
- SkTDArray<ActiveEdge*> activeEdgeList;
- sortHorizontal(activeEdges, activeEdgeList, y);
- bottom = adjustCoincident(activeEdgeList, windingMask, y, bottom,
- outBuilder);
- stitchEdge(activeEdgeList, y, bottom, windingMask, asFill, outBuilder);
- }
- y = bottom;
- // OPTIMIZATION: as edges expire, InEdge allocations could be released
- currentPtr = advanceEdges(&activeEdges, currentPtr, lastPtr, y);
- } while (*currentPtr != &edgeSentinel);
- // assemble output path from string of pts, verbs
- outBuilder.bridge();
- outBuilder.assemble(simple);
-}
diff --git a/experimental/Intersection/EdgeWalkerPolygon4x4_Test.cpp b/experimental/Intersection/EdgeWalkerPolygon4x4_Test.cpp
deleted file mode 100755
index 9a5c1d01e3..0000000000
--- a/experimental/Intersection/EdgeWalkerPolygon4x4_Test.cpp
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "EdgeWalker_Test.h"
-#include "Intersection_Tests.h"
-
-static void* testSimplify4x4QuadralateralsMain(void* data)
-{
- SkASSERT(data);
- State4& state = *(State4*) data;
- char pathStr[1024];
- bzero(pathStr, sizeof(pathStr));
- do {
- int ax = state.a & 0x03;
- int ay = state.a >> 2;
- int bx = state.b & 0x03;
- int by = state.b >> 2;
- int cx = state.c & 0x03;
- int cy = state.c >> 2;
- int dx = state.d & 0x03;
- int dy = state.d >> 2;
- for (int e = 0 ; e < 16; ++e) {
- int ex = e & 0x03;
- int ey = e >> 2;
- for (int f = e ; f < 16; ++f) {
- int fx = f & 0x03;
- int fy = f >> 2;
- for (int g = f ; g < 16; ++g) {
- int gx = g & 0x03;
- int gy = g >> 2;
- for (int h = g ; h < 16; ++h) {
- int hx = h & 0x03;
- int hy = h >> 2;
- SkPath path, out;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(ax, ay);
- path.lineTo(bx, by);
- path.lineTo(cx, cy);
- path.lineTo(dx, dy);
- path.close();
- path.moveTo(ex, ey);
- path.lineTo(fx, fy);
- path.lineTo(gx, gy);
- path.lineTo(hx, hy);
- path.close();
- if (1) { // gdb: set print elements 400
- char* str = pathStr;
- str += sprintf(str, " path.moveTo(%d, %d);\n", ax, ay);
- str += sprintf(str, " path.lineTo(%d, %d);\n", bx, by);
- str += sprintf(str, " path.lineTo(%d, %d);\n", cx, cy);
- str += sprintf(str, " path.lineTo(%d, %d);\n", dx, dy);
- str += sprintf(str, " path.close();\n");
- str += sprintf(str, " path.moveTo(%d, %d);\n", ex, ey);
- str += sprintf(str, " path.lineTo(%d, %d);\n", fx, fy);
- str += sprintf(str, " path.lineTo(%d, %d);\n", gx, gy);
- str += sprintf(str, " path.lineTo(%d, %d);\n", hx, hy);
- str += sprintf(str, " path.close();\n");
- }
- outputProgress(state, pathStr, SkPath::kWinding_FillType);
- testSimplifyx(path, false, out, state, pathStr);
- state.testsRun++;
- path.setFillType(SkPath::kEvenOdd_FillType);
- outputProgress(state, pathStr, SkPath::kEvenOdd_FillType);
- testSimplifyx(path, true, out, state, pathStr);
- state.testsRun++;
- }
- }
- }
- }
- } while (runNextTestSet(state));
- return NULL;
-}
-
-void Simplify4x4QuadralateralsThreaded_Test(int& testsRun)
-{
- SkDebugf("%s\n", __FUNCTION__);
-#ifdef SK_DEBUG
- gDebugMaxWindSum = 4; // FIXME: 3?
- gDebugMaxWindValue = 4;
-#endif
- const char testStr[] = "testQuadralateral";
- initializeTests(testStr, sizeof(testStr));
- int testsStart = testsRun;
- for (int a = 0; a < 16; ++a) {
- for (int b = a ; b < 16; ++b) {
- for (int c = b ; c < 16; ++c) {
- for (int d = c; d < 16; ++d) {
- testsRun += dispatchTest4(testSimplify4x4QuadralateralsMain,
- a, b, c, d);
- }
- if (!gRunTestsInOneThread) SkDebugf(".");
- }
- if (!gRunTestsInOneThread) SkDebugf("%d", b);
- }
- if (!gRunTestsInOneThread) SkDebugf("\n%d", a);
- }
- testsRun += waitForCompletion();
- SkDebugf("%s tests=%d total=%d\n", __FUNCTION__, testsRun - testsStart, testsRun);
-}
-
-
-static void* testSimplify4x4NondegeneratesMain(void* data) {
- SkASSERT(data);
- State4& state = *(State4*) data;
- char pathStr[1024];
- bzero(pathStr, sizeof(pathStr));
- do {
- int ax = state.a & 0x03;
- int ay = state.a >> 2;
- int bx = state.b & 0x03;
- int by = state.b >> 2;
- int cx = state.c & 0x03;
- int cy = state.c >> 2;
- for (int d = 0; d < 15; ++d) {
- int dx = d & 0x03;
- int dy = d >> 2;
- for (int e = d + 1; e < 16; ++e) {
- int ex = e & 0x03;
- int ey = e >> 2;
- for (int f = d + 1; f < 16; ++f) {
- if (e == f) {
- continue;
- }
- int fx = f & 0x03;
- int fy = f >> 2;
- if ((ex - dx) * (fy - dy) == (ey - dy) * (fx - dx)) {
- continue;
- }
- SkPath path, out;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(ax, ay);
- path.lineTo(bx, by);
- path.lineTo(cx, cy);
- path.close();
- path.moveTo(dx, dy);
- path.lineTo(ex, ey);
- path.lineTo(fx, fy);
- path.close();
- if (1) {
- char* str = pathStr;
- str += sprintf(str, " path.moveTo(%d, %d);\n", ax, ay);
- str += sprintf(str, " path.lineTo(%d, %d);\n", bx, by);
- str += sprintf(str, " path.lineTo(%d, %d);\n", cx, cy);
- str += sprintf(str, " path.close();\n");
- str += sprintf(str, " path.moveTo(%d, %d);\n", dx, dy);
- str += sprintf(str, " path.lineTo(%d, %d);\n", ex, ey);
- str += sprintf(str, " path.lineTo(%d, %d);\n", fx, fy);
- str += sprintf(str, " path.close();\n");
- }
- outputProgress(state, pathStr, SkPath::kWinding_FillType);
- testSimplifyx(path, false, out, state, pathStr);
- state.testsRun++;
- path.setFillType(SkPath::kEvenOdd_FillType);
- outputProgress(state, pathStr, SkPath::kEvenOdd_FillType);
- testSimplifyx(path, true, out, state, pathStr);
- state.testsRun++;
- }
- }
- }
- } while (runNextTestSet(state));
- return NULL;
-}
-
-void SimplifyNondegenerate4x4TrianglesThreaded_Test(int& testsRun) {
- SkDebugf("%s\n", __FUNCTION__);
-#ifdef SK_DEBUG
- gDebugMaxWindSum = 2;
- gDebugMaxWindValue = 2;
-#endif
- const char testStr[] = "testNondegenerate";
- initializeTests(testStr, sizeof(testStr));
- int testsStart = testsRun;
- for (int a = 0; a < 15; ++a) {
- int ax = a & 0x03;
- int ay = a >> 2;
- for (int b = a + 1; b < 16; ++b) {
- int bx = b & 0x03;
- int by = b >> 2;
- for (int c = a + 1; c < 16; ++c) {
- if (b == c) {
- continue;
- }
- int cx = c & 0x03;
- int cy = c >> 2;
- if ((bx - ax) * (cy - ay) == (by - ay) * (cx - ax)) {
- continue;
- }
- testsRun += dispatchTest4(testSimplify4x4NondegeneratesMain,
- a, b, c, 0);
- }
- if (!gRunTestsInOneThread) SkDebugf(".");
- }
- if (!gRunTestsInOneThread) SkDebugf("\n%d", a);
- }
- testsRun += waitForCompletion();
- SkDebugf("%s tests=%d total=%d\n", __FUNCTION__, testsRun - testsStart, testsRun);
-}
-
-static void* testSimplify4x4DegeneratesMain(void* data) {
- SkASSERT(data);
- State4& state = *(State4*) data;
- char pathStr[1024];
- bzero(pathStr, sizeof(pathStr));
- do {
- int ax = state.a & 0x03;
- int ay = state.a >> 2;
- int bx = state.b & 0x03;
- int by = state.b >> 2;
- int cx = state.c & 0x03;
- int cy = state.c >> 2;
- for (int d = 0; d < 16; ++d) {
- int dx = d & 0x03;
- int dy = d >> 2;
- for (int e = d ; e < 16; ++e) {
- int ex = e & 0x03;
- int ey = e >> 2;
- for (int f = d ; f < 16; ++f) {
- int fx = f & 0x03;
- int fy = f >> 2;
- if (state.d && (ex - dx) * (fy - dy)
- != (ey - dy) * (fx - dx)) {
- continue;
- }
- SkPath path, out;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(ax, ay);
- path.lineTo(bx, by);
- path.lineTo(cx, cy);
- path.close();
- path.moveTo(dx, dy);
- path.lineTo(ex, ey);
- path.lineTo(fx, fy);
- path.close();
- if (1) {
- char* str = pathStr;
- str += sprintf(str, " path.moveTo(%d, %d);\n", ax, ay);
- str += sprintf(str, " path.lineTo(%d, %d);\n", bx, by);
- str += sprintf(str, " path.lineTo(%d, %d);\n", cx, cy);
- str += sprintf(str, " path.close();\n");
- str += sprintf(str, " path.moveTo(%d, %d);\n", dx, dy);
- str += sprintf(str, " path.lineTo(%d, %d);\n", ex, ey);
- str += sprintf(str, " path.lineTo(%d, %d);\n", fx, fy);
- str += sprintf(str, " path.close();\n");
- }
- outputProgress(state, pathStr, SkPath::kWinding_FillType);
- testSimplifyx(path, false, out, state, pathStr);
- state.testsRun++;
- path.setFillType(SkPath::kEvenOdd_FillType);
- outputProgress(state, pathStr, SkPath::kEvenOdd_FillType);
- testSimplifyx(path, true, out, state, pathStr);
- state.testsRun++;
- }
- }
- }
- } while (runNextTestSet(state));
- return NULL;
-}
-
-void SimplifyDegenerate4x4TrianglesThreaded_Test(int& testsRun) {
- SkDebugf("%s\n", __FUNCTION__);
-#ifdef SK_DEBUG
- gDebugMaxWindSum = 2;
- gDebugMaxWindValue = 2;
-#endif
- const char testStr[] = "testDegenerate";
- initializeTests(testStr, sizeof(testStr));
- int testsStart = testsRun;
- for (int a = 0; a < 16; ++a) {
- int ax = a & 0x03;
- int ay = a >> 2;
- for (int b = a ; b < 16; ++b) {
- int bx = b & 0x03;
- int by = b >> 2;
- for (int c = a ; c < 16; ++c) {
- int cx = c & 0x03;
- int cy = c >> 2;
- bool abcIsATriangle = (bx - ax) * (cy - ay) != (by - ay) * (cx - ax);
- testsRun += dispatchTest4(testSimplify4x4DegeneratesMain,
- a, b, c, abcIsATriangle);
- }
- if (!gRunTestsInOneThread) SkDebugf(".");
- }
- if (!gRunTestsInOneThread) SkDebugf("\n%d", a);
- }
- testsRun += waitForCompletion();
- SkDebugf("%s tests=%d total=%d\n", __FUNCTION__, testsRun - testsStart, testsRun);
-}
diff --git a/experimental/Intersection/EdgeWalkerPolygons_Mismatches.cpp b/experimental/Intersection/EdgeWalkerPolygons_Mismatches.cpp
deleted file mode 100644
index a20e2e64a7..0000000000
--- a/experimental/Intersection/EdgeWalkerPolygons_Mismatches.cpp
+++ /dev/null
@@ -1,1622 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "EdgeWalker_Test.h"
-#include "Intersection_Tests.h"
-#include "SkBitmap.h"
-
-// edges that didn't match
-struct misMatch {
- SkPath::FillType fType;
- int a, b, c, d, e, f, g, h;
-} misMatches[] = {
-/*
-___________________________________|___________________________________
-_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx__|_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx__
-__xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx___|__xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx___
-__xxxxxxxxxxxxxxxxxxxxxxxxxxxx_____|__xxxxxxxxxxxxxxxxxxxxxxxxxxxx_____
-___xxxxxxxxxx__xxxxxxxxxxxxxx______|___xxxxxxxxxx__xxxxxxxxxxxxxx______
-___xxxxxxx______xxxxxxxxxxx________|___xxxxxxx______xxxxxxxxxxx________
-____xxx__________xxxxxxxxx_________|____xxx__________xxxxxxxxx_________
-____x_____________xxxxxxx__________|____x_____________xxxxxxx__________
-__xx_______________xxxx____________|__xxx______________xxxx____________
-___xx_______________xx_____________|___xx_______________xx_____________
-____________________x______________|____________________x______________
-______x____________xxx_____________|______x____________xxx_____________
-______xxx_________xxxxx____________|______xxx_________xxxxx____________
-_______xxxx_____xxxxxxxx___________|_______xxxx_____xxxxxxxx___________
-_______xxxxxx__xxxxxxxxx___________|_______xxxxxx__xxxxxxxxxx__________
-________xxxxx__xxxxxxxxxx__________|________xxxxx__xxxxxxxxxx__________
-________xxxx_____xxxxxxxxx_________|________xxxx_____xxxxxxxxx_________
-_________xxx_______xxxxxxxx________|_________xxx_______xxxxxxxx________
-_________xxx_________xxxxxxx_______|_________xxx_________xxxxxxx_______
-__________xx____________xxxxx______|__________xx____________xxxxx______
-__________xx______________xxxx_____|__________xx______________xxxx_____
-___________x________________xxx____|___________x________________xxx____
-___________x__________________xx___|___________x__________________xx___
-___________x____________________x__|___________x____________________x__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kWinding_FillType, 0, 3, 9, 13, 1, 2, 4, 15 },
-/*
-___________________________________|___________________________________
-_xxxxxxxxxxx_________xxxxxxxxxxxx__|_xxxxxxxxxxx_________xxxxxxxxxxxx__
-__xxxxxxxxxxx______xxxxxxxxxxxxx___|__xxxxxxxxxxx______xxxxxxxxxxxxx___
-__xxxxxxxxxxxx__xxxxxxxxxxxxxx_____|__xxxxxxxxxxxx__xxxxxxxxxxxxxx_____
-___xxxxxxxxxx__xxxxxxxxxxxxxx______|___xxxxxxxxxx__xxxxxxxxxxxxxx______
-___xxxxxxx______xxxxxxxxxxx________|___xxxxxxx______xxxxxxxxxxx________
-____xxx__________xxxxxxxxx_________|____xxx__________xxxxxxxxx_________
-____x_____________xxxxxxx__________|____x_____________xxxxxxx__________
-__xx_______________xxxx____________|__xxx______________xxxx____________
-___xx_______________xx_____________|___xx_______________xx_____________
-____________________x______________|____________________x______________
-______x____________xxx_____________|______x____________xxx_____________
-______xxx_________xxxxx____________|______xxx_________xxxxx____________
-_______xxxx_____xxxxxxxx___________|_______xxxx_____xxxxxxxx___________
-_______xxxxxx__xxxxxxxxx___________|_______xxxxxx__xxxxxxxxxx__________
-________xxxxx__xxxxxxxxxx__________|________xxxxx__xxxxxxxxxx__________
-________xxxx_____xxxxxxxxx_________|________xxxx_____xxxxxxxxx_________
-_________xxx_______xxxxxxxx________|_________xxx_______xxxxxxxx________
-_________xxx_________xxxxxxx_______|_________xxx_________xxxxxxx_______
-__________xx____________xxxxx______|__________xx____________xxxxx______
-__________xx______________xxxx_____|__________xx______________xxxx_____
-___________x________________xxx____|___________x________________xxx____
-___________x__________________xx___|___________x__________________xx___
-___________x____________________x__|___________x____________________x__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kEvenOdd_FillType, 0, 3, 9, 13, 1, 2, 4, 15 },
-/*
-___________________________________|___________________________________
-_x__________xxxxxxxxx______________|_x__________xxxxxxxxx______________
-__xxx________xxxxxx________________|__xxx________xxxxxx________________
-__xxxxxx______xx___________________|__xxxxxx______xx___________________
-___xxxxxxxx__xx____________________|___xxxxxxxx__xx____________________
-___xxxxxxx____xx___________________|___xxxxxxx____xx___________________
-____xxx_________x__________________|____xxx_________x__________________
-____x_____________x________________|____x_____________x________________
-__xx_______________xxx_____________|__xxx______________xxx_____________
-___xx_______________xx_____________|___xx_______________xx_____________
-____________________x______________|____________________x______________
-______x____________xxx_____________|______x____________xxx_____________
-______xxx_________xxxxx____________|______xxx_________xxxxx____________
-_______xxxx_____xxxxxxxx___________|_______xxxx_____xxxxxxxx___________
-_______xxxxxx__xxxxxxxxx___________|_______xxxxxx__xxxxxxxxxx__________
-________xxxxx__xxxxxxxxxx__________|________xxxxx__xxxxxxxxxx__________
-________xxxx_____xxxxxxxxx_________|________xxxx_____xxxxxxxxx_________
-_________xxx_______xxxxxxxx________|_________xxx_______xxxxxxxx________
-_________xxx_________xxxxxxx_______|_________xxx_________xxxxxxx_______
-__________xx____________xxxxx______|__________xx____________xxxxx______
-__________xx______________xxxx_____|__________xx______________xxxx_____
-___________x________________xxx____|___________x________________xxx____
-___________x__________________xx___|___________x__________________xx___
-___________x____________________x__|___________x____________________x__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kWinding_FillType, 0, 6, 9, 13, 1, 2, 4, 15 },
-/*
-___________________________________|___________________________________
-_x__________xxxxxxxxx______________|_x__________xxxxxxxxx______________
-__xxx________xxxxxx________________|__xxx________xxxxxx________________
-__xxxxxx______xx___________________|__xxxxxx______xx___________________
-___xxxxxxxx__xx____________________|___xxxxxxxx__xx____________________
-___xxxxxxx____xx___________________|___xxxxxxx____xx___________________
-____xxx_________x__________________|____xxx_________x__________________
-____x_____________x________________|____x_____________x________________
-__xx_______________xxx_____________|__xxx______________xxx_____________
-___xx_______________xx_____________|___xx_______________xx_____________
-____________________x______________|____________________x______________
-______x____________xxx_____________|______x____________xxx_____________
-______xxx_________xxxxx____________|______xxx_________xxxxx____________
-_______xxxx_____xxxxxxxx___________|_______xxxx_____xxxxxxxx___________
-_______xxxxxx__xxxxxxxxx___________|_______xxxxxx__xxxxxxxxxx__________
-________xxxxx__xxxxxxxxxx__________|________xxxxx__xxxxxxxxxx__________
-________xxxx_____xxxxxxxxx_________|________xxxx_____xxxxxxxxx_________
-_________xxx_______xxxxxxxx________|_________xxx_______xxxxxxxx________
-_________xxx_________xxxxxxx_______|_________xxx_________xxxxxxx_______
-__________xx____________xxxxx______|__________xx____________xxxxx______
-__________xx______________xxxx_____|__________xx______________xxxx_____
-___________x________________xxx____|___________x________________xxx____
-___________x__________________xx___|___________x__________________xx___
-___________x____________________x__|___________x____________________x__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kEvenOdd_FillType, 0, 6, 9, 13, 1, 2, 4, 15 },
-/*
-___________________________________|___________________________________
-_xx__________________x_____________|_xx__________________x_____________
-__xxxxx____________xx______________|__xxxxx____________xx______________
-__xxxxxxxxxx____xxxx_______________|__xxxxxxxxxx____xxxx_______________
-___xxxxxxxxxx___xxx________________|___xxxxxxxxxx___xxx________________
-___xxxxxxx_________x_______________|___xxxxxxx_________x_______________
-____xxx___________xxxxxx___________|____xxx___________xxxxxx___________
-____x____________xxxxxxxxxxx_______|____x____________xxxxxxxxxxx_______
-__xx____________xxxxxxxxxxxxxxxxx__|__xxx___________xxxxxxxxxxxxxxxxx__
-__xxx__________xxxxxxxxxxxxxxxx____|__xxx__________xxxxxxxxxxxxxxxx____
-___xx_________xxxxxxxxxxxx_________|___xx_________xxxxxxxxxxxx_________
-_____x_______xxxxxxxxx_____________|_____x_______xxxxxxxxx_____________
-____________xxxxxx_________________|____________xxxxxx_________________
-_______x___xxx_____________________|_______x___xxx_____________________
-_______xx__________________________|_______xx__________________________
-_____xxx_x_________________________|_____xxx_x_________________________
-_xxxxxxxxxxx_______________________|_xxxxxxxxxxx_______________________
-__xxxxx__xx________________________|__xxxxx__xx________________________
-____xx_____________________________|____xx_____________________________
-________xx_________________________|________xx_________________________
-_____x_xxx_________________________|_____x_xxx_________________________
-____x___xxx________________________|____x___xxx________________________
-___x_____xx________________________|___x_____xx________________________
-___________________________________|___________________________________
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kWinding_FillType, 0, 7, 8, 13, 2, 4, 9, 12 },
-/*
-___________________________________|___________________________________
-_xx__________________x_____________|_xx__________________x_____________
-__xxxxx____________xx______________|__xxxxx____________xx______________
-__xxxxxxxxxx____xxxx_______________|__xxxxxxxxxx____xxxx_______________
-___xxxxxxxxxx___xxx________________|___xxxxxxxxxx___xxx________________
-___xxxxxxx_________x_______________|___xxxxxxx_________x_______________
-____xxx___________xxxxxx___________|____xxx___________xxxxxx___________
-____x____________xxxxxxxxxxx_______|____x____________xxxxxxxxxxx_______
-__xx____________xxxxxxxxxxxxxxxxx__|__xxx___________xxxxxxxxxxxxxxxxx__
-__xxx__________xxxxxxxxxxxxxxxx____|__xxx__________xxxxxxxxxxxxxxxx____
-___xx_________xxxxxxxxxxxx_________|___xx_________xxxxxxxxxxxx_________
-_____x_______xxxxxxxxx_____________|_____x_______xxxxxxxxx_____________
-____________xxxxxx_________________|____________xxxxxx_________________
-_______x___xxx_____________________|_______x___xxx_____________________
-_______xx__________________________|_______xx__________________________
-_____xxx_x_________________________|_____xxx_x_________________________
-_xxxxxxxxxxx_______________________|_xxxxxxxxxxx_______________________
-__xxxxx__xx________________________|__xxxxx__xx________________________
-____xx_____________________________|____xx_____________________________
-________xx_________________________|________xx_________________________
-_____x_xxx_________________________|_____x_xxx_________________________
-____x___xxx________________________|____x___xxx________________________
-___x_____xx________________________|___x_____xx________________________
-___________________________________|___________________________________
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kEvenOdd_FillType, 0, 7, 8, 13, 2, 4, 9, 12 },
-/*
-___________________________________|___________________________________
-_x_________x_______________________|_x_________x_______________________
-__x_______xxx______________________|__x_______xxx______________________
-___x____xxxxxx_____________________|___x____xxxxxx_____________________
-____xx_xxxxxxxx____________________|____xx_xxxxxxxx____________________
-_____x_xxxxxxxxx___________________|_____x_xxxxxxxxx___________________
-____xx___xxxxxxxx__________________|____xx___xxxxxxxx__________________
-___xxxx___xxxxxxxx_________________|___xxxx___xxxxxxxx_________________
-_xxxxxxx___xxxxxxxx________________|_xxxxxxx____xxxxxxx________________
-__xxxxxxx____xxxxxxx_______________|__xxxxxxx____xxxxxxx_______________
-___xxxxxxx____xxxxxxx______________|___xxxxxxx____xxxxxxx______________
-_____xxxxxx_____xxxxxx_____________|_____xxxxxx_____xxxxxx_____________
-______xxxxxx_____xxxxxx____________|______xxxxxx_____xxxxxx____________
-________xxxxx______xxxxx___________|________xxxxx______xxxxx___________
-_________xxxxx______xxxx___________|_________xxxxx______xxxx___________
-__________xxxxx______xxxx__________|__________xxxxx______xxxx__________
-____________xxx________xxx_________|____________xxx________xxx_________
-_______________x___________xxxxx___|_______________x___________xxxxx___
-____________________________xxx____|____________________________xxx____
-__________________xx_______________|__________________xx_________x_____
-___________________xxxx_____xx_____|___________________xxxx_____xx_____
-____________________xxxxxx_xxxx____|____________________xxxxxx_xxxx____
-_____________________xxxx____xxx___|_____________________xxxx____xxx___
-______________________xx_______xx__|______________________xx_______xx__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kWinding_FillType, 0, 10, 11, 14, 1, 4, 9, 15 },
-/*
-___________________________________|___________________________________
-_x_________x_______________________|_x_________x_______________________
-__x_______xxx______________________|__x_______xxx______________________
-___x____xxxxxx_____________________|___x____xxxxxx_____________________
-____xx_xxxxxxxx____________________|____xx_xxxxxxxx____________________
-_____x_xxxxxxxxx___________________|_____x_xxxxxxxxx___________________
-____xx___xxxxxxxx__________________|____xx___xxxxxxxx__________________
-___xxxx___xxxxxxxx_________________|___xxxx___xxxxxxxx_________________
-_xxxxxxx___xxxxxxxx________________|_xxxxxxx____xxxxxxx________________
-__xxxxxxx____xxxxxxx_______________|__xxxxxxx____xxxxxxx_______________
-___xxxxxxx____xxxxxxx______________|___xxxxxxx____xxxxxxx______________
-_____xxxxxx_____xxxxxx_____________|_____xxxxxx_____xxxxxx_____________
-______xxxxxx_____xxxxxx____________|______xxxxxx_____xxxxxx____________
-________xxxxx______xxxxx___________|________xxxxx______xxxxx___________
-_________xxxxx______xxxx___________|_________xxxxx______xxxx___________
-__________xxxxx______xxxx__________|__________xxxxx______xxxx__________
-____________xxx________xxx_________|____________xxx________xxx_________
-_______________x___________xxxxx___|_______________x___________xxxxx___
-____________________________xxx____|____________________________xxx____
-__________________xx_______________|__________________xx_________x_____
-___________________xxxx_____xx_____|___________________xxxx_____xx_____
-____________________xxxxxx_xxxx____|____________________xxxxxx_xxxx____
-_____________________xxxx____xxx___|_____________________xxxx____xxx___
-______________________xx_______xx__|______________________xx_______xx__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kEvenOdd_FillType, 0, 10, 11, 14, 1, 4, 9, 15 },
-/*
-___________________________________|___________________________________
-_____________xxxxxxxxxxxxxxxxxxx___|_____________xxxxxxxxxxxxxxxxxxx___
-___________xx___xxxxxxxxxxx________|___________xx___xxxxxxxxxxx________
-___________xxx_____xxxx____________|___________xxx_____xxxx____________
-__________xxxxx____xxx_____________|__________xxxxx____xxx_____________
-__________xxxxx_xxxxxxxx___________|__________xxxxx_xxxxxxxxx__________
-_________xx______xxxxxxxxxx________|_________x_______xxxxxxxxxx________
-______xxx_________xxxxxxxxxxxx_____|______xxx_________xxxxxxxxxxxx_____
-__xxxxxx___________xxxxxxxxxxxxxx__|__xxxxxx___________xxxxxxxxxxxxxx__
-___xxxxx____________xxxxxxxxxxxx___|___xxxxx____________xxxxxxxxxxxx___
-_____xx______________xxxxxxxxx_____|_____xx______________xxxxxxxxx_____
-______________________xxxxxx_______|______________________xxxxxx_______
-_______xx______________xxx_________|_______xx______________xxx_________
-______xxxxx________________________|______xxxxx________________________
-______xxxxxxx_________xx___________|______xxxxxxx_________xxx__________
-_____xxxxxxxxxx____xxxxxx__________|_____xxxxxxxxxx____xxxxxx__________
-_____xxxxxxxxxxxxxxxxxxxxx_________|_____xxxxxxxxxxxxxxxxxxxxx_________
-____xxxxxxxxxxx____xxxxxxxx________|____xxxxxxxxxxx____xxxxxxxx________
-____xxxxxxxxx________xxxxxxx_______|____xxxxxxxxx________xxxxxxx_______
-___xxxxxxxx_____________xxxxx______|___xxxxxxxx_____________xxxxx______
-___xxxxxx_________________xxxx_____|___xxxxxx_________________xxxx_____
-__xxxxx_____________________xxx____|__xxxxx_____________________xxx____
-__xxx_________________________xx___|__xxx_________________________xx___
-_xx_____________________________x__|_xx_____________________________x__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kEvenOdd_FillType, 1, 1, 7, 12, 1, 3, 4, 15 },
-/*
-___________________________________|___________________________________
-_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx__|_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx__
-__xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx___|__xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx___
-__xxxxxxxxxxxxxxxxxxxxxxxxxxxx_____|__xxxxxxxxxxxxxxxxxxxxxxxxxxxx_____
-___xxxxxxxxxx__xxxxxxxxxxxxxx______|___xxxxxxxxxx__xxxxxxxxxxxxxx______
-___xxxxxxx______xxxxxxxxxxx________|___xxxxxxx______xxxxxxxxxxx________
-____xxx__________xxxxxxxxx_________|____xxx__________xxxxxxxxx_________
-____x_____________xxxxxxx__________|____x_____________xxxxxxx__________
-__xx_______________xxxx____________|__xxx______________xxxx____________
-___xx_______________xx_____________|___xx_______________xx_____________
-____________________x______________|____________________x______________
-______x____________xxx_____________|______x____________xxx_____________
-______xxx_________xxxxx____________|______xxx_________xxxxx____________
-_______xxxx_____xxxxxxxx___________|_______xxxx_____xxxxxxxx___________
-_______xxxxxx__xxxxxxxxx___________|_______xxxxxx__xxxxxxxxxx__________
-________xxxxx__xxxxxxxxxx__________|________xxxxx__xxxxxxxxxx__________
-________xxxx_____xxxxxxxxx_________|________xxxx_____xxxxxxxxx_________
-_________xxx_______xxxxxxxx________|_________xxx_______xxxxxxxx________
-_________xxx_________xxxxxxx_______|_________xxx_________xxxxxxx_______
-__________xx____________xxxxx______|__________xx____________xxxxx______
-__________xx______________xxxx_____|__________xx______________xxxx_____
-___________x________________xxx____|___________x________________xxx____
-___________x__________________xx___|___________x__________________xx___
-___________x____________________x__|___________x____________________x__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kWinding_FillType, 1, 2, 4, 15, 0, 3, 9, 13 },
-/*
-___________________________________|___________________________________
-_xxxxxxxxxxx_________xxxxxxxxxxxx__|_xxxxxxxxxxx_________xxxxxxxxxxxx__
-__xxxxxxxxxxx______xxxxxxxxxxxxx___|__xxxxxxxxxxx______xxxxxxxxxxxxx___
-__xxxxxxxxxxxx__xxxxxxxxxxxxxx_____|__xxxxxxxxxxxx__xxxxxxxxxxxxxx_____
-___xxxxxxxxxx__xxxxxxxxxxxxxx______|___xxxxxxxxxx__xxxxxxxxxxxxxx______
-___xxxxxxx______xxxxxxxxxxx________|___xxxxxxx______xxxxxxxxxxx________
-____xxx__________xxxxxxxxx_________|____xxx__________xxxxxxxxx_________
-____x_____________xxxxxxx__________|____x_____________xxxxxxx__________
-__xx_______________xxxx____________|__xxx______________xxxx____________
-___xx_______________xx_____________|___xx_______________xx_____________
-____________________x______________|____________________x______________
-______x____________xxx_____________|______x____________xxx_____________
-______xxx_________xxxxx____________|______xxx_________xxxxx____________
-_______xxxx_____xxxxxxxx___________|_______xxxx_____xxxxxxxx___________
-_______xxxxxx__xxxxxxxxx___________|_______xxxxxx__xxxxxxxxxx__________
-________xxxxx__xxxxxxxxxx__________|________xxxxx__xxxxxxxxxx__________
-________xxxx_____xxxxxxxxx_________|________xxxx_____xxxxxxxxx_________
-_________xxx_______xxxxxxxx________|_________xxx_______xxxxxxxx________
-_________xxx_________xxxxxxx_______|_________xxx_________xxxxxxx_______
-__________xx____________xxxxx______|__________xx____________xxxxx______
-__________xx______________xxxx_____|__________xx______________xxxx_____
-___________x________________xxx____|___________x________________xxx____
-___________x__________________xx___|___________x__________________xx___
-___________x____________________x__|___________x____________________x__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kEvenOdd_FillType, 1, 2, 4, 15, 0, 3, 9, 13 },
-/*
-___________________________________|___________________________________
-_x__________xxxxxxxxx______________|_x__________xxxxxxxxx______________
-__xxx________xxxxxx________________|__xxx________xxxxxx________________
-__xxxxxx______xx___________________|__xxxxxx______xx___________________
-___xxxxxxxx__xx____________________|___xxxxxxxx__xx____________________
-___xxxxxxx____xx___________________|___xxxxxxx____xx___________________
-____xxx_________x__________________|____xxx_________x__________________
-____x_____________x________________|____x_____________x________________
-__xx_______________xxx_____________|__xxx______________xxx_____________
-___xx_______________xx_____________|___xx_______________xx_____________
-____________________x______________|____________________x______________
-______x____________xxx_____________|______x____________xxx_____________
-______xxx_________xxxxx____________|______xxx_________xxxxx____________
-_______xxxx_____xxxxxxxx___________|_______xxxx_____xxxxxxxx___________
-_______xxxxxx__xxxxxxxxx___________|_______xxxxxx__xxxxxxxxxx__________
-________xxxxx__xxxxxxxxxx__________|________xxxxx__xxxxxxxxxx__________
-________xxxx_____xxxxxxxxx_________|________xxxx_____xxxxxxxxx_________
-_________xxx_______xxxxxxxx________|_________xxx_______xxxxxxxx________
-_________xxx_________xxxxxxx_______|_________xxx_________xxxxxxx_______
-__________xx____________xxxxx______|__________xx____________xxxxx______
-__________xx______________xxxx_____|__________xx______________xxxx_____
-___________x________________xxx____|___________x________________xxx____
-___________x__________________xx___|___________x__________________xx___
-___________x____________________x__|___________x____________________x__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kWinding_FillType, 1, 2, 4, 15, 0, 6, 9, 13 },
-/*
-___________________________________|___________________________________
-_x__________xxxxxxxxx______________|_x__________xxxxxxxxx______________
-__xxx________xxxxxx________________|__xxx________xxxxxx________________
-__xxxxxx______xx___________________|__xxxxxx______xx___________________
-___xxxxxxxx__xx____________________|___xxxxxxxx__xx____________________
-___xxxxxxx____xx___________________|___xxxxxxx____xx___________________
-____xxx_________x__________________|____xxx_________x__________________
-____x_____________x________________|____x_____________x________________
-__xx_______________xxx_____________|__xxx______________xxx_____________
-___xx_______________xx_____________|___xx_______________xx_____________
-____________________x______________|____________________x______________
-______x____________xxx_____________|______x____________xxx_____________
-______xxx_________xxxxx____________|______xxx_________xxxxx____________
-_______xxxx_____xxxxxxxx___________|_______xxxx_____xxxxxxxx___________
-_______xxxxxx__xxxxxxxxx___________|_______xxxxxx__xxxxxxxxxx__________
-________xxxxx__xxxxxxxxxx__________|________xxxxx__xxxxxxxxxx__________
-________xxxx_____xxxxxxxxx_________|________xxxx_____xxxxxxxxx_________
-_________xxx_______xxxxxxxx________|_________xxx_______xxxxxxxx________
-_________xxx_________xxxxxxx_______|_________xxx_________xxxxxxx_______
-__________xx____________xxxxx______|__________xx____________xxxxx______
-__________xx______________xxxx_____|__________xx______________xxxx_____
-___________x________________xxx____|___________x________________xxx____
-___________x__________________xx___|___________x__________________xx___
-___________x____________________x__|___________x____________________x__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kEvenOdd_FillType, 1, 2, 4, 15, 0, 6, 9, 13 },
-/*
-___________________________________|___________________________________
-_______________________xxxxxxxxx___|_______________________xxxxxxxxx___
-___________xx____________xx________|___________xx____________xx________
-___________xxx_________xxx_________|___________xxx_________xxx_________
-__________xxxxx____xxxxxxxxx_______|__________xxxxx____xxxxxxxxx_______
-__________xxxxx_xxxxxxxxxxxxx______|__________xxxxx_xxxxxxxxxxxxx______
-_________xx______xxxxxxxxxxxxx_____|_________x_______xxxxxxxxxxxxx_____
-______xxx_________xxxxxxxxxxxxxx___|______xxx_________xxxxxxxxxxxxxx___
-__xxxxxx___________xxxxxxxxxxxxxx__|__xxxxxx___________xxxxxxxxxxxxxx__
-___xxxxx____________xxxxxxxxxxxx___|___xxxxx____________xxxxxxxxxxxx___
-_____xx______________xxxxxxxxx_____|_____xx______________xxxxxxxxx_____
-______________________xxxxxx_______|______________________xxxxxx_______
-_______xx______________xxx_________|_______xx______________xxx_________
-______xxxxx________________________|______xxxxx________________________
-______xxxxxxx_________xx___________|______xxxxxxx_________xxx__________
-_____xxxxxxxxxx____xxxxxx__________|_____xxxxxxxxxx____xxxxxx__________
-_____xxxxxxxxxxxxxxxxxxxxx_________|_____xxxxxxxxxxxxxxxxxxxxx_________
-____xxxxxxxxxxx____xxxxxxxx________|____xxxxxxxxxxx____xxxxxxxx________
-____xxxxxxxxx________xxxxxxx_______|____xxxxxxxxx________xxxxxxx_______
-___xxxxxxxx_____________xxxxx______|___xxxxxxxx_____________xxxxx______
-___xxxxxx_________________xxxx_____|___xxxxxx_________________xxxx_____
-__xxxxx_____________________xxx____|__xxxxx_____________________xxx____
-__xxx_________________________xx___|__xxx_________________________xx___
-_xx_____________________________x__|_xx_____________________________x__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kEvenOdd_FillType, 1, 2, 7, 12, 1, 3, 4, 15 },
-/*
-___________________________________|___________________________________
-_____________xxxxxxxxxxxxxxxxxxx___|_____________xxxxxxxxxxxxxxxxxxx___
-___________xx___xxxxxxxxxxx________|___________xx___xxxxxxxxxxx________
-___________xxx_____xxxx____________|___________xxx_____xxxx____________
-__________xxxxx____xxx_____________|__________xxxxx____xxx_____________
-__________xxxxx_xxxxxxxx___________|__________xxxxx_xxxxxxxxx__________
-_________xx______xxxxxxxxxx________|_________x_______xxxxxxxxxx________
-______xxx_________xxxxxxxxxxxx_____|______xxx_________xxxxxxxxxxxx_____
-__xxxxxx___________xxxxxxxxxxxxxx__|__xxxxxx___________xxxxxxxxxxxxxx__
-___xxxxx____________xxxxxxxxxxxx___|___xxxxx____________xxxxxxxxxxxx___
-_____xx______________xxxxxxxxx_____|_____xx______________xxxxxxxxx_____
-______________________xxxxxx_______|______________________xxxxxx_______
-_______xx______________xxx_________|_______xx______________xxx_________
-______xxxxx________________________|______xxxxx________________________
-______xxxxxxx_________xx___________|______xxxxxxx_________xxx__________
-_____xxxxxxxxxx____xxxxxx__________|_____xxxxxxxxxx____xxxxxx__________
-_____xxxxxxxxxxxxxxxxxxxxx_________|_____xxxxxxxxxxxxxxxxxxxxx_________
-____xxxxxxxxxxx____xxxxxxxx________|____xxxxxxxxxxx____xxxxxxxx________
-____xxxxxxxxx________xxxxxxx_______|____xxxxxxxxx________xxxxxxx_______
-___xxxxxxxx_____________xxxxx______|___xxxxxxxx_____________xxxxx______
-___xxxxxx_________________xxxx_____|___xxxxxx_________________xxxx_____
-__xxxxx_____________________xxx____|__xxxxx_____________________xxx____
-__xxx_________________________xx___|__xxx_________________________xx___
-_xx_____________________________x__|_xx_____________________________x__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kEvenOdd_FillType, 1, 3, 4, 15, 1, 1, 7, 12 },
-/*
-___________________________________|___________________________________
-_______________________xxxxxxxxx___|_______________________xxxxxxxxx___
-___________xx____________xx________|___________xx____________xx________
-___________xxx_________xxx_________|___________xxx_________xxx_________
-__________xxxxx____xxxxxxxxx_______|__________xxxxx____xxxxxxxxx_______
-__________xxxxx_xxxxxxxxxxxxx______|__________xxxxx_xxxxxxxxxxxxx______
-_________xx______xxxxxxxxxxxxx_____|_________x_______xxxxxxxxxxxxx_____
-______xxx_________xxxxxxxxxxxxxx___|______xxx_________xxxxxxxxxxxxxx___
-__xxxxxx___________xxxxxxxxxxxxxx__|__xxxxxx___________xxxxxxxxxxxxxx__
-___xxxxx____________xxxxxxxxxxxx___|___xxxxx____________xxxxxxxxxxxx___
-_____xx______________xxxxxxxxx_____|_____xx______________xxxxxxxxx_____
-______________________xxxxxx_______|______________________xxxxxx_______
-_______xx______________xxx_________|_______xx______________xxx_________
-______xxxxx________________________|______xxxxx________________________
-______xxxxxxx_________xx___________|______xxxxxxx_________xxx__________
-_____xxxxxxxxxx____xxxxxx__________|_____xxxxxxxxxx____xxxxxx__________
-_____xxxxxxxxxxxxxxxxxxxxx_________|_____xxxxxxxxxxxxxxxxxxxxx_________
-____xxxxxxxxxxx____xxxxxxxx________|____xxxxxxxxxxx____xxxxxxxx________
-____xxxxxxxxx________xxxxxxx_______|____xxxxxxxxx________xxxxxxx_______
-___xxxxxxxx_____________xxxxx______|___xxxxxxxx_____________xxxxx______
-___xxxxxx_________________xxxx_____|___xxxxxx_________________xxxx_____
-__xxxxx_____________________xxx____|__xxxxx_____________________xxx____
-__xxx_________________________xx___|__xxx_________________________xx___
-_xx_____________________________x__|_xx_____________________________x__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kEvenOdd_FillType, 1, 3, 4, 15, 1, 2, 7, 12 },
-/*
-___________________________________|___________________________________
-________________________________xx_|________________________________xx_
-___________xx______________xxxxxxx_|___________xx______________xxxxxxx_
-___________xxx_________xxxxxxxxxxx_|___________xxx_________xxxxxxxxxxx_
-__________xxxxx____xxxxxxxxxxxxxxx_|__________xxxxx____xxxxxxxxxxxxxxx_
-__________xxxxx_xxxxxxxxxxxxxxxxxx_|__________xxxxx_xxxxxxxxxxxxxxxxxx_
-_________xx______xxxxxxxxxxxxxxxxx_|_________x_______xxxxxxxxxxxxxxxxx_
-______xxx_________xxxxxxxxxxxxxxxx_|______xxx_________xxxxxxxxxxxxxxxx_
-__xxxxxx___________xxxxxxxxxxxxxxx_|__xxxxxx___________xxxxxxxxxxxxxxx_
-___xxxxx____________xxxxxxxxxxxx___|___xxxxx____________xxxxxxxxxxxx___
-_____xx______________xxxxxxxxx_____|_____xx______________xxxxxxxxx_____
-______________________xxxxxx_______|______________________xxxxxx_______
-_______xx______________xxx_________|_______xx______________xxx_________
-______xxxxx________________________|______xxxxx________________________
-______xxxxxxx_________xx___________|______xxxxxxx_________xxx__________
-_____xxxxxxxxxx____xxxxxx__________|_____xxxxxxxxxx____xxxxxx__________
-_____xxxxxxxxxxxxxxxxxxxxx_________|_____xxxxxxxxxxxxxxxxxxxxx_________
-____xxxxxxxxxxx____xxxxxxxx________|____xxxxxxxxxxx____xxxxxxxx________
-____xxxxxxxxx________xxxxxxx_______|____xxxxxxxxx________xxxxxxx_______
-___xxxxxxxx_____________xxxxx______|___xxxxxxxx_____________xxxxx______
-___xxxxxx_________________xxxx_____|___xxxxxx_________________xxxx_____
-__xxxxx_____________________xxx____|__xxxxx_____________________xxx____
-__xxx_________________________xx___|__xxx_________________________xx___
-_xx_____________________________x__|_xx_____________________________x__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kEvenOdd_FillType, 1, 3, 4, 15, 1, 3, 7, 12 },
-/*
-___________________________________|___________________________________
-_____________xxxxxxxxxxxxxxxxxxx___|_____________xxxxxxxxxxxxxxxxxxx___
-___________xx___xxxxxxxxxxx________|___________xx___xxxxxxxxxxx________
-___________xxx_____xxxx____________|___________xxx_____xxxx____________
-__________xxxxx____xxx_____________|__________xxxxx____xxx_____________
-__________xxxxx_xxxxxxxx___________|__________xxxxx_xxxxxxxxx__________
-_________xx______xxxxxxxxxx________|_________x_______xxxxxxxxxx________
-______xxx_________xxxxxxxxxxxx_____|______xxx_________xxxxxxxxxxxx_____
-__xxxxxx___________xxxxxxxxxxxxxx__|__xxxxxx___________xxxxxxxxxxxxxx__
-___xxxxx____________xxxxxxxxxxxx___|___xxxxx____________xxxxxxxxxxxx___
-_____xx______________xxxxxxxxx_____|_____xx______________xxxxxxxxx_____
-______________________xxxxxx_______|______________________xxxxxx_______
-_______xx______________xxx_________|_______xx______________xxx_________
-______xxxxx________________________|______xxxxx________________________
-______xxxxxxx_________xx___________|______xxxxxxx_________xxx__________
-_____xxxxxxxxxx____xxxxxx__________|_____xxxxxxxxxx____xxxxxx__________
-_____xxxxxxxxxxxxxxxxxxxxx_________|_____xxxxxxxxxxxxxxxxxxxxx_________
-____xxxxxxxxxxx____xxxxxxxx________|____xxxxxxxxxxx____xxxxxxxx________
-____xxxxxxxxx________xxxxxxx_______|____xxxxxxxxx________xxxxxxx_______
-___xxxxxxxx_____________xxxxx______|___xxxxxxxx_____________xxxxx______
-___xxxxxx_________________xxxx_____|___xxxxxx_________________xxxx_____
-__xxxxx_____________________xxx____|__xxxxx_____________________xxx____
-__xxx_________________________xx___|__xxx_________________________xx___
-_xx_____________________________x__|_xx_____________________________x__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kEvenOdd_FillType, 1, 3, 4, 15, 1, 7, 7, 12 },
-/*
-___________________________________|___________________________________
-_____________xxxxxxxxxxxxxxxxxxx___|_____________xxxxxxxxxxxxxxxxxxx___
-___________xx___xxxxxxxxxxx________|___________xx___xxxxxxxxxxx________
-___________xxx_____xxxx____________|___________xxx_____xxxx____________
-__________xxxxx____xxx_____________|__________xxxxx____xxx_____________
-__________xxxxx_xxxxxxxx___________|__________xxxxx_xxxxxxxxx__________
-_________xx______xxxxxxxxxx________|_________x_______xxxxxxxxxx________
-______xxx_________xxxxxxxxxxxx_____|______xxx_________xxxxxxxxxxxx_____
-__xxxxxx___________xxxxxxxxxxxxxx__|__xxxxxx___________xxxxxxxxxxxxxx__
-___xxxxx____________xxxxxxxxxxxx___|___xxxxx____________xxxxxxxxxxxx___
-_____xx______________xxxxxxxxx_____|_____xx______________xxxxxxxxx_____
-______________________xxxxxx_______|______________________xxxxxx_______
-_______xx______________xxx_________|_______xx______________xxx_________
-______xxxxx________________________|______xxxxx________________________
-______xxxxxxx_________xx___________|______xxxxxxx_________xxx__________
-_____xxxxxxxxxx____xxxxxx__________|_____xxxxxxxxxx____xxxxxx__________
-_____xxxxxxxxxxxxxxxxxxxxx_________|_____xxxxxxxxxxxxxxxxxxxxx_________
-____xxxxxxxxxxx____xxxxxxxx________|____xxxxxxxxxxx____xxxxxxxx________
-____xxxxxxxxx________xxxxxxx_______|____xxxxxxxxx________xxxxxxx_______
-___xxxxxxxx_____________xxxxx______|___xxxxxxxx_____________xxxxx______
-___xxxxxx_________________xxxx_____|___xxxxxx_________________xxxx_____
-__xxxxx_____________________xxx____|__xxxxx_____________________xxx____
-__xxx_________________________xx___|__xxx_________________________xx___
-_xx_____________________________x__|_xx_____________________________x__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kEvenOdd_FillType, 1, 3, 4, 15, 1, 7, 12, 12 },
-/*
-___________________________________|___________________________________
-________________________________xx_|________________________________xx_
-___________xx______________xxxxxxx_|___________xx______________xxxxxxx_
-___________xxx_________xxxxxxxxxxx_|___________xxx_________xxxxxxxxxxx_
-__________xxxxx____xxxxxxxxxxxxxxx_|__________xxxxx____xxxxxxxxxxxxxxx_
-__________xxxxx_xxxxxxxxxxxxxxxxxx_|__________xxxxx_xxxxxxxxxxxxxxxxxx_
-_________xx______xxxxxxxxxxxxxxxxx_|_________x_______xxxxxxxxxxxxxxxxx_
-______xxx_________xxxxxxxxxxxxxxxx_|______xxx_________xxxxxxxxxxxxxxxx_
-__xxxxxx___________xxxxxxxxxxxxxxx_|__xxxxxx___________xxxxxxxxxxxxxxx_
-___xxxxx____________xxxxxxxxxxxx___|___xxxxx____________xxxxxxxxxxxx___
-_____xx______________xxxxxxxxx_____|_____xx______________xxxxxxxxx_____
-______________________xxxxxx_______|______________________xxxxxx_______
-_______xx______________xxx_________|_______xx______________xxx_________
-______xxxxx________________________|______xxxxx________________________
-______xxxxxxx_________xx___________|______xxxxxxx_________xxx__________
-_____xxxxxxxxxx____xxxxxx__________|_____xxxxxxxxxx____xxxxxx__________
-_____xxxxxxxxxxxxxxxxxxxxx_________|_____xxxxxxxxxxxxxxxxxxxxx_________
-____xxxxxxxxxxx____xxxxxxxx________|____xxxxxxxxxxx____xxxxxxxx________
-____xxxxxxxxx________xxxxxxx_______|____xxxxxxxxx________xxxxxxx_______
-___xxxxxxxx_____________xxxxx______|___xxxxxxxx_____________xxxxx______
-___xxxxxx_________________xxxx_____|___xxxxxx_________________xxxx_____
-__xxxxx_____________________xxx____|__xxxxx_____________________xxx____
-__xxx_________________________xx___|__xxx_________________________xx___
-_xx_____________________________x__|_xx_____________________________x__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kEvenOdd_FillType, 1, 3, 7, 12, 1, 3, 4, 15 },
-/*
-___________________________________|___________________________________
-____________xxxxxxxxxxxxxxxxxxxxx__|____________xxxxxxxxxxxxxxxxxxxxx__
-_____________xxxxxxxxxxxxxxxxxxx___|_____________xxxxxxxxxxxxxxxxxxx___
-______________xxxxxxxxx_xxxxxx_____|______________xxxxxxxxx_xxxxxx_____
-_______________xxxxxxxx_xxxxx______|_______________xxxxxxxx_xxxxx______
-________________xxxxxxx__xx________|________________xxxxxxx__xx________
-_________________xxxxxx__x_________|_________________xxxxxx__x_________
-__________________xxxxx__x_________|__________________xxxxx__x_________
-___________________xxxxxxx_________|___________________xxxxxxx_________
-____________________x_xxxxx________|____________________x_xxxxx________
-__________________xx_xxxxxx________|__________________xx_xxxxxx________
-_______________xxxx___xxxxxx_______|_______________xxxx___xxxxxx_______
-____________xxxxxx_____xxxxx_______|____________xxxxxx_____xxxxx_______
-_________xxxxxxx________xxxxx______|_________xxxxxxx________xxxxx______
-_______xxxxxxxx_________xxxxx______|_______xxxxxxxx__________xxxx______
-____xxxxxxxxx____________xxxxx_____|____xxxxxxxxx____________xxxxx_____
-_xxxxxxxxxxx______________xxxx_____|_xxxxxxxxxxx______________xxxx_____
-_____xxxxxx________________xxx_____|_____xxxxxx________________xxx_____
-____________________________xxx____|____________________________xxx____
-________xxxxx________________xx____|________xxxxx________________xx____
-______xxxxxxxxxxxx____________xx___|______xxxxxxxxxxxx____________xx___
-_____xxxxxxxxxxxxxxxxx_________x___|_____xxxxxxxxxxxxxxxxx_________x___
-____xxxxxxxxxxxxxxxxxxxxxx______x__|____xxxxxxxxxxxxxxxxxxxxxx______x__
-__xxxxxxxxxxxxxxxxxxxxxxxxxxxx_____|__xxxxxxxxxxxxxxxxxxxxxxxxxxxx_____
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kEvenOdd_FillType, 1, 3, 12, 15, 2, 6, 8, 15 },
-/*
-___________________________________|___________________________________
-_x_________x_______________________|_x_________x_______________________
-__x_______xxx______________________|__x_______xxx______________________
-___x____xxxxxx_____________________|___x____xxxxxx_____________________
-____xx_xxxxxxxx____________________|____xx_xxxxxxxx____________________
-_____x_xxxxxxxxx___________________|_____x_xxxxxxxxx___________________
-____xx___xxxxxxxx__________________|____xx___xxxxxxxx__________________
-___xxxx___xxxxxxxx_________________|___xxxx___xxxxxxxx_________________
-_xxxxxxx___xxxxxxxx________________|_xxxxxxx____xxxxxxx________________
-__xxxxxxx____xxxxxxx_______________|__xxxxxxx____xxxxxxx_______________
-___xxxxxxx____xxxxxxx______________|___xxxxxxx____xxxxxxx______________
-_____xxxxxx_____xxxxxx_____________|_____xxxxxx_____xxxxxx_____________
-______xxxxxx_____xxxxxx____________|______xxxxxx_____xxxxxx____________
-________xxxxx______xxxxx___________|________xxxxx______xxxxx___________
-_________xxxxx______xxxx___________|_________xxxxx______xxxx___________
-__________xxxxx______xxxx__________|__________xxxxx______xxxx__________
-____________xxx________xxx_________|____________xxx________xxx_________
-_______________x___________xxxxx___|_______________x___________xxxxx___
-____________________________xxx____|____________________________xxx____
-__________________xx_______________|__________________xx_________x_____
-___________________xxxx_____xx_____|___________________xxxx_____xx_____
-____________________xxxxxx_xxxx____|____________________xxxxxx_xxxx____
-_____________________xxxx____xxx___|_____________________xxxx____xxx___
-______________________xx_______xx__|______________________xx_______xx__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kWinding_FillType, 1, 4, 9, 15, 0, 10, 11, 14 },
-/*
-___________________________________|___________________________________
-_x_________x_______________________|_x_________x_______________________
-__x_______xxx______________________|__x_______xxx______________________
-___x____xxxxxx_____________________|___x____xxxxxx_____________________
-____xx_xxxxxxxx____________________|____xx_xxxxxxxx____________________
-_____x_xxxxxxxxx___________________|_____x_xxxxxxxxx___________________
-____xx___xxxxxxxx__________________|____xx___xxxxxxxx__________________
-___xxxx___xxxxxxxx_________________|___xxxx___xxxxxxxx_________________
-_xxxxxxx___xxxxxxxx________________|_xxxxxxx____xxxxxxx________________
-__xxxxxxx____xxxxxxx_______________|__xxxxxxx____xxxxxxx_______________
-___xxxxxxx____xxxxxxx______________|___xxxxxxx____xxxxxxx______________
-_____xxxxxx_____xxxxxx_____________|_____xxxxxx_____xxxxxx_____________
-______xxxxxx_____xxxxxx____________|______xxxxxx_____xxxxxx____________
-________xxxxx______xxxxx___________|________xxxxx______xxxxx___________
-_________xxxxx______xxxx___________|_________xxxxx______xxxx___________
-__________xxxxx______xxxx__________|__________xxxxx______xxxx__________
-____________xxx________xxx_________|____________xxx________xxx_________
-_______________x___________xxxxx___|_______________x___________xxxxx___
-____________________________xxx____|____________________________xxx____
-__________________xx_______________|__________________xx_________x_____
-___________________xxxx_____xx_____|___________________xxxx_____xx_____
-____________________xxxxxx_xxxx____|____________________xxxxxx_xxxx____
-_____________________xxxx____xxx___|_____________________xxxx____xxx___
-______________________xx_______xx__|______________________xx_______xx__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kEvenOdd_FillType, 1, 4, 9, 15, 0, 10, 11, 14 },
-/*
-___________________________________|___________________________________
-____________x__________xxxxxxxxxx__|____________x__________xxxxxxxxxx__
-_____________x_________xxxxxxxxx___|_____________x_________xxxxxxxxx___
-______________x_________xxxxxx_____|______________x_________xxxxxx_____
-_______________xx_______xxxxx______|_______________xx_______xxxxx______
-________________xx_______xx________|________________xx_______xx________
-_________________xxx_____x_________|_________________xxx_____x_________
-__________________xxx____x_________|__________________xxx____x_________
-___________________xxx_xxx_________|___________________xxx_xxx_________
-____________________x_xxxxx________|____________________x_xxxxx________
-__________________xx_xxxxxx________|__________________xx_xxxxxx________
-_______________xxxx___xxxxxx_______|_______________xxxx___xxxxxx_______
-____________xxxxxx_____xxxxx_______|____________xxxxxx_____xxxxx_______
-_________xxxxxxx________xxxxx______|_________xxxxxxx________xxxxx______
-_______xxxxxxxx_________xxxxx______|_______xxxxxxxx__________xxxx______
-____xxxxxxxxx____________xxxxx_____|____xxxxxxxxx____________xxxxx_____
-_xxxxxxxxxxx______________xxxx_____|_xxxxxxxxxxx______________xxxx_____
-_____xxxxxx________________xxx_____|_____xxxxxx________________xxx_____
-____________________________xxx____|____________________________xxx____
-________xxxxx________________xx____|________xxxxx________________xx____
-______xxxxxxxxxxxx____________xx___|______xxxxxxxxxxxx____________xx___
-_____xxxxxxxxxxxxxxxxx_________x___|_____xxxxxxxxxxxxxxxxx_________x___
-____xxxxxxxxxxxxxxxxxxxxxx______x__|____xxxxxxxxxxxxxxxxxxxxxx______x__
-__xxxxxxxxxxxxxxxxxxxxxxxxxxxx_____|__xxxxxxxxxxxxxxxxxxxxxxxxxxxx_____
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kEvenOdd_FillType, 1, 6, 8, 15, 2, 3, 12, 15 },
-/*
-___________________________________|___________________________________
-____________x________x_____________|____________x________x_____________
-_____________x_____xx______________|_____________x_____xx______________
-______________x_xxxx_______________|______________x_xxxx_______________
-_____________xx__xx________________|_____________xx__xx________________
-__________xxxxxx__x________________|__________xxxxxx__x________________
-_______xxxxxxxxxx_xx_______________|_______xxxxxxxxxx_xx_______________
-_____xxxxxxxxxxxx_xxx______________|_____xxxxxxxxxxxx_xxx______________
-__xxxxxxxxxxxxxx___xxx_____________|__xxxxxxxxxxxxxx___xxx_____________
-____xxxxxxxxxxx_____xx_____________|____xxxxxxxxxxx_____xx_____________
-________xxxxxx______x______________|________xxxxxx______x______________
-____________x______xxx_____________|____________x______xxx_____________
-____________xxxxx_xxxxx____________|____________xxxxx_xxxxx____________
-___________xxxxx_____xxx___________|___________xxxxx_____xxx___________
-__________xxxxx_________x__________|__________xxxxx____________________
-_________xxxx____________xxxx______|_________xxxx____________xxxx______
-________xxxx______________xxxxxxxx_|________xxxx______________xxxxxxxx_
-_______xxxxxxxx____________xxx_____|_______xxxxxxxx____________xxx_____
-______xxxxxxxxxxx________xxx_______|______xxxxxxxxxxx________xxx_______
-_____xxxxxxxxxxxxxxx_xxxxxxxx______|_____xxxxxxxxxxxxxxx_xxxxxxxx______
-_____xxxxxxxxxxxx______xxxxxxx_____|_____xxxxxxxxxxxx______xxxxxxx_____
-____xxxxxxxxx_____________xxxxx____|____xxxxxxxxx_____________xxxxx____
-___xxxxxx____________________xxx___|___xxxxxx____________________xxx___
-__xx___________________________xx__|__xx___________________________xx__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kWinding_FillType, 1, 6, 9, 15, 2, 4, 11, 12 },
-/*
-___________________________________|___________________________________
-____________x________x_____________|____________x________x_____________
-_____________x_____xx______________|_____________x_____xx______________
-______________x_xxxx_______________|______________x_xxxx_______________
-_____________xx__xx________________|_____________xx__xx________________
-__________xxxxxx__x________________|__________xxxxxx__x________________
-_______xxxxxxxxxx_xx_______________|_______xxxxxxxxxx_xx_______________
-_____xxxxxxxxxxxx_xxx______________|_____xxxxxxxxxxxx_xxx______________
-__xxxxxxxxxxxxxx___xxx_____________|__xxxxxxxxxxxxxx___xxx_____________
-____xxxxxxxxxxx_____xx_____________|____xxxxxxxxxxx_____xx_____________
-________xxxxxx______x______________|________xxxxxx______x______________
-____________x______xxx_____________|____________x______xxx_____________
-____________xxxxx_xxxxx____________|____________xxxxx_xxxxx____________
-___________xxxxx_____xxx___________|___________xxxxx_____xxx___________
-__________xxxxx_________x__________|__________xxxxx____________________
-_________xxxx____________xxxx______|_________xxxx____________xxxx______
-________xxxx______________xxxxxxxx_|________xxxx______________xxxxxxxx_
-_______xxxxxxxx____________xxx_____|_______xxxxxxxx____________xxx_____
-______xxxxxxxxxxx________xxx_______|______xxxxxxxxxxx________xxx_______
-_____xxxxxxxxxxxxxxx_xxxxxxxx______|_____xxxxxxxxxxxxxxx_xxxxxxxx______
-_____xxxxxxxxxxxx______xxxxxxx_____|_____xxxxxxxxxxxx______xxxxxxx_____
-____xxxxxxxxx_____________xxxxx____|____xxxxxxxxx_____________xxxxx____
-___xxxxxx____________________xxx___|___xxxxxx____________________xxx___
-__xx___________________________xx__|__xx___________________________xx__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kEvenOdd_FillType, 1, 6, 9, 15, 2, 4, 11, 12 },
-/*
-___________________________________|___________________________________
-_____________xxxxxxxxxxxxxxxxxxx___|_____________xxxxxxxxxxxxxxxxxxx___
-___________xx___xxxxxxxxxxx________|___________xx___xxxxxxxxxxx________
-___________xxx_____xxxx____________|___________xxx_____xxxx____________
-__________xxxxx____xxx_____________|__________xxxxx____xxx_____________
-__________xxxxx_xxxxxxxx___________|__________xxxxx_xxxxxxxxx__________
-_________xx______xxxxxxxxxx________|_________x_______xxxxxxxxxx________
-______xxx_________xxxxxxxxxxxx_____|______xxx_________xxxxxxxxxxxx_____
-__xxxxxx___________xxxxxxxxxxxxxx__|__xxxxxx___________xxxxxxxxxxxxxx__
-___xxxxx____________xxxxxxxxxxxx___|___xxxxx____________xxxxxxxxxxxx___
-_____xx______________xxxxxxxxx_____|_____xx______________xxxxxxxxx_____
-______________________xxxxxx_______|______________________xxxxxx_______
-_______xx______________xxx_________|_______xx______________xxx_________
-______xxxxx________________________|______xxxxx________________________
-______xxxxxxx_________xx___________|______xxxxxxx_________xxx__________
-_____xxxxxxxxxx____xxxxxx__________|_____xxxxxxxxxx____xxxxxx__________
-_____xxxxxxxxxxxxxxxxxxxxx_________|_____xxxxxxxxxxxxxxxxxxxxx_________
-____xxxxxxxxxxx____xxxxxxxx________|____xxxxxxxxxxx____xxxxxxxx________
-____xxxxxxxxx________xxxxxxx_______|____xxxxxxxxx________xxxxxxx_______
-___xxxxxxxx_____________xxxxx______|___xxxxxxxx_____________xxxxx______
-___xxxxxx_________________xxxx_____|___xxxxxx_________________xxxx_____
-__xxxxx_____________________xxx____|__xxxxx_____________________xxx____
-__xxx_________________________xx___|__xxx_________________________xx___
-_xx_____________________________x__|_xx_____________________________x__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kEvenOdd_FillType, 1, 7, 7, 12, 1, 3, 4, 15 },
-/*
-___________________________________|___________________________________
-____________x____________________x_|____________x____________________x_
-_____________xxx_________________x_|_____________xxx_________________x_
-______________xxxxx_____________xx_|______________xxxxx_____________xx_
-_______________xxxxxxx__________xx_|_______________xxxxxxx__________xx_
-________________xxxxxxxx________xx_|________________xxxxxxxx________xx_
-_________________xxxxxxxxxx____xxx_|_________________xxxxxxxxxx____xxx_
-__________________xxxxxxxxxxxx_xxx_|__________________xxxxxxxxxxxx_xxx_
-___________________xxxxxxxxxxx___x_|___________________xxxxxxxxxxx___x_
-____________________xxxxxxxxxx_xxx_|____________________xxxxxxxxxx_xxx_
-_____________________xxxxx___xxxxx_|_____________________xxxxx___xxxxx_
-_____________________________xxxxx_|_____________________________xxxxx_
-__________________xxxxx_____xxxxxx_|__________________xxxxx_____xxxxxx_
-______________xxxxxxxxxx____xxxxxx_|______________xxxxxxxxxx____xxxxxx_
-__________xxxxxxxxxxxxxx___xxxxxxx_|__________xxxxxxxxxxxxxx___xxxxxxx_
-_____xxxxxxxxxxxxxxxxxxxx__xxxxxxx_|_____xxxxxxxxxxxxxxxxxxxx__xxxxxxx_
-_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_|_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_
-_____xxxxxxxxxxxxxxxxxxxxx_xxxxx___|_____xxxxxxxxxxxxxxxxxxxxx_xxxxx___
-_________xxxxxxxxxxxxxxxx___xxx____|_________xxxxxxxxxxxxxxxx___xxx____
-_____________xxxxxxxxxxxx__________|_____________xxxxxxxxxxxx____x_____
-__________________xxxxxxx___xx_____|__________________xxxxxxx___xx_____
-______________________xx___xxxx____|______________________xx___xxxx____
-________________________x_xxxxxx___|________________________x_xxxxxx___
-_______________________x______xxx__|_______________________x______xxx__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kEvenOdd_FillType, 1, 7, 8, 15, 3, 3, 11, 14 },
-/*
-___________________________________|___________________________________
-____________x___________________x__|____________x___________________x__
-_____________xxx___________xxxxxx__|_____________xxx___________xxxxxx__
-______________xxxxx____xxxxxxxxx___|______________xxxxx____xxxxxxxxx___
-_______________xxxx___xxxxxxxxxx___|_______________xxxx___xxxxxxxxxx___
-_______________x________xxxxxxxx___|_______________x_________xxxxxxx___
-___________xxxxxx__________xxxx____|___________xxxxxx__________xxxx____
-______xxxxxxxxxxxx____________x____|______xxxxxxxxxxxx____________x____
-__xxxxxxxxxxxxxxxxx___________xxx__|__xxxxxxxxxxxxxxxxx___________xxx__
-____xxxxxxxxxxxxxxxx__________x____|____xxxxxxxxxxxxxxxx__________x____
-________xxxxxxxxxxxxx_____xxx______|________xxxxxxxxxxxxx_____xxx______
-____________xxxxxxxxxxxxxxxxx______|_____________xxxxxxxxxxxxxxxx______
-_________________xxxxxxxxxxx_______|_________________xxxxxxxxxxx_______
-______________xxxxxxxxxxxxxx_______|______________xxxxxxxxxxxxxx_______
-__________xxxxxxxxxxxxxx_xx________|__________xxxxxxxxxxxxxxxxx________
-_____xxxxxxxxxxxxxxxxxxxx__xx______|_____xxxxxxxxxxxxxxxxxxxx__xx______
-_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_|_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_
-_____xxxxxxxxxxxxxxxxxxxxx_xxxxx___|_____xxxxxxxxxxxxxxxxxxxxx_xxxxx___
-_________xxxxxxxxxxxxxxxx___xxx____|_________xxxxxxxxxxxxxxxx___xxx____
-_____________xxxxxxxxxxxx__________|_____________xxxxxxxxxxxx____x_____
-__________________xxxxxxx___xx_____|__________________xxxxxxx___xx_____
-______________________xx___xxxx____|______________________xx___xxxx____
-________________________x_xxxxxx___|________________________x_xxxxxx___
-_______________________x______xxx__|_______________________x______xxx__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kWinding_FillType, 1, 7, 8, 15, 3, 4, 11, 14 },
-/*
-___________________________________|___________________________________
-____________x___________________x__|____________x___________________x__
-_____________xxx___________xxxxxx__|_____________xxx___________xxxxxx__
-______________xxxxx____xxxxxxxxx___|______________xxxxx____xxxxxxxxx___
-_______________xxxx___xxxxxxxxxx___|_______________xxxx___xxxxxxxxxx___
-_______________x________xxxxxxxx___|_______________x_________xxxxxxx___
-___________xxxxxx__________xxxx____|___________xxxxxx__________xxxx____
-______xxxxxxxxxxxx____________x____|______xxxxxxxxxxxx____________x____
-__xxxxxxxxxxxxxxxxx___________xxx__|__xxxxxxxxxxxxxxxxx___________xxx__
-____xxxxxxxxxxxxxxxx__________x____|____xxxxxxxxxxxxxxxx__________x____
-________xxxxxxxxxxxxx_____xxx______|________xxxxxxxxxxxxx_____xxx______
-____________xxxxxxxxxxxxxxxxx______|_____________xxxxxxxxxxxxxxxx______
-_________________x_____xxxxx_______|_________________x_____xxxxx_______
-______________xxxxxxx___xxxx_______|______________xxxxxxx___xxxx_______
-__________xxxxxxxxxxxxxx_xx________|__________xxxxxxxxxxxxxxxxx________
-_____xxxxxxxxxxxxxxxxxxxx__xx______|_____xxxxxxxxxxxxxxxxxxxx__xx______
-_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_|_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_
-_____xxxxxxxxxxxxxxxxxxxxx_xxxxx___|_____xxxxxxxxxxxxxxxxxxxxx_xxxxx___
-_________xxxxxxxxxxxxxxxx___xxx____|_________xxxxxxxxxxxxxxxx___xxx____
-_____________xxxxxxxxxxxx__________|_____________xxxxxxxxxxxx____x_____
-__________________xxxxxxx___xx_____|__________________xxxxxxx___xx_____
-______________________xx___xxxx____|______________________xx___xxxx____
-________________________x_xxxxxx___|________________________x_xxxxxx___
-_______________________x______xxx__|_______________________x______xxx__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kEvenOdd_FillType, 1, 7, 8, 15, 3, 4, 11, 14 },
-/*
-___________________________________|___________________________________
-____________x______________________|____________x______________________
-_____________xxx________________x__|_____________xxx________________x__
-______________xxxxx___________xx___|______________xxxxx___________xx___
-_______________xxxxxxx_______xxx___|_______________xxxxxxx_______xxx___
-________________xxxxxxxx___xxxxx___|________________xxxxxxxxx__xxxxx___
-_________________xxxxxxxxx_xxxx____|_________________xxxxxxxxx_xxxx____
-__________________xxxxxxx_____x____|__________________xxxxxxx_____x____
-___________________xxxx_______xxx__|___________________xxxx_______xxx__
-____________________xxxx______x____|____________________xxxx______x____
-_____________________xxxx_xxx______|_____________________xxxx_xxx______
-___________________________xx______|___________________________xx______
-__________________xxxxx____________|__________________xxxxx____________
-______________xxxxxxxxxx____x______|______________xxxxxxxxxx____x______
-__________xxxxxxxxxxxxxx___xxxx____|__________xxxxxxxxxxxxxx___xxxx____
-_____xxxxxxxxxxxxxxxxxxxx__xxxxx___|_____xxxxxxxxxxxxxxxxxxxx__xxxxx___
-_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_|_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_
-_____xxxxxxxxxxxxxxxxxxxxx_xxxxx___|_____xxxxxxxxxxxxxxxxxxxxx_xxxxx___
-_________xxxxxxxxxxxxxxxx___xxx____|_________xxxxxxxxxxxxxxxx___xxx____
-_____________xxxxxxxxxxxx__________|_____________xxxxxxxxxxxx____x_____
-__________________xxxxxxx___xx_____|__________________xxxxxxx___xx_____
-______________________xx___xxxx____|______________________xx___xxxx____
-________________________x_xxxxxx___|________________________x_xxxxxx___
-_______________________x______xxx__|_______________________x______xxx__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kWinding_FillType, 1, 7, 8, 15, 3, 6, 11, 14 },
-/*
-___________________________________|___________________________________
-____________x______________________|____________x______________________
-_____________xxx________________x__|_____________xxx________________x__
-______________xxxxx___________xx___|______________xxxxx___________xx___
-_______________xxxxxxx_______xxx___|_______________xxxxxxx_______xxx___
-________________xxxxxxxx___xxxxx___|________________xxxxxxxxx__xxxxx___
-_________________xxxxxxxxx_xxxx____|_________________xxxxxxxxx_xxxx____
-__________________xxxxxxx_____x____|__________________xxxxxxx_____x____
-___________________xxxx_______xxx__|___________________xxxx_______xxx__
-____________________xxxx______x____|____________________xxxx______x____
-_____________________xxxx_xxx______|_____________________xxxx_xxx______
-___________________________xx______|___________________________xx______
-__________________xxxxx____________|__________________xxxxx____________
-______________xxxxxxxxxx____x______|______________xxxxxxxxxx____x______
-__________xxxxxxxxxxxxxx___xxxx____|__________xxxxxxxxxxxxxx___xxxx____
-_____xxxxxxxxxxxxxxxxxxxx__xxxxx___|_____xxxxxxxxxxxxxxxxxxxx__xxxxx___
-_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_|_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_
-_____xxxxxxxxxxxxxxxxxxxxx_xxxxx___|_____xxxxxxxxxxxxxxxxxxxxx_xxxxx___
-_________xxxxxxxxxxxxxxxx___xxx____|_________xxxxxxxxxxxxxxxx___xxx____
-_____________xxxxxxxxxxxx__________|_____________xxxxxxxxxxxx____x_____
-__________________xxxxxxx___xx_____|__________________xxxxxxx___xx_____
-______________________xx___xxxx____|______________________xx___xxxx____
-________________________x_xxxxxx___|________________________x_xxxxxx___
-_______________________x______xxx__|_______________________x______xxx__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kEvenOdd_FillType, 1, 7, 8, 15, 3, 6, 11, 14 },
-/*
-___________________________________|___________________________________
-____________x____________________x_|____________x____________________x_
-_____________xxx_________________x_|_____________xxx_________________x_
-______________xxxxx_____________xx_|______________xxxxx_____________xx_
-_______________xxxxxxx__________xx_|_______________xxxxxxx__________xx_
-________________xxxxxxxx________xx_|________________xxxxxxxx________xx_
-_________________xxxxxxxxxx____xxx_|_________________xxxxxxxxxx____xxx_
-__________________xxxxxxxxxxxx_xxx_|__________________xxxxxxxxxxxx_xxx_
-___________________xxxxxxxxxxx___x_|___________________xxxxxxxxxxx___x_
-____________________xxxxxxxxxx_xxx_|____________________xxxxxxxxxx_xxx_
-_____________________xxxxx___xxxxx_|_____________________xxxxx___xxxxx_
-_____________________________xxxxx_|_____________________________xxxxx_
-__________________xxxxx_____xxxxxx_|__________________xxxxx_____xxxxxx_
-______________xxxxxxxxxx____xxxxxx_|______________xxxxxxxxxx____xxxxxx_
-__________xxxxxxxxxxxxxx___xxxxxxx_|__________xxxxxxxxxxxxxx___xxxxxxx_
-_____xxxxxxxxxxxxxxxxxxxx__xxxxxxx_|_____xxxxxxxxxxxxxxxxxxxx__xxxxxxx_
-_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_|_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_
-_____xxxxxxxxxxxxxxxxxxxxx_xxxxx___|_____xxxxxxxxxxxxxxxxxxxxx_xxxxx___
-_________xxxxxxxxxxxxxxxx___xxx____|_________xxxxxxxxxxxxxxxx___xxx____
-_____________xxxxxxxxxxxx__________|_____________xxxxxxxxxxxx____x_____
-__________________xxxxxxx___xx_____|__________________xxxxxxx___xx_____
-______________________xx___xxxx____|______________________xx___xxxx____
-________________________x_xxxxxx___|________________________x_xxxxxx___
-_______________________x______xxx__|_______________________x______xxx__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kEvenOdd_FillType, 1, 7, 8, 15, 3, 7, 11, 14 },
-/*
-___________________________________|___________________________________
-____________x______________________|____________x______________________
-_____________xxx___________________|_____________xxx___________________
-______________xxxxx________________|______________xxxxx________________
-_______________xxxxxxx_________x___|_______________xxxxxxx_________x___
-________________xxxxxxxx______xx___|________________xxxxxxxxx_____xx___
-_________________xxxxxxxxxx___x____|_________________xxxxxxxxxx___x____
-__________________xxxxxxxxxxx_x____|__________________xxxxxxxxxxx_x____
-___________________xxxxxxxxx__xxx__|___________________xxxxxxxxx__xxx__
-____________________xxxxxxxx__x____|____________________xxxxxxxx__x____
-_____________________xxxxx_xx______|_____________________xxxxx_xx______
-__________________________xxx______|__________________________xxx______
-__________________xxxxx___xx_______|__________________xxxxx___xx_______
-______________xxxxxxxxxx_xxx_______|______________xxxxxxxxxx_xxx_______
-__________xxxxxxxxxxxxxxxxx________|__________xxxxxxxxxxxxxxxxx________
-_____xxxxxxxxxxxxxxxxxxxxxx________|_____xxxxxxxxxxxxxxxxxxxxxx________
-_xxxxxxxxxxxxxxxxxxxxxxxxx_________|_xxxxxxxxxxxxxxxxxxxxxxxxx_________
-_____xxxxxxxxxxxxxxxxxxxxx_xxxxx___|_____xxxxxxxxxxxxxxxxxxxxx_xxxxx___
-_________xxxxxxxxxxxxxxxx___xxx____|_________xxxxxxxxxxxxxxxx___xxx____
-_____________xxxxxxxxxxxx__________|_____________xxxxxxxxxxxx____x_____
-__________________xxxxxxx___xx_____|__________________xxxxxxx___xx_____
-______________________xx___xxxx____|______________________xx___xxxx____
-________________________x_xxxxxx___|________________________x_xxxxxx___
-_______________________x______xxx__|_______________________x______xxx__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kWinding_FillType, 1, 7, 8, 15, 3, 10, 11, 14 },
-/*
-___________________________________|___________________________________
-____________x______________________|____________x______________________
-_____________xxx___________________|_____________xxx___________________
-______________xxxxx________________|______________xxxxx________________
-_______________xxxxxxx_________x___|_______________xxxxxxx_________x___
-________________xxxxxxxx______xx___|________________xxxxxxxxx_____xx___
-_________________xxxxxxxxxx___x____|_________________xxxxxxxxxx___x____
-__________________xxxxxxxxxxx_x____|__________________xxxxxxxxxxx_x____
-___________________xxxxxxxxx__xxx__|___________________xxxxxxxxx__xxx__
-____________________xxxxxxxx__x____|____________________xxxxxxxx__x____
-_____________________xxxxx_xx______|_____________________xxxxx_xx______
-__________________________xxx______|__________________________xxx______
-__________________xxxxx___xx_______|__________________xxxxx___xx_______
-______________xxxxxxxxxx_xxx_______|______________xxxxxxxxxx_xxx_______
-__________xxxxxxxxxxxxxxxxx________|__________xxxxxxxxxxxxxx_xx________
-_____xxxxxxxxxxxxxxxxxx__xx________|_____xxxxxxxxxxxxxxxxxx__xx________
-_xxxxxxxxxxxxxxxxxxxxxx____________|_xxxxxxxxxxxxxxxxxxxxxx____________
-_____xxxxxxxxxxxxxxxxxxxxx_xxxxx___|_____xxxxxxxxxxxxxxxxxxxxx_xxxxx___
-_________xxxxxxxxxxxxxxxx___xxx____|_________xxxxxxxxxxxxxxxx___xxx____
-_____________xxxxxxxxxxxx__________|_____________xxxxxxxxxxxx____x_____
-__________________xxxxxxx___xx_____|__________________xxxxxxx___xx_____
-______________________xx___xxxx____|______________________xx___xxxx____
-________________________x_xxxxxx___|________________________x_xxxxxx___
-_______________________x______xxx__|_______________________x______xxx__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kEvenOdd_FillType, 1, 7, 8, 15, 3, 10, 11, 14 },
-/*
-___________________________________|___________________________________
-____________x____________________x_|____________x____________________x_
-_____________xxx_________________x_|_____________xxx_________________x_
-______________xxxxx_____________xx_|______________xxxxx_____________xx_
-_______________xxxxxxx__________xx_|_______________xxxxxxx__________xx_
-________________xxxxxxxx________xx_|________________xxxxxxxx________xx_
-_________________xxxxxxxxxx____xxx_|_________________xxxxxxxxxx____xxx_
-__________________xxxxxxxxxxxx_xxx_|__________________xxxxxxxxxxxx_xxx_
-___________________xxxxxxxxxxx___x_|___________________xxxxxxxxxxx___x_
-____________________xxxxxxxxxx_xxx_|____________________xxxxxxxxxx_xxx_
-_____________________xxxxx___xxxxx_|_____________________xxxxx___xxxxx_
-_____________________________xxxxx_|_____________________________xxxxx_
-__________________xxxxx_____xxxxxx_|__________________xxxxx_____xxxxxx_
-______________xxxxxxxxxx____xxxxxx_|______________xxxxxxxxxx____xxxxxx_
-__________xxxxxxxxxxxxxx___xxxxxxx_|__________xxxxxxxxxxxxxx___xxxxxxx_
-_____xxxxxxxxxxxxxxxxxxxx__xxxxxxx_|_____xxxxxxxxxxxxxxxxxxxx__xxxxxxx_
-_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_|_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_
-_____xxxxxxxxxxxxxxxxxxxxx_xxxxx___|_____xxxxxxxxxxxxxxxxxxxxx_xxxxx___
-_________xxxxxxxxxxxxxxxx___xxx____|_________xxxxxxxxxxxxxxxx___xxx____
-_____________xxxxxxxxxxxx__________|_____________xxxxxxxxxxxx____x_____
-__________________xxxxxxx___xx_____|__________________xxxxxxx___xx_____
-______________________xx___xxxx____|______________________xx___xxxx____
-________________________x_xxxxxx___|________________________x_xxxxxx___
-_______________________x______xxx__|_______________________x______xxx__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kEvenOdd_FillType, 1, 7, 8, 15, 3, 11, 11, 14 },
-/*
-___________________________________|___________________________________
-____________x____________________x_|____________x____________________x_
-_____________xxx_________________x_|_____________xxx_________________x_
-______________xxxxx_____________xx_|______________xxxxx_____________xx_
-_______________xxxxxxx__________xx_|_______________xxxxxxx__________xx_
-________________xxxxxxxx________xx_|________________xxxxxxxx________xx_
-_________________xxxxxxxxxx____xxx_|_________________xxxxxxxxxx____xxx_
-__________________xxxxxxxxxxxx_xxx_|__________________xxxxxxxxxxxx_xxx_
-___________________xxxxxxxxxxx___x_|___________________xxxxxxxxxxx___x_
-____________________xxxxxxxxxx_xxx_|____________________xxxxxxxxxx_xxx_
-_____________________xxxxx___xxxxx_|_____________________xxxxx___xxxxx_
-_____________________________xxxxx_|_____________________________xxxxx_
-__________________xxxxx_____xxxxxx_|__________________xxxxx_____xxxxxx_
-______________xxxxxxxxxx____xxxxxx_|______________xxxxxxxxxx____xxxxxx_
-__________xxxxxxxxxxxxxx___xxxxxxx_|__________xxxxxxxxxxxxxx___xxxxxxx_
-_____xxxxxxxxxxxxxxxxxxxx__xxxxxxx_|_____xxxxxxxxxxxxxxxxxxxx__xxxxxxx_
-_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_|_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_
-_____xxxxxxxxxxxxxxxxxxxxx_xxxxx___|_____xxxxxxxxxxxxxxxxxxxxx_xxxxx___
-_________xxxxxxxxxxxxxxxx___xxx____|_________xxxxxxxxxxxxxxxx___xxx____
-_____________xxxxxxxxxxxx__________|_____________xxxxxxxxxxxx____x_____
-__________________xxxxxxx___xx_____|__________________xxxxxxx___xx_____
-______________________xx___xxxx____|______________________xx___xxxx____
-________________________x_xxxxxx___|________________________x_xxxxxx___
-_______________________x______xxx__|_______________________x______xxx__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kEvenOdd_FillType, 1, 7, 8, 15, 3, 11, 14, 14 },
-/*
-___________________________________|___________________________________
-_____________xxxxxxxxxxxxxxxxxxx___|_____________xxxxxxxxxxxxxxxxxxx___
-___________xx___xxxxxxxxxxx________|___________xx___xxxxxxxxxxx________
-___________xxx_____xxxx____________|___________xxx_____xxxx____________
-__________xxxxx____xxx_____________|__________xxxxx____xxx_____________
-__________xxxxx_xxxxxxxx___________|__________xxxxx_xxxxxxxxx__________
-_________xx______xxxxxxxxxx________|_________x_______xxxxxxxxxx________
-______xxx_________xxxxxxxxxxxx_____|______xxx_________xxxxxxxxxxxx_____
-__xxxxxx___________xxxxxxxxxxxxxx__|__xxxxxx___________xxxxxxxxxxxxxx__
-___xxxxx____________xxxxxxxxxxxx___|___xxxxx____________xxxxxxxxxxxx___
-_____xx______________xxxxxxxxx_____|_____xx______________xxxxxxxxx_____
-______________________xxxxxx_______|______________________xxxxxx_______
-_______xx______________xxx_________|_______xx______________xxx_________
-______xxxxx________________________|______xxxxx________________________
-______xxxxxxx_________xx___________|______xxxxxxx_________xxx__________
-_____xxxxxxxxxx____xxxxxx__________|_____xxxxxxxxxx____xxxxxx__________
-_____xxxxxxxxxxxxxxxxxxxxx_________|_____xxxxxxxxxxxxxxxxxxxxx_________
-____xxxxxxxxxxx____xxxxxxxx________|____xxxxxxxxxxx____xxxxxxxx________
-____xxxxxxxxx________xxxxxxx_______|____xxxxxxxxx________xxxxxxx_______
-___xxxxxxxx_____________xxxxx______|___xxxxxxxx_____________xxxxx______
-___xxxxxx_________________xxxx_____|___xxxxxx_________________xxxx_____
-__xxxxx_____________________xxx____|__xxxxx_____________________xxx____
-__xxx_________________________xx___|__xxx_________________________xx___
-_xx_____________________________x__|_xx_____________________________x__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kEvenOdd_FillType, 1, 7, 12, 12, 1, 3, 4, 15 },
-/*
-___________________________________|___________________________________
-____________x__________xxxxxxxxxx__|____________x__________xxxxxxxxxx__
-_____________x_________xxxxxxxxx___|_____________x_________xxxxxxxxx___
-______________x_________xxxxxx_____|______________x_________xxxxxx_____
-_______________xx_______xxxxx______|_______________xx_______xxxxx______
-________________xx_______xx________|________________xx_______xx________
-_________________xxx_____x_________|_________________xxx_____x_________
-__________________xxx____x_________|__________________xxx____x_________
-___________________xxx_xxx_________|___________________xxx_xxx_________
-____________________x_xxxxx________|____________________x_xxxxx________
-__________________xx_xxxxxx________|__________________xx_xxxxxx________
-_______________xxxx___xxxxxx_______|_______________xxxx___xxxxxx_______
-____________xxxxxx_____xxxxx_______|____________xxxxxx_____xxxxx_______
-_________xxxxxxx________xxxxx______|_________xxxxxxx________xxxxx______
-_______xxxxxxxx_________xxxxx______|_______xxxxxxxx__________xxxx______
-____xxxxxxxxx____________xxxxx_____|____xxxxxxxxx____________xxxxx_____
-_xxxxxxxxxxx______________xxxx_____|_xxxxxxxxxxx______________xxxx_____
-_____xxxxxx________________xxx_____|_____xxxxxx________________xxx_____
-____________________________xxx____|____________________________xxx____
-________xxxxx________________xx____|________xxxxx________________xx____
-______xxxxxxxxxxxx____________xx___|______xxxxxxxxxxxx____________xx___
-_____xxxxxxxxxxxxxxxxx_________x___|_____xxxxxxxxxxxxxxxxx_________x___
-____xxxxxxxxxxxxxxxxxxxxxx______x__|____xxxxxxxxxxxxxxxxxxxxxx______x__
-__xxxxxxxxxxxxxxxxxxxxxxxxxxxx_____|__xxxxxxxxxxxxxxxxxxxxxxxxxxxx_____
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kEvenOdd_FillType, 2, 3, 12, 15, 1, 6, 8, 15 },
-/*
-___________________________________|___________________________________
-_xx__________________x_____________|_xx__________________x_____________
-__xxxxx____________xx______________|__xxxxx____________xx______________
-__xxxxxxxxxx____xxxx_______________|__xxxxxxxxxx____xxxx_______________
-___xxxxxxxxxx___xxx________________|___xxxxxxxxxx___xxx________________
-___xxxxxxx_________x_______________|___xxxxxxx_________x_______________
-____xxx___________xxxxxx___________|____xxx___________xxxxxx___________
-____x____________xxxxxxxxxxx_______|____x____________xxxxxxxxxxx_______
-__xx____________xxxxxxxxxxxxxxxxx__|__xxx___________xxxxxxxxxxxxxxxxx__
-__xxx__________xxxxxxxxxxxxxxxx____|__xxx__________xxxxxxxxxxxxxxxx____
-___xx_________xxxxxxxxxxxx_________|___xx_________xxxxxxxxxxxx_________
-_____x_______xxxxxxxxx_____________|_____x_______xxxxxxxxx_____________
-____________xxxxxx_________________|____________xxxxxx_________________
-_______x___xxx_____________________|_______x___xxx_____________________
-_______xx__________________________|_______xx__________________________
-_____xxx_x_________________________|_____xxx_x_________________________
-_xxxxxxxxxxx_______________________|_xxxxxxxxxxx_______________________
-__xxxxx__xx________________________|__xxxxx__xx________________________
-____xx_____________________________|____xx_____________________________
-________xx_________________________|________xx_________________________
-_____x_xxx_________________________|_____x_xxx_________________________
-____x___xxx________________________|____x___xxx________________________
-___x_____xx________________________|___x_____xx________________________
-___________________________________|___________________________________
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kWinding_FillType, 2, 4, 9, 12, 0, 7, 8, 13 },
-/*
-___________________________________|___________________________________
-_xx__________________x_____________|_xx__________________x_____________
-__xxxxx____________xx______________|__xxxxx____________xx______________
-__xxxxxxxxxx____xxxx_______________|__xxxxxxxxxx____xxxx_______________
-___xxxxxxxxxx___xxx________________|___xxxxxxxxxx___xxx________________
-___xxxxxxx_________x_______________|___xxxxxxx_________x_______________
-____xxx___________xxxxxx___________|____xxx___________xxxxxx___________
-____x____________xxxxxxxxxxx_______|____x____________xxxxxxxxxxx_______
-__xx____________xxxxxxxxxxxxxxxxx__|__xxx___________xxxxxxxxxxxxxxxxx__
-__xxx__________xxxxxxxxxxxxxxxx____|__xxx__________xxxxxxxxxxxxxxxx____
-___xx_________xxxxxxxxxxxx_________|___xx_________xxxxxxxxxxxx_________
-_____x_______xxxxxxxxx_____________|_____x_______xxxxxxxxx_____________
-____________xxxxxx_________________|____________xxxxxx_________________
-_______x___xxx_____________________|_______x___xxx_____________________
-_______xx__________________________|_______xx__________________________
-_____xxx_x_________________________|_____xxx_x_________________________
-_xxxxxxxxxxx_______________________|_xxxxxxxxxxx_______________________
-__xxxxx__xx________________________|__xxxxx__xx________________________
-____xx_____________________________|____xx_____________________________
-________xx_________________________|________xx_________________________
-_____x_xxx_________________________|_____x_xxx_________________________
-____x___xxx________________________|____x___xxx________________________
-___x_____xx________________________|___x_____xx________________________
-___________________________________|___________________________________
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kEvenOdd_FillType, 2, 4, 9, 12, 0, 7, 8, 13 },
-/*
-___________________________________|___________________________________
-____________x________x_____________|____________x________x_____________
-_____________x_____xx______________|_____________x_____xx______________
-______________x_xxxx_______________|______________x_xxxx_______________
-_____________xx__xx________________|_____________xx__xx________________
-__________xxxxxx__x________________|__________xxxxxx__x________________
-_______xxxxxxxxxx_xx_______________|_______xxxxxxxxxx_xx_______________
-_____xxxxxxxxxxxx_xxx______________|_____xxxxxxxxxxxx_xxx______________
-__xxxxxxxxxxxxxx___xxx_____________|__xxxxxxxxxxxxxx___xxx_____________
-____xxxxxxxxxxx_____xx_____________|____xxxxxxxxxxx_____xx_____________
-________xxxxxx______x______________|________xxxxxx______x______________
-____________x______xxx_____________|____________x______xxx_____________
-____________xxxxx_xxxxx____________|____________xxxxx_xxxxx____________
-___________xxxxx_____xxx___________|___________xxxxx_____xxx___________
-__________xxxxx_________x__________|__________xxxxx____________________
-_________xxxx____________xxxx______|_________xxxx____________xxxx______
-________xxxx______________xxxxxxxx_|________xxxx______________xxxxxxxx_
-_______xxxxxxxx____________xxx_____|_______xxxxxxxx____________xxx_____
-______xxxxxxxxxxx________xxx_______|______xxxxxxxxxxx________xxx_______
-_____xxxxxxxxxxxxxxx_xxxxxxxx______|_____xxxxxxxxxxxxxxx_xxxxxxxx______
-_____xxxxxxxxxxxx______xxxxxxx_____|_____xxxxxxxxxxxx______xxxxxxx_____
-____xxxxxxxxx_____________xxxxx____|____xxxxxxxxx_____________xxxxx____
-___xxxxxx____________________xxx___|___xxxxxx____________________xxx___
-__xx___________________________xx__|__xx___________________________xx__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kWinding_FillType, 2, 4, 11, 12, 1, 6, 9, 15 },
-/*
-___________________________________|___________________________________
-____________x________x_____________|____________x________x_____________
-_____________x_____xx______________|_____________x_____xx______________
-______________x_xxxx_______________|______________x_xxxx_______________
-_____________xx__xx________________|_____________xx__xx________________
-__________xxxxxx__x________________|__________xxxxxx__x________________
-_______xxxxxxxxxx_xx_______________|_______xxxxxxxxxx_xx_______________
-_____xxxxxxxxxxxx_xxx______________|_____xxxxxxxxxxxx_xxx______________
-__xxxxxxxxxxxxxx___xxx_____________|__xxxxxxxxxxxxxx___xxx_____________
-____xxxxxxxxxxx_____xx_____________|____xxxxxxxxxxx_____xx_____________
-________xxxxxx______x______________|________xxxxxx______x______________
-____________x______xxx_____________|____________x______xxx_____________
-____________xxxxx_xxxxx____________|____________xxxxx_xxxxx____________
-___________xxxxx_____xxx___________|___________xxxxx_____xxx___________
-__________xxxxx_________x__________|__________xxxxx____________________
-_________xxxx____________xxxx______|_________xxxx____________xxxx______
-________xxxx______________xxxxxxxx_|________xxxx______________xxxxxxxx_
-_______xxxxxxxx____________xxx_____|_______xxxxxxxx____________xxx_____
-______xxxxxxxxxxx________xxx_______|______xxxxxxxxxxx________xxx_______
-_____xxxxxxxxxxxxxxx_xxxxxxxx______|_____xxxxxxxxxxxxxxx_xxxxxxxx______
-_____xxxxxxxxxxxx______xxxxxxx_____|_____xxxxxxxxxxxx______xxxxxxx_____
-____xxxxxxxxx_____________xxxxx____|____xxxxxxxxx_____________xxxxx____
-___xxxxxx____________________xxx___|___xxxxxx____________________xxx___
-__xx___________________________xx__|__xx___________________________xx__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kEvenOdd_FillType, 2, 4, 11, 12, 1, 6, 9, 15 },
-/*
-___________________________________|___________________________________
-____________xxxxxxxxxxxxxxxxxxxxx__|____________xxxxxxxxxxxxxxxxxxxxx__
-_____________xxxxxxxxxxxxxxxxxxx___|_____________xxxxxxxxxxxxxxxxxxx___
-______________xxxxxxxxx_xxxxxx_____|______________xxxxxxxxx_xxxxxx_____
-_______________xxxxxxxx_xxxxx______|_______________xxxxxxxx_xxxxx______
-________________xxxxxxx__xx________|________________xxxxxxx__xx________
-_________________xxxxxx__x_________|_________________xxxxxx__x_________
-__________________xxxxx__x_________|__________________xxxxx__x_________
-___________________xxxxxxx_________|___________________xxxxxxx_________
-____________________x_xxxxx________|____________________x_xxxxx________
-__________________xx_xxxxxx________|__________________xx_xxxxxx________
-_______________xxxx___xxxxxx_______|_______________xxxx___xxxxxx_______
-____________xxxxxx_____xxxxx_______|____________xxxxxx_____xxxxx_______
-_________xxxxxxx________xxxxx______|_________xxxxxxx________xxxxx______
-_______xxxxxxxx_________xxxxx______|_______xxxxxxxx__________xxxx______
-____xxxxxxxxx____________xxxxx_____|____xxxxxxxxx____________xxxxx_____
-_xxxxxxxxxxx______________xxxx_____|_xxxxxxxxxxx______________xxxx_____
-_____xxxxxx________________xxx_____|_____xxxxxx________________xxx_____
-____________________________xxx____|____________________________xxx____
-________xxxxx________________xx____|________xxxxx________________xx____
-______xxxxxxxxxxxx____________xx___|______xxxxxxxxxxxx____________xx___
-_____xxxxxxxxxxxxxxxxx_________x___|_____xxxxxxxxxxxxxxxxx_________x___
-____xxxxxxxxxxxxxxxxxxxxxx______x__|____xxxxxxxxxxxxxxxxxxxxxx______x__
-__xxxxxxxxxxxxxxxxxxxxxxxxxxxx_____|__xxxxxxxxxxxxxxxxxxxxxxxxxxxx_____
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kEvenOdd_FillType, 2, 6, 8, 15, 1, 3, 12, 15 },
-/*
-___________________________________|___________________________________
-____________x____________________x_|____________x____________________x_
-_____________xxx_________________x_|_____________xxx_________________x_
-______________xxxxx_____________xx_|______________xxxxx_____________xx_
-_______________xxxxxxx__________xx_|_______________xxxxxxx__________xx_
-________________xxxxxxxx________xx_|________________xxxxxxxx________xx_
-_________________xxxxxxxxxx____xxx_|_________________xxxxxxxxxx____xxx_
-__________________xxxxxxxxxxxx_xxx_|__________________xxxxxxxxxxxx_xxx_
-___________________xxxxxxxxxxx___x_|___________________xxxxxxxxxxx___x_
-____________________xxxxxxxxxx_xxx_|____________________xxxxxxxxxx_xxx_
-_____________________xxxxx___xxxxx_|_____________________xxxxx___xxxxx_
-_____________________________xxxxx_|_____________________________xxxxx_
-__________________xxxxx_____xxxxxx_|__________________xxxxx_____xxxxxx_
-______________xxxxxxxxxx____xxxxxx_|______________xxxxxxxxxx____xxxxxx_
-__________xxxxxxxxxxxxxx___xxxxxxx_|__________xxxxxxxxxxxxxx___xxxxxxx_
-_____xxxxxxxxxxxxxxxxxxxx__xxxxxxx_|_____xxxxxxxxxxxxxxxxxxxx__xxxxxxx_
-_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_|_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_
-_____xxxxxxxxxxxxxxxxxxxxx_xxxxx___|_____xxxxxxxxxxxxxxxxxxxxx_xxxxx___
-_________xxxxxxxxxxxxxxxx___xxx____|_________xxxxxxxxxxxxxxxx___xxx____
-_____________xxxxxxxxxxxx__________|_____________xxxxxxxxxxxx____x_____
-__________________xxxxxxx___xx_____|__________________xxxxxxx___xx_____
-______________________xx___xxxx____|______________________xx___xxxx____
-________________________x_xxxxxx___|________________________x_xxxxxx___
-_______________________x______xxx__|_______________________x______xxx__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kEvenOdd_FillType, 3, 3, 11, 14, 1, 7, 8, 15 },
-/*
-___________________________________|___________________________________
-____________x___________________x__|____________x___________________x__
-_____________xxx___________xxxxxx__|_____________xxx___________xxxxxx__
-______________xxxxx____xxxxxxxxx___|______________xxxxx____xxxxxxxxx___
-_______________xxxx___xxxxxxxxxx___|_______________xxxx___xxxxxxxxxx___
-_______________x________xxxxxxxx___|_______________x_________xxxxxxx___
-___________xxxxxx__________xxxx____|___________xxxxxx__________xxxx____
-______xxxxxxxxxxxx____________x____|______xxxxxxxxxxxx____________x____
-__xxxxxxxxxxxxxxxxx___________xxx__|__xxxxxxxxxxxxxxxxx___________xxx__
-____xxxxxxxxxxxxxxxx__________x____|____xxxxxxxxxxxxxxxx__________x____
-________xxxxxxxxxxxxx_____xxx______|________xxxxxxxxxxxxx_____xxx______
-____________xxxxxxxxxxxxxxxxx______|_____________xxxxxxxxxxxxxxxx______
-_________________xxxxxxxxxxx_______|_________________xxxxxxxxxxx_______
-______________xxxxxxxxxxxxxx_______|______________xxxxxxxxxxxxxx_______
-__________xxxxxxxxxxxxxx_xx________|__________xxxxxxxxxxxxxxxxx________
-_____xxxxxxxxxxxxxxxxxxxx__xx______|_____xxxxxxxxxxxxxxxxxxxx__xx______
-_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_|_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_
-_____xxxxxxxxxxxxxxxxxxxxx_xxxxx___|_____xxxxxxxxxxxxxxxxxxxxx_xxxxx___
-_________xxxxxxxxxxxxxxxx___xxx____|_________xxxxxxxxxxxxxxxx___xxx____
-_____________xxxxxxxxxxxx__________|_____________xxxxxxxxxxxx____x_____
-__________________xxxxxxx___xx_____|__________________xxxxxxx___xx_____
-______________________xx___xxxx____|______________________xx___xxxx____
-________________________x_xxxxxx___|________________________x_xxxxxx___
-_______________________x______xxx__|_______________________x______xxx__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kWinding_FillType, 3, 4, 11, 14, 1, 7, 8, 15 },
-/*
-___________________________________|___________________________________
-____________x___________________x__|____________x___________________x__
-_____________xxx___________xxxxxx__|_____________xxx___________xxxxxx__
-______________xxxxx____xxxxxxxxx___|______________xxxxx____xxxxxxxxx___
-_______________xxxx___xxxxxxxxxx___|_______________xxxx___xxxxxxxxxx___
-_______________x________xxxxxxxx___|_______________x_________xxxxxxx___
-___________xxxxxx__________xxxx____|___________xxxxxx__________xxxx____
-______xxxxxxxxxxxx____________x____|______xxxxxxxxxxxx____________x____
-__xxxxxxxxxxxxxxxxx___________xxx__|__xxxxxxxxxxxxxxxxx___________xxx__
-____xxxxxxxxxxxxxxxx__________x____|____xxxxxxxxxxxxxxxx__________x____
-________xxxxxxxxxxxxx_____xxx______|________xxxxxxxxxxxxx_____xxx______
-____________xxxxxxxxxxxxxxxxx______|_____________xxxxxxxxxxxxxxxx______
-_________________x_____xxxxx_______|_________________x_____xxxxx_______
-______________xxxxxxx___xxxx_______|______________xxxxxxx___xxxx_______
-__________xxxxxxxxxxxxxx_xx________|__________xxxxxxxxxxxxxxxxx________
-_____xxxxxxxxxxxxxxxxxxxx__xx______|_____xxxxxxxxxxxxxxxxxxxx__xx______
-_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_|_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_
-_____xxxxxxxxxxxxxxxxxxxxx_xxxxx___|_____xxxxxxxxxxxxxxxxxxxxx_xxxxx___
-_________xxxxxxxxxxxxxxxx___xxx____|_________xxxxxxxxxxxxxxxx___xxx____
-_____________xxxxxxxxxxxx__________|_____________xxxxxxxxxxxx____x_____
-__________________xxxxxxx___xx_____|__________________xxxxxxx___xx_____
-______________________xx___xxxx____|______________________xx___xxxx____
-________________________x_xxxxxx___|________________________x_xxxxxx___
-_______________________x______xxx__|_______________________x______xxx__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kEvenOdd_FillType, 3, 4, 11, 14, 1, 7, 8, 15 },
-/*
-___________________________________|___________________________________
-____________x______________________|____________x______________________
-_____________xxx________________x__|_____________xxx________________x__
-______________xxxxx___________xx___|______________xxxxx___________xx___
-_______________xxxxxxx_______xxx___|_______________xxxxxxx_______xxx___
-________________xxxxxxxx___xxxxx___|________________xxxxxxxxx__xxxxx___
-_________________xxxxxxxxx_xxxx____|_________________xxxxxxxxx_xxxx____
-__________________xxxxxxx_____x____|__________________xxxxxxx_____x____
-___________________xxxx_______xxx__|___________________xxxx_______xxx__
-____________________xxxx______x____|____________________xxxx______x____
-_____________________xxxx_xxx______|_____________________xxxx_xxx______
-___________________________xx______|___________________________xx______
-__________________xxxxx____________|__________________xxxxx____________
-______________xxxxxxxxxx____x______|______________xxxxxxxxxx____x______
-__________xxxxxxxxxxxxxx___xxxx____|__________xxxxxxxxxxxxxx___xxxx____
-_____xxxxxxxxxxxxxxxxxxxx__xxxxx___|_____xxxxxxxxxxxxxxxxxxxx__xxxxx___
-_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_|_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_
-_____xxxxxxxxxxxxxxxxxxxxx_xxxxx___|_____xxxxxxxxxxxxxxxxxxxxx_xxxxx___
-_________xxxxxxxxxxxxxxxx___xxx____|_________xxxxxxxxxxxxxxxx___xxx____
-_____________xxxxxxxxxxxx__________|_____________xxxxxxxxxxxx____x_____
-__________________xxxxxxx___xx_____|__________________xxxxxxx___xx_____
-______________________xx___xxxx____|______________________xx___xxxx____
-________________________x_xxxxxx___|________________________x_xxxxxx___
-_______________________x______xxx__|_______________________x______xxx__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kWinding_FillType, 3, 6, 11, 14, 1, 7, 8, 15 },
-/*
-___________________________________|___________________________________
-____________x______________________|____________x______________________
-_____________xxx________________x__|_____________xxx________________x__
-______________xxxxx___________xx___|______________xxxxx___________xx___
-_______________xxxxxxx_______xxx___|_______________xxxxxxx_______xxx___
-________________xxxxxxxx___xxxxx___|________________xxxxxxxxx__xxxxx___
-_________________xxxxxxxxx_xxxx____|_________________xxxxxxxxx_xxxx____
-__________________xxxxxxx_____x____|__________________xxxxxxx_____x____
-___________________xxxx_______xxx__|___________________xxxx_______xxx__
-____________________xxxx______x____|____________________xxxx______x____
-_____________________xxxx_xxx______|_____________________xxxx_xxx______
-___________________________xx______|___________________________xx______
-__________________xxxxx____________|__________________xxxxx____________
-______________xxxxxxxxxx____x______|______________xxxxxxxxxx____x______
-__________xxxxxxxxxxxxxx___xxxx____|__________xxxxxxxxxxxxxx___xxxx____
-_____xxxxxxxxxxxxxxxxxxxx__xxxxx___|_____xxxxxxxxxxxxxxxxxxxx__xxxxx___
-_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_|_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_
-_____xxxxxxxxxxxxxxxxxxxxx_xxxxx___|_____xxxxxxxxxxxxxxxxxxxxx_xxxxx___
-_________xxxxxxxxxxxxxxxx___xxx____|_________xxxxxxxxxxxxxxxx___xxx____
-_____________xxxxxxxxxxxx__________|_____________xxxxxxxxxxxx____x_____
-__________________xxxxxxx___xx_____|__________________xxxxxxx___xx_____
-______________________xx___xxxx____|______________________xx___xxxx____
-________________________x_xxxxxx___|________________________x_xxxxxx___
-_______________________x______xxx__|_______________________x______xxx__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kEvenOdd_FillType, 3, 6, 11, 14, 1, 7, 8, 15 },
-/*
-___________________________________|___________________________________
-____________x____________________x_|____________x____________________x_
-_____________xxx_________________x_|_____________xxx_________________x_
-______________xxxxx_____________xx_|______________xxxxx_____________xx_
-_______________xxxxxxx__________xx_|_______________xxxxxxx__________xx_
-________________xxxxxxxx________xx_|________________xxxxxxxx________xx_
-_________________xxxxxxxxxx____xxx_|_________________xxxxxxxxxx____xxx_
-__________________xxxxxxxxxxxx_xxx_|__________________xxxxxxxxxxxx_xxx_
-___________________xxxxxxxxxxx___x_|___________________xxxxxxxxxxx___x_
-____________________xxxxxxxxxx_xxx_|____________________xxxxxxxxxx_xxx_
-_____________________xxxxx___xxxxx_|_____________________xxxxx___xxxxx_
-_____________________________xxxxx_|_____________________________xxxxx_
-__________________xxxxx_____xxxxxx_|__________________xxxxx_____xxxxxx_
-______________xxxxxxxxxx____xxxxxx_|______________xxxxxxxxxx____xxxxxx_
-__________xxxxxxxxxxxxxx___xxxxxxx_|__________xxxxxxxxxxxxxx___xxxxxxx_
-_____xxxxxxxxxxxxxxxxxxxx__xxxxxxx_|_____xxxxxxxxxxxxxxxxxxxx__xxxxxxx_
-_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_|_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_
-_____xxxxxxxxxxxxxxxxxxxxx_xxxxx___|_____xxxxxxxxxxxxxxxxxxxxx_xxxxx___
-_________xxxxxxxxxxxxxxxx___xxx____|_________xxxxxxxxxxxxxxxx___xxx____
-_____________xxxxxxxxxxxx__________|_____________xxxxxxxxxxxx____x_____
-__________________xxxxxxx___xx_____|__________________xxxxxxx___xx_____
-______________________xx___xxxx____|______________________xx___xxxx____
-________________________x_xxxxxx___|________________________x_xxxxxx___
-_______________________x______xxx__|_______________________x______xxx__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kEvenOdd_FillType, 3, 7, 11, 14, 1, 7, 8, 15 },
-/*
-___________________________________|___________________________________
-____________x______________________|____________x______________________
-_____________xxx___________________|_____________xxx___________________
-______________xxxxx________________|______________xxxxx________________
-_______________xxxxxxx_________x___|_______________xxxxxxx_________x___
-________________xxxxxxxx______xx___|________________xxxxxxxxx_____xx___
-_________________xxxxxxxxxx___x____|_________________xxxxxxxxxx___x____
-__________________xxxxxxxxxxx_x____|__________________xxxxxxxxxxx_x____
-___________________xxxxxxxxx__xxx__|___________________xxxxxxxxx__xxx__
-____________________xxxxxxxx__x____|____________________xxxxxxxx__x____
-_____________________xxxxx_xx______|_____________________xxxxx_xx______
-__________________________xxx______|__________________________xxx______
-__________________xxxxx___xx_______|__________________xxxxx___xx_______
-______________xxxxxxxxxx_xxx_______|______________xxxxxxxxxx_xxx_______
-__________xxxxxxxxxxxxxxxxx________|__________xxxxxxxxxxxxxxxxx________
-_____xxxxxxxxxxxxxxxxxxxxxx________|_____xxxxxxxxxxxxxxxxxxxxxx________
-_xxxxxxxxxxxxxxxxxxxxxxxxx_________|_xxxxxxxxxxxxxxxxxxxxxxxxx_________
-_____xxxxxxxxxxxxxxxxxxxxx_xxxxx___|_____xxxxxxxxxxxxxxxxxxxxx_xxxxx___
-_________xxxxxxxxxxxxxxxx___xxx____|_________xxxxxxxxxxxxxxxx___xxx____
-_____________xxxxxxxxxxxx__________|_____________xxxxxxxxxxxx____x_____
-__________________xxxxxxx___xx_____|__________________xxxxxxx___xx_____
-______________________xx___xxxx____|______________________xx___xxxx____
-________________________x_xxxxxx___|________________________x_xxxxxx___
-_______________________x______xxx__|_______________________x______xxx__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kWinding_FillType, 3, 10, 11, 14, 1, 7, 8, 15 },
-/*
-___________________________________|___________________________________
-____________x______________________|____________x______________________
-_____________xxx___________________|_____________xxx___________________
-______________xxxxx________________|______________xxxxx________________
-_______________xxxxxxx_________x___|_______________xxxxxxx_________x___
-________________xxxxxxxx______xx___|________________xxxxxxxxx_____xx___
-_________________xxxxxxxxxx___x____|_________________xxxxxxxxxx___x____
-__________________xxxxxxxxxxx_x____|__________________xxxxxxxxxxx_x____
-___________________xxxxxxxxx__xxx__|___________________xxxxxxxxx__xxx__
-____________________xxxxxxxx__x____|____________________xxxxxxxx__x____
-_____________________xxxxx_xx______|_____________________xxxxx_xx______
-__________________________xxx______|__________________________xxx______
-__________________xxxxx___xx_______|__________________xxxxx___xx_______
-______________xxxxxxxxxx_xxx_______|______________xxxxxxxxxx_xxx_______
-__________xxxxxxxxxxxxxxxxx________|__________xxxxxxxxxxxxxx_xx________
-_____xxxxxxxxxxxxxxxxxx__xx________|_____xxxxxxxxxxxxxxxxxx__xx________
-_xxxxxxxxxxxxxxxxxxxxxx____________|_xxxxxxxxxxxxxxxxxxxxxx____________
-_____xxxxxxxxxxxxxxxxxxxxx_xxxxx___|_____xxxxxxxxxxxxxxxxxxxxx_xxxxx___
-_________xxxxxxxxxxxxxxxx___xxx____|_________xxxxxxxxxxxxxxxx___xxx____
-_____________xxxxxxxxxxxx__________|_____________xxxxxxxxxxxx____x_____
-__________________xxxxxxx___xx_____|__________________xxxxxxx___xx_____
-______________________xx___xxxx____|______________________xx___xxxx____
-________________________x_xxxxxx___|________________________x_xxxxxx___
-_______________________x______xxx__|_______________________x______xxx__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kEvenOdd_FillType, 3, 10, 11, 14, 1, 7, 8, 15 },
-/*
-___________________________________|___________________________________
-____________x____________________x_|____________x____________________x_
-_____________xxx_________________x_|_____________xxx_________________x_
-______________xxxxx_____________xx_|______________xxxxx_____________xx_
-_______________xxxxxxx__________xx_|_______________xxxxxxx__________xx_
-________________xxxxxxxx________xx_|________________xxxxxxxx________xx_
-_________________xxxxxxxxxx____xxx_|_________________xxxxxxxxxx____xxx_
-__________________xxxxxxxxxxxx_xxx_|__________________xxxxxxxxxxxx_xxx_
-___________________xxxxxxxxxxx___x_|___________________xxxxxxxxxxx___x_
-____________________xxxxxxxxxx_xxx_|____________________xxxxxxxxxx_xxx_
-_____________________xxxxx___xxxxx_|_____________________xxxxx___xxxxx_
-_____________________________xxxxx_|_____________________________xxxxx_
-__________________xxxxx_____xxxxxx_|__________________xxxxx_____xxxxxx_
-______________xxxxxxxxxx____xxxxxx_|______________xxxxxxxxxx____xxxxxx_
-__________xxxxxxxxxxxxxx___xxxxxxx_|__________xxxxxxxxxxxxxx___xxxxxxx_
-_____xxxxxxxxxxxxxxxxxxxx__xxxxxxx_|_____xxxxxxxxxxxxxxxxxxxx__xxxxxxx_
-_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_|_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_
-_____xxxxxxxxxxxxxxxxxxxxx_xxxxx___|_____xxxxxxxxxxxxxxxxxxxxx_xxxxx___
-_________xxxxxxxxxxxxxxxx___xxx____|_________xxxxxxxxxxxxxxxx___xxx____
-_____________xxxxxxxxxxxx__________|_____________xxxxxxxxxxxx____x_____
-__________________xxxxxxx___xx_____|__________________xxxxxxx___xx_____
-______________________xx___xxxx____|______________________xx___xxxx____
-________________________x_xxxxxx___|________________________x_xxxxxx___
-_______________________x______xxx__|_______________________x______xxx__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kEvenOdd_FillType, 3, 11, 11, 14, 1, 7, 8, 15 },
-/*
-___________________________________|___________________________________
-____________x____________________x_|____________x____________________x_
-_____________xxx_________________x_|_____________xxx_________________x_
-______________xxxxx_____________xx_|______________xxxxx_____________xx_
-_______________xxxxxxx__________xx_|_______________xxxxxxx__________xx_
-________________xxxxxxxx________xx_|________________xxxxxxxx________xx_
-_________________xxxxxxxxxx____xxx_|_________________xxxxxxxxxx____xxx_
-__________________xxxxxxxxxxxx_xxx_|__________________xxxxxxxxxxxx_xxx_
-___________________xxxxxxxxxxx___x_|___________________xxxxxxxxxxx___x_
-____________________xxxxxxxxxx_xxx_|____________________xxxxxxxxxx_xxx_
-_____________________xxxxx___xxxxx_|_____________________xxxxx___xxxxx_
-_____________________________xxxxx_|_____________________________xxxxx_
-__________________xxxxx_____xxxxxx_|__________________xxxxx_____xxxxxx_
-______________xxxxxxxxxx____xxxxxx_|______________xxxxxxxxxx____xxxxxx_
-__________xxxxxxxxxxxxxx___xxxxxxx_|__________xxxxxxxxxxxxxx___xxxxxxx_
-_____xxxxxxxxxxxxxxxxxxxx__xxxxxxx_|_____xxxxxxxxxxxxxxxxxxxx__xxxxxxx_
-_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_|_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_
-_____xxxxxxxxxxxxxxxxxxxxx_xxxxx___|_____xxxxxxxxxxxxxxxxxxxxx_xxxxx___
-_________xxxxxxxxxxxxxxxx___xxx____|_________xxxxxxxxxxxxxxxx___xxx____
-_____________xxxxxxxxxxxx__________|_____________xxxxxxxxxxxx____x_____
-__________________xxxxxxx___xx_____|__________________xxxxxxx___xx_____
-______________________xx___xxxx____|______________________xx___xxxx____
-________________________x_xxxxxx___|________________________x_xxxxxx___
-_______________________x______xxx__|_______________________x______xxx__
-___________________________________|___________________________________
-___________________________________|___________________________________
-*/
-{ SkPath::kEvenOdd_FillType, 3, 11, 14, 14, 1, 7, 8, 15 },
-};
-
-size_t misMatchCount = sizeof(misMatches) / sizeof(misMatches[0]);
-
-void TestMismatches();
-
-void TestMismatches() {
- SkBitmap bitmap;
- for (size_t index = 0; index < misMatchCount; ++index) {
- const misMatch& miss = misMatches[index];
- int ax = miss.a & 0x03;
- int ay = miss.a >> 2;
- int bx = miss.b & 0x03;
- int by = miss.b >> 2;
- int cx = miss.c & 0x03;
- int cy = miss.c >> 2;
- int dx = miss.d & 0x03;
- int dy = miss.d >> 2;
- int ex = miss.e & 0x03;
- int ey = miss.e >> 2;
- int fx = miss.f & 0x03;
- int fy = miss.f >> 2;
- int gx = miss.g & 0x03;
- int gy = miss.g >> 2;
- int hx = miss.h & 0x03;
- int hy = miss.h >> 2;
- SkPath path, out;
- path.setFillType(miss.fType);
- path.moveTo(ax, ay);
- path.lineTo(bx, by);
- path.lineTo(cx, cy);
- path.lineTo(dx, dy);
- path.close();
- path.moveTo(ex, ey);
- path.lineTo(fx, fy);
- path.lineTo(gx, gy);
- path.lineTo(hx, hy);
- path.close();
- testSimplify(path, true, out, bitmap);
- }
-}
diff --git a/experimental/Intersection/EdgeWalkerPolygons_Test.cpp b/experimental/Intersection/EdgeWalkerPolygons_Test.cpp
deleted file mode 100644
index 8cda8e6b56..0000000000
--- a/experimental/Intersection/EdgeWalkerPolygons_Test.cpp
+++ /dev/null
@@ -1,790 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "EdgeWalker_Test.h"
-#include "Intersection_Tests.h"
-#include "SkBitmap.h"
-
-static SkBitmap bitmap;
-
-static void testSimplifyTriangle() {
- SkPath path, out;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(10,10); // triangle |\ .
- path.lineTo(10,30); // |_\ .
- path.lineTo(20,30);
- path.close();
- path.moveTo(20,10); // triangle /|
- path.lineTo(10,30); // /_|
- path.lineTo(20,30);
- path.close();
- testSimplify(path, true, out, bitmap); // expect |\/|
- // |__|
-}
-
-static void testSimplifyTriangle3() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(0, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(3, 1);
- path.close();
- testSimplify(path, true, out, bitmap);
-}
-
-static void testSimplifyTriangle4() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(0, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(2, 1);
- path.close();
- testSimplify(path, true, out, bitmap);
-}
-
-static void testSimplifyTriangle5() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(0, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 1);
- path.lineTo(2, 1);
- path.close();
- testSimplify(path, true, out, bitmap);
-}
-
-static void testSimplifyTriangle6() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(0, 1);
- path.lineTo(0, 0);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 1);
- path.lineTo(3, 1);
- path.lineTo(0, 0);
- path.close();
- testSimplify(path, true, out, bitmap);
-}
-
-static void testSimplifyTriangle7() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(0, 1);
- path.lineTo(0, 0);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 1);
- path.lineTo(0, 2);
- path.lineTo(0, 0);
- path.close();
- testSimplify(path, true, out, bitmap);
-}
-
-static void testSimplifyTriangle8() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(0, 1);
- path.lineTo(0, 0);
- path.close();
- path.moveTo(0, 1);
- path.lineTo(1, 2);
- path.lineTo(1, 3);
- path.lineTo(0, 1);
- path.close();
- testSimplify(path, true, out, bitmap);
-}
-
-static void testSimplifyTriangle9() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(1, 1);
- path.lineTo(0, 0);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 1);
- path.lineTo(2, 1);
- path.lineTo(0, 0);
- path.close();
- testSimplify(path, true, out, bitmap);
-}
-
-static void testSimplifyTriangle10() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(1, 1);
- path.lineTo(0, 0);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(2, 0);
- path.lineTo(0, 1);
- path.lineTo(0, 0);
- path.close();
- testSimplify(path, true, out, bitmap);
-}
-
-static void testSimplifyTriangle11() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(0, 2);
- path.lineTo(0, 0);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(2, 1);
- path.lineTo(2, 2);
- path.lineTo(0, 0);
- path.close();
- testSimplify(path, true, out, bitmap);
-}
-
-static void testSimplifyTriangle12() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(1, 2);
- path.lineTo(0, 0);
- path.close();
- path.moveTo(2, 0);
- path.lineTo(0, 3);
- path.lineTo(1, 1);
- path.lineTo(2, 0);
- path.close();
- testSimplify(path, true, out, bitmap);
-}
-
-static void testSimplifyTriangle13() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(0, 3);
- path.lineTo(0, 0);
- path.close();
- path.moveTo(3, 0);
- path.lineTo(0, 3);
- path.lineTo(1, 1);
- path.lineTo(3, 0);
- path.close();
- testSimplify(path, true, out, bitmap);
-}
-
-static void testSimplifyTriangle14() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(0, 1);
- path.lineTo(0, 0);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(0, 1);
- path.lineTo(0, 0);
- path.close();
- testSimplify(path, true, out, bitmap);
-}
-
-static void testSimplifyTriangle15() {
- SkPath path, out;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0, 0);
- path.lineTo(0, 1);
- path.lineTo(1, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 1);
- path.lineTo(2, 2);
- path.close();
- testSimplify(path, true, out, bitmap);
-}
-
-static void testSimplifyTriangle16() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.lineTo(0, 1);
- path.lineTo(1, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 1);
- path.lineTo(1, 3);
- path.close();
- testSimplify(path, true, out, bitmap);
-}
-
-static void testSimplifyTriangle17() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.lineTo(0, 1);
- path.lineTo(1, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 3);
- path.lineTo(0, 1);
- path.close();
- testSimplify(path, true, out, bitmap);
-}
-
-static void testSimplifyTriangle18() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.lineTo(0, 1);
- path.lineTo(1, 2);
- path.close();
- path.moveTo(1, 0);
- path.lineTo(0, 1);
- path.lineTo(0, 3);
- path.close();
- testSimplify(path, true, out, bitmap);
-}
-
-static void testSimplifyTriangle19() {
- SkPath path, out;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0, 0);
- path.lineTo(0, 1);
- path.lineTo(3, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 1);
- path.lineTo(2, 1);
- path.close();
- testSimplify(path, true, out, bitmap);
-}
-
-static void testSimplifyTriangle20() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.lineTo(2, 1);
- path.lineTo(1, 3);
- path.close();
- path.moveTo(2, 0);
- path.lineTo(3, 2);
- path.lineTo(0, 3);
- path.close();
- testSimplify(path, true, out, bitmap);
-}
-
-static void testSimplifyTriangle21() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(1, 2);
- path.close();
- path.moveTo(2, 0);
- path.lineTo(2, 1);
- path.lineTo(0, 3);
- path.close();
- testSimplify(path, true, out, bitmap);
-}
-
-static void testSimplifyDegenerateTriangle1() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.lineTo(0, 0);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.lineTo(0, 0);
- path.close();
- testSimplify(path, true, out, bitmap);
-}
-
-static void testSimplifyDegenerateTriangle2() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.lineTo(1, 1);
- path.lineTo(2, 2);
- path.close();
- path.moveTo(1, 0);
- path.lineTo(2, 2);
- path.lineTo(3, 3);
- path.close();
- testSimplify(path, true, out, bitmap);
-}
-
-static void testSimplifyWindingParallelogram() {
- SkPath path, out;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(20,10); // parallelogram _
- path.lineTo(30,30); // \ \ .
- path.lineTo(40,30); // \_\ .
- path.lineTo(30,10);
- path.close();
- path.moveTo(20,10); // parallelogram _
- path.lineTo(10,30); // / /
- path.lineTo(20,30); // /_/
- path.lineTo(30,10);
- path.close();
- testSimplify(path, true, out, bitmap); // expect _
- // / \ .
-} // /___\ .
-
-static void testSimplifyXorParallelogram() {
- SkPath path, out;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(20,10); // parallelogram _
- path.lineTo(30,30); // \ \ .
- path.lineTo(40,30); // \_\ .
- path.lineTo(30,10);
- path.close();
- path.moveTo(20,10); // parallelogram _
- path.lineTo(10,30); // / /
- path.lineTo(20,30); // /_/
- path.lineTo(30,10);
- path.close();
- testSimplify(path, true, out, bitmap); // expect _
-} // \ /
-
-static void testSimplifyTriangle2() {
- SkPath path, out;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(10,10); // triangle |\ .
- path.lineTo(10,30); // |_\ .
- path.lineTo(20,30);
- path.close();
- path.moveTo(10,10); // triangle _
- path.lineTo(20,10); // \ |
- path.lineTo(20,30); // \|
- path.close(); // _
- testSimplify(path, true, out, bitmap); // expect | |
-} // |_|
-
-#if 0
-static void testPathTriangleRendering() {
- SkPath one, two;
- one.moveTo(0, 0);
- one.lineTo(3, 3);
- one.lineTo(0, 3);
- one.lineTo(1, 2);
- one.close();
- for (float x = .1f; x <= 2.9ff; x += .1f) {
- SkDebugf("%s x=%g\n", __FUNCTION__, x);
- two.moveTo(0, 0);
- two.lineTo(x, x);
- two.lineTo(3, 3);
- two.lineTo(0, 3);
- two.lineTo(1, 2);
- two.close();
- comparePaths(one, two);
- two.reset();
- }
-}
-#endif
-
-static void simplify(const char* functionName, const SkPath& path,
- bool fill, SkPath& out) {
- if (false) SkDebugf("%s\n", functionName);
- simplify(path, fill, out);
-}
-
-static void testSimplifySkinnyTriangle1() {
- for (int x = 1; x < 255; ++x) {
- SkPath path, out;
- path.moveTo((x * 101) % 10, 0);
- path.lineTo((x * 91) % 10, 1000);
- path.lineTo((x * 71) % 10, 2000);
- path.lineTo((x * 51) % 10, 3000);
- path.close();
- path.moveTo((x * 101) % 20, 0);
- path.lineTo((x * 91) % 20, 1000);
- path.lineTo((x * 71) % 20, 2000);
- path.lineTo((x * 51) % 20, 3000);
- path.close();
- path.moveTo((x * 101) % 30, 0);
- path.lineTo((x * 91) % 30, 1000);
- path.lineTo((x * 71) % 30, 2000);
- path.lineTo((x * 51) % 30, 3000);
- path.close();
- simplify(path, true, out);
- }
-}
-
-static void testSimplifySkinnyTriangle2() {
- SkPath path, out;
-#if 01
-path.moveTo(591.091064f, 627.534851f);
-path.lineTo(541.088135f, 560.707642f);
-path.lineTo(491.085175f, 493.880310f);
-path.lineTo(441.082214f, 427.053101f);
-//path.lineTo(591.091064f, 627.534851f);
-path.close();
-#endif
-path.moveTo(317.093445f, 592.013306f);
-path.lineTo(366.316162f, 542.986572f);
-path.lineTo(416.051514f, 486.978577f);
-path.lineTo(465.786865f, 430.970581f);
-//path.lineTo(317.093445f, 592.013306f);
-path.close();
-#if 0
-path.moveTo(289.392517f, 517.138489f);
-path.lineTo(249.886078f, 508.598022f);
-path.lineTo(217.110916f, 450.916443f);
-path.lineTo(196.621033f, 394.917633f);
-//path.lineTo(289.392517f, 517.138489f);
-path.close();
-#endif
- simplify(__FUNCTION__, path, true, out);
-}
-
-static void testSimplifySkinnyTriangle3() {
- SkPath path, out;
- path.moveTo(591, 627.534851f);
- path.lineTo(541, 560.707642f);
- path.lineTo(491, 493.880310f);
- path.lineTo(441, 427.053101f);
- path.close();
- path.moveTo(317, 592.013306f);
- path.lineTo(366, 542.986572f);
- path.lineTo(416, 486.978577f);
- path.lineTo(465, 430.970581f);
- path.close();
- simplify(__FUNCTION__, path, true, out);
-}
-
-static void testSimplifySkinnyTriangle4() {
- SkPath path, out;
-path.moveTo(572.655212f, 614.959961f);
-path.lineTo(524.618896f, 549.339600f);
-path.lineTo(476.582581f, 483.719269f);
-path.lineTo(428.546265f, 418.098938f);
-path.lineTo(572.655212f, 614.959961f);
-path.close();
-path.moveTo(312.166382f, 583.723083f);
-path.lineTo(361.047791f, 529.824219f);
-path.lineTo(409.929230f, 475.925354f);
-path.lineTo(458.810669f, 422.026520f);
-path.lineTo(312.166382f, 583.723083f);
-path.close();
-path.moveTo(278.742737f, 508.065643f);
-path.lineTo(241.475800f, 493.465118f);
-path.lineTo(210.344177f, 437.315125f);
-path.lineTo(197.019455f, 383.794556f);
-path.lineTo(278.742737f, 508.065643f);
-path.close();
- simplify(__FUNCTION__, path, true, out);
-}
-
-static void testSimplifySkinnyTriangle5() {
- SkPath path, out;
-path.moveTo(554.690613f, 602.286072f);
-path.lineTo(508.590057f, 537.906250f);
-path.lineTo(462.489441f, 473.526520f);
-path.lineTo(416.388855f, 409.146729f);
-path.lineTo(554.690613f, 602.286072f);
-path.close();
-path.moveTo(307.216949f, 575.189270f);
-path.lineTo(355.826965f, 516.804688f);
-path.lineTo(403.815918f, 464.990753f);
-path.lineTo(451.804871f, 413.176819f);
-path.lineTo(307.216949f, 575.189270f);
-path.close();
-path.moveTo(271.998901f, 521.301025f);
-path.lineTo(234.619705f, 499.687683f);
-path.lineTo(203.059692f, 441.332336f);
-path.lineTo(195.994370f, 386.856506f);
-path.lineTo(271.998901f, 521.301025f);
-path.close();
- simplify(__FUNCTION__, path, true, out);
-}
-
-static void testSimplifySkinnyTriangle6() {
- SkPath path, out;
-path.moveTo(591.091064f, 627.534851f);
-path.lineTo(541.088135f, 560.707642f);
-path.lineTo(491.085175f, 493.880310f);
-path.lineTo(441.082214f, 427.053101f);
-path.lineTo(591.091064f, 627.534851f);
-path.close();
-path.moveTo(317.093445f, 592.013306f);
-path.lineTo(366.316162f, 542.986572f);
-path.lineTo(416.051514f, 486.978577f);
-path.lineTo(465.786865f, 430.970581f);
-path.lineTo(317.093445f, 592.013306f);
-path.close();
-path.moveTo(289.392517f, 517.138489f);
-path.lineTo(249.886078f, 508.598022f);
-path.lineTo(217.110916f, 450.916443f);
-path.lineTo(196.621033f, 394.917633f);
-path.lineTo(289.392517f, 517.138489f);
-path.close();
- simplify(__FUNCTION__, path, true, out);
-}
-
-static void testSimplifyTriangle22() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(0, 2);
- path.close();
- path.moveTo(1, 0);
- path.lineTo(0, 2);
- path.lineTo(0, 1);
- path.close();
- testSimplify(path, true, out, bitmap);
-}
-
-static void testSimplifyTriangle23() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.lineTo(0, 0);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 1);
- path.lineTo(1, 2);
- path.close();
- testSimplify(path, true, out, bitmap);
-}
-
-static void testSimplifyTriangle24() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.lineTo(0, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(0, 1);
- path.close();
- testSimplify(path, true, out, bitmap);
-}
-
-static void testSimplifySkinnyTriangle7() {
- SkPath path, out;
-path.moveTo(487.502319f, 550.811279f);
-path.lineTo(448.826050f, 491.720123f);
-path.lineTo(410.149780f, 432.628967f);
-path.lineTo(371.473572f, 373.537781f);
-path.lineTo(487.502319f, 550.811279f);
-path.close();
-path.moveTo(295.817108f, 532.655579f);
-path.lineTo(342.896271f, 485.912292f);
-path.lineTo(389.975433f, 439.169006f);
-path.lineTo(437.054596f, 392.425781f);
-path.lineTo(295.817108f, 532.655579f);
-path.close();
-path.moveTo(239.726822f, 575.025269f);
-path.lineTo(204.117569f, 521.429688f);
-path.lineTo(171.275452f, 454.110382f);
-path.lineTo(193.328583f, 397.859497f);
-path.lineTo(239.726822f, 575.025269f);
-path.close();
- simplify(__FUNCTION__, path, true, out);
-}
-
-static void testSimplifySkinnyTriangle8() {
- SkPath path, out;
-path.moveTo(441.943115f, 511.678040f);
-path.lineTo(408.487549f, 456.880920f);
-path.lineTo(375.031952f, 402.083801f);
-path.lineTo(341.576385f, 347.286682f);
-path.lineTo(441.943115f, 511.678040f);
-path.close();
-path.moveTo(297.548492f, 557.246704f);
-path.lineTo(350.768494f, 507.627014f);
-path.lineTo(403.988525f, 458.007385f);
-path.lineTo(457.208527f, 408.387695f);
-path.lineTo(297.548492f, 557.246704f);
-path.close();
-path.moveTo(209.857895f, 615.802979f);
-path.lineTo(178.249481f, 534.230347f);
-path.lineTo(144.905640f, 460.056824f);
-path.lineTo(192.953125f, 404.972900f);
-path.lineTo(209.857895f, 615.802979f);
-path.close();
- simplify(__FUNCTION__, path, true, out);
-}
-
-static void testSimplifySkinnyTriangle9() {
- SkPath path, out;
-path.moveTo(439.867065f, 528.291931f);
-path.lineTo(405.413025f, 469.107178f);
-path.lineTo(370.958954f, 409.922363f);
-path.lineTo(336.504883f, 350.737610f);
-path.lineTo(439.867065f, 528.291931f);
-path.close();
-path.moveTo(298.922455f, 573.251953f);
-path.lineTo(356.360962f, 521.905090f);
-path.lineTo(413.799438f, 470.558228f);
-path.lineTo(471.237915f, 419.211365f);
-path.lineTo(298.922455f, 573.251953f);
-path.close();
-path.moveTo(187.200775f, 643.035156f);
-path.lineTo(159.713165f, 540.993774f);
-path.lineTo(126.257164f, 462.198517f);
-path.lineTo(193.534012f, 409.266235f);
-path.lineTo(187.200775f, 643.035156f);
-path.close();
-path.close();
- simplify(__FUNCTION__, path, true, out);
-}
-
-static void testSimplifySkinnyTriangle10() {
- SkPath path, out;
-#if 0
-path.moveTo(99.270325f, 239.365234f);
-path.lineTo(105.967056f, 173.361206f);
-path.lineTo(148.821381f, 141.309891f);
-path.lineTo(159.101013f, 189.235138f);
-path.lineTo(99.270325f, 239.365234f);
-path.close();
-#endif
-path.moveTo(213.673737f, 413.292938f);
-path.lineTo(225.200134f, 343.616821f);
-path.lineTo(236.726532f, 273.940704f);
-path.lineTo(219.386414f, 231.373322f);
-path.lineTo(213.673737f, 413.292938f);
-path.close();
-path.moveTo(43.485352f, 308.984497f);
-path.lineTo(122.610657f, 305.950134f);
-path.lineTo(201.735962f, 302.915802f);
-path.lineTo(280.861267f, 299.881470f);
-path.lineTo(43.485352f, 308.984497f);
-path.close();
- simplify(__FUNCTION__, path, true, out);
-}
-
-static void testSimplifySkinnyTriangle11() {
- SkPath path, out;
-path.moveTo(-177.878387f, 265.368988f);
-path.lineTo(-254.415771f, 303.709961f);
-path.lineTo(-317.465363f, 271.325562f);
-path.lineTo(-374.520386f, 207.507660f);
-path.lineTo(-177.878387f, 265.368988f);
-path.close();
-path.moveTo(-63.582489f, -3.679123f);
-path.lineTo(-134.496841f, 26.434566f);
-path.lineTo(-205.411209f, 56.548256f);
-path.lineTo(-276.325562f, 86.661942f);
-path.lineTo(-63.582489f, -3.679123f);
-path.close();
-path.moveTo(-57.078423f, 162.633453f);
-path.lineTo(-95.963928f, 106.261139f);
-path.lineTo(-134.849457f, 49.888824f);
-path.lineTo(-173.734955f, -6.483480f);
-path.lineTo(-57.078423f, 162.633453f);
-path.close();
- simplify(__FUNCTION__, path, true, out);
-}
-
-static void testSimplifySkinnyTriangle12() {
- SkPath path, out;
-path.moveTo(98.666489f, -94.295059f);
-path.lineTo(156.584320f, -61.939133f);
-path.lineTo(174.672974f, -12.343765f);
-path.lineTo(158.622345f, 52.028267f);
-path.lineTo(98.666489f, -94.295059f);
-path.close();
-path.moveTo(-133.225616f, -48.622055f);
-path.lineTo(-73.855499f, -10.375397f);
-path.lineTo(-14.485367f, 27.871277f);
-path.lineTo(44.884750f, 66.117935f);
-path.lineTo(-133.225616f, -48.622055f);
-path.close();
-path.moveTo( 9.030045f, -163.413132f);
-path.lineTo(-19.605331f, -89.588760f);
-path.lineTo(-48.240707f, -15.764404f);
-path.lineTo(-76.876053f, 58.059944f);
-path.lineTo( 9.030045f, -163.413132f);
-path.close();
- simplify(__FUNCTION__, path, true, out);
-}
-
-static void testSimplifySkinnyTriangle13() {
- SkPath path, out;
-path.moveTo(340.41568f, -170.97171f);
-path.lineTo(418.846893f, -142.428329f);
-path.lineTo(497.278107f, -113.884933f);
-path.lineTo(449.18222f, -45.6723022f);
-path.lineTo(340.41568f, -170.97171f);
-path.close();
-path.moveTo(326.610535f, 34.0393639f);
-path.lineTo(371.334595f, -14.9620667f);
-path.lineTo(416.058624f, -63.9634857f);
-path.lineTo(460.782654f, -112.96492f);
-path.lineTo(326.610535f, 34.0393639f);
-path.close();
- simplify(__FUNCTION__, path, true, out);
-}
-
-static void (*simplifyTests[])() = {
- testSimplifySkinnyTriangle13,
- testSimplifySkinnyTriangle12,
- testSimplifySkinnyTriangle11,
- testSimplifySkinnyTriangle10,
- testSimplifySkinnyTriangle9,
- testSimplifySkinnyTriangle8,
- testSimplifySkinnyTriangle7,
- testSimplifySkinnyTriangle6,
- testSimplifySkinnyTriangle5,
- testSimplifySkinnyTriangle4,
- testSimplifySkinnyTriangle3,
- testSimplifySkinnyTriangle2,
- testSimplifySkinnyTriangle1,
- testSimplifyTriangle24,
- testSimplifyTriangle23,
- testSimplifyTriangle22,
- testSimplifyDegenerateTriangle2,
- testSimplifyDegenerateTriangle1,
- testSimplifyTriangle21,
- testSimplifyTriangle20,
- testSimplifyTriangle19,
- testSimplifyTriangle18,
- testSimplifyTriangle17,
- testSimplifyTriangle16,
- testSimplifyTriangle15,
- testSimplifyTriangle14,
- testSimplifyTriangle13,
- testSimplifyTriangle12,
- testSimplifyTriangle11,
- testSimplifyTriangle10,
- testSimplifyTriangle7,
- testSimplifyTriangle9,
- testSimplifyTriangle8,
- testSimplifyTriangle6,
- testSimplifyTriangle5,
- testSimplifyTriangle4,
- testSimplifyTriangle3,
- testSimplifyTriangle,
- testSimplifyTriangle2,
- testSimplifyWindingParallelogram,
- testSimplifyXorParallelogram,
-// testPathTriangleRendering,
-};
-
-static size_t simplifyTestsCount = sizeof(simplifyTests) / sizeof(simplifyTests[0]);
-
-static void (*firstTest)() = testSimplifySkinnyTriangle12;
-
-void SimplifyPolygonPaths_Test() {
- size_t index = 0;
- if (firstTest) {
- while (index < simplifyTestsCount && simplifyTests[index] != firstTest) {
- ++index;
- }
- }
- bool firstTestComplete = false;
- for ( ; index < simplifyTestsCount; ++index) {
- (*simplifyTests[index])();
- if (simplifyTests[index] == testSimplifySkinnyTriangle2) {
- if (false) SkDebugf("%s last fast skinny test\n", __FUNCTION__);
- }
- firstTestComplete = true;
- }
-}
diff --git a/experimental/Intersection/EdgeWalkerQuadralaterals_Test.cpp b/experimental/Intersection/EdgeWalkerQuadralaterals_Test.cpp
deleted file mode 100644
index 92e474b84a..0000000000
--- a/experimental/Intersection/EdgeWalkerQuadralaterals_Test.cpp
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "EdgeWalker_Test.h"
-#include "Intersection_Tests.h"
-#include "SkBitmap.h"
-
-static SkBitmap bitmap;
-
-static void testSimplifyQuad1() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(3, 2);
- path.lineTo(3, 3);
- path.close();
- path.moveTo(1, 0);
- path.lineTo(1, 3);
- path.lineTo(1, 3);
- path.lineTo(1, 3);
- path.close();
- testSimplify(path, true, out, bitmap);
-}
-
-static void testSimplifyQuad2() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.lineTo(0, 0);
- path.lineTo(0, 2);
- path.close();
- path.moveTo(0, 1);
- path.lineTo(0, 1);
- path.lineTo(1, 1);
- path.lineTo(0, 2);
- path.close();
- testSimplify(path, true, out, bitmap);
-}
-
-static void testSimplifyQuad3() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(1, 2);
- path.close();
- path.moveTo(0, 1);
- path.lineTo(1, 1);
- path.lineTo(2, 1);
- path.lineTo(0, 2);
- path.close();
- testSimplify(path, true, out, bitmap);
-}
-
-static void testSimplifyQuad4() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(2, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(2, 1);
- path.lineTo(3, 1);
- path.lineTo(3, 3);
- path.close();
- testSimplify(path, true, out, bitmap);
-}
-
-static void testSimplifyQuad5() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(3, 2);
- path.close();
- path.moveTo(0, 1);
- path.lineTo(1, 1);
- path.lineTo(2, 1);
- path.lineTo(0, 2);
- path.close();
- testSimplify(path, true, out, bitmap);
-}
-
-static void testSimplifyQuad6() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(1, 1);
- path.lineTo(3, 3);
- path.close();
- path.moveTo(1, 1);
- path.lineTo(1, 1);
- path.lineTo(1, 1);
- path.lineTo(2, 2);
- path.close();
- testSimplify(path, true, out, bitmap);
-}
-
-static void (*simplifyTests[])() = {
- testSimplifyQuad6,
- testSimplifyQuad5,
- testSimplifyQuad4,
- testSimplifyQuad3,
- testSimplifyQuad2,
- testSimplifyQuad1,
-};
-
-static size_t simplifyTestsCount = sizeof(simplifyTests) / sizeof(simplifyTests[0]);
-
-static void (*firstTest)() = 0;
-
-void SimplifyQuadralateralPaths_Test() {
- size_t index = 0;
- if (firstTest) {
- while (index < simplifyTestsCount && simplifyTests[index] != firstTest) {
- ++index;
- }
- }
- for ( ; index < simplifyTestsCount; ++index) {
- (*simplifyTests[index])();
- }
-}
diff --git a/experimental/Intersection/EdgeWalkerQuadratic4x4_Test.cpp b/experimental/Intersection/EdgeWalkerQuadratic4x4_Test.cpp
deleted file mode 100644
index a55f6ab9a4..0000000000
--- a/experimental/Intersection/EdgeWalkerQuadratic4x4_Test.cpp
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "EdgeWalker_Test.h"
-#include "Intersection_Tests.h"
-#include "SkBitmap.h"
-#include "SkCanvas.h"
-
-
-static void* testSimplify4x4QuadraticsMain(void* data)
-{
- SkASSERT(data);
- State4& state = *(State4*) data;
- char pathStr[1024];
- bzero(pathStr, sizeof(pathStr));
- do {
- int ax = state.a & 0x03;
- int ay = state.a >> 2;
- int bx = state.b & 0x03;
- int by = state.b >> 2;
- int cx = state.c & 0x03;
- int cy = state.c >> 2;
- int dx = state.d & 0x03;
- int dy = state.d >> 2;
- for (int e = 0 ; e < 16; ++e) {
- int ex = e & 0x03;
- int ey = e >> 2;
- for (int f = e ; f < 16; ++f) {
- int fx = f & 0x03;
- int fy = f >> 2;
- for (int g = f ; g < 16; ++g) {
- int gx = g & 0x03;
- int gy = g >> 2;
- for (int h = g ; h < 16; ++h) {
- int hx = h & 0x03;
- int hy = h >> 2;
- SkPath path, out;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(ax, ay);
- path.quadTo(bx, by, cx, cy);
- path.lineTo(dx, dy);
- path.close();
- path.moveTo(ex, ey);
- path.lineTo(fx, fy);
- path.quadTo(gx, gy, hx, hy);
- path.close();
- if (1) { // gdb: set print elements 400
- char* str = pathStr;
- str += sprintf(str, " path.moveTo(%d, %d);\n", ax, ay);
- str += sprintf(str, " path.quadTo(%d, %d, %d, %d);\n", bx, by, cx, cy);
- str += sprintf(str, " path.lineTo(%d, %d);\n", dx, dy);
- str += sprintf(str, " path.close();\n");
- str += sprintf(str, " path.moveTo(%d, %d);\n", ex, ey);
- str += sprintf(str, " path.lineTo(%d, %d);\n", fx, fy);
- str += sprintf(str, " path.quadTo(%d, %d, %d, %d);\n", gx, gy, hx, hy);
- str += sprintf(str, " path.close();\n");
- }
- outputProgress(state, pathStr, SkPath::kWinding_FillType);
- testSimplifyx(path, false, out, state, pathStr);
- state.testsRun++;
- path.setFillType(SkPath::kEvenOdd_FillType);
- outputProgress(state, pathStr, SkPath::kEvenOdd_FillType);
- testSimplifyx(path, true, out, state, pathStr);
- state.testsRun++;
- }
- }
- }
- }
- } while (runNextTestSet(state));
- return NULL;
-}
-
-void Simplify4x4QuadraticsThreaded_Test(int& testsRun)
-{
- SkDebugf("%s\n", __FUNCTION__);
-#ifdef SK_DEBUG
- gDebugMaxWindSum = 4; // FIXME: 3?
- gDebugMaxWindValue = 4;
-#endif
- const char testStr[] = "testQuadratic";
- initializeTests(testStr, sizeof(testStr));
- int testsStart = testsRun;
- int a = 0;
-#define SKIP_A 0
-#if SKIP_A
- a = 2;
-#endif
- for (; a < 16; ++a) {
- for (int b = a ; b < 16; ++b) {
- for (int c = b ; c < 16; ++c) {
- for (int d = c; d < 16; ++d) {
- testsRun += dispatchTest4(testSimplify4x4QuadraticsMain,
- a, b, c, d);
- }
- if (!gRunTestsInOneThread) SkDebugf(".");
- }
- if (!gRunTestsInOneThread) SkDebugf("%d", b);
- }
- if (!gRunTestsInOneThread) SkDebugf("\n%d", a);
- }
- testsRun += waitForCompletion();
- SkDebugf("%s tests=%d total=%d\n", __FUNCTION__, testsRun - testsStart, testsRun);
-}
diff --git a/experimental/Intersection/EdgeWalkerQuadratics_Test.cpp b/experimental/Intersection/EdgeWalkerQuadratics_Test.cpp
deleted file mode 100644
index febc972259..0000000000
--- a/experimental/Intersection/EdgeWalkerQuadratics_Test.cpp
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "EdgeWalker_Test.h"
-#include "Intersection_Tests.h"
-#include "SkBitmap.h"
-
-static SkBitmap bitmap;
-
-static void testSimplifyQuadratic1() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.quadTo(1, 0, 1, 1);
- path.close();
- path.moveTo(1, 0);
- path.quadTo(0, 0, 0, 1);
- path.close();
- testSimplify(path, true, out, bitmap);
-}
-
-static void testSimplifyQuadratic2() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.quadTo(20, 0, 20, 20);
- path.close();
- path.moveTo(20, 0);
- path.quadTo(0, 0, 0, 20);
- path.close();
- testSimplify(path, true, out, bitmap);
-}
-
-static void testSimplifyQuadratic3() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.quadTo(20, 0, 20, 20);
- path.close();
- path.moveTo(0, 20);
- path.quadTo(0, 0, 20, 0);
- path.close();
- testSimplify(path, true, out, bitmap);
-}
-
-static void testSimplifyQuadratic4() {
- SkPath path, out;
- path.moveTo(0, 20);
- path.quadTo(20, 0, 40, 20);
- path.close();
- path.moveTo(40, 10);
- path.quadTo(20, 30, 0, 10);
- path.close();
- testSimplify(path, true, out, bitmap);
- drawAsciiPaths(path, out, true);
-}
-
-static void testSimplifyQuadratic5() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.lineTo(0, 0);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(0, 0, 0, 1);
- path.close();
- testSimplify(path, true, out, bitmap);
- drawAsciiPaths(path, out, true);
-}
-
-static void testSimplifyQuadratic6() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.lineTo(1, 0);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(1, 0, 0, 1);
- path.close();
- testSimplify(path, true, out, bitmap);
- drawAsciiPaths(path, out, true);
-}
-
-static void testSimplifyQuadratic7() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.lineTo(0, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(1, 0, 0, 2);
- path.close();
- testSimplify(path, true, out, bitmap);
- drawAsciiPaths(path, out, true);
-}
-
-static void testSimplifyQuadratic8() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.lineTo(0, 0);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(1, 0, 0, 2);
- path.close();
- testSimplify(path, true, out, bitmap);
- drawAsciiPaths(path, out, true);
-}
-
-static void testSimplifyQuadratic9() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.lineTo(1, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(1, 0, 2, 2);
- path.close();
- testSimplify(path, true, out, bitmap);
- drawAsciiPaths(path, out, true);
-}
-
-static void testSimplifyQuadratic10() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.lineTo(0, 0);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 1);
- path.quadTo(1, 1, 1, 2);
- path.close();
- testSimplify(path, true, out, bitmap);
- drawAsciiPaths(path, out, true);
-}
-
-static void testSimplifyQuadratic11() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.lineTo(0, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(2, 1);
- path.quadTo(2, 2, 3, 3);
- path.close();
- testSimplify(path, true, out, bitmap);
- drawAsciiPaths(path, out, true);
-}
-
-static void testSimplifyQuadratic12() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.lineTo(0, 2);
- path.lineTo(0, 0);
- path.close();
- path.moveTo(3, 0);
- path.quadTo(1, 1, 0, 2);
- path.lineTo(3, 0);
- path.close();
- testSimplify(path, true, out, bitmap);
- drawAsciiPaths(path, out, true);
-}
-
-static void testSimplifyQuadratic13() {
- SkPath path, out;
-path.moveTo(0, 0);
-path.quadTo(0, 0, 1, 0);
-path.lineTo(1, 1);
-path.lineTo(0, 0);
-path.close();
-path.moveTo(0, 0);
-path.quadTo(3, 0, 1, 1);
-path.lineTo(0, 0);
-path.close();
- testSimplify(path, true, out, bitmap);
- drawAsciiPaths(path, out, true);
-}
-
-static void testSimplifyQuadratic14() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.lineTo(1, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(0, 1, 2, 1);
- path.close();
- testSimplify(path, true, out, bitmap);
- drawAsciiPaths(path, out, true);
-}
-
-static void testSimplifyQuadratic15() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.quadTo(0, 0, 1, 3);
- path.lineTo(3, 3);
- path.close();
- path.moveTo(0, 1);
- path.lineTo(1, 1);
- path.quadTo(0, 3, 3, 3);
- path.close();
- testSimplify(path, true, out, bitmap);
- drawAsciiPaths(path, out, true);
-}
-
-static void testSimplifyQuadratic16() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.lineTo(0, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(1, 0, 0, 1);
- path.close();
- testSimplify(path, true, out, bitmap);
- drawAsciiPaths(path, out, true);
-}
-
-static void testSimplifyQuadratic17() {
- SkPath path, out;
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.lineTo(2, 2);
- path.close();
- path.moveTo(0, 1);
- path.lineTo(0, 1);
- path.quadTo(2, 1, 3, 3);
- path.close();
- testSimplify(path, true, out, bitmap);
- drawAsciiPaths(path, out, true);
-}
-
-static void (*simplifyTests[])() = {
- testSimplifyQuadratic17,
- testSimplifyQuadratic16,
- testSimplifyQuadratic15,
- testSimplifyQuadratic14,
- testSimplifyQuadratic13,
- testSimplifyQuadratic12,
- testSimplifyQuadratic11,
- testSimplifyQuadratic10,
- testSimplifyQuadratic9,
- testSimplifyQuadratic8,
- testSimplifyQuadratic7,
- testSimplifyQuadratic6,
- testSimplifyQuadratic5,
- testSimplifyQuadratic4,
- testSimplifyQuadratic3,
- testSimplifyQuadratic2,
- testSimplifyQuadratic1,
-};
-
-static size_t simplifyTestsCount = sizeof(simplifyTests) / sizeof(simplifyTests[0]);
-
-static void (*firstTest)() = testSimplifyQuadratic14;
-static bool skipAll = false;
-
-void SimplifyQuadraticPaths_Test() {
- if (skipAll) {
- return;
- }
- size_t index = 0;
- if (firstTest) {
- while (index < simplifyTestsCount && simplifyTests[index] != firstTest) {
- ++index;
- }
- }
- bool firstTestComplete = false;
- for ( ; index < simplifyTestsCount; ++index) {
- (*simplifyTests[index])();
- if (simplifyTests[index] == testSimplifyQuadratic1) {
- SkDebugf("%s last fast quad test\n", __FUNCTION__);
- }
- firstTestComplete = true;
- }
-}
diff --git a/experimental/Intersection/EdgeWalkerRectangles_Test.cpp b/experimental/Intersection/EdgeWalkerRectangles_Test.cpp
deleted file mode 100644
index 5f1b7f876b..0000000000
--- a/experimental/Intersection/EdgeWalkerRectangles_Test.cpp
+++ /dev/null
@@ -1,469 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "EdgeWalker_Test.h"
-#include "Intersection_Tests.h"
-#include "SkBitmap.h"
-
-static SkBitmap bitmap;
-
-static void testSimplifyCoincidentInner() {
- SkPath path, out;
- path.setFillType(SkPath::kWinding_FillType);
- path.addRect(10, 10, 60, 60, SkPath::kCCW_Direction);
- path.addRect(20, 20, 50, 50, SkPath::kCW_Direction);
- path.addRect(20, 30, 40, 40, SkPath::kCW_Direction);
- testSimplify(path, true, out, bitmap);
-}
-
-static void testSimplifyCoincidentVertical() {
- SkPath path, out;
- path.setFillType(SkPath::kWinding_FillType);
- path.addRect(10, 10, 30, 30);
- path.addRect(10, 30, 30, 40);
- simplify(path, true, out);
- SkRect rect;
- if (!out.isRect(&rect)) {
- SkDebugf("%s expected rect\n", __FUNCTION__);
- }
- if (rect != SkRect::MakeLTRB(10, 10, 30, 40)) {
- SkDebugf("%s expected union\n", __FUNCTION__);
- }
-}
-
-static void testSimplifyCoincidentHorizontal() {
- SkPath path, out;
- path.setFillType(SkPath::kWinding_FillType);
- path.addRect(10, 10, 30, 30);
- path.addRect(30, 10, 40, 30);
- simplify(path, true, out);
- SkRect rect;
- if (!out.isRect(&rect)) {
- SkDebugf("%s expected rect\n", __FUNCTION__);
- }
- if (rect != SkRect::MakeLTRB(10, 10, 40, 30)) {
- SkDebugf("%s expected union\n", __FUNCTION__);
- }
-}
-
-static void testSimplifyMulti() {
- SkPath path, out;
- path.setFillType(SkPath::kWinding_FillType);
- path.addRect(10, 10, 30, 30);
- path.addRect(20, 20, 40, 40);
- simplify(path, true, out);
- SkPath expected;
- expected.setFillType(SkPath::kEvenOdd_FillType);
- expected.moveTo(10,10); // two cutout corners
- expected.lineTo(10,30);
- expected.lineTo(20,30);
- expected.lineTo(20,40);
- expected.lineTo(40,40);
- expected.lineTo(40,20);
- expected.lineTo(30,20);
- expected.lineTo(30,10);
- expected.lineTo(10,10);
- expected.close();
- if (out != expected) {
- SkDebugf("%s expected equal\n", __FUNCTION__);
- }
-
- path = out;
- path.addRect(30, 10, 40, 20);
- path.addRect(10, 30, 20, 40);
- simplify(path, true, out);
- SkRect rect;
- if (!out.isRect(&rect)) {
- SkDebugf("%s expected rect\n", __FUNCTION__);
- }
- if (rect != SkRect::MakeLTRB(10, 10, 40, 40)) {
- SkDebugf("%s expected union\n", __FUNCTION__);
- }
-
- path = out;
- path.addRect(10, 10, 40, 40, SkPath::kCCW_Direction);
- simplify(path, true, out);
- if (!out.isEmpty()) {
- SkDebugf("%s expected empty\n", __FUNCTION__);
- }
-}
-
-static void testSimplifyAddL() {
- SkPath path, out;
- path.moveTo(10,10); // 'L' shape
- path.lineTo(10,40);
- path.lineTo(40,40);
- path.lineTo(40,20);
- path.lineTo(30,20);
- path.lineTo(30,10);
- path.lineTo(10,10);
- path.close();
- path.addRect(30, 10, 40, 20); // missing notch of 'L'
- simplify(path, true, out);
- SkRect rect;
- if (!out.isRect(&rect)) {
- SkDebugf("%s expected rect\n", __FUNCTION__);
- }
- if (rect != SkRect::MakeLTRB(10, 10, 40, 40)) {
- SkDebugf("%s expected union\n", __FUNCTION__);
- }
-}
-
-static void testSimplifyCoincidentCCW() {
- SkPath path, out;
- path.addRect(10, 10, 40, 40, SkPath::kCCW_Direction);
- path.addRect(10, 10, 40, 40, SkPath::kCCW_Direction);
- simplify(path, true, out);
- SkRect rect;
- if (!out.isRect(&rect)) {
- SkDebugf("%s expected rect\n", __FUNCTION__);
- }
- if (rect != SkRect::MakeLTRB(10, 10, 40, 40)) {
- SkDebugf("%s expected union\n", __FUNCTION__);
- }
-}
-
-static void testSimplifyCoincidentCW() {
- SkPath path, out;
- path.addRect(10, 10, 40, 40, SkPath::kCCW_Direction);
- path.addRect(10, 10, 40, 40, SkPath::kCW_Direction);
- simplify(path, true, out);
- if (!out.isEmpty()) {
- SkDebugf("%s expected empty\n", __FUNCTION__);
- }
-}
-
-static void testSimplifyCorner() {
- SkPath path, out;
- path.addRect(10, 10, 20, 20, SkPath::kCCW_Direction);
- path.addRect(20, 20, 40, 40, SkPath::kCW_Direction);
- simplify(path, true, out);
- SkTDArray<SkRect> boundsArray;
- contourBounds(out, boundsArray);
- if (boundsArray.count() != 2) {
- SkDebugf("%s expected 2 contours\n", __FUNCTION__);
- return;
- }
- SkRect one = SkRect::MakeLTRB(10, 10, 20, 20);
- SkRect two = SkRect::MakeLTRB(20, 20, 40, 40);
- if ((boundsArray[0] != one && boundsArray[0] != two)
- || (boundsArray[1] != one && boundsArray[1] != two)) {
- SkDebugf("%s expected match\n", __FUNCTION__);
- }
-}
-
-static void testSimplifyDiagonal() {
- SkRect rect2 = SkRect::MakeXYWH(10, 10, 10, 10);
- for (size_t outDir = SkPath::kCW_Direction; outDir <= SkPath::kCCW_Direction; ++outDir) {
- for (size_t inDir = SkPath::kCW_Direction; inDir <= SkPath::kCCW_Direction; ++inDir) {
- for (int x = 0; x <= 20; x += 20) {
- for (int y = 0; y <= 20; y += 20) {
- SkPath path, out;
- SkRect rect1 = SkRect::MakeXYWH(x, y, 10, 10);
- path.addRect(rect1, static_cast<SkPath::Direction>(outDir));
- path.addRect(rect2, static_cast<SkPath::Direction>(inDir));
- simplify(path, true, out);
- SkPath::Iter iter(out, false);
- SkPoint pts[4], lastLine[2];
- SkPath::Verb verb;
- SkRect bounds[2];
- bounds[0].setEmpty();
- bounds[1].setEmpty();
- SkRect* boundsPtr = bounds;
- int count = 0, segments = 0;
- bool lastLineSet = false;
- while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
- switch (verb) {
- case SkPath::kMove_Verb:
- if (!boundsPtr->isEmpty()) {
- SkASSERT(boundsPtr == bounds);
- ++boundsPtr;
- }
- boundsPtr->set(pts[0].fX, pts[0].fY, pts[0].fX, pts[0].fY);
- count = 0;
- lastLineSet = false;
- break;
- case SkPath::kLine_Verb:
- if (lastLineSet) {
- SkASSERT((lastLine[1].fX - lastLine[0].fX) *
- (pts[1].fY - lastLine[0].fY) !=
- (lastLine[1].fY - lastLine[0].fY) *
- (pts[1].fX - lastLine[0].fX));
- }
- lastLineSet = true;
- lastLine[0] = pts[0];
- lastLine[1] = pts[1];
- count = 1;
- ++segments;
- break;
- case SkPath::kClose_Verb:
- count = 0;
- break;
- default:
- SkDEBUGFAIL("bad verb");
- return;
- }
- for (int i = 1; i <= count; ++i) {
- boundsPtr->growToInclude(pts[i].fX, pts[i].fY);
- }
- }
- if (boundsPtr != bounds) {
- SkASSERT((bounds[0] == rect1 || bounds[1] == rect1)
- && (bounds[0] == rect2 || bounds[1] == rect2));
- } else {
- SkASSERT(segments == 8);
- }
- }
- }
- }
- }
-}
-
-static void assertOneContour(const SkPath& out, bool edge, bool extend) {
- SkPath::Iter iter(out, false);
- SkPoint pts[4];
- SkPath::Verb verb;
- SkRect bounds;
- bounds.setEmpty();
- int count = 0;
- while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
- switch (verb) {
- case SkPath::kMove_Verb:
- SkASSERT(count == 0);
- break;
- case SkPath::kLine_Verb:
- SkASSERT(pts[0].fX == pts[1].fX || pts[0].fY == pts[1].fY);
- ++count;
- break;
- case SkPath::kClose_Verb:
- break;
- default:
- SkDEBUGFAIL("bad verb");
- return;
- }
- }
- SkASSERT(count == (extend ? 4 : edge ? 6 : 8));
-}
-
-static void testSimplifyCoincident() {
- // outside to inside, outside to right, outside to outside
- // left to inside, left to right, left to outside
- // inside to right, inside to outside
- // repeat above for left, right, bottom
- SkScalar start[] = { 0, 10, 20 };
- size_t startCount = sizeof(start) / sizeof(start[0]);
- SkScalar stop[] = { 30, 40, 50 };
- size_t stopCount = sizeof(stop) / sizeof(stop[0]);
- SkRect rect2 = SkRect::MakeXYWH(10, 10, 30, 30);
- for (size_t outDir = SkPath::kCW_Direction; outDir <= SkPath::kCCW_Direction; ++outDir) {
- for (size_t inDir = SkPath::kCW_Direction; inDir <= SkPath::kCCW_Direction; ++inDir) {
- for (size_t startIndex = 0; startIndex < startCount; ++startIndex) {
- for (size_t stopIndex = 0; stopIndex < stopCount; ++stopIndex) {
- bool extend = start[startIndex] == rect2.fLeft && stop[stopIndex] == rect2.fRight;
- bool edge = start[startIndex] == rect2.fLeft || stop[stopIndex] == rect2.fRight;
- SkRect rect1 = SkRect::MakeLTRB(start[startIndex], 0, stop[stopIndex], 10);
- SkPath path, out;
- path.addRect(rect1, static_cast<SkPath::Direction>(outDir));
- path.addRect(rect2, static_cast<SkPath::Direction>(inDir));
- simplify(path, true, out);
- assertOneContour(out, edge, extend);
-
- path.reset();
- rect1 = SkRect::MakeLTRB(start[startIndex], 40, stop[stopIndex], 50);
- path.addRect(rect1, static_cast<SkPath::Direction>(outDir));
- path.addRect(rect2, static_cast<SkPath::Direction>(inDir));
- simplify(path, true, out);
- assertOneContour(out, edge, extend);
-
- path.reset();
- rect1 = SkRect::MakeLTRB(0, start[startIndex], 10, stop[stopIndex]);
- path.addRect(rect1, static_cast<SkPath::Direction>(outDir));
- path.addRect(rect2, static_cast<SkPath::Direction>(inDir));
- simplify(path, true, out);
- assertOneContour(out, edge, extend);
-
- path.reset();
- rect1 = SkRect::MakeLTRB(40, start[startIndex], 50, stop[stopIndex]);
- path.addRect(rect1, static_cast<SkPath::Direction>(outDir));
- path.addRect(rect2, static_cast<SkPath::Direction>(inDir));
- simplify(path, true, out);
- assertOneContour(out, edge, extend);
- }
- }
- }
- }
-}
-
-static void testSimplifyOverlap() {
- SkScalar start[] = { 0, 10, 20 };
- size_t startCount = sizeof(start) / sizeof(start[0]);
- SkScalar stop[] = { 30, 40, 50 };
- size_t stopCount = sizeof(stop) / sizeof(stop[0]);
- SkRect rect2 = SkRect::MakeXYWH(10, 10, 30, 30);
- for (size_t dir = SkPath::kCW_Direction; dir <= SkPath::kCCW_Direction; ++dir) {
- for (size_t lefty = 0; lefty < startCount; ++lefty) {
- for (size_t righty = 0; righty < stopCount; ++righty) {
- for (size_t toppy = 0; toppy < startCount; ++toppy) {
- for (size_t botty = 0; botty < stopCount; ++botty) {
- SkRect rect1 = SkRect::MakeLTRB(start[lefty], start[toppy],
- stop[righty], stop[botty]);
- SkPath path, out;
- path.addRect(rect1, static_cast<SkPath::Direction>(dir));
- path.addRect(rect2, static_cast<SkPath::Direction>(dir));
- testSimplify(path, true, out, bitmap);
- }
- }
- }
- }
- }
-}
-
-static void testSimplifyOverlapTiny() {
- SkScalar start[] = { 0, 1, 2 };
- size_t startCount = sizeof(start) / sizeof(start[0]);
- SkScalar stop[] = { 3, 4, 5 };
- size_t stopCount = sizeof(stop) / sizeof(stop[0]);
- SkRect rect2 = SkRect::MakeXYWH(1, 1, 3, 3);
- for (size_t dir = SkPath::kCW_Direction; dir <= SkPath::kCCW_Direction; ++dir) {
- for (size_t lefty = 0; lefty < startCount; ++lefty) {
- for (size_t righty = 0; righty < stopCount; ++righty) {
- for (size_t toppy = 0; toppy < startCount; ++toppy) {
- for (size_t botty = 0; botty < stopCount; ++botty) {
- SkRect rect1 = SkRect::MakeLTRB(start[lefty], start[toppy],
- stop[righty], stop[botty]);
- SkPath path, out;
- path.addRect(rect1, static_cast<SkPath::Direction>(dir));
- path.addRect(rect2, static_cast<SkPath::Direction>(dir));
- simplify(path, true, out);
- comparePathsTiny(path, out);
- }
- }
- }
- }
- }
-}
-
-static void testSimplifyDegenerate() {
- SkScalar start[] = { 0, 10, 20 };
- size_t startCount = sizeof(start) / sizeof(start[0]);
- SkScalar stop[] = { 30, 40, 50 };
- size_t stopCount = sizeof(stop) / sizeof(stop[0]);
- SkRect rect2 = SkRect::MakeXYWH(10, 10, 30, 30);
- for (size_t outDir = SkPath::kCW_Direction; outDir <= SkPath::kCCW_Direction; ++outDir) {
- for (size_t inDir = SkPath::kCW_Direction; inDir <= SkPath::kCCW_Direction; ++inDir) {
- for (size_t startIndex = 0; startIndex < startCount; ++startIndex) {
- for (size_t stopIndex = 0; stopIndex < stopCount; ++stopIndex) {
- SkRect rect1 = SkRect::MakeLTRB(start[startIndex], 0, stop[stopIndex], 0);
- SkPath path, out;
- path.addRect(rect1, static_cast<SkPath::Direction>(outDir));
- path.addRect(rect2, static_cast<SkPath::Direction>(inDir));
- simplify(path, true, out);
- SkRect rect;
- if (!out.isRect(&rect)) {
- SkDebugf("%s 1 expected rect\n", __FUNCTION__);
- }
- if (rect != rect2) {
- SkDebugf("%s 1 expected union\n", __FUNCTION__);
- }
-
- path.reset();
- rect1 = SkRect::MakeLTRB(start[startIndex], 40, stop[stopIndex], 40);
- path.addRect(rect1, static_cast<SkPath::Direction>(outDir));
- path.addRect(rect2, static_cast<SkPath::Direction>(inDir));
- simplify(path, true, out);
- if (!out.isRect(&rect)) {
- SkDebugf("%s 2 expected rect\n", __FUNCTION__);
- }
- if (rect != rect2) {
- SkDebugf("%s 2 expected union\n", __FUNCTION__);
- }
-
- path.reset();
- rect1 = SkRect::MakeLTRB(0, start[startIndex], 0, stop[stopIndex]);
- path.addRect(rect1, static_cast<SkPath::Direction>(outDir));
- path.addRect(rect2, static_cast<SkPath::Direction>(inDir));
- simplify(path, true, out);
- if (!out.isRect(&rect)) {
- SkDebugf("%s 3 expected rect\n", __FUNCTION__);
- }
- if (rect != rect2) {
- SkDebugf("%s 3 expected union\n", __FUNCTION__);
- }
-
- path.reset();
- rect1 = SkRect::MakeLTRB(40, start[startIndex], 40, stop[stopIndex]);
- path.addRect(rect1, static_cast<SkPath::Direction>(outDir));
- path.addRect(rect2, static_cast<SkPath::Direction>(inDir));
- simplify(path, true, out);
- if (!out.isRect(&rect)) {
- SkDebugf("%s 4 expected rect\n", __FUNCTION__);
- }
- if (rect != rect2) {
- SkDebugf("%s 4 expected union\n", __FUNCTION__);
- }
- }
- }
- }
- }
-}
-
-static void testSimplifyDegenerate1() {
- SkPath path, out;
- path.setFillType(SkPath::kWinding_FillType);
- path.addRect( 0, 0, 0, 30);
- path.addRect(10, 10, 40, 40);
- simplify(path, true, out);
- SkRect rect;
- if (!out.isRect(&rect)) {
- SkDebugf("%s expected rect\n", __FUNCTION__);
- }
- if (rect != SkRect::MakeLTRB(10, 10, 40, 40)) {
- SkDebugf("%s expected union\n", __FUNCTION__);
- }
-}
-
-static void (*simplifyTests[])() = {
- testSimplifyCoincidentInner,
- testSimplifyOverlapTiny,
- testSimplifyDegenerate1,
- testSimplifyCorner,
- testSimplifyDegenerate,
- testSimplifyOverlap,
- testSimplifyDiagonal,
- testSimplifyCoincident,
- testSimplifyCoincidentCW,
- testSimplifyCoincidentCCW,
- testSimplifyCoincidentVertical,
- testSimplifyCoincidentHorizontal,
- testSimplifyAddL,
- testSimplifyMulti,
-};
-
-static size_t simplifyTestsCount = sizeof(simplifyTests) / sizeof(simplifyTests[0]);
-
-static void (*firstTest)() = 0;
-
-void SimplifyRectangularPaths_Test() {
- size_t index = 0;
- if (firstTest) {
- while (index < simplifyTestsCount && simplifyTests[index] != firstTest) {
- ++index;
- }
- }
- for ( ; index < simplifyTestsCount; ++index) {
- if (simplifyTests[index] == testSimplifyCorner) {
- // testSimplifyCorner fails because it expects two contours, where
- // only one is returned. Both results are reasonable, but if two
- // contours are desirable, or if we provide an option to choose
- // between longer contours and more contours, turn this back on. For
- // the moment, testSimplifyDiagonal also checks the test case, and
- // permits either two rects or one non-crossing poly as valid
- // unreported results.
- continue;
- }
- (*simplifyTests[index])();
- }
-}
diff --git a/experimental/Intersection/EdgeWalker_Test.h b/experimental/Intersection/EdgeWalker_Test.h
deleted file mode 100644
index 5e8e7b7bf0..0000000000
--- a/experimental/Intersection/EdgeWalker_Test.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "ShapeOps.h"
-#include "SkBitmap.h"
-#include "SkStream.h"
-#include <pthread.h>
-
-struct State4;
-
-//extern int comparePaths(const SkPath& one, const SkPath& two);
-extern int comparePaths(const SkPath& one, const SkPath& two, SkBitmap& bitmap);
-extern void comparePathsTiny(const SkPath& one, const SkPath& two);
-extern bool drawAsciiPaths(const SkPath& one, const SkPath& two,
- bool drawPaths);
-extern void showOp(const ShapeOp op);
-extern void showPath(const SkPath& path, const char* str);
-extern void showPath(const SkPath& path);
-extern void showPathData(const SkPath& path);
-extern bool testSimplify(const SkPath& path, bool fill, SkPath& out,
- SkBitmap& bitmap);
-extern bool testSimplifyx(SkPath& path, bool useXor, SkPath& out,
- State4& state, const char* pathStr);
-extern bool testSimplifyx(const SkPath& path);
-extern bool testShapeOp(const SkPath& a, const SkPath& b, const ShapeOp );
-
-struct State4 {
- State4();
- static pthread_mutex_t addQueue;
- static pthread_cond_t checkQueue;
- pthread_cond_t initialized;
- static State4* queue;
- pthread_t threadID;
- int index;
- bool done;
- bool last;
- int a;
- int b;
- int c;
- int d; // sometimes 1 if abc_is_a_triangle
- int testsRun;
- char filename[256];
-
- SkBitmap bitmap;
-};
-
-void createThread(State4* statePtr, void* (*test)(void* ));
-int dispatchTest4(void* (*testFun)(void* ), int a, int b, int c, int d);
-void initializeTests(const char* testName, size_t testNameSize);
-void outputProgress(const State4& state, const char* pathStr, SkPath::FillType );
-void outputProgress(const State4& state, const char* pathStr, ShapeOp op);
-void outputToStream(const State4& state, const char* pathStr, const char* pathPrefix,
- const char* nameSuffix,
- const char* testFunction, SkWStream& outFile);
-bool runNextTestSet(State4& state);
-int waitForCompletion();
diff --git a/experimental/Intersection/EdgeWalker_TestUtility.cpp b/experimental/Intersection/EdgeWalker_TestUtility.cpp
deleted file mode 100644
index 7926ee9822..0000000000
--- a/experimental/Intersection/EdgeWalker_TestUtility.cpp
+++ /dev/null
@@ -1,761 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "DataTypes.h"
-#include "EdgeWalker_Test.h"
-#include "Intersection_Tests.h"
-#include "SkBitmap.h"
-#include "SkCanvas.h"
-#include "SkMatrix.h"
-#include "SkPaint.h"
-#include "SkStream.h"
-
-#include <algorithm>
-#include <errno.h>
-#include <pthread.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/sysctl.h>
-
-#undef SkASSERT
-#define SkASSERT(cond) while (!(cond)) { sk_throw(); }
-
-static const char marker[] =
- "</div>\n"
- "\n"
- "<script type=\"text/javascript\">\n"
- "\n"
- "var testDivs = [\n";
-
-static const char* opStrs[] = {
- "kDifference_Op",
- "kIntersect_Op",
- "kUnion_Op",
- "kXor_Op",
-};
-
-static const char* opSuffixes[] = {
- "d",
- "i",
- "u",
- "x",
-};
-
-static const char preferredFilename[] = "/flash/debug/XX.txt";
-static const char backupFilename[] = "../../experimental/Intersection/debugXX.txt";
-
-static bool gShowPath = false;
-static bool gComparePaths = true;
-static bool gShowOutputProgress = false;
-static bool gComparePathsAssert = true;
-static bool gPathStrAssert = true;
-static bool gUsePhysicalFiles = false;
-
-static void showPathContour(SkPath::Iter& iter) {
- uint8_t verb;
- SkPoint pts[4];
- while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
- switch (verb) {
- case SkPath::kMove_Verb:
- SkDebugf("path.moveTo(%1.9g,%1.9g);\n", pts[0].fX, pts[0].fY);
- continue;
- case SkPath::kLine_Verb:
- SkDebugf("path.lineTo(%1.9g,%1.9g);\n", pts[1].fX, pts[1].fY);
- break;
- case SkPath::kQuad_Verb:
- SkDebugf("path.quadTo(%1.9g,%1.9g, %1.9g,%1.9g);\n",
- pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY);
- break;
- case SkPath::kCubic_Verb:
- SkDebugf("path.cubicTo(%1.9g,%1.9g, %1.9g,%1.9g, %1.9g,%1.9g);\n",
- pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY, pts[3].fX, pts[3].fY);
- break;
- case SkPath::kClose_Verb:
- SkDebugf("path.close();\n");
- break;
- default:
- SkDEBUGFAIL("bad verb");
- return;
- }
- }
-}
-
-void showPath(const SkPath& path, const char* str) {
- SkDebugf("%s\n", !str ? "original:" : str);
- showPath(path);
-}
-
-void showPath(const SkPath& path) {
- SkPath::Iter iter(path, true);
- int rectCount = path.isRectContours() ? path.rectContours(NULL, NULL) : 0;
- if (rectCount > 0) {
- SkTDArray<SkRect> rects;
- SkTDArray<SkPath::Direction> directions;
- rects.setCount(rectCount);
- directions.setCount(rectCount);
- path.rectContours(rects.begin(), directions.begin());
- for (int contour = 0; contour < rectCount; ++contour) {
- const SkRect& rect = rects[contour];
- SkDebugf("path.addRect(%1.9g, %1.9g, %1.9g, %1.9g, %s);\n", rect.fLeft, rect.fTop,
- rect.fRight, rect.fBottom, directions[contour] == SkPath::kCCW_Direction
- ? "SkPath::kCCW_Direction" : "SkPath::kCW_Direction");
- }
- return;
- }
- iter.setPath(path, true);
- showPathContour(iter);
-}
-
-void showPathData(const SkPath& path) {
- SkPath::Iter iter(path, true);
- uint8_t verb;
- SkPoint pts[4];
- while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
- switch (verb) {
- case SkPath::kMove_Verb:
- continue;
- case SkPath::kLine_Verb:
- SkDebugf("{{%1.9g,%1.9g}, {%1.9g,%1.9g}},\n", pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY);
- break;
- case SkPath::kQuad_Verb:
- SkDebugf("{{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}},\n",
- pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY);
- break;
- case SkPath::kCubic_Verb:
- SkDebugf("{{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}},\n",
- pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY, pts[3].fX, pts[3].fY);
- break;
- case SkPath::kClose_Verb:
- break;
- default:
- SkDEBUGFAIL("bad verb");
- return;
- }
- }
-}
-
-void showOp(const ShapeOp op) {
- switch (op) {
- case kDifference_Op:
- SkDebugf("op difference\n");
- break;
- case kIntersect_Op:
- SkDebugf("op intersect\n");
- break;
- case kUnion_Op:
- SkDebugf("op union\n");
- break;
- case kXor_Op:
- SkDebugf("op xor\n");
- break;
- default:
- SkASSERT(0);
- }
-}
-
-static void showPath(const SkPath& path, const char* str, const SkMatrix& scale) {
- SkPath scaled;
- SkMatrix inverse;
- bool success = scale.invert(&inverse);
- if (!success) SkASSERT(0);
- path.transform(inverse, &scaled);
- showPath(scaled, str);
-}
-
-const int bitWidth = 64;
-const int bitHeight = 64;
-
-static void scaleMatrix(const SkPath& one, const SkPath& two, SkMatrix& scale) {
- SkRect larger = one.getBounds();
- larger.join(two.getBounds());
- SkScalar largerWidth = larger.width();
- if (largerWidth < 4) {
- largerWidth = 4;
- }
- SkScalar largerHeight = larger.height();
- if (largerHeight < 4) {
- largerHeight = 4;
- }
- SkScalar hScale = (bitWidth - 2) / largerWidth;
- SkScalar vScale = (bitHeight - 2) / largerHeight;
- scale.reset();
- scale.preScale(hScale, vScale);
-}
-
-static int pathsDrawTheSame(SkBitmap& bits, const SkPath& scaledOne, const SkPath& scaledTwo,
- int& error2x2) {
- if (bits.width() == 0) {
- bits.setConfig(SkBitmap::kARGB_8888_Config, bitWidth * 2, bitHeight);
- bits.allocPixels();
- }
- SkCanvas canvas(bits);
- canvas.drawColor(SK_ColorWHITE);
- SkPaint paint;
- canvas.save();
- const SkRect& bounds1 = scaledOne.getBounds();
- canvas.translate(-bounds1.fLeft + 1, -bounds1.fTop + 1);
- canvas.drawPath(scaledOne, paint);
- canvas.restore();
- canvas.save();
- canvas.translate(-bounds1.fLeft + 1 + bitWidth, -bounds1.fTop + 1);
- canvas.drawPath(scaledTwo, paint);
- canvas.restore();
- int errors2 = 0;
- int errors = 0;
- for (int y = 0; y < bitHeight - 1; ++y) {
- uint32_t* addr1 = bits.getAddr32(0, y);
- uint32_t* addr2 = bits.getAddr32(0, y + 1);
- uint32_t* addr3 = bits.getAddr32(bitWidth, y);
- uint32_t* addr4 = bits.getAddr32(bitWidth, y + 1);
- for (int x = 0; x < bitWidth - 1; ++x) {
- // count 2x2 blocks
- bool err = addr1[x] != addr3[x];
- if (err) {
- errors2 += addr1[x + 1] != addr3[x + 1]
- && addr2[x] != addr4[x] && addr2[x + 1] != addr4[x + 1];
- errors++;
- }
- }
- }
- if (errors2 >= 6 || errors > 160) {
- SkDebugf("%s errors2=%d errors=%d\n", __FUNCTION__, errors2, errors);
- }
- error2x2 = errors2;
- return errors;
-}
-
-static int pathsDrawTheSame(const SkPath& one, const SkPath& two, SkBitmap& bits, SkPath& scaledOne,
- SkPath& scaledTwo, int& error2x2) {
- SkMatrix scale;
- scaleMatrix(one, two, scale);
- one.transform(scale, &scaledOne);
- two.transform(scale, &scaledTwo);
- return pathsDrawTheSame(bits, scaledOne, scaledTwo, error2x2);
-}
-
-bool drawAsciiPaths(const SkPath& one, const SkPath& two, bool drawPaths) {
- if (!drawPaths) {
- return true;
- }
- const SkRect& bounds1 = one.getBounds();
- const SkRect& bounds2 = two.getBounds();
- SkRect larger = bounds1;
- larger.join(bounds2);
- SkBitmap bits;
- char out[256];
- int bitWidth = SkScalarCeil(larger.width()) + 2;
- if (bitWidth * 2 + 1 >= (int) sizeof(out)) {
- return false;
- }
- int bitHeight = SkScalarCeil(larger.height()) + 2;
- if (bitHeight >= (int) sizeof(out)) {
- return false;
- }
- bits.setConfig(SkBitmap::kARGB_8888_Config, bitWidth * 2, bitHeight);
- bits.allocPixels();
- SkCanvas canvas(bits);
- canvas.drawColor(SK_ColorWHITE);
- SkPaint paint;
- canvas.save();
- canvas.translate(-bounds1.fLeft + 1, -bounds1.fTop + 1);
- canvas.drawPath(one, paint);
- canvas.restore();
- canvas.save();
- canvas.translate(-bounds1.fLeft + 1 + bitWidth, -bounds1.fTop + 1);
- canvas.drawPath(two, paint);
- canvas.restore();
- for (int y = 0; y < bitHeight; ++y) {
- uint32_t* addr1 = bits.getAddr32(0, y);
- int x;
- char* outPtr = out;
- for (x = 0; x < bitWidth; ++x) {
- *outPtr++ = addr1[x] == (uint32_t) -1 ? '_' : 'x';
- }
- *outPtr++ = '|';
- for (x = bitWidth; x < bitWidth * 2; ++x) {
- *outPtr++ = addr1[x] == (uint32_t) -1 ? '_' : 'x';
- }
- *outPtr++ = '\0';
- SkDebugf("%s\n", out);
- }
- return true;
-}
-
-static void showSimplifiedPath(const SkPath& one, const SkPath& two,
- const SkPath& scaledOne, const SkPath& scaledTwo) {
- showPath(one, "original:");
- showPath(two, "simplified:");
- drawAsciiPaths(scaledOne, scaledTwo, true);
-}
-
-int comparePaths(const SkPath& one, const SkPath& two, SkBitmap& bitmap) {
- int errors2x2;
- SkPath scaledOne, scaledTwo;
- int errors = pathsDrawTheSame(one, two, bitmap, scaledOne, scaledTwo, errors2x2);
- if (errors2x2 == 0) {
- return 0;
- }
- const int MAX_ERRORS = 9;
- if (errors2x2 == MAX_ERRORS || errors2x2 == MAX_ERRORS - 1) {
- showSimplifiedPath(one, two, scaledOne, scaledTwo);
- }
- if (errors2x2 > MAX_ERRORS && gComparePathsAssert) {
- SkDebugf("%s errors=%d\n", __FUNCTION__, errors);
- showSimplifiedPath(one, two, scaledOne, scaledTwo);
- SkASSERT(0);
- }
- return errors2x2 > MAX_ERRORS ? errors2x2 : 0;
-}
-
-static void showShapeOpPath(const SkPath& one, const SkPath& two, const SkPath& a, const SkPath& b,
- const SkPath& scaledOne, const SkPath& scaledTwo, const ShapeOp shapeOp,
- const SkMatrix& scale) {
- SkASSERT((unsigned) shapeOp < sizeof(opStrs) / sizeof(opStrs[0]));
- showPath(a, "minuend:");
- SkDebugf("op: %s\n", opStrs[shapeOp]);
- showPath(b, "subtrahend:");
- // the region often isn't very helpful since it approximates curves with a lot of line-tos
- if (0) showPath(scaledOne, "region:", scale);
- showPath(two, "op result:");
- drawAsciiPaths(scaledOne, scaledTwo, true);
-}
-
-static int comparePaths(const SkPath& one, const SkPath& scaledOne, const SkPath& two,
- const SkPath& scaledTwo,
- SkBitmap& bitmap, const SkPath& a, const SkPath& b, const ShapeOp shapeOp,
- const SkMatrix& scale) {
- int errors2x2;
- int errors = pathsDrawTheSame(bitmap, scaledOne, scaledTwo, errors2x2);
- if (errors2x2 == 0) {
- return 0;
- }
- const int MAX_ERRORS = 8;
- if (errors2x2 == MAX_ERRORS || errors2x2 == MAX_ERRORS - 1) {
- showShapeOpPath(one, two, a, b, scaledOne, scaledTwo, shapeOp, scale);
- }
- if (errors2x2 > MAX_ERRORS && gComparePathsAssert) {
- SkDebugf("%s errors=%d\n", __FUNCTION__, errors);
- showShapeOpPath(one, two, a, b, scaledOne, scaledTwo, shapeOp, scale);
- SkASSERT(0);
- }
- return errors2x2 > MAX_ERRORS ? errors2x2 : 0;
-}
-
-// doesn't work yet
-void comparePathsTiny(const SkPath& one, const SkPath& two) {
- const SkRect& bounds1 = one.getBounds();
- const SkRect& bounds2 = two.getBounds();
- SkRect larger = bounds1;
- larger.join(bounds2);
- SkBitmap bits;
- int bitWidth = SkScalarCeil(larger.width()) + 2;
- int bitHeight = SkScalarCeil(larger.height()) + 2;
- bits.setConfig(SkBitmap::kA1_Config, bitWidth * 2, bitHeight);
- bits.allocPixels();
- SkCanvas canvas(bits);
- canvas.drawColor(SK_ColorWHITE);
- SkPaint paint;
- canvas.save();
- canvas.translate(-bounds1.fLeft + 1, -bounds1.fTop + 1);
- canvas.drawPath(one, paint);
- canvas.restore();
- canvas.save();
- canvas.translate(-bounds2.fLeft + 1, -bounds2.fTop + 1);
- canvas.drawPath(two, paint);
- canvas.restore();
- for (int y = 0; y < bitHeight; ++y) {
- uint8_t* addr1 = bits.getAddr1(0, y);
- uint8_t* addr2 = bits.getAddr1(bitWidth, y);
- for (unsigned x = 0; x < bits.rowBytes(); ++x) {
- SkASSERT(addr1[x] == addr2[x]);
- }
- }
-}
-
-bool testSimplify(const SkPath& path, bool fill, SkPath& out, SkBitmap& bitmap) {
- if (gShowPath) {
- showPath(path);
- }
- simplify(path, fill, out);
- if (!gComparePaths) {
- return true;
- }
- return comparePaths(path, out, bitmap) == 0;
-}
-
-bool testSimplifyx(SkPath& path, bool useXor, SkPath& out, State4& state,
- const char* pathStr) {
- SkPath::FillType fillType = useXor ? SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType;
- path.setFillType(fillType);
- if (gShowPath) {
- showPath(path);
- }
- simplifyx(path, out);
- if (!gComparePaths) {
- return true;
- }
- int result = comparePaths(path, out, state.bitmap);
- if (result && gPathStrAssert) {
- SkDebugf("addTest %s\n", state.filename);
- char temp[8192];
- bzero(temp, sizeof(temp));
- SkMemoryWStream stream(temp, sizeof(temp));
- const char* pathPrefix = NULL;
- const char* nameSuffix = NULL;
- if (fillType == SkPath::kEvenOdd_FillType) {
- pathPrefix = " path.setFillType(SkPath::kEvenOdd_FillType);\n";
- nameSuffix = "x";
- }
- const char testFunction[] = "testSimplifyx(path);";
- outputToStream(state, pathStr, pathPrefix, nameSuffix, testFunction, stream);
- SkDebugf(temp);
- SkASSERT(0);
- }
- return result == 0;
-}
-
-bool testSimplifyx(const SkPath& path) {
- SkPath out;
- simplifyx(path, out);
- SkBitmap bitmap;
- int result = comparePaths(path, out, bitmap);
- if (result && gPathStrAssert) {
- SkASSERT(0);
- }
- return result == 0;
-}
-
-bool testShapeOp(const SkPath& a, const SkPath& b, const ShapeOp shapeOp) {
-#if FORCE_RELEASE == 0
- showPathData(a);
- showOp(shapeOp);
- showPathData(b);
-#endif
- SkPath out;
- operate(a, b, shapeOp, out);
- SkPath pathOut, scaledPathOut;
- SkRegion rgnA, rgnB, openClip, rgnOut;
- openClip.setRect(-16000, -16000, 16000, 16000);
- rgnA.setPath(a, openClip);
- rgnB.setPath(b, openClip);
- rgnOut.op(rgnA, rgnB, (SkRegion::Op) shapeOp);
- rgnOut.getBoundaryPath(&pathOut);
-
- SkMatrix scale;
- scaleMatrix(a, b, scale);
- SkRegion scaledRgnA, scaledRgnB, scaledRgnOut;
- SkPath scaledA, scaledB;
- scaledA.addPath(a, scale);
- scaledA.setFillType(a.getFillType());
- scaledB.addPath(b, scale);
- scaledB.setFillType(b.getFillType());
- scaledRgnA.setPath(scaledA, openClip);
- scaledRgnB.setPath(scaledB, openClip);
- scaledRgnOut.op(scaledRgnA, scaledRgnB, (SkRegion::Op) shapeOp);
- scaledRgnOut.getBoundaryPath(&scaledPathOut);
- SkBitmap bitmap;
- SkPath scaledOut;
- scaledOut.addPath(out, scale);
- scaledOut.setFillType(out.getFillType());
- int result = comparePaths(pathOut, scaledPathOut, out, scaledOut, bitmap, a, b, shapeOp, scale);
- if (result && gPathStrAssert) {
- SkASSERT(0);
- }
- return result == 0;
-}
-
-const int maxThreadsAllocated = 64;
-static int maxThreads = 1;
-static int threadIndex;
-State4 threadState[maxThreadsAllocated];
-static int testNumber;
-static const char* testName;
-static bool debugThreads = false;
-
-State4* State4::queue = NULL;
-pthread_mutex_t State4::addQueue = PTHREAD_MUTEX_INITIALIZER;
-pthread_cond_t State4::checkQueue = PTHREAD_COND_INITIALIZER;
-
-State4::State4() {
- bitmap.setConfig(SkBitmap::kARGB_8888_Config, 150 * 2, 100);
- bitmap.allocPixels();
-}
-
-void createThread(State4* statePtr, void* (*testFun)(void* )) {
- int threadError = pthread_create(&statePtr->threadID, NULL, testFun,
- (void*) statePtr);
- SkASSERT(!threadError);
-}
-
-int dispatchTest4(void* (*testFun)(void* ), int a, int b, int c, int d) {
- int testsRun = 0;
- State4* statePtr;
- if (!gRunTestsInOneThread) {
- pthread_mutex_lock(&State4::addQueue);
- if (threadIndex < maxThreads) {
- statePtr = &threadState[threadIndex];
- statePtr->testsRun = 0;
- statePtr->a = a;
- statePtr->b = b;
- statePtr->c = c;
- statePtr->d = d;
- statePtr->done = false;
- statePtr->index = threadIndex;
- statePtr->last = false;
- if (debugThreads) SkDebugf("%s %d create done=%d last=%d\n", __FUNCTION__,
- statePtr->index, statePtr->done, statePtr->last);
- pthread_cond_init(&statePtr->initialized, NULL);
- ++threadIndex;
- createThread(statePtr, testFun);
- } else {
- while (!State4::queue) {
- if (debugThreads) SkDebugf("%s checkQueue\n", __FUNCTION__);
- pthread_cond_wait(&State4::checkQueue, &State4::addQueue);
- }
- statePtr = State4::queue;
- testsRun += statePtr->testsRun;
- statePtr->testsRun = 0;
- statePtr->a = a;
- statePtr->b = b;
- statePtr->c = c;
- statePtr->d = d;
- statePtr->done = false;
- State4::queue = NULL;
- for (int index = 0; index < maxThreads; ++index) {
- if (threadState[index].done) {
- State4::queue = &threadState[index];
- }
- }
- if (debugThreads) SkDebugf("%s %d init done=%d last=%d queued=%d\n", __FUNCTION__,
- statePtr->index, statePtr->done, statePtr->last,
- State4::queue ? State4::queue->index : -1);
- pthread_cond_signal(&statePtr->initialized);
- }
- pthread_mutex_unlock(&State4::addQueue);
- } else {
- statePtr = &threadState[0];
- testsRun += statePtr->testsRun;
- statePtr->testsRun = 0;
- statePtr->a = a;
- statePtr->b = b;
- statePtr->c = c;
- statePtr->d = d;
- statePtr->done = false;
- statePtr->index = threadIndex;
- statePtr->last = false;
- (*testFun)(statePtr);
- }
- return testsRun;
-}
-
-void initializeTests(const char* test, size_t testNameSize) {
- testName = test;
- if (!gRunTestsInOneThread) {
- int threads = -1;
- size_t size = sizeof(threads);
- sysctlbyname("hw.logicalcpu_max", &threads, &size, NULL, 0);
- if (threads > 0) {
- maxThreads = threads;
- } else {
- maxThreads = 8;
- }
- }
- SkFILEStream inFile("../../experimental/Intersection/op.htm");
- if (inFile.isValid()) {
- SkTDArray<char> inData;
- inData.setCount(inFile.getLength());
- size_t inLen = inData.count();
- inFile.read(inData.begin(), inLen);
- inFile.setPath(NULL);
- char* insert = strstr(inData.begin(), marker);
- if (insert) {
- insert += sizeof(marker) - 1;
- const char* numLoc = insert + 4 /* indent spaces */ + testNameSize - 1;
- testNumber = atoi(numLoc) + 1;
- }
- }
- const char* filename = preferredFilename;
- SkFILEWStream preferredTest(filename);
- if (!preferredTest.isValid()) {
- filename = backupFilename;
- SkFILEWStream backupTest(filename);
- SkASSERT(backupTest.isValid());
- }
- for (int index = 0; index < maxThreads; ++index) {
- State4* statePtr = &threadState[index];
- strcpy(statePtr->filename, filename);
- size_t len = strlen(filename);
- SkASSERT(statePtr->filename[len - 6] == 'X');
- SkASSERT(statePtr->filename[len - 5] == 'X');
- statePtr->filename[len - 6] = '0' + index / 10;
- statePtr->filename[len - 5] = '0' + index % 10;
- }
- threadIndex = 0;
-}
-
-void outputProgress(const State4& state, const char* pathStr, SkPath::FillType pathFillType) {
- if (gRunTestsInOneThread && gShowOutputProgress) {
- if (pathFillType == SkPath::kEvenOdd_FillType) {
- SkDebugf(" path.setFillType(SkPath::kEvenOdd_FillType);\n", pathStr);
- }
- SkDebugf("%s\n", pathStr);
- }
- const char testFunction[] = "testSimplifyx(path);";
- const char* pathPrefix = NULL;
- const char* nameSuffix = NULL;
- if (pathFillType == SkPath::kEvenOdd_FillType) {
- pathPrefix = " path.setFillType(SkPath::kEvenOdd_FillType);\n";
- nameSuffix = "x";
- }
- if (gUsePhysicalFiles) {
- SkFILEWStream outFile(state.filename);
- if (!outFile.isValid()) {
- SkASSERT(0);
- return;
- }
- outputToStream(state, pathStr, pathPrefix, nameSuffix, testFunction, outFile);
- return;
- }
- SkFILEWStream outRam(state.filename);
- outputToStream(state, pathStr, pathPrefix, nameSuffix, testFunction, outRam);
-}
-
-void outputProgress(const State4& state, const char* pathStr, ShapeOp op) {
- SkString testFunc("testShapeOp(path, pathB, ");
- testFunc += opStrs[op];
- testFunc += ");";
- const char* testFunction = testFunc.c_str();
- if (gRunTestsInOneThread && gShowOutputProgress) {
- SkDebugf("%s\n", pathStr);
- SkDebugf(" %s\n", testFunction);
- }
- const char* nameSuffix = opSuffixes[op];
- if (gUsePhysicalFiles) {
- SkFILEWStream outFile(state.filename);
- if (!outFile.isValid()) {
- SkASSERT(0);
- return;
- }
- outputToStream(state, pathStr, NULL, nameSuffix, testFunction, outFile);
- return;
- }
- SkFILEWStream outRam(state.filename);
- outputToStream(state, pathStr, NULL, nameSuffix, testFunction, outRam);
-}
-
-static void writeTestName(const char* nameSuffix, SkWStream& outFile) {
- outFile.writeText(testName);
- outFile.writeDecAsText(testNumber);
- if (nameSuffix) {
- outFile.writeText(nameSuffix);
- }
-}
-
-void outputToStream(const State4& state, const char* pathStr, const char* pathPrefix,
- const char* nameSuffix,
- const char* testFunction, SkWStream& outFile) {
- outFile.writeText("<div id=\"");
- writeTestName(nameSuffix, outFile);
- outFile.writeText("\">\n");
- if (pathPrefix) {
- outFile.writeText(pathPrefix);
- }
- outFile.writeText(pathStr);
- outFile.writeText("</div>\n\n");
-
- outFile.writeText(marker);
- outFile.writeText(" ");
- writeTestName(nameSuffix, outFile);
- outFile.writeText(",\n\n\n");
-
- outFile.writeText("static void ");
- writeTestName(nameSuffix, outFile);
- outFile.writeText("() {\n SkPath path");
- if (!pathPrefix) {
- outFile.writeText(", pathB");
- }
- outFile.writeText(";\n");
- if (pathPrefix) {
- outFile.writeText(pathPrefix);
- }
- outFile.writeText(pathStr);
- outFile.writeText(" ");
- outFile.writeText(testFunction);
- outFile.writeText("\n}\n\n");
- outFile.writeText("static void (*firstTest)() = ");
- writeTestName(nameSuffix, outFile);
- outFile.writeText(";\n\n");
-
- outFile.writeText("static struct {\n");
- outFile.writeText(" void (*fun)();\n");
- outFile.writeText(" const char* str;\n");
- outFile.writeText("} tests[] = {\n");
- outFile.writeText(" TEST(");
- writeTestName(nameSuffix, outFile);
- outFile.writeText("),\n");
- outFile.flush();
-}
-
-bool runNextTestSet(State4& state) {
- if (gRunTestsInOneThread) {
- return false;
- }
- pthread_mutex_lock(&State4::addQueue);
- state.done = true;
- State4::queue = &state;
- if (debugThreads) SkDebugf("%s %d checkQueue done=%d last=%d\n", __FUNCTION__, state.index,
- state.done, state.last);
- pthread_cond_signal(&State4::checkQueue);
- while (state.done && !state.last) {
- if (debugThreads) SkDebugf("%s %d done=%d last=%d\n", __FUNCTION__, state.index, state.done, state.last);
- pthread_cond_wait(&state.initialized, &State4::addQueue);
- }
- pthread_mutex_unlock(&State4::addQueue);
- return !state.last;
-}
-
-int waitForCompletion() {
- int testsRun = 0;
- if (!gRunTestsInOneThread) {
- pthread_mutex_lock(&State4::addQueue);
- int runningThreads = maxThreads;
- int index;
- while (runningThreads > 0) {
- while (!State4::queue) {
- if (debugThreads) SkDebugf("%s checkQueue\n", __FUNCTION__);
- pthread_cond_wait(&State4::checkQueue, &State4::addQueue);
- }
- while (State4::queue) {
- --runningThreads;
- SkDebugf("•");
- State4::queue->last = true;
- State4* next = NULL;
- for (index = 0; index < maxThreads; ++index) {
- State4& test = threadState[index];
- if (test.done && !test.last) {
- next = &test;
- }
- }
- if (debugThreads) SkDebugf("%s %d next=%d deQueue\n", __FUNCTION__,
- State4::queue->index, next ? next->index : -1);
- pthread_cond_signal(&State4::queue->initialized);
- State4::queue = next;
- }
- }
- pthread_mutex_unlock(&State4::addQueue);
- for (index = 0; index < maxThreads; ++index) {
- pthread_join(threadState[index].threadID, NULL);
- testsRun += threadState[index].testsRun;
- }
- SkDebugf("\n");
- }
-#ifdef SK_DEBUG
- gDebugMaxWindSum = SK_MaxS32;
- gDebugMaxWindValue = SK_MaxS32;
-#endif
- return testsRun;
-}
diff --git a/experimental/Intersection/English.lproj/InfoPlist.strings b/experimental/Intersection/English.lproj/InfoPlist.strings
deleted file mode 100644
index 477b28ff8f..0000000000
--- a/experimental/Intersection/English.lproj/InfoPlist.strings
+++ /dev/null
@@ -1,2 +0,0 @@
-/* Localized versions of Info.plist keys */
-
diff --git a/experimental/Intersection/English.lproj/MainMenu.xib b/experimental/Intersection/English.lproj/MainMenu.xib
deleted file mode 100644
index 6e4dd1fca2..0000000000
--- a/experimental/Intersection/English.lproj/MainMenu.xib
+++ /dev/null
@@ -1,4119 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
- <data>
- <int key="IBDocument.SystemTarget">1060</int>
- <string key="IBDocument.SystemVersion">10A324</string>
- <string key="IBDocument.InterfaceBuilderVersion">719</string>
- <string key="IBDocument.AppKitVersion">1015</string>
- <string key="IBDocument.HIToolboxVersion">418.00</string>
- <object class="NSMutableDictionary" key="IBDocument.PluginVersions">
- <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string key="NS.object.0">719</string>
- </object>
- <object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <integer value="371"/>
- <integer value="29"/>
- </object>
- <object class="NSArray" key="IBDocument.PluginDependencies">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- </object>
- <object class="NSMutableDictionary" key="IBDocument.Metadata">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSArray" key="dict.sortedKeys" id="0">
- <bool key="EncodedWithXMLCoder">YES</bool>
- </object>
- <object class="NSMutableArray" key="dict.values">
- <bool key="EncodedWithXMLCoder">YES</bool>
- </object>
- </object>
- <object class="NSMutableArray" key="IBDocument.RootObjects" id="1048">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSCustomObject" id="1021">
- <string key="NSClassName">NSApplication</string>
- </object>
- <object class="NSCustomObject" id="1014">
- <string key="NSClassName">FirstResponder</string>
- </object>
- <object class="NSCustomObject" id="1050">
- <string key="NSClassName">NSApplication</string>
- </object>
- <object class="NSMenu" id="649796088">
- <string key="NSTitle">AMainMenu</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSMenuItem" id="694149608">
- <reference key="NSMenu" ref="649796088"/>
- <string key="NSTitle">edge</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <object class="NSCustomResource" key="NSOnImage" id="35465992">
- <string key="NSClassName">NSImage</string>
- <string key="NSResourceName">NSMenuCheckmark</string>
- </object>
- <object class="NSCustomResource" key="NSMixedImage" id="502551668">
- <string key="NSClassName">NSImage</string>
- <string key="NSResourceName">NSMenuMixedState</string>
- </object>
- <string key="NSAction">submenuAction:</string>
- <object class="NSMenu" key="NSSubmenu" id="110575045">
- <string key="NSTitle">edge</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSMenuItem" id="238522557">
- <reference key="NSMenu" ref="110575045"/>
- <string key="NSTitle">About edge</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="304266470">
- <reference key="NSMenu" ref="110575045"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="609285721">
- <reference key="NSMenu" ref="110575045"/>
- <string key="NSTitle">Preferences…</string>
- <string key="NSKeyEquiv">,</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="481834944">
- <reference key="NSMenu" ref="110575045"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="1046388886">
- <reference key="NSMenu" ref="110575045"/>
- <string key="NSTitle">Services</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <string key="NSAction">submenuAction:</string>
- <object class="NSMenu" key="NSSubmenu" id="752062318">
- <string key="NSTitle">Services</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- </object>
- <string key="NSName">_NSServicesMenu</string>
- </object>
- </object>
- <object class="NSMenuItem" id="646227648">
- <reference key="NSMenu" ref="110575045"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="755159360">
- <reference key="NSMenu" ref="110575045"/>
- <string key="NSTitle">Hide edge</string>
- <string key="NSKeyEquiv">h</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="342932134">
- <reference key="NSMenu" ref="110575045"/>
- <string key="NSTitle">Hide Others</string>
- <string key="NSKeyEquiv">h</string>
- <int key="NSKeyEquivModMask">1572864</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="908899353">
- <reference key="NSMenu" ref="110575045"/>
- <string key="NSTitle">Show All</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="1056857174">
- <reference key="NSMenu" ref="110575045"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="632727374">
- <reference key="NSMenu" ref="110575045"/>
- <string key="NSTitle">Quit edge</string>
- <string key="NSKeyEquiv">q</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- </object>
- <string key="NSName">_NSAppleMenu</string>
- </object>
- </object>
- <object class="NSMenuItem" id="379814623">
- <reference key="NSMenu" ref="649796088"/>
- <string key="NSTitle">File</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <string key="NSAction">submenuAction:</string>
- <object class="NSMenu" key="NSSubmenu" id="720053764">
- <string key="NSTitle">File</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSMenuItem" id="705341025">
- <reference key="NSMenu" ref="720053764"/>
- <string key="NSTitle">New</string>
- <string key="NSKeyEquiv">n</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="722745758">
- <reference key="NSMenu" ref="720053764"/>
- <string key="NSTitle">Open…</string>
- <string key="NSKeyEquiv">o</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="1025936716">
- <reference key="NSMenu" ref="720053764"/>
- <string key="NSTitle">Open Recent</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <string key="NSAction">submenuAction:</string>
- <object class="NSMenu" key="NSSubmenu" id="1065607017">
- <string key="NSTitle">Open Recent</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSMenuItem" id="759406840">
- <reference key="NSMenu" ref="1065607017"/>
- <string key="NSTitle">Clear Menu</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- </object>
- <string key="NSName">_NSRecentDocumentsMenu</string>
- </object>
- </object>
- <object class="NSMenuItem" id="425164168">
- <reference key="NSMenu" ref="720053764"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="776162233">
- <reference key="NSMenu" ref="720053764"/>
- <string key="NSTitle">Close</string>
- <string key="NSKeyEquiv">w</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="1023925487">
- <reference key="NSMenu" ref="720053764"/>
- <string key="NSTitle">Save</string>
- <string key="NSKeyEquiv">s</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="117038363">
- <reference key="NSMenu" ref="720053764"/>
- <string key="NSTitle">Save As…</string>
- <string key="NSKeyEquiv">S</string>
- <int key="NSKeyEquivModMask">1179648</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="579971712">
- <reference key="NSMenu" ref="720053764"/>
- <string key="NSTitle">Revert to Saved</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="1010469920">
- <reference key="NSMenu" ref="720053764"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="294629803">
- <reference key="NSMenu" ref="720053764"/>
- <string key="NSTitle">Page Setup...</string>
- <string key="NSKeyEquiv">P</string>
- <int key="NSKeyEquivModMask">1179648</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <string key="NSToolTip"/>
- </object>
- <object class="NSMenuItem" id="49223823">
- <reference key="NSMenu" ref="720053764"/>
- <string key="NSTitle">Print…</string>
- <string key="NSKeyEquiv">p</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- </object>
- </object>
- </object>
- <object class="NSMenuItem" id="952259628">
- <reference key="NSMenu" ref="649796088"/>
- <string key="NSTitle">Edit</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <string key="NSAction">submenuAction:</string>
- <object class="NSMenu" key="NSSubmenu" id="789758025">
- <string key="NSTitle">Edit</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSMenuItem" id="1058277027">
- <reference key="NSMenu" ref="789758025"/>
- <string key="NSTitle">Undo</string>
- <string key="NSKeyEquiv">z</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="790794224">
- <reference key="NSMenu" ref="789758025"/>
- <string key="NSTitle">Redo</string>
- <string key="NSKeyEquiv">Z</string>
- <int key="NSKeyEquivModMask">1179648</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="1040322652">
- <reference key="NSMenu" ref="789758025"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="296257095">
- <reference key="NSMenu" ref="789758025"/>
- <string key="NSTitle">Cut</string>
- <string key="NSKeyEquiv">x</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="860595796">
- <reference key="NSMenu" ref="789758025"/>
- <string key="NSTitle">Copy</string>
- <string key="NSKeyEquiv">c</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="29853731">
- <reference key="NSMenu" ref="789758025"/>
- <string key="NSTitle">Paste</string>
- <string key="NSKeyEquiv">v</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="82994268">
- <reference key="NSMenu" ref="789758025"/>
- <string key="NSTitle">Paste and Match Style</string>
- <string key="NSKeyEquiv">V</string>
- <int key="NSKeyEquivModMask">1572864</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="437104165">
- <reference key="NSMenu" ref="789758025"/>
- <string key="NSTitle">Delete</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="583158037">
- <reference key="NSMenu" ref="789758025"/>
- <string key="NSTitle">Select All</string>
- <string key="NSKeyEquiv">a</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="212016141">
- <reference key="NSMenu" ref="789758025"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="892235320">
- <reference key="NSMenu" ref="789758025"/>
- <string key="NSTitle">Find</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <string key="NSAction">submenuAction:</string>
- <object class="NSMenu" key="NSSubmenu" id="963351320">
- <string key="NSTitle">Find</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSMenuItem" id="447796847">
- <reference key="NSMenu" ref="963351320"/>
- <string key="NSTitle">Find…</string>
- <string key="NSKeyEquiv">f</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <int key="NSTag">1</int>
- </object>
- <object class="NSMenuItem" id="326711663">
- <reference key="NSMenu" ref="963351320"/>
- <string key="NSTitle">Find Next</string>
- <string key="NSKeyEquiv">g</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <int key="NSTag">2</int>
- </object>
- <object class="NSMenuItem" id="270902937">
- <reference key="NSMenu" ref="963351320"/>
- <string key="NSTitle">Find Previous</string>
- <string key="NSKeyEquiv">G</string>
- <int key="NSKeyEquivModMask">1179648</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <int key="NSTag">3</int>
- </object>
- <object class="NSMenuItem" id="159080638">
- <reference key="NSMenu" ref="963351320"/>
- <string key="NSTitle">Use Selection for Find</string>
- <string key="NSKeyEquiv">e</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <int key="NSTag">7</int>
- </object>
- <object class="NSMenuItem" id="88285865">
- <reference key="NSMenu" ref="963351320"/>
- <string key="NSTitle">Jump to Selection</string>
- <string key="NSKeyEquiv">j</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- </object>
- </object>
- </object>
- <object class="NSMenuItem" id="972420730">
- <reference key="NSMenu" ref="789758025"/>
- <string key="NSTitle">Spelling and Grammar</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <string key="NSAction">submenuAction:</string>
- <object class="NSMenu" key="NSSubmenu" id="769623530">
- <string key="NSTitle">Spelling and Grammar</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSMenuItem" id="679648819">
- <reference key="NSMenu" ref="769623530"/>
- <string key="NSTitle">Show Spelling and Grammar</string>
- <string key="NSKeyEquiv">:</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="96193923">
- <reference key="NSMenu" ref="769623530"/>
- <string key="NSTitle">Check Document Now</string>
- <string key="NSKeyEquiv">;</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="859480356">
- <reference key="NSMenu" ref="769623530"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="948374510">
- <reference key="NSMenu" ref="769623530"/>
- <string key="NSTitle">Check Spelling While Typing</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="967646866">
- <reference key="NSMenu" ref="769623530"/>
- <string key="NSTitle">Check Grammar With Spelling</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="795346622">
- <reference key="NSMenu" ref="769623530"/>
- <string key="NSTitle">Correct Spelling Automatically</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- </object>
- </object>
- </object>
- <object class="NSMenuItem" id="507821607">
- <reference key="NSMenu" ref="789758025"/>
- <string key="NSTitle">Substitutions</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <string key="NSAction">submenuAction:</string>
- <object class="NSMenu" key="NSSubmenu" id="698887838">
- <string key="NSTitle">Substitutions</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSMenuItem" id="65139061">
- <reference key="NSMenu" ref="698887838"/>
- <string key="NSTitle">Show Substitutions</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="19036812">
- <reference key="NSMenu" ref="698887838"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="605118523">
- <reference key="NSMenu" ref="698887838"/>
- <string key="NSTitle">Smart Copy/Paste</string>
- <string key="NSKeyEquiv">f</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <int key="NSTag">1</int>
- </object>
- <object class="NSMenuItem" id="197661976">
- <reference key="NSMenu" ref="698887838"/>
- <string key="NSTitle">Smart Quotes</string>
- <string key="NSKeyEquiv">g</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <int key="NSTag">2</int>
- </object>
- <object class="NSMenuItem" id="672708820">
- <reference key="NSMenu" ref="698887838"/>
- <string key="NSTitle">Smart Dashes</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="708854459">
- <reference key="NSMenu" ref="698887838"/>
- <string key="NSTitle">Smart Links</string>
- <string key="NSKeyEquiv">G</string>
- <int key="NSKeyEquivModMask">1179648</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <int key="NSTag">3</int>
- </object>
- <object class="NSMenuItem" id="537092702">
- <reference key="NSMenu" ref="698887838"/>
- <string key="NSTitle">Text Replacement</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- </object>
- </object>
- </object>
- <object class="NSMenuItem" id="288088188">
- <reference key="NSMenu" ref="789758025"/>
- <string key="NSTitle">Transformations</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <string key="NSAction">submenuAction:</string>
- <object class="NSMenu" key="NSSubmenu" id="579392910">
- <string key="NSTitle">Transformations</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSMenuItem" id="1060694897">
- <reference key="NSMenu" ref="579392910"/>
- <string key="NSTitle">Make Upper Case</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="879586729">
- <reference key="NSMenu" ref="579392910"/>
- <string key="NSTitle">Make Lower Case</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="56570060">
- <reference key="NSMenu" ref="579392910"/>
- <string key="NSTitle">Capitalize</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- </object>
- </object>
- </object>
- <object class="NSMenuItem" id="676164635">
- <reference key="NSMenu" ref="789758025"/>
- <string key="NSTitle">Speech</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <string key="NSAction">submenuAction:</string>
- <object class="NSMenu" key="NSSubmenu" id="785027613">
- <string key="NSTitle">Speech</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSMenuItem" id="731782645">
- <reference key="NSMenu" ref="785027613"/>
- <string key="NSTitle">Start Speaking</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="680220178">
- <reference key="NSMenu" ref="785027613"/>
- <string key="NSTitle">Stop Speaking</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- <object class="NSMenuItem" id="302598603">
- <reference key="NSMenu" ref="649796088"/>
- <string key="NSTitle">Format</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <string key="NSAction">submenuAction:</string>
- <object class="NSMenu" key="NSSubmenu" id="941447902">
- <string key="NSTitle">Format</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSMenuItem" id="792887677">
- <reference key="NSMenu" ref="941447902"/>
- <string key="NSTitle">Font</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <string key="NSAction">submenuAction:</string>
- <object class="NSMenu" key="NSSubmenu" id="786677654">
- <string key="NSTitle">Font</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSMenuItem" id="159677712">
- <reference key="NSMenu" ref="786677654"/>
- <string key="NSTitle">Show Fonts</string>
- <string key="NSKeyEquiv">t</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="305399458">
- <reference key="NSMenu" ref="786677654"/>
- <string key="NSTitle">Bold</string>
- <string key="NSKeyEquiv">b</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <int key="NSTag">2</int>
- </object>
- <object class="NSMenuItem" id="814362025">
- <reference key="NSMenu" ref="786677654"/>
- <string key="NSTitle">Italic</string>
- <string key="NSKeyEquiv">i</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <int key="NSTag">1</int>
- </object>
- <object class="NSMenuItem" id="330926929">
- <reference key="NSMenu" ref="786677654"/>
- <string key="NSTitle">Underline</string>
- <string key="NSKeyEquiv">u</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="533507878">
- <reference key="NSMenu" ref="786677654"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="158063935">
- <reference key="NSMenu" ref="786677654"/>
- <string key="NSTitle">Bigger</string>
- <string key="NSKeyEquiv">+</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <int key="NSTag">3</int>
- </object>
- <object class="NSMenuItem" id="885547335">
- <reference key="NSMenu" ref="786677654"/>
- <string key="NSTitle">Smaller</string>
- <string key="NSKeyEquiv">-</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <int key="NSTag">4</int>
- </object>
- <object class="NSMenuItem" id="901062459">
- <reference key="NSMenu" ref="786677654"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="767671776">
- <reference key="NSMenu" ref="786677654"/>
- <string key="NSTitle">Kern</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <string key="NSAction">submenuAction:</string>
- <object class="NSMenu" key="NSSubmenu" id="175441468">
- <string key="NSTitle">Kern</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSMenuItem" id="252969304">
- <reference key="NSMenu" ref="175441468"/>
- <string key="NSTitle">Use Default</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="766922938">
- <reference key="NSMenu" ref="175441468"/>
- <string key="NSTitle">Use None</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="677519740">
- <reference key="NSMenu" ref="175441468"/>
- <string key="NSTitle">Tighten</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="238351151">
- <reference key="NSMenu" ref="175441468"/>
- <string key="NSTitle">Loosen</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- </object>
- </object>
- </object>
- <object class="NSMenuItem" id="691570813">
- <reference key="NSMenu" ref="786677654"/>
- <string key="NSTitle">Ligature</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <string key="NSAction">submenuAction:</string>
- <object class="NSMenu" key="NSSubmenu" id="1058217995">
- <string key="NSTitle">Ligature</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSMenuItem" id="706297211">
- <reference key="NSMenu" ref="1058217995"/>
- <string key="NSTitle">Use Default</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="568384683">
- <reference key="NSMenu" ref="1058217995"/>
- <string key="NSTitle">Use None</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="663508465">
- <reference key="NSMenu" ref="1058217995"/>
- <string key="NSTitle">Use All</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- </object>
- </object>
- </object>
- <object class="NSMenuItem" id="769124883">
- <reference key="NSMenu" ref="786677654"/>
- <string key="NSTitle">Baseline</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <string key="NSAction">submenuAction:</string>
- <object class="NSMenu" key="NSSubmenu" id="18263474">
- <string key="NSTitle">Baseline</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSMenuItem" id="257962622">
- <reference key="NSMenu" ref="18263474"/>
- <string key="NSTitle">Use Default</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="644725453">
- <reference key="NSMenu" ref="18263474"/>
- <string key="NSTitle">Superscript</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="1037576581">
- <reference key="NSMenu" ref="18263474"/>
- <string key="NSTitle">Subscript</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="941806246">
- <reference key="NSMenu" ref="18263474"/>
- <string key="NSTitle">Raise</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="1045724900">
- <reference key="NSMenu" ref="18263474"/>
- <string key="NSTitle">Lower</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- </object>
- </object>
- </object>
- <object class="NSMenuItem" id="739652853">
- <reference key="NSMenu" ref="786677654"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="1012600125">
- <reference key="NSMenu" ref="786677654"/>
- <string key="NSTitle">Show Colors</string>
- <string key="NSKeyEquiv">C</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="214559597">
- <reference key="NSMenu" ref="786677654"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="596732606">
- <reference key="NSMenu" ref="786677654"/>
- <string key="NSTitle">Copy Style</string>
- <string key="NSKeyEquiv">c</string>
- <int key="NSKeyEquivModMask">1572864</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="393423671">
- <reference key="NSMenu" ref="786677654"/>
- <string key="NSTitle">Paste Style</string>
- <string key="NSKeyEquiv">v</string>
- <int key="NSKeyEquivModMask">1572864</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- </object>
- <string key="NSName">_NSFontMenu</string>
- </object>
- </object>
- <object class="NSMenuItem" id="215659978">
- <reference key="NSMenu" ref="941447902"/>
- <string key="NSTitle">Text</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <string key="NSAction">submenuAction:</string>
- <object class="NSMenu" key="NSSubmenu" id="446991534">
- <string key="NSTitle">Text</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSMenuItem" id="875092757">
- <reference key="NSMenu" ref="446991534"/>
- <string key="NSTitle">Align Left</string>
- <string key="NSKeyEquiv">{</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="630155264">
- <reference key="NSMenu" ref="446991534"/>
- <string key="NSTitle">Center</string>
- <string key="NSKeyEquiv">|</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="945678886">
- <reference key="NSMenu" ref="446991534"/>
- <string key="NSTitle">Justify</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="512868991">
- <reference key="NSMenu" ref="446991534"/>
- <string key="NSTitle">Align Right</string>
- <string key="NSKeyEquiv">}</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="163117631">
- <reference key="NSMenu" ref="446991534"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="31516759">
- <reference key="NSMenu" ref="446991534"/>
- <string key="NSTitle">Writing Direction</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <string key="NSAction">submenuAction:</string>
- <object class="NSMenu" key="NSSubmenu" id="956096989">
- <string key="NSTitle">Writing Direction</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSMenuItem" id="257099033">
- <reference key="NSMenu" ref="956096989"/>
- <bool key="NSIsDisabled">YES</bool>
- <string key="NSTitle">Paragraph</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="551969625">
- <reference key="NSMenu" ref="956096989"/>
- <string type="base64-UTF8" key="NSTitle">CURlZmF1bHQ</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="249532473">
- <reference key="NSMenu" ref="956096989"/>
- <string type="base64-UTF8" key="NSTitle">CUxlZnQgdG8gUmlnaHQ</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="607364498">
- <reference key="NSMenu" ref="956096989"/>
- <string type="base64-UTF8" key="NSTitle">CVJpZ2h0IHRvIExlZnQ</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="508151438">
- <reference key="NSMenu" ref="956096989"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="981751889">
- <reference key="NSMenu" ref="956096989"/>
- <bool key="NSIsDisabled">YES</bool>
- <string key="NSTitle">Selection</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="380031999">
- <reference key="NSMenu" ref="956096989"/>
- <string type="base64-UTF8" key="NSTitle">CURlZmF1bHQ</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="825984362">
- <reference key="NSMenu" ref="956096989"/>
- <string type="base64-UTF8" key="NSTitle">CUxlZnQgdG8gUmlnaHQ</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="560145579">
- <reference key="NSMenu" ref="956096989"/>
- <string type="base64-UTF8" key="NSTitle">CVJpZ2h0IHRvIExlZnQ</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- </object>
- </object>
- </object>
- <object class="NSMenuItem" id="908105787">
- <reference key="NSMenu" ref="446991534"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="644046920">
- <reference key="NSMenu" ref="446991534"/>
- <string key="NSTitle">Show Ruler</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="231811626">
- <reference key="NSMenu" ref="446991534"/>
- <string key="NSTitle">Copy Ruler</string>
- <string key="NSKeyEquiv">c</string>
- <int key="NSKeyEquivModMask">1310720</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="883618387">
- <reference key="NSMenu" ref="446991534"/>
- <string key="NSTitle">Paste Ruler</string>
- <string key="NSKeyEquiv">v</string>
- <int key="NSKeyEquivModMask">1310720</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- <object class="NSMenuItem" id="586577488">
- <reference key="NSMenu" ref="649796088"/>
- <string key="NSTitle">View</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <string key="NSAction">submenuAction:</string>
- <object class="NSMenu" key="NSSubmenu" id="466310130">
- <string key="NSTitle">View</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSMenuItem" id="102151532">
- <reference key="NSMenu" ref="466310130"/>
- <string key="NSTitle">Show Toolbar</string>
- <string key="NSKeyEquiv">t</string>
- <int key="NSKeyEquivModMask">1572864</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="237841660">
- <reference key="NSMenu" ref="466310130"/>
- <string key="NSTitle">Customize Toolbar…</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- </object>
- </object>
- </object>
- <object class="NSMenuItem" id="713487014">
- <reference key="NSMenu" ref="649796088"/>
- <string key="NSTitle">Window</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <string key="NSAction">submenuAction:</string>
- <object class="NSMenu" key="NSSubmenu" id="835318025">
- <string key="NSTitle">Window</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSMenuItem" id="1011231497">
- <reference key="NSMenu" ref="835318025"/>
- <string key="NSTitle">Minimize</string>
- <string key="NSKeyEquiv">m</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="575023229">
- <reference key="NSMenu" ref="835318025"/>
- <string key="NSTitle">Zoom</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="299356726">
- <reference key="NSMenu" ref="835318025"/>
- <bool key="NSIsDisabled">YES</bool>
- <bool key="NSIsSeparator">YES</bool>
- <string key="NSTitle"/>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- <object class="NSMenuItem" id="625202149">
- <reference key="NSMenu" ref="835318025"/>
- <string key="NSTitle">Bring All to Front</string>
- <string key="NSKeyEquiv"/>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- </object>
- <string key="NSName">_NSWindowsMenu</string>
- </object>
- </object>
- <object class="NSMenuItem" id="448692316">
- <reference key="NSMenu" ref="649796088"/>
- <string key="NSTitle">Help</string>
- <string key="NSKeyEquiv"/>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- <string key="NSAction">submenuAction:</string>
- <object class="NSMenu" key="NSSubmenu" id="992780483">
- <string key="NSTitle">Help</string>
- <object class="NSMutableArray" key="NSMenuItems">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSMenuItem" id="105068016">
- <reference key="NSMenu" ref="992780483"/>
- <string key="NSTitle">edge Help</string>
- <string key="NSKeyEquiv">?</string>
- <int key="NSKeyEquivModMask">1048576</int>
- <int key="NSMnemonicLoc">2147483647</int>
- <reference key="NSOnImage" ref="35465992"/>
- <reference key="NSMixedImage" ref="502551668"/>
- </object>
- </object>
- <string key="NSName">_NSHelpMenu</string>
- </object>
- </object>
- </object>
- <string key="NSName">_NSMainMenu</string>
- </object>
- <object class="NSWindowTemplate" id="972006081">
- <int key="NSWindowStyleMask">15</int>
- <int key="NSWindowBacking">2</int>
- <string key="NSWindowRect">{{335, 390}, {480, 360}}</string>
- <int key="NSWTFlags">1954021376</int>
- <string key="NSWindowTitle">edge</string>
- <string key="NSWindowClass">NSWindow</string>
- <nil key="NSViewClass"/>
- <string key="NSWindowContentMaxSize">{1.79769e+308, 1.79769e+308}</string>
- <object class="NSView" key="NSWindowView" id="439893737">
- <reference key="NSNextResponder"/>
- <int key="NSvFlags">256</int>
- <string key="NSFrameSize">{480, 360}</string>
- <reference key="NSSuperview"/>
- </object>
- <string key="NSScreenRect">{{0, 0}, {1920, 1178}}</string>
- <string key="NSMaxSize">{1.79769e+308, 1.79769e+308}</string>
- </object>
- <object class="NSCustomObject" id="976324537">
- <string key="NSClassName">edgeAppDelegate</string>
- </object>
- <object class="NSCustomObject" id="755631768">
- <string key="NSClassName">NSFontManager</string>
- </object>
- </object>
- <object class="IBObjectContainer" key="IBDocument.Objects">
- <object class="NSMutableArray" key="connectionRecords">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">performMiniaturize:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="1011231497"/>
- </object>
- <int key="connectionID">37</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">arrangeInFront:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="625202149"/>
- </object>
- <int key="connectionID">39</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">print:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="49223823"/>
- </object>
- <int key="connectionID">86</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">runPageLayout:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="294629803"/>
- </object>
- <int key="connectionID">87</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">clearRecentDocuments:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="759406840"/>
- </object>
- <int key="connectionID">127</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">orderFrontStandardAboutPanel:</string>
- <reference key="source" ref="1021"/>
- <reference key="destination" ref="238522557"/>
- </object>
- <int key="connectionID">142</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">performClose:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="776162233"/>
- </object>
- <int key="connectionID">193</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">toggleContinuousSpellChecking:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="948374510"/>
- </object>
- <int key="connectionID">222</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">undo:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="1058277027"/>
- </object>
- <int key="connectionID">223</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">copy:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="860595796"/>
- </object>
- <int key="connectionID">224</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">checkSpelling:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="96193923"/>
- </object>
- <int key="connectionID">225</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">paste:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="29853731"/>
- </object>
- <int key="connectionID">226</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">stopSpeaking:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="680220178"/>
- </object>
- <int key="connectionID">227</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">cut:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="296257095"/>
- </object>
- <int key="connectionID">228</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">showGuessPanel:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="679648819"/>
- </object>
- <int key="connectionID">230</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">redo:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="790794224"/>
- </object>
- <int key="connectionID">231</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">selectAll:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="583158037"/>
- </object>
- <int key="connectionID">232</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">startSpeaking:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="731782645"/>
- </object>
- <int key="connectionID">233</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">delete:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="437104165"/>
- </object>
- <int key="connectionID">235</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">performZoom:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="575023229"/>
- </object>
- <int key="connectionID">240</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">performFindPanelAction:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="447796847"/>
- </object>
- <int key="connectionID">241</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">centerSelectionInVisibleArea:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="88285865"/>
- </object>
- <int key="connectionID">245</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">toggleGrammarChecking:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="967646866"/>
- </object>
- <int key="connectionID">347</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">toggleSmartInsertDelete:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="605118523"/>
- </object>
- <int key="connectionID">355</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">toggleAutomaticQuoteSubstitution:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="197661976"/>
- </object>
- <int key="connectionID">356</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">toggleAutomaticLinkDetection:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="708854459"/>
- </object>
- <int key="connectionID">357</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">saveDocument:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="1023925487"/>
- </object>
- <int key="connectionID">362</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">saveDocumentAs:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="117038363"/>
- </object>
- <int key="connectionID">363</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">revertDocumentToSaved:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="579971712"/>
- </object>
- <int key="connectionID">364</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">runToolbarCustomizationPalette:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="237841660"/>
- </object>
- <int key="connectionID">365</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">toggleToolbarShown:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="102151532"/>
- </object>
- <int key="connectionID">366</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">hide:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="755159360"/>
- </object>
- <int key="connectionID">367</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">hideOtherApplications:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="342932134"/>
- </object>
- <int key="connectionID">368</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">unhideAllApplications:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="908899353"/>
- </object>
- <int key="connectionID">370</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">newDocument:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="705341025"/>
- </object>
- <int key="connectionID">373</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">openDocument:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="722745758"/>
- </object>
- <int key="connectionID">374</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">addFontTrait:</string>
- <reference key="source" ref="755631768"/>
- <reference key="destination" ref="305399458"/>
- </object>
- <int key="connectionID">421</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">addFontTrait:</string>
- <reference key="source" ref="755631768"/>
- <reference key="destination" ref="814362025"/>
- </object>
- <int key="connectionID">422</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">modifyFont:</string>
- <reference key="source" ref="755631768"/>
- <reference key="destination" ref="885547335"/>
- </object>
- <int key="connectionID">423</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">orderFrontFontPanel:</string>
- <reference key="source" ref="755631768"/>
- <reference key="destination" ref="159677712"/>
- </object>
- <int key="connectionID">424</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">modifyFont:</string>
- <reference key="source" ref="755631768"/>
- <reference key="destination" ref="158063935"/>
- </object>
- <int key="connectionID">425</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">raiseBaseline:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="941806246"/>
- </object>
- <int key="connectionID">426</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">lowerBaseline:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="1045724900"/>
- </object>
- <int key="connectionID">427</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">copyFont:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="596732606"/>
- </object>
- <int key="connectionID">428</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">subscript:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="1037576581"/>
- </object>
- <int key="connectionID">429</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">superscript:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="644725453"/>
- </object>
- <int key="connectionID">430</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">tightenKerning:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="677519740"/>
- </object>
- <int key="connectionID">431</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">underline:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="330926929"/>
- </object>
- <int key="connectionID">432</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">orderFrontColorPanel:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="1012600125"/>
- </object>
- <int key="connectionID">433</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">useAllLigatures:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="663508465"/>
- </object>
- <int key="connectionID">434</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">loosenKerning:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="238351151"/>
- </object>
- <int key="connectionID">435</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">pasteFont:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="393423671"/>
- </object>
- <int key="connectionID">436</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">unscript:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="257962622"/>
- </object>
- <int key="connectionID">437</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">useStandardKerning:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="252969304"/>
- </object>
- <int key="connectionID">438</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">useStandardLigatures:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="706297211"/>
- </object>
- <int key="connectionID">439</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">turnOffLigatures:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="568384683"/>
- </object>
- <int key="connectionID">440</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">turnOffKerning:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="766922938"/>
- </object>
- <int key="connectionID">441</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">terminate:</string>
- <reference key="source" ref="1050"/>
- <reference key="destination" ref="632727374"/>
- </object>
- <int key="connectionID">449</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">toggleAutomaticSpellingCorrection:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="795346622"/>
- </object>
- <int key="connectionID">456</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">orderFrontSubstitutionsPanel:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="65139061"/>
- </object>
- <int key="connectionID">458</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">toggleAutomaticDashSubstitution:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="672708820"/>
- </object>
- <int key="connectionID">461</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">toggleAutomaticTextReplacement:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="537092702"/>
- </object>
- <int key="connectionID">463</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">uppercaseWord:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="1060694897"/>
- </object>
- <int key="connectionID">464</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">capitalizeWord:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="56570060"/>
- </object>
- <int key="connectionID">467</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">lowercaseWord:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="879586729"/>
- </object>
- <int key="connectionID">468</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">pasteAsPlainText:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="82994268"/>
- </object>
- <int key="connectionID">486</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">performFindPanelAction:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="326711663"/>
- </object>
- <int key="connectionID">487</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">performFindPanelAction:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="270902937"/>
- </object>
- <int key="connectionID">488</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">performFindPanelAction:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="159080638"/>
- </object>
- <int key="connectionID">489</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">showHelp:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="105068016"/>
- </object>
- <int key="connectionID">493</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBOutletConnection" key="connection">
- <string key="label">delegate</string>
- <reference key="source" ref="1021"/>
- <reference key="destination" ref="976324537"/>
- </object>
- <int key="connectionID">495</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">alignCenter:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="630155264"/>
- </object>
- <int key="connectionID">518</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">pasteRuler:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="883618387"/>
- </object>
- <int key="connectionID">519</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">toggleRuler:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="644046920"/>
- </object>
- <int key="connectionID">520</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">alignRight:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="512868991"/>
- </object>
- <int key="connectionID">521</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">copyRuler:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="231811626"/>
- </object>
- <int key="connectionID">522</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">alignJustified:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="945678886"/>
- </object>
- <int key="connectionID">523</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">alignLeft:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="875092757"/>
- </object>
- <int key="connectionID">524</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">makeBaseWritingDirectionNatural:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="551969625"/>
- </object>
- <int key="connectionID">525</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">makeBaseWritingDirectionLeftToRight:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="249532473"/>
- </object>
- <int key="connectionID">526</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">makeBaseWritingDirectionRightToLeft:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="607364498"/>
- </object>
- <int key="connectionID">527</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">makeTextWritingDirectionNatural:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="380031999"/>
- </object>
- <int key="connectionID">528</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">makeTextWritingDirectionLeftToRight:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="825984362"/>
- </object>
- <int key="connectionID">529</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">makeTextWritingDirectionRightToLeft:</string>
- <reference key="source" ref="1014"/>
- <reference key="destination" ref="560145579"/>
- </object>
- <int key="connectionID">530</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBOutletConnection" key="connection">
- <string key="label">window</string>
- <reference key="source" ref="976324537"/>
- <reference key="destination" ref="972006081"/>
- </object>
- <int key="connectionID">532</int>
- </object>
- </object>
- <object class="IBMutableOrderedSet" key="objectRecords">
- <object class="NSArray" key="orderedObjects">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="IBObjectRecord">
- <int key="objectID">0</int>
- <reference key="object" ref="0"/>
- <reference key="children" ref="1048"/>
- <nil key="parent"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">-2</int>
- <reference key="object" ref="1021"/>
- <reference key="parent" ref="0"/>
- <string key="objectName">File's Owner</string>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">-1</int>
- <reference key="object" ref="1014"/>
- <reference key="parent" ref="0"/>
- <string key="objectName">First Responder</string>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">-3</int>
- <reference key="object" ref="1050"/>
- <reference key="parent" ref="0"/>
- <string key="objectName">Application</string>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">29</int>
- <reference key="object" ref="649796088"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="713487014"/>
- <reference ref="694149608"/>
- <reference ref="952259628"/>
- <reference ref="379814623"/>
- <reference ref="586577488"/>
- <reference ref="302598603"/>
- <reference ref="448692316"/>
- </object>
- <reference key="parent" ref="0"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">19</int>
- <reference key="object" ref="713487014"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="835318025"/>
- </object>
- <reference key="parent" ref="649796088"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">56</int>
- <reference key="object" ref="694149608"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="110575045"/>
- </object>
- <reference key="parent" ref="649796088"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">217</int>
- <reference key="object" ref="952259628"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="789758025"/>
- </object>
- <reference key="parent" ref="649796088"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">83</int>
- <reference key="object" ref="379814623"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="720053764"/>
- </object>
- <reference key="parent" ref="649796088"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">81</int>
- <reference key="object" ref="720053764"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="1023925487"/>
- <reference ref="117038363"/>
- <reference ref="49223823"/>
- <reference ref="722745758"/>
- <reference ref="705341025"/>
- <reference ref="1025936716"/>
- <reference ref="294629803"/>
- <reference ref="776162233"/>
- <reference ref="425164168"/>
- <reference ref="579971712"/>
- <reference ref="1010469920"/>
- </object>
- <reference key="parent" ref="379814623"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">75</int>
- <reference key="object" ref="1023925487"/>
- <reference key="parent" ref="720053764"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">80</int>
- <reference key="object" ref="117038363"/>
- <reference key="parent" ref="720053764"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">78</int>
- <reference key="object" ref="49223823"/>
- <reference key="parent" ref="720053764"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">72</int>
- <reference key="object" ref="722745758"/>
- <reference key="parent" ref="720053764"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">82</int>
- <reference key="object" ref="705341025"/>
- <reference key="parent" ref="720053764"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">124</int>
- <reference key="object" ref="1025936716"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="1065607017"/>
- </object>
- <reference key="parent" ref="720053764"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">77</int>
- <reference key="object" ref="294629803"/>
- <reference key="parent" ref="720053764"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">73</int>
- <reference key="object" ref="776162233"/>
- <reference key="parent" ref="720053764"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">79</int>
- <reference key="object" ref="425164168"/>
- <reference key="parent" ref="720053764"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">112</int>
- <reference key="object" ref="579971712"/>
- <reference key="parent" ref="720053764"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">74</int>
- <reference key="object" ref="1010469920"/>
- <reference key="parent" ref="720053764"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">125</int>
- <reference key="object" ref="1065607017"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="759406840"/>
- </object>
- <reference key="parent" ref="1025936716"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">126</int>
- <reference key="object" ref="759406840"/>
- <reference key="parent" ref="1065607017"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">205</int>
- <reference key="object" ref="789758025"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="437104165"/>
- <reference ref="583158037"/>
- <reference ref="1058277027"/>
- <reference ref="212016141"/>
- <reference ref="296257095"/>
- <reference ref="29853731"/>
- <reference ref="860595796"/>
- <reference ref="1040322652"/>
- <reference ref="790794224"/>
- <reference ref="892235320"/>
- <reference ref="972420730"/>
- <reference ref="676164635"/>
- <reference ref="507821607"/>
- <reference ref="288088188"/>
- <reference ref="82994268"/>
- </object>
- <reference key="parent" ref="952259628"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">202</int>
- <reference key="object" ref="437104165"/>
- <reference key="parent" ref="789758025"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">198</int>
- <reference key="object" ref="583158037"/>
- <reference key="parent" ref="789758025"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">207</int>
- <reference key="object" ref="1058277027"/>
- <reference key="parent" ref="789758025"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">214</int>
- <reference key="object" ref="212016141"/>
- <reference key="parent" ref="789758025"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">199</int>
- <reference key="object" ref="296257095"/>
- <reference key="parent" ref="789758025"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">203</int>
- <reference key="object" ref="29853731"/>
- <reference key="parent" ref="789758025"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">197</int>
- <reference key="object" ref="860595796"/>
- <reference key="parent" ref="789758025"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">206</int>
- <reference key="object" ref="1040322652"/>
- <reference key="parent" ref="789758025"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">215</int>
- <reference key="object" ref="790794224"/>
- <reference key="parent" ref="789758025"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">218</int>
- <reference key="object" ref="892235320"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="963351320"/>
- </object>
- <reference key="parent" ref="789758025"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">216</int>
- <reference key="object" ref="972420730"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="769623530"/>
- </object>
- <reference key="parent" ref="789758025"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">200</int>
- <reference key="object" ref="769623530"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="948374510"/>
- <reference ref="96193923"/>
- <reference ref="679648819"/>
- <reference ref="967646866"/>
- <reference ref="859480356"/>
- <reference ref="795346622"/>
- </object>
- <reference key="parent" ref="972420730"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">219</int>
- <reference key="object" ref="948374510"/>
- <reference key="parent" ref="769623530"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">201</int>
- <reference key="object" ref="96193923"/>
- <reference key="parent" ref="769623530"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">204</int>
- <reference key="object" ref="679648819"/>
- <reference key="parent" ref="769623530"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">220</int>
- <reference key="object" ref="963351320"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="270902937"/>
- <reference ref="88285865"/>
- <reference ref="159080638"/>
- <reference ref="326711663"/>
- <reference ref="447796847"/>
- </object>
- <reference key="parent" ref="892235320"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">213</int>
- <reference key="object" ref="270902937"/>
- <reference key="parent" ref="963351320"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">210</int>
- <reference key="object" ref="88285865"/>
- <reference key="parent" ref="963351320"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">221</int>
- <reference key="object" ref="159080638"/>
- <reference key="parent" ref="963351320"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">208</int>
- <reference key="object" ref="326711663"/>
- <reference key="parent" ref="963351320"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">209</int>
- <reference key="object" ref="447796847"/>
- <reference key="parent" ref="963351320"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">57</int>
- <reference key="object" ref="110575045"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="238522557"/>
- <reference ref="755159360"/>
- <reference ref="908899353"/>
- <reference ref="632727374"/>
- <reference ref="646227648"/>
- <reference ref="609285721"/>
- <reference ref="481834944"/>
- <reference ref="304266470"/>
- <reference ref="1046388886"/>
- <reference ref="1056857174"/>
- <reference ref="342932134"/>
- </object>
- <reference key="parent" ref="694149608"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">58</int>
- <reference key="object" ref="238522557"/>
- <reference key="parent" ref="110575045"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">134</int>
- <reference key="object" ref="755159360"/>
- <reference key="parent" ref="110575045"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">150</int>
- <reference key="object" ref="908899353"/>
- <reference key="parent" ref="110575045"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">136</int>
- <reference key="object" ref="632727374"/>
- <reference key="parent" ref="110575045"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">144</int>
- <reference key="object" ref="646227648"/>
- <reference key="parent" ref="110575045"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">129</int>
- <reference key="object" ref="609285721"/>
- <reference key="parent" ref="110575045"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">143</int>
- <reference key="object" ref="481834944"/>
- <reference key="parent" ref="110575045"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">236</int>
- <reference key="object" ref="304266470"/>
- <reference key="parent" ref="110575045"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">131</int>
- <reference key="object" ref="1046388886"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="752062318"/>
- </object>
- <reference key="parent" ref="110575045"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">149</int>
- <reference key="object" ref="1056857174"/>
- <reference key="parent" ref="110575045"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">145</int>
- <reference key="object" ref="342932134"/>
- <reference key="parent" ref="110575045"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">130</int>
- <reference key="object" ref="752062318"/>
- <reference key="parent" ref="1046388886"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">24</int>
- <reference key="object" ref="835318025"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="299356726"/>
- <reference ref="625202149"/>
- <reference ref="575023229"/>
- <reference ref="1011231497"/>
- </object>
- <reference key="parent" ref="713487014"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">92</int>
- <reference key="object" ref="299356726"/>
- <reference key="parent" ref="835318025"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">5</int>
- <reference key="object" ref="625202149"/>
- <reference key="parent" ref="835318025"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">239</int>
- <reference key="object" ref="575023229"/>
- <reference key="parent" ref="835318025"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">23</int>
- <reference key="object" ref="1011231497"/>
- <reference key="parent" ref="835318025"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">295</int>
- <reference key="object" ref="586577488"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="466310130"/>
- </object>
- <reference key="parent" ref="649796088"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">296</int>
- <reference key="object" ref="466310130"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="102151532"/>
- <reference ref="237841660"/>
- </object>
- <reference key="parent" ref="586577488"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">297</int>
- <reference key="object" ref="102151532"/>
- <reference key="parent" ref="466310130"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">298</int>
- <reference key="object" ref="237841660"/>
- <reference key="parent" ref="466310130"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">211</int>
- <reference key="object" ref="676164635"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="785027613"/>
- </object>
- <reference key="parent" ref="789758025"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">212</int>
- <reference key="object" ref="785027613"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="680220178"/>
- <reference ref="731782645"/>
- </object>
- <reference key="parent" ref="676164635"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">195</int>
- <reference key="object" ref="680220178"/>
- <reference key="parent" ref="785027613"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">196</int>
- <reference key="object" ref="731782645"/>
- <reference key="parent" ref="785027613"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">346</int>
- <reference key="object" ref="967646866"/>
- <reference key="parent" ref="769623530"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">348</int>
- <reference key="object" ref="507821607"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="698887838"/>
- </object>
- <reference key="parent" ref="789758025"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">349</int>
- <reference key="object" ref="698887838"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="605118523"/>
- <reference ref="197661976"/>
- <reference ref="708854459"/>
- <reference ref="65139061"/>
- <reference ref="19036812"/>
- <reference ref="672708820"/>
- <reference ref="537092702"/>
- </object>
- <reference key="parent" ref="507821607"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">350</int>
- <reference key="object" ref="605118523"/>
- <reference key="parent" ref="698887838"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">351</int>
- <reference key="object" ref="197661976"/>
- <reference key="parent" ref="698887838"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">354</int>
- <reference key="object" ref="708854459"/>
- <reference key="parent" ref="698887838"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">371</int>
- <reference key="object" ref="972006081"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="439893737"/>
- </object>
- <reference key="parent" ref="0"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">372</int>
- <reference key="object" ref="439893737"/>
- <reference key="parent" ref="972006081"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">375</int>
- <reference key="object" ref="302598603"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="941447902"/>
- </object>
- <reference key="parent" ref="649796088"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">376</int>
- <reference key="object" ref="941447902"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="792887677"/>
- <reference ref="215659978"/>
- </object>
- <reference key="parent" ref="302598603"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">377</int>
- <reference key="object" ref="792887677"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="786677654"/>
- </object>
- <reference key="parent" ref="941447902"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">388</int>
- <reference key="object" ref="786677654"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="159677712"/>
- <reference ref="305399458"/>
- <reference ref="814362025"/>
- <reference ref="330926929"/>
- <reference ref="533507878"/>
- <reference ref="158063935"/>
- <reference ref="885547335"/>
- <reference ref="901062459"/>
- <reference ref="767671776"/>
- <reference ref="691570813"/>
- <reference ref="769124883"/>
- <reference ref="739652853"/>
- <reference ref="1012600125"/>
- <reference ref="214559597"/>
- <reference ref="596732606"/>
- <reference ref="393423671"/>
- </object>
- <reference key="parent" ref="792887677"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">389</int>
- <reference key="object" ref="159677712"/>
- <reference key="parent" ref="786677654"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">390</int>
- <reference key="object" ref="305399458"/>
- <reference key="parent" ref="786677654"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">391</int>
- <reference key="object" ref="814362025"/>
- <reference key="parent" ref="786677654"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">392</int>
- <reference key="object" ref="330926929"/>
- <reference key="parent" ref="786677654"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">393</int>
- <reference key="object" ref="533507878"/>
- <reference key="parent" ref="786677654"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">394</int>
- <reference key="object" ref="158063935"/>
- <reference key="parent" ref="786677654"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">395</int>
- <reference key="object" ref="885547335"/>
- <reference key="parent" ref="786677654"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">396</int>
- <reference key="object" ref="901062459"/>
- <reference key="parent" ref="786677654"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">397</int>
- <reference key="object" ref="767671776"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="175441468"/>
- </object>
- <reference key="parent" ref="786677654"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">398</int>
- <reference key="object" ref="691570813"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="1058217995"/>
- </object>
- <reference key="parent" ref="786677654"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">399</int>
- <reference key="object" ref="769124883"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="18263474"/>
- </object>
- <reference key="parent" ref="786677654"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">400</int>
- <reference key="object" ref="739652853"/>
- <reference key="parent" ref="786677654"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">401</int>
- <reference key="object" ref="1012600125"/>
- <reference key="parent" ref="786677654"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">402</int>
- <reference key="object" ref="214559597"/>
- <reference key="parent" ref="786677654"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">403</int>
- <reference key="object" ref="596732606"/>
- <reference key="parent" ref="786677654"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">404</int>
- <reference key="object" ref="393423671"/>
- <reference key="parent" ref="786677654"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">405</int>
- <reference key="object" ref="18263474"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="257962622"/>
- <reference ref="644725453"/>
- <reference ref="1037576581"/>
- <reference ref="941806246"/>
- <reference ref="1045724900"/>
- </object>
- <reference key="parent" ref="769124883"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">406</int>
- <reference key="object" ref="257962622"/>
- <reference key="parent" ref="18263474"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">407</int>
- <reference key="object" ref="644725453"/>
- <reference key="parent" ref="18263474"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">408</int>
- <reference key="object" ref="1037576581"/>
- <reference key="parent" ref="18263474"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">409</int>
- <reference key="object" ref="941806246"/>
- <reference key="parent" ref="18263474"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">410</int>
- <reference key="object" ref="1045724900"/>
- <reference key="parent" ref="18263474"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">411</int>
- <reference key="object" ref="1058217995"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="706297211"/>
- <reference ref="568384683"/>
- <reference ref="663508465"/>
- </object>
- <reference key="parent" ref="691570813"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">412</int>
- <reference key="object" ref="706297211"/>
- <reference key="parent" ref="1058217995"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">413</int>
- <reference key="object" ref="568384683"/>
- <reference key="parent" ref="1058217995"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">414</int>
- <reference key="object" ref="663508465"/>
- <reference key="parent" ref="1058217995"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">415</int>
- <reference key="object" ref="175441468"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="252969304"/>
- <reference ref="766922938"/>
- <reference ref="677519740"/>
- <reference ref="238351151"/>
- </object>
- <reference key="parent" ref="767671776"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">416</int>
- <reference key="object" ref="252969304"/>
- <reference key="parent" ref="175441468"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">417</int>
- <reference key="object" ref="766922938"/>
- <reference key="parent" ref="175441468"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">418</int>
- <reference key="object" ref="677519740"/>
- <reference key="parent" ref="175441468"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">419</int>
- <reference key="object" ref="238351151"/>
- <reference key="parent" ref="175441468"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">420</int>
- <reference key="object" ref="755631768"/>
- <reference key="parent" ref="0"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">450</int>
- <reference key="object" ref="288088188"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="579392910"/>
- </object>
- <reference key="parent" ref="789758025"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">451</int>
- <reference key="object" ref="579392910"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="1060694897"/>
- <reference ref="879586729"/>
- <reference ref="56570060"/>
- </object>
- <reference key="parent" ref="288088188"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">452</int>
- <reference key="object" ref="1060694897"/>
- <reference key="parent" ref="579392910"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">453</int>
- <reference key="object" ref="859480356"/>
- <reference key="parent" ref="769623530"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">454</int>
- <reference key="object" ref="795346622"/>
- <reference key="parent" ref="769623530"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">457</int>
- <reference key="object" ref="65139061"/>
- <reference key="parent" ref="698887838"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">459</int>
- <reference key="object" ref="19036812"/>
- <reference key="parent" ref="698887838"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">460</int>
- <reference key="object" ref="672708820"/>
- <reference key="parent" ref="698887838"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">462</int>
- <reference key="object" ref="537092702"/>
- <reference key="parent" ref="698887838"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">465</int>
- <reference key="object" ref="879586729"/>
- <reference key="parent" ref="579392910"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">466</int>
- <reference key="object" ref="56570060"/>
- <reference key="parent" ref="579392910"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">485</int>
- <reference key="object" ref="82994268"/>
- <reference key="parent" ref="789758025"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">490</int>
- <reference key="object" ref="448692316"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="992780483"/>
- </object>
- <reference key="parent" ref="649796088"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">491</int>
- <reference key="object" ref="992780483"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="105068016"/>
- </object>
- <reference key="parent" ref="448692316"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">492</int>
- <reference key="object" ref="105068016"/>
- <reference key="parent" ref="992780483"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">494</int>
- <reference key="object" ref="976324537"/>
- <reference key="parent" ref="0"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">496</int>
- <reference key="object" ref="215659978"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="446991534"/>
- </object>
- <reference key="parent" ref="941447902"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">497</int>
- <reference key="object" ref="446991534"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="875092757"/>
- <reference ref="630155264"/>
- <reference ref="945678886"/>
- <reference ref="512868991"/>
- <reference ref="163117631"/>
- <reference ref="31516759"/>
- <reference ref="908105787"/>
- <reference ref="644046920"/>
- <reference ref="231811626"/>
- <reference ref="883618387"/>
- </object>
- <reference key="parent" ref="215659978"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">498</int>
- <reference key="object" ref="875092757"/>
- <reference key="parent" ref="446991534"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">499</int>
- <reference key="object" ref="630155264"/>
- <reference key="parent" ref="446991534"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">500</int>
- <reference key="object" ref="945678886"/>
- <reference key="parent" ref="446991534"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">501</int>
- <reference key="object" ref="512868991"/>
- <reference key="parent" ref="446991534"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">502</int>
- <reference key="object" ref="163117631"/>
- <reference key="parent" ref="446991534"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">503</int>
- <reference key="object" ref="31516759"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="956096989"/>
- </object>
- <reference key="parent" ref="446991534"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">504</int>
- <reference key="object" ref="908105787"/>
- <reference key="parent" ref="446991534"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">505</int>
- <reference key="object" ref="644046920"/>
- <reference key="parent" ref="446991534"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">506</int>
- <reference key="object" ref="231811626"/>
- <reference key="parent" ref="446991534"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">507</int>
- <reference key="object" ref="883618387"/>
- <reference key="parent" ref="446991534"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">508</int>
- <reference key="object" ref="956096989"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="257099033"/>
- <reference ref="551969625"/>
- <reference ref="249532473"/>
- <reference ref="607364498"/>
- <reference ref="508151438"/>
- <reference ref="981751889"/>
- <reference ref="380031999"/>
- <reference ref="825984362"/>
- <reference ref="560145579"/>
- </object>
- <reference key="parent" ref="31516759"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">509</int>
- <reference key="object" ref="257099033"/>
- <reference key="parent" ref="956096989"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">510</int>
- <reference key="object" ref="551969625"/>
- <reference key="parent" ref="956096989"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">511</int>
- <reference key="object" ref="249532473"/>
- <reference key="parent" ref="956096989"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">512</int>
- <reference key="object" ref="607364498"/>
- <reference key="parent" ref="956096989"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">513</int>
- <reference key="object" ref="508151438"/>
- <reference key="parent" ref="956096989"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">514</int>
- <reference key="object" ref="981751889"/>
- <reference key="parent" ref="956096989"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">515</int>
- <reference key="object" ref="380031999"/>
- <reference key="parent" ref="956096989"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">516</int>
- <reference key="object" ref="825984362"/>
- <reference key="parent" ref="956096989"/>
- </object>
- <object class="IBObjectRecord">
- <int key="objectID">517</int>
- <reference key="object" ref="560145579"/>
- <reference key="parent" ref="956096989"/>
- </object>
- </object>
- </object>
- <object class="NSMutableDictionary" key="flattenedProperties">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSArray" key="dict.sortedKeys">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <string>-3.IBPluginDependency</string>
- <string>112.IBPluginDependency</string>
- <string>112.ImportedFromIB2</string>
- <string>124.IBPluginDependency</string>
- <string>124.ImportedFromIB2</string>
- <string>125.IBPluginDependency</string>
- <string>125.ImportedFromIB2</string>
- <string>125.editorWindowContentRectSynchronizationRect</string>
- <string>126.IBPluginDependency</string>
- <string>126.ImportedFromIB2</string>
- <string>129.IBPluginDependency</string>
- <string>129.ImportedFromIB2</string>
- <string>130.IBPluginDependency</string>
- <string>130.ImportedFromIB2</string>
- <string>130.editorWindowContentRectSynchronizationRect</string>
- <string>131.IBPluginDependency</string>
- <string>131.ImportedFromIB2</string>
- <string>134.IBPluginDependency</string>
- <string>134.ImportedFromIB2</string>
- <string>136.IBPluginDependency</string>
- <string>136.ImportedFromIB2</string>
- <string>143.IBPluginDependency</string>
- <string>143.ImportedFromIB2</string>
- <string>144.IBPluginDependency</string>
- <string>144.ImportedFromIB2</string>
- <string>145.IBPluginDependency</string>
- <string>145.ImportedFromIB2</string>
- <string>149.IBPluginDependency</string>
- <string>149.ImportedFromIB2</string>
- <string>150.IBPluginDependency</string>
- <string>150.ImportedFromIB2</string>
- <string>19.IBPluginDependency</string>
- <string>19.ImportedFromIB2</string>
- <string>195.IBPluginDependency</string>
- <string>195.ImportedFromIB2</string>
- <string>196.IBPluginDependency</string>
- <string>196.ImportedFromIB2</string>
- <string>197.IBPluginDependency</string>
- <string>197.ImportedFromIB2</string>
- <string>198.IBPluginDependency</string>
- <string>198.ImportedFromIB2</string>
- <string>199.IBPluginDependency</string>
- <string>199.ImportedFromIB2</string>
- <string>200.IBEditorWindowLastContentRect</string>
- <string>200.IBPluginDependency</string>
- <string>200.ImportedFromIB2</string>
- <string>200.editorWindowContentRectSynchronizationRect</string>
- <string>201.IBPluginDependency</string>
- <string>201.ImportedFromIB2</string>
- <string>202.IBPluginDependency</string>
- <string>202.ImportedFromIB2</string>
- <string>203.IBPluginDependency</string>
- <string>203.ImportedFromIB2</string>
- <string>204.IBPluginDependency</string>
- <string>204.ImportedFromIB2</string>
- <string>205.IBEditorWindowLastContentRect</string>
- <string>205.IBPluginDependency</string>
- <string>205.ImportedFromIB2</string>
- <string>205.editorWindowContentRectSynchronizationRect</string>
- <string>206.IBPluginDependency</string>
- <string>206.ImportedFromIB2</string>
- <string>207.IBPluginDependency</string>
- <string>207.ImportedFromIB2</string>
- <string>208.IBPluginDependency</string>
- <string>208.ImportedFromIB2</string>
- <string>209.IBPluginDependency</string>
- <string>209.ImportedFromIB2</string>
- <string>210.IBPluginDependency</string>
- <string>210.ImportedFromIB2</string>
- <string>211.IBPluginDependency</string>
- <string>211.ImportedFromIB2</string>
- <string>212.IBPluginDependency</string>
- <string>212.ImportedFromIB2</string>
- <string>212.editorWindowContentRectSynchronizationRect</string>
- <string>213.IBPluginDependency</string>
- <string>213.ImportedFromIB2</string>
- <string>214.IBPluginDependency</string>
- <string>214.ImportedFromIB2</string>
- <string>215.IBPluginDependency</string>
- <string>215.ImportedFromIB2</string>
- <string>216.IBPluginDependency</string>
- <string>216.ImportedFromIB2</string>
- <string>217.IBPluginDependency</string>
- <string>217.ImportedFromIB2</string>
- <string>218.IBPluginDependency</string>
- <string>218.ImportedFromIB2</string>
- <string>219.IBPluginDependency</string>
- <string>219.ImportedFromIB2</string>
- <string>220.IBEditorWindowLastContentRect</string>
- <string>220.IBPluginDependency</string>
- <string>220.ImportedFromIB2</string>
- <string>220.editorWindowContentRectSynchronizationRect</string>
- <string>221.IBPluginDependency</string>
- <string>221.ImportedFromIB2</string>
- <string>23.IBPluginDependency</string>
- <string>23.ImportedFromIB2</string>
- <string>236.IBPluginDependency</string>
- <string>236.ImportedFromIB2</string>
- <string>239.IBPluginDependency</string>
- <string>239.ImportedFromIB2</string>
- <string>24.IBEditorWindowLastContentRect</string>
- <string>24.IBPluginDependency</string>
- <string>24.ImportedFromIB2</string>
- <string>24.editorWindowContentRectSynchronizationRect</string>
- <string>29.IBEditorWindowLastContentRect</string>
- <string>29.IBPluginDependency</string>
- <string>29.ImportedFromIB2</string>
- <string>29.WindowOrigin</string>
- <string>29.editorWindowContentRectSynchronizationRect</string>
- <string>295.IBPluginDependency</string>
- <string>296.IBEditorWindowLastContentRect</string>
- <string>296.IBPluginDependency</string>
- <string>296.editorWindowContentRectSynchronizationRect</string>
- <string>297.IBPluginDependency</string>
- <string>298.IBPluginDependency</string>
- <string>346.IBPluginDependency</string>
- <string>346.ImportedFromIB2</string>
- <string>348.IBPluginDependency</string>
- <string>348.ImportedFromIB2</string>
- <string>349.IBEditorWindowLastContentRect</string>
- <string>349.IBPluginDependency</string>
- <string>349.ImportedFromIB2</string>
- <string>349.editorWindowContentRectSynchronizationRect</string>
- <string>350.IBPluginDependency</string>
- <string>350.ImportedFromIB2</string>
- <string>351.IBPluginDependency</string>
- <string>351.ImportedFromIB2</string>
- <string>354.IBPluginDependency</string>
- <string>354.ImportedFromIB2</string>
- <string>371.IBEditorWindowLastContentRect</string>
- <string>371.IBPluginDependency</string>
- <string>371.IBWindowTemplateEditedContentRect</string>
- <string>371.NSWindowTemplate.visibleAtLaunch</string>
- <string>371.editorWindowContentRectSynchronizationRect</string>
- <string>371.windowTemplate.maxSize</string>
- <string>372.IBPluginDependency</string>
- <string>375.IBPluginDependency</string>
- <string>376.IBEditorWindowLastContentRect</string>
- <string>376.IBPluginDependency</string>
- <string>377.IBPluginDependency</string>
- <string>388.IBEditorWindowLastContentRect</string>
- <string>388.IBPluginDependency</string>
- <string>389.IBPluginDependency</string>
- <string>390.IBPluginDependency</string>
- <string>391.IBPluginDependency</string>
- <string>392.IBPluginDependency</string>
- <string>393.IBPluginDependency</string>
- <string>394.IBPluginDependency</string>
- <string>395.IBPluginDependency</string>
- <string>396.IBPluginDependency</string>
- <string>397.IBPluginDependency</string>
- <string>398.IBPluginDependency</string>
- <string>399.IBPluginDependency</string>
- <string>400.IBPluginDependency</string>
- <string>401.IBPluginDependency</string>
- <string>402.IBPluginDependency</string>
- <string>403.IBPluginDependency</string>
- <string>404.IBPluginDependency</string>
- <string>405.IBPluginDependency</string>
- <string>406.IBPluginDependency</string>
- <string>407.IBPluginDependency</string>
- <string>408.IBPluginDependency</string>
- <string>409.IBPluginDependency</string>
- <string>410.IBPluginDependency</string>
- <string>411.IBPluginDependency</string>
- <string>412.IBPluginDependency</string>
- <string>413.IBPluginDependency</string>
- <string>414.IBPluginDependency</string>
- <string>415.IBPluginDependency</string>
- <string>416.IBPluginDependency</string>
- <string>417.IBPluginDependency</string>
- <string>418.IBPluginDependency</string>
- <string>419.IBPluginDependency</string>
- <string>450.IBPluginDependency</string>
- <string>451.IBEditorWindowLastContentRect</string>
- <string>451.IBPluginDependency</string>
- <string>452.IBPluginDependency</string>
- <string>453.IBPluginDependency</string>
- <string>454.IBPluginDependency</string>
- <string>457.IBPluginDependency</string>
- <string>459.IBPluginDependency</string>
- <string>460.IBPluginDependency</string>
- <string>462.IBPluginDependency</string>
- <string>465.IBPluginDependency</string>
- <string>466.IBPluginDependency</string>
- <string>485.IBPluginDependency</string>
- <string>490.IBPluginDependency</string>
- <string>491.IBEditorWindowLastContentRect</string>
- <string>491.IBPluginDependency</string>
- <string>492.IBPluginDependency</string>
- <string>496.IBPluginDependency</string>
- <string>497.IBEditorWindowLastContentRect</string>
- <string>497.IBPluginDependency</string>
- <string>498.IBPluginDependency</string>
- <string>499.IBPluginDependency</string>
- <string>5.IBPluginDependency</string>
- <string>5.ImportedFromIB2</string>
- <string>500.IBPluginDependency</string>
- <string>501.IBPluginDependency</string>
- <string>502.IBPluginDependency</string>
- <string>503.IBPluginDependency</string>
- <string>504.IBPluginDependency</string>
- <string>505.IBPluginDependency</string>
- <string>506.IBPluginDependency</string>
- <string>507.IBPluginDependency</string>
- <string>508.IBEditorWindowLastContentRect</string>
- <string>508.IBPluginDependency</string>
- <string>509.IBPluginDependency</string>
- <string>510.IBPluginDependency</string>
- <string>511.IBPluginDependency</string>
- <string>512.IBPluginDependency</string>
- <string>513.IBPluginDependency</string>
- <string>514.IBPluginDependency</string>
- <string>515.IBPluginDependency</string>
- <string>516.IBPluginDependency</string>
- <string>517.IBPluginDependency</string>
- <string>56.IBPluginDependency</string>
- <string>56.ImportedFromIB2</string>
- <string>57.IBEditorWindowLastContentRect</string>
- <string>57.IBPluginDependency</string>
- <string>57.ImportedFromIB2</string>
- <string>57.editorWindowContentRectSynchronizationRect</string>
- <string>58.IBPluginDependency</string>
- <string>58.ImportedFromIB2</string>
- <string>72.IBPluginDependency</string>
- <string>72.ImportedFromIB2</string>
- <string>73.IBPluginDependency</string>
- <string>73.ImportedFromIB2</string>
- <string>74.IBPluginDependency</string>
- <string>74.ImportedFromIB2</string>
- <string>75.IBPluginDependency</string>
- <string>75.ImportedFromIB2</string>
- <string>77.IBPluginDependency</string>
- <string>77.ImportedFromIB2</string>
- <string>78.IBPluginDependency</string>
- <string>78.ImportedFromIB2</string>
- <string>79.IBPluginDependency</string>
- <string>79.ImportedFromIB2</string>
- <string>80.IBPluginDependency</string>
- <string>80.ImportedFromIB2</string>
- <string>81.IBEditorWindowLastContentRect</string>
- <string>81.IBPluginDependency</string>
- <string>81.ImportedFromIB2</string>
- <string>81.editorWindowContentRectSynchronizationRect</string>
- <string>82.IBPluginDependency</string>
- <string>82.ImportedFromIB2</string>
- <string>83.IBPluginDependency</string>
- <string>83.ImportedFromIB2</string>
- <string>92.IBPluginDependency</string>
- <string>92.ImportedFromIB2</string>
- </object>
- <object class="NSMutableArray" key="dict.values">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>{{522, 812}, {146, 23}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>{{436, 809}, {64, 6}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>{{753, 187}, {275, 113}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>{{608, 612}, {275, 83}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>{{547, 180}, {254, 283}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>{{187, 434}, {243, 243}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>{{608, 612}, {167, 43}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>{{753, 217}, {238, 103}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>{{608, 612}, {241, 103}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>{{654, 239}, {194, 73}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>{{525, 802}, {197, 73}}</string>
- <string>{{380, 836}, {512, 20}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>{74, 862}</string>
- <string>{{6, 978}, {478, 20}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>{{604, 269}, {231, 43}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>{{475, 832}, {234, 43}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>{{746, 287}, {220, 133}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>{{608, 612}, {215, 63}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>{{380, 496}, {480, 360}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>{{380, 496}, {480, 360}}</string>
- <integer value="1"/>
- <string>{{33, 99}, {480, 360}}</string>
- <string>{3.40282e+38, 3.40282e+38}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>{{591, 420}, {83, 43}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>{{523, 2}, {178, 283}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>{{753, 197}, {170, 63}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>{{725, 289}, {246, 23}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>{{674, 260}, {204, 183}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>{{878, 180}, {164, 173}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>{{286, 129}, {275, 183}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>{{23, 794}, {245, 183}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>{{452, 109}, {196, 203}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>{{145, 474}, {199, 203}}</string>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <integer value="1"/>
- </object>
- </object>
- <object class="NSMutableDictionary" key="unlocalizedProperties">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference key="dict.sortedKeys" ref="0"/>
- <object class="NSMutableArray" key="dict.values">
- <bool key="EncodedWithXMLCoder">YES</bool>
- </object>
- </object>
- <nil key="activeLocalization"/>
- <object class="NSMutableDictionary" key="localizations">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference key="dict.sortedKeys" ref="0"/>
- <object class="NSMutableArray" key="dict.values">
- <bool key="EncodedWithXMLCoder">YES</bool>
- </object>
- </object>
- <nil key="sourceID"/>
- <int key="maxID">532</int>
- </object>
- <object class="IBClassDescriber" key="IBDocument.Classes">
- <object class="NSMutableArray" key="referencedPartialClassDescriptions">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="IBPartialClassDescription">
- <string key="className">edgeAppDelegate</string>
- <string key="superclassName">NSObject</string>
- <object class="NSMutableDictionary" key="outlets">
- <string key="NS.key.0">window</string>
- <string key="NS.object.0">NSWindow</string>
- </object>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBProjectSource</string>
- <string key="minorKey">edgeAppDelegate.h</string>
- </object>
- </object>
- </object>
- <object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="IBPartialClassDescription">
- <string key="className">NSApplication</string>
- <string key="superclassName">NSResponder</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier" id="822405504">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSApplication.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSApplication</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier" id="850738725">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSApplicationScripting.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSApplication</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier" id="624831158">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSColorPanel.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSApplication</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSHelpManager.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSApplication</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSPageLayout.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSApplication</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSUserInterfaceItemSearching.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSBrowser</string>
- <string key="superclassName">NSControl</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSBrowser.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSControl</string>
- <string key="superclassName">NSView</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier" id="310914472">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSControl.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSDocument</string>
- <string key="superclassName">NSObject</string>
- <object class="NSMutableDictionary" key="actions">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSArray" key="dict.sortedKeys">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <string>printDocument:</string>
- <string>revertDocumentToSaved:</string>
- <string>runPageLayout:</string>
- <string>saveDocument:</string>
- <string>saveDocumentAs:</string>
- <string>saveDocumentTo:</string>
- </object>
- <object class="NSMutableArray" key="dict.values">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <string>id</string>
- <string>id</string>
- <string>id</string>
- <string>id</string>
- <string>id</string>
- <string>id</string>
- </object>
- </object>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSDocument.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSDocument</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSDocumentScripting.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSDocumentController</string>
- <string key="superclassName">NSObject</string>
- <object class="NSMutableDictionary" key="actions">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <object class="NSArray" key="dict.sortedKeys">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <string>clearRecentDocuments:</string>
- <string>newDocument:</string>
- <string>openDocument:</string>
- <string>saveAllDocuments:</string>
- </object>
- <object class="NSMutableArray" key="dict.values">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <string>id</string>
- <string>id</string>
- <string>id</string>
- <string>id</string>
- </object>
- </object>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSDocumentController.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSFontManager</string>
- <string key="superclassName">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier" id="946436764">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSFontManager.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSFormatter</string>
- <string key="superclassName">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">Foundation.framework/Headers/NSFormatter.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSMatrix</string>
- <string key="superclassName">NSControl</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSMatrix.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSMenu</string>
- <string key="superclassName">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier" id="1056362899">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSMenu.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSMenuItem</string>
- <string key="superclassName">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier" id="472958451">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSMenuItem.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSMovieView</string>
- <string key="superclassName">NSView</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSMovieView.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSAccessibility.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <reference key="sourceIdentifier" ref="822405504"/>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <reference key="sourceIdentifier" ref="850738725"/>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <reference key="sourceIdentifier" ref="624831158"/>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <reference key="sourceIdentifier" ref="310914472"/>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSDictionaryController.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSDragging.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <reference key="sourceIdentifier" ref="946436764"/>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSFontPanel.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSKeyValueBinding.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <reference key="sourceIdentifier" ref="1056362899"/>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSNibLoading.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSOutlineView.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSPasteboard.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSSavePanel.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier" id="809545482">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSTableView.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSToolbarItem.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier" id="260078765">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSView.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">Foundation.framework/Headers/NSArchiver.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">Foundation.framework/Headers/NSClassDescription.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">Foundation.framework/Headers/NSError.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">Foundation.framework/Headers/NSFileManager.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">Foundation.framework/Headers/NSKeyValueCoding.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">Foundation.framework/Headers/NSKeyValueObserving.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">Foundation.framework/Headers/NSKeyedArchiver.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">Foundation.framework/Headers/NSObject.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">Foundation.framework/Headers/NSObjectScripting.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">Foundation.framework/Headers/NSPortCoder.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">Foundation.framework/Headers/NSRunLoop.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">Foundation.framework/Headers/NSScriptClassDescription.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">Foundation.framework/Headers/NSScriptKeyValueCoding.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">Foundation.framework/Headers/NSScriptObjectSpecifiers.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">Foundation.framework/Headers/NSScriptWhoseTests.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">Foundation.framework/Headers/NSThread.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">Foundation.framework/Headers/NSURL.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">Foundation.framework/Headers/NSURLConnection.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">Foundation.framework/Headers/NSURLDownload.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSResponder</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSInterfaceStyle.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSResponder</string>
- <string key="superclassName">NSObject</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSResponder.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSTableView</string>
- <string key="superclassName">NSControl</string>
- <reference key="sourceIdentifier" ref="809545482"/>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSText</string>
- <string key="superclassName">NSView</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSText.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSTextView</string>
- <string key="superclassName">NSText</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSTextView.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSView</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSClipView.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSView</string>
- <reference key="sourceIdentifier" ref="472958451"/>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSView</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSRulerView.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSView</string>
- <string key="superclassName">NSResponder</string>
- <reference key="sourceIdentifier" ref="260078765"/>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSWindow</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSDrawer.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSWindow</string>
- <string key="superclassName">NSResponder</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSWindow.h</string>
- </object>
- </object>
- <object class="IBPartialClassDescription">
- <string key="className">NSWindow</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBFrameworkSource</string>
- <string key="minorKey">AppKit.framework/Headers/NSWindowScripting.h</string>
- </object>
- </object>
- </object>
- </object>
- <int key="IBDocument.localizationMode">0</int>
- <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults">
- <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.macosx</string>
- <integer value="1060" key="NS.object.0"/>
- </object>
- <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
- <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3</string>
- <integer value="3000" key="NS.object.0"/>
- </object>
- <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
- <string key="IBDocument.LastKnownRelativeProjectPath">../edge.xcodeproj</string>
- <int key="IBDocument.defaultPropertyAccessControl">3</int>
- </data>
-</archive>
diff --git a/experimental/Intersection/Extrema.cpp b/experimental/Intersection/Extrema.cpp
deleted file mode 100644
index 7a41ddf77d..0000000000
--- a/experimental/Intersection/Extrema.cpp
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "DataTypes.h"
-#include "Extrema.h"
-
-static int validUnitDivide(double numer, double denom, double* ratio)
-{
- if (numer < 0) {
- numer = -numer;
- denom = -denom;
- }
- if (denom == 0 || numer == 0 || numer >= denom)
- return 0;
- double r = numer / denom;
- if (r == 0) { // catch underflow if numer <<<< denom
- return 0;
- }
- *ratio = r;
- return 1;
-}
-
-/** From Numerical Recipes in C.
-
- Q = -1/2 (B + sign(B) sqrt[B*B - 4*A*C])
- x1 = Q / A
- x2 = C / Q
-*/
-static int findUnitQuadRoots(double A, double B, double C, double roots[2])
-{
- if (A == 0)
- return validUnitDivide(-C, B, roots);
-
- double* r = roots;
-
- double R = B*B - 4*A*C;
- if (R < 0) { // complex roots
- return 0;
- }
- R = sqrt(R);
-
- double Q = (B < 0) ? -(B-R)/2 : -(B+R)/2;
- r += validUnitDivide(Q, A, r);
- r += validUnitDivide(C, Q, r);
- if (r - roots == 2 && AlmostEqualUlps(roots[0], roots[1])) { // nearly-equal?
- r -= 1; // skip the double root
- }
- return (int)(r - roots);
-}
-
-/** Cubic'(t) = At^2 + Bt + C, where
- A = 3(-a + 3(b - c) + d)
- B = 6(a - 2b + c)
- C = 3(b - a)
- Solve for t, keeping only those that fit between 0 < t < 1
-*/
-int findExtrema(double a, double b, double c, double d, double tValues[2])
-{
- // we divide A,B,C by 3 to simplify
- double A = d - a + 3*(b - c);
- double B = 2*(a - b - b + c);
- double C = b - a;
-
- return findUnitQuadRoots(A, B, C, tValues);
-}
-
-/** Quad'(t) = At + B, where
- A = 2(a - 2b + c)
- B = 2(b - a)
- Solve for t, only if it fits between 0 < t < 1
-*/
-int findExtrema(double a, double b, double c, double tValue[1])
-{
- /* At + B == 0
- t = -B / A
- */
- return validUnitDivide(a - b, a - b - b + c, tValue);
-}
diff --git a/experimental/Intersection/Extrema.h b/experimental/Intersection/Extrema.h
deleted file mode 100644
index 94113acb63..0000000000
--- a/experimental/Intersection/Extrema.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-int findExtrema(double a, double b, double c, double d, double tValues[2]);
-int findExtrema(double a, double b, double c, double tValue[1]);
diff --git a/experimental/Intersection/Inline_Tests.cpp b/experimental/Intersection/Inline_Tests.cpp
deleted file mode 100644
index 90f5e7ab02..0000000000
--- a/experimental/Intersection/Inline_Tests.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "CurveIntersection.h"
-#include "Intersection_Tests.h"
-#include "IntersectionUtilities.h"
-
-static void assert_that(int x, int y, const char* s) {
- if (x == y) {
- return;
- }
- SkDebugf("result=%d expected=%d %s\n", x, y, s);
-}
-
-static void side_test() {
- assert_that(side(-1), 0, "side(-1) != 0");
- assert_that(side(0), 1, "side(0) != 1");
- assert_that(side(1), 2, "side(1) != 2");
-}
-
-static void sideBit_test() {
- assert_that(sideBit(-1), 1, "sideBit(-1) != 1");
- assert_that(sideBit(0), 2, "sideBit(0) != 2");
- assert_that(sideBit(1), 4, "sideBit(1) != 4");
-}
-
-static void other_two_test() {
- for (int x = 0; x < 4; ++x) {
- for (int y = 0; y < 4; ++y) {
- if (x == y) {
- continue;
- }
- int mask = other_two(x, y);
- int all = 1 << x;
- all |= 1 << y;
- all |= 1 << (x ^ mask);
- all |= 1 << (y ^ mask);
- if (all == 0x0F) {
- continue;
- }
- SkDebugf("[%d,%d] other_two failed mask=%d [%d,%d]\n",
- x, y, mask, x ^ mask, y ^ mask);
- }
- }
-}
-
-void Inline_Tests() {
- side_test();
- sideBit_test();
- other_two_test();
-}
diff --git a/experimental/Intersection/IntersectionUtilities.cpp b/experimental/Intersection/IntersectionUtilities.cpp
deleted file mode 100644
index e6c4abc590..0000000000
--- a/experimental/Intersection/IntersectionUtilities.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#if 0
-// snippets that one day may be useful, unused for now...
-
-// get sign, exponent, mantissa from double
-// Translate the double into sign, exponent and mantissa.
- long bits = BitConverter.DoubleToInt64Bits(d);
- // Note that the shift is sign-extended, hence the test against -1 not 1
- bool negative = (bits < 0);
- int exponent = (int) ((bits >> 52) & 0x7ffL);
- long mantissa = bits & 0xfffffffffffffL;
-
- // Subnormal numbers; exponent is effectively one higher,
- // but there's no extra normalisation bit in the mantissa
- if (exponent==0)
- {
- exponent++;
- }
- // Normal numbers; leave exponent as it is but add extra
- // bit to the front of the mantissa
- else
- {
- mantissa = mantissa | (1L<<52);
- }
-
- // Bias the exponent. It's actually biased by 1023, but we're
- // treating the mantissa as m.0 rather than 0.m, so we need
- // to subtract another 52 from it.
- exponent -= 1075;
-
- if (mantissa == 0)
- {
- return "0";
- }
-
- /* Normalize */
- while((mantissa & 1) == 0)
- { /* i.e., Mantissa is even */
- mantissa >>= 1;
- exponent++;
- }
-#endif
diff --git a/experimental/Intersection/IntersectionUtilities.h b/experimental/Intersection/IntersectionUtilities.h
deleted file mode 100644
index b7e69fb65c..0000000000
--- a/experimental/Intersection/IntersectionUtilities.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-// inline utilities
-/* Returns 0 if negative, 1 if zero, 2 if positive
-*/
-inline int side(double x) {
- return (x > 0) + (x >= 0);
-}
-
-/* Returns 1 if negative, 2 if zero, 4 if positive
-*/
-inline int sideBit(double x) {
- return 1 << side(x);
-}
-
-/* Given the set [0, 1, 2, 3], and two of the four members, compute an XOR mask
- that computes the other two. Note that:
-
- one ^ two == 3 for (0, 3), (1, 2)
- one ^ two < 3 for (0, 1), (0, 2), (1, 3), (2, 3)
- 3 - (one ^ two) is either 0, 1, or 2
- 1 >> 3 - (one ^ two) is either 0 or 1
-thus:
- returned == 2 for (0, 3), (1, 2)
- returned == 3 for (0, 1), (0, 2), (1, 3), (2, 3)
-given that:
- (0, 3) ^ 2 -> (2, 1) (1, 2) ^ 2 -> (3, 0)
- (0, 1) ^ 3 -> (3, 2) (0, 2) ^ 3 -> (3, 1) (1, 3) ^ 3 -> (2, 0) (2, 3) ^ 3 -> (1, 0)
-*/
-inline int other_two(int one, int two) {
- return 1 >> 3 - (one ^ two) ^ 3;
-}
-
-/* Returns -1 if negative, 0 if zero, 1 if positive
-*/
-inline int sign(double x) {
- return (x > 0) - (x < 0);
-}
-
-inline double interp(double A, double B, double t) {
- return A + (B - A) * t;
-}
diff --git a/experimental/Intersection/Intersection_Tests.cpp b/experimental/Intersection/Intersection_Tests.cpp
deleted file mode 100644
index 0754ecc27f..0000000000
--- a/experimental/Intersection/Intersection_Tests.cpp
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "CubicIntersection_TestData.h"
-#include "Intersection_Tests.h"
-
-void cubecode_test(int test);
-void parseSVG();
-
-#define TEST_QUADS_FIRST 0
-
-void Intersection_Tests() {
- int testsRun = 0;
-#if 0
- CubicIntersection_OneOffTest();
- CubicIntersection_SelfTest();
- QuadraticIntersection_IntersectionFinder();
- QuadraticIntersection_OneOffTest();
- CubicIntersection_IntersectionFinder();
- CubicUtilities_Test();
-#endif
- SimplifyNew_Test();
- CubicsToQuadratics_OneOffTest();
- CubicIntersection_OneOffTest();
-// CubicIntersection_OneOffTests();
- #if 0
- parseSVG();
- #endif
-// QuadraticIntersection_PointFinder();
- ShapeOps4x4CubicsThreaded_Test(testsRun);
- CubicToQuadratics_Test();
- QuadraticIntersection_Test();
- QuarticRoot_Test();
- CubicIntersection_RandTest();
- CubicsToQuadratics_RandTest();
- Simplify4x4RectsThreaded_Test(testsRun);
- Simplify4x4QuadraticsThreaded_Test(testsRun);
- QuadLineIntersectThreaded_Test(testsRun);
- SimplifyNondegenerate4x4TrianglesThreaded_Test(testsRun);
- SimplifyDegenerate4x4TrianglesThreaded_Test(testsRun);
- Simplify4x4QuadralateralsThreaded_Test(testsRun);
- ShapeOps4x4RectsThreaded_Test(testsRun);
- SkDebugf("%s total testsRun=%d\n", __FUNCTION__, testsRun);
- LineQuadraticIntersection_Test();
- MiniSimplify_Test();
- SimplifyAngle_Test();
- QuadraticBezierClip_Test();
- SimplifyFindNext_Test();
- SimplifyFindTop_Test();
- QuadraticReduceOrder_Test();
- SimplifyAddIntersectingTs_Test();
-
- cubecode_test(1);
- convert_testx();
- // tests are in dependency / complexity order
- Inline_Tests();
- ConvexHull_Test();
- ConvexHull_X_Test();
-
- LineParameter_Test();
- LineIntersection_Test();
- LineCubicIntersection_Test();
-
- SimplifyQuadraticPaths_Test();
-
- SimplifyPolygonPaths_Test();
- SimplifyRectangularPaths_Test();
- SimplifyQuadralateralPaths_Test();
-
- // ActiveEdge_Test();
-
- QuadraticCoincidence_Test();
- QuadraticIntersection_Test();
-
- CubicParameterization_Test();
- CubicCoincidence_Test();
- CubicReduceOrder_Test();
- CubicBezierClip_Test();
- CubicIntersection_Test();
-
-}
diff --git a/experimental/Intersection/Intersection_Tests.h b/experimental/Intersection/Intersection_Tests.h
deleted file mode 100644
index 78f793890f..0000000000
--- a/experimental/Intersection/Intersection_Tests.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "DataTypes_Test.h"
-
-void ActiveEdge_Test();
-void ConvexHull_Test();
-void ConvexHull_X_Test();
-void CubicBezierClip_Test();
-void CubicCoincidence_Test();
-void CubicIntersection_IntersectionFinder();
-void CubicIntersection_NewOneOffTest();
-void CubicIntersection_OneOffTest();
-void CubicIntersection_OneOffTests();
-void CubicIntersection_SelfTest();
-void CubicIntersection_Test();
-void CubicIntersection_RandTest();
-void CubicIntersection_RandTestOld();
-void CubicParameterization_Test();
-void CubicReduceOrder_Test();
-void CubicsToQuadratics_OneOffTest();
-void CubicsToQuadratics_OneOffTests();
-void CubicsToQuadratics_RandTest();
-void CubicToQuadratics_Test();
-void CubicUtilities_Test();
-void Inline_Tests();
-void Intersection_Tests();
-void LineCubicIntersection_Test();
-void LineIntersection_Test();
-void LineParameter_Test();
-void LineQuadraticIntersection_Test();
-void MiniSimplify_Test();
-void QuadraticIntersection_IntersectionFinder();
-void QuadraticIntersection_OneOffTest();
-void QuadraticIntersection_PointFinder();
-void QuadLineIntersectThreaded_Test(int& );
-void QuadraticBezierClip_Test();
-void QuadraticCoincidence_Test();
-void QuadraticIntersection_Test();
-void QuadraticParameterization_Test();
-void QuadraticReduceOrder_Test();
-void QuarticRoot_Test();
-void SimplifyAddIntersectingTs_Test();
-void SimplifyAngle_Test();
-void SimplifyDegenerate4x4TrianglesThreaded_Test(int& );
-void SimplifyFindNext_Test();
-void SimplifyFindTop_Test();
-void SimplifyNew_Test();
-void SimplifyNondegenerate4x4TrianglesThreaded_Test(int& );
-void SimplifyPolygonPaths_Test();
-void SimplifyQuadralateralPaths_Test();
-void SimplifyQuadraticPaths_Test();
-void Simplify4x4QuadralateralsThreaded_Test(int& );
-void Simplify4x4QuadraticsThreaded_Test(int& );
-void Simplify4x4RectsThreaded_Test(int& );
-void SimplifyRectangularPaths_Test();
-void ShapeOps4x4CubicsThreaded_Test(int& );
-void ShapeOps4x4RectsThreaded_Test(int& );
diff --git a/experimental/Intersection/Intersections.cpp b/experimental/Intersection/Intersections.cpp
deleted file mode 100644
index 1877bd40e2..0000000000
--- a/experimental/Intersection/Intersections.cpp
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "DataTypes.h"
-#include "Intersections.h"
-
-void Intersections::insertCoincidentPair(double s1, double e1, double s2, double e2,
- const _Point& startPt, const _Point& endPt) {
- if (fSwap) {
- remove(s2, e2, startPt, endPt);
- } else {
- remove(s1, e1, startPt, endPt);
- }
- SkASSERT(coincidentUsed() == fUsed);
- SkASSERT((coincidentUsed() & 1) != 1);
- int i1 = 0;
- int i2 = 0;
- do {
- while (i1 < fUsed && !(fIsCoincident[fSwap] & (1 << i1))) {
- ++i1;
- }
- if (i1 == fUsed) {
- break;
- }
- SkASSERT(i1 < fUsed);
- int iEnd1 = i1 + 1;
- while (!(fIsCoincident[fSwap] & (1 << iEnd1))) {
- ++iEnd1;
- }
- SkASSERT(iEnd1 < fUsed);
- double cs1 = fT[fSwap][i1];
- double ce1 = fT[fSwap][iEnd1];
- bool s1in = between(cs1, s1, ce1) || startPt.approximatelyEqual(fPt[i1])
- || startPt.approximatelyEqual(fPt[iEnd1]);
- bool e1in = between(cs1, e1, ce1) || endPt.approximatelyEqual(fPt[i1])
- || endPt.approximatelyEqual(fPt[iEnd1]);
- while (i2 < fUsed && !(fIsCoincident[fSwap ^ 1] & (1 << i2))) {
- ++i2;
- }
- int iEnd2 = i2 + 1;
- while (!(fIsCoincident[fSwap ^ 1] & (1 << iEnd2))) {
- ++iEnd2;
- }
- SkASSERT(iEnd2 < fUsed);
- double cs2 = fT[fSwap ^ 1][i2];
- double ce2 = fT[fSwap ^ 1][iEnd2];
- bool s2in = between(cs2, s2, ce2) || startPt.approximatelyEqual(fPt[i2])
- || startPt.approximatelyEqual(fPt[iEnd2]);
- bool e2in = between(cs2, e2, ce2) || endPt.approximatelyEqual(fPt[i2])
- || endPt.approximatelyEqual(fPt[iEnd2]);
- if ((s1in | e1in) & (s2in | e2in)) {
- if (s1 < cs1) {
- fT[fSwap][i1] = s1;
- fPt[i1] = startPt;
- } else if (e1 < cs1) {
- fT[fSwap][i1] = e1;
- fPt[i1] = endPt;
- }
- if (s1 > ce1) {
- fT[fSwap][iEnd1] = s1;
- fPt[iEnd1] = startPt;
- } else if (e1 > ce1) {
- fT[fSwap][iEnd1] = e1;
- fPt[iEnd1] = endPt;
- }
- if (s2 > e2) {
- SkTSwap(cs2, ce2);
- SkTSwap(i2, iEnd2);
- }
- if (s2 < cs2) {
- fT[fSwap ^ 1][i2] = s2;
- } else if (e2 < cs2) {
- fT[fSwap ^ 1][i2] = e2;
- }
- if (s2 > ce2) {
- fT[fSwap ^ 1][iEnd2] = s2;
- } else if (e2 > ce2) {
- fT[fSwap ^ 1][iEnd2] = e2;
- }
- return;
- }
- } while (true);
- SkASSERT(fUsed < 9);
- insertCoincident(s1, s2, startPt);
- insertCoincident(e1, e2, endPt);
-}
-
-int Intersections::insert(double one, double two, const _Point& pt) {
- SkASSERT(fUsed <= 1 || fT[0][0] <= fT[0][1]);
- int index;
- for (index = 0; index < fUsed; ++index) {
- double oldOne = fT[0][index];
- double oldTwo = fT[1][index];
- if (roughly_equal(oldOne, one) && roughly_equal(oldTwo, two)) {
- if ((precisely_zero(one) && !precisely_zero(oldOne))
- || (precisely_equal(one, 1) && !precisely_equal(oldOne, 1))
- || (precisely_zero(two) && !precisely_zero(oldTwo))
- || (precisely_equal(two, 1) && !precisely_equal(oldTwo, 1))) {
- fT[0][index] = one;
- fT[1][index] = two;
- fPt[index] = pt;
- }
- return -1;
- }
- #if ONE_OFF_DEBUG
- if (pt.roughlyEqual(fPt[index])) {
- SkDebugf("%s t=%1.9g pts roughly equal\n", __FUNCTION__, one);
- }
- #endif
- if (fT[0][index] > one) {
- break;
- }
- }
- SkASSERT(fUsed < 9);
- int remaining = fUsed - index;
- if (remaining > 0) {
- memmove(&fPt[index + 1], &fPt[index], sizeof(fPt[0]) * remaining);
- memmove(&fT[0][index + 1], &fT[0][index], sizeof(fT[0][0]) * remaining);
- memmove(&fT[1][index + 1], &fT[1][index], sizeof(fT[1][0]) * remaining);
- fIsCoincident[0] += fIsCoincident[0] & ~((1 << index) - 1);
- fIsCoincident[1] += fIsCoincident[1] & ~((1 << index) - 1);
- }
- fPt[index] = pt;
- fT[0][index] = one;
- fT[1][index] = two;
- ++fUsed;
- return index;
-}
-
-void Intersections::remove(double one, double two, const _Point& startPt, const _Point& endPt) {
- for (int index = fUsed - 1; index >= 0; --index) {
- if (!(fIsCoincident[0] & (1 << index)) && (between(one, fT[fSwap][index], two)
- || startPt.approximatelyEqual(fPt[index])
- || endPt.approximatelyEqual(fPt[index]))) {
- SkASSERT(fUsed > 0);
- removeOne(index);
- }
- }
-}
-
-void Intersections::removeOne(int index) {
- int remaining = --fUsed - index;
- if (remaining <= 0) {
- return;
- }
- memmove(&fPt[index], &fPt[index + 1], sizeof(fPt[0]) * remaining);
- memmove(&fT[0][index], &fT[0][index + 1], sizeof(fT[0][0]) * remaining);
- memmove(&fT[1][index], &fT[1][index + 1], sizeof(fT[1][0]) * remaining);
- SkASSERT(fIsCoincident[0] == 0);
- int coBit = fIsCoincident[0] & (1 << index);
- fIsCoincident[0] -= ((fIsCoincident[0] >> 1) & ~((1 << index) - 1)) + coBit;
- SkASSERT(!(coBit ^ (fIsCoincident[1] & (1 << index))));
- fIsCoincident[1] -= ((fIsCoincident[1] >> 1) & ~((1 << index) - 1)) + coBit;
-}
diff --git a/experimental/Intersection/Intersections.h b/experimental/Intersection/Intersections.h
deleted file mode 100644
index a4135af643..0000000000
--- a/experimental/Intersection/Intersections.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#ifndef Intersections_DEFINE
-#define Intersections_DEFINE
-
-class Intersections {
-public:
- Intersections()
- : fFlip(0)
-#ifdef SK_DEBUG
- , fDepth(0)
-#endif
- , fSwap(0)
- {
-#ifdef SK_DEBUG
- bzero(fPt, sizeof(fPt));
- bzero(fT, sizeof(fT));
- bzero(fIsCoincident, sizeof(fIsCoincident));
-#endif
- reset();
- }
-
- int coincidentUsed() const {
- if (!fIsCoincident[0]) {
- SkASSERT(!fIsCoincident[0]);
- return 0;
- }
- int count = 0;
- SkDEBUGCODE(int count2 = 0;)
- for (int index = 0; index < fUsed; ++index) {
- if (fIsCoincident[0] & (1 << index)) {
- ++count;
- }
- #ifdef SK_DEBUG
- if (fIsCoincident[1] & (1 << index)) {
- ++count2;
- }
- #endif
- }
- SkASSERT(count == count2);
- return count;
- }
-
- void offset(int base, double start, double end) {
- for (int index = base; index < fUsed; ++index) {
- double val = fT[fSwap][index];
- val *= end - start;
- val += start;
- fT[fSwap][index] = val;
- }
- }
-
- // FIXME : does not respect swap
- int insert(double one, double two, const _Point& pt);
-
- // start if index == 0 : end if index == 1
- void insertCoincident(double one, double two, const _Point& pt) {
- int index = insertSwap(one, two, pt);
- int bit = 1 << index;
- fIsCoincident[0] |= bit;
- fIsCoincident[1] |= bit;
- }
-
- void insertCoincidentPair(double s1, double e1, double s2, double e2,
- const _Point& startPt, const _Point& endPt);
-
- int insertSwap(double one, double two, const _Point& pt) {
- if (fSwap) {
- return insert(two, one, pt);
- } else {
- return insert(one, two, pt);
- }
- }
-
- bool intersected() const {
- return fUsed > 0;
- }
-
- void removeOne(int index);
-
- // leaves flip, swap alone
- void reset() {
- fUsed = 0;
- fUnsortable = false;
- }
-
- void swap() {
- fSwap ^= true;
- }
-
- void swapPts() {
- int index;
- for (index = 0; index < fUsed; ++index) {
- SkTSwap(fT[0][index], fT[1][index]);
- }
- }
-
- bool swapped() const {
- return fSwap;
- }
-
- bool unsortable() const {
- return fUnsortable;
- }
-
- int used() const {
- return fUsed;
- }
-
- void downDepth() {
- SkASSERT(--fDepth >= 0);
- }
-
- void upDepth() {
- SkASSERT(++fDepth < 16);
- }
-
-#ifdef SK_DEBUG
- int depth() const {
- return fDepth;
- }
-#endif
-
- _Point fPt[9];
- double fT[2][9];
- unsigned short fIsCoincident[2]; // bit arrays, one bit set for each coincident T
- unsigned char fUsed;
- bool fFlip;
- bool fUnsortable;
-#ifdef SK_DEBUG
- int fDepth;
-#endif
-protected:
- // used by addCoincident to remove ordinary intersections in range
- void remove(double one, double two, const _Point& startPt, const _Point& endPt);
-private:
- bool fSwap;
-};
-
-#endif
diff --git a/experimental/Intersection/LineCubicIntersection.cpp b/experimental/Intersection/LineCubicIntersection.cpp
deleted file mode 100644
index c433fc2a29..0000000000
--- a/experimental/Intersection/LineCubicIntersection.cpp
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "CurveIntersection.h"
-#include "CubicUtilities.h"
-#include "Intersections.h"
-#include "LineUtilities.h"
-
-/*
-Find the interection of a line and cubic by solving for valid t values.
-
-Analogous to line-quadratic intersection, solve line-cubic intersection by
-representing the cubic as:
- x = a(1-t)^3 + 2b(1-t)^2t + c(1-t)t^2 + dt^3
- y = e(1-t)^3 + 2f(1-t)^2t + g(1-t)t^2 + ht^3
-and the line as:
- y = i*x + j (if the line is more horizontal)
-or:
- x = i*y + j (if the line is more vertical)
-
-Then using Mathematica, solve for the values of t where the cubic intersects the
-line:
-
- (in) Resultant[
- a*(1 - t)^3 + 3*b*(1 - t)^2*t + 3*c*(1 - t)*t^2 + d*t^3 - x,
- e*(1 - t)^3 + 3*f*(1 - t)^2*t + 3*g*(1 - t)*t^2 + h*t^3 - i*x - j, x]
- (out) -e + j +
- 3 e t - 3 f t -
- 3 e t^2 + 6 f t^2 - 3 g t^2 +
- e t^3 - 3 f t^3 + 3 g t^3 - h t^3 +
- i ( a -
- 3 a t + 3 b t +
- 3 a t^2 - 6 b t^2 + 3 c t^2 -
- a t^3 + 3 b t^3 - 3 c t^3 + d t^3 )
-
-if i goes to infinity, we can rewrite the line in terms of x. Mathematica:
-
- (in) Resultant[
- a*(1 - t)^3 + 3*b*(1 - t)^2*t + 3*c*(1 - t)*t^2 + d*t^3 - i*y - j,
- e*(1 - t)^3 + 3*f*(1 - t)^2*t + 3*g*(1 - t)*t^2 + h*t^3 - y, y]
- (out) a - j -
- 3 a t + 3 b t +
- 3 a t^2 - 6 b t^2 + 3 c t^2 -
- a t^3 + 3 b t^3 - 3 c t^3 + d t^3 -
- i ( e -
- 3 e t + 3 f t +
- 3 e t^2 - 6 f t^2 + 3 g t^2 -
- e t^3 + 3 f t^3 - 3 g t^3 + h t^3 )
-
-Solving this with Mathematica produces an expression with hundreds of terms;
-instead, use Numeric Solutions recipe to solve the cubic.
-
-The near-horizontal case, in terms of: Ax^3 + Bx^2 + Cx + D == 0
- A = (-(-e + 3*f - 3*g + h) + i*(-a + 3*b - 3*c + d) )
- B = 3*(-( e - 2*f + g ) + i*( a - 2*b + c ) )
- C = 3*(-(-e + f ) + i*(-a + b ) )
- D = (-( e ) + i*( a ) + j )
-
-The near-vertical case, in terms of: Ax^3 + Bx^2 + Cx + D == 0
- A = ( (-a + 3*b - 3*c + d) - i*(-e + 3*f - 3*g + h) )
- B = 3*( ( a - 2*b + c ) - i*( e - 2*f + g ) )
- C = 3*( (-a + b ) - i*(-e + f ) )
- D = ( ( a ) - i*( e ) - j )
-
-For horizontal lines:
-(in) Resultant[
- a*(1 - t)^3 + 3*b*(1 - t)^2*t + 3*c*(1 - t)*t^2 + d*t^3 - j,
- e*(1 - t)^3 + 3*f*(1 - t)^2*t + 3*g*(1 - t)*t^2 + h*t^3 - y, y]
-(out) e - j -
- 3 e t + 3 f t +
- 3 e t^2 - 6 f t^2 + 3 g t^2 -
- e t^3 + 3 f t^3 - 3 g t^3 + h t^3
-So the cubic coefficients are:
-
- */
-
-class LineCubicIntersections {
-public:
-
-LineCubicIntersections(const Cubic& c, const _Line& l, Intersections& i)
- : cubic(c)
- , line(l)
- , intersections(i) {
-}
-
-// see parallel routine in line quadratic intersections
-int intersectRay(double roots[3]) {
- double adj = line[1].x - line[0].x;
- double opp = line[1].y - line[0].y;
- Cubic r;
- for (int n = 0; n < 4; ++n) {
- r[n].x = (cubic[n].y - line[0].y) * adj - (cubic[n].x - line[0].x) * opp;
- }
- double A, B, C, D;
- coefficients(&r[0].x, A, B, C, D);
- return cubicRootsValidT(A, B, C, D, roots);
-}
-
-int intersect() {
- addEndPoints();
- double rootVals[3];
- int roots = intersectRay(rootVals);
- for (int index = 0; index < roots; ++index) {
- double cubicT = rootVals[index];
- double lineT = findLineT(cubicT);
- if (pinTs(cubicT, lineT)) {
- _Point pt;
- xy_at_t(line, lineT, pt.x, pt.y);
- intersections.insert(cubicT, lineT, pt);
- }
- }
- return intersections.fUsed;
-}
-
-int horizontalIntersect(double axisIntercept, double roots[3]) {
- double A, B, C, D;
- coefficients(&cubic[0].y, A, B, C, D);
- D -= axisIntercept;
- return cubicRootsValidT(A, B, C, D, roots);
-}
-
-int horizontalIntersect(double axisIntercept, double left, double right, bool flipped) {
- addHorizontalEndPoints(left, right, axisIntercept);
- double rootVals[3];
- int roots = horizontalIntersect(axisIntercept, rootVals);
- for (int index = 0; index < roots; ++index) {
- _Point pt;
- double cubicT = rootVals[index];
- xy_at_t(cubic, cubicT, pt.x, pt.y);
- double lineT = (pt.x - left) / (right - left);
- if (pinTs(cubicT, lineT)) {
- intersections.insert(cubicT, lineT, pt);
- }
- }
- if (flipped) {
- flip();
- }
- return intersections.fUsed;
-}
-
-int verticalIntersect(double axisIntercept, double roots[3]) {
- double A, B, C, D;
- coefficients(&cubic[0].x, A, B, C, D);
- D -= axisIntercept;
- return cubicRootsValidT(A, B, C, D, roots);
-}
-
-int verticalIntersect(double axisIntercept, double top, double bottom, bool flipped) {
- addVerticalEndPoints(top, bottom, axisIntercept);
- double rootVals[3];
- int roots = verticalIntersect(axisIntercept, rootVals);
- for (int index = 0; index < roots; ++index) {
- _Point pt;
- double cubicT = rootVals[index];
- xy_at_t(cubic, cubicT, pt.x, pt.y);
- double lineT = (pt.y - top) / (bottom - top);
- if (pinTs(cubicT, lineT)) {
- intersections.insert(cubicT, lineT, pt);
- }
- }
- if (flipped) {
- flip();
- }
- return intersections.fUsed;
-}
-
-protected:
-
-void addEndPoints()
-{
- for (int cIndex = 0; cIndex < 4; cIndex += 3) {
- for (int lIndex = 0; lIndex < 2; lIndex++) {
- if (cubic[cIndex] == line[lIndex]) {
- intersections.insert(cIndex >> 1, lIndex, line[lIndex]);
- }
- }
- }
-}
-
-void addHorizontalEndPoints(double left, double right, double y)
-{
- for (int cIndex = 0; cIndex < 4; cIndex += 3) {
- if (cubic[cIndex].y != y) {
- continue;
- }
- if (cubic[cIndex].x == left) {
- intersections.insert(cIndex >> 1, 0, cubic[cIndex]);
- }
- if (cubic[cIndex].x == right) {
- intersections.insert(cIndex >> 1, 1, cubic[cIndex]);
- }
- }
-}
-
-void addVerticalEndPoints(double top, double bottom, double x)
-{
- for (int cIndex = 0; cIndex < 4; cIndex += 3) {
- if (cubic[cIndex].x != x) {
- continue;
- }
- if (cubic[cIndex].y == top) {
- intersections.insert(cIndex >> 1, 0, cubic[cIndex]);
- }
- if (cubic[cIndex].y == bottom) {
- intersections.insert(cIndex >> 1, 1, cubic[cIndex]);
- }
- }
-}
-
-double findLineT(double t) {
- double x, y;
- xy_at_t(cubic, t, x, y);
- double dx = line[1].x - line[0].x;
- double dy = line[1].y - line[0].y;
- if (fabs(dx) > fabs(dy)) {
- return (x - line[0].x) / dx;
- }
- return (y - line[0].y) / dy;
-}
-
-void flip() {
- // OPTIMIZATION: instead of swapping, pass original line, use [1].y - [0].y
- int roots = intersections.fUsed;
- for (int index = 0; index < roots; ++index) {
- intersections.fT[1][index] = 1 - intersections.fT[1][index];
- }
-}
-
-static bool pinTs(double& cubicT, double& lineT) {
- if (!approximately_one_or_less(lineT)) {
- return false;
- }
- if (!approximately_zero_or_more(lineT)) {
- return false;
- }
- if (precisely_less_than_zero(cubicT)) {
- cubicT = 0;
- } else if (precisely_greater_than_one(cubicT)) {
- cubicT = 1;
- }
- if (precisely_less_than_zero(lineT)) {
- lineT = 0;
- } else if (precisely_greater_than_one(lineT)) {
- lineT = 1;
- }
- return true;
-}
-
-private:
-
-const Cubic& cubic;
-const _Line& line;
-Intersections& intersections;
-};
-
-int horizontalIntersect(const Cubic& cubic, double left, double right, double y,
- double tRange[3]) {
- LineCubicIntersections c(cubic, *((_Line*) 0), *((Intersections*) 0));
- double rootVals[3];
- int result = c.horizontalIntersect(y, rootVals);
- int tCount = 0;
- for (int index = 0; index < result; ++index) {
- double x, y;
- xy_at_t(cubic, rootVals[index], x, y);
- if (x < left || x > right) {
- continue;
- }
- tRange[tCount++] = rootVals[index];
- }
- return result;
-}
-
-int horizontalIntersect(const Cubic& cubic, double left, double right, double y,
- bool flipped, Intersections& intersections) {
- LineCubicIntersections c(cubic, *((_Line*) 0), intersections);
- return c.horizontalIntersect(y, left, right, flipped);
-}
-
-int verticalIntersect(const Cubic& cubic, double top, double bottom, double x,
- bool flipped, Intersections& intersections) {
- LineCubicIntersections c(cubic, *((_Line*) 0), intersections);
- return c.verticalIntersect(x, top, bottom, flipped);
-}
-
-int intersect(const Cubic& cubic, const _Line& line, Intersections& i) {
- LineCubicIntersections c(cubic, line, i);
- return c.intersect();
-}
-
-int intersectRay(const Cubic& cubic, const _Line& line, Intersections& i) {
- LineCubicIntersections c(cubic, line, i);
- return c.intersectRay(i.fT[0]);
-}
diff --git a/experimental/Intersection/LineCubicIntersection_Test.cpp b/experimental/Intersection/LineCubicIntersection_Test.cpp
deleted file mode 100644
index adf01122ac..0000000000
--- a/experimental/Intersection/LineCubicIntersection_Test.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "CurveIntersection.h"
-#include "CurveUtilities.h"
-#include "Intersection_Tests.h"
-#include "Intersections.h"
-#include "TestUtilities.h"
-
-struct lineCubic {
- Cubic cubic;
- _Line line;
-} lineCubicTests[] = {
- {{{0, 0}, {0, 1}, {0, 1}, {1, 1}}, {{0, 1}, {1, 0}}}
-};
-
-size_t lineCubicTests_count = sizeof(lineCubicTests) / sizeof(lineCubicTests[0]);
-
-const int firstLineCubicIntersectionTest = 0;
-
-void LineCubicIntersection_Test() {
- for (size_t index = firstLineCubicIntersectionTest; index < lineCubicTests_count; ++index) {
- const Cubic& cubic = lineCubicTests[index].cubic;
- const _Line& line = lineCubicTests[index].line;
- Cubic reduce1;
- _Line reduce2;
- int order1 = reduceOrder(cubic, reduce1, kReduceOrder_NoQuadraticsAllowed,
- kReduceOrder_TreatAsFill);
- int order2 = reduceOrder(line, reduce2);
- if (order1 < 4) {
- printf("[%d] cubic order=%d\n", (int) index, order1);
- }
- if (order2 < 2) {
- printf("[%d] line order=%d\n", (int) index, order2);
- }
- if (order1 == 4 && order2 == 2) {
- Intersections i;
- double* range1 = i.fT[0];
- double* range2 = i.fT[1];
- int roots = intersect(reduce1, reduce2, i);
- for (int pt = 0; pt < roots; ++pt) {
- double tt1 = range1[pt];
- double tx1, ty1;
- xy_at_t(cubic, tt1, tx1, ty1);
- double tt2 = range2[pt];
- double tx2, ty2;
- xy_at_t(line, tt2, tx2, ty2);
- if (!AlmostEqualUlps(tx1, tx2)) {
- printf("%s [%d,%d] x!= t1=%g (%g,%g) t2=%g (%g,%g)\n",
- __FUNCTION__, (int)index, pt, tt1, tx1, ty1, tt2, tx2, ty2);
- }
- if (!AlmostEqualUlps(ty1, ty2)) {
- printf("%s [%d,%d] y!= t1=%g (%g,%g) t2=%g (%g,%g)\n",
- __FUNCTION__, (int)index, pt, tt1, tx1, ty1, tt2, tx2, ty2);
- }
- }
- }
- }
-}
diff --git a/experimental/Intersection/LineIntersection.cpp b/experimental/Intersection/LineIntersection.cpp
deleted file mode 100644
index ca6a8e4081..0000000000
--- a/experimental/Intersection/LineIntersection.cpp
+++ /dev/null
@@ -1,338 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "CurveIntersection.h"
-#include "Intersections.h"
-#include "LineIntersection.h"
-#include "LineUtilities.h"
-
-/* Determine the intersection point of two lines. This assumes the lines are not parallel,
- and that that the lines are infinite.
- From http://en.wikipedia.org/wiki/Line-line_intersection
- */
-void lineIntersect(const _Line& a, const _Line& b, _Point& p) {
- double axLen = a[1].x - a[0].x;
- double ayLen = a[1].y - a[0].y;
- double bxLen = b[1].x - b[0].x;
- double byLen = b[1].y - b[0].y;
- double denom = byLen * axLen - ayLen * bxLen;
- SkASSERT(denom);
- double term1 = a[1].x * a[0].y - a[1].y * a[0].x;
- double term2 = b[1].x * b[0].y - b[1].y * b[0].x;
- p.x = (term1 * bxLen - axLen * term2) / denom;
- p.y = (term1 * byLen - ayLen * term2) / denom;
-}
-
-static int computePoints(const _Line& a, int used, Intersections& i) {
- i.fPt[0] = xy_at_t(a, i.fT[0][0]);
- if ((i.fUsed = used) == 2) {
- i.fPt[1] = xy_at_t(a, i.fT[0][1]);
- }
- return i.fUsed;
-}
-
-/*
- Determine the intersection point of two line segments
- Return FALSE if the lines don't intersect
- from: http://paulbourke.net/geometry/lineline2d/
- */
-
-int intersect(const _Line& a, const _Line& b, Intersections& i) {
- double axLen = a[1].x - a[0].x;
- double ayLen = a[1].y - a[0].y;
- double bxLen = b[1].x - b[0].x;
- double byLen = b[1].y - b[0].y;
- /* Slopes match when denom goes to zero:
- axLen / ayLen == bxLen / byLen
- (ayLen * byLen) * axLen / ayLen == (ayLen * byLen) * bxLen / byLen
- byLen * axLen == ayLen * bxLen
- byLen * axLen - ayLen * bxLen == 0 ( == denom )
- */
- double denom = byLen * axLen - ayLen * bxLen;
- double ab0y = a[0].y - b[0].y;
- double ab0x = a[0].x - b[0].x;
- double numerA = ab0y * bxLen - byLen * ab0x;
- double numerB = ab0y * axLen - ayLen * ab0x;
- bool mayNotOverlap = (numerA < 0 && denom > numerA) || (numerA > 0 && denom < numerA)
- || (numerB < 0 && denom > numerB) || (numerB > 0 && denom < numerB);
- numerA /= denom;
- numerB /= denom;
- if ((!approximately_zero(denom) || (!approximately_zero_inverse(numerA)
- && !approximately_zero_inverse(numerB))) && !sk_double_isnan(numerA)
- && !sk_double_isnan(numerB)) {
- if (mayNotOverlap) {
- return 0;
- }
- i.fT[0][0] = numerA;
- i.fT[1][0] = numerB;
- i.fPt[0] = xy_at_t(a, numerA);
- return computePoints(a, 1, i);
- }
- /* See if the axis intercepts match:
- ay - ax * ayLen / axLen == by - bx * ayLen / axLen
- axLen * (ay - ax * ayLen / axLen) == axLen * (by - bx * ayLen / axLen)
- axLen * ay - ax * ayLen == axLen * by - bx * ayLen
- */
- // FIXME: need to use AlmostEqualUlps variant instead
- if (!approximately_equal_squared(axLen * a[0].y - ayLen * a[0].x,
- axLen * b[0].y - ayLen * b[0].x)) {
- return 0;
- }
- const double* aPtr;
- const double* bPtr;
- if (fabs(axLen) > fabs(ayLen) || fabs(bxLen) > fabs(byLen)) {
- aPtr = &a[0].x;
- bPtr = &b[0].x;
- } else {
- aPtr = &a[0].y;
- bPtr = &b[0].y;
- }
- double a0 = aPtr[0];
- double a1 = aPtr[2];
- double b0 = bPtr[0];
- double b1 = bPtr[2];
- // OPTIMIZATION: restructure to reject before the divide
- // e.g., if ((a0 - b0) * (a0 - a1) < 0 || abs(a0 - b0) > abs(a0 - a1))
- // (except efficient)
- double aDenom = a0 - a1;
- if (approximately_zero(aDenom)) {
- if (!between(b0, a0, b1)) {
- return 0;
- }
- i.fT[0][0] = i.fT[0][1] = 0;
- } else {
- double at0 = (a0 - b0) / aDenom;
- double at1 = (a0 - b1) / aDenom;
- if ((at0 < 0 && at1 < 0) || (at0 > 1 && at1 > 1)) {
- return 0;
- }
- i.fT[0][0] = SkTMax(SkTMin(at0, 1.0), 0.0);
- i.fT[0][1] = SkTMax(SkTMin(at1, 1.0), 0.0);
- }
- double bDenom = b0 - b1;
- if (approximately_zero(bDenom)) {
- i.fT[1][0] = i.fT[1][1] = 0;
- } else {
- int bIn = aDenom * bDenom < 0;
- i.fT[1][bIn] = SkTMax(SkTMin((b0 - a0) / bDenom, 1.0), 0.0);
- i.fT[1][!bIn] = SkTMax(SkTMin((b0 - a1) / bDenom, 1.0), 0.0);
- }
- bool second = fabs(i.fT[0][0] - i.fT[0][1]) > FLT_EPSILON;
- SkASSERT((fabs(i.fT[1][0] - i.fT[1][1]) <= FLT_EPSILON) ^ second);
- return computePoints(a, 1 + second, i);
-}
-
-int horizontalIntersect(const _Line& line, double y, double tRange[2]) {
- double min = line[0].y;
- double max = line[1].y;
- if (min > max) {
- SkTSwap(min, max);
- }
- if (min > y || max < y) {
- return 0;
- }
- if (AlmostEqualUlps(min, max)) {
- tRange[0] = 0;
- tRange[1] = 1;
- return 2;
- }
- tRange[0] = (y - line[0].y) / (line[1].y - line[0].y);
- return 1;
-}
-
-// OPTIMIZATION Given: dy = line[1].y - line[0].y
-// and: xIntercept / (y - line[0].y) == (line[1].x - line[0].x) / dy
-// then: xIntercept * dy == (line[1].x - line[0].x) * (y - line[0].y)
-// Assuming that dy is always > 0, the line segment intercepts if:
-// left * dy <= xIntercept * dy <= right * dy
-// thus: left * dy <= (line[1].x - line[0].x) * (y - line[0].y) <= right * dy
-// (clever as this is, it does not give us the t value, so may be useful only
-// as a quick reject -- and maybe not then; it takes 3 muls, 3 adds, 2 cmps)
-int horizontalLineIntersect(const _Line& line, double left, double right,
- double y, double tRange[2]) {
- int result = horizontalIntersect(line, y, tRange);
- if (result != 1) {
- // FIXME: this is incorrect if result == 2
- return result;
- }
- double xIntercept = line[0].x + tRange[0] * (line[1].x - line[0].x);
- if (xIntercept > right || xIntercept < left) {
- return 0;
- }
- return result;
-}
-
-int horizontalIntersect(const _Line& line, double left, double right,
- double y, bool flipped, Intersections& intersections) {
- int result = horizontalIntersect(line, y, intersections.fT[0]);
- switch (result) {
- case 0:
- break;
- case 1: {
- double xIntercept = line[0].x + intersections.fT[0][0]
- * (line[1].x - line[0].x);
- if (xIntercept > right || xIntercept < left) {
- return 0;
- }
- intersections.fT[1][0] = (xIntercept - left) / (right - left);
- break;
- }
- case 2:
- #if 0 // sorting edges fails to preserve original direction
- double lineL = line[0].x;
- double lineR = line[1].x;
- if (lineL > lineR) {
- SkTSwap(lineL, lineR);
- }
- double overlapL = SkTMax(left, lineL);
- double overlapR = SkTMin(right, lineR);
- if (overlapL > overlapR) {
- return 0;
- }
- if (overlapL == overlapR) {
- result = 1;
- }
- intersections.fT[0][0] = (overlapL - line[0].x) / (line[1].x - line[0].x);
- intersections.fT[1][0] = (overlapL - left) / (right - left);
- if (result > 1) {
- intersections.fT[0][1] = (overlapR - line[0].x) / (line[1].x - line[0].x);
- intersections.fT[1][1] = (overlapR - left) / (right - left);
- }
- #else
- double a0 = line[0].x;
- double a1 = line[1].x;
- double b0 = flipped ? right : left;
- double b1 = flipped ? left : right;
- // FIXME: share common code below
- double at0 = (a0 - b0) / (a0 - a1);
- double at1 = (a0 - b1) / (a0 - a1);
- if ((at0 < 0 && at1 < 0) || (at0 > 1 && at1 > 1)) {
- return 0;
- }
- intersections.fT[0][0] = SkTMax(SkTMin(at0, 1.0), 0.0);
- intersections.fT[0][1] = SkTMax(SkTMin(at1, 1.0), 0.0);
- int bIn = (a0 - a1) * (b0 - b1) < 0;
- intersections.fT[1][bIn] = SkTMax(SkTMin((b0 - a0) / (b0 - b1),
- 1.0), 0.0);
- intersections.fT[1][!bIn] = SkTMax(SkTMin((b0 - a1) / (b0 - b1),
- 1.0), 0.0);
- bool second = fabs(intersections.fT[0][0] - intersections.fT[0][1])
- > FLT_EPSILON;
- SkASSERT((fabs(intersections.fT[1][0] - intersections.fT[1][1])
- <= FLT_EPSILON) ^ second);
- return computePoints(line, 1 + second, intersections);
- #endif
- break;
- }
- if (flipped) {
- // OPTIMIZATION: instead of swapping, pass original line, use [1].x - [0].x
- for (int index = 0; index < result; ++index) {
- intersections.fT[1][index] = 1 - intersections.fT[1][index];
- }
- }
- return computePoints(line, result, intersections);
-}
-
-static int verticalIntersect(const _Line& line, double x, double tRange[2]) {
- double min = line[0].x;
- double max = line[1].x;
- if (min > max) {
- SkTSwap(min, max);
- }
- if (min > x || max < x) {
- return 0;
- }
- if (AlmostEqualUlps(min, max)) {
- tRange[0] = 0;
- tRange[1] = 1;
- return 2;
- }
- tRange[0] = (x - line[0].x) / (line[1].x - line[0].x);
- return 1;
-}
-
-int verticalIntersect(const _Line& line, double top, double bottom,
- double x, bool flipped, Intersections& intersections) {
- int result = verticalIntersect(line, x, intersections.fT[0]);
- switch (result) {
- case 0:
- break;
- case 1: {
- double yIntercept = line[0].y + intersections.fT[0][0]
- * (line[1].y - line[0].y);
- if (yIntercept > bottom || yIntercept < top) {
- return 0;
- }
- intersections.fT[1][0] = (yIntercept - top) / (bottom - top);
- break;
- }
- case 2:
- #if 0 // sorting edges fails to preserve original direction
- double lineT = line[0].y;
- double lineB = line[1].y;
- if (lineT > lineB) {
- SkTSwap(lineT, lineB);
- }
- double overlapT = SkTMax(top, lineT);
- double overlapB = SkTMin(bottom, lineB);
- if (overlapT > overlapB) {
- return 0;
- }
- if (overlapT == overlapB) {
- result = 1;
- }
- intersections.fT[0][0] = (overlapT - line[0].y) / (line[1].y - line[0].y);
- intersections.fT[1][0] = (overlapT - top) / (bottom - top);
- if (result > 1) {
- intersections.fT[0][1] = (overlapB - line[0].y) / (line[1].y - line[0].y);
- intersections.fT[1][1] = (overlapB - top) / (bottom - top);
- }
- #else
- double a0 = line[0].y;
- double a1 = line[1].y;
- double b0 = flipped ? bottom : top;
- double b1 = flipped ? top : bottom;
- // FIXME: share common code above
- double at0 = (a0 - b0) / (a0 - a1);
- double at1 = (a0 - b1) / (a0 - a1);
- if ((at0 < 0 && at1 < 0) || (at0 > 1 && at1 > 1)) {
- return 0;
- }
- intersections.fT[0][0] = SkTMax(SkTMin(at0, 1.0), 0.0);
- intersections.fT[0][1] = SkTMax(SkTMin(at1, 1.0), 0.0);
- int bIn = (a0 - a1) * (b0 - b1) < 0;
- intersections.fT[1][bIn] = SkTMax(SkTMin((b0 - a0) / (b0 - b1),
- 1.0), 0.0);
- intersections.fT[1][!bIn] = SkTMax(SkTMin((b0 - a1) / (b0 - b1),
- 1.0), 0.0);
- bool second = fabs(intersections.fT[0][0] - intersections.fT[0][1])
- > FLT_EPSILON;
- SkASSERT((fabs(intersections.fT[1][0] - intersections.fT[1][1])
- <= FLT_EPSILON) ^ second);
- return computePoints(line, 1 + second, intersections);
- #endif
- break;
- }
- if (flipped) {
- // OPTIMIZATION: instead of swapping, pass original line, use [1].y - [0].y
- for (int index = 0; index < result; ++index) {
- intersections.fT[1][index] = 1 - intersections.fT[1][index];
- }
- }
- return computePoints(line, result, intersections);
-}
-
-// from http://www.bryceboe.com/wordpress/wp-content/uploads/2006/10/intersect.py
-// 4 subs, 2 muls, 1 cmp
-static bool ccw(const _Point& A, const _Point& B, const _Point& C) {
- return (C.y - A.y) * (B.x - A.x) > (B.y - A.y) * (C.x - A.x);
-}
-
-// 16 subs, 8 muls, 6 cmps
-bool testIntersect(const _Line& a, const _Line& b) {
- return ccw(a[0], b[0], b[1]) != ccw(a[1], b[0], b[1])
- && ccw(a[0], a[1], b[0]) != ccw(a[0], a[1], b[1]);
-}
diff --git a/experimental/Intersection/LineIntersection.h b/experimental/Intersection/LineIntersection.h
deleted file mode 100644
index 4036f136e1..0000000000
--- a/experimental/Intersection/LineIntersection.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#ifndef LineIntersection_DEFINE
-#define LineIntersection_DEFINE
-
-#include "Intersections.h"
-
-int horizontalIntersect(const _Line& line, double y, double tRange[2]);
-int horizontalLineIntersect(const _Line& line, double left, double right,
- double y, double tRange[2]);
-void lineIntersect(const _Line& a, const _Line& b, _Point& p);
-int intersect(const _Line& a, const _Line& b, Intersections&);
-bool testIntersect(const _Line& a, const _Line& b);
-int verticalLineIntersect(const _Line& line, double top, double bottom,
- double x, double tRange[2]);
-
-#endif
diff --git a/experimental/Intersection/LineIntersection_Test.cpp b/experimental/Intersection/LineIntersection_Test.cpp
deleted file mode 100644
index 283d9dfe4b..0000000000
--- a/experimental/Intersection/LineIntersection_Test.cpp
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "CurveUtilities.h"
-#include "Intersection_Tests.h"
-#include "LineIntersection.h"
-
-// FIXME: add tests for intersecting, non-intersecting, degenerate, coincident
-const _Line tests[][2] = {
- {{{0, 0}, {1, 0}}, {{1, 0}, {0, 0}}},
- {{{0, 0}, {0, 0}}, {{0, 0}, {1, 0}}},
- {{{0, 1}, {0, 1}}, {{0, 0}, {0, 2}}},
- {{{0, 0}, {1, 0}}, {{0, 0}, {2, 0}}},
- {{{1, 1}, {2, 2}}, {{0, 0}, {3, 3}}},
- {{{166.86950047022856, 112.69654129527828}, {166.86948801592692, 112.69655741235339}},
- {{166.86960700313026, 112.6965477747386}, {166.86925794355412, 112.69656471103423}}}
-};
-
-const size_t tests_count = sizeof(tests) / sizeof(tests[0]);
-
-const _Line noIntersect[][2] = {
- {{{0, 0}, {1, 0}}, {{3, 0}, {2, 0}}},
- {{{0, 0}, {0, 0}}, {{1, 0}, {2, 0}}},
- {{{0, 1}, {0, 1}}, {{0, 3}, {0, 2}}},
- {{{0, 0}, {1, 0}}, {{2, 0}, {3, 0}}},
- {{{1, 1}, {2, 2}}, {{4, 4}, {3, 3}}},
-};
-
-const size_t noIntersect_count = sizeof(noIntersect) / sizeof(noIntersect[0]);
-
-static size_t firstLineIntersectionTest = 0;
-static size_t firstNoIntersectionTest = 0;
-
-void LineIntersection_Test() {
- size_t index;
- for (index = firstLineIntersectionTest; index < tests_count; ++index) {
- const _Line& line1 = tests[index][0];
- const _Line& line2 = tests[index][1];
- Intersections ts;
- int pts = intersect(line1, line2, ts);
- if (!pts) {
- printf("%s [%zu] no intersection found\n", __FUNCTION__, index);
- }
- for (int i = 0; i < pts; ++i) {
- _Point result1, result2;
- xy_at_t(line1, ts.fT[0][i], result1.x, result1.y);
- xy_at_t(line2, ts.fT[1][i], result2.x, result2.y);
- if (!result1.approximatelyEqual(result2)) {
- if (pts == 1) {
- printf("%s [%zu] not equal\n", __FUNCTION__, index);
- } else {
- xy_at_t(line2, ts.fT[1][i ^ 1], result2.x, result2.y);
- if (!result1.approximatelyEqual(result2)) {
- printf("%s [%zu] not equal\n", __FUNCTION__, index);
- }
- }
- }
- }
- }
- for (index = firstNoIntersectionTest; index < noIntersect_count; ++index) {
- const _Line& line1 = noIntersect[index][0];
- const _Line& line2 = noIntersect[index][1];
- Intersections ts;
- int pts = intersect(line1, line2, ts);
- if (pts) {
- printf("%s [%zu] no intersection expected\n", __FUNCTION__, index);
- }
- }
-}
diff --git a/experimental/Intersection/LineParameterization.cpp b/experimental/Intersection/LineParameterization.cpp
deleted file mode 100644
index 197394530b..0000000000
--- a/experimental/Intersection/LineParameterization.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "CurveIntersection.h"
-
-/* This rejects coincidence with two muls, two adds, and one cmp.
- Coincident candidates will take another four muls and two adds, but may still
- fail if they don't overlap. (The overlap test isn't performed here.)
- */
-bool implicit_matches(const _Line& one, const _Line& two) {
- _Point oneD, twoD;
- tangent(one, oneD);
- tangent(two, twoD);
- /* See if the slopes match, i.e.
- dx1 / dy1 == dx2 / dy2
- (dy1 * dy2) * dx1 / dy1 == (dy1 * dy2) * dx2 / dy2
- dy2 * dx1 == dy1 * dx2
- */
- if (!AlmostEqualUlps(oneD.x * twoD.y, twoD.x * oneD.y)) {
- return false;
- }
- /* See if the axis intercepts match, i.e.
- y0 - x0 * dy / dx == y1 - x1 * dy / dx
- dx * (y0 - x0 * dy / dx) == dx * (y1 - x1 * dy / dx)
- dx * y0 - x0 * dy == dx * y1 - x1 * dy
- */
- if (!AlmostEqualUlps(oneD.x * one[0].y - oneD.y * one[0].x,
- oneD.x * two[0].y - oneD.y * two[0].x)) {
- return false;
- }
- return true;
-}
-
-bool implicit_matches_ulps(const _Line& one, const _Line& two, int ulps) {
- _Point oneD, twoD;
- tangent(one, oneD);
- tangent(two, twoD);
- /* See if the slopes match, i.e.
- dx1 / dy1 == dx2 / dy2
- (dy1 * dy2) * dx1 / dy1 == (dy1 * dy2) * dx2 / dy2
- dy2 * dx1 == dy1 * dx2
- */
- int diff = UlpsDiff((float) (oneD.x * twoD.y), (float) (twoD.x * oneD.y));
- if (diff < 0 || diff > ulps) {
- return false;
- }
- /* See if the axis intercepts match, i.e.
- y0 - x0 * dy / dx == y1 - x1 * dy / dx
- dx * (y0 - x0 * dy / dx) == dx * (y1 - x1 * dy / dx)
- dx * y0 - x0 * dy == dx * y1 - x1 * dy
- */
- diff = UlpsDiff((float) (oneD.x * one[0].y - oneD.y * one[0].x),
- (float) (oneD.x * two[0].y - oneD.y * two[0].x));
- return diff >= 0 && diff <= ulps;
-}
-
-void tangent(const _Line& line, _Point& result) {
- result.x = line[0].x - line[1].x;
- result.y = line[0].y - line[1].y;
-}
diff --git a/experimental/Intersection/LineParameters.h b/experimental/Intersection/LineParameters.h
deleted file mode 100644
index 637b3b6d21..0000000000
--- a/experimental/Intersection/LineParameters.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "DataTypes.h"
-
-// Sources
-// computer-aided design - volume 22 number 9 november 1990 pp 538 - 549
-// online at http://cagd.cs.byu.edu/~tom/papers/bezclip.pdf
-
-// This turns a line segment into a parameterized line, of the form
-// ax + by + c = 0
-// When a^2 + b^2 == 1, the line is normalized.
-// The distance to the line for (x, y) is d(x,y) = ax + by + c
-//
-// Note that the distances below are not necessarily normalized. To get the true
-// distance, it's necessary to either call normalize() after xxxEndPoints(), or
-// divide the result of xxxDistance() by sqrt(normalSquared())
-
-class LineParameters {
-public:
- void cubicEndPoints(const Cubic& pts) {
- cubicEndPoints(pts, 0, 3);
- }
-
- void cubicEndPoints(const Cubic& pts, int s, int e) {
- a = approximately_pin(pts[s].y - pts[e].y);
- b = approximately_pin(pts[e].x - pts[s].x);
- c = pts[s].x * pts[e].y - pts[e].x * pts[s].y;
- }
-
- void lineEndPoints(const _Line& pts) {
- a = approximately_pin(pts[0].y - pts[1].y);
- b = approximately_pin(pts[1].x - pts[0].x);
- c = pts[0].x * pts[1].y - pts[1].x * pts[0].y;
- }
-
- void quadEndPoints(const Quadratic& pts) {
- quadEndPoints(pts, 0, 2);
- }
-
- void quadEndPoints(const Quadratic& pts, int s, int e) {
- a = approximately_pin(pts[s].y - pts[e].y);
- b = approximately_pin(pts[e].x - pts[s].x);
- c = pts[s].x * pts[e].y - pts[e].x * pts[s].y;
- }
-
- double normalSquared() const {
- return a * a + b * b;
- }
-
- bool normalize() {
- double normal = sqrt(normalSquared());
- if (approximately_zero(normal)) {
- a = b = c = 0;
- return false;
- }
- double reciprocal = 1 / normal;
- a *= reciprocal;
- b *= reciprocal;
- c *= reciprocal;
- return true;
- }
-
- void cubicDistanceY(const Cubic& pts, Cubic& distance) const {
- double oneThird = 1 / 3.0;
- for (int index = 0; index < 4; ++index) {
- distance[index].x = index * oneThird;
- distance[index].y = a * pts[index].x + b * pts[index].y + c;
- }
- }
-
- void quadDistanceY(const Quadratic& pts, Quadratic& distance) const {
- double oneHalf = 1 / 2.0;
- for (int index = 0; index < 3; ++index) {
- distance[index].x = index * oneHalf;
- distance[index].y = a * pts[index].x + b * pts[index].y + c;
- }
- }
-
- double controlPtDistance(const Cubic& pts, int index) const {
- SkASSERT(index == 1 || index == 2);
- return a * pts[index].x + b * pts[index].y + c;
- }
-
- double controlPtDistance(const Quadratic& pts) const {
- return a * pts[1].x + b * pts[1].y + c;
- }
-
- double pointDistance(const _Point& pt) const {
- return a * pt.x + b * pt.y + c;
- }
-
- double dx() const {
- return b;
- }
-
- double dy() const {
- return -a;
- }
-
-private:
- double a;
- double b;
- double c;
-};
diff --git a/experimental/Intersection/LineParameteters_Test.cpp b/experimental/Intersection/LineParameteters_Test.cpp
deleted file mode 100644
index 462ca16950..0000000000
--- a/experimental/Intersection/LineParameteters_Test.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "Intersection_Tests.h"
-#include "LineParameters.h"
-
-
-// tests to verify that distance calculations are coded correctly
-const Cubic tests[] = {
- {{0, 0}, {1, 1}, {2, 2}, {0, 3}},
- {{0, 0}, {1, 1}, {2, 2}, {3, 0}},
- {{0, 0}, {5, 0}, {-2,4}, {3, 4}},
- {{0, 2}, {1, 0}, {2, 0}, {3, 0}},
- {{0, .2}, {1, 0}, {2, 0}, {3, 0}},
- {{0, .02}, {1, 0}, {2, 0}, {3, 0}},
- {{0, .002}, {1, 0}, {2, 0}, {3, 0}},
- {{0, .0002}, {1, 0}, {2, 0}, {3, 0}},
- {{0, .00002}, {1, 0}, {2, 0}, {3, 0}},
- {{0, PointEpsilon * 2}, {1, 0}, {2, 0}, {3, 0}},
-};
-
-const double answers[][2] = {
- {1, 2},
- {1, 2},
- {4, 4},
- {1.1094003924, 0.5547001962},
- {0.133038021, 0.06651901052},
- {0.0133330370, 0.006666518523},
- {0.001333333037, 0.0006666665185},
- {0.000133333333, 6.666666652e-05},
- {1.333333333e-05, 6.666666667e-06},
- {1.333333333e-06, 6.666666667e-07},
-};
-
-const size_t tests_count = sizeof(tests) / sizeof(tests[0]);
-
-static size_t firstLineParameterTest = 0;
-
-void LineParameter_Test() {
- for (size_t index = firstLineParameterTest; index < tests_count; ++index) {
- LineParameters lineParameters;
- const Cubic& cubic = tests[index];
- lineParameters.cubicEndPoints(cubic);
- double denormalizedDistance[2];
- denormalizedDistance[0] = lineParameters.controlPtDistance(cubic, 1);
- denormalizedDistance[1] = lineParameters.controlPtDistance(cubic, 2);
- double normalSquared = lineParameters.normalSquared();
- size_t inner;
- for (inner = 0; inner < 2; ++inner) {
- double distSq = denormalizedDistance[inner];
- distSq *= distSq;
- double answersSq = answers[index][inner];
- answersSq *= answersSq;
- if (AlmostEqualUlps(distSq, normalSquared * answersSq)) {
- continue;
- }
- SkDebugf("%s [%d,%d] denormalizedDistance:%g != answer:%g"
- " distSq:%g answerSq:%g normalSquared:%g\n",
- __FUNCTION__, (int)index, (int)inner,
- denormalizedDistance[inner], answers[index][inner],
- distSq, answersSq, normalSquared);
- }
- lineParameters.normalize();
- double normalizedDistance[2];
- normalizedDistance[0] = lineParameters.controlPtDistance(cubic, 1);
- normalizedDistance[1] = lineParameters.controlPtDistance(cubic, 2);
- for (inner = 0; inner < 2; ++inner) {
- if (AlmostEqualUlps(fabs(normalizedDistance[inner]), answers[index][inner])) {
- continue;
- }
- SkDebugf("%s [%d,%d] normalizedDistance:%1.10g != answer:%g\n",
- __FUNCTION__, (int)index, (int)inner,
- normalizedDistance[inner], answers[index][inner]);
- }
- }
-}
diff --git a/experimental/Intersection/LineQuadraticIntersection.cpp b/experimental/Intersection/LineQuadraticIntersection.cpp
deleted file mode 100644
index f855d97e4c..0000000000
--- a/experimental/Intersection/LineQuadraticIntersection.cpp
+++ /dev/null
@@ -1,369 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "CurveIntersection.h"
-#include "Intersections.h"
-#include "LineUtilities.h"
-#include "QuadraticUtilities.h"
-
-/*
-Find the interection of a line and quadratic by solving for valid t values.
-
-From http://stackoverflow.com/questions/1853637/how-to-find-the-mathematical-function-defining-a-bezier-curve
-
-"A Bezier curve is a parametric function. A quadratic Bezier curve (i.e. three
-control points) can be expressed as: F(t) = A(1 - t)^2 + B(1 - t)t + Ct^2 where
-A, B and C are points and t goes from zero to one.
-
-This will give you two equations:
-
- x = a(1 - t)^2 + b(1 - t)t + ct^2
- y = d(1 - t)^2 + e(1 - t)t + ft^2
-
-If you add for instance the line equation (y = kx + m) to that, you'll end up
-with three equations and three unknowns (x, y and t)."
-
-Similar to above, the quadratic is represented as
- x = a(1-t)^2 + 2b(1-t)t + ct^2
- y = d(1-t)^2 + 2e(1-t)t + ft^2
-and the line as
- y = g*x + h
-
-Using Mathematica, solve for the values of t where the quadratic intersects the
-line:
-
- (in) t1 = Resultant[a*(1 - t)^2 + 2*b*(1 - t)*t + c*t^2 - x,
- d*(1 - t)^2 + 2*e*(1 - t)*t + f*t^2 - g*x - h, x]
- (out) -d + h + 2 d t - 2 e t - d t^2 + 2 e t^2 - f t^2 +
- g (a - 2 a t + 2 b t + a t^2 - 2 b t^2 + c t^2)
- (in) Solve[t1 == 0, t]
- (out) {
- {t -> (-2 d + 2 e + 2 a g - 2 b g -
- Sqrt[(2 d - 2 e - 2 a g + 2 b g)^2 -
- 4 (-d + 2 e - f + a g - 2 b g + c g) (-d + a g + h)]) /
- (2 (-d + 2 e - f + a g - 2 b g + c g))
- },
- {t -> (-2 d + 2 e + 2 a g - 2 b g +
- Sqrt[(2 d - 2 e - 2 a g + 2 b g)^2 -
- 4 (-d + 2 e - f + a g - 2 b g + c g) (-d + a g + h)]) /
- (2 (-d + 2 e - f + a g - 2 b g + c g))
- }
- }
-
-Using the results above (when the line tends towards horizontal)
- A = (-(d - 2*e + f) + g*(a - 2*b + c) )
- B = 2*( (d - e ) - g*(a - b ) )
- C = (-(d ) + g*(a ) + h )
-
-If g goes to infinity, we can rewrite the line in terms of x.
- x = g'*y + h'
-
-And solve accordingly in Mathematica:
-
- (in) t2 = Resultant[a*(1 - t)^2 + 2*b*(1 - t)*t + c*t^2 - g'*y - h',
- d*(1 - t)^2 + 2*e*(1 - t)*t + f*t^2 - y, y]
- (out) a - h' - 2 a t + 2 b t + a t^2 - 2 b t^2 + c t^2 -
- g' (d - 2 d t + 2 e t + d t^2 - 2 e t^2 + f t^2)
- (in) Solve[t2 == 0, t]
- (out) {
- {t -> (2 a - 2 b - 2 d g' + 2 e g' -
- Sqrt[(-2 a + 2 b + 2 d g' - 2 e g')^2 -
- 4 (a - 2 b + c - d g' + 2 e g' - f g') (a - d g' - h')]) /
- (2 (a - 2 b + c - d g' + 2 e g' - f g'))
- },
- {t -> (2 a - 2 b - 2 d g' + 2 e g' +
- Sqrt[(-2 a + 2 b + 2 d g' - 2 e g')^2 -
- 4 (a - 2 b + c - d g' + 2 e g' - f g') (a - d g' - h')])/
- (2 (a - 2 b + c - d g' + 2 e g' - f g'))
- }
- }
-
-Thus, if the slope of the line tends towards vertical, we use:
- A = ( (a - 2*b + c) - g'*(d - 2*e + f) )
- B = 2*(-(a - b ) + g'*(d - e ) )
- C = ( (a ) - g'*(d ) - h' )
- */
-
-
-class LineQuadraticIntersections {
-public:
-
-LineQuadraticIntersections(const Quadratic& q, const _Line& l, Intersections& i)
- : quad(q)
- , line(l)
- , intersections(i) {
-}
-
-int intersectRay(double roots[2]) {
-/*
- solve by rotating line+quad so line is horizontal, then finding the roots
- set up matrix to rotate quad to x-axis
- |cos(a) -sin(a)|
- |sin(a) cos(a)|
- note that cos(a) = A(djacent) / Hypoteneuse
- sin(a) = O(pposite) / Hypoteneuse
- since we are computing Ts, we can ignore hypoteneuse, the scale factor:
- | A -O |
- | O A |
- A = line[1].x - line[0].x (adjacent side of the right triangle)
- O = line[1].y - line[0].y (opposite side of the right triangle)
- for each of the three points (e.g. n = 0 to 2)
- quad[n].y' = (quad[n].y - line[0].y) * A - (quad[n].x - line[0].x) * O
-*/
- double adj = line[1].x - line[0].x;
- double opp = line[1].y - line[0].y;
- double r[3];
- for (int n = 0; n < 3; ++n) {
- r[n] = (quad[n].y - line[0].y) * adj - (quad[n].x - line[0].x) * opp;
- }
- double A = r[2];
- double B = r[1];
- double C = r[0];
- A += C - 2 * B; // A = a - 2*b + c
- B -= C; // B = -(b - c)
- return quadraticRootsValidT(A, 2 * B, C, roots);
-}
-
-int intersect() {
- addEndPoints();
- double rootVals[2];
- int roots = intersectRay(rootVals);
- for (int index = 0; index < roots; ++index) {
- double quadT = rootVals[index];
- double lineT = findLineT(quadT);
- if (pinTs(quadT, lineT)) {
- _Point pt;
- xy_at_t(line, lineT, pt.x, pt.y);
- intersections.insert(quadT, lineT, pt);
- }
- }
- return intersections.fUsed;
-}
-
-int horizontalIntersect(double axisIntercept, double roots[2]) {
- double D = quad[2].y; // f
- double E = quad[1].y; // e
- double F = quad[0].y; // d
- D += F - 2 * E; // D = d - 2*e + f
- E -= F; // E = -(d - e)
- F -= axisIntercept;
- return quadraticRootsValidT(D, 2 * E, F, roots);
-}
-
-int horizontalIntersect(double axisIntercept, double left, double right, bool flipped) {
- addHorizontalEndPoints(left, right, axisIntercept);
- double rootVals[2];
- int roots = horizontalIntersect(axisIntercept, rootVals);
- for (int index = 0; index < roots; ++index) {
- _Point pt;
- double quadT = rootVals[index];
- xy_at_t(quad, quadT, pt.x, pt.y);
- double lineT = (pt.x - left) / (right - left);
- if (pinTs(quadT, lineT)) {
- intersections.insert(quadT, lineT, pt);
- }
- }
- if (flipped) {
- flip();
- }
- return intersections.fUsed;
-}
-
-int verticalIntersect(double axisIntercept, double roots[2]) {
- double D = quad[2].x; // f
- double E = quad[1].x; // e
- double F = quad[0].x; // d
- D += F - 2 * E; // D = d - 2*e + f
- E -= F; // E = -(d - e)
- F -= axisIntercept;
- return quadraticRootsValidT(D, 2 * E, F, roots);
-}
-
-int verticalIntersect(double axisIntercept, double top, double bottom, bool flipped) {
- addVerticalEndPoints(top, bottom, axisIntercept);
- double rootVals[2];
- int roots = verticalIntersect(axisIntercept, rootVals);
- for (int index = 0; index < roots; ++index) {
- _Point pt;
- double quadT = rootVals[index];
- xy_at_t(quad, quadT, pt.x, pt.y);
- double lineT = (pt.y - top) / (bottom - top);
- if (pinTs(quadT, lineT)) {
- intersections.insert(quadT, lineT, pt);
- }
- }
- if (flipped) {
- flip();
- }
- return intersections.fUsed;
-}
-
-protected:
-
-// add endpoints first to get zero and one t values exactly
-void addEndPoints()
-{
- for (int qIndex = 0; qIndex < 3; qIndex += 2) {
- for (int lIndex = 0; lIndex < 2; lIndex++) {
- if (quad[qIndex] == line[lIndex]) {
- intersections.insert(qIndex >> 1, lIndex, line[lIndex]);
- }
- }
- }
-}
-
-void addHorizontalEndPoints(double left, double right, double y)
-{
- for (int qIndex = 0; qIndex < 3; qIndex += 2) {
- if (quad[qIndex].y != y) {
- continue;
- }
- if (quad[qIndex].x == left) {
- intersections.insert(qIndex >> 1, 0, quad[qIndex]);
- }
- if (quad[qIndex].x == right) {
- intersections.insert(qIndex >> 1, 1, quad[qIndex]);
- }
- }
-}
-
-void addVerticalEndPoints(double top, double bottom, double x)
-{
- for (int qIndex = 0; qIndex < 3; qIndex += 2) {
- if (quad[qIndex].x != x) {
- continue;
- }
- if (quad[qIndex].y == top) {
- intersections.insert(qIndex >> 1, 0, quad[qIndex]);
- }
- if (quad[qIndex].y == bottom) {
- intersections.insert(qIndex >> 1, 1, quad[qIndex]);
- }
- }
-}
-
-double findLineT(double t) {
- double x, y;
- xy_at_t(quad, t, x, y);
- double dx = line[1].x - line[0].x;
- double dy = line[1].y - line[0].y;
- if (fabs(dx) > fabs(dy)) {
- return (x - line[0].x) / dx;
- }
- return (y - line[0].y) / dy;
-}
-
-void flip() {
- // OPTIMIZATION: instead of swapping, pass original line, use [1].y - [0].y
- int roots = intersections.fUsed;
- for (int index = 0; index < roots; ++index) {
- intersections.fT[1][index] = 1 - intersections.fT[1][index];
- }
-}
-
-static bool pinTs(double& quadT, double& lineT) {
- if (!approximately_one_or_less(lineT)) {
- return false;
- }
- if (!approximately_zero_or_more(lineT)) {
- return false;
- }
- if (precisely_less_than_zero(quadT)) {
- quadT = 0;
- } else if (precisely_greater_than_one(quadT)) {
- quadT = 1;
- }
- if (precisely_less_than_zero(lineT)) {
- lineT = 0;
- } else if (precisely_greater_than_one(lineT)) {
- lineT = 1;
- }
- return true;
-}
-
-private:
-
-const Quadratic& quad;
-const _Line& line;
-Intersections& intersections;
-};
-
-// utility for pairs of coincident quads
-static double horizontalIntersect(const Quadratic& quad, const _Point& pt) {
- LineQuadraticIntersections q(quad, *((_Line*) 0), *((Intersections*) 0));
- double rootVals[2];
- int roots = q.horizontalIntersect(pt.y, rootVals);
- for (int index = 0; index < roots; ++index) {
- double x;
- double t = rootVals[index];
- xy_at_t(quad, t, x, *(double*) 0);
- if (AlmostEqualUlps(x, pt.x)) {
- return t;
- }
- }
- return -1;
-}
-
-static double verticalIntersect(const Quadratic& quad, const _Point& pt) {
- LineQuadraticIntersections q(quad, *((_Line*) 0), *((Intersections*) 0));
- double rootVals[2];
- int roots = q.verticalIntersect(pt.x, rootVals);
- for (int index = 0; index < roots; ++index) {
- double y;
- double t = rootVals[index];
- xy_at_t(quad, t, *(double*) 0, y);
- if (AlmostEqualUlps(y, pt.y)) {
- return t;
- }
- }
- return -1;
-}
-
-double axialIntersect(const Quadratic& q1, const _Point& p, bool vertical) {
- if (vertical) {
- return verticalIntersect(q1, p);
- }
- return horizontalIntersect(q1, p);
-}
-
-int horizontalIntersect(const Quadratic& quad, double left, double right,
- double y, double tRange[2]) {
- LineQuadraticIntersections q(quad, *((_Line*) 0), *((Intersections*) 0));
- double rootVals[2];
- int result = q.horizontalIntersect(y, rootVals);
- int tCount = 0;
- for (int index = 0; index < result; ++index) {
- double x, y;
- xy_at_t(quad, rootVals[index], x, y);
- if (x < left || x > right) {
- continue;
- }
- tRange[tCount++] = rootVals[index];
- }
- return tCount;
-}
-
-int horizontalIntersect(const Quadratic& quad, double left, double right, double y,
- bool flipped, Intersections& intersections) {
- LineQuadraticIntersections q(quad, *((_Line*) 0), intersections);
- return q.horizontalIntersect(y, left, right, flipped);
-}
-
-int verticalIntersect(const Quadratic& quad, double top, double bottom, double x,
- bool flipped, Intersections& intersections) {
- LineQuadraticIntersections q(quad, *((_Line*) 0), intersections);
- return q.verticalIntersect(x, top, bottom, flipped);
-}
-
-int intersect(const Quadratic& quad, const _Line& line, Intersections& i) {
- LineQuadraticIntersections q(quad, line, i);
- return q.intersect();
-}
-
-int intersectRay(const Quadratic& quad, const _Line& line, Intersections& i) {
- LineQuadraticIntersections q(quad, line, i);
- return q.intersectRay(i.fT[0]);
-}
diff --git a/experimental/Intersection/LineQuadraticIntersection_Test.cpp b/experimental/Intersection/LineQuadraticIntersection_Test.cpp
deleted file mode 100644
index 3e7e230ac9..0000000000
--- a/experimental/Intersection/LineQuadraticIntersection_Test.cpp
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "CurveIntersection.h"
-#include "CurveUtilities.h"
-#include "EdgeWalker_Test.h"
-#include "Intersection_Tests.h"
-#include "Intersections.h"
-#include "TestUtilities.h"
-
-struct lineQuad {
- Quadratic quad;
- _Line line;
- int result;
- _Point expected[2];
-} lineQuadTests[] = {
- // quad line results
- {{{1, 1}, {2, 1}, {0, 2}}, {{0, 0}, {1, 1}}, 1, {{1, 1} }},
- {{{0, 0}, {1, 1}, {3, 1}}, {{0, 0}, {3, 1}}, 2, {{0, 0}, {3, 1}}},
- {{{2, 0}, {1, 1}, {2, 2}}, {{0, 0}, {0, 2}}, 0 },
- {{{4, 0}, {0, 1}, {4, 2}}, {{3, 1}, {4, 1}}, 0, },
- {{{0, 0}, {0, 1}, {1, 1}}, {{0, 1}, {1, 0}}, 1, {{.25, .75} }},
-};
-
-size_t lineQuadTests_count = sizeof(lineQuadTests) / sizeof(lineQuadTests[0]);
-
-const int firstLineQuadIntersectionTest = 0;
-
-static int doIntersect(Intersections& intersections, const Quadratic& quad, const _Line& line, bool& flipped) {
- int result;
- flipped = false;
- if (line[0].x == line[1].x) {
- double top = line[0].y;
- double bottom = line[1].y;
- flipped = top > bottom;
- if (flipped) {
- SkTSwap<double>(top, bottom);
- }
- result = verticalIntersect(quad, top, bottom, line[0].x, flipped, intersections);
- } else if (line[0].y == line[1].y) {
- double left = line[0].x;
- double right = line[1].x;
- flipped = left > right;
- if (flipped) {
- SkTSwap<double>(left, right);
- }
- result = horizontalIntersect(quad, left, right, line[0].y, flipped, intersections);
- } else {
- intersect(quad, line, intersections);
- result = intersections.fUsed;
- }
- return result;
-}
-
-static struct oneLineQuad {
- Quadratic quad;
- _Line line;
-} oneOffs[] = {
- {{{369.848602,145.680267}, {382.360413,121.298294}, {406.207703,121.298294}},
- {{406.207703,121.298294}, {348.781738,123.864815}}}
- };
-
-static size_t oneOffs_count = sizeof(oneOffs) / sizeof(oneOffs[0]);
-
-
-static void testOneOffs() {
- Intersections intersections;
- bool flipped = false;
- for (size_t index = 0; index < oneOffs_count; ++index) {
- const Quadratic& quad = oneOffs[index].quad;
- const _Line& line = oneOffs[index].line;
- int result = doIntersect(intersections, quad, line, flipped);
- for (int inner = 0; inner < result; ++inner) {
- double quadT = intersections.fT[0][inner];
- double quadX, quadY;
- xy_at_t(quad, quadT, quadX, quadY);
- double lineT = intersections.fT[1][inner];
- double lineX, lineY;
- xy_at_t(line, lineT, lineX, lineY);
- SkASSERT(AlmostEqualUlps(quadX, lineX)
- && AlmostEqualUlps(quadY, lineY));
- }
- }
-}
-
-void LineQuadraticIntersection_Test() {
- if (1) {
- testOneOffs();
- }
- for (size_t index = firstLineQuadIntersectionTest; index < lineQuadTests_count; ++index) {
- const Quadratic& quad = lineQuadTests[index].quad;
- const _Line& line = lineQuadTests[index].line;
- Quadratic reduce1;
- _Line reduce2;
- int order1 = reduceOrder(quad, reduce1, kReduceOrder_TreatAsFill);
- int order2 = reduceOrder(line, reduce2);
- if (order1 < 3) {
- SkDebugf("%s [%d] quad order=%d\n", __FUNCTION__, (int) index, order1);
- SkASSERT(0);
- }
- if (order2 < 2) {
- SkDebugf("%s [%d] line order=%d\n", __FUNCTION__, (int) index, order2);
- SkASSERT(0);
- }
- Intersections intersections;
- bool flipped = false;
- int result = doIntersect(intersections, quad, line, flipped);
- SkASSERT(result == lineQuadTests[index].result);
- if (!intersections.intersected()) {
- continue;
- }
- for (int pt = 0; pt < result; ++pt) {
- double tt1 = intersections.fT[0][pt];
- SkASSERT(tt1 >= 0 && tt1 <= 1);
- _Point t1, t2;
- xy_at_t(quad, tt1, t1.x, t1.y);
- double tt2 = intersections.fT[1][pt];
- SkASSERT(tt2 >= 0 && tt2 <= 1);
- xy_at_t(line, tt2, t2.x, t2.y);
- if (!AlmostEqualUlps(t1.x, t2.x)) {
- SkDebugf("%s [%d,%d] x!= t1=%1.9g (%1.9g,%1.9g) t2=%1.9g (%1.9g,%1.9g)\n",
- __FUNCTION__, (int)index, pt, tt1, t1.x, t1.y, tt2, t2.x, t2.y);
- SkASSERT(0);
- }
- if (!AlmostEqualUlps(t1.y, t2.y)) {
- SkDebugf("%s [%d,%d] y!= t1=%1.9g (%1.9g,%1.9g) t2=%1.9g (%1.9g,%1.9g)\n",
- __FUNCTION__, (int)index, pt, tt1, t1.x, t1.y, tt2, t2.x, t2.y);
- SkASSERT(0);
- }
- if (!t1.approximatelyEqual(lineQuadTests[index].expected[0])
- && (lineQuadTests[index].result == 1
- || !t1.approximatelyEqual(lineQuadTests[index].expected[1]))) {
- SkDebugf("%s t1=(%1.9g,%1.9g)\n", __FUNCTION__, t1.x, t1.y);
- SkASSERT(0);
- }
- }
- }
-}
-
-static void testLineIntersect(State4& state, const Quadratic& quad, const _Line& line,
- const double x, const double y) {
- char pathStr[1024];
- bzero(pathStr, sizeof(pathStr));
- char* str = pathStr;
- str += sprintf(str, " path.moveTo(%1.9g, %1.9g);\n", quad[0].x, quad[0].y);
- str += sprintf(str, " path.quadTo(%1.9g, %1.9g, %1.9g, %1.9g);\n", quad[1].x, quad[1].y, quad[2].x, quad[2].y);
- str += sprintf(str, " path.moveTo(%1.9g, %1.9g);\n", line[0].x, line[0].y);
- str += sprintf(str, " path.lineTo(%1.9g, %1.9g);\n", line[1].x, line[1].y);
-
- Intersections intersections;
- bool flipped = false;
- int result = doIntersect(intersections, quad, line, flipped);
- bool found = false;
- for (int index = 0; index < result; ++index) {
- double quadT = intersections.fT[0][index];
- double quadX, quadY;
- xy_at_t(quad, quadT, quadX, quadY);
- double lineT = intersections.fT[1][index];
- double lineX, lineY;
- xy_at_t(line, lineT, lineX, lineY);
- if (fabs(quadX - lineX) < FLT_EPSILON && fabs(quadY - lineY) < FLT_EPSILON
- && fabs(x - lineX) < FLT_EPSILON && fabs(y - lineY) < FLT_EPSILON) {
- found = true;
- }
- }
- SkASSERT(found);
- state.testsRun++;
-}
-
-
-// find a point on a quad by choosing a t from 0 to 1
-// create a vertical span above and below the point
-// verify that intersecting the vertical span and the quad returns t
-// verify that a vertical span starting at quad[0] intersects at t=0
-// verify that a vertical span starting at quad[2] intersects at t=1
-static void* testQuadLineIntersectMain(void* data)
-{
- SkASSERT(data);
- State4& state = *(State4*) data;
- do {
- int ax = state.a & 0x03;
- int ay = state.a >> 2;
- int bx = state.b & 0x03;
- int by = state.b >> 2;
- int cx = state.c & 0x03;
- int cy = state.c >> 2;
- Quadratic quad = {{ax, ay}, {bx, by}, {cx, cy}};
- Quadratic reduced;
- int order = reduceOrder(quad, reduced, kReduceOrder_TreatAsFill);
- if (order < 3) {
- continue; // skip degenerates
- }
- for (int tIndex = 0; tIndex <= 4; ++tIndex) {
- double x, y;
- xy_at_t(quad, tIndex / 4.0, x, y);
- for (int h = -2; h <= 2; ++h) {
- for (int v = -2; v <= 2; ++v) {
- if (h == v && abs(h) != 1) {
- continue;
- }
- _Line line = {{x - h, y - v}, {x, y}};
- testLineIntersect(state, quad, line, x, y);
- _Line line2 = {{x, y}, {x + h, y + v}};
- testLineIntersect(state, quad, line2, x, y);
- _Line line3 = {{x - h, y - v}, {x + h, y + v}};
- testLineIntersect(state, quad, line3, x, y);
- }
- }
- }
- } while (runNextTestSet(state));
- return NULL;
-}
-
-void QuadLineIntersectThreaded_Test(int& testsRun)
-{
- SkDebugf("%s\n", __FUNCTION__);
- const char testStr[] = "testQuadLineIntersect";
- initializeTests(testStr, sizeof(testStr));
- int testsStart = testsRun;
- for (int a = 0; a < 16; ++a) {
- for (int b = 0 ; b < 16; ++b) {
- for (int c = 0 ; c < 16; ++c) {
- testsRun += dispatchTest4(testQuadLineIntersectMain,
- a, b, c, 0);
- }
- if (!gRunTestsInOneThread) SkDebugf(".");
- }
- if (!gRunTestsInOneThread) SkDebugf("%d", a);
- }
- testsRun += waitForCompletion();
- SkDebugf("\n%s tests=%d total=%d\n", __FUNCTION__, testsRun - testsStart, testsRun);
-}
diff --git a/experimental/Intersection/LineUtilities.cpp b/experimental/Intersection/LineUtilities.cpp
deleted file mode 100644
index 53319c4560..0000000000
--- a/experimental/Intersection/LineUtilities.cpp
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "CurveIntersection.h"
-#include "LineUtilities.h"
-
-bool implicitLine(const _Line& line, double& slope, double& axisIntercept) {
- _Point delta;
- tangent(line, delta);
- bool moreHorizontal = fabs(delta.x) > fabs(delta.y);
- if (moreHorizontal) {
- slope = delta.y / delta.x;
- axisIntercept = line[0].y - slope * line[0].x;
- } else {
- slope = delta.x / delta.y;
- axisIntercept = line[0].x - slope * line[0].y;
- }
- return moreHorizontal;
-}
-
-int reduceOrder(const _Line& line, _Line& reduced) {
- reduced[0] = line[0];
- int different = line[0] != line[1];
- reduced[1] = line[different];
- return 1 + different;
-}
-
-void sub_divide(const _Line& line, double t1, double t2, _Line& dst) {
- _Point delta;
- tangent(line, delta);
- dst[0].x = line[0].x - t1 * delta.x;
- dst[0].y = line[0].y - t1 * delta.y;
- dst[1].x = line[0].x - t2 * delta.x;
- dst[1].y = line[0].y - t2 * delta.y;
-}
-
-// may have this below somewhere else already:
-// copying here because I thought it was clever
-
-// Copyright 2001, softSurfer (www.softsurfer.com)
-// This code may be freely used and modified for any purpose
-// providing that this copyright notice is included with it.
-// SoftSurfer makes no warranty for this code, and cannot be held
-// liable for any real or imagined damage resulting from its use.
-// Users of this code must verify correctness for their application.
-
-// Assume that a class is already given for the object:
-// Point with coordinates {float x, y;}
-//===================================================================
-
-// isLeft(): tests if a point is Left|On|Right of an infinite line.
-// Input: three points P0, P1, and P2
-// Return: >0 for P2 left of the line through P0 and P1
-// =0 for P2 on the line
-// <0 for P2 right of the line
-// See: the January 2001 Algorithm on Area of Triangles
-// return (float) ((P1.x - P0.x)*(P2.y - P0.y) - (P2.x - P0.x)*(P1.y - P0.y));
-double is_left(const _Line& line, const _Point& pt) {
- _Vector P0 = line[1] - line[0];
- _Vector P2 = pt - line[0];
- return P0.cross(P2);
-}
-
-double t_at(const _Line& line, const _Point& pt) {
- double dx = line[1].x - line[0].x;
- double dy = line[1].y - line[0].y;
- if (fabs(dx) > fabs(dy)) {
- if (approximately_zero(dx)) {
- return 0;
- }
- return (pt.x - line[0].x) / dx;
- }
- if (approximately_zero(dy)) {
- return 0;
- }
- return (pt.y - line[0].y) / dy;
-}
-
-static void setMinMax(double x, int flags, double& minX, double& maxX) {
- if (minX > x && (flags & (kFindTopMin | kFindBottomMin))) {
- minX = x;
- }
- if (maxX < x && (flags & (kFindTopMax | kFindBottomMax))) {
- maxX = x;
- }
-}
-
-void x_at(const _Point& p1, const _Point& p2, double top, double bottom,
- int flags, double& minX, double& maxX) {
- if (AlmostEqualUlps(p1.y, p2.y)) {
- // It should be OK to bail early in this case. There's another edge
- // which shares this end point which can intersect without failing to
- // have a slope ... maybe
- return;
- }
-
- // p2.x is always greater than p1.x -- the part of points (p1, p2) are
- // moving from the start of the cubic towards its end.
- // if p1.y < p2.y, minX can be affected
- // if p1.y > p2.y, maxX can be affected
- double slope = (p2.x - p1.x) / (p2.y - p1.y);
- int topFlags = flags & (kFindTopMin | kFindTopMax);
- if (topFlags && ((top <= p1.y && top >= p2.y)
- || (top >= p1.y && top <= p2.y))) {
- double x = p1.x + (top - p1.y) * slope;
- setMinMax(x, topFlags, minX, maxX);
- }
- int bottomFlags = flags & (kFindBottomMin | kFindBottomMax);
- if (bottomFlags && ((bottom <= p1.y && bottom >= p2.y)
- || (bottom >= p1.y && bottom <= p2.y))) {
- double x = p1.x + (bottom - p1.y) * slope;
- setMinMax(x, bottomFlags, minX, maxX);
- }
-}
-
-void xy_at_t(const _Line& line, double t, double& x, double& y) {
- double one_t = 1 - t;
- if (&x) {
- x = one_t * line[0].x + t * line[1].x;
- }
- if (&y) {
- y = one_t * line[0].y + t * line[1].y;
- }
-}
-
-_Point xy_at_t(const _Line& line, double t) {
- double one_t = 1 - t;
- _Point result = { one_t * line[0].x + t * line[1].x, one_t * line[0].y + t * line[1].y };
- return result;
-}
diff --git a/experimental/Intersection/LineUtilities.h b/experimental/Intersection/LineUtilities.h
deleted file mode 100644
index d1d4570769..0000000000
--- a/experimental/Intersection/LineUtilities.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "DataTypes.h"
-
-bool implicitLine(const _Line& line, double& slope, double& axisIntercept);
-int reduceOrder(const _Line& line, _Line& reduced);
-double is_left(const _Line& line, const _Point& pt);
-void sub_divide(const _Line& src, double t1, double t2, _Line& dst);
-double t_at(const _Line&, const _Point& );
-void xy_at_t(const _Line& , double t, double& x, double& y);
-_Point xy_at_t(const _Line& , double t);
-
-enum x_at_flags {
- kFindTopMin = 1,
- kFindTopMax = 2,
- kFindBottomMin = 4,
- kFindBottomMax = 8
-};
-
-void x_at(const _Point& p1, const _Point& p2, double minY, double maxY,
- int flags, double& tMin, double& tMax);
diff --git a/experimental/Intersection/LogoPlay.cpp b/experimental/Intersection/LogoPlay.cpp
deleted file mode 100644
index 718da38bd3..0000000000
--- a/experimental/Intersection/LogoPlay.cpp
+++ /dev/null
@@ -1,353 +0,0 @@
-#include <ctype.h>
-#include "SkPath.h"
-#include "SkParse.h"
-#include "SkPoint.h"
-#include "SkUtils.h"
-#define QUADRATIC_APPROXIMATION 0
-
-const char logoStr[] =
- "<path fill=\"#0081C6\""
- "d=\"M440.51,289.479c1.623,1.342,5.01,4.164,5.01,9.531c0,5.223-2.965,7.697-5.93,10.024"
- "c-0.918,0.916-1.977,1.907-1.977,3.462c0,1.551,1.059,2.397,1.834,3.035l2.545,1.973c3.105,2.613,5.928,5.016,5.928,9.889"
- "c0,6.635-6.426,13.341-18.566,13.341c-10.238,0-15.178-4.87-15.178-10.097c0-2.543,1.268-6.139,5.438-8.613"
- "c4.373-2.682,10.307-3.033,13.482-3.249c-0.99-1.271-2.119-2.61-2.119-4.798c0-1.199,0.355-1.907,0.707-2.754"
- "c-0.779,0.07-1.553,0.141-2.26,0.141c-7.482,0-11.719-5.579-11.719-11.082c0-3.247,1.484-6.851,4.518-9.461"
- "c4.025-3.318,8.824-3.883,12.639-3.883h14.541l-4.518,2.541H440.51z"
- "M435.494,320.826c-0.562-0.072-0.916-0.072-1.619-0.072"
- "c-0.637,0-4.451,0.143-7.416,1.132c-1.553,0.564-6.07,2.257-6.07,7.271c0,5.013,4.873,8.615,12.426,8.615"
- "c6.775,0,10.379-3.253,10.379-7.624C443.193,326.54,440.863,324.64,435.494,320.826z"
- "M437.543,307.412"
- "c1.623-1.627,1.764-3.883,1.764-5.154c0-5.083-3.035-12.99-8.893-12.99c-1.838,0-3.812,0.918-4.945,2.331"
- "c-1.199,1.483-1.551,3.387-1.551,5.225c0,4.729,2.754,12.565,8.826,12.565C434.508,309.389,436.41,308.543,437.543,307.412z\"/>"
- "<path fill=\"#FFD200\""
- "d=\"M396.064,319.696c-11.206,0-17.198-8.739-17.198-16.636c0-9.233,7.542-17.126,18.258-17.126"
- "c10.357,0,16.844,8.104,16.844,16.635C413.969,310.884,407.557,319.696,396.064,319.696z"
- "M404.873,313.987"
- "c1.695-2.257,2.119-5.074,2.119-7.826c0-6.202-2.961-18.042-11.701-18.042c-2.326,0-4.652,0.918-6.342,2.399"
- "c-2.749,2.465-3.245,5.566-3.245,8.599c0,6.977,3.454,18.463,11.984,18.463C400.436,317.58,403.256,316.242,404.873,313.987z\"/>"
- "<path fill=\"#ED174F\""
- "d=\"M357.861,319.696c-11.207,0-17.199-8.739-17.199-16.636c0-9.233,7.544-17.126,18.258-17.126"
- "c10.359,0,16.845,8.104,16.845,16.635C375.764,310.884,369.351,319.696,357.861,319.696z"
- "M366.671,313.987"
- "c1.693-2.257,2.116-5.074,2.116-7.826c0-6.202-2.961-18.042-11.701-18.042c-2.325,0-4.652,0.918-6.344,2.399"
- "c-2.749,2.465-3.241,5.566-3.241,8.599c0,6.977,3.452,18.463,11.983,18.463C362.234,317.58,365.053,316.242,366.671,313.987z\"/>"
- "<path fill=\"#0081C6\""
- "d=\"M335.278,318.591l-10.135,2.339c-4.111,0.638-7.795,1.204-11.69,1.204"
- "c-19.56,0-26.998-14.386-26.998-25.654c0-13.746,10.558-26.498,28.629-26.498c3.827,0,7.51,0.564,10.839,1.486"
- "c5.316,1.488,7.796,3.331,9.355,4.394l-5.883,5.599l-2.479,0.565l1.771-2.837c-2.408-2.336-6.805-6.658-15.164-6.658"
- "c-11.196,0-19.63,8.507-19.63,20.906c0,13.319,9.638,25.861,25.084,25.861c4.539,0,6.874-0.918,9-1.771v-11.407l-10.698,0.566"
- "l5.667-3.047h15.023l-1.841,1.77c-0.5,0.424-0.567,0.57-0.71,1.133c-0.073,0.64-0.141,2.695-0.141,3.403V318.591z\"/>"
- "<path fill=\"#49A942\""
- "d=\"M462.908,316.552c-2.342-0.214-2.832-0.638-2.832-3.401v-0.782v-39.327c0.014-0.153,0.025-0.31,0.041-0.457"
- "c0.283-2.479,0.992-2.903,3.189-4.182h-10.135l-5.316,2.552h5.418v0.032l-0.004-0.024v41.406v2.341"
- "c0,1.416-0.281,1.629-1.912,3.753H463.9l2.623-1.557C465.318,316.763,464.113,316.692,462.908,316.552z\"/>"
- "<path fill=\"#ED174F\""
- "d=\"M491.742,317.203c-0.771,0.422-1.547,0.916-2.318,1.268c-2.326,1.055-4.719,1.336-6.83,1.336"
- "c-2.25,0-5.77-0.143-9.361-2.744c-4.992-3.521-7.176-9.572-7.176-14.851c0-10.906,8.869-16.255,16.115-16.255"
- "c2.533,0,5.141,0.633,7.252,1.972c3.516,2.318,4.43,5.344,4.922,6.963l-16.535,6.688l-5.422,0.422"
- "c1.758,8.938,7.812,14.145,14.498,14.145c3.59,0,6.193-1.266,8.586-2.461L491.742,317.203z"
- "M485.129,296.229"
- "c1.336-0.493,2.039-0.914,2.039-1.899c0-2.812-3.166-6.053-6.967-6.053c-2.818,0-8.094,2.183-8.094,9.783"
- "c0,1.197,0.141,2.464,0.213,3.73L485.129,296.229z\"/>"
- "<path fill=\"#77787B\""
- "d=\"M498.535,286.439v4.643h-0.564v-4.643h-1.537v-0.482h3.637v0.482H498.535z\"/>"
- "<path fill=\"#77787B\""
- "d=\"M504.863,291.082v-4.687h-0.023l-1.432,4.687h-0.439l-1.443-4.687h-0.02v4.687h-0.512v-5.125h0.877"
- "l1.307,4.143h0.018l1.285-4.143h0.891v5.125H504.863z\"/>"
-;
-
-size_t logoStrLen = sizeof(logoStr);
-
-#if QUADRATIC_APPROXIMATION
-////////////////////////////////////////////////////////////////////////////////////
-//functions to approximate a cubic using two quadratics
-
-// midPt sets the first argument to be the midpoint of the other two
-// it is used by quadApprox
-static inline void midPt(SkPoint& dest,const SkPoint& a,const SkPoint& b)
-{
- dest.set(SkScalarAve(a.fX, b.fX),SkScalarAve(a.fY, b.fY));
-}
-// quadApprox - makes an approximation, which we hope is faster
-static void quadApprox(SkPath &fPath, const SkPoint &p0, const SkPoint &p1, const SkPoint &p2)
-{
- //divide the cubic up into two cubics, then convert them into quadratics
- //define our points
- SkPoint c,j,k,l,m,n,o,p,q, mid;
- fPath.getLastPt(&c);
- midPt(j, p0, c);
- midPt(k, p0, p1);
- midPt(l, p1, p2);
- midPt(o, j, k);
- midPt(p, k, l);
- midPt(q, o, p);
- //compute the first half
- m.set(SkScalarHalf(3*j.fX - c.fX), SkScalarHalf(3*j.fY - c.fY));
- n.set(SkScalarHalf(3*o.fX -q.fX), SkScalarHalf(3*o.fY - q.fY));
- midPt(mid,m,n);
- fPath.quadTo(mid,q);
- c = q;
- //compute the second half
- m.set(SkScalarHalf(3*p.fX - c.fX), SkScalarHalf(3*p.fY - c.fY));
- n.set(SkScalarHalf(3*l.fX -p2.fX),SkScalarHalf(3*l.fY -p2.fY));
- midPt(mid,m,n);
- fPath.quadTo(mid,p2);
-}
-#endif
-
-
-static inline bool is_between(int c, int min, int max)
-{
- return (unsigned)(c - min) <= (unsigned)(max - min);
-}
-
-static inline bool is_ws(int c)
-{
- return is_between(c, 1, 32);
-}
-
-static inline bool is_digit(int c)
-{
- return is_between(c, '0', '9');
-}
-
-static inline bool is_sep(int c)
-{
- return is_ws(c) || c == ',';
-}
-
-static const char* skip_ws(const char str[])
-{
- SkASSERT(str);
- while (is_ws(*str))
- str++;
- return str;
-}
-
-static const char* skip_sep(const char str[])
-{
- SkASSERT(str);
- while (is_sep(*str))
- str++;
- return str;
-}
-
-static const char* find_points(const char str[], SkPoint value[], int count,
- bool isRelative, SkPoint* relative)
-{
- str = SkParse::FindScalars(str, &value[0].fX, count * 2);
- if (isRelative) {
- for (int index = 0; index < count; index++) {
- value[index].fX += relative->fX;
- value[index].fY += relative->fY;
- }
- }
- return str;
-}
-
-static const char* find_scalar(const char str[], SkScalar* value,
- bool isRelative, SkScalar relative)
-{
- str = SkParse::FindScalar(str, value);
- if (isRelative)
- *value += relative;
- return str;
-}
-
-static void showPathContour(SkPath::Iter& iter) {
- uint8_t verb;
- SkPoint pts[4];
- while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
- switch (verb) {
- case SkPath::kMove_Verb:
- SkDebugf("path.moveTo(%1.9gf,%1.9gf);\n", pts[0].fX, pts[0].fY);
- continue;
- case SkPath::kLine_Verb:
- SkDebugf("path.lineTo(%1.9gf,%1.9gf);\n", pts[1].fX, pts[1].fY);
- break;
- case SkPath::kQuad_Verb:
- SkDebugf("path.quadTo(%1.9gf,%1.9gf, %1.9gf,%1.9gf);\n",
- pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY);
- break;
- case SkPath::kCubic_Verb:
- SkDebugf("path.cubicTo(%1.9gf,%1.9gf, %1.9gf,%1.9gf, %1.9gf,%1.9gf);\n",
- pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY, pts[3].fX, pts[3].fY);
- break;
- case SkPath::kClose_Verb:
- SkDebugf("path.close();\n");
- break;
- default:
- SkDEBUGFAIL("bad verb");
- return;
- }
- }
-}
-
-static void showPath(const SkPath& path) {
- SkPath::Iter iter(path, true);
- int rectCount = path.isRectContours() ? path.rectContours(NULL, NULL) : 0;
- if (rectCount > 0) {
- SkTDArray<SkRect> rects;
- SkTDArray<SkPath::Direction> directions;
- rects.setCount(rectCount);
- directions.setCount(rectCount);
- path.rectContours(rects.begin(), directions.begin());
- for (int contour = 0; contour < rectCount; ++contour) {
- const SkRect& rect = rects[contour];
- SkDebugf("path.addRect(%1.9g, %1.9g, %1.9g, %1.9g, %s);\n", rect.fLeft, rect.fTop,
- rect.fRight, rect.fBottom, directions[contour] == SkPath::kCCW_Direction
- ? "SkPath::kCCW_Direction" : "SkPath::kCW_Direction");
- }
- return;
- }
- iter.setPath(path, true);
- showPathContour(iter);
-}
-
-static const char* parsePath(const char* data) {
- SkPath fPath;
- SkPoint f = {0, 0};
- SkPoint c = {0, 0};
- SkPoint lastc = {0, 0};
- SkPoint points[3];
- char op = '\0';
- char previousOp = '\0';
- bool relative = false;
- do {
- data = skip_ws(data);
- if (data[0] == '\0')
- break;
- char ch = data[0];
- if (is_digit(ch) || ch == '-' || ch == '+') {
- if (op == '\0') {
- SkASSERT(0);
- return 0;
- }
- }
- else {
- op = ch;
- relative = false;
- if (islower(op)) {
- op = (char) toupper(op);
- relative = true;
- }
- data++;
- data = skip_sep(data);
- }
- switch (op) {
- case 'M':
- data = find_points(data, points, 1, relative, &c);
- fPath.moveTo(points[0]);
- op = 'L';
- c = points[0];
- break;
- case 'L':
- data = find_points(data, points, 1, relative, &c);
- fPath.lineTo(points[0]);
- c = points[0];
- break;
- case 'H': {
- SkScalar x;
- data = find_scalar(data, &x, relative, c.fX);
- fPath.lineTo(x, c.fY);
- c.fX = x;
- }
- break;
- case 'V': {
- SkScalar y;
- data = find_scalar(data, &y, relative, c.fY);
- fPath.lineTo(c.fX, y);
- c.fY = y;
- }
- break;
- case 'C':
- data = find_points(data, points, 3, relative, &c);
- goto cubicCommon;
- case 'S':
- data = find_points(data, &points[1], 2, relative, &c);
- points[0] = c;
- if (previousOp == 'C' || previousOp == 'S') {
- points[0].fX -= lastc.fX - c.fX;
- points[0].fY -= lastc.fY - c.fY;
- }
- cubicCommon:
- // if (data[0] == '\0')
- // return;
-#if QUADRATIC_APPROXIMATION
- quadApprox(fPath, points[0], points[1], points[2]);
-#else //this way just does a boring, slow old cubic
- fPath.cubicTo(points[0], points[1], points[2]);
-#endif
- //if we are using the quadApprox, lastc is what it would have been if we had used
- //cubicTo
- lastc = points[1];
- c = points[2];
- break;
- case 'Q': // Quadratic Bezier Curve
- data = find_points(data, points, 2, relative, &c);
- goto quadraticCommon;
- case 'T':
- data = find_points(data, &points[1], 1, relative, &c);
- points[0] = points[1];
- if (previousOp == 'Q' || previousOp == 'T') {
- points[0].fX = c.fX * 2 - lastc.fX;
- points[0].fY = c.fY * 2 - lastc.fY;
- }
- quadraticCommon:
- fPath.quadTo(points[0], points[1]);
- lastc = points[0];
- c = points[1];
- break;
- case 'Z':
- fPath.close();
-#if 0 // !!! still a bug?
- if (fPath.isEmpty() && (f.fX != 0 || f.fY != 0)) {
- c.fX -= SkScalar.Epsilon; // !!! enough?
- fPath.moveTo(c);
- fPath.lineTo(f);
- fPath.close();
- }
-#endif
- c = f;
- op = '\0';
- break;
- case '~': {
- SkPoint args[2];
- data = find_points(data, args, 2, false, NULL);
- fPath.moveTo(args[0].fX, args[0].fY);
- fPath.lineTo(args[1].fX, args[1].fY);
- }
- break;
- default:
- SkASSERT(0);
- return 0;
- }
- if (previousOp == 0)
- f = c;
- previousOp = op;
- } while (data[0] != '"');
- showPath(fPath);
- return data;
-}
-
-const char pathPrefix[] = "<path fill=\"";
-
-void parseSVG();
-void parseSVG() {
- const char* data = logoStr;
- const char* dataEnd = logoStr + logoStrLen - 1;
- while (data < dataEnd) {
- SkASSERT(strncmp(data, pathPrefix, sizeof(pathPrefix) - 1) == 0);
- data += sizeof(pathPrefix) - 1;
- SkDebugf("paint.setColor(0xFF%c%c%c%c%c%c);\n", data[1], data[2], data[3], data[4],
- data[5], data[6]);
- data += 8;
- SkASSERT(strncmp(data, "d=\"", 3) == 0);
- data += 3;
- SkDebugf("path.reset();\n");
- data = parsePath(data);
- SkDebugf("canvas->drawPath(path, paint);\n");
- SkASSERT(strncmp(data, "\"/>", 3) == 0);
- data += 3;
- }
-}
diff --git a/experimental/Intersection/MiniSimplify_Test.cpp b/experimental/Intersection/MiniSimplify_Test.cpp
deleted file mode 100644
index 3cb90ab927..0000000000
--- a/experimental/Intersection/MiniSimplify_Test.cpp
+++ /dev/null
@@ -1,99 +0,0 @@
-#include "EdgeWalker_Test.h"
-#include "Intersection_Tests.h"
-#include "ShapeOps.h"
-
-bool gShowOriginal = true;
-
-struct curve {
- SkPath::Verb verb;
- SkPoint pts[4];
-};
-
-struct curve test1[] = {
-{SkPath::kQuad_Verb, {{366.608826f, 151.196014f}, {378.803101f, 136.674606f}, {398.164948f, 136.674606f}}},
-{SkPath::kLine_Verb, {{354.009216f, 208.816208f}, {393.291473f, 102.232819f}}},
-{SkPath::kQuad_Verb, {{359.978058f, 136.581512f}, {378.315979f, 136.581512f}, {388.322723f, 149.613556f}}},
-{SkPath::kQuad_Verb, {{364.390686f, 157.898193f}, {375.281769f, 136.674606f}, {396.039917f, 136.674606f}}},
-{SkPath::kLine_Verb, {{396.039917f, 136.674606f}, {350, 120}}},
-{SkPath::kDone_Verb}
-};
-
-struct curve test2[] = {
-{SkPath::kQuad_Verb, {{366.608826f, 151.196014f}, {378.803101f, 136.674606f}, {398.164948f, 136.674606f}}},
-{SkPath::kQuad_Verb, {{359.978058f, 136.581512f}, {378.315979f, 136.581512f}, {388.322723f, 149.613556f}}},
-{SkPath::kQuad_Verb, {{364.390686f, 157.898193f}, {375.281769f, 136.674606f}, {396.039917f, 136.674606f}}},
-{SkPath::kDone_Verb}
-};
-
-struct curve* testSet[] = {
- test2,
- test1
-};
-
-size_t testSet_count = sizeof(testSet) / sizeof(testSet[0]);
-
-static void construct() {
- for (size_t idx = 0; idx < testSet_count; ++idx) {
- const curve* test = testSet[idx];
- SkPath path;
- bool pathComplete = false;
- bool first = true;
- do {
- if (first) {
- path.moveTo(test->pts[0].fX, test->pts[0].fY);
- first = false;
- } else if (test->verb != SkPath::kDone_Verb) {
- path.lineTo(test->pts[0].fX, test->pts[0].fY);
- }
- switch (test->verb) {
- case SkPath::kDone_Verb:
- pathComplete = true;
- break;
- case SkPath::kLine_Verb:
- path.lineTo(test->pts[1].fX, test->pts[1].fY);
- break;
- case SkPath::kQuad_Verb:
- path.quadTo(test->pts[1].fX, test->pts[1].fY, test->pts[2].fX, test->pts[2].fY);
- break;
- case SkPath::kCubic_Verb:
- path.cubicTo(test->pts[1].fX, test->pts[1].fY, test->pts[2].fX, test->pts[2].fY, test->pts[3].fX, test->pts[3].fY);
- break;
- default:
- SkASSERT(0);
- }
- test++;
- } while (!pathComplete);
- path.close();
- if (gShowOriginal) {
- showPath(path, NULL);
- SkDebugf("simplified:\n");
- }
- testSimplifyx(path);
- }
-}
-
-static void (*tests[])() = {
- construct,
-};
-
-static const size_t testCount = sizeof(tests) / sizeof(tests[0]);
-
-static void (*firstTest)() = 0;
-static bool skipAll = false;
-
-void MiniSimplify_Test() {
- if (skipAll) {
- return;
- }
- size_t index = 0;
- if (firstTest) {
- while (index < testCount && tests[index] != firstTest) {
- ++index;
- }
- }
- bool firstTestComplete = false;
- for ( ; index < testCount; ++index) {
- (*tests[index])();
- firstTestComplete = true;
- }
-}
diff --git a/experimental/Intersection/NearestPoint.cpp b/experimental/Intersection/NearestPoint.cpp
deleted file mode 100644
index 2b3c11d20a..0000000000
--- a/experimental/Intersection/NearestPoint.cpp
+++ /dev/null
@@ -1,473 +0,0 @@
-/*
-Solving the Nearest Point-on-Curve Problem
-and
-A Bezier Curve-Based Root-Finder
-by Philip J. Schneider
-from "Graphics Gems", Academic Press, 1990
-*/
-
- /* point_on_curve.c */
-
-#include <stdio.h>
-#include <malloc.h>
-#include <math.h>
-#include "GraphicsGems.h"
-
-#define TESTMODE
-
-/*
- * Forward declarations
- */
-Point2 NearestPointOnCurve();
-static int FindRoots();
-static Point2 *ConvertToBezierForm();
-static double ComputeXIntercept();
-static int ControlPolygonFlatEnough();
-static int CrossingCount();
-static Point2 Bezier();
-static Vector2 V2ScaleII();
-
-int MAXDEPTH = 64; /* Maximum depth for recursion */
-
-#define EPSILON (ldexp(1.0,-MAXDEPTH-1)) /*Flatness control value */
-#define DEGREE 3 /* Cubic Bezier curve */
-#define W_DEGREE 5 /* Degree of eqn to find roots of */
-
-#ifdef TESTMODE
-/*
- * main :
- * Given a cubic Bezier curve (i.e., its control points), and some
- * arbitrary point in the plane, find the point on the curve
- * closest to that arbitrary point.
- */
-main()
-{
-
- static Point2 bezCurve[4] = { /* A cubic Bezier curve */
- { 0.0, 0.0 },
- { 1.0, 2.0 },
- { 3.0, 3.0 },
- { 4.0, 2.0 },
- };
- static Point2 arbPoint = { 3.5, 2.0 }; /*Some arbitrary point*/
- Point2 pointOnCurve; /* Nearest point on the curve */
-
- /* Find the closest point */
- pointOnCurve = NearestPointOnCurve(arbPoint, bezCurve);
- printf("pointOnCurve : (%4.4f, %4.4f)\n", pointOnCurve.x,
- pointOnCurve.y);
-}
-#endif /* TESTMODE */
-
-
-/*
- * NearestPointOnCurve :
- * Compute the parameter value of the point on a Bezier
- * curve segment closest to some arbtitrary, user-input point.
- * Return the point on the curve at that parameter value.
- *
- */
-Point2 NearestPointOnCurve(P, V)
- Point2 P; /* The user-supplied point */
- Point2 *V; /* Control points of cubic Bezier */
-{
- Point2 *w; /* Ctl pts for 5th-degree eqn */
- double t_candidate[W_DEGREE]; /* Possible roots */
- int n_solutions; /* Number of roots found */
- double t; /* Parameter value of closest pt*/
-
- /* Convert problem to 5th-degree Bezier form */
- w = ConvertToBezierForm(P, V);
-
- /* Find all possible roots of 5th-degree equation */
- n_solutions = FindRoots(w, W_DEGREE, t_candidate, 0);
- free((char *)w);
-
- /* Compare distances of P to all candidates, and to t=0, and t=1 */
- {
- double dist, new_dist;
- Point2 p;
- Vector2 v;
- int i;
-
-
- /* Check distance to beginning of curve, where t = 0 */
- dist = V2SquaredLength(V2Sub(&P, &V[0], &v));
- t = 0.0;
-
- /* Find distances for candidate points */
- for (i = 0; i < n_solutions; i++) {
- p = Bezier(V, DEGREE, t_candidate[i],
- (Point2 *)NULL, (Point2 *)NULL);
- new_dist = V2SquaredLength(V2Sub(&P, &p, &v));
- if (new_dist < dist) {
- dist = new_dist;
- t = t_candidate[i];
- }
- }
-
- /* Finally, look at distance to end point, where t = 1.0 */
- new_dist = V2SquaredLength(V2Sub(&P, &V[DEGREE], &v));
- if (new_dist < dist) {
- dist = new_dist;
- t = 1.0;
- }
- }
-
- /* Return the point on the curve at parameter value t */
- printf("t : %4.12f\n", t);
- return (Bezier(V, DEGREE, t, (Point2 *)NULL, (Point2 *)NULL));
-}
-
-
-/*
- * ConvertToBezierForm :
- * Given a point and a Bezier curve, generate a 5th-degree
- * Bezier-format equation whose solution finds the point on the
- * curve nearest the user-defined point.
- */
-static Point2 *ConvertToBezierForm(P, V)
- Point2 P; /* The point to find t for */
- Point2 *V; /* The control points */
-{
- int i, j, k, m, n, ub, lb;
- int row, column; /* Table indices */
- Vector2 c[DEGREE+1]; /* V(i)'s - P */
- Vector2 d[DEGREE]; /* V(i+1) - V(i) */
- Point2 *w; /* Ctl pts of 5th-degree curve */
- double cdTable[3][4]; /* Dot product of c, d */
- static double z[3][4] = { /* Precomputed "z" for cubics */
- {1.0, 0.6, 0.3, 0.1},
- {0.4, 0.6, 0.6, 0.4},
- {0.1, 0.3, 0.6, 1.0},
- };
-
-
- /*Determine the c's -- these are vectors created by subtracting*/
- /* point P from each of the control points */
- for (i = 0; i <= DEGREE; i++) {
- V2Sub(&V[i], &P, &c[i]);
- }
- /* Determine the d's -- these are vectors created by subtracting*/
- /* each control point from the next */
- for (i = 0; i <= DEGREE - 1; i++) {
- d[i] = V2ScaleII(V2Sub(&V[i+1], &V[i], &d[i]), 3.0);
- }
-
- /* Create the c,d table -- this is a table of dot products of the */
- /* c's and d's */
- for (row = 0; row <= DEGREE - 1; row++) {
- for (column = 0; column <= DEGREE; column++) {
- cdTable[row][column] = V2Dot(&d[row], &c[column]);
- }
- }
-
- /* Now, apply the z's to the dot products, on the skew diagonal*/
- /* Also, set up the x-values, making these "points" */
- w = (Point2 *)malloc((unsigned)(W_DEGREE+1) * sizeof(Point2));
- for (i = 0; i <= W_DEGREE; i++) {
- w[i].y = 0.0;
- w[i].x = (double)(i) / W_DEGREE;
- }
-
- n = DEGREE;
- m = DEGREE-1;
- for (k = 0; k <= n + m; k++) {
- lb = MAX(0, k - m);
- ub = MIN(k, n);
- for (i = lb; i <= ub; i++) {
- j = k - i;
- w[i+j].y += cdTable[j][i] * z[j][i];
- }
- }
-
- return (w);
-}
-
-
-/*
- * FindRoots :
- * Given a 5th-degree equation in Bernstein-Bezier form, find
- * all of the roots in the interval [0, 1]. Return the number
- * of roots found.
- */
-static int FindRoots(w, degree, t, depth)
- Point2 *w; /* The control points */
- int degree; /* The degree of the polynomial */
- double *t; /* RETURN candidate t-values */
- int depth; /* The depth of the recursion */
-{
- int i;
- Point2 Left[W_DEGREE+1], /* New left and right */
- Right[W_DEGREE+1]; /* control polygons */
- int left_count, /* Solution count from */
- right_count; /* children */
- double left_t[W_DEGREE+1], /* Solutions from kids */
- right_t[W_DEGREE+1];
-
- switch (CrossingCount(w, degree)) {
- case 0 : { /* No solutions here */
- return 0;
- }
- case 1 : { /* Unique solution */
- /* Stop recursion when the tree is deep enough */
- /* if deep enough, return 1 solution at midpoint */
- if (depth >= MAXDEPTH) {
- t[0] = (w[0].x + w[W_DEGREE].x) / 2.0;
- return 1;
- }
- if (ControlPolygonFlatEnough(w, degree)) {
- t[0] = ComputeXIntercept(w, degree);
- return 1;
- }
- break;
- }
-}
-
- /* Otherwise, solve recursively after */
- /* subdividing control polygon */
- Bezier(w, degree, 0.5, Left, Right);
- left_count = FindRoots(Left, degree, left_t, depth+1);
- right_count = FindRoots(Right, degree, right_t, depth+1);
-
-
- /* Gather solutions together */
- for (i = 0; i < left_count; i++) {
- t[i] = left_t[i];
- }
- for (i = 0; i < right_count; i++) {
- t[i+left_count] = right_t[i];
- }
-
- /* Send back total number of solutions */
- return (left_count+right_count);
-}
-
-
-/*
- * CrossingCount :
- * Count the number of times a Bezier control polygon
- * crosses the 0-axis. This number is >= the number of roots.
- *
- */
-static int CrossingCount(V, degree)
- Point2 *V; /* Control pts of Bezier curve */
- int degree; /* Degreee of Bezier curve */
-{
- int i;
- int n_crossings = 0; /* Number of zero-crossings */
- int sign, old_sign; /* Sign of coefficients */
-
- sign = old_sign = SGN(V[0].y);
- for (i = 1; i <= degree; i++) {
- sign = SGN(V[i].y);
- if (sign != old_sign) n_crossings++;
- old_sign = sign;
- }
- return n_crossings;
-}
-
-
-
-/*
- * ControlPolygonFlatEnough :
- * Check if the control polygon of a Bezier curve is flat enough
- * for recursive subdivision to bottom out.
- *
- */
-static int ControlPolygonFlatEnough(V, degree)
- Point2 *V; /* Control points */
- int degree; /* Degree of polynomial */
-{
- int i; /* Index variable */
- double *distance; /* Distances from pts to line */
- double max_distance_above; /* maximum of these */
- double max_distance_below;
- double error; /* Precision of root */
- double intercept_1,
- intercept_2,
- left_intercept,
- right_intercept;
- double a, b, c; /* Coefficients of implicit */
- /* eqn for line from V[0]-V[deg]*/
-
- /* Find the perpendicular distance */
- /* from each interior control point to */
- /* line connecting V[0] and V[degree] */
- distance = (double *)malloc((unsigned)(degree + 1) * sizeof(double));
- {
- double abSquared;
-
- /* Derive the implicit equation for line connecting first *'
- /* and last control points */
- a = V[0].y - V[degree].y;
- b = V[degree].x - V[0].x;
- c = V[0].x * V[degree].y - V[degree].x * V[0].y;
-
- abSquared = (a * a) + (b * b);
-
- for (i = 1; i < degree; i++) {
- /* Compute distance from each of the points to that line */
- distance[i] = a * V[i].x + b * V[i].y + c;
- if (distance[i] > 0.0) {
- distance[i] = (distance[i] * distance[i]) / abSquared;
- }
- if (distance[i] < 0.0) {
- distance[i] = -((distance[i] * distance[i]) / abSquared);
- }
- }
- }
-
-
- /* Find the largest distance */
- max_distance_above = 0.0;
- max_distance_below = 0.0;
- for (i = 1; i < degree; i++) {
- if (distance[i] < 0.0) {
- max_distance_below = MIN(max_distance_below, distance[i]);
- };
- if (distance[i] > 0.0) {
- max_distance_above = MAX(max_distance_above, distance[i]);
- }
- }
- free((char *)distance);
-
- {
- double det, dInv;
- double a1, b1, c1, a2, b2, c2;
-
- /* Implicit equation for zero line */
- a1 = 0.0;
- b1 = 1.0;
- c1 = 0.0;
-
- /* Implicit equation for "above" line */
- a2 = a;
- b2 = b;
- c2 = c + max_distance_above;
-
- det = a1 * b2 - a2 * b1;
- dInv = 1.0/det;
-
- intercept_1 = (b1 * c2 - b2 * c1) * dInv;
-
- /* Implicit equation for "below" line */
- a2 = a;
- b2 = b;
- c2 = c + max_distance_below;
-
- det = a1 * b2 - a2 * b1;
- dInv = 1.0/det;
-
- intercept_2 = (b1 * c2 - b2 * c1) * dInv;
- }
-
- /* Compute intercepts of bounding box */
- left_intercept = MIN(intercept_1, intercept_2);
- right_intercept = MAX(intercept_1, intercept_2);
-
- error = 0.5 * (right_intercept-left_intercept);
- if (error < EPSILON) {
- return 1;
- }
- else {
- return 0;
- }
-}
-
-
-
-/*
- * ComputeXIntercept :
- * Compute intersection of chord from first control point to last
- * with 0-axis.
- *
- */
-/* NOTE: "T" and "Y" do not have to be computed, and there are many useless
- * operations in the following (e.g. "0.0 - 0.0").
- */
-static double ComputeXIntercept(V, degree)
- Point2 *V; /* Control points */
- int degree; /* Degree of curve */
-{
- double XLK, YLK, XNM, YNM, XMK, YMK;
- double det, detInv;
- double S, T;
- double X, Y;
-
- XLK = 1.0 - 0.0;
- YLK = 0.0 - 0.0;
- XNM = V[degree].x - V[0].x;
- YNM = V[degree].y - V[0].y;
- XMK = V[0].x - 0.0;
- YMK = V[0].y - 0.0;
-
- det = XNM*YLK - YNM*XLK;
- detInv = 1.0/det;
-
- S = (XNM*YMK - YNM*XMK) * detInv;
-/* T = (XLK*YMK - YLK*XMK) * detInv; */
-
- X = 0.0 + XLK * S;
-/* Y = 0.0 + YLK * S; */
-
- return X;
-}
-
-
-/*
- * Bezier :
- * Evaluate a Bezier curve at a particular parameter value
- * Fill in control points for resulting sub-curves if "Left" and
- * "Right" are non-null.
- *
- */
-static Point2 Bezier(V, degree, t, Left, Right)
- int degree; /* Degree of bezier curve */
- Point2 *V; /* Control pts */
- double t; /* Parameter value */
- Point2 *Left; /* RETURN left half ctl pts */
- Point2 *Right; /* RETURN right half ctl pts */
-{
- int i, j; /* Index variables */
- Point2 Vtemp[W_DEGREE+1][W_DEGREE+1];
-
-
- /* Copy control points */
- for (j =0; j <= degree; j++) {
- Vtemp[0][j] = V[j];
- }
-
- /* Triangle computation */
- for (i = 1; i <= degree; i++) {
- for (j =0 ; j <= degree - i; j++) {
- Vtemp[i][j].x =
- (1.0 - t) * Vtemp[i-1][j].x + t * Vtemp[i-1][j+1].x;
- Vtemp[i][j].y =
- (1.0 - t) * Vtemp[i-1][j].y + t * Vtemp[i-1][j+1].y;
- }
- }
-
- if (Left != NULL) {
- for (j = 0; j <= degree; j++) {
- Left[j] = Vtemp[j][0];
- }
- }
- if (Right != NULL) {
- for (j = 0; j <= degree; j++) {
- Right[j] = Vtemp[degree-j][j];
- }
- }
-
- return (Vtemp[degree][0]);
-}
-
-static Vector2 V2ScaleII(v, s)
- Vector2 *v;
- double s;
-{
- Vector2 result;
-
- result.x = v->x * s; result.y = v->y * s;
- return (result);
-}
diff --git a/experimental/Intersection/Parameterization_Test.h b/experimental/Intersection/Parameterization_Test.h
deleted file mode 100644
index 93a27ec29d..0000000000
--- a/experimental/Intersection/Parameterization_Test.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "DataTypes.h"
-
-// utilities used only for unit testing
-bool point_on_parameterized_curve(const Cubic& cubic, const _Point& point);
-bool point_on_parameterized_line(const _Line& line, const _Point& point);
-bool point_on_parameterized_curve(const Quadratic& quad, const _Point& point);
diff --git a/experimental/Intersection/QuadraticBezierClip.cpp b/experimental/Intersection/QuadraticBezierClip.cpp
deleted file mode 100644
index 5b15fe51c6..0000000000
--- a/experimental/Intersection/QuadraticBezierClip.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "CurveIntersection.h"
-#include "CurveUtilities.h"
-#include "LineParameters.h"
-
-#define DEBUG_BEZIER_CLIP 1
-
-// return false if unable to clip (e.g., unable to create implicit line)
-// caller should subdivide, or create degenerate if the values are too small
-bool bezier_clip(const Quadratic& q1, const Quadratic& q2, double& minT, double& maxT) {
- minT = 1;
- maxT = 0;
- // determine normalized implicit line equation for pt[0] to pt[3]
- // of the form ax + by + c = 0, where a*a + b*b == 1
-
- // find the implicit line equation parameters
- LineParameters endLine;
- endLine.quadEndPoints(q1);
- if (!endLine.normalize()) {
- printf("line cannot be normalized: need more code here\n");
- SkASSERT(0);
- return false;
- }
-
- double distance = endLine.controlPtDistance(q1);
-
- // find fat line
- double top = 0;
- double bottom = distance / 2; // http://students.cs.byu.edu/~tom/557/text/cic.pdf (7.6)
- if (top > bottom) {
- SkTSwap(top, bottom);
- }
-
- // compute intersecting candidate distance
- Quadratic distance2y; // points with X of (0, 1/2, 1)
- endLine.quadDistanceY(q2, distance2y);
-
- int flags = 0;
- if (approximately_lesser_or_equal(distance2y[0].y, top)) {
- flags |= kFindTopMin;
- } else if (approximately_greater_or_equal(distance2y[0].y, bottom)) {
- flags |= kFindBottomMin;
- } else {
- minT = 0;
- }
-
- if (approximately_lesser_or_equal(distance2y[2].y, top)) {
- flags |= kFindTopMax;
- } else if (approximately_greater_or_equal(distance2y[2].y, bottom)) {
- flags |= kFindBottomMax;
- } else {
- maxT = 1;
- }
- // Find the intersection of distance convex hull and fat line.
- int idx = 0;
- do {
- int next = idx + 1;
- if (next == 3) {
- next = 0;
- }
- x_at(distance2y[idx], distance2y[next], top, bottom, flags, minT, maxT);
- idx = next;
- } while (idx);
-#if DEBUG_BEZIER_CLIP
- _Rect r1, r2;
- r1.setBounds(q1);
- r2.setBounds(q2);
- _Point testPt = {0.487, 0.337};
- if (r1.contains(testPt) && r2.contains(testPt)) {
- printf("%s q1=(%1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g)"
- " q2=(%1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g) minT=%1.9g maxT=%1.9g\n",
- __FUNCTION__, q1[0].x, q1[0].y, q1[1].x, q1[1].y, q1[2].x, q1[2].y,
- q2[0].x, q2[0].y, q2[1].x, q2[1].y, q2[2].x, q2[2].y, minT, maxT);
- }
-#endif
- return minT < maxT; // returns false if distance shows no intersection
-}
diff --git a/experimental/Intersection/QuadraticBezierClip_Test.cpp b/experimental/Intersection/QuadraticBezierClip_Test.cpp
deleted file mode 100644
index 1579f98884..0000000000
--- a/experimental/Intersection/QuadraticBezierClip_Test.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "CurveIntersection.h"
-#include "Intersection_Tests.h"
-#include "QuadraticIntersection_TestData.h"
-
-static const Quadratic testSet[] = {
- // data for oneOffTest
- {{8.0000000000000071, 8.0000000000000071},
- {8.7289570079366854, 8.7289570079366889},
- {9.3914917259458743, 9.0593802763083691}},
- {{8.0000000000000142, 8.0000000000000142},
- {8.1250000000000107, 8.1250000000000071},
- {8.2500000000000071, 8.2187500000000053}},
- // data for oneAtEndTest
- {{0.91292418204644155, 0.41931201426549197},
- {0.70491388044579517, 0.64754305977710236},
- {0, 1 }},
- {{0.21875, 0.765625 },
- {0.125, 0.875 },
- {0, 1 }}
-};
-
-static void oneAtEndTest() {
- const Quadratic& quad1 = testSet[2];
- const Quadratic& quad2 = testSet[3];
- double minT = 0;
- double maxT = 1;
- bezier_clip(quad1, quad2, minT, maxT);
-}
-
-
-static void oneOffTest() {
- const Quadratic& quad1 = testSet[0];
- const Quadratic& quad2 = testSet[1];
- double minT = 0;
- double maxT = 1;
- bezier_clip(quad1, quad2, minT, maxT);
-}
-
-static void standardTestCases() {
- for (size_t index = 0; index < quadraticTests_count; ++index) {
- const Quadratic& quad1 = quadraticTests[index][0];
- const Quadratic& quad2 = quadraticTests[index][1];
- Quadratic reduce1, reduce2;
- int order1 = reduceOrder(quad1, reduce1, kReduceOrder_TreatAsFill);
- int order2 = reduceOrder(quad2, reduce2, kReduceOrder_TreatAsFill);
- if (order1 < 3) {
- SkDebugf("%s [%d] quad1 order=%d\n", __FUNCTION__, (int)index, order1);
- }
- if (order2 < 3) {
- SkDebugf("%s [%d] quad2 order=%d\n", __FUNCTION__, (int)index, order2);
- }
- if (order1 == 3 && order2 == 3) {
- double minT = 0;
- double maxT = 1;
- bezier_clip(reduce1, reduce2, minT, maxT);
- }
- }
-}
-
-void QuadraticBezierClip_Test() {
- oneAtEndTest();
- oneOffTest();
- standardTestCases();
-}
diff --git a/experimental/Intersection/QuadraticBounds.cpp b/experimental/Intersection/QuadraticBounds.cpp
deleted file mode 100644
index 193743b04a..0000000000
--- a/experimental/Intersection/QuadraticBounds.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "CurveIntersection.h"
-#include "CurveUtilities.h"
-#include "Extrema.h"
-
-double leftMostT(const Quadratic& quad, double startT, double endT) {
- double leftT;
- if (findExtrema(quad[0].x, quad[1].x, quad[2].x, &leftT)
- && startT <= leftT && leftT <= endT) {
- return leftT;
- }
- _Point startPt;
- xy_at_t(quad, startT, startPt.x, startPt.y);
- _Point endPt;
- xy_at_t(quad, endT, endPt.x, endPt.y);
- return startPt.x <= endPt.x ? startT : endT;
-}
-
-void _Rect::setBounds(const Quadratic& quad) {
- set(quad[0]);
- add(quad[2]);
- double tValues[2];
- int roots = 0;
- if (!between(quad[0].x, quad[1].x, quad[2].x)) {
- roots = findExtrema(quad[0].x, quad[1].x, quad[2].x, tValues);
- }
- if (!between(quad[0].y, quad[1].y, quad[2].y)) {
- roots += findExtrema(quad[0].y, quad[1].y, quad[2].y, &tValues[roots]);
- }
- for (int x = 0; x < roots; ++x) {
- _Point result;
- xy_at_t(quad, tValues[x], result.x, result.y);
- add(result);
- }
-}
-
-void _Rect::setRawBounds(const Quadratic& quad) {
- set(quad[0]);
- for (int x = 1; x < 3; ++x) {
- add(quad[x]);
- }
-}
diff --git a/experimental/Intersection/QuadraticImplicit.cpp b/experimental/Intersection/QuadraticImplicit.cpp
deleted file mode 100644
index f16ddd9370..0000000000
--- a/experimental/Intersection/QuadraticImplicit.cpp
+++ /dev/null
@@ -1,572 +0,0 @@
-// Another approach is to start with the implicit form of one curve and solve
-// (seek implicit coefficients in QuadraticParameter.cpp
-// by substituting in the parametric form of the other.
-// The downside of this approach is that early rejects are difficult to come by.
-// http://planetmath.org/encyclopedia/GaloisTheoreticDerivationOfTheQuarticFormula.html#step
-
-
-#include "CubicUtilities.h"
-#include "CurveIntersection.h"
-#include "Intersections.h"
-#include "QuadraticParameterization.h"
-#include "QuarticRoot.h"
-#include "QuadraticUtilities.h"
-#include "TSearch.h"
-
-#ifdef SK_DEBUG
-#include "LineUtilities.h"
-#endif
-
-/* given the implicit form 0 = Ax^2 + Bxy + Cy^2 + Dx + Ey + F
- * and given x = at^2 + bt + c (the parameterized form)
- * y = dt^2 + et + f
- * then
- * 0 = A(at^2+bt+c)(at^2+bt+c)+B(at^2+bt+c)(dt^2+et+f)+C(dt^2+et+f)(dt^2+et+f)+D(at^2+bt+c)+E(dt^2+et+f)+F
- */
-
-static int findRoots(const QuadImplicitForm& i, const Quadratic& q2, double roots[4],
- bool oneHint, int firstCubicRoot) {
- double a, b, c;
- set_abc(&q2[0].x, a, b, c);
- double d, e, f;
- set_abc(&q2[0].y, d, e, f);
- const double t4 = i.x2() * a * a
- + i.xy() * a * d
- + i.y2() * d * d;
- const double t3 = 2 * i.x2() * a * b
- + i.xy() * (a * e + b * d)
- + 2 * i.y2() * d * e;
- const double t2 = i.x2() * (b * b + 2 * a * c)
- + i.xy() * (c * d + b * e + a * f)
- + i.y2() * (e * e + 2 * d * f)
- + i.x() * a
- + i.y() * d;
- const double t1 = 2 * i.x2() * b * c
- + i.xy() * (c * e + b * f)
- + 2 * i.y2() * e * f
- + i.x() * b
- + i.y() * e;
- const double t0 = i.x2() * c * c
- + i.xy() * c * f
- + i.y2() * f * f
- + i.x() * c
- + i.y() * f
- + i.c();
- int rootCount = reducedQuarticRoots(t4, t3, t2, t1, t0, oneHint, roots);
- if (rootCount >= 0) {
- return rootCount;
- }
- return quarticRootsReal(firstCubicRoot, t4, t3, t2, t1, t0, roots);
-}
-
-static int addValidRoots(const double roots[4], const int count, double valid[4]) {
- int result = 0;
- int index;
- for (index = 0; index < count; ++index) {
- if (!approximately_zero_or_more(roots[index]) || !approximately_one_or_less(roots[index])) {
- continue;
- }
- double t = 1 - roots[index];
- if (approximately_less_than_zero(t)) {
- t = 0;
- } else if (approximately_greater_than_one(t)) {
- t = 1;
- }
- valid[result++] = t;
- }
- return result;
-}
-
-static bool onlyEndPtsInCommon(const Quadratic& q1, const Quadratic& q2, Intersections& i) {
-// the idea here is to see at minimum do a quick reject by rotating all points
-// to either side of the line formed by connecting the endpoints
-// if the opposite curves points are on the line or on the other side, the
-// curves at most intersect at the endpoints
- for (int oddMan = 0; oddMan < 3; ++oddMan) {
- const _Point* endPt[2];
- for (int opp = 1; opp < 3; ++opp) {
- int end = oddMan ^ opp;
- if (end == 3) {
- end = opp;
- }
- endPt[opp - 1] = &q1[end];
- }
- double origX = endPt[0]->x;
- double origY = endPt[0]->y;
- double adj = endPt[1]->x - origX;
- double opp = endPt[1]->y - origY;
- double sign = (q1[oddMan].y - origY) * adj - (q1[oddMan].x - origX) * opp;
- if (approximately_zero(sign)) {
- goto tryNextHalfPlane;
- }
- for (int n = 0; n < 3; ++n) {
- double test = (q2[n].y - origY) * adj - (q2[n].x - origX) * opp;
- if (test * sign > 0) {
- goto tryNextHalfPlane;
- }
- }
- for (int i1 = 0; i1 < 3; i1 += 2) {
- for (int i2 = 0; i2 < 3; i2 += 2) {
- if (q1[i1] == q2[i2]) {
- i.insert(i1 >> 1, i2 >> 1, q1[i1]);
- }
- }
- }
- SkASSERT(i.fUsed < 3);
- return true;
-tryNextHalfPlane:
- ;
- }
- return false;
-}
-
-// returns false if there's more than one intercept or the intercept doesn't match the point
-// returns true if the intercept was successfully added or if the
-// original quads need to be subdivided
-static bool addIntercept(const Quadratic& q1, const Quadratic& q2, double tMin, double tMax,
- Intersections& i, bool* subDivide) {
- double tMid = (tMin + tMax) / 2;
- _Point mid;
- xy_at_t(q2, tMid, mid.x, mid.y);
- _Line line;
- line[0] = line[1] = mid;
- _Vector dxdy = dxdy_at_t(q2, tMid);
- line[0] -= dxdy;
- line[1] += dxdy;
- Intersections rootTs;
- int roots = intersect(q1, line, rootTs);
- if (roots == 0) {
- if (subDivide) {
- *subDivide = true;
- }
- return true;
- }
- if (roots == 2) {
- return false;
- }
- _Point pt2;
- xy_at_t(q1, rootTs.fT[0][0], pt2.x, pt2.y);
- if (!pt2.approximatelyEqualHalf(mid)) {
- return false;
- }
- i.insertSwap(rootTs.fT[0][0], tMid, pt2);
- return true;
-}
-
-static bool isLinearInner(const Quadratic& q1, double t1s, double t1e, const Quadratic& q2,
- double t2s, double t2e, Intersections& i, bool* subDivide) {
- Quadratic hull;
- sub_divide(q1, t1s, t1e, hull);
- _Line line = {hull[2], hull[0]};
- const _Line* testLines[] = { &line, (const _Line*) &hull[0], (const _Line*) &hull[1] };
- size_t testCount = sizeof(testLines) / sizeof(testLines[0]);
- SkTDArray<double> tsFound;
- for (size_t index = 0; index < testCount; ++index) {
- Intersections rootTs;
- int roots = intersect(q2, *testLines[index], rootTs);
- for (int idx2 = 0; idx2 < roots; ++idx2) {
- double t = rootTs.fT[0][idx2];
-#ifdef SK_DEBUG
- _Point qPt, lPt;
- xy_at_t(q2, t, qPt.x, qPt.y);
- xy_at_t(*testLines[index], rootTs.fT[1][idx2], lPt.x, lPt.y);
- SkASSERT(qPt.approximatelyEqual(lPt));
-#endif
- if (approximately_negative(t - t2s) || approximately_positive(t - t2e)) {
- continue;
- }
- *tsFound.append() = rootTs.fT[0][idx2];
- }
- }
- int tCount = tsFound.count();
- if (!tCount) {
- return true;
- }
- double tMin, tMax;
- if (tCount == 1) {
- tMin = tMax = tsFound[0];
- } else if (tCount > 1) {
- QSort<double>(tsFound.begin(), tsFound.end() - 1);
- tMin = tsFound[0];
- tMax = tsFound[tsFound.count() - 1];
- }
- _Point end;
- xy_at_t(q2, t2s, end.x, end.y);
- bool startInTriangle = point_in_hull(hull, end);
- if (startInTriangle) {
- tMin = t2s;
- }
- xy_at_t(q2, t2e, end.x, end.y);
- bool endInTriangle = point_in_hull(hull, end);
- if (endInTriangle) {
- tMax = t2e;
- }
- int split = 0;
- _Vector dxy1, dxy2;
- if (tMin != tMax || tCount > 2) {
- dxy2 = dxdy_at_t(q2, tMin);
- for (int index = 1; index < tCount; ++index) {
- dxy1 = dxy2;
- dxy2 = dxdy_at_t(q2, tsFound[index]);
- double dot = dxy1.dot(dxy2);
- if (dot < 0) {
- split = index - 1;
- break;
- }
- }
-
- }
- if (split == 0) { // there's one point
- if (addIntercept(q1, q2, tMin, tMax, i, subDivide)) {
- return true;
- }
- i.swap();
- return isLinearInner(q2, tMin, tMax, q1, t1s, t1e, i, subDivide);
- }
- // At this point, we have two ranges of t values -- treat each separately at the split
- bool result;
- if (addIntercept(q1, q2, tMin, tsFound[split - 1], i, subDivide)) {
- result = true;
- } else {
- i.swap();
- result = isLinearInner(q2, tMin, tsFound[split - 1], q1, t1s, t1e, i, subDivide);
- }
- if (addIntercept(q1, q2, tsFound[split], tMax, i, subDivide)) {
- result = true;
- } else {
- i.swap();
- result |= isLinearInner(q2, tsFound[split], tMax, q1, t1s, t1e, i, subDivide);
- }
- return result;
-}
-
-static double flatMeasure(const Quadratic& q) {
- _Vector mid = q[1] - q[0];
- _Vector dxy = q[2] - q[0];
- double length = dxy.length(); // OPTIMIZE: get rid of sqrt
- return fabs(mid.cross(dxy) / length);
-}
-
-// FIXME ? should this measure both and then use the quad that is the flattest as the line?
-static bool isLinear(const Quadratic& q1, const Quadratic& q2, Intersections& i) {
- double measure = flatMeasure(q1);
- // OPTIMIZE: (get rid of sqrt) use approximately_zero
- if (!approximately_zero_sqrt(measure)) {
- return false;
- }
- return isLinearInner(q1, 0, 1, q2, 0, 1, i, NULL);
-}
-
-// FIXME: if flat measure is sufficiently large, then probably the quartic solution failed
-static void relaxedIsLinear(const Quadratic& q1, const Quadratic& q2, Intersections& i) {
- double m1 = flatMeasure(q1);
- double m2 = flatMeasure(q2);
-#ifdef SK_DEBUG
- double min = SkTMin(m1, m2);
- if (min > 5) {
- SkDebugf("%s maybe not flat enough.. %1.9g\n", __FUNCTION__, min);
- }
-#endif
- i.reset();
- const Quadratic& rounder = m2 < m1 ? q1 : q2;
- const Quadratic& flatter = m2 < m1 ? q2 : q1;
- bool subDivide = false;
- isLinearInner(flatter, 0, 1, rounder, 0, 1, i, &subDivide);
- if (subDivide) {
- QuadraticPair pair;
- chop_at(flatter, pair, 0.5);
- Intersections firstI, secondI;
- relaxedIsLinear(pair.first(), rounder, firstI);
- for (int index = 0; index < firstI.used(); ++index) {
- i.insert(firstI.fT[0][index] * 0.5, firstI.fT[1][index], firstI.fPt[index]);
- }
- relaxedIsLinear(pair.second(), rounder, secondI);
- for (int index = 0; index < secondI.used(); ++index) {
- i.insert(0.5 + secondI.fT[0][index] * 0.5, secondI.fT[1][index], secondI.fPt[index]);
- }
- }
- if (m2 < m1) {
- i.swapPts();
- }
-}
-
-#if 0
-static void unsortableExpanse(const Quadratic& q1, const Quadratic& q2, Intersections& i) {
- const Quadratic* qs[2] = { &q1, &q2 };
- // need t values for start and end of unsortable expanse on both curves
- // try projecting lines parallel to the end points
- i.fT[0][0] = 0;
- i.fT[0][1] = 1;
- int flip = -1; // undecided
- for (int qIdx = 0; qIdx < 2; qIdx++) {
- for (int t = 0; t < 2; t++) {
- _Point dxdy;
- dxdy_at_t(*qs[qIdx], t, dxdy);
- _Line perp;
- perp[0] = perp[1] = (*qs[qIdx])[t == 0 ? 0 : 2];
- perp[0].x += dxdy.y;
- perp[0].y -= dxdy.x;
- perp[1].x -= dxdy.y;
- perp[1].y += dxdy.x;
- Intersections hitData;
- int hits = intersectRay(*qs[qIdx ^ 1], perp, hitData);
- SkASSERT(hits <= 1);
- if (hits) {
- if (flip < 0) {
- _Point dxdy2;
- dxdy_at_t(*qs[qIdx ^ 1], hitData.fT[0][0], dxdy2);
- double dot = dxdy.dot(dxdy2);
- flip = dot < 0;
- i.fT[1][0] = flip;
- i.fT[1][1] = !flip;
- }
- i.fT[qIdx ^ 1][t ^ flip] = hitData.fT[0][0];
- }
- }
- }
- i.fUnsortable = true; // failed, probably coincident or near-coincident
- i.fUsed = 2;
-}
-#endif
-
-// each time through the loop, this computes values it had from the last loop
-// if i == j == 1, the center values are still good
-// otherwise, for i != 1 or j != 1, four of the values are still good
-// and if i == 1 ^ j == 1, an additional value is good
-static bool binarySearch(const Quadratic& quad1, const Quadratic& quad2, double& t1Seed,
- double& t2Seed, _Point& pt) {
- double tStep = ROUGH_EPSILON;
- _Point t1[3], t2[3];
- int calcMask = ~0;
- do {
- if (calcMask & (1 << 1)) t1[1] = xy_at_t(quad1, t1Seed);
- if (calcMask & (1 << 4)) t2[1] = xy_at_t(quad2, t2Seed);
- if (t1[1].approximatelyEqual(t2[1])) {
- pt = t1[1];
- #if ONE_OFF_DEBUG
- SkDebugf("%s t1=%1.9g t2=%1.9g (%1.9g,%1.9g) == (%1.9g,%1.9g)\n", __FUNCTION__,
- t1Seed, t2Seed, t1[1].x, t1[1].y, t1[2].x, t1[2].y);
- #endif
- return true;
- }
- if (calcMask & (1 << 0)) t1[0] = xy_at_t(quad1, t1Seed - tStep);
- if (calcMask & (1 << 2)) t1[2] = xy_at_t(quad1, t1Seed + tStep);
- if (calcMask & (1 << 3)) t2[0] = xy_at_t(quad2, t2Seed - tStep);
- if (calcMask & (1 << 5)) t2[2] = xy_at_t(quad2, t2Seed + tStep);
- double dist[3][3];
- // OPTIMIZE: using calcMask value permits skipping some distance calcuations
- // if prior loop's results are moved to correct slot for reuse
- dist[1][1] = t1[1].distanceSquared(t2[1]);
- int best_i = 1, best_j = 1;
- for (int i = 0; i < 3; ++i) {
- for (int j = 0; j < 3; ++j) {
- if (i == 1 && j == 1) {
- continue;
- }
- dist[i][j] = t1[i].distanceSquared(t2[j]);
- if (dist[best_i][best_j] > dist[i][j]) {
- best_i = i;
- best_j = j;
- }
- }
- }
- if (best_i == 1 && best_j == 1) {
- tStep /= 2;
- if (tStep < FLT_EPSILON_HALF) {
- break;
- }
- calcMask = (1 << 0) | (1 << 2) | (1 << 3) | (1 << 5);
- continue;
- }
- if (best_i == 0) {
- t1Seed -= tStep;
- t1[2] = t1[1];
- t1[1] = t1[0];
- calcMask = 1 << 0;
- } else if (best_i == 2) {
- t1Seed += tStep;
- t1[0] = t1[1];
- t1[1] = t1[2];
- calcMask = 1 << 2;
- } else {
- calcMask = 0;
- }
- if (best_j == 0) {
- t2Seed -= tStep;
- t2[2] = t2[1];
- t2[1] = t2[0];
- calcMask |= 1 << 3;
- } else if (best_j == 2) {
- t2Seed += tStep;
- t2[0] = t2[1];
- t2[1] = t2[2];
- calcMask |= 1 << 5;
- }
- } while (true);
-#if ONE_OFF_DEBUG
- SkDebugf("%s t1=%1.9g t2=%1.9g (%1.9g,%1.9g) != (%1.9g,%1.9g) %s\n", __FUNCTION__,
- t1Seed, t2Seed, t1[1].x, t1[1].y, t1[2].x, t1[2].y);
-#endif
- return false;
-}
-
-bool intersect2(const Quadratic& q1, const Quadratic& q2, Intersections& i) {
- // if the quads share an end point, check to see if they overlap
-
- if (onlyEndPtsInCommon(q1, q2, i)) {
- return i.intersected();
- }
- if (onlyEndPtsInCommon(q2, q1, i)) {
- i.swapPts();
- return i.intersected();
- }
- // see if either quad is really a line
- if (isLinear(q1, q2, i)) {
- return i.intersected();
- }
- if (isLinear(q2, q1, i)) {
- i.swapPts();
- return i.intersected();
- }
- QuadImplicitForm i1(q1);
- QuadImplicitForm i2(q2);
- if (i1.implicit_match(i2)) {
- // FIXME: compute T values
- // compute the intersections of the ends to find the coincident span
- bool useVertical = fabs(q1[0].x - q1[2].x) < fabs(q1[0].y - q1[2].y);
- double t;
- if ((t = axialIntersect(q1, q2[0], useVertical)) >= 0) {
- i.insertCoincident(t, 0, q2[0]);
- }
- if ((t = axialIntersect(q1, q2[2], useVertical)) >= 0) {
- i.insertCoincident(t, 1, q2[2]);
- }
- useVertical = fabs(q2[0].x - q2[2].x) < fabs(q2[0].y - q2[2].y);
- if ((t = axialIntersect(q2, q1[0], useVertical)) >= 0) {
- i.insertCoincident(0, t, q1[0]);
- }
- if ((t = axialIntersect(q2, q1[2], useVertical)) >= 0) {
- i.insertCoincident(1, t, q1[2]);
- }
- SkASSERT(i.coincidentUsed() <= 2);
- return i.coincidentUsed() > 0;
- }
- int index;
- bool useCubic = q1[0] == q2[0] || q1[0] == q2[2] || q1[2] == q2[0];
- double roots1[4];
- int rootCount = findRoots(i2, q1, roots1, useCubic, 0);
- // OPTIMIZATION: could short circuit here if all roots are < 0 or > 1
- double roots1Copy[4];
- int r1Count = addValidRoots(roots1, rootCount, roots1Copy);
- _Point pts1[4];
- for (index = 0; index < r1Count; ++index) {
- xy_at_t(q1, roots1Copy[index], pts1[index].x, pts1[index].y);
- }
- double roots2[4];
- int rootCount2 = findRoots(i1, q2, roots2, useCubic, 0);
- double roots2Copy[4];
- int r2Count = addValidRoots(roots2, rootCount2, roots2Copy);
- _Point pts2[4];
- for (index = 0; index < r2Count; ++index) {
- xy_at_t(q2, roots2Copy[index], pts2[index].x, pts2[index].y);
- }
- if (r1Count == r2Count && r1Count <= 1) {
- if (r1Count == 1) {
- if (pts1[0].approximatelyEqualHalf(pts2[0])) {
- i.insert(roots1Copy[0], roots2Copy[0], pts1[0]);
- } else if (pts1[0].moreRoughlyEqual(pts2[0])) {
- // experiment: see if a different cubic solution provides the correct quartic answer
- #if 0
- for (int cu1 = 0; cu1 < 3; ++cu1) {
- rootCount = findRoots(i2, q1, roots1, useCubic, cu1);
- r1Count = addValidRoots(roots1, rootCount, roots1Copy);
- if (r1Count == 0) {
- continue;
- }
- for (int cu2 = 0; cu2 < 3; ++cu2) {
- if (cu1 == 0 && cu2 == 0) {
- continue;
- }
- rootCount2 = findRoots(i1, q2, roots2, useCubic, cu2);
- r2Count = addValidRoots(roots2, rootCount2, roots2Copy);
- if (r2Count == 0) {
- continue;
- }
- SkASSERT(r1Count == 1 && r2Count == 1);
- SkDebugf("*** [%d,%d] (%1.9g,%1.9g) %s (%1.9g,%1.9g)\n", cu1, cu2,
- pts1[0].x, pts1[0].y, pts1[0].approximatelyEqualHalf(pts2[0])
- ? "==" : "!=", pts2[0].x, pts2[0].y);
- }
- }
- #endif
- // experiment: try to find intersection by chasing t
- rootCount = findRoots(i2, q1, roots1, useCubic, 0);
- r1Count = addValidRoots(roots1, rootCount, roots1Copy);
- rootCount2 = findRoots(i1, q2, roots2, useCubic, 0);
- r2Count = addValidRoots(roots2, rootCount2, roots2Copy);
- if (binarySearch(q1, q2, roots1Copy[0], roots2Copy[0], pts1[0])) {
- i.insert(roots1Copy[0], roots2Copy[0], pts1[0]);
- }
- }
- }
- return i.intersected();
- }
- int closest[4];
- double dist[4];
- bool foundSomething = false;
- for (index = 0; index < r1Count; ++index) {
- dist[index] = DBL_MAX;
- closest[index] = -1;
- for (int ndex2 = 0; ndex2 < r2Count; ++ndex2) {
- if (!pts2[ndex2].approximatelyEqualHalf(pts1[index])) {
- continue;
- }
- double dx = pts2[ndex2].x - pts1[index].x;
- double dy = pts2[ndex2].y - pts1[index].y;
- double distance = dx * dx + dy * dy;
- if (dist[index] <= distance) {
- continue;
- }
- for (int outer = 0; outer < index; ++outer) {
- if (closest[outer] != ndex2) {
- continue;
- }
- if (dist[outer] < distance) {
- goto next;
- }
- closest[outer] = -1;
- }
- dist[index] = distance;
- closest[index] = ndex2;
- foundSomething = true;
- next:
- ;
- }
- }
- if (r1Count && r2Count && !foundSomething) {
- relaxedIsLinear(q1, q2, i);
- return i.intersected();
- }
- int used = 0;
- do {
- double lowest = DBL_MAX;
- int lowestIndex = -1;
- for (index = 0; index < r1Count; ++index) {
- if (closest[index] < 0) {
- continue;
- }
- if (roots1Copy[index] < lowest) {
- lowestIndex = index;
- lowest = roots1Copy[index];
- }
- }
- if (lowestIndex < 0) {
- break;
- }
- i.insert(roots1Copy[lowestIndex], roots2Copy[closest[lowestIndex]],
- pts1[lowestIndex]);
- closest[lowestIndex] = -1;
- } while (++used < r1Count);
- i.fFlip = false;
- return i.intersected();
-}
diff --git a/experimental/Intersection/QuadraticIntersection.cpp b/experimental/Intersection/QuadraticIntersection.cpp
deleted file mode 100644
index 07b8ecf8f3..0000000000
--- a/experimental/Intersection/QuadraticIntersection.cpp
+++ /dev/null
@@ -1,403 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "CurveIntersection.h"
-#include "Intersections.h"
-#include "IntersectionUtilities.h"
-#include "LineIntersection.h"
-#include "LineUtilities.h"
-#include "QuadraticLineSegments.h"
-#include "QuadraticUtilities.h"
-#include <algorithm> // for swap
-
-static const double tClipLimit = 0.8; // http://cagd.cs.byu.edu/~tom/papers/bezclip.pdf see Multiple intersections
-
-class QuadraticIntersections {
-public:
-
-QuadraticIntersections(const Quadratic& q1, const Quadratic& q2, Intersections& i)
- : quad1(q1)
- , quad2(q2)
- , intersections(i)
- , depth(0)
- , splits(0)
- , coinMinT1(-1) {
-}
-
-bool intersect() {
- double minT1, minT2, maxT1, maxT2;
- if (!bezier_clip(quad2, quad1, minT1, maxT1)) {
- return false;
- }
- if (!bezier_clip(quad1, quad2, minT2, maxT2)) {
- return false;
- }
- quad1Divisions = 1 / subDivisions(quad1);
- quad2Divisions = 1 / subDivisions(quad2);
- int split;
- if (maxT1 - minT1 < maxT2 - minT2) {
- intersections.swap();
- minT2 = 0;
- maxT2 = 1;
- split = maxT1 - minT1 > tClipLimit;
- } else {
- minT1 = 0;
- maxT1 = 1;
- split = (maxT2 - minT2 > tClipLimit) << 1;
- }
- return chop(minT1, maxT1, minT2, maxT2, split);
-}
-
-protected:
-
-bool intersect(double minT1, double maxT1, double minT2, double maxT2) {
- bool t1IsLine = maxT1 - minT1 <= quad1Divisions;
- bool t2IsLine = maxT2 - minT2 <= quad2Divisions;
- if (t1IsLine | t2IsLine) {
- return intersectAsLine(minT1, maxT1, minT2, maxT2, t1IsLine, t2IsLine);
- }
- Quadratic smaller, larger;
- // FIXME: carry last subdivide and reduceOrder result with quad
- sub_divide(quad1, minT1, maxT1, intersections.swapped() ? larger : smaller);
- sub_divide(quad2, minT2, maxT2, intersections.swapped() ? smaller : larger);
- double minT, maxT;
- if (!bezier_clip(smaller, larger, minT, maxT)) {
- if (approximately_equal(minT, maxT)) {
- double smallT, largeT;
- _Point q2pt, q1pt;
- if (intersections.swapped()) {
- largeT = interp(minT2, maxT2, minT);
- xy_at_t(quad2, largeT, q2pt.x, q2pt.y);
- xy_at_t(quad1, minT1, q1pt.x, q1pt.y);
- if (AlmostEqualUlps(q2pt.x, q1pt.x) && AlmostEqualUlps(q2pt.y, q1pt.y)) {
- smallT = minT1;
- } else {
- xy_at_t(quad1, maxT1, q1pt.x, q1pt.y); // FIXME: debug code
- SkASSERT(AlmostEqualUlps(q2pt.x, q1pt.x) && AlmostEqualUlps(q2pt.y, q1pt.y));
- smallT = maxT1;
- }
- } else {
- smallT = interp(minT1, maxT1, minT);
- xy_at_t(quad1, smallT, q1pt.x, q1pt.y);
- xy_at_t(quad2, minT2, q2pt.x, q2pt.y);
- if (AlmostEqualUlps(q2pt.x, q1pt.x) && AlmostEqualUlps(q2pt.y, q1pt.y)) {
- largeT = minT2;
- } else {
- xy_at_t(quad2, maxT2, q2pt.x, q2pt.y); // FIXME: debug code
- SkASSERT(AlmostEqualUlps(q2pt.x, q1pt.x) && AlmostEqualUlps(q2pt.y, q1pt.y));
- largeT = maxT2;
- }
- }
- intersections.add(smallT, largeT);
- return true;
- }
- return false;
- }
- int split;
- if (intersections.swapped()) {
- double newMinT1 = interp(minT1, maxT1, minT);
- double newMaxT1 = interp(minT1, maxT1, maxT);
- split = (newMaxT1 - newMinT1 > (maxT1 - minT1) * tClipLimit) << 1;
-#define VERBOSE 0
-#if VERBOSE
- printf("%s d=%d s=%d new1=(%g,%g) old1=(%g,%g) split=%d\n", __FUNCTION__, depth,
- splits, newMinT1, newMaxT1, minT1, maxT1, split);
-#endif
- minT1 = newMinT1;
- maxT1 = newMaxT1;
- } else {
- double newMinT2 = interp(minT2, maxT2, minT);
- double newMaxT2 = interp(minT2, maxT2, maxT);
- split = newMaxT2 - newMinT2 > (maxT2 - minT2) * tClipLimit;
-#if VERBOSE
- printf("%s d=%d s=%d new2=(%g,%g) old2=(%g,%g) split=%d\n", __FUNCTION__, depth,
- splits, newMinT2, newMaxT2, minT2, maxT2, split);
-#endif
- minT2 = newMinT2;
- maxT2 = newMaxT2;
- }
- return chop(minT1, maxT1, minT2, maxT2, split);
-}
-
-bool intersectAsLine(double minT1, double maxT1, double minT2, double maxT2,
- bool treat1AsLine, bool treat2AsLine)
-{
- _Line line1, line2;
- if (intersections.swapped()) {
- SkTSwap(treat1AsLine, treat2AsLine);
- SkTSwap(minT1, minT2);
- SkTSwap(maxT1, maxT2);
- }
- if (coinMinT1 >= 0) {
- bool earlyExit;
- if ((earlyExit = coinMaxT1 == minT1)) {
- coinMaxT1 = maxT1;
- }
- if (coinMaxT2 == minT2) {
- coinMaxT2 = maxT2;
- return true;
- }
- if (earlyExit) {
- return true;
- }
- coinMinT1 = -1;
- }
- // do line/quadratic or even line/line intersection instead
- if (treat1AsLine) {
- xy_at_t(quad1, minT1, line1[0].x, line1[0].y);
- xy_at_t(quad1, maxT1, line1[1].x, line1[1].y);
- }
- if (treat2AsLine) {
- xy_at_t(quad2, minT2, line2[0].x, line2[0].y);
- xy_at_t(quad2, maxT2, line2[1].x, line2[1].y);
- }
- int pts;
- double smallT1, largeT1, smallT2, largeT2;
- if (treat1AsLine & treat2AsLine) {
- double t1[2], t2[2];
- pts = ::intersect(line1, line2, t1, t2);
- if (pts == 2) {
- smallT1 = interp(minT1, maxT1, t1[0]);
- largeT1 = interp(minT2, maxT2, t2[0]);
- smallT2 = interp(minT1, maxT1, t1[1]);
- largeT2 = interp(minT2, maxT2, t2[1]);
- intersections.addCoincident(smallT1, smallT2, largeT1, largeT2);
- } else {
- smallT1 = interp(minT1, maxT1, t1[0]);
- largeT1 = interp(minT2, maxT2, t2[0]);
- intersections.add(smallT1, largeT1);
- }
- } else {
- Intersections lq;
- pts = ::intersect(treat1AsLine ? quad2 : quad1,
- treat1AsLine ? line1 : line2, lq);
- if (pts == 2) { // if the line and edge are coincident treat differently
- _Point midQuad, midLine;
- double midQuadT = (lq.fT[0][0] + lq.fT[0][1]) / 2;
- xy_at_t(treat1AsLine ? quad2 : quad1, midQuadT, midQuad.x, midQuad.y);
- double lineT = t_at(treat1AsLine ? line1 : line2, midQuad);
- xy_at_t(treat1AsLine ? line1 : line2, lineT, midLine.x, midLine.y);
- if (AlmostEqualUlps(midQuad.x, midLine.x)
- && AlmostEqualUlps(midQuad.y, midLine.y)) {
- smallT1 = lq.fT[0][0];
- largeT1 = lq.fT[1][0];
- smallT2 = lq.fT[0][1];
- largeT2 = lq.fT[1][1];
- if (treat2AsLine) {
- smallT1 = interp(minT1, maxT1, smallT1);
- smallT2 = interp(minT1, maxT1, smallT2);
- } else {
- largeT1 = interp(minT2, maxT2, largeT1);
- largeT2 = interp(minT2, maxT2, largeT2);
- }
- intersections.addCoincident(smallT1, smallT2, largeT1, largeT2);
- goto setCoinMinMax;
- }
- }
- for (int index = 0; index < pts; ++index) {
- smallT1 = lq.fT[0][index];
- largeT1 = lq.fT[1][index];
- if (treat2AsLine) {
- smallT1 = interp(minT1, maxT1, smallT1);
- } else {
- largeT1 = interp(minT2, maxT2, largeT1);
- }
- intersections.add(smallT1, largeT1);
- }
- }
- if (pts > 0) {
-setCoinMinMax:
- coinMinT1 = minT1;
- coinMaxT1 = maxT1;
- coinMinT2 = minT2;
- coinMaxT2 = maxT2;
- }
- return pts > 0;
-}
-
-bool chop(double minT1, double maxT1, double minT2, double maxT2, int split) {
- ++depth;
- intersections.swap();
- if (split) {
- ++splits;
- if (split & 2) {
- double middle1 = (maxT1 + minT1) / 2;
- intersect(minT1, middle1, minT2, maxT2);
- intersect(middle1, maxT1, minT2, maxT2);
- } else {
- double middle2 = (maxT2 + minT2) / 2;
- intersect(minT1, maxT1, minT2, middle2);
- intersect(minT1, maxT1, middle2, maxT2);
- }
- --splits;
- intersections.swap();
- --depth;
- return intersections.intersected();
- }
- bool result = intersect(minT1, maxT1, minT2, maxT2);
- intersections.swap();
- --depth;
- return result;
-}
-
-private:
-
-const Quadratic& quad1;
-const Quadratic& quad2;
-Intersections& intersections;
-int depth;
-int splits;
-double quad1Divisions; // line segments to approximate original within error
-double quad2Divisions;
-double coinMinT1; // range of Ts where approximate line intersected curve
-double coinMaxT1;
-double coinMinT2;
-double coinMaxT2;
-};
-
-#include "LineParameters.h"
-
-static void hackToFixPartialCoincidence(const Quadratic& q1, const Quadratic& q2, Intersections& i) {
- // look to see if non-coincident data basically has unsortable tangents
-
- // look to see if a point between non-coincident data is on the curve
- int cIndex;
- for (int uIndex = 0; uIndex < i.fUsed; ) {
- double bestDist1 = 1;
- double bestDist2 = 1;
- int closest1 = -1;
- int closest2 = -1;
- for (cIndex = 0; cIndex < i.fCoincidentUsed; ++cIndex) {
- double dist = fabs(i.fT[0][uIndex] - i.fCoincidentT[0][cIndex]);
- if (bestDist1 > dist) {
- bestDist1 = dist;
- closest1 = cIndex;
- }
- dist = fabs(i.fT[1][uIndex] - i.fCoincidentT[1][cIndex]);
- if (bestDist2 > dist) {
- bestDist2 = dist;
- closest2 = cIndex;
- }
- }
- _Line ends;
- _Point mid;
- double t1 = i.fT[0][uIndex];
- xy_at_t(q1, t1, ends[0].x, ends[0].y);
- xy_at_t(q1, i.fCoincidentT[0][closest1], ends[1].x, ends[1].y);
- double midT = (t1 + i.fCoincidentT[0][closest1]) / 2;
- xy_at_t(q1, midT, mid.x, mid.y);
- LineParameters params;
- params.lineEndPoints(ends);
- double midDist = params.pointDistance(mid);
- // Note that we prefer to always measure t error, which does not scale,
- // instead of point error, which is scale dependent. FIXME
- if (!approximately_zero(midDist)) {
- ++uIndex;
- continue;
- }
- double t2 = i.fT[1][uIndex];
- xy_at_t(q2, t2, ends[0].x, ends[0].y);
- xy_at_t(q2, i.fCoincidentT[1][closest2], ends[1].x, ends[1].y);
- midT = (t2 + i.fCoincidentT[1][closest2]) / 2;
- xy_at_t(q2, midT, mid.x, mid.y);
- params.lineEndPoints(ends);
- midDist = params.pointDistance(mid);
- if (!approximately_zero(midDist)) {
- ++uIndex;
- continue;
- }
- // if both midpoints are close to the line, lengthen coincident span
- int cEnd = closest1 ^ 1; // assume coincidence always travels in pairs
- if (!between(i.fCoincidentT[0][cEnd], t1, i.fCoincidentT[0][closest1])) {
- i.fCoincidentT[0][closest1] = t1;
- }
- cEnd = closest2 ^ 1;
- if (!between(i.fCoincidentT[0][cEnd], t2, i.fCoincidentT[0][closest2])) {
- i.fCoincidentT[0][closest2] = t2;
- }
- int remaining = --i.fUsed - uIndex;
- if (remaining > 0) {
- memmove(&i.fT[0][uIndex], &i.fT[0][uIndex + 1], sizeof(i.fT[0][0]) * remaining);
- memmove(&i.fT[1][uIndex], &i.fT[1][uIndex + 1], sizeof(i.fT[1][0]) * remaining);
- }
- }
- // if coincident data is subjectively a tiny span, replace it with a single point
- for (cIndex = 0; cIndex < i.fCoincidentUsed; ) {
- double start1 = i.fCoincidentT[0][cIndex];
- double end1 = i.fCoincidentT[0][cIndex + 1];
- _Line ends1;
- xy_at_t(q1, start1, ends1[0].x, ends1[0].y);
- xy_at_t(q1, end1, ends1[1].x, ends1[1].y);
- if (!AlmostEqualUlps(ends1[0].x, ends1[1].x) || AlmostEqualUlps(ends1[0].y, ends1[1].y)) {
- cIndex += 2;
- continue;
- }
- double start2 = i.fCoincidentT[1][cIndex];
- double end2 = i.fCoincidentT[1][cIndex + 1];
- _Line ends2;
- xy_at_t(q2, start2, ends2[0].x, ends2[0].y);
- xy_at_t(q2, end2, ends2[1].x, ends2[1].y);
- // again, approximately should be used with T values, not points FIXME
- if (!AlmostEqualUlps(ends2[0].x, ends2[1].x) || AlmostEqualUlps(ends2[0].y, ends2[1].y)) {
- cIndex += 2;
- continue;
- }
- if (approximately_less_than_zero(start1) || approximately_less_than_zero(end1)) {
- start1 = 0;
- } else if (approximately_greater_than_one(start1) || approximately_greater_than_one(end1)) {
- start1 = 1;
- } else {
- start1 = (start1 + end1) / 2;
- }
- if (approximately_less_than_zero(start2) || approximately_less_than_zero(end2)) {
- start2 = 0;
- } else if (approximately_greater_than_one(start2) || approximately_greater_than_one(end2)) {
- start2 = 1;
- } else {
- start2 = (start2 + end2) / 2;
- }
- i.insert(start1, start2);
- i.fCoincidentUsed -= 2;
- int remaining = i.fCoincidentUsed - cIndex;
- if (remaining > 0) {
- memmove(&i.fCoincidentT[0][cIndex], &i.fCoincidentT[0][cIndex + 2], sizeof(i.fCoincidentT[0][0]) * remaining);
- memmove(&i.fCoincidentT[1][cIndex], &i.fCoincidentT[1][cIndex + 2], sizeof(i.fCoincidentT[1][0]) * remaining);
- }
- }
-}
-
-bool intersect(const Quadratic& q1, const Quadratic& q2, Intersections& i) {
- if (implicit_matches(q1, q2)) {
- // FIXME: compute T values
- // compute the intersections of the ends to find the coincident span
- bool useVertical = fabs(q1[0].x - q1[2].x) < fabs(q1[0].y - q1[2].y);
- double t;
- if ((t = axialIntersect(q1, q2[0], useVertical)) >= 0) {
- i.addCoincident(t, 0);
- }
- if ((t = axialIntersect(q1, q2[2], useVertical)) >= 0) {
- i.addCoincident(t, 1);
- }
- useVertical = fabs(q2[0].x - q2[2].x) < fabs(q2[0].y - q2[2].y);
- if ((t = axialIntersect(q2, q1[0], useVertical)) >= 0) {
- i.addCoincident(0, t);
- }
- if ((t = axialIntersect(q2, q1[2], useVertical)) >= 0) {
- i.addCoincident(1, t);
- }
- SkASSERT(i.fCoincidentUsed <= 2);
- return i.fCoincidentUsed > 0;
- }
- QuadraticIntersections q(q1, q2, i);
- bool result = q.intersect();
- // FIXME: partial coincidence detection is currently poor. For now, try
- // to fix up the data after the fact. In the future, revisit the error
- // term to try to avoid this kind of result in the first place.
- if (i.fUsed && i.fCoincidentUsed) {
- hackToFixPartialCoincidence(q1, q2, i);
- }
- return result;
-}
diff --git a/experimental/Intersection/QuadraticIntersection_Test.cpp b/experimental/Intersection/QuadraticIntersection_Test.cpp
deleted file mode 100644
index f3503c70d7..0000000000
--- a/experimental/Intersection/QuadraticIntersection_Test.cpp
+++ /dev/null
@@ -1,436 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "CurveIntersection.h"
-#include "CurveUtilities.h"
-#include "Intersection_Tests.h"
-#include "Intersections.h"
-#include "LineIntersection.h"
-#include "QuadraticIntersection_TestData.h"
-#include "QuadraticUtilities.h"
-#include "TestUtilities.h"
-
-const int firstQuadIntersectionTest = 9;
-
-static void standardTestCases() {
- for (size_t index = firstQuadIntersectionTest; index < quadraticTests_count; ++index) {
- const Quadratic& quad1 = quadraticTests[index][0];
- const Quadratic& quad2 = quadraticTests[index][1];
- Quadratic reduce1, reduce2;
- int order1 = reduceOrder(quad1, reduce1, kReduceOrder_TreatAsFill);
- int order2 = reduceOrder(quad2, reduce2, kReduceOrder_TreatAsFill);
- if (order1 < 3) {
- printf("[%d] quad1 order=%d\n", (int) index, order1);
- }
- if (order2 < 3) {
- printf("[%d] quad2 order=%d\n", (int) index, order2);
- }
- if (order1 == 3 && order2 == 3) {
- Intersections intersections;
- intersect2(reduce1, reduce2, intersections);
- if (intersections.intersected()) {
- for (int pt = 0; pt < intersections.used(); ++pt) {
- double tt1 = intersections.fT[0][pt];
- double tx1, ty1;
- xy_at_t(quad1, tt1, tx1, ty1);
- double tt2 = intersections.fT[1][pt];
- double tx2, ty2;
- xy_at_t(quad2, tt2, tx2, ty2);
- if (!approximately_equal(tx1, tx2)) {
- printf("%s [%d,%d] x!= t1=%g (%g,%g) t2=%g (%g,%g)\n",
- __FUNCTION__, (int)index, pt, tt1, tx1, ty1, tt2, tx2, ty2);
- }
- if (!approximately_equal(ty1, ty2)) {
- printf("%s [%d,%d] y!= t1=%g (%g,%g) t2=%g (%g,%g)\n",
- __FUNCTION__, (int)index, pt, tt1, tx1, ty1, tt2, tx2, ty2);
- }
- }
- }
- }
- }
-}
-
-static const Quadratic testSet[] = {
-{{3.0774019473063863, 3.35198509346713}, {3.0757503498668397, 3.327320623945933}, {3.0744102085015879, 3.3025879417907196}},
-{{3.053913680774329, 3.3310471586283938}, {3.0758730889691694, 3.3273466070370152}, {3.0975671980059394, 3.3235031316554351}},
-
- {{3.39068129,4.44939202}, {3.03659239,3.81843234}, {3.06844529,3.02100922}},
- {{2.10714698,3.44196686}, {3.12180288,3.38575704}, {3.75968569,3.1281838}},
-
- {{2.74792918,4.77711896}, {2.82236867,4.23882547}, {2.82848144,3.63729341}},
- {{2.62772567,3.64823958}, {3.46652495,3.64258364}, {4.1425079,3.48623815}},
-
- {{1.34375,2.03125}, {2.2734375,2.6640625}, {3.25,3.25}},
- {{3.96875,4.65625}, {3.3359375,3.7265625}, {2.75,2.75}},
-
- {{0,1}, {0.324417544,2.27953848}, {0.664376547,2.58940267}},
- {{1,2}, {0.62109375,2.70703125}, {0.640625,2.546875}},
-
- {{1,2}, {0.984375,2.3359375}, {1.0625,2.15625}},
- {{0,1}, {0.983539095,2.30041152}, {1.47325103,2.61316872}},
-
- {{4.09011926,2.20971038}, {4.74608133,1.9335932}, {5.02469918,2.00694987}},
- {{2.79472921,1.73568666}, {3.36246373,1.21251209}, {5,2}},
-
- {{1.80814127,2.41537795}, {2.23475077,2.05922313}, {3.16529668,1.98358763}},
- {{2.16505631,2.55782454}, {2.40541285,2.02193091}, {2.99836023,1.68247638}},
-
-{{3, 1.875}, {3.375, 1.54296875}, {3.375, 1.421875}},
-{{3.375, 1.421875}, {3.3749999999999996, 1.3007812499999998}, {3, 2}},
-
- {{3.34,8.98}, {2.83363281,9.4265625}, {2.83796875,9.363125}},
- {{2.83796875,9.363125}, {2.84230469,9.2996875}, {3.17875,9.1725}},
-
-{{2.7279999999999998, 3.024}, {2.5600000000000005, 2.5600000000000005}, {2.1520000000000001, 1.8560000000000001}},
-{{0.66666666666666652, 1.1481481481481481}, {1.3333333333333326, 1.3333333333333335}, {2.6666666666666665, 2.1851851851851851}},
-
- {{2.728,3.024}, {2.56,2.56}, {2.152,1.856}},
- {{0.666666667,1.14814815}, {1.33333333,1.33333333}, {2.66666667,2.18518519}},
-
- {{0.875,1.5}, {1.03125,1.11022302e-16}, {1,0}},
- {{0.875,0.859375}, {1.6875,0.73046875}, {2.5,0.625}},
-
- {{1.64451042,0.0942001592}, {1.53635465,0.00152863961}, {1,0}},
- {{1.27672209,0.15}, {1.32143477,9.25185854e-17}, {1,0}},
-
-{{0, 0}, {0.51851851851851849, 1.0185185185185186}, {1.2592592592592591, 1.9259259259259258}},
-{{1.2592592592592593, 1.9259259259259265}, {0.51851851851851893, 1.0185185185185195}, {0, 0}},
-
- {{1.93281168,2.58856757}, {2.38543691,2.7096125}, {2.51967352,2.34531784}},
- {{2.51967352,2.34531784}, {2.65263731,2.00639194}, {3.1212119,1.98608967}},
- {{2.09544533,2.51981963}, {2.33331524,2.25252128}, {2.92003302,2.39442311}},
-
-
-{{0.924337655,1.94072717}, {1.25185043,1.52836494}, {1.71793901,1.06149951}},
-{{0.940798831,1.67439357}, {1.25988251,1.39778567}, {1.71791672,1.06650313}},
-
- {{0.924337655,1.94072717}, {1.39158994,1.32418496}, {2.14967426,0.687365435}},
- {{0.940798831,1.67439357}, {1.48941875,1.16280321}, {2.47884711,0.60465921}},
-
- {{1.7465749139282332,1.9930452039527999}, {1.8320006564080331,1.859481345189089}, {1.8731035127758437,1.6344055934266613}},
- {{1.8731035127758437,1.6344055934266613}, {1.89928170345231,1.5006405518943067}, {1.9223833226085514,1.3495796165215643}},
- {{1.74657491,1.9930452}, {1.87407679,1.76762853}, {1.92238332,1.34957962}},
- {{0.60797907,1.68776977}, {1.0447864,1.50810914}, {1.87464474,1.63655092}},
- {{1.87464474,1.63655092}, {2.70450308,1.76499271}, {4,3}},
-
-{{1.2071879545809394,0.82163474041730045}, {1.1534203513372994,0.52790870069930229}, {1.0880000000000001,0.29599999999999982}}, //t=0.63155333662549329,0.80000000000000004
-{{0.33333333333333326,0.81481481481481488}, {0.63395173631977997,0.68744136726313931}, {1.205684411948591,0.81344322326274499}},
-{{0.33333333333333326,0.81481481481481488}, {0.63396444791444551,0.68743368362444768}, {1.205732763658403,0.81345617746834109}},//t=0.33333333333333331,0.63396444791444551
-{{1.205684411948591,0.81344322326274499}, {1.2057085875611198,0.81344969999329253}, {1.205732763658403,0.81345617746834109}},
-
- {{1.20718795,0.82163474}, {1.15342035,0.527908701}, {1.088,0.296}},
- {{1.20568441,0.813443223}, {1.20570859,0.8134497}, {1.20573276,0.813456177}},
-
- {{41.5072916,87.1234036}, {28.2747836,80.9545395}, {23.5780771,69.3344126}},
- {{72.9633878,95.6593007}, {42.7738746,88.4730382}, {31.1932785,80.2458029}},
-
- {{31.1663962,54.7302484}, {31.1662882,54.7301074}, {31.1663969,54.7302485}},
- {{26.0404936,45.4260361}, {27.7887523,33.1863051}, {40.8833242,26.0301855}},
-
- {{29.9404074,49.1672596}, {44.3131071,45.3915253}, {58.1067559,59.5061814}},
- {{72.6510251,64.2972928}, {53.6989659,60.1862397}, {35.2053722,44.8391126}},
-
-{{52.14807018377202, 65.012420045148644}, {44.778669050208237, 66.315562705604378}, {51.619118408823567, 63.787827046262684}},
-{{30.004993234763383, 93.921296668202288}, {53.384822003076991, 60.732180341802753}, {58.652998934338584, 43.111073088306185}},
-
-{{80.897794748143198, 49.236332042718459}, {81.082078218891212, 64.066749904488631}, {69.972305057149981, 72.968595519850993}},
-{{72.503745601281395, 32.952320736577882}, {88.030880716061645, 38.137194847810164}, {73.193774825517906, 67.773492479591397}},
-
-{{67.426548091427676, 37.993772624988935}, {51.129513170665035, 57.542281234563646}, {44.594748190899189, 65.644267382683879}},
-{{61.336508189019057, 82.693132843213675}, {54.825078921449354, 71.663932799212432}, {47.727444217558926, 61.4049645128392}},
-
-{{67.4265481,37.9937726}, {51.1295132,57.5422812}, {44.5947482,65.6442674}},
-{{61.3365082,82.6931328}, {54.8250789,71.6639328}, {47.7274442,61.4049645}},
-
-{{53.774852327053594, 53.318060789841951}, {45.787877803416805, 51.393492026284981}, {46.703936967162392, 53.06860709822206}},
-{{46.703936967162392, 53.06860709822206}, {47.619996130907957, 54.74372217015916}, {53.020051653535361, 48.633140968832024}},
-
-{{50.934805397717923, 51.52391952648901}, {56.803308902971423, 44.246234610627596}, {69.776888596721406, 40.166645096692555}},
-{{50.230212796400401, 38.386469101526998}, {49.855620812184917, 38.818990392153609}, {56.356567496227363, 47.229909093319407}},
-
-{{36.148792695174222, 70.336952793070424}, {36.141613037691357, 70.711654739870085}, {36.154708826402597, 71.088492662905836}},
-{{35.216235592661825, 70.580199617313212}, {36.244476835123969, 71.010897787304074}, {37.230244263238326, 71.423156953613102}},
-
-// this pair is nearly coincident, and causes the quartic code to produce bad
-// data. Mathematica doesn't think they touch. Graphically, I can't tell.
-// it may not be so bad to pretend that they don't touch, if I can detect that
-{{369.848602,145.680267}, {382.360413,121.298294}, {406.207703,121.298294}},
-{{369.850525,145.675964}, {382.362915,121.29287}, {406.211273,121.29287}},
-
-{{33.567436351153468, 62.336347586395924}, {35.200980274619084, 65.038561460144479}, {36.479571811084995, 67.632178905412445}},
-{{41.349524945572696, 67.886658677862641}, {39.125562529359087, 67.429772735149214}, {35.600314083992416, 66.705372160552685}},
-
-{{67.25299631583178, 21.109080184767524}, {43.617595267398613, 33.658034168577529}, {33.38371819435676, 44.214192553988745}},
-{{40.476838859398541, 39.543209911285999}, {36.701186108431131, 34.8817994016458}, {30.102144288878023, 26.739063172945315}},
-
-{{25.367434474345036, 50.4712103169743}, {17.865013304933097, 37.356741010559439}, {16.818988838905465, 37.682915484123129}},
-{{16.818988838905465, 37.682915484123129}, {15.772964372877833, 38.009089957686811}, {20.624104547604965, 41.825131596683121}},
-
-{{26.440225044088567, 79.695009812848298}, {26.085525979582247, 83.717928354134784}, {27.075079976297072, 84.820633667838905}},
-{{27.075079976297072, 84.820633667838905}, {28.276546859574015, 85.988574184029034}, {25.649263209500006, 87.166762066617025}},
-
-{{34.879150914024962, 83.862726601601125}, {35.095810134304429, 83.693473210169543}, {35.359284111931586, 83.488069234177502}},
-{{54.503204203015471, 76.094098492518242}, {51.366889541918894, 71.609856061299155}, {46.53086955445437, 69.949863036494207}},
-
-{{0, 0}, {1, 0}, {0, 3}},
-{{1, 0}, {0, 1}, {1, 1}},
-{{369.961151,137.980698}, {383.970093,121.298294}, {406.213287,121.298294}},
-{{353.2948,194.351074}, {353.2948,173.767563}, {364.167572,160.819855}},
-{{360.416077,166.795715}, {370.126831,147.872162}, {388.635406,147.872162}},
-{{406.236359,121.254936}, {409.445679,121.254936}, {412.975952,121.789818}},
-{{406.235992,121.254936}, {425.705902,121.254936}, {439.71994,137.087616}},
-
-{{369.8543701171875, 145.66734313964844}, {382.36788940429688, 121.28203582763672}, {406.21844482421875, 121.28203582763672}},
-{{369.96469116210938, 137.96672058105469}, {383.97555541992188, 121.28203582763672}, {406.2218017578125, 121.28203582763672}},
-
- {{369.962311, 137.976044}, {383.971893, 121.29287}, {406.216125, 121.29287}},
-
- {{400.121704, 149.468719}, {391.949493, 161.037186}, {391.949493, 181.202423}},
- {{391.946747, 181.839218}, {391.946747, 155.62442}, {406.115479, 138.855438}},
- {{360.048828125, 229.2578125}, {360.048828125, 224.4140625}, {362.607421875, 221.3671875}},
- {{362.607421875, 221.3671875}, {365.166015625, 218.3203125}, {369.228515625, 218.3203125}},
- {{8, 8}, {10, 10}, {8, -10}},
- {{8, 8}, {12, 12}, {14, 4}},
- {{8, 8}, {9, 9}, {10, 8}}
-};
-
-const size_t testSetCount = sizeof(testSet) / sizeof(testSet[0]);
-
-static void oneOffTest1(size_t outer, size_t inner) {
- const Quadratic& quad1 = testSet[outer];
- const Quadratic& quad2 = testSet[inner];
- Intersections intersections2;
- intersect2(quad1, quad2, intersections2);
- if (intersections2.fUnsortable) {
- SkASSERT(0);
- return;
- }
- for (int pt = 0; pt < intersections2.used(); ++pt) {
- double tt1 = intersections2.fT[0][pt];
- double tx1, ty1;
- xy_at_t(quad1, tt1, tx1, ty1);
- int pt2 = intersections2.fFlip ? intersections2.used() - pt - 1 : pt;
- double tt2 = intersections2.fT[1][pt2];
- double tx2, ty2;
- xy_at_t(quad2, tt2, tx2, ty2);
- if (!AlmostEqualUlps(tx1, tx2)) {
- SkDebugf("%s [%d,%d] x!= t1=%g (%g,%g) t2=%g (%g,%g)\n",
- __FUNCTION__, (int)outer, (int)inner, tt1, tx1, ty1, tt2, tx2, ty2);
- SkASSERT(0);
- }
- if (!AlmostEqualUlps(ty1, ty2)) {
- SkDebugf("%s [%d,%d] y!= t1=%g (%g,%g) t2=%g (%g,%g)\n",
- __FUNCTION__, (int)outer, (int)inner, tt1, tx1, ty1, tt2, tx2, ty2);
- SkASSERT(0);
- }
-#if ONE_OFF_DEBUG
- SkDebugf("%s [%d][%d] t1=%1.9g (%1.9g, %1.9g) t2=%1.9g\n", __FUNCTION__,
- outer, inner, tt1, tx1, ty1, tt2);
-#endif
- }
-}
-
-void QuadraticIntersection_OneOffTest() {
- oneOffTest1(0, 1);
- oneOffTest1(1, 0);
-}
-
-static void oneOffTests() {
- for (size_t outer = 0; outer < testSetCount - 1; ++outer) {
- for (size_t inner = outer + 1; inner < testSetCount; ++inner) {
- oneOffTest1(outer, inner);
- }
- }
-}
-
-static const Quadratic coincidentTestSet[] = {
- {{369.850525, 145.675964}, {382.362915, 121.29287}, {406.211273, 121.29287}},
- {{369.850525, 145.675964}, {382.362915, 121.29287}, {406.211273, 121.29287}},
- {{8, 8}, {10, 10}, {8, -10}},
- {{8, -10}, {10, 10}, {8, 8}},
-};
-
-const size_t coincidentTestSetCount = sizeof(coincidentTestSet) / sizeof(coincidentTestSet[0]);
-
-static void coincidentTest() {
- for (size_t testIndex = 0; testIndex < coincidentTestSetCount - 1; testIndex += 2) {
- const Quadratic& quad1 = coincidentTestSet[testIndex];
- const Quadratic& quad2 = coincidentTestSet[testIndex + 1];
- Intersections intersections2;
- intersect2(quad1, quad2, intersections2);
- SkASSERT(intersections2.coincidentUsed() == 2);
- SkASSERT(intersections2.used() == 2);
- for (int pt = 0; pt < intersections2.coincidentUsed(); ++pt) {
- SkDEBUGCODE(double tt1 = intersections2.fT[0][pt]);
- SkDEBUGCODE(double tt2 = intersections2.fT[1][pt]);
- SkASSERT(approximately_equal(1, tt1) || approximately_zero(tt1));
- SkASSERT(approximately_equal(1, tt2) || approximately_zero(tt2));
- }
- }
-}
-
-void QuadraticIntersection_Test() {
- oneOffTests();
- coincidentTest();
- standardTestCases();
-}
-
-static int floatSign(double x) {
- return x < 0 ? -1 : x > 0 ? 1 : 0;
-}
-
-static const Quadratic pointFinderTestSet[] = {
- //>=0.633974464 0.633974846 <=
-{{1.2071879545809394,0.82163474041730045}, {1.1534203513372994,0.52790870069930229}, {1.0880000000000001,0.29599999999999982}}, //t=0.63155333662549329,0.80000000000000004
-{{1.2071879545809394,0.82163474041730045}, {1.2065040319428038,0.81766753259119995}, {1.2058123269101506,0.81370135061854221}}, //t=0.63155333662549329,0.6339049773632347
-{{1.2058123269101506,0.81370135061854221}, {1.152376363978022,0.5244097415381026}, {1.0880000000000001,0.29599999999999982}}, //t=0.6339049773632347, 0.80000000000000004
- //>=0.633974083 0.633975227 <=
-{{0.33333333333333326,0.81481481481481488}, {0.63395173631977997,0.68744136726313931}, {1.205684411948591,0.81344322326274499}},//t=0.33333333333333331,0.63395173631977986
-{{0.33333333333333326,0.81481481481481488}, {0.63396444791444551,0.68743368362444768}, {1.205732763658403,0.81345617746834109}},//t=0.33333333333333331,0.63396444791444551
-{{1.205684411948591,0.81344322326274499}, {1.2057085875611198,0.81344969999329253}, {1.205732763658403,0.81345617746834109}}, //t=0.63395173631977986,0.63396444791444551
-{{1.205732763658403,0.81345617746834109}, {1.267928895828891,0.83008534558465619}, {1.3333333333333333,0.85185185185185175}}, //t=0.63396444791444551,0.66666666666666663
-};
-
-static void pointFinder(const Quadratic& q1, const Quadratic& q2) {
- for (int index = 0; index < 3; ++index) {
- double t = nearestT(q1, q2[index]);
- _Point onQuad;
- xy_at_t(q1, t, onQuad.x, onQuad.y);
- SkDebugf("%s t=%1.9g (%1.9g,%1.9g) dist=%1.9g\n", __FUNCTION__, t, onQuad.x, onQuad.y,
- onQuad.distance(q2[index]));
- double left[3];
- left[0] = is_left((const _Line&) q1[0], q2[index]);
- left[1] = is_left((const _Line&) q1[1], q2[index]);
- _Line diag = {q1[0], q1[2]};
- left[2] = is_left(diag, q2[index]);
- SkDebugf("%s left=(%d, %d, %d) inHull=%s\n", __FUNCTION__, floatSign(left[0]),
- floatSign(left[1]), floatSign(left[2]),
- point_in_hull(q1, q2[index]) ? "true" : "false");
- }
- SkDebugf("\n");
-}
-
-static void hullIntersect(const Quadratic& q1, const Quadratic& q2) {
- SkDebugf("%s", __FUNCTION__);
- Intersections ts;
- for (int i1 = 0; i1 < 3; ++i1) {
- _Line l1 = {q1[i1], q1[(i1 + 1) % 3]};
- for (int i2 = 0; i2 < 3; ++i2) {
- _Line l2 = {q2[i2], q2[(i2 + 1) % 3]};
- if (intersect(l1, l2, ts)) {
- SkDebugf(" [%d,%d]", i1, i2);
- }
- }
- }
- SkDebugf("\n");
-}
-
-void QuadraticIntersection_PointFinder() {
- pointFinder(pointFinderTestSet[0], pointFinderTestSet[4]);
- pointFinder(pointFinderTestSet[4], pointFinderTestSet[0]);
- pointFinder(pointFinderTestSet[0], pointFinderTestSet[6]);
- pointFinder(pointFinderTestSet[6], pointFinderTestSet[0]);
- hullIntersect(pointFinderTestSet[0], pointFinderTestSet[4]);
- hullIntersect(pointFinderTestSet[0], pointFinderTestSet[6]);
-}
-
-static void intersectionFinder(int test1, int test2) {
- const Quadratic& quad1 = testSet[test1];
- const Quadratic& quad2 = testSet[test2];
-
- double t1Seed = 0.5;
- double t2Seed = 0.8;
- double t1Step = 0.1;
- double t2Step = 0.1;
- _Point t1[3], t2[3];
- bool toggle = true;
- do {
- xy_at_t(quad1, t1Seed - t1Step, t1[0].x, t1[0].y);
- xy_at_t(quad1, t1Seed, t1[1].x, t1[1].y);
- xy_at_t(quad1, t1Seed + t1Step, t1[2].x, t1[2].y);
- xy_at_t(quad2, t2Seed - t2Step, t2[0].x, t2[0].y);
- xy_at_t(quad2, t2Seed, t2[1].x, t2[1].y);
- xy_at_t(quad2, t2Seed + t2Step, t2[2].x, t2[2].y);
- double dist[3][3];
- dist[1][1] = t1[1].distance(t2[1]);
- int best_i = 1, best_j = 1;
- for (int i = 0; i < 3; ++i) {
- for (int j = 0; j < 3; ++j) {
- if (i == 1 && j == 1) {
- continue;
- }
- dist[i][j] = t1[i].distance(t2[j]);
- if (dist[best_i][best_j] > dist[i][j]) {
- best_i = i;
- best_j = j;
- }
- }
- }
- if (best_i == 0) {
- t1Seed -= t1Step;
- } else if (best_i == 2) {
- t1Seed += t1Step;
- }
- if (best_j == 0) {
- t2Seed -= t2Step;
- } else if (best_j == 2) {
- t2Seed += t2Step;
- }
- if (best_i == 1 && best_j == 1) {
- if ((toggle ^= true)) {
- t1Step /= 2;
- } else {
- t2Step /= 2;
- }
- }
- } while (!t1[1].approximatelyEqual(t2[1]));
- t1Step = t2Step = 0.1;
- double t10 = t1Seed - t1Step * 2;
- double t12 = t1Seed + t1Step * 2;
- double t20 = t2Seed - t2Step * 2;
- double t22 = t2Seed + t2Step * 2;
- _Point test;
- while (!approximately_zero(t1Step)) {
- xy_at_t(quad1, t10, test.x, test.y);
- t10 += t1[1].approximatelyEqual(test) ? -t1Step : t1Step;
- t1Step /= 2;
- }
- t1Step = 0.1;
- while (!approximately_zero(t1Step)) {
- xy_at_t(quad1, t12, test.x, test.y);
- t12 -= t1[1].approximatelyEqual(test) ? -t1Step : t1Step;
- t1Step /= 2;
- }
- while (!approximately_zero(t2Step)) {
- xy_at_t(quad2, t20, test.x, test.y);
- t20 += t2[1].approximatelyEqual(test) ? -t2Step : t2Step;
- t2Step /= 2;
- }
- t2Step = 0.1;
- while (!approximately_zero(t2Step)) {
- xy_at_t(quad2, t22, test.x, test.y);
- t22 -= t2[1].approximatelyEqual(test) ? -t2Step : t2Step;
- t2Step /= 2;
- }
-#if ONE_OFF_DEBUG
- SkDebugf("%s t1=(%1.9g<%1.9g<%1.9g) t2=(%1.9g<%1.9g<%1.9g)\n", __FUNCTION__,
- t10, t1Seed, t12, t20, t2Seed, t22);
- _Point p10 = xy_at_t(quad1, t10);
- _Point p1Seed = xy_at_t(quad1, t1Seed);
- _Point p12 = xy_at_t(quad1, t12);
- SkDebugf("%s p1=(%1.9g,%1.9g)<(%1.9g,%1.9g)<(%1.9g,%1.9g)\n", __FUNCTION__,
- p10.x, p10.y, p1Seed.x, p1Seed.y, p12.x, p12.y);
- _Point p20 = xy_at_t(quad2, t20);
- _Point p2Seed = xy_at_t(quad2, t2Seed);
- _Point p22 = xy_at_t(quad2, t22);
- SkDebugf("%s p2=(%1.9g,%1.9g)<(%1.9g,%1.9g)<(%1.9g,%1.9g)\n", __FUNCTION__,
- p20.x, p20.y, p2Seed.x, p2Seed.y, p22.x, p22.y);
-#endif
-}
-
-void QuadraticIntersection_IntersectionFinder() {
- intersectionFinder(0, 1);
-}
diff --git a/experimental/Intersection/QuadraticIntersection_TestData.cpp b/experimental/Intersection/QuadraticIntersection_TestData.cpp
deleted file mode 100644
index 9ec585a730..0000000000
--- a/experimental/Intersection/QuadraticIntersection_TestData.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "QuadraticIntersection_TestData.h"
-
-const Quadratic quadraticLines[] = {
- {{0, 0}, {0, 0}, {1, 0}},
- {{0, 0}, {1, 0}, {0, 0}},
- {{1, 0}, {0, 0}, {0, 0}},
- {{1, 0}, {2, 0}, {3, 0}},
- {{0, 0}, {0, 0}, {0, 1}},
- {{0, 0}, {0, 1}, {0, 0}},
- {{0, 1}, {0, 0}, {0, 0}},
- {{0, 1}, {0, 2}, {0, 3}},
- {{0, 0}, {0, 0}, {1, 1}},
- {{0, 0}, {1, 1}, {0, 0}},
- {{1, 1}, {0, 0}, {0, 0}},
- {{1, 1}, {2, 2}, {3, 3}},
- {{1, 1}, {3, 3}, {3, 3}},
- {{1, 1}, {1, 1}, {2, 2}},
- {{1, 1}, {2, 2}, {1, 1}},
- {{1, 1}, {1, 1}, {3, 3}},
- {{1, 1}, {2, 2}, {4, 4}}, // no coincident
- {{1, 1}, {3, 3}, {4, 4}},
- {{1, 1}, {3, 3}, {2, 2}},
- {{1, 1}, {4, 4}, {2, 2}},
- {{1, 1}, {4, 4}, {3, 3}},
- {{2, 2}, {1, 1}, {3, 3}},
- {{2, 2}, {1, 1}, {4, 4}},
- {{2, 2}, {3, 3}, {1, 1}},
- {{2, 2}, {3, 3}, {4, 4}},
- {{2, 2}, {4, 4}, {1, 1}},
- {{2, 2}, {4, 4}, {3, 3}},
-};
-
-const size_t quadraticLines_count = sizeof(quadraticLines) / sizeof(quadraticLines[0]);
-
-static const double F = PointEpsilon * 3;
-static const double H = PointEpsilon * 4;
-static const double J = PointEpsilon * 5;
-static const double K = PointEpsilon * 8; // INVESTIGATE: why are larger multiples necessary?
-
-const Quadratic quadraticModEpsilonLines[] = {
- {{0, F}, {0, 0}, {1, 0}},
- {{0, 0}, {1, 0}, {0, F}},
- {{1, 0}, {0, F}, {0, 0}},
- {{1, H}, {2, 0}, {3, 0}},
- {{F, 0}, {0, 0}, {0, 1}},
- {{0, 0}, {0, 1}, {F, 0}},
- {{0, 1}, {F, 0}, {0, 0}},
- {{H, 1}, {0, 2}, {0, 3}},
- {{0, F}, {0, 0}, {1, 1}},
- {{0, 0}, {1, 1}, {F, 0}},
- {{1, 1}, {F, 0}, {0, 0}},
- {{1, 1+J}, {2, 2}, {3, 3}},
- {{1, 1}, {3, 3}, {3+F, 3}},
- {{1, 1}, {1+F, 1}, {2, 2}},
- {{1, 1}, {2, 2}, {1, 1+F}},
- {{1, 1}, {1, 1+F}, {3, 3}},
- {{1+H, 1}, {2, 2}, {4, 4}}, // no coincident
- {{1, 1+K}, {3, 3}, {4, 4}},
- {{1, 1}, {3+F, 3}, {2, 2}},
- {{1, 1}, {4, 4+F}, {2, 2}},
- {{1, 1}, {4, 4}, {3+F, 3}},
- {{2, 2}, {1, 1}, {3, 3+F}},
- {{2+F, 2}, {1, 1}, {4, 4}},
- {{2, 2+F}, {3, 3}, {1, 1}},
- {{2, 2}, {3+F, 3}, {4, 4}},
- {{2, 2}, {4, 4+F}, {1, 1}},
- {{2, 2}, {4, 4}, {3+F, 3}},
-};
-
-const size_t quadraticModEpsilonLines_count = sizeof(quadraticModEpsilonLines) / sizeof(quadraticModEpsilonLines[0]);
-
-const Quadratic quadraticTests[][2] = {
- { // one intersection
- {{0, 0},
- {0, 1},
- {1, 1}},
- {{0, 1},
- {0, 0},
- {1, 0}}
- },
- { // four intersections
- {{1, 0},
- {2, 6},
- {3, 0}},
- {{0, 1},
- {6, 2},
- {0, 3}}
- }
-};
-
-const size_t quadraticTests_count = sizeof(quadraticTests) / sizeof(quadraticTests[0]);
diff --git a/experimental/Intersection/QuadraticIntersection_TestData.h b/experimental/Intersection/QuadraticIntersection_TestData.h
deleted file mode 100644
index 2dbf34a29c..0000000000
--- a/experimental/Intersection/QuadraticIntersection_TestData.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "DataTypes.h"
-#include "DataTypes_Test.h"
-
-extern const Quadratic quadraticLines[];
-extern const Quadratic quadraticModEpsilonLines[];
-extern const Quadratic quadraticTests[][2];
-
-extern const size_t quadraticLines_count;
-extern const size_t quadraticModEpsilonLines_count;
-extern const size_t quadraticTests_count;
diff --git a/experimental/Intersection/QuadraticLineSegments.cpp b/experimental/Intersection/QuadraticLineSegments.cpp
deleted file mode 100644
index 5e26d35f87..0000000000
--- a/experimental/Intersection/QuadraticLineSegments.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "QuadraticLineSegments.h"
-
-// http://cagd.cs.byu.edu/~557/text/cagd.pdf 2.7
-// A hodograph is the first derivative curve
-void hodograph(const Quadratic& quad, _Line& hodo) {
- hodo[0].x = 2 * (quad[1].x - quad[0].x);
- hodo[0].y = 2 * (quad[1].y - quad[0].y);
- hodo[1].x = 2 * (quad[2].x - quad[1].x);
- hodo[1].y = 2 * (quad[2].y - quad[1].y);
-}
-
-// A 2nd hodograph is the second derivative curve
-void secondHodograph(const Quadratic& quad, _Point& hodo2) {
- _Line hodo;
- hodograph(quad, hodo);
- hodo2.x = hodo[1].x - hodo[0].x;
- hodo2.y = hodo[1].y - hodo[0].y;
-}
-
-// The number of line segments required to approximate the quad
-// see http://cagd.cs.byu.edu/~557/text/cagd.pdf 10.6
-double subDivisions(const Quadratic& quad) {
- _Point hodo2;
- secondHodograph(quad, hodo2);
- double dist = sqrt(hodo2.x * hodo2.x + hodo2.y * hodo2.y);
- double segments = sqrt(dist / (8 * FLT_EPSILON));
- return segments;
-}
diff --git a/experimental/Intersection/QuadraticLineSegments.h b/experimental/Intersection/QuadraticLineSegments.h
deleted file mode 100644
index 640a69b787..0000000000
--- a/experimental/Intersection/QuadraticLineSegments.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "DataTypes.h"
-
-void hodograph(const Quadratic& , _Line& hodo);
-void secondHodograph(const Quadratic& , _Point& hodo2);
-double subDivisions(const Quadratic& );
diff --git a/experimental/Intersection/QuadraticParameterization.cpp b/experimental/Intersection/QuadraticParameterization.cpp
deleted file mode 100644
index 76441aa4d5..0000000000
--- a/experimental/Intersection/QuadraticParameterization.cpp
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "CurveIntersection.h"
-#include "QuadraticParameterization.h"
-#include "QuadraticUtilities.h"
-
-/* from http://tom.cs.byu.edu/~tom/papers/cvgip84.pdf 4.1
- *
- * This paper proves that Syvester's method can compute the implicit form of
- * the quadratic from the parameterized form.
- *
- * Given x = a*t*t + b*t + c (the parameterized form)
- * y = d*t*t + e*t + f
- *
- * we want to find an equation of the implicit form:
- *
- * A*x*x + B*x*y + C*y*y + D*x + E*y + F = 0
- *
- * The implicit form can be expressed as a 4x4 determinant, as shown.
- *
- * The resultant obtained by Syvester's method is
- *
- * | a b (c - x) 0 |
- * | 0 a b (c - x) |
- * | d e (f - y) 0 |
- * | 0 d e (f - y) |
- *
- * which expands to
- *
- * d*d*x*x + -2*a*d*x*y + a*a*y*y
- * + (-2*c*d*d + b*e*d - a*e*e + 2*a*f*d)*x
- * + (-2*f*a*a + e*b*a - d*b*b + 2*d*c*a)*y
- * +
- * | a b c 0 |
- * | 0 a b c | == 0.
- * | d e f 0 |
- * | 0 d e f |
- *
- * Expanding the constant determinant results in
- *
- * | a b c | | b c 0 |
- * a*| e f 0 | + d*| a b c | ==
- * | d e f | | d e f |
- *
- * a*(a*f*f + c*e*e - c*f*d - b*e*f) + d*(b*b*f + c*c*d - c*a*f - c*e*b)
- *
- */
-
-
-static bool straight_forward = true;
-
-QuadImplicitForm::QuadImplicitForm(const Quadratic& q) {
- double a, b, c;
- set_abc(&q[0].x, a, b, c);
- double d, e, f;
- set_abc(&q[0].y, d, e, f);
- // compute the implicit coefficients
- if (straight_forward) { // 42 muls, 13 adds
- p[xx_coeff] = d * d;
- p[xy_coeff] = -2 * a * d;
- p[yy_coeff] = a * a;
- p[x_coeff] = -2*c*d*d + b*e*d - a*e*e + 2*a*f*d;
- p[y_coeff] = -2*f*a*a + e*b*a - d*b*b + 2*d*c*a;
- p[c_coeff] = a*(a*f*f + c*e*e - c*f*d - b*e*f)
- + d*(b*b*f + c*c*d - c*a*f - c*e*b);
- } else { // 26 muls, 11 adds
- double aa = a * a;
- double ad = a * d;
- double dd = d * d;
- p[xx_coeff] = dd;
- p[xy_coeff] = -2 * ad;
- p[yy_coeff] = aa;
- double be = b * e;
- double bde = be * d;
- double cdd = c * dd;
- double ee = e * e;
- p[x_coeff] = -2*cdd + bde - a*ee + 2*ad*f;
- double aaf = aa * f;
- double abe = a * be;
- double ac = a * c;
- double bb_2ac = b*b - 2*ac;
- p[y_coeff] = -2*aaf + abe - d*bb_2ac;
- p[c_coeff] = aaf*f + ac*ee + d*f*bb_2ac - abe*f + c*cdd - c*bde;
- }
-}
-
- /* Given a pair of quadratics, determine their parametric coefficients.
- * If the scaled coefficients are nearly equal, then the part of the quadratics
- * may be coincident.
- * FIXME: optimization -- since comparison short-circuits on no match,
- * lazily compute the coefficients, comparing the easiest to compute first.
- * xx and yy first; then xy; and so on.
- */
-bool QuadImplicitForm::implicit_match(const QuadImplicitForm& p2) const {
- int first = 0;
- for (int index = 0; index < coeff_count; ++index) {
- if (approximately_zero(p[index]) && approximately_zero(p2.p[index])) {
- first += first == index;
- continue;
- }
- if (first == index) {
- continue;
- }
- if (!AlmostEqualUlps(p[index] * p2.p[first], p[first] * p2.p[index])) {
- return false;
- }
- }
- return true;
-}
-
-bool implicit_matches(const Quadratic& quad1, const Quadratic& quad2) {
- QuadImplicitForm i1(quad1); // a'xx , b'xy , c'yy , d'x , e'y , f
- QuadImplicitForm i2(quad2);
- return i1.implicit_match(i2);
-}
-
-static double tangent(const double* quadratic, double t) {
- double a, b, c;
- set_abc(quadratic, a, b, c);
- return 2 * a * t + b;
-}
-
-void tangent(const Quadratic& quadratic, double t, _Point& result) {
- result.x = tangent(&quadratic[0].x, t);
- result.y = tangent(&quadratic[0].y, t);
-}
-
-
-
-// unit test to return and validate parametric coefficients
-#include "QuadraticParameterization_TestUtility.cpp"
diff --git a/experimental/Intersection/QuadraticParameterization.h b/experimental/Intersection/QuadraticParameterization.h
deleted file mode 100644
index ca7d072208..0000000000
--- a/experimental/Intersection/QuadraticParameterization.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#include "DataTypes.h"
-
-class QuadImplicitForm {
-public:
- QuadImplicitForm(const Quadratic& q);
- bool implicit_match(const QuadImplicitForm& two) const;
-
- double x2() const { return p[xx_coeff]; }
- double xy() const { return p[xy_coeff]; }
- double y2() const { return p[yy_coeff]; }
- double x() const { return p[x_coeff]; }
- double y() const { return p[y_coeff]; }
- double c() const { return p[c_coeff]; }
-
-private:
- enum Coeffs {
- xx_coeff,
- xy_coeff,
- yy_coeff,
- x_coeff,
- y_coeff,
- c_coeff,
- coeff_count
- };
-
- double p[coeff_count];
-};
diff --git a/experimental/Intersection/QuadraticParameterization_Test.cpp b/experimental/Intersection/QuadraticParameterization_Test.cpp
deleted file mode 100644
index eedd6a45bf..0000000000
--- a/experimental/Intersection/QuadraticParameterization_Test.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "CurveIntersection.h"
-#include "Intersection_Tests.h"
-#include "Parameterization_Test.h"
-#include "QuadraticUtilities.h"
-
-const Quadratic quadratics[] = {
- {{0, 0}, {1, 0}, {1, 1}},
-};
-
-const size_t quadratics_count = sizeof(quadratics) / sizeof(quadratics[0]);
-
-int firstQuadraticCoincidenceTest = 0;
-
-void QuadraticCoincidence_Test() {
- // split large quadratic
- // compare original, parts, to see if the are coincident
- for (size_t index = firstQuadraticCoincidenceTest; index < quadratics_count; ++index) {
- const Quadratic& test = quadratics[index];
- QuadraticPair split;
- chop_at(test, split, 0.5);
- Quadratic midThird;
- sub_divide(test, 1.0/3, 2.0/3, midThird);
- const Quadratic* quads[] = {
- &test, &midThird, &split.first(), &split.second()
- };
- size_t quadsCount = sizeof(quads) / sizeof(quads[0]);
- for (size_t one = 0; one < quadsCount; ++one) {
- for (size_t two = 0; two < quadsCount; ++two) {
- for (size_t inner = 0; inner < 3; inner += 2) {
- if (!point_on_parameterized_curve(*quads[one], (*quads[two])[inner])) {
- SkDebugf("%s %zu [%zu,%zu] %zu parameterization failed\n",
- __FUNCTION__, index, one, two, inner);
- }
- }
- if (!implicit_matches(*quads[one], *quads[two])) {
- SkDebugf("%s %zu [%zu,%zu] coincidence failed\n", __FUNCTION__,
- index, one, two);
- }
- }
- }
- }
-}
diff --git a/experimental/Intersection/QuadraticParameterization_TestUtility.cpp b/experimental/Intersection/QuadraticParameterization_TestUtility.cpp
deleted file mode 100644
index 7c91eb5e8b..0000000000
--- a/experimental/Intersection/QuadraticParameterization_TestUtility.cpp
+++ /dev/null
@@ -1,16 +0,0 @@
-// included by QuadraticParameterization.cpp
-// accesses internal functions to validate parameterized coefficients
-
-#include "Parameterization_Test.h"
-
-bool point_on_parameterized_curve(const Quadratic& quad, const _Point& point) {
- QuadImplicitForm q(quad);
- double xx = q.x2() * point.x * point.x;
- double xy = q.xy() * point.x * point.y;
- double yy = q.y2() * point.y * point.y;
- double x = q.x() * point.x;
- double y = q.y() * point.y;
- double c = q.c();
- double sum = xx + xy + yy + x + y + c;
- return approximately_zero(sum);
-}
diff --git a/experimental/Intersection/QuadraticReduceOrder.cpp b/experimental/Intersection/QuadraticReduceOrder.cpp
deleted file mode 100644
index 27c7a29bf2..0000000000
--- a/experimental/Intersection/QuadraticReduceOrder.cpp
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "CurveIntersection.h"
-#include "Extrema.h"
-#include "IntersectionUtilities.h"
-#include "LineParameters.h"
-
-static double interp_quad_coords(double a, double b, double c, double t)
-{
- double ab = interp(a, b, t);
- double bc = interp(b, c, t);
- return interp(ab, bc, t);
-}
-
-static int coincident_line(const Quadratic& quad, Quadratic& reduction) {
- reduction[0] = reduction[1] = quad[0];
- return 1;
-}
-
-static int vertical_line(const Quadratic& quad, ReduceOrder_Styles reduceStyle,
- Quadratic& reduction) {
- double tValue;
- reduction[0] = quad[0];
- reduction[1] = quad[2];
- if (reduceStyle == kReduceOrder_TreatAsFill) {
- return 2;
- }
- int smaller = reduction[1].y > reduction[0].y;
- int larger = smaller ^ 1;
- if (findExtrema(quad[0].y, quad[1].y, quad[2].y, &tValue)) {
- double yExtrema = interp_quad_coords(quad[0].y, quad[1].y, quad[2].y, tValue);
- if (reduction[smaller].y > yExtrema) {
- reduction[smaller].y = yExtrema;
- } else if (reduction[larger].y < yExtrema) {
- reduction[larger].y = yExtrema;
- }
- }
- return 2;
-}
-
-static int horizontal_line(const Quadratic& quad, ReduceOrder_Styles reduceStyle,
- Quadratic& reduction) {
- double tValue;
- reduction[0] = quad[0];
- reduction[1] = quad[2];
- if (reduceStyle == kReduceOrder_TreatAsFill) {
- return 2;
- }
- int smaller = reduction[1].x > reduction[0].x;
- int larger = smaller ^ 1;
- if (findExtrema(quad[0].x, quad[1].x, quad[2].x, &tValue)) {
- double xExtrema = interp_quad_coords(quad[0].x, quad[1].x, quad[2].x, tValue);
- if (reduction[smaller].x > xExtrema) {
- reduction[smaller].x = xExtrema;
- } else if (reduction[larger].x < xExtrema) {
- reduction[larger].x = xExtrema;
- }
- }
- return 2;
-}
-
-static int check_linear(const Quadratic& quad, ReduceOrder_Styles reduceStyle,
- int minX, int maxX, int minY, int maxY, Quadratic& reduction) {
- int startIndex = 0;
- int endIndex = 2;
- while (quad[startIndex].approximatelyEqual(quad[endIndex])) {
- --endIndex;
- if (endIndex == 0) {
- printf("%s shouldn't get here if all four points are about equal", __FUNCTION__);
- SkASSERT(0);
- }
- }
- if (!isLinear(quad, startIndex, endIndex)) {
- return 0;
- }
- // four are colinear: return line formed by outside
- reduction[0] = quad[0];
- reduction[1] = quad[2];
- if (reduceStyle == kReduceOrder_TreatAsFill) {
- return 2;
- }
- int sameSide;
- bool useX = quad[maxX].x - quad[minX].x >= quad[maxY].y - quad[minY].y;
- if (useX) {
- sameSide = sign(quad[0].x - quad[1].x) + sign(quad[2].x - quad[1].x);
- } else {
- sameSide = sign(quad[0].y - quad[1].y) + sign(quad[2].y - quad[1].y);
- }
- if ((sameSide & 3) != 2) {
- return 2;
- }
- double tValue;
- int root;
- if (useX) {
- root = findExtrema(quad[0].x, quad[1].x, quad[2].x, &tValue);
- } else {
- root = findExtrema(quad[0].y, quad[1].y, quad[2].y, &tValue);
- }
- if (root) {
- _Point extrema;
- extrema.x = interp_quad_coords(quad[0].x, quad[1].x, quad[2].x, tValue);
- extrema.y = interp_quad_coords(quad[0].y, quad[1].y, quad[2].y, tValue);
- // sameSide > 0 means mid is smaller than either [0] or [2], so replace smaller
- int replace;
- if (useX) {
- if (extrema.x < quad[0].x ^ extrema.x < quad[2].x) {
- return 2;
- }
- replace = (extrema.x < quad[0].x | extrema.x < quad[2].x)
- ^ (quad[0].x < quad[2].x);
- } else {
- if (extrema.y < quad[0].y ^ extrema.y < quad[2].y) {
- return 2;
- }
- replace = (extrema.y < quad[0].y | extrema.y < quad[2].y)
- ^ (quad[0].y < quad[2].y);
- }
- reduction[replace] = extrema;
- }
- return 2;
-}
-
-bool isLinear(const Quadratic& quad, int startIndex, int endIndex) {
- LineParameters lineParameters;
- lineParameters.quadEndPoints(quad, startIndex, endIndex);
- // FIXME: maybe it's possible to avoid this and compare non-normalized
- lineParameters.normalize();
- double distance = lineParameters.controlPtDistance(quad);
- return approximately_zero(distance);
-}
-
-// reduce to a quadratic or smaller
-// look for identical points
-// look for all four points in a line
- // note that three points in a line doesn't simplify a cubic
-// look for approximation with single quadratic
- // save approximation with multiple quadratics for later
-int reduceOrder(const Quadratic& quad, Quadratic& reduction, ReduceOrder_Styles reduceStyle) {
- int index, minX, maxX, minY, maxY;
- int minXSet, minYSet;
- minX = maxX = minY = maxY = 0;
- minXSet = minYSet = 0;
- for (index = 1; index < 3; ++index) {
- if (quad[minX].x > quad[index].x) {
- minX = index;
- }
- if (quad[minY].y > quad[index].y) {
- minY = index;
- }
- if (quad[maxX].x < quad[index].x) {
- maxX = index;
- }
- if (quad[maxY].y < quad[index].y) {
- maxY = index;
- }
- }
- for (index = 0; index < 3; ++index) {
- if (AlmostEqualUlps(quad[index].x, quad[minX].x)) {
- minXSet |= 1 << index;
- }
- if (AlmostEqualUlps(quad[index].y, quad[minY].y)) {
- minYSet |= 1 << index;
- }
- }
- if (minXSet == 0x7) { // test for vertical line
- if (minYSet == 0x7) { // return 1 if all four are coincident
- return coincident_line(quad, reduction);
- }
- return vertical_line(quad, reduceStyle, reduction);
- }
- if (minYSet == 0xF) { // test for horizontal line
- return horizontal_line(quad, reduceStyle, reduction);
- }
- int result = check_linear(quad, reduceStyle, minX, maxX, minY, maxY, reduction);
- if (result) {
- return result;
- }
- memcpy(reduction, quad, sizeof(Quadratic));
- return 3;
-}
diff --git a/experimental/Intersection/QuadraticReduceOrder_Test.cpp b/experimental/Intersection/QuadraticReduceOrder_Test.cpp
deleted file mode 100644
index e9e8b4bc92..0000000000
--- a/experimental/Intersection/QuadraticReduceOrder_Test.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "CurveIntersection.h"
-#include "Intersection_Tests.h"
-#include "QuadraticIntersection_TestData.h"
-#include "TestUtilities.h"
-
-static const Quadratic testSet[] = {
- {{1, 1}, {2, 2}, {1, 1.000003}},
- {{1, 0}, {2, 6}, {3, 0}}
-};
-
-static const size_t testSetCount = sizeof(testSet) / sizeof(testSet[0]);
-
-
-static void oneOffTest() {
- SkDebugf("%s FLT_EPSILON=%1.9g\n", __FUNCTION__, FLT_EPSILON);
- for (size_t index = 0; index < testSetCount; ++index) {
- const Quadratic& quad = testSet[index];
- Quadratic reduce;
- SkDEBUGCODE(int result = ) reduceOrder(quad, reduce, kReduceOrder_TreatAsFill);
- SkASSERT(result == 3);
- }
-}
-
-static void standardTestCases() {
- size_t index;
- Quadratic reduce;
- int order;
- enum {
- RunAll,
- RunQuadraticLines,
- RunQuadraticModLines,
- RunNone
- } run = RunAll;
- int firstTestIndex = 0;
-#if 0
- run = RunQuadraticLines;
- firstTestIndex = 1;
-#endif
- int firstQuadraticLineTest = run == RunAll ? 0 : run == RunQuadraticLines ? firstTestIndex : SK_MaxS32;
- int firstQuadraticModLineTest = run == RunAll ? 0 : run == RunQuadraticModLines ? firstTestIndex : SK_MaxS32;
-
- for (index = firstQuadraticLineTest; index < quadraticLines_count; ++index) {
- const Quadratic& quad = quadraticLines[index];
- order = reduceOrder(quad, reduce, kReduceOrder_TreatAsFill);
- if (order != 2) {
- printf("[%d] line quad order=%d\n", (int) index, order);
- }
- }
- for (index = firstQuadraticModLineTest; index < quadraticModEpsilonLines_count; ++index) {
- const Quadratic& quad = quadraticModEpsilonLines[index];
- order = reduceOrder(quad, reduce, kReduceOrder_TreatAsFill);
- if (order != 3) {
- printf("[%d] line mod quad order=%d\n", (int) index, order);
- }
- }
-}
-
-void QuadraticReduceOrder_Test() {
- oneOffTest();
- standardTestCases();
-}
diff --git a/experimental/Intersection/QuadraticSubDivide.cpp b/experimental/Intersection/QuadraticSubDivide.cpp
deleted file mode 100644
index 2ced9e325a..0000000000
--- a/experimental/Intersection/QuadraticSubDivide.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "CurveIntersection.h"
-#include "IntersectionUtilities.h"
-#include "QuadraticUtilities.h"
-
-/*
-Given a quadratic q, t1, and t2, find a small quadratic segment.
-
-The new quadratic is defined by A, B, and C, where
- A = c[0]*(1 - t1)*(1 - t1) + 2*c[1]*t1*(1 - t1) + c[2]*t1*t1
- C = c[3]*(1 - t1)*(1 - t1) + 2*c[2]*t1*(1 - t1) + c[1]*t1*t1
-
-To find B, compute the point halfway between t1 and t2:
-
-q(at (t1 + t2)/2) == D
-
-Next, compute where D must be if we know the value of B:
-
-_12 = A/2 + B/2
-12_ = B/2 + C/2
-123 = A/4 + B/2 + C/4
- = D
-
-Group the known values on one side:
-
-B = D*2 - A/2 - C/2
-*/
-
-static double interp_quad_coords(const double* src, double t)
-{
- double ab = interp(src[0], src[2], t);
- double bc = interp(src[2], src[4], t);
- double abc = interp(ab, bc, t);
- return abc;
-}
-
-void sub_divide(const Quadratic& src, double t1, double t2, Quadratic& dst) {
- double ax = dst[0].x = interp_quad_coords(&src[0].x, t1);
- double ay = dst[0].y = interp_quad_coords(&src[0].y, t1);
- double dx = interp_quad_coords(&src[0].x, (t1 + t2) / 2);
- double dy = interp_quad_coords(&src[0].y, (t1 + t2) / 2);
- double cx = dst[2].x = interp_quad_coords(&src[0].x, t2);
- double cy = dst[2].y = interp_quad_coords(&src[0].y, t2);
- /* bx = */ dst[1].x = 2*dx - (ax + cx)/2;
- /* by = */ dst[1].y = 2*dy - (ay + cy)/2;
-}
-
-_Point sub_divide(const Quadratic& src, const _Point& a, const _Point& c, double t1, double t2) {
- _Point b;
- double dx = interp_quad_coords(&src[0].x, (t1 + t2) / 2);
- double dy = interp_quad_coords(&src[0].y, (t1 + t2) / 2);
- b.x = 2 * dx - (a.x + c.x) / 2;
- b.y = 2 * dy - (a.y + c.y) / 2;
- return b;
-}
-
-/* classic one t subdivision */
-static void interp_quad_coords(const double* src, double* dst, double t)
-{
- double ab = interp(src[0], src[2], t);
- double bc = interp(src[2], src[4], t);
-
- dst[0] = src[0];
- dst[2] = ab;
- dst[4] = interp(ab, bc, t);
- dst[6] = bc;
- dst[8] = src[4];
-}
-
-void chop_at(const Quadratic& src, QuadraticPair& dst, double t)
-{
- interp_quad_coords(&src[0].x, &dst.pts[0].x, t);
- interp_quad_coords(&src[0].y, &dst.pts[0].y, t);
-}
diff --git a/experimental/Intersection/QuadraticUtilities.cpp b/experimental/Intersection/QuadraticUtilities.cpp
deleted file mode 100644
index cba722be7f..0000000000
--- a/experimental/Intersection/QuadraticUtilities.cpp
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "CubicUtilities.h"
-#include "Extrema.h"
-#include "QuadraticUtilities.h"
-#include "TriangleUtilities.h"
-
-// from http://blog.gludion.com/2009/08/distance-to-quadratic-bezier-curve.html
-double nearestT(const Quadratic& quad, const _Point& pt) {
- _Vector pos = quad[0] - pt;
- // search points P of bezier curve with PM.(dP / dt) = 0
- // a calculus leads to a 3d degree equation :
- _Vector A = quad[1] - quad[0];
- _Vector B = quad[2] - quad[1];
- B -= A;
- double a = B.dot(B);
- double b = 3 * A.dot(B);
- double c = 2 * A.dot(A) + pos.dot(B);
- double d = pos.dot(A);
- double ts[3];
- int roots = cubicRootsValidT(a, b, c, d, ts);
- double d0 = pt.distanceSquared(quad[0]);
- double d2 = pt.distanceSquared(quad[2]);
- double distMin = SkTMin(d0, d2);
- int bestIndex = -1;
- for (int index = 0; index < roots; ++index) {
- _Point onQuad;
- xy_at_t(quad, ts[index], onQuad.x, onQuad.y);
- double dist = pt.distanceSquared(onQuad);
- if (distMin > dist) {
- distMin = dist;
- bestIndex = index;
- }
- }
- if (bestIndex >= 0) {
- return ts[bestIndex];
- }
- return d0 < d2 ? 0 : 1;
-}
-
-bool point_in_hull(const Quadratic& quad, const _Point& pt) {
- return pointInTriangle((const Triangle&) quad, pt);
-}
-
-_Point top(const Quadratic& quad, double startT, double endT) {
- Quadratic sub;
- sub_divide(quad, startT, endT, sub);
- _Point topPt = sub[0];
- if (topPt.y > sub[2].y || (topPt.y == sub[2].y && topPt.x > sub[2].x)) {
- topPt = sub[2];
- }
- if (!between(sub[0].y, sub[1].y, sub[2].y)) {
- double extremeT;
- if (findExtrema(sub[0].y, sub[1].y, sub[2].y, &extremeT)) {
- extremeT = startT + (endT - startT) * extremeT;
- _Point test;
- xy_at_t(quad, extremeT, test.x, test.y);
- if (topPt.y > test.y || (topPt.y == test.y && topPt.x > test.x)) {
- topPt = test;
- }
- }
- }
- return topPt;
-}
-
-/*
-Numeric Solutions (5.6) suggests to solve the quadratic by computing
- Q = -1/2(B + sgn(B)Sqrt(B^2 - 4 A C))
-and using the roots
- t1 = Q / A
- t2 = C / Q
-*/
-int add_valid_ts(double s[], int realRoots, double* t) {
- int foundRoots = 0;
- for (int index = 0; index < realRoots; ++index) {
- double tValue = s[index];
- if (approximately_zero_or_more(tValue) && approximately_one_or_less(tValue)) {
- if (approximately_less_than_zero(tValue)) {
- tValue = 0;
- } else if (approximately_greater_than_one(tValue)) {
- tValue = 1;
- }
- for (int idx2 = 0; idx2 < foundRoots; ++idx2) {
- if (approximately_equal(t[idx2], tValue)) {
- goto nextRoot;
- }
- }
- t[foundRoots++] = tValue;
- }
-nextRoot:
- ;
- }
- return foundRoots;
-}
-
-// note: caller expects multiple results to be sorted smaller first
-// note: http://en.wikipedia.org/wiki/Loss_of_significance has an interesting
-// analysis of the quadratic equation, suggesting why the following looks at
-// the sign of B -- and further suggesting that the greatest loss of precision
-// is in b squared less two a c
-int quadraticRootsValidT(double A, double B, double C, double t[2]) {
-#if 0
- B *= 2;
- double square = B * B - 4 * A * C;
- if (approximately_negative(square)) {
- if (!approximately_positive(square)) {
- return 0;
- }
- square = 0;
- }
- double squareRt = sqrt(square);
- double Q = (B + (B < 0 ? -squareRt : squareRt)) / -2;
- int foundRoots = 0;
- double ratio = Q / A;
- if (approximately_zero_or_more(ratio) && approximately_one_or_less(ratio)) {
- if (approximately_less_than_zero(ratio)) {
- ratio = 0;
- } else if (approximately_greater_than_one(ratio)) {
- ratio = 1;
- }
- t[0] = ratio;
- ++foundRoots;
- }
- ratio = C / Q;
- if (approximately_zero_or_more(ratio) && approximately_one_or_less(ratio)) {
- if (approximately_less_than_zero(ratio)) {
- ratio = 0;
- } else if (approximately_greater_than_one(ratio)) {
- ratio = 1;
- }
- if (foundRoots == 0 || !approximately_negative(ratio - t[0])) {
- t[foundRoots++] = ratio;
- } else if (!approximately_negative(t[0] - ratio)) {
- t[foundRoots++] = t[0];
- t[0] = ratio;
- }
- }
-#else
- double s[2];
- int realRoots = quadraticRootsReal(A, B, C, s);
- int foundRoots = add_valid_ts(s, realRoots, t);
-#endif
- return foundRoots;
-}
-
-// unlike quadratic roots, this does not discard real roots <= 0 or >= 1
-int quadraticRootsReal(const double A, const double B, const double C, double s[2]) {
- const double p = B / (2 * A);
- const double q = C / A;
- if (approximately_zero(A) && (approximately_zero_inverse(p) || approximately_zero_inverse(q))) {
- if (approximately_zero(B)) {
- s[0] = 0;
- return C == 0;
- }
- s[0] = -C / B;
- return 1;
- }
- /* normal form: x^2 + px + q = 0 */
- const double p2 = p * p;
-#if 0
- double D = AlmostEqualUlps(p2, q) ? 0 : p2 - q;
- if (D <= 0) {
- if (D < 0) {
- return 0;
- }
- s[0] = -p;
- SkDebugf("[%d] %1.9g\n", 1, s[0]);
- return 1;
- }
- double sqrt_D = sqrt(D);
- s[0] = sqrt_D - p;
- s[1] = -sqrt_D - p;
- SkDebugf("[%d] %1.9g %1.9g\n", 2, s[0], s[1]);
- return 2;
-#else
- if (!AlmostEqualUlps(p2, q) && p2 < q) {
- return 0;
- }
- double sqrt_D = 0;
- if (p2 > q) {
- sqrt_D = sqrt(p2 - q);
- }
- s[0] = sqrt_D - p;
- s[1] = -sqrt_D - p;
-#if 0
- if (AlmostEqualUlps(s[0], s[1])) {
- SkDebugf("[%d] %1.9g\n", 1, s[0]);
- } else {
- SkDebugf("[%d] %1.9g %1.9g\n", 2, s[0], s[1]);
- }
-#endif
- return 1 + !AlmostEqualUlps(s[0], s[1]);
-#endif
-}
-
-void toCubic(const Quadratic& quad, Cubic& cubic) {
- cubic[0] = quad[0];
- cubic[2] = quad[1];
- cubic[3] = quad[2];
- cubic[1].x = (cubic[0].x + cubic[2].x * 2) / 3;
- cubic[1].y = (cubic[0].y + cubic[2].y * 2) / 3;
- cubic[2].x = (cubic[3].x + cubic[2].x * 2) / 3;
- cubic[2].y = (cubic[3].y + cubic[2].y * 2) / 3;
-}
-
-static double derivativeAtT(const double* quad, double t) {
- double a = t - 1;
- double b = 1 - 2 * t;
- double c = t;
- return a * quad[0] + b * quad[2] + c * quad[4];
-}
-
-double dx_at_t(const Quadratic& quad, double t) {
- return derivativeAtT(&quad[0].x, t);
-}
-
-double dy_at_t(const Quadratic& quad, double t) {
- return derivativeAtT(&quad[0].y, t);
-}
-
-_Vector dxdy_at_t(const Quadratic& quad, double t) {
- double a = t - 1;
- double b = 1 - 2 * t;
- double c = t;
- _Vector result = { a * quad[0].x + b * quad[1].x + c * quad[2].x,
- a * quad[0].y + b * quad[1].y + c * quad[2].y };
- return result;
-}
-
-void xy_at_t(const Quadratic& quad, double t, double& x, double& y) {
- double one_t = 1 - t;
- double a = one_t * one_t;
- double b = 2 * one_t * t;
- double c = t * t;
- if (&x) {
- x = a * quad[0].x + b * quad[1].x + c * quad[2].x;
- }
- if (&y) {
- y = a * quad[0].y + b * quad[1].y + c * quad[2].y;
- }
-}
-
-_Point xy_at_t(const Quadratic& quad, double t) {
- double one_t = 1 - t;
- double a = one_t * one_t;
- double b = 2 * one_t * t;
- double c = t * t;
- _Point result = { a * quad[0].x + b * quad[1].x + c * quad[2].x,
- a * quad[0].y + b * quad[1].y + c * quad[2].y };
- return result;
-}
diff --git a/experimental/Intersection/QuadraticUtilities.h b/experimental/Intersection/QuadraticUtilities.h
deleted file mode 100644
index 8ec9037e10..0000000000
--- a/experimental/Intersection/QuadraticUtilities.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#if !defined QUADRATIC_UTILITIES_H
-#define QUADRATIC_UTILITIES_H
-
-#include "DataTypes.h"
-
-int add_valid_ts(double s[], int realRoots, double* t);
-void chop_at(const Quadratic& src, QuadraticPair& dst, double t);
-double dx_at_t(const Quadratic& , double t);
-double dy_at_t(const Quadratic& , double t);
-//void dxdy_at_t(const Quadratic& , double t, _Point& xy);
-_Vector dxdy_at_t(const Quadratic& , double t);
-
-double nearestT(const Quadratic& , const _Point& );
-bool point_in_hull(const Quadratic& , const _Point& );
-
-/* Parameterization form, given A*t*t + 2*B*t*(1-t) + C*(1-t)*(1-t)
- *
- * a = A - 2*B + C
- * b = 2*B - 2*C
- * c = C
- */
-inline void set_abc(const double* quad, double& a, double& b, double& c) {
- a = quad[0]; // a = A
- b = 2 * quad[2]; // b = 2*B
- c = quad[4]; // c = C
- b -= c; // b = 2*B - C
- a -= b; // a = A - 2*B + C
- b -= c; // b = 2*B - 2*C
-}
-
-int quadraticRootsReal(double A, double B, double C, double t[2]);
-int quadraticRootsValidT(const double A, const double B, const double C, double s[2]);
-void sub_divide(const Quadratic& src, double t1, double t2, Quadratic& dst);
-_Point sub_divide(const Quadratic& src, const _Point& a, const _Point& c, double t1, double t2);
-void toCubic(const Quadratic& , Cubic& );
-_Point top(const Quadratic& , double startT, double endT);
-void xy_at_t(const Quadratic& , double t, double& x, double& y);
-_Point xy_at_t(const Quadratic& , double t);
-
-#endif
diff --git a/experimental/Intersection/QuarticRoot.cpp b/experimental/Intersection/QuarticRoot.cpp
deleted file mode 100644
index 46bb4f5024..0000000000
--- a/experimental/Intersection/QuarticRoot.cpp
+++ /dev/null
@@ -1,236 +0,0 @@
-// from http://tog.acm.org/resources/GraphicsGems/gems/Roots3And4.c
-/*
- * Roots3And4.c
- *
- * Utility functions to find cubic and quartic roots,
- * coefficients are passed like this:
- *
- * c[0] + c[1]*x + c[2]*x^2 + c[3]*x^3 + c[4]*x^4 = 0
- *
- * The functions return the number of non-complex roots and
- * put the values into the s array.
- *
- * Author: Jochen Schwarze (schwarze@isa.de)
- *
- * Jan 26, 1990 Version for Graphics Gems
- * Oct 11, 1990 Fixed sign problem for negative q's in SolveQuartic
- * (reported by Mark Podlipec),
- * Old-style function definitions,
- * IsZero() as a macro
- * Nov 23, 1990 Some systems do not declare acos() and cbrt() in
- * <math.h>, though the functions exist in the library.
- * If large coefficients are used, EQN_EPS should be
- * reduced considerably (e.g. to 1E-30), results will be
- * correct but multiple roots might be reported more
- * than once.
- */
-
-#include <math.h>
-#include "CubicUtilities.h"
-#include "QuadraticUtilities.h"
-#include "QuarticRoot.h"
-
-int reducedQuarticRoots(const double t4, const double t3, const double t2, const double t1,
- const double t0, const bool oneHint, double roots[4]) {
-#ifdef SK_DEBUG
- // create a string mathematica understands
- // GDB set print repe 15 # if repeated digits is a bother
- // set print elements 400 # if line doesn't fit
- char str[1024];
- bzero(str, sizeof(str));
- sprintf(str, "Solve[%1.19g x^4 + %1.19g x^3 + %1.19g x^2 + %1.19g x + %1.19g == 0, x]",
- t4, t3, t2, t1, t0);
- mathematica_ize(str, sizeof(str));
-#if ONE_OFF_DEBUG && ONE_OFF_DEBUG_MATHEMATICA
- SkDebugf("%s\n", str);
-#endif
-#endif
-#if 0 && SK_DEBUG
- bool t4Or = approximately_zero_when_compared_to(t4, t0) // 0 is one root
- || approximately_zero_when_compared_to(t4, t1)
- || approximately_zero_when_compared_to(t4, t2);
- bool t4And = approximately_zero_when_compared_to(t4, t0) // 0 is one root
- && approximately_zero_when_compared_to(t4, t1)
- && approximately_zero_when_compared_to(t4, t2);
- if (t4Or != t4And) {
- SkDebugf("%s t4 or and\n", __FUNCTION__);
- }
- bool t3Or = approximately_zero_when_compared_to(t3, t0)
- || approximately_zero_when_compared_to(t3, t1)
- || approximately_zero_when_compared_to(t3, t2);
- bool t3And = approximately_zero_when_compared_to(t3, t0)
- && approximately_zero_when_compared_to(t3, t1)
- && approximately_zero_when_compared_to(t3, t2);
- if (t3Or != t3And) {
- SkDebugf("%s t3 or and\n", __FUNCTION__);
- }
- bool t0Or = approximately_zero_when_compared_to(t0, t1) // 0 is one root
- && approximately_zero_when_compared_to(t0, t2)
- && approximately_zero_when_compared_to(t0, t3)
- && approximately_zero_when_compared_to(t0, t4);
- bool t0And = approximately_zero_when_compared_to(t0, t1) // 0 is one root
- && approximately_zero_when_compared_to(t0, t2)
- && approximately_zero_when_compared_to(t0, t3)
- && approximately_zero_when_compared_to(t0, t4);
- if (t0Or != t0And) {
- SkDebugf("%s t0 or and\n", __FUNCTION__);
- }
-#endif
- if (approximately_zero_when_compared_to(t4, t0) // 0 is one root
- && approximately_zero_when_compared_to(t4, t1)
- && approximately_zero_when_compared_to(t4, t2)) {
- if (approximately_zero_when_compared_to(t3, t0)
- && approximately_zero_when_compared_to(t3, t1)
- && approximately_zero_when_compared_to(t3, t2)) {
- return quadraticRootsReal(t2, t1, t0, roots);
- }
- if (approximately_zero_when_compared_to(t4, t3)) {
- return cubicRootsReal(t3, t2, t1, t0, roots);
- }
- }
- if ((approximately_zero_when_compared_to(t0, t1) || approximately_zero(t1))// 0 is one root
- // && approximately_zero_when_compared_to(t0, t2)
- && approximately_zero_when_compared_to(t0, t3)
- && approximately_zero_when_compared_to(t0, t4)) {
- int num = cubicRootsReal(t4, t3, t2, t1, roots);
- for (int i = 0; i < num; ++i) {
- if (approximately_zero(roots[i])) {
- return num;
- }
- }
- roots[num++] = 0;
- return num;
- }
- if (oneHint) {
- SkASSERT(approximately_zero(t4 + t3 + t2 + t1 + t0)); // 1 is one root
- int num = cubicRootsReal(t4, t4 + t3, -(t1 + t0), -t0, roots); // note that -C==A+B+D+E
- for (int i = 0; i < num; ++i) {
- if (approximately_equal(roots[i], 1)) {
- return num;
- }
- }
- roots[num++] = 1;
- return num;
- }
- return -1;
-}
-
-int quarticRootsReal(int firstCubicRoot, const double A, const double B, const double C,
- const double D, const double E, double s[4]) {
- double u, v;
- /* normal form: x^4 + Ax^3 + Bx^2 + Cx + D = 0 */
- const double invA = 1 / A;
- const double a = B * invA;
- const double b = C * invA;
- const double c = D * invA;
- const double d = E * invA;
- /* substitute x = y - a/4 to eliminate cubic term:
- x^4 + px^2 + qx + r = 0 */
- const double a2 = a * a;
- const double p = -3 * a2 / 8 + b;
- const double q = a2 * a / 8 - a * b / 2 + c;
- const double r = -3 * a2 * a2 / 256 + a2 * b / 16 - a * c / 4 + d;
- int num;
- if (approximately_zero(r)) {
- /* no absolute term: y(y^3 + py + q) = 0 */
- num = cubicRootsReal(1, 0, p, q, s);
- s[num++] = 0;
- } else {
- /* solve the resolvent cubic ... */
- double cubicRoots[3];
- int roots = cubicRootsReal(1, -p / 2, -r, r * p / 2 - q * q / 8, cubicRoots);
- int index;
- #if 0 && SK_DEBUG // enable to verify that any cubic root is as good as any other
- double tries[3][4];
- int nums[3];
- for (index = 0; index < roots; ++index) {
- /* ... and take one real solution ... */
- const double z = cubicRoots[index];
- /* ... to build two quadric equations */
- u = z * z - r;
- v = 2 * z - p;
- if (approximately_zero_squared(u)) {
- u = 0;
- } else if (u > 0) {
- u = sqrt(u);
- } else {
- SkDebugf("%s u=%1.9g <0\n", __FUNCTION__, u);
- continue;
- }
- if (approximately_zero_squared(v)) {
- v = 0;
- } else if (v > 0) {
- v = sqrt(v);
- } else {
- SkDebugf("%s v=%1.9g <0\n", __FUNCTION__, v);
- continue;
- }
- nums[index] = quadraticRootsReal(1, q < 0 ? -v : v, z - u, tries[index]);
- nums[index] += quadraticRootsReal(1, q < 0 ? v : -v, z + u, tries[index] + nums[index]);
- /* resubstitute */
- const double sub = a / 4;
- for (int i = 0; i < nums[index]; ++i) {
- tries[index][i] -= sub;
- }
- }
- for (index = 0; index < roots; ++index) {
- SkDebugf("%s", __FUNCTION__);
- for (int idx2 = 0; idx2 < nums[index]; ++idx2) {
- SkDebugf(" %1.9g", tries[index][idx2]);
- }
- SkDebugf("\n");
- }
- #endif
- /* ... and take one real solution ... */
- double z;
- num = 0;
- int num2 = 0;
- for (index = firstCubicRoot; index < roots; ++index) {
- z = cubicRoots[index];
- /* ... to build two quadric equations */
- u = z * z - r;
- v = 2 * z - p;
- if (approximately_zero_squared(u)) {
- u = 0;
- } else if (u > 0) {
- u = sqrt(u);
- } else {
- continue;
- }
- if (approximately_zero_squared(v)) {
- v = 0;
- } else if (v > 0) {
- v = sqrt(v);
- } else {
- continue;
- }
- num = quadraticRootsReal(1, q < 0 ? -v : v, z - u, s);
- num2 = quadraticRootsReal(1, q < 0 ? v : -v, z + u, s + num);
- if (!((num | num2) & 1)) {
- break; // prefer solutions without single quad roots
- }
- }
- num += num2;
- if (!num) {
- return 0; // no valid cubic root
- }
- }
- /* resubstitute */
- const double sub = a / 4;
- for (int i = 0; i < num; ++i) {
- s[i] -= sub;
- }
- // eliminate duplicates
- for (int i = 0; i < num - 1; ++i) {
- for (int j = i + 1; j < num; ) {
- if (AlmostEqualUlps(s[i], s[j])) {
- if (j < --num) {
- s[j] = s[num];
- }
- } else {
- ++j;
- }
- }
- }
- return num;
-}
diff --git a/experimental/Intersection/QuarticRoot.h b/experimental/Intersection/QuarticRoot.h
deleted file mode 100644
index 3089d59c88..0000000000
--- a/experimental/Intersection/QuarticRoot.h
+++ /dev/null
@@ -1,5 +0,0 @@
-int reducedQuarticRoots(const double t4, const double t3, const double t2, const double t1,
- const double t0, const bool oneHint, double s[4]);
-
-int quarticRootsReal(int firstCubicRoot, const double A, const double B, const double C,
- const double D, const double E, double s[4]);
diff --git a/experimental/Intersection/QuarticRoot_Test.cpp b/experimental/Intersection/QuarticRoot_Test.cpp
deleted file mode 100644
index 48431c8f0a..0000000000
--- a/experimental/Intersection/QuarticRoot_Test.cpp
+++ /dev/null
@@ -1,195 +0,0 @@
-#include "CubicUtilities.h"
-#include "Intersection_Tests.h"
-#include "QuadraticUtilities.h"
-#include "QuarticRoot.h"
-
-double mulA[] = {-3, -1, 1, 3};
-size_t mulACount = sizeof(mulA) / sizeof(mulA[0]);
-double rootB[] = {-9, -6, -3, -1, 0, 1, 3, 6, 9};
-size_t rootBCount = sizeof(rootB) / sizeof(rootB[0]);
-double rootC[] = {-8, -6, -2, -1, 0, 1, 2, 6, 8};
-size_t rootCCount = sizeof(rootC) / sizeof(rootC[0]);
-double rootD[] = {-7, -4, -1, 0, 1, 2, 5};
-size_t rootDCount = sizeof(rootD) / sizeof(rootD[0]);
-double rootE[] = {-5, -1, 0, 1, 7};
-size_t rootECount = sizeof(rootE) / sizeof(rootE[0]);
-
-
-static void quadraticTest(bool limit) {
- // (x - a)(x - b) == x^2 - (a + b)x + ab
- for (size_t aIndex = 0; aIndex < mulACount; ++aIndex) {
- for (size_t bIndex = 0; bIndex < rootBCount; ++bIndex) {
- for (size_t cIndex = 0; cIndex < rootCCount; ++cIndex) {
- const double A = mulA[aIndex];
- double B = rootB[bIndex];
- double C = rootC[cIndex];
- if (limit) {
- B = (B - 6) / 12;
- C = (C - 6) / 12;
- }
- const double b = A * (B + C);
- const double c = A * B * C;
- double roots[2];
- const int rootCount = limit ? quadraticRootsValidT(A, b, c, roots)
- : quadraticRootsReal(A, b, c, roots);
- int expected;
- if (limit) {
- expected = B <= 0 && B >= -1;
- expected += B != C && C <= 0 && C >= -1;
- } else {
- expected = 1 + (B != C);
- }
- SkASSERT(rootCount == expected);
- if (!rootCount) {
- continue;
- }
- SkASSERT(approximately_equal(roots[0], -B)
- || approximately_equal(roots[0], -C));
- if (expected > 1) {
- SkASSERT(!approximately_equal(roots[0], roots[1]));
- SkASSERT(approximately_equal(roots[1], -B)
- || approximately_equal(roots[1], -C));
- }
- }
- }
- }
-}
-
-static void testOneCubic(bool limit, size_t aIndex, size_t bIndex, size_t cIndex, size_t dIndex) {
- const double A = mulA[aIndex];
- double B = rootB[bIndex];
- double C = rootC[cIndex];
- double D = rootD[dIndex];
- if (limit) {
- B = (B - 6) / 12;
- C = (C - 6) / 12;
- D = (C - 2) / 6;
- }
- const double b = A * (B + C + D);
- const double c = A * (B * C + C * D + B * D);
- const double d = A * B * C * D;
- double roots[3];
- const int rootCount = limit ? cubicRootsValidT(A, b, c, d, roots)
- : cubicRootsReal(A, b, c, d, roots);
- int expected;
- if (limit) {
- expected = B <= 0 && B >= -1;
- expected += B != C && C <= 0 && C >= -1;
- expected += B != D && C != D && D <= 0 && D >= -1;
- } else {
- expected = 1 + (B != C) + (B != D && C != D);
- }
- SkASSERT(rootCount == expected);
- if (!rootCount) {
- return;
- }
- SkASSERT(approximately_equal(roots[0], -B)
- || approximately_equal(roots[0], -C)
- || approximately_equal(roots[0], -D));
- if (expected <= 1) {
- return;
- }
- SkASSERT(!approximately_equal(roots[0], roots[1]));
- SkASSERT(approximately_equal(roots[1], -B)
- || approximately_equal(roots[1], -C)
- || approximately_equal(roots[1], -D));
- if (expected <= 2) {
- return;
- }
- SkASSERT(!approximately_equal(roots[0], roots[2])
- && !approximately_equal(roots[1], roots[2]));
- SkASSERT(approximately_equal(roots[2], -B)
- || approximately_equal(roots[2], -C)
- || approximately_equal(roots[2], -D));
-}
-
-static void cubicTest(bool limit) {
- // (x - a)(x - b)(x - c) == x^3 - (a + b + c)x^2 + (ab + bc + ac)x - abc
- for (size_t aIndex = 0; aIndex < mulACount; ++aIndex) {
- for (size_t bIndex = 0; bIndex < rootBCount; ++bIndex) {
- for (size_t cIndex = 0; cIndex < rootCCount; ++cIndex) {
- for (size_t dIndex = 0; dIndex < rootDCount; ++dIndex) {
- testOneCubic(limit, aIndex, bIndex, cIndex, dIndex);
- }
- }
- }
- }
-}
-
-static void testOneQuartic(size_t aIndex, size_t bIndex, size_t cIndex, size_t dIndex,
- size_t eIndex) {
- const double A = mulA[aIndex];
- const double B = rootB[bIndex];
- const double C = rootC[cIndex];
- const double D = rootD[dIndex];
- const double E = rootE[eIndex];
- const double b = A * (B + C + D + E);
- const double c = A * (B * C + C * D + B * D + B * E + C * E + D * E);
- const double d = A * (B * C * D + B * C * E + B * D * E + C * D * E);
- const double e = A * B * C * D * E;
- double roots[4];
- bool oneHint = approximately_zero(A + b + c + d + e);
- int rootCount = reducedQuarticRoots(A, b, c, d, e, oneHint, roots);
- if (rootCount < 0) {
- rootCount = quarticRootsReal(0, A, b, c, d, e, roots);
- }
- const int expected = 1 + (B != C) + (B != D && C != D) + (B != E && C != E && D != E);
- SkASSERT(rootCount == expected);
- SkASSERT(AlmostEqualUlps(roots[0], -B)
- || AlmostEqualUlps(roots[0], -C)
- || AlmostEqualUlps(roots[0], -D)
- || AlmostEqualUlps(roots[0], -E));
- if (expected <= 1) {
- return;
- }
- SkASSERT(!AlmostEqualUlps(roots[0], roots[1]));
- SkASSERT(AlmostEqualUlps(roots[1], -B)
- || AlmostEqualUlps(roots[1], -C)
- || AlmostEqualUlps(roots[1], -D)
- || AlmostEqualUlps(roots[1], -E));
- if (expected <= 2) {
- return;
- }
- SkASSERT(!AlmostEqualUlps(roots[0], roots[2])
- && !AlmostEqualUlps(roots[1], roots[2]));
- SkASSERT(AlmostEqualUlps(roots[2], -B)
- || AlmostEqualUlps(roots[2], -C)
- || AlmostEqualUlps(roots[2], -D)
- || AlmostEqualUlps(roots[2], -E));
- if (expected <= 3) {
- return;
- }
- SkASSERT(!AlmostEqualUlps(roots[0], roots[3])
- && !AlmostEqualUlps(roots[1], roots[3])
- && !AlmostEqualUlps(roots[2], roots[3]));
- SkASSERT(AlmostEqualUlps(roots[3], -B)
- || AlmostEqualUlps(roots[3], -C)
- || AlmostEqualUlps(roots[3], -D)
- || AlmostEqualUlps(roots[3], -E));
-}
-
-static void quarticTest() {
- // (x - a)(x - b)(x - c)(x - d) == x^4 - (a + b + c + d)x^3
- // + (ab + bc + cd + ac + bd + cd)x^2 - (abc + bcd + abd + acd) * x + abcd
- for (size_t aIndex = 0; aIndex < mulACount; ++aIndex) {
- for (size_t bIndex = 0; bIndex < rootBCount; ++bIndex) {
- for (size_t cIndex = 0; cIndex < rootCCount; ++cIndex) {
- for (size_t dIndex = 0; dIndex < rootDCount; ++dIndex) {
- for (size_t eIndex = 0; eIndex < rootECount; ++eIndex) {
- testOneQuartic(aIndex, bIndex, cIndex, dIndex, eIndex);
- }
- }
- }
- }
- }
-}
-
-void QuarticRoot_Test() {
- testOneCubic(false, 0, 5, 5, 4);
- testOneQuartic(0, 0, 2, 4, 3);
- quadraticTest(true);
- quadraticTest(false);
- cubicTest(true);
- cubicTest(false);
- quarticTest();
-}
diff --git a/experimental/Intersection/ShapeOpCubic4x4_Test.cpp b/experimental/Intersection/ShapeOpCubic4x4_Test.cpp
deleted file mode 100644
index d974a12bbe..0000000000
--- a/experimental/Intersection/ShapeOpCubic4x4_Test.cpp
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "EdgeWalker_Test.h"
-#include "Intersection_Tests.h"
-#include "ShapeOps.h"
-
-// four rects, of four sizes
-// for 3 smaller sizes, tall, wide
- // top upper mid lower bottom aligned (3 bits, 5 values)
- // same with x (3 bits, 5 values)
-// not included, square, tall, wide (2 bits)
-// cw or ccw (1 bit)
-
-int failSet[][8] = {
- { 0, 1, 0, 6, 2, 3, 1, 4 }
-};
-
-static void* testShapeOps4x4CubicsMain(void* data)
-{
- SkASSERT(data);
- State4& state = *(State4*) data;
- char pathStr[1024]; // gdb: set print elements 400
- bzero(pathStr, sizeof(pathStr));
- do {
- for (int a = 0 ; a < 6; ++a) {
- for (int b = a + 1 ; b < 7; ++b) {
- for (int c = 0 ; c < 6; ++c) {
- for (int d = c + 1 ; d < 7; ++d) {
- for (int e = SkPath::kWinding_FillType ; e <= SkPath::kEvenOdd_FillType; ++e) {
- for (int f = SkPath::kWinding_FillType ; f <= SkPath::kEvenOdd_FillType; ++f) {
-
-#if 0
- if (state.a == fail[0] && state.b == fail[1] && state.c == fail[2] && state.d == fail[3]
- && a == fail[4] && b == fail[5] && c == fail[6] && d == fail[7]) {
- SkDebugf("skip failing case\n");
- }
- // skip this troublesome cubic pair
-#endif
- SkPath pathA, pathB;
- char* str = pathStr;
- pathA.setFillType((SkPath::FillType) e);
- str += sprintf(str, " path.setFillType(SkPath::k%s_FillType);\n",
- e == SkPath::kWinding_FillType ? "Winding" : e == SkPath::kEvenOdd_FillType
- ? "EvenOdd" : "?UNDEFINED");
- pathA.moveTo(state.a, state.b);
- str += sprintf(str, " path.moveTo(%d,%d);\n", state.a, state.b);
- pathA.cubicTo(state.c, state.d, b, a, d, c);
- str += sprintf(str, " path.cubicTo(%d,%d, %d,%d, %d,%d);\n", state.c, state.d,
- b, a, d, c);
- pathA.close();
- str += sprintf(str, " path.close();\n");
- pathB.setFillType((SkPath::FillType) f);
- str += sprintf(str, " pathB.setFillType(SkPath::k%s_FillType);\n",
- f == SkPath::kWinding_FillType ? "Winding" : f == SkPath::kEvenOdd_FillType
- ? "EvenOdd" : "?UNDEFINED");
- pathB.moveTo(a, b);
- str += sprintf(str, " pathB.moveTo(%d,%d);\n", a, b);
- pathB.cubicTo(c, d, state.b, state.a, state.d, state.c);
- str += sprintf(str, " pathB.cubicTo(%d,%d, %d,%d, %d,%d);\n", c, d,
- state.b, state.a, state.d, state.c);
- pathB.close();
- str += sprintf(str, " pathB.close();\n");
- for (int op = 0 ; op < kShapeOp_Count; ++op) {
- outputProgress(state, pathStr, (ShapeOp) op);
- testShapeOp(pathA, pathB, (ShapeOp) op);
- state.testsRun++;
- }
- }
- }
- }
- }
- }
- }
- } while (runNextTestSet(state));
- return NULL;
-}
-
-void ShapeOps4x4CubicsThreaded_Test(int& testsRun)
-{
- SkDebugf("%s\n", __FUNCTION__);
-#ifdef SK_DEBUG
- gDebugMaxWindSum = 4;
- gDebugMaxWindValue = 4;
-#endif
- const char testLineStr[] = "cubicOp";
- initializeTests(testLineStr, sizeof(testLineStr));
- int testsStart = testsRun;
- for (int a = 0; a < 6; ++a) { // outermost
- for (int b = a + 1; b < 7; ++b) {
- for (int c = 0 ; c < 6; ++c) {
- for (int d = c + 1; d < 7; ++d) {
- testsRun += dispatchTest4(testShapeOps4x4CubicsMain, a, b, c, d);
- }
- if (!gRunTestsInOneThread) SkDebugf(".");
- }
- if (!gRunTestsInOneThread) SkDebugf("%d", b);
- }
- if (!gRunTestsInOneThread) SkDebugf("\n%d", a);
- }
- testsRun += waitForCompletion();
- SkDebugf("%s tests=%d total=%d\n", __FUNCTION__, testsRun - testsStart, testsRun);
-}
diff --git a/experimental/Intersection/ShapeOpRect4x4_Test.cpp b/experimental/Intersection/ShapeOpRect4x4_Test.cpp
deleted file mode 100644
index e6e44c1441..0000000000
--- a/experimental/Intersection/ShapeOpRect4x4_Test.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "EdgeWalker_Test.h"
-#include "Intersection_Tests.h"
-#include "ShapeOps.h"
-
-// four rects, of four sizes
-// for 3 smaller sizes, tall, wide
- // top upper mid lower bottom aligned (3 bits, 5 values)
- // same with x (3 bits, 5 values)
-// not included, square, tall, wide (2 bits)
-// cw or ccw (1 bit)
-
-static void* testShapeOps4x4RectsMain(void* data)
-{
- SkASSERT(data);
- State4& state = *(State4*) data;
- char pathStr[1024]; // gdb: set print elements 400
- bzero(pathStr, sizeof(pathStr));
- do {
- for (int a = 0 ; a < 6; ++a) {
- for (int b = a + 1 ; b < 7; ++b) {
- for (int c = 0 ; c < 6; ++c) {
- for (int d = c + 1 ; d < 7; ++d) {
- for (int e = SkPath::kWinding_FillType ; e <= SkPath::kEvenOdd_FillType; ++e) {
- for (int f = SkPath::kWinding_FillType ; f <= SkPath::kEvenOdd_FillType; ++f) {
- SkPath pathA, pathB;
- char* str = pathStr;
- pathA.setFillType((SkPath::FillType) e);
- str += sprintf(str, " path.setFillType(SkPath::k%s_FillType);\n",
- e == SkPath::kWinding_FillType ? "Winding" : e == SkPath::kEvenOdd_FillType
- ? "EvenOdd" : "?UNDEFINED");
- pathA.addRect(state.a, state.a, state.b, state.b, SkPath::kCW_Direction);
- str += sprintf(str, " path.addRect(%d, %d, %d, %d,"
- " SkPath::kCW_Direction);\n", state.a, state.a, state.b, state.b);
- pathA.addRect(state.c, state.c, state.d, state.d, SkPath::kCW_Direction);
- str += sprintf(str, " path.addRect(%d, %d, %d, %d,"
- " SkPath::kCW_Direction);\n", state.c, state.c, state.d, state.d);
- pathA.close();
- pathB.setFillType((SkPath::FillType) f);
- str += sprintf(str, " pathB.setFillType(SkPath::k%s_FillType);\n",
- f == SkPath::kWinding_FillType ? "Winding" : f == SkPath::kEvenOdd_FillType
- ? "EvenOdd" : "?UNDEFINED");
- pathB.addRect(a, a, b, b, SkPath::kCW_Direction);
- str += sprintf(str, " pathB.addRect(%d, %d, %d, %d,"
- " SkPath::kCW_Direction);\n", a, a, b, b);
- pathB.addRect(c, c, d, d, SkPath::kCW_Direction);
- str += sprintf(str, " pathB.addRect(%d, %d, %d, %d,"
- " SkPath::kCW_Direction);\n", c, c, d, d);
- pathB.close();
- for (int op = 0 ; op < kShapeOp_Count; ++op) {
- outputProgress(state, pathStr, (ShapeOp) op);
- testShapeOp(pathA, pathB, (ShapeOp) op);
- state.testsRun++;
- }
- }
- }
- }
- }
- }
- }
- } while (runNextTestSet(state));
- return NULL;
-}
-
-void ShapeOps4x4RectsThreaded_Test(int& testsRun)
-{
- SkDebugf("%s\n", __FUNCTION__);
-#ifdef SK_DEBUG
- gDebugMaxWindSum = 4;
- gDebugMaxWindValue = 4;
-#endif
- const char testLineStr[] = "testOp";
- initializeTests(testLineStr, sizeof(testLineStr));
- int testsStart = testsRun;
- for (int a = 0; a < 6; ++a) { // outermost
- for (int b = a + 1; b < 7; ++b) {
- for (int c = 0 ; c < 6; ++c) {
- for (int d = c + 1; d < 7; ++d) {
- testsRun += dispatchTest4(testShapeOps4x4RectsMain, a, b, c, d);
- }
- if (!gRunTestsInOneThread) SkDebugf(".");
- }
- if (!gRunTestsInOneThread) SkDebugf("%d", b);
- }
- if (!gRunTestsInOneThread) SkDebugf("\n%d", a);
- }
- testsRun += waitForCompletion();
- SkDebugf("%s tests=%d total=%d\n", __FUNCTION__, testsRun - testsStart, testsRun);
-}
diff --git a/experimental/Intersection/ShapeOps.cpp b/experimental/Intersection/ShapeOps.cpp
deleted file mode 100644
index e58a9e69f2..0000000000
--- a/experimental/Intersection/ShapeOps.cpp
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "Simplify.h"
-
-namespace Op {
-
-#define INCLUDED_BY_SHAPE_OPS 1
-
-#include "Simplify.cpp"
-
-// FIXME: this and find chase should be merge together, along with
-// other code that walks winding in angles
-// OPTIMIZATION: Probably, the walked winding should be rolled into the angle structure
-// so it isn't duplicated by walkers like this one
-static Segment* findChaseOp(SkTDArray<Span*>& chase, int& nextStart, int& nextEnd) {
- while (chase.count()) {
- Span* span;
- chase.pop(&span);
- const Span& backPtr = span->fOther->span(span->fOtherIndex);
- Segment* segment = backPtr.fOther;
- nextStart = backPtr.fOtherIndex;
- SkTDArray<Angle> angles;
- int done = 0;
- if (segment->activeAngle(nextStart, done, angles)) {
- Angle* last = angles.end() - 1;
- nextStart = last->start();
- nextEnd = last->end();
- #if TRY_ROTATE
- *chase.insert(0) = span;
- #else
- *chase.append() = span;
- #endif
- return last->segment();
- }
- if (done == angles.count()) {
- continue;
- }
- SkTDArray<Angle*> sorted;
- bool sortable = Segment::SortAngles(angles, sorted);
- int angleCount = sorted.count();
-#if DEBUG_SORT
- sorted[0]->segment()->debugShowSort(__FUNCTION__, sorted, 0);
-#endif
- if (!sortable) {
- continue;
- }
- // find first angle, initialize winding to computed fWindSum
- int firstIndex = -1;
- const Angle* angle;
- do {
- angle = sorted[++firstIndex];
- segment = angle->segment();
- } while (segment->windSum(angle) == SK_MinS32);
- #if DEBUG_SORT
- segment->debugShowSort(__FUNCTION__, sorted, firstIndex);
- #endif
- int sumMiWinding = segment->updateWindingReverse(angle);
- int sumSuWinding = segment->updateOppWindingReverse(angle);
- if (segment->operand()) {
- SkTSwap<int>(sumMiWinding, sumSuWinding);
- }
- int nextIndex = firstIndex + 1;
- int lastIndex = firstIndex != 0 ? firstIndex : angleCount;
- Segment* first = NULL;
- do {
- SkASSERT(nextIndex != firstIndex);
- if (nextIndex == angleCount) {
- nextIndex = 0;
- }
- angle = sorted[nextIndex];
- segment = angle->segment();
- int start = angle->start();
- int end = angle->end();
- int maxWinding, sumWinding, oppMaxWinding, oppSumWinding;
- segment->setUpWindings(start, end, sumMiWinding, sumSuWinding,
- maxWinding, sumWinding, oppMaxWinding, oppSumWinding);
- if (!segment->done(angle)) {
- if (!first) {
- first = segment;
- nextStart = start;
- nextEnd = end;
- }
- (void) segment->markAngle(maxWinding, sumWinding, oppMaxWinding,
- oppSumWinding, true, angle);
- }
- } while (++nextIndex != lastIndex);
- if (first) {
- #if TRY_ROTATE
- *chase.insert(0) = span;
- #else
- *chase.append() = span;
- #endif
- return first;
- }
- }
- return NULL;
-}
-
-/*
-static bool windingIsActive(int winding, int oppWinding, int spanWinding, int oppSpanWinding,
- bool windingIsOp, ShapeOp op) {
- bool active = windingIsActive(winding, spanWinding);
- if (!active) {
- return false;
- }
- if (oppSpanWinding && windingIsActive(oppWinding, oppSpanWinding)) {
- switch (op) {
- case kIntersect_Op:
- case kUnion_Op:
- return true;
- case kDifference_Op: {
- int absSpan = abs(spanWinding);
- int absOpp = abs(oppSpanWinding);
- return windingIsOp ? absSpan < absOpp : absSpan > absOpp;
- }
- case kXor_Op:
- return spanWinding != oppSpanWinding;
- default:
- SkASSERT(0);
- }
- }
- bool opActive = oppWinding != 0;
- return gOpLookup[op][opActive][windingIsOp];
-}
-*/
-
-static bool bridgeOp(SkTDArray<Contour*>& contourList, const ShapeOp op,
- const int xorMask, const int xorOpMask, PathWrapper& simple) {
- bool firstContour = true;
- bool unsortable = false;
- bool topUnsortable = false;
- SkPoint topLeft = {SK_ScalarMin, SK_ScalarMin};
- do {
- int index, endIndex;
- bool done;
- Segment* current = findSortableTop(contourList, firstContour, index, endIndex, topLeft,
- topUnsortable, done, true);
- if (!current) {
- if (topUnsortable || !done) {
- topUnsortable = false;
- SkASSERT(topLeft.fX != SK_ScalarMin && topLeft.fY != SK_ScalarMin);
- topLeft.fX = topLeft.fY = SK_ScalarMin;
- continue;
- }
- break;
- }
- SkTDArray<Span*> chaseArray;
- do {
- if (current->activeOp(index, endIndex, xorMask, xorOpMask, op)) {
- do {
- #if DEBUG_ACTIVE_SPANS
- if (!unsortable && current->done()) {
- debugShowActiveSpans(contourList);
- }
- #endif
- SkASSERT(unsortable || !current->done());
- int nextStart = index;
- int nextEnd = endIndex;
- Segment* next = current->findNextOp(chaseArray, nextStart, nextEnd,
- unsortable, op, xorMask, xorOpMask);
- if (!next) {
- if (!unsortable && simple.hasMove()
- && current->verb() != SkPath::kLine_Verb
- && !simple.isClosed()) {
- current->addCurveTo(index, endIndex, simple, true);
- SkASSERT(simple.isClosed());
- }
- break;
- }
- #if DEBUG_FLOW
- SkDebugf("%s current id=%d from=(%1.9g,%1.9g) to=(%1.9g,%1.9g)\n", __FUNCTION__,
- current->debugID(), current->xyAtT(index).fX, current->xyAtT(index).fY,
- current->xyAtT(endIndex).fX, current->xyAtT(endIndex).fY);
- #endif
- current->addCurveTo(index, endIndex, simple, true);
- current = next;
- index = nextStart;
- endIndex = nextEnd;
- } while (!simple.isClosed() && ((!unsortable)
- || !current->done(SkMin32(index, endIndex))));
- if (current->activeWinding(index, endIndex) && !simple.isClosed()) {
- SkASSERT(unsortable);
- int min = SkMin32(index, endIndex);
- if (!current->done(min)) {
- current->addCurveTo(index, endIndex, simple, true);
- current->markDoneBinary(min);
- }
- }
- simple.close();
- } else {
- Span* last = current->markAndChaseDoneBinary(index, endIndex);
- if (last && !last->fLoop) {
- *chaseArray.append() = last;
- }
- }
- current = findChaseOp(chaseArray, index, endIndex);
- #if DEBUG_ACTIVE_SPANS
- debugShowActiveSpans(contourList);
- #endif
- if (!current) {
- break;
- }
- } while (true);
- } while (true);
- return simple.someAssemblyRequired();
-}
-
-} // end of Op namespace
-
-
-void operate(const SkPath& one, const SkPath& two, ShapeOp op, SkPath& result) {
-#if DEBUG_SORT || DEBUG_SWAP_TOP
- Op::gDebugSortCount = Op::gDebugSortCountDefault;
-#endif
- result.reset();
- result.setFillType(SkPath::kEvenOdd_FillType);
- // turn path into list of segments
- SkTArray<Op::Contour> contours;
- // FIXME: add self-intersecting cubics' T values to segment
- Op::EdgeBuilder builder(one, contours);
- const int xorMask = builder.xorMask();
- builder.addOperand(two);
- builder.finish();
- const int xorOpMask = builder.xorMask();
- SkTDArray<Op::Contour*> contourList;
- makeContourList(contours, contourList, xorMask == kEvenOdd_Mask,
- xorOpMask == kEvenOdd_Mask);
- Op::Contour** currentPtr = contourList.begin();
- if (!currentPtr) {
- return;
- }
- Op::Contour** listEnd = contourList.end();
- // find all intersections between segments
- do {
- Op::Contour** nextPtr = currentPtr;
- Op::Contour* current = *currentPtr++;
- if (current->containsCubics()) {
- addSelfIntersectTs(current);
- }
- Op::Contour* next;
- do {
- next = *nextPtr++;
- } while (addIntersectTs(current, next) && nextPtr != listEnd);
- } while (currentPtr != listEnd);
- // eat through coincident edges
-
- int total = 0;
- int index;
- for (index = 0; index < contourList.count(); ++index) {
- total += contourList[index]->segments().count();
- }
-#if DEBUG_SHOW_WINDING
- Op::Contour::debugShowWindingValues(contourList);
-#endif
- coincidenceCheck(contourList, total);
-#if DEBUG_SHOW_WINDING
- Op::Contour::debugShowWindingValues(contourList);
-#endif
- fixOtherTIndex(contourList);
- sortSegments(contourList);
-#if DEBUG_ACTIVE_SPANS
- debugShowActiveSpans(contourList);
-#endif
- // construct closed contours
- Op::PathWrapper wrapper(result);
- bridgeOp(contourList, op, xorMask, xorOpMask, wrapper);
- { // if some edges could not be resolved, assemble remaining fragments
- SkPath temp;
- temp.setFillType(SkPath::kEvenOdd_FillType);
- Op::PathWrapper assembled(temp);
- assemble(wrapper, assembled);
- result = *assembled.nativePath();
- }
-}
diff --git a/experimental/Intersection/ShapeOps.h b/experimental/Intersection/ShapeOps.h
deleted file mode 100644
index d6959b9ed1..0000000000
--- a/experimental/Intersection/ShapeOps.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "SkPath.h"
-
-// region-inspired approach
-void contourBounds(const SkPath& path, SkTDArray<SkRect>& boundsArray);
-void simplify(const SkPath& path, bool asFill, SkPath& simple);
-
-// contour outer edge walking approach
-#ifndef DEFINE_SHAPE_OP
-// FIXME: namespace testing doesn't allow global enums like this
-#define DEFINE_SHAPE_OP
-enum ShapeOp {
- kDifference_Op,
- kIntersect_Op,
- kUnion_Op,
- kXor_Op,
- kShapeOp_Count
-};
-
-enum ShapeOpMask {
- kWinding_Mask = -1,
- kNo_Mask = 0,
- kEvenOdd_Mask = 1
-};
-#endif
-
-void operate(const SkPath& one, const SkPath& two, ShapeOp op, SkPath& result);
-void simplifyx(const SkPath& path, SkPath& simple);
-
-// FIXME: remove this section once debugging is complete
-extern const bool gRunTestsInOneThread;
-#ifdef SK_DEBUG
-extern int gDebugMaxWindSum;
-extern int gDebugMaxWindValue;
-#endif
diff --git a/experimental/Intersection/Simplify.cpp b/experimental/Intersection/Simplify.cpp
deleted file mode 100644
index d99cdf315e..0000000000
--- a/experimental/Intersection/Simplify.cpp
+++ /dev/null
@@ -1,6608 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "Simplify.h"
-
-#undef SkASSERT
-#define SkASSERT(cond) while (!(cond)) { sk_throw(); }
-
-// Terminology:
-// A Path contains one of more Contours
-// A Contour is made up of Segment array
-// A Segment is described by a Verb and a Point array with 2, 3, or 4 points
-// A Verb is one of Line, Quad(ratic), or Cubic
-// A Segment contains a Span array
-// A Span is describes a portion of a Segment using starting and ending T
-// T values range from 0 to 1, where 0 is the first Point in the Segment
-// An Edge is a Segment generated from a Span
-
-// FIXME: remove once debugging is complete
-#ifdef SK_DEBUG
-int gDebugMaxWindSum = SK_MaxS32;
-int gDebugMaxWindValue = SK_MaxS32;
-#endif
-
-#define PIN_ADD_T 0
-#define TRY_ROTATE 1
-#define ONE_PASS_COINCIDENCE_CHECK 0
-#define APPROXIMATE_CUBICS 1
-#define COMPACT_DEBUG_SORT 0
-
-#define DEBUG_UNUSED 0 // set to expose unused functions
-
-#if FORCE_RELEASE || defined SK_RELEASE
-
-const bool gRunTestsInOneThread = false;
-
-#define DEBUG_ACTIVE_OP 0
-#define DEBUG_ACTIVE_SPANS 0
-#define DEBUG_ACTIVE_SPANS_SHORT_FORM 0
-#define DEBUG_ADD_INTERSECTING_TS 0
-#define DEBUG_ADD_T_PAIR 0
-#define DEBUG_ANGLE 0
-#define DEBUG_AS_C_CODE 1
-#define DEBUG_ASSEMBLE 0
-#define DEBUG_CONCIDENT 0
-#define DEBUG_CROSS 0
-#define DEBUG_FLOW 0
-#define DEBUG_MARK_DONE 0
-#define DEBUG_PATH_CONSTRUCTION 0
-#define DEBUG_SHOW_WINDING 0
-#define DEBUG_SORT 0
-#define DEBUG_SWAP_TOP 0
-#define DEBUG_UNSORTABLE 0
-#define DEBUG_WIND_BUMP 0
-#define DEBUG_WINDING 0
-#define DEBUG_WINDING_AT_T 0
-
-#else
-
-const bool gRunTestsInOneThread = true;
-
-#define DEBUG_ACTIVE_OP 1
-#define DEBUG_ACTIVE_SPANS 1
-#define DEBUG_ACTIVE_SPANS_SHORT_FORM 0
-#define DEBUG_ADD_INTERSECTING_TS 1
-#define DEBUG_ADD_T_PAIR 1
-#define DEBUG_ANGLE 1
-#define DEBUG_AS_C_CODE 1
-#define DEBUG_ASSEMBLE 1
-#define DEBUG_CONCIDENT 1
-#define DEBUG_CROSS 0
-#define DEBUG_FLOW 1
-#define DEBUG_MARK_DONE 1
-#define DEBUG_PATH_CONSTRUCTION 1
-#define DEBUG_SHOW_WINDING 0
-#define DEBUG_SORT 1
-#define DEBUG_SWAP_TOP 1
-#define DEBUG_UNSORTABLE 1
-#define DEBUG_WIND_BUMP 0
-#define DEBUG_WINDING 1
-#define DEBUG_WINDING_AT_T 1
-
-#endif
-
-#define DEBUG_DUMP (DEBUG_ACTIVE_OP | DEBUG_ACTIVE_SPANS | DEBUG_CONCIDENT | DEBUG_SORT | \
- DEBUG_PATH_CONSTRUCTION)
-
-#if DEBUG_AS_C_CODE
-#define CUBIC_DEBUG_STR "{{%1.17g,%1.17g}, {%1.17g,%1.17g}, {%1.17g,%1.17g}, {%1.17g,%1.17g}}"
-#define QUAD_DEBUG_STR "{{%1.17g,%1.17g}, {%1.17g,%1.17g}, {%1.17g,%1.17g}}"
-#define LINE_DEBUG_STR "{{%1.17g,%1.17g}, {%1.17g,%1.17g}}"
-#define PT_DEBUG_STR "{{%1.17g,%1.17g}}"
-#else
-#define CUBIC_DEBUG_STR "(%1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g)"
-#define QUAD_DEBUG_STR "(%1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g)"
-#define LINE_DEBUG_STR "(%1.9g,%1.9g %1.9g,%1.9g)"
-#define PT_DEBUG_STR "(%1.9g,%1.9g)"
-#endif
-#define T_DEBUG_STR(t, n) #t "[" #n "]=%1.9g"
-#define TX_DEBUG_STR(t) #t "[%d]=%1.9g"
-#define CUBIC_DEBUG_DATA(c) c[0].fX, c[0].fY, c[1].fX, c[1].fY, c[2].fX, c[2].fY, c[3].fX, c[3].fY
-#define QUAD_DEBUG_DATA(q) q[0].fX, q[0].fY, q[1].fX, q[1].fY, q[2].fX, q[2].fY
-#define LINE_DEBUG_DATA(l) l[0].fX, l[0].fY, l[1].fX, l[1].fY
-#define PT_DEBUG_DATA(i, n) i.fPt[n].x, i.fPt[n].y
-
-#if DEBUG_DUMP
-static const char* kLVerbStr[] = {"", "line", "quad", "cubic"};
-// static const char* kUVerbStr[] = {"", "Line", "Quad", "Cubic"};
-static int gContourID;
-static int gSegmentID;
-#endif
-
-#if DEBUG_SORT || DEBUG_SWAP_TOP
-static int gDebugSortCountDefault = SK_MaxS32;
-static int gDebugSortCount;
-#endif
-
-#if DEBUG_ACTIVE_OP
-static const char* kShapeOpStr[] = {"diff", "sect", "union", "xor"};
-#endif
-
-#ifndef DEBUG_TEST
-#define DEBUG_TEST 0
-#endif
-
-#define MAKE_CONST_LINE(line, pts) \
- const _Line line = {{pts[0].fX, pts[0].fY}, {pts[1].fX, pts[1].fY}}
-#define MAKE_CONST_QUAD(quad, pts) \
- const Quadratic quad = {{pts[0].fX, pts[0].fY}, {pts[1].fX, pts[1].fY}, \
- {pts[2].fX, pts[2].fY}}
-#define MAKE_CONST_CUBIC(cubic, pts) \
- const Cubic cubic = {{pts[0].fX, pts[0].fY}, {pts[1].fX, pts[1].fY}, \
- {pts[2].fX, pts[2].fY}, {pts[3].fX, pts[3].fY}}
-
-static int LineIntersect(const SkPoint a[2], const SkPoint b[2],
- Intersections& intersections) {
- MAKE_CONST_LINE(aLine, a);
- MAKE_CONST_LINE(bLine, b);
- return intersect(aLine, bLine, intersections);
-}
-
-static int QuadLineIntersect(const SkPoint a[3], const SkPoint b[2],
- Intersections& intersections) {
- MAKE_CONST_QUAD(aQuad, a);
- MAKE_CONST_LINE(bLine, b);
- return intersect(aQuad, bLine, intersections);
-}
-
-static int CubicLineIntersect(const SkPoint a[4], const SkPoint b[2],
- Intersections& intersections) {
- MAKE_CONST_CUBIC(aCubic, a);
- MAKE_CONST_LINE(bLine, b);
- return intersect(aCubic, bLine, intersections);
-}
-
-static int QuadIntersect(const SkPoint a[3], const SkPoint b[3],
- Intersections& intersections) {
- MAKE_CONST_QUAD(aQuad, a);
- MAKE_CONST_QUAD(bQuad, b);
-#define TRY_QUARTIC_SOLUTION 1
-#if TRY_QUARTIC_SOLUTION
- intersect2(aQuad, bQuad, intersections);
-#else
- intersect(aQuad, bQuad, intersections);
-#endif
- return intersections.fUsed;
-}
-
-#if APPROXIMATE_CUBICS
-static int CubicQuadIntersect(const SkPoint a[4], const SkPoint b[3],
- Intersections& intersections) {
- MAKE_CONST_CUBIC(aCubic, a);
- MAKE_CONST_QUAD(bQuad, b);
- return intersect(aCubic, bQuad, intersections);
-}
-#endif
-
-static int CubicIntersect(const SkPoint a[4], const SkPoint b[4], Intersections& intersections) {
- MAKE_CONST_CUBIC(aCubic, a);
- MAKE_CONST_CUBIC(bCubic, b);
-#if APPROXIMATE_CUBICS
- intersect3(aCubic, bCubic, intersections);
-#else
- intersect(aCubic, bCubic, intersections);
-#endif
- return intersections.fUsed;
-}
-
-static int CubicIntersect(const SkPoint a[4], Intersections& intersections) {
- MAKE_CONST_CUBIC(aCubic, a);
- return intersect(aCubic, intersections);
-}
-
-static int HLineIntersect(const SkPoint a[2], SkScalar left, SkScalar right,
- SkScalar y, bool flipped, Intersections& intersections) {
- MAKE_CONST_LINE(aLine, a);
- return horizontalIntersect(aLine, left, right, y, flipped, intersections);
-}
-
-static int HQuadIntersect(const SkPoint a[3], SkScalar left, SkScalar right,
- SkScalar y, bool flipped, Intersections& intersections) {
- MAKE_CONST_QUAD(aQuad, a);
- return horizontalIntersect(aQuad, left, right, y, flipped, intersections);
-}
-
-static int HCubicIntersect(const SkPoint a[4], SkScalar left, SkScalar right,
- SkScalar y, bool flipped, Intersections& intersections) {
- MAKE_CONST_CUBIC(aCubic, a);
- return horizontalIntersect(aCubic, left, right, y, flipped, intersections);
-}
-
-static int (* const HSegmentIntersect[])(const SkPoint [], SkScalar ,
- SkScalar , SkScalar , bool , Intersections& ) = {
- NULL,
- HLineIntersect,
- HQuadIntersect,
- HCubicIntersect
-};
-
-static int VLineIntersect(const SkPoint a[2], SkScalar top, SkScalar bottom,
- SkScalar x, bool flipped, Intersections& intersections) {
- MAKE_CONST_LINE(aLine, a);
- return verticalIntersect(aLine, top, bottom, x, flipped, intersections);
-}
-
-static int VQuadIntersect(const SkPoint a[3], SkScalar top, SkScalar bottom,
- SkScalar x, bool flipped, Intersections& intersections) {
- MAKE_CONST_QUAD(aQuad, a);
- return verticalIntersect(aQuad, top, bottom, x, flipped, intersections);
-}
-
-static int VCubicIntersect(const SkPoint a[4], SkScalar top, SkScalar bottom,
- SkScalar x, bool flipped, Intersections& intersections) {
- MAKE_CONST_CUBIC(aCubic, a);
- return verticalIntersect(aCubic, top, bottom, x, flipped, intersections);
-}
-
-static int (* const VSegmentIntersect[])(const SkPoint [], SkScalar ,
- SkScalar , SkScalar , bool , Intersections& ) = {
- NULL,
- VLineIntersect,
- VQuadIntersect,
- VCubicIntersect
-};
-
-static void LineXYAtT(const SkPoint a[2], double t, SkPoint* out) {
- MAKE_CONST_LINE(line, a);
- double x, y;
- xy_at_t(line, t, x, y);
- out->fX = SkDoubleToScalar(x);
- out->fY = SkDoubleToScalar(y);
-}
-
-static void LineXYAtT(const SkPoint a[2], double t, _Point* out) {
- MAKE_CONST_LINE(line, a);
- xy_at_t(line, t, out->x, out->y);
-}
-
-static void QuadXYAtT(const SkPoint a[3], double t, SkPoint* out) {
- MAKE_CONST_QUAD(quad, a);
- double x, y;
- xy_at_t(quad, t, x, y);
- out->fX = SkDoubleToScalar(x);
- out->fY = SkDoubleToScalar(y);
-}
-
-static void QuadXYAtT(const SkPoint a[3], double t, _Point* out) {
- MAKE_CONST_QUAD(quad, a);
- xy_at_t(quad, t, out->x, out->y);
-}
-
-static void CubicXYAtT(const SkPoint a[4], double t, SkPoint* out) {
- MAKE_CONST_CUBIC(cubic, a);
- double x, y;
- xy_at_t(cubic, t, x, y);
- out->fX = SkDoubleToScalar(x);
- out->fY = SkDoubleToScalar(y);
-}
-
-static void CubicXYAtT(const SkPoint a[4], double t, _Point* out) {
- MAKE_CONST_CUBIC(cubic, a);
- xy_at_t(cubic, t, out->x, out->y);
-}
-
-static void (* const SegmentXYAtT[])(const SkPoint [], double , SkPoint* ) = {
- NULL,
- LineXYAtT,
- QuadXYAtT,
- CubicXYAtT
-};
-
-static void (* const SegmentXYAtT2[])(const SkPoint [], double , _Point* ) = {
- NULL,
- LineXYAtT,
- QuadXYAtT,
- CubicXYAtT
-};
-
-static SkScalar LineXAtT(const SkPoint a[2], double t) {
- MAKE_CONST_LINE(aLine, a);
- double x;
- xy_at_t(aLine, t, x, *(double*) 0);
- return SkDoubleToScalar(x);
-}
-
-static SkScalar QuadXAtT(const SkPoint a[3], double t) {
- MAKE_CONST_QUAD(quad, a);
- double x;
- xy_at_t(quad, t, x, *(double*) 0);
- return SkDoubleToScalar(x);
-}
-
-static SkScalar CubicXAtT(const SkPoint a[4], double t) {
- MAKE_CONST_CUBIC(cubic, a);
- double x;
- xy_at_t(cubic, t, x, *(double*) 0);
- return SkDoubleToScalar(x);
-}
-
-static SkScalar (* const SegmentXAtT[])(const SkPoint [], double ) = {
- NULL,
- LineXAtT,
- QuadXAtT,
- CubicXAtT
-};
-
-static SkScalar LineYAtT(const SkPoint a[2], double t) {
- MAKE_CONST_LINE(aLine, a);
- double y;
- xy_at_t(aLine, t, *(double*) 0, y);
- return SkDoubleToScalar(y);
-}
-
-static SkScalar QuadYAtT(const SkPoint a[3], double t) {
- MAKE_CONST_QUAD(quad, a);
- double y;
- xy_at_t(quad, t, *(double*) 0, y);
- return SkDoubleToScalar(y);
-}
-
-static SkScalar CubicYAtT(const SkPoint a[4], double t) {
- MAKE_CONST_CUBIC(cubic, a);
- double y;
- xy_at_t(cubic, t, *(double*) 0, y);
- return SkDoubleToScalar(y);
-}
-
-static SkScalar (* const SegmentYAtT[])(const SkPoint [], double ) = {
- NULL,
- LineYAtT,
- QuadYAtT,
- CubicYAtT
-};
-
-static SkScalar LineDXAtT(const SkPoint a[2], double ) {
- return a[1].fX - a[0].fX;
-}
-
-static SkScalar QuadDXAtT(const SkPoint a[3], double t) {
- MAKE_CONST_QUAD(quad, a);
- double x = dx_at_t(quad, t);
- return SkDoubleToScalar(x);
-}
-
-static SkScalar CubicDXAtT(const SkPoint a[4], double t) {
- MAKE_CONST_CUBIC(cubic, a);
- double x = dx_at_t(cubic, t);
- return SkDoubleToScalar(x);
-}
-
-static SkScalar (* const SegmentDXAtT[])(const SkPoint [], double ) = {
- NULL,
- LineDXAtT,
- QuadDXAtT,
- CubicDXAtT
-};
-
-static SkScalar LineDYAtT(const SkPoint a[2], double ) {
- return a[1].fY - a[0].fY;
-}
-
-static SkScalar QuadDYAtT(const SkPoint a[3], double t) {
- MAKE_CONST_QUAD(quad, a);
- double y = dy_at_t(quad, t);
- return SkDoubleToScalar(y);
-}
-
-static SkScalar CubicDYAtT(const SkPoint a[4], double t) {
- MAKE_CONST_CUBIC(cubic, a);
- double y = dy_at_t(cubic, t);
- return SkDoubleToScalar(y);
-}
-
-static SkScalar (* const SegmentDYAtT[])(const SkPoint [], double ) = {
- NULL,
- LineDYAtT,
- QuadDYAtT,
- CubicDYAtT
-};
-
-static SkVector LineDXDYAtT(const SkPoint a[2], double ) {
- return a[1] - a[0];
-}
-
-static SkVector QuadDXDYAtT(const SkPoint a[3], double t) {
- MAKE_CONST_QUAD(quad, a);
- _Vector v = dxdy_at_t(quad, t);
- return v.asSkVector();
-}
-
-static SkVector CubicDXDYAtT(const SkPoint a[4], double t) {
- MAKE_CONST_CUBIC(cubic, a);
- _Vector v = dxdy_at_t(cubic, t);
- return v.asSkVector();
-}
-
-static SkVector (* const SegmentDXDYAtT[])(const SkPoint [], double ) = {
- NULL,
- LineDXDYAtT,
- QuadDXDYAtT,
- CubicDXDYAtT
-};
-
-static void LineSubDivide(const SkPoint a[2], double startT, double endT,
- SkPoint sub[2]) {
- MAKE_CONST_LINE(aLine, a);
- _Line dst;
- sub_divide(aLine, startT, endT, dst);
- sub[0].fX = SkDoubleToScalar(dst[0].x);
- sub[0].fY = SkDoubleToScalar(dst[0].y);
- sub[1].fX = SkDoubleToScalar(dst[1].x);
- sub[1].fY = SkDoubleToScalar(dst[1].y);
-}
-
-static void QuadSubDivide(const SkPoint a[3], double startT, double endT,
- SkPoint sub[3]) {
- MAKE_CONST_QUAD(aQuad, a);
- Quadratic dst;
- sub_divide(aQuad, startT, endT, dst);
- sub[0].fX = SkDoubleToScalar(dst[0].x);
- sub[0].fY = SkDoubleToScalar(dst[0].y);
- sub[1].fX = SkDoubleToScalar(dst[1].x);
- sub[1].fY = SkDoubleToScalar(dst[1].y);
- sub[2].fX = SkDoubleToScalar(dst[2].x);
- sub[2].fY = SkDoubleToScalar(dst[2].y);
-}
-
-static void CubicSubDivide(const SkPoint a[4], double startT, double endT,
- SkPoint sub[4]) {
- MAKE_CONST_CUBIC(aCubic, a);
- Cubic dst;
- sub_divide(aCubic, startT, endT, dst);
- sub[0].fX = SkDoubleToScalar(dst[0].x);
- sub[0].fY = SkDoubleToScalar(dst[0].y);
- sub[1].fX = SkDoubleToScalar(dst[1].x);
- sub[1].fY = SkDoubleToScalar(dst[1].y);
- sub[2].fX = SkDoubleToScalar(dst[2].x);
- sub[2].fY = SkDoubleToScalar(dst[2].y);
- sub[3].fX = SkDoubleToScalar(dst[3].x);
- sub[3].fY = SkDoubleToScalar(dst[3].y);
-}
-
-static void (* const SegmentSubDivide[])(const SkPoint [], double , double ,
- SkPoint []) = {
- NULL,
- LineSubDivide,
- QuadSubDivide,
- CubicSubDivide
-};
-
-static void LineSubDivideHD(const SkPoint a[2], double startT, double endT, _Line& dst) {
- MAKE_CONST_LINE(aLine, a);
- sub_divide(aLine, startT, endT, dst);
-}
-
-static void QuadSubDivideHD(const SkPoint a[3], double startT, double endT, Quadratic& dst) {
- MAKE_CONST_QUAD(aQuad, a);
- sub_divide(aQuad, startT, endT, dst);
-}
-
-static void CubicSubDivideHD(const SkPoint a[4], double startT, double endT, Cubic& dst) {
- MAKE_CONST_CUBIC(aCubic, a);
- sub_divide(aCubic, startT, endT, dst);
-}
-
-static SkPoint QuadTop(const SkPoint a[3], double startT, double endT) {
- MAKE_CONST_QUAD(quad, a);
- _Point topPt = top(quad, startT, endT);
- return topPt.asSkPoint();
-}
-
-static SkPoint CubicTop(const SkPoint a[3], double startT, double endT) {
- MAKE_CONST_CUBIC(cubic, a);
- _Point topPt = top(cubic, startT, endT);
- return topPt.asSkPoint();
-}
-
-static SkPoint (* SegmentTop[])(const SkPoint[], double , double ) = {
- NULL,
- NULL,
- QuadTop,
- CubicTop
-};
-
-#if DEBUG_UNUSED
-static void QuadSubBounds(const SkPoint a[3], double startT, double endT,
- SkRect& bounds) {
- SkPoint dst[3];
- QuadSubDivide(a, startT, endT, dst);
- bounds.fLeft = bounds.fRight = dst[0].fX;
- bounds.fTop = bounds.fBottom = dst[0].fY;
- for (int index = 1; index < 3; ++index) {
- bounds.growToInclude(dst[index].fX, dst[index].fY);
- }
-}
-
-static void CubicSubBounds(const SkPoint a[4], double startT, double endT,
- SkRect& bounds) {
- SkPoint dst[4];
- CubicSubDivide(a, startT, endT, dst);
- bounds.fLeft = bounds.fRight = dst[0].fX;
- bounds.fTop = bounds.fBottom = dst[0].fY;
- for (int index = 1; index < 4; ++index) {
- bounds.growToInclude(dst[index].fX, dst[index].fY);
- }
-}
-#endif
-
-static SkPath::Verb QuadReduceOrder(const SkPoint a[3],
- SkTDArray<SkPoint>& reducePts) {
- MAKE_CONST_QUAD(aQuad, a);
- Quadratic dst;
- int order = reduceOrder(aQuad, dst, kReduceOrder_TreatAsFill);
- if (order == 2) { // quad became line
- for (int index = 0; index < order; ++index) {
- SkPoint* pt = reducePts.append();
- pt->fX = SkDoubleToScalar(dst[index].x);
- pt->fY = SkDoubleToScalar(dst[index].y);
- }
- }
- return (SkPath::Verb) (order - 1);
-}
-
-static SkPath::Verb CubicReduceOrder(const SkPoint a[4],
- SkTDArray<SkPoint>& reducePts) {
- MAKE_CONST_CUBIC(aCubic, a);
- Cubic dst;
- int order = reduceOrder(aCubic, dst, kReduceOrder_QuadraticsAllowed, kReduceOrder_TreatAsFill);
- if (order == 2 || order == 3) { // cubic became line or quad
- for (int index = 0; index < order; ++index) {
- SkPoint* pt = reducePts.append();
- pt->fX = SkDoubleToScalar(dst[index].x);
- pt->fY = SkDoubleToScalar(dst[index].y);
- }
- }
- return (SkPath::Verb) (order - 1);
-}
-
-static bool QuadIsLinear(const SkPoint a[3]) {
- MAKE_CONST_QUAD(aQuad, a);
- return isLinear(aQuad, 0, 2);
-}
-
-static bool CubicIsLinear(const SkPoint a[4]) {
- MAKE_CONST_CUBIC(aCubic, a);
- return isLinear(aCubic, 0, 3);
-}
-
-static SkScalar LineLeftMost(const SkPoint a[2], double startT, double endT) {
- MAKE_CONST_LINE(aLine, a);
- double x[2];
- xy_at_t(aLine, startT, x[0], *(double*) 0);
- xy_at_t(aLine, endT, x[1], *(double*) 0);
- return SkMinScalar((float) x[0], (float) x[1]);
-}
-
-static SkScalar QuadLeftMost(const SkPoint a[3], double startT, double endT) {
- MAKE_CONST_QUAD(aQuad, a);
- return (float) leftMostT(aQuad, startT, endT);
-}
-
-static SkScalar CubicLeftMost(const SkPoint a[4], double startT, double endT) {
- MAKE_CONST_CUBIC(aCubic, a);
- return (float) leftMostT(aCubic, startT, endT);
-}
-
-static SkScalar (* const SegmentLeftMost[])(const SkPoint [], double , double) = {
- NULL,
- LineLeftMost,
- QuadLeftMost,
- CubicLeftMost
-};
-
-#if 0 // currently unused
-static int QuadRayIntersect(const SkPoint a[3], const SkPoint b[2],
- Intersections& intersections) {
- MAKE_CONST_QUAD(aQuad, a);
- MAKE_CONST_LINE(bLine, b);
- return intersectRay(aQuad, bLine, intersections);
-}
-#endif
-
-static int QuadRayIntersect(const SkPoint a[3], const _Line& bLine, Intersections& intersections) {
- MAKE_CONST_QUAD(aQuad, a);
- return intersectRay(aQuad, bLine, intersections);
-}
-
-static int CubicRayIntersect(const SkPoint a[3], const _Line& bLine, Intersections& intersections) {
- MAKE_CONST_CUBIC(aCubic, a);
- return intersectRay(aCubic, bLine, intersections);
-}
-
-static int (* const SegmentRayIntersect[])(const SkPoint [], const _Line& , Intersections&) = {
- NULL,
- NULL,
- QuadRayIntersect,
- CubicRayIntersect
-};
-
-
-
-static bool LineVertical(const SkPoint a[2], double startT, double endT) {
- MAKE_CONST_LINE(aLine, a);
- double x[2];
- xy_at_t(aLine, startT, x[0], *(double*) 0);
- xy_at_t(aLine, endT, x[1], *(double*) 0);
- return AlmostEqualUlps((float) x[0], (float) x[1]);
-}
-
-static bool QuadVertical(const SkPoint a[3], double startT, double endT) {
- SkPoint dst[3];
- QuadSubDivide(a, startT, endT, dst);
- return AlmostEqualUlps(dst[0].fX, dst[1].fX) && AlmostEqualUlps(dst[1].fX, dst[2].fX);
-}
-
-static bool CubicVertical(const SkPoint a[4], double startT, double endT) {
- SkPoint dst[4];
- CubicSubDivide(a, startT, endT, dst);
- return AlmostEqualUlps(dst[0].fX, dst[1].fX) && AlmostEqualUlps(dst[1].fX, dst[2].fX)
- && AlmostEqualUlps(dst[2].fX, dst[3].fX);
-}
-
-static bool (* const SegmentVertical[])(const SkPoint [], double , double) = {
- NULL,
- LineVertical,
- QuadVertical,
- CubicVertical
-};
-
-class Segment;
-
-struct Span {
- Segment* fOther;
- mutable SkPoint fPt; // lazily computed as needed
- double fT;
- double fOtherT; // value at fOther[fOtherIndex].fT
- int fOtherIndex; // can't be used during intersection
- int fWindSum; // accumulated from contours surrounding this one.
- int fOppSum; // for binary operators: the opposite winding sum
- int fWindValue; // 0 == canceled; 1 == normal; >1 == coincident
- int fOppValue; // normally 0 -- when binary coincident edges combine, opp value goes here
- bool fDone; // if set, this span to next higher T has been processed
- bool fUnsortableStart; // set when start is part of an unsortable pair
- bool fUnsortableEnd; // set when end is part of an unsortable pair
- bool fTiny; // if set, span may still be considered once for edge following
- bool fLoop; // set when a cubic loops back to this point
-};
-
-// sorting angles
-// given angles of {dx dy ddx ddy dddx dddy} sort them
-class Angle {
-public:
- // FIXME: this is bogus for quads and cubics
- // if the quads and cubics' line from end pt to ctrl pt are coincident,
- // there's no obvious way to determine the curve ordering from the
- // derivatives alone. In particular, if one quadratic's coincident tangent
- // is longer than the other curve, the final control point can place the
- // longer curve on either side of the shorter one.
- // Using Bezier curve focus http://cagd.cs.byu.edu/~tom/papers/bezclip.pdf
- // may provide some help, but nothing has been figured out yet.
-
- /*(
- for quads and cubics, set up a parameterized line (e.g. LineParameters )
- for points [0] to [1]. See if point [2] is on that line, or on one side
- or the other. If it both quads' end points are on the same side, choose
- the shorter tangent. If the tangents are equal, choose the better second
- tangent angle
-
- maybe I could set up LineParameters lazily
- */
- bool operator<(const Angle& rh) const {
- double y = dy();
- double ry = rh.dy();
- if ((y < 0) ^ (ry < 0)) { // OPTIMIZATION: better to use y * ry < 0 ?
- return y < 0;
- }
- double x = dx();
- double rx = rh.dx();
- if (y == 0 && ry == 0 && x * rx < 0) {
- return x < rx;
- }
- double x_ry = x * ry;
- double rx_y = rx * y;
- double cmp = x_ry - rx_y;
- if (!approximately_zero(cmp)) {
- return cmp < 0;
- }
- if (approximately_zero(x_ry) && approximately_zero(rx_y)
- && !approximately_zero_squared(cmp)) {
- return cmp < 0;
- }
- // at this point, the initial tangent line is coincident
- // see if edges curl away from each other
- if (fSide * rh.fSide <= 0 && (!approximately_zero(fSide)
- || !approximately_zero(rh.fSide))) {
- // FIXME: running demo will trigger this assertion
- // (don't know if commenting out will trigger further assertion or not)
- // commenting it out allows demo to run in release, though
- // SkASSERT(fSide != rh.fSide);
- return fSide < rh.fSide;
- }
- // see if either curve can be lengthened and try the tangent compare again
- if (cmp && (*fSpans)[fEnd].fOther != rh.fSegment // tangents not absolutely identical
- && (*rh.fSpans)[rh.fEnd].fOther != fSegment) { // and not intersecting
- Angle longer = *this;
- Angle rhLonger = rh;
- if (longer.lengthen() | rhLonger.lengthen()) {
- return longer < rhLonger;
- }
- #if 0
- // what if we extend in the other direction?
- longer = *this;
- rhLonger = rh;
- if (longer.reverseLengthen() | rhLonger.reverseLengthen()) {
- return longer < rhLonger;
- }
- #endif
- }
- if ((fVerb == SkPath::kLine_Verb && approximately_zero(x) && approximately_zero(y))
- || (rh.fVerb == SkPath::kLine_Verb
- && approximately_zero(rx) && approximately_zero(ry))) {
- // See general unsortable comment below. This case can happen when
- // one line has a non-zero change in t but no change in x and y.
- fUnsortable = true;
- rh.fUnsortable = true;
- return this < &rh; // even with no solution, return a stable sort
- }
- if ((*rh.fSpans)[SkMin32(rh.fStart, rh.fEnd)].fTiny
- || (*fSpans)[SkMin32(fStart, fEnd)].fTiny) {
- fUnsortable = true;
- rh.fUnsortable = true;
- return this < &rh; // even with no solution, return a stable sort
- }
- SkASSERT(fVerb >= SkPath::kQuad_Verb);
- SkASSERT(rh.fVerb >= SkPath::kQuad_Verb);
- // FIXME: until I can think of something better, project a ray from the
- // end of the shorter tangent to midway between the end points
- // through both curves and use the resulting angle to sort
- // FIXME: some of this setup can be moved to set() if it works, or cached if it's expensive
- double len = fTangent1.normalSquared();
- double rlen = rh.fTangent1.normalSquared();
- _Line ray;
- Intersections i, ri;
- int roots, rroots;
- bool flip = false;
- do {
- bool useThis = (len < rlen) ^ flip;
- const Cubic& part = useThis ? fCurvePart : rh.fCurvePart;
- SkPath::Verb partVerb = useThis ? fVerb : rh.fVerb;
- ray[0] = partVerb == SkPath::kCubic_Verb && part[0].approximatelyEqual(part[1]) ?
- part[2] : part[1];
- ray[1].x = (part[0].x + part[partVerb].x) / 2;
- ray[1].y = (part[0].y + part[partVerb].y) / 2;
- SkASSERT(ray[0] != ray[1]);
- roots = (*SegmentRayIntersect[fVerb])(fPts, ray, i);
- rroots = (*SegmentRayIntersect[rh.fVerb])(rh.fPts, ray, ri);
- } while ((roots == 0 || rroots == 0) && (flip ^= true));
- if (roots == 0 || rroots == 0) {
- // FIXME: we don't have a solution in this case. The interim solution
- // is to mark the edges as unsortable, exclude them from this and
- // future computations, and allow the returned path to be fragmented
- fUnsortable = true;
- rh.fUnsortable = true;
- return this < &rh; // even with no solution, return a stable sort
- }
- _Point loc;
- double best = SK_ScalarInfinity;
- double dx, dy, dist;
- int index;
- for (index = 0; index < roots; ++index) {
- (*SegmentXYAtT2[fVerb])(fPts, i.fT[0][index], &loc);
- dx = loc.x - ray[0].x;
- dy = loc.y - ray[0].y;
- dist = dx * dx + dy * dy;
- if (best > dist) {
- best = dist;
- }
- }
- for (index = 0; index < rroots; ++index) {
- (*SegmentXYAtT2[rh.fVerb])(rh.fPts, ri.fT[0][index], &loc);
- dx = loc.x - ray[0].x;
- dy = loc.y - ray[0].y;
- dist = dx * dx + dy * dy;
- if (best > dist) {
- return fSide < 0;
- }
- }
- return fSide > 0;
- }
-
- double dx() const {
- return fTangent1.dx();
- }
-
- double dy() const {
- return fTangent1.dy();
- }
-
- int end() const {
- return fEnd;
- }
-
- bool isHorizontal() const {
- return dy() == 0 && fVerb == SkPath::kLine_Verb;
- }
-
- bool lengthen() {
- int newEnd = fEnd;
- if (fStart < fEnd ? ++newEnd < fSpans->count() : --newEnd >= 0) {
- fEnd = newEnd;
- setSpans();
- return true;
- }
- return false;
- }
-
- bool reverseLengthen() {
- if (fReversed) {
- return false;
- }
- int newEnd = fStart;
- if (fStart > fEnd ? ++newEnd < fSpans->count() : --newEnd >= 0) {
- fEnd = newEnd;
- fReversed = true;
- setSpans();
- return true;
- }
- return false;
- }
-
- void set(const SkPoint* orig, SkPath::Verb verb, const Segment* segment,
- int start, int end, const SkTDArray<Span>& spans) {
- fSegment = segment;
- fStart = start;
- fEnd = end;
- fPts = orig;
- fVerb = verb;
- fSpans = &spans;
- fReversed = false;
- fUnsortable = false;
- setSpans();
- }
-
-
- void setSpans() {
- double startT = (*fSpans)[fStart].fT;
- double endT = (*fSpans)[fEnd].fT;
- switch (fVerb) {
- case SkPath::kLine_Verb:
- _Line l;
- LineSubDivideHD(fPts, startT, endT, l);
- // OPTIMIZATION: for pure line compares, we never need fTangent1.c
- fTangent1.lineEndPoints(l);
- fSide = 0;
- break;
- case SkPath::kQuad_Verb: {
- Quadratic& quad = (Quadratic&)fCurvePart;
- QuadSubDivideHD(fPts, startT, endT, quad);
- fTangent1.quadEndPoints(quad, 0, 1);
- if (dx() == 0 && dy() == 0) {
- fTangent1.quadEndPoints(quad);
- }
- fSide = -fTangent1.pointDistance(fCurvePart[2]); // not normalized -- compare sign only
- } break;
- case SkPath::kCubic_Verb: {
- int nextC = 2;
- CubicSubDivideHD(fPts, startT, endT, fCurvePart);
- fTangent1.cubicEndPoints(fCurvePart, 0, 1);
- if (dx() == 0 && dy() == 0) {
- fTangent1.cubicEndPoints(fCurvePart, 0, 2);
- nextC = 3;
- if (dx() == 0 && dy() == 0) {
- fTangent1.cubicEndPoints(fCurvePart, 0, 3);
- }
- }
- fSide = -fTangent1.pointDistance(fCurvePart[nextC]); // compare sign only
- if (nextC == 2 && approximately_zero(fSide)) {
- fSide = -fTangent1.pointDistance(fCurvePart[3]);
- }
- } break;
- default:
- SkASSERT(0);
- }
- fUnsortable = dx() == 0 && dy() == 0;
- if (fUnsortable) {
- return;
- }
- SkASSERT(fStart != fEnd);
- int step = fStart < fEnd ? 1 : -1; // OPTIMIZE: worth fStart - fEnd >> 31 type macro?
- for (int index = fStart; index != fEnd; index += step) {
-#if 1
- const Span& thisSpan = (*fSpans)[index];
- const Span& nextSpan = (*fSpans)[index + step];
- if (thisSpan.fTiny || precisely_equal(thisSpan.fT, nextSpan.fT)) {
- continue;
- }
- fUnsortable = step > 0 ? thisSpan.fUnsortableStart : nextSpan.fUnsortableEnd;
-#if DEBUG_UNSORTABLE
- if (fUnsortable) {
- SkPoint iPt, ePt;
- (*SegmentXYAtT[fVerb])(fPts, thisSpan.fT, &iPt);
- (*SegmentXYAtT[fVerb])(fPts, nextSpan.fT, &ePt);
- SkDebugf("%s unsortable [%d] (%1.9g,%1.9g) [%d] (%1.9g,%1.9g)\n", __FUNCTION__,
- index, iPt.fX, iPt.fY, fEnd, ePt.fX, ePt.fY);
- }
-#endif
- return;
-#else
- if ((*fSpans)[index].fUnsortableStart) {
- fUnsortable = true;
- return;
- }
-#endif
- }
-#if 1
-#if DEBUG_UNSORTABLE
- SkPoint iPt, ePt;
- (*SegmentXYAtT[fVerb])(fPts, startT, &iPt);
- (*SegmentXYAtT[fVerb])(fPts, endT, &ePt);
- SkDebugf("%s all tiny unsortable [%d] (%1.9g,%1.9g) [%d] (%1.9g,%1.9g)\n", __FUNCTION__,
- fStart, iPt.fX, iPt.fY, fEnd, ePt.fX, ePt.fY);
-#endif
- fUnsortable = true;
-#endif
- }
-
- Segment* segment() const {
- return const_cast<Segment*>(fSegment);
- }
-
- int sign() const {
- return SkSign32(fStart - fEnd);
- }
-
- const SkTDArray<Span>* spans() const {
- return fSpans;
- }
-
- int start() const {
- return fStart;
- }
-
- bool unsortable() const {
- return fUnsortable;
- }
-
-#if DEBUG_ANGLE
- const SkPoint* pts() const {
- return fPts;
- }
-
- SkPath::Verb verb() const {
- return fVerb;
- }
-
- void debugShow(const SkPoint& a) const {
- SkDebugf(" d=(%1.9g,%1.9g) side=%1.9g\n", dx(), dy(), fSide);
- }
-#endif
-
-private:
- const SkPoint* fPts;
- Cubic fCurvePart;
- SkPath::Verb fVerb;
- double fSide;
- LineParameters fTangent1;
- const SkTDArray<Span>* fSpans;
- const Segment* fSegment;
- int fStart;
- int fEnd;
- bool fReversed;
- mutable bool fUnsortable; // this alone is editable by the less than operator
-};
-
-// Bounds, unlike Rect, does not consider a line to be empty.
-struct Bounds : public SkRect {
- static bool Intersects(const Bounds& a, const Bounds& b) {
- return a.fLeft <= b.fRight && b.fLeft <= a.fRight &&
- a.fTop <= b.fBottom && b.fTop <= a.fBottom;
- }
-
- void add(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
- if (left < fLeft) {
- fLeft = left;
- }
- if (top < fTop) {
- fTop = top;
- }
- if (right > fRight) {
- fRight = right;
- }
- if (bottom > fBottom) {
- fBottom = bottom;
- }
- }
-
- void add(const Bounds& toAdd) {
- add(toAdd.fLeft, toAdd.fTop, toAdd.fRight, toAdd.fBottom);
- }
-
- void add(const SkPoint& pt) {
- if (pt.fX < fLeft) fLeft = pt.fX;
- if (pt.fY < fTop) fTop = pt.fY;
- if (pt.fX > fRight) fRight = pt.fX;
- if (pt.fY > fBottom) fBottom = pt.fY;
- }
-
- bool isEmpty() {
- return fLeft > fRight || fTop > fBottom
- || (fLeft == fRight && fTop == fBottom)
- || sk_double_isnan(fLeft) || sk_double_isnan(fRight)
- || sk_double_isnan(fTop) || sk_double_isnan(fBottom);
- }
-
- void setCubicBounds(const SkPoint a[4]) {
- _Rect dRect;
- MAKE_CONST_CUBIC(cubic, a);
- dRect.setBounds(cubic);
- set((float) dRect.left, (float) dRect.top, (float) dRect.right,
- (float) dRect.bottom);
- }
-
- void setLineBounds(const SkPoint a[2]) {
- setPoint(a[0]);
- add(a[1]);
- }
-
- void setQuadBounds(const SkPoint a[3]) {
- MAKE_CONST_QUAD(quad, a);
- _Rect dRect;
- dRect.setBounds(quad);
- set((float) dRect.left, (float) dRect.top, (float) dRect.right,
- (float) dRect.bottom);
- }
-
- void setPoint(const SkPoint& pt) {
- fLeft = fRight = pt.fX;
- fTop = fBottom = pt.fY;
- }
-};
-
-static void (Bounds::*setSegmentBounds[])(const SkPoint[]) = {
- NULL,
- &Bounds::setLineBounds,
- &Bounds::setQuadBounds,
- &Bounds::setCubicBounds
-};
-
-// OPTIMIZATION: does the following also work, and is it any faster?
-// return outerWinding * innerWinding > 0
-// || ((outerWinding + innerWinding < 0) ^ ((outerWinding - innerWinding) < 0)))
-static bool useInnerWinding(int outerWinding, int innerWinding) {
- SkASSERT(outerWinding != SK_MaxS32);
- SkASSERT(innerWinding != SK_MaxS32);
- int absOut = abs(outerWinding);
- int absIn = abs(innerWinding);
- bool result = absOut == absIn ? outerWinding < 0 : absOut < absIn;
-#if 0 && DEBUG_WINDING
- if (outerWinding * innerWinding < 0) {
- SkDebugf("%s outer=%d inner=%d result=%s\n", __FUNCTION__,
- outerWinding, innerWinding, result ? "true" : "false");
- }
-#endif
- return result;
-}
-
-#define F (false) // discard the edge
-#define T (true) // keep the edge
-
-static const bool gUnaryActiveEdge[2][2] = {
-// from=0 from=1
-// to=0,1 to=0,1
- {F, T}, {T, F},
-};
-
-static const bool gActiveEdge[kShapeOp_Count][2][2][2][2] = {
-// miFrom=0 miFrom=1
-// miTo=0 miTo=1 miTo=0 miTo=1
-// suFrom=0 1 suFrom=0 1 suFrom=0 1 suFrom=0 1
-// suTo=0,1 suTo=0,1 suTo=0,1 suTo=0,1 suTo=0,1 suTo=0,1 suTo=0,1 suTo=0,1
- {{{{F, F}, {F, F}}, {{T, F}, {T, F}}}, {{{T, T}, {F, F}}, {{F, T}, {T, F}}}}, // mi - su
- {{{{F, F}, {F, F}}, {{F, T}, {F, T}}}, {{{F, F}, {T, T}}, {{F, T}, {T, F}}}}, // mi & su
- {{{{F, T}, {T, F}}, {{T, T}, {F, F}}}, {{{T, F}, {T, F}}, {{F, F}, {F, F}}}}, // mi | su
- {{{{F, T}, {T, F}}, {{T, F}, {F, T}}}, {{{T, F}, {F, T}}, {{F, T}, {T, F}}}}, // mi ^ su
-};
-
-#undef F
-#undef T
-
-// wrap path to keep track of whether the contour is initialized and non-empty
-class PathWrapper {
-public:
- PathWrapper(SkPath& path)
- : fPathPtr(&path)
- , fCloses(0)
- , fMoves(0)
- {
- init();
- }
-
- void close() {
- if (!fHasMove) {
- return;
- }
- bool callClose = isClosed();
- lineTo();
- if (fEmpty) {
- return;
- }
- if (callClose) {
- #if DEBUG_PATH_CONSTRUCTION
- SkDebugf("path.close();\n");
- #endif
- fPathPtr->close();
- fCloses++;
- }
- init();
- }
-
- void cubicTo(const SkPoint& pt1, const SkPoint& pt2, const SkPoint& pt3) {
- lineTo();
- moveTo();
- fDefer[1] = pt3;
- nudge();
- fDefer[0] = fDefer[1];
-#if DEBUG_PATH_CONSTRUCTION
- SkDebugf("path.cubicTo(%1.9g,%1.9g, %1.9g,%1.9g, %1.9g,%1.9g);\n",
- pt1.fX, pt1.fY, pt2.fX, pt2.fY, fDefer[1].fX, fDefer[1].fY);
-#endif
- fPathPtr->cubicTo(pt1.fX, pt1.fY, pt2.fX, pt2.fY, fDefer[1].fX, fDefer[1].fY);
- fEmpty = false;
- }
-
- void deferredLine(const SkPoint& pt) {
- if (pt == fDefer[1]) {
- return;
- }
- if (changedSlopes(pt)) {
- lineTo();
- fDefer[0] = fDefer[1];
- }
- fDefer[1] = pt;
- }
-
- void deferredMove(const SkPoint& pt) {
- fMoved = true;
- fHasMove = true;
- fEmpty = true;
- fDefer[0] = fDefer[1] = pt;
- }
-
- void deferredMoveLine(const SkPoint& pt) {
- if (!fHasMove) {
- deferredMove(pt);
- }
- deferredLine(pt);
- }
-
- bool hasMove() const {
- return fHasMove;
- }
-
- void init() {
- fEmpty = true;
- fHasMove = false;
- fMoved = false;
- }
-
- bool isClosed() const {
- return !fEmpty && fFirstPt == fDefer[1];
- }
-
- void lineTo() {
- if (fDefer[0] == fDefer[1]) {
- return;
- }
- moveTo();
- nudge();
- fEmpty = false;
-#if DEBUG_PATH_CONSTRUCTION
- SkDebugf("path.lineTo(%1.9g,%1.9g);\n", fDefer[1].fX, fDefer[1].fY);
-#endif
- fPathPtr->lineTo(fDefer[1].fX, fDefer[1].fY);
- fDefer[0] = fDefer[1];
- }
-
- const SkPath* nativePath() const {
- return fPathPtr;
- }
-
- void nudge() {
- if (fEmpty || !AlmostEqualUlps(fDefer[1].fX, fFirstPt.fX)
- || !AlmostEqualUlps(fDefer[1].fY, fFirstPt.fY)) {
- return;
- }
- fDefer[1] = fFirstPt;
- }
-
- void quadTo(const SkPoint& pt1, const SkPoint& pt2) {
- lineTo();
- moveTo();
- fDefer[1] = pt2;
- nudge();
- fDefer[0] = fDefer[1];
-#if DEBUG_PATH_CONSTRUCTION
- SkDebugf("path.quadTo(%1.9g,%1.9g, %1.9g,%1.9g);\n",
- pt1.fX, pt1.fY, fDefer[1].fX, fDefer[1].fY);
-#endif
- fPathPtr->quadTo(pt1.fX, pt1.fY, fDefer[1].fX, fDefer[1].fY);
- fEmpty = false;
- }
-
- bool someAssemblyRequired() const {
- return fCloses < fMoves;
- }
-
-protected:
- bool changedSlopes(const SkPoint& pt) const {
- if (fDefer[0] == fDefer[1]) {
- return false;
- }
- SkScalar deferDx = fDefer[1].fX - fDefer[0].fX;
- SkScalar deferDy = fDefer[1].fY - fDefer[0].fY;
- SkScalar lineDx = pt.fX - fDefer[1].fX;
- SkScalar lineDy = pt.fY - fDefer[1].fY;
- return deferDx * lineDy != deferDy * lineDx;
- }
-
- void moveTo() {
- if (!fMoved) {
- return;
- }
- fFirstPt = fDefer[0];
-#if DEBUG_PATH_CONSTRUCTION
- SkDebugf("path.moveTo(%1.9g,%1.9g);\n", fDefer[0].fX, fDefer[0].fY);
-#endif
- fPathPtr->moveTo(fDefer[0].fX, fDefer[0].fY);
- fMoved = false;
- fMoves++;
- }
-
-private:
- SkPath* fPathPtr;
- SkPoint fDefer[2];
- SkPoint fFirstPt;
- int fCloses;
- int fMoves;
- bool fEmpty;
- bool fHasMove;
- bool fMoved;
-};
-
-class Segment {
-public:
- Segment() {
-#if DEBUG_DUMP
- fID = ++gSegmentID;
-#endif
- }
-
- bool operator<(const Segment& rh) const {
- return fBounds.fTop < rh.fBounds.fTop;
- }
-
- bool activeAngle(int index, int& done, SkTDArray<Angle>& angles) {
- if (activeAngleInner(index, done, angles)) {
- return true;
- }
- int lesser = index;
- while (--lesser >= 0 && equalPoints(index, lesser)) {
- if (activeAngleOther(lesser, done, angles)) {
- return true;
- }
- }
- lesser = index;
- do {
- if (activeAngleOther(index, done, angles)) {
- return true;
- }
- } while (++index < fTs.count() && equalPoints(index, lesser));
- return false;
- }
-
- bool activeAngleOther(int index, int& done, SkTDArray<Angle>& angles) {
- Span* span = &fTs[index];
- Segment* other = span->fOther;
- int oIndex = span->fOtherIndex;
- return other->activeAngleInner(oIndex, done, angles);
- }
-
- bool activeAngleInner(int index, int& done, SkTDArray<Angle>& angles) {
- int next = nextExactSpan(index, 1);
- if (next > 0) {
- Span& upSpan = fTs[index];
- if (upSpan.fWindValue || upSpan.fOppValue) {
- addAngle(angles, index, next);
- if (upSpan.fDone || upSpan.fUnsortableEnd) {
- done++;
- } else if (upSpan.fWindSum != SK_MinS32) {
- return true;
- }
- } else if (!upSpan.fDone) {
- upSpan.fDone = true;
- fDoneSpans++;
- }
- }
- int prev = nextExactSpan(index, -1);
- // edge leading into junction
- if (prev >= 0) {
- Span& downSpan = fTs[prev];
- if (downSpan.fWindValue || downSpan.fOppValue) {
- addAngle(angles, index, prev);
- if (downSpan.fDone) {
- done++;
- } else if (downSpan.fWindSum != SK_MinS32) {
- return true;
- }
- } else if (!downSpan.fDone) {
- downSpan.fDone = true;
- fDoneSpans++;
- }
- }
- return false;
- }
-
- SkPoint activeLeftTop(bool onlySortable, int* firstT) const {
- SkASSERT(!done());
- SkPoint topPt = {SK_ScalarMax, SK_ScalarMax};
- int count = fTs.count();
- // see if either end is not done since we want smaller Y of the pair
- bool lastDone = true;
- bool lastUnsortable = false;
- double lastT = -1;
- for (int index = 0; index < count; ++index) {
- const Span& span = fTs[index];
- if (onlySortable && (span.fUnsortableStart || lastUnsortable)) {
- goto next;
- }
- if (span.fDone && lastDone) {
- goto next;
- }
- if (approximately_negative(span.fT - lastT)) {
- goto next;
- }
- {
- const SkPoint& xy = xyAtT(&span);
- if (topPt.fY > xy.fY || (topPt.fY == xy.fY && topPt.fX > xy.fX)) {
- topPt = xy;
- if (firstT) {
- *firstT = index;
- }
- }
- if (fVerb != SkPath::kLine_Verb && !lastDone) {
- SkPoint curveTop = (*SegmentTop[fVerb])(fPts, lastT, span.fT);
- if (topPt.fY > curveTop.fY || (topPt.fY == curveTop.fY
- && topPt.fX > curveTop.fX)) {
- topPt = curveTop;
- if (firstT) {
- *firstT = index;
- }
- }
- }
- lastT = span.fT;
- }
- next:
- lastDone = span.fDone;
- lastUnsortable = span.fUnsortableEnd;
- }
- return topPt;
- }
-
- bool activeOp(int index, int endIndex, int xorMiMask, int xorSuMask, ShapeOp op) {
- int sumMiWinding = updateWinding(endIndex, index);
- int sumSuWinding = updateOppWinding(endIndex, index);
- if (fOperand) {
- SkTSwap<int>(sumMiWinding, sumSuWinding);
- }
- int maxWinding, sumWinding, oppMaxWinding, oppSumWinding;
- return activeOp(xorMiMask, xorSuMask, index, endIndex, op, sumMiWinding, sumSuWinding,
- maxWinding, sumWinding, oppMaxWinding, oppSumWinding);
- }
-
- bool activeOp(int xorMiMask, int xorSuMask, int index, int endIndex, ShapeOp op,
- int& sumMiWinding, int& sumSuWinding,
- int& maxWinding, int& sumWinding, int& oppMaxWinding, int& oppSumWinding) {
- setUpWindings(index, endIndex, sumMiWinding, sumSuWinding,
- maxWinding, sumWinding, oppMaxWinding, oppSumWinding);
- bool miFrom;
- bool miTo;
- bool suFrom;
- bool suTo;
- if (operand()) {
- miFrom = (oppMaxWinding & xorMiMask) != 0;
- miTo = (oppSumWinding & xorMiMask) != 0;
- suFrom = (maxWinding & xorSuMask) != 0;
- suTo = (sumWinding & xorSuMask) != 0;
- } else {
- miFrom = (maxWinding & xorMiMask) != 0;
- miTo = (sumWinding & xorMiMask) != 0;
- suFrom = (oppMaxWinding & xorSuMask) != 0;
- suTo = (oppSumWinding & xorSuMask) != 0;
- }
- bool result = gActiveEdge[op][miFrom][miTo][suFrom][suTo];
-#if DEBUG_ACTIVE_OP
- SkDebugf("%s op=%s miFrom=%d miTo=%d suFrom=%d suTo=%d result=%d\n", __FUNCTION__,
- kShapeOpStr[op], miFrom, miTo, suFrom, suTo, result);
-#endif
- SkASSERT(result != -1);
- return result;
- }
-
- bool activeWinding(int index, int endIndex) {
- int sumWinding = updateWinding(endIndex, index);
- int maxWinding;
- return activeWinding(index, endIndex, maxWinding, sumWinding);
- }
-
- bool activeWinding(int index, int endIndex, int& maxWinding, int& sumWinding) {
- setUpWinding(index, endIndex, maxWinding, sumWinding);
- bool from = maxWinding != 0;
- bool to = sumWinding != 0;
- bool result = gUnaryActiveEdge[from][to];
- SkASSERT(result != -1);
- return result;
- }
-
- void addAngle(SkTDArray<Angle>& angles, int start, int end) const {
- SkASSERT(start != end);
- Angle* angle = angles.append();
-#if DEBUG_ANGLE
- if (angles.count() > 1 && !fTs[start].fTiny) {
- SkPoint angle0Pt, newPt;
- (*SegmentXYAtT[angles[0].verb()])(angles[0].pts(),
- (*angles[0].spans())[angles[0].start()].fT, &angle0Pt);
- (*SegmentXYAtT[fVerb])(fPts, fTs[start].fT, &newPt);
- SkASSERT(AlmostEqualUlps(angle0Pt.fX, newPt.fX));
- SkASSERT(AlmostEqualUlps(angle0Pt.fY, newPt.fY));
- }
-#endif
- angle->set(fPts, fVerb, this, start, end, fTs);
- }
-
- void addCancelOutsides(double tStart, double oStart, Segment& other,
- double oEnd) {
- int tIndex = -1;
- int tCount = fTs.count();
- int oIndex = -1;
- int oCount = other.fTs.count();
- do {
- ++tIndex;
- } while (!approximately_negative(tStart - fTs[tIndex].fT) && tIndex < tCount);
- int tIndexStart = tIndex;
- do {
- ++oIndex;
- } while (!approximately_negative(oStart - other.fTs[oIndex].fT) && oIndex < oCount);
- int oIndexStart = oIndex;
- double nextT;
- do {
- nextT = fTs[++tIndex].fT;
- } while (nextT < 1 && approximately_negative(nextT - tStart));
- double oNextT;
- do {
- oNextT = other.fTs[++oIndex].fT;
- } while (oNextT < 1 && approximately_negative(oNextT - oStart));
- // at this point, spans before and after are at:
- // fTs[tIndexStart - 1], fTs[tIndexStart], fTs[tIndex]
- // if tIndexStart == 0, no prior span
- // if nextT == 1, no following span
-
- // advance the span with zero winding
- // if the following span exists (not past the end, non-zero winding)
- // connect the two edges
- if (!fTs[tIndexStart].fWindValue) {
- if (tIndexStart > 0 && fTs[tIndexStart - 1].fWindValue) {
- #if DEBUG_CONCIDENT
- SkDebugf("%s 1 this=%d other=%d t [%d] %1.9g (%1.9g,%1.9g)\n",
- __FUNCTION__, fID, other.fID, tIndexStart - 1,
- fTs[tIndexStart].fT, xyAtT(tIndexStart).fX,
- xyAtT(tIndexStart).fY);
- #endif
- addTPair(fTs[tIndexStart].fT, other, other.fTs[oIndex].fT, false,
- fTs[tIndexStart].fPt);
- }
- if (nextT < 1 && fTs[tIndex].fWindValue) {
- #if DEBUG_CONCIDENT
- SkDebugf("%s 2 this=%d other=%d t [%d] %1.9g (%1.9g,%1.9g)\n",
- __FUNCTION__, fID, other.fID, tIndex,
- fTs[tIndex].fT, xyAtT(tIndex).fX,
- xyAtT(tIndex).fY);
- #endif
- addTPair(fTs[tIndex].fT, other, other.fTs[oIndexStart].fT, false, fTs[tIndex].fPt);
- }
- } else {
- SkASSERT(!other.fTs[oIndexStart].fWindValue);
- if (oIndexStart > 0 && other.fTs[oIndexStart - 1].fWindValue) {
- #if DEBUG_CONCIDENT
- SkDebugf("%s 3 this=%d other=%d t [%d] %1.9g (%1.9g,%1.9g)\n",
- __FUNCTION__, fID, other.fID, oIndexStart - 1,
- other.fTs[oIndexStart].fT, other.xyAtT(oIndexStart).fX,
- other.xyAtT(oIndexStart).fY);
- other.debugAddTPair(other.fTs[oIndexStart].fT, *this, fTs[tIndex].fT);
- #endif
- }
- if (oNextT < 1 && other.fTs[oIndex].fWindValue) {
- #if DEBUG_CONCIDENT
- SkDebugf("%s 4 this=%d other=%d t [%d] %1.9g (%1.9g,%1.9g)\n",
- __FUNCTION__, fID, other.fID, oIndex,
- other.fTs[oIndex].fT, other.xyAtT(oIndex).fX,
- other.xyAtT(oIndex).fY);
- other.debugAddTPair(other.fTs[oIndex].fT, *this, fTs[tIndexStart].fT);
- #endif
- }
- }
- }
-
- void addCoinOutsides(const SkTDArray<double>& outsideTs, Segment& other,
- double oEnd) {
- // walk this to outsideTs[0]
- // walk other to outsideTs[1]
- // if either is > 0, add a pointer to the other, copying adjacent winding
- int tIndex = -1;
- int oIndex = -1;
- double tStart = outsideTs[0];
- double oStart = outsideTs[1];
- do {
- ++tIndex;
- } while (!approximately_negative(tStart - fTs[tIndex].fT));
- SkPoint ptStart = fTs[tIndex].fPt;
- do {
- ++oIndex;
- } while (!approximately_negative(oStart - other.fTs[oIndex].fT));
- if (tIndex > 0 || oIndex > 0 || fOperand != other.fOperand) {
- addTPair(tStart, other, oStart, false, ptStart);
- }
- tStart = fTs[tIndex].fT;
- oStart = other.fTs[oIndex].fT;
- do {
- double nextT;
- do {
- nextT = fTs[++tIndex].fT;
- } while (approximately_negative(nextT - tStart));
- tStart = nextT;
- ptStart = fTs[tIndex].fPt;
- do {
- nextT = other.fTs[++oIndex].fT;
- } while (approximately_negative(nextT - oStart));
- oStart = nextT;
- if (tStart == 1 && oStart == 1 && fOperand == other.fOperand) {
- break;
- }
- addTPair(tStart, other, oStart, false, ptStart);
- } while (tStart < 1 && oStart < 1 && !approximately_negative(oEnd - oStart));
- }
-
- void addCubic(const SkPoint pts[4], bool operand, bool evenOdd) {
- init(pts, SkPath::kCubic_Verb, operand, evenOdd);
- fBounds.setCubicBounds(pts);
- }
-
- /* SkPoint */ void addCurveTo(int start, int end, PathWrapper& path, bool active) const {
- SkPoint edge[4];
- const SkPoint* ePtr;
- int lastT = fTs.count() - 1;
- if (lastT < 0 || (start == 0 && end == lastT) || (start == lastT && end == 0)) {
- ePtr = fPts;
- } else {
- // OPTIMIZE? if not active, skip remainder and return xy_at_t(end)
- subDivide(start, end, edge);
- ePtr = edge;
- }
- if (active) {
- bool reverse = ePtr == fPts && start != 0;
- if (reverse) {
- path.deferredMoveLine(ePtr[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::kCubic_Verb:
- path.cubicTo(ePtr[2], ePtr[1], ePtr[0]);
- break;
- default:
- SkASSERT(0);
- }
- // return ePtr[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::kCubic_Verb:
- path.cubicTo(ePtr[1], ePtr[2], ePtr[3]);
- break;
- default:
- SkASSERT(0);
- }
- }
- }
- // return ePtr[fVerb];
- }
-
- void addLine(const SkPoint pts[2], bool operand, bool evenOdd) {
- init(pts, SkPath::kLine_Verb, operand, evenOdd);
- fBounds.set(pts, 2);
- }
-
-#if 0
- const SkPoint& addMoveTo(int tIndex, PathWrapper& path, bool active) const {
- const SkPoint& pt = xyAtT(tIndex);
- if (active) {
- path.deferredMove(pt);
- }
- return pt;
- }
-#endif
-
- // add 2 to edge or out of range values to get T extremes
- void addOtherT(int index, double otherT, int otherIndex) {
- Span& span = fTs[index];
- #if PIN_ADD_T
- if (precisely_less_than_zero(otherT)) {
- otherT = 0;
- } else if (precisely_greater_than_one(otherT)) {
- otherT = 1;
- }
- #endif
- span.fOtherT = otherT;
- span.fOtherIndex = otherIndex;
- }
-
- void addQuad(const SkPoint pts[3], bool operand, bool evenOdd) {
- init(pts, SkPath::kQuad_Verb, operand, evenOdd);
- fBounds.setQuadBounds(pts);
- }
-
- // Defer all coincident edge processing until
- // after normal intersections have been computed
-
-// no need to be tricky; insert in normal T order
-// resolve overlapping ts when considering coincidence later
-
- // add non-coincident intersection. Resulting edges are sorted in T.
- int addT(Segment* other, const SkPoint& pt, double& newT) {
- // FIXME: in the pathological case where there is a ton of intercepts,
- // binary search?
- int insertedAt = -1;
- size_t tCount = fTs.count();
- #if PIN_ADD_T
- // FIXME: only do this pinning here (e.g. this is done also in quad/line intersect)
- if (precisely_less_than_zero(newT)) {
- newT = 0;
- } else if (precisely_greater_than_one(newT)) {
- newT = 1;
- }
- #endif
- for (size_t index = 0; index < tCount; ++index) {
- // OPTIMIZATION: if there are three or more identical Ts, then
- // the fourth and following could be further insertion-sorted so
- // that all the edges are clockwise or counterclockwise.
- // This could later limit segment tests to the two adjacent
- // neighbors, although it doesn't help with determining which
- // circular direction to go in.
- if (newT < fTs[index].fT) {
- insertedAt = index;
- break;
- }
- }
- Span* span;
- if (insertedAt >= 0) {
- span = fTs.insert(insertedAt);
- } else {
- insertedAt = tCount;
- span = fTs.append();
- }
- span->fT = newT;
- span->fOther = other;
- span->fPt = pt;
- span->fWindSum = SK_MinS32;
- span->fOppSum = SK_MinS32;
- span->fWindValue = 1;
- span->fOppValue = 0;
- span->fTiny = false;
- span->fLoop = false;
- if ((span->fDone = newT == 1)) {
- ++fDoneSpans;
- }
- span->fUnsortableStart = false;
- span->fUnsortableEnd = false;
- int less = -1;
- while (&span[less + 1] - fTs.begin() > 0 && xyAtT(&span[less]) == xyAtT(span)) {
-#if 1
- if (span[less].fDone) {
- break;
- }
- double tInterval = newT - span[less].fT;
- if (precisely_negative(tInterval)) {
- break;
- }
- if (fVerb == SkPath::kCubic_Verb) {
- double tMid = newT - tInterval / 2;
- _Point midPt;
- CubicXYAtT(fPts, tMid, &midPt);
- if (!midPt.approximatelyEqual(xyAtT(span))) {
- break;
- }
- }
- span[less].fTiny = true;
- span[less].fDone = true;
- if (approximately_negative(newT - span[less].fT)) {
- if (approximately_greater_than_one(newT)) {
- span[less].fUnsortableStart = true;
- span[less - 1].fUnsortableEnd = true;
- }
- if (approximately_less_than_zero(span[less].fT)) {
- span[less + 1].fUnsortableStart = true;
- span[less].fUnsortableEnd = true;
- }
- }
- ++fDoneSpans;
-#else
- double tInterval = newT - span[less].fT;
- if (precisely_negative(tInterval)) {
- break;
- }
- if (fVerb == SkPath::kCubic_Verb) {
- double tMid = newT - tInterval / 2;
- _Point midPt;
- CubicXYAtT(fPts, tMid, &midPt);
- if (!midPt.approximatelyEqual(xyAtT(span))) {
- break;
- }
- }
- SkASSERT(span[less].fDone == span->fDone);
- if (span[less].fT == 0) {
- span->fT = newT = 0;
- } else {
- setSpanT(less, newT);
- }
-#endif
- --less;
- }
- int more = 1;
- while (fTs.end() - &span[more - 1] > 1 && xyAtT(&span[more]) == xyAtT(span)) {
-#if 1
- if (span[more - 1].fDone) {
- break;
- }
- double tEndInterval = span[more].fT - newT;
- if (precisely_negative(tEndInterval)) {
- break;
- }
- if (fVerb == SkPath::kCubic_Verb) {
- double tMid = newT - tEndInterval / 2;
- _Point midEndPt;
- CubicXYAtT(fPts, tMid, &midEndPt);
- if (!midEndPt.approximatelyEqual(xyAtT(span))) {
- break;
- }
- }
- span[more - 1].fTiny = true;
- span[more - 1].fDone = true;
- if (approximately_negative(span[more].fT - newT)) {
- if (approximately_greater_than_one(span[more].fT)) {
- span[more + 1].fUnsortableStart = true;
- span[more].fUnsortableEnd = true;
- }
- if (approximately_less_than_zero(newT)) {
- span[more].fUnsortableStart = true;
- span[more - 1].fUnsortableEnd = true;
- }
- }
- ++fDoneSpans;
-#else
- double tEndInterval = span[more].fT - newT;
- if (precisely_negative(tEndInterval)) {
- break;
- }
- if (fVerb == SkPath::kCubic_Verb) {
- double tMid = newT - tEndInterval / 2;
- _Point midEndPt;
- CubicXYAtT(fPts, tMid, &midEndPt);
- if (!midEndPt.approximatelyEqual(xyAtT(span))) {
- break;
- }
- }
- SkASSERT(span[more - 1].fDone == span[more].fDone);
- if (newT == 0) {
- setSpanT(more, 0);
- } else {
- span->fT = newT = span[more].fT;
- }
-#endif
- ++more;
- }
- return insertedAt;
- }
-
- // set spans from start to end to decrement by one
- // note this walks other backwards
- // FIMXE: there's probably an edge case that can be constructed where
- // two span in one segment are separated by float epsilon on one span but
- // not the other, if one segment is very small. For this
- // case the counts asserted below may or may not be enough to separate the
- // spans. Even if the counts work out, what if the spans aren't correctly
- // sorted? It feels better in such a case to match the span's other span
- // pointer since both coincident segments must contain the same spans.
- void addTCancel(double startT, double endT, Segment& other,
- double oStartT, double oEndT) {
- SkASSERT(!approximately_negative(endT - startT));
- SkASSERT(!approximately_negative(oEndT - oStartT));
- bool binary = fOperand != other.fOperand;
- int index = 0;
- while (!approximately_negative(startT - fTs[index].fT)) {
- ++index;
- }
- int oIndex = other.fTs.count();
- while (approximately_positive(other.fTs[--oIndex].fT - oEndT))
- ;
- double tRatio = (oEndT - oStartT) / (endT - startT);
- Span* test = &fTs[index];
- Span* oTest = &other.fTs[oIndex];
- SkTDArray<double> outsideTs;
- SkTDArray<double> oOutsideTs;
- do {
- bool decrement = test->fWindValue && oTest->fWindValue && !binary;
- bool track = test->fWindValue || oTest->fWindValue;
- double testT = test->fT;
- double oTestT = oTest->fT;
- Span* span = test;
- do {
- if (decrement) {
- decrementSpan(span);
- } else if (track && span->fT < 1 && oTestT < 1) {
- TrackOutside(outsideTs, span->fT, oTestT);
- }
- span = &fTs[++index];
- } while (approximately_negative(span->fT - testT));
- Span* oSpan = oTest;
- double otherTMatchStart = oEndT - (span->fT - startT) * tRatio;
- double otherTMatchEnd = oEndT - (test->fT - startT) * tRatio;
- SkDEBUGCODE(int originalWindValue = oSpan->fWindValue);
- while (approximately_negative(otherTMatchStart - oSpan->fT)
- && !approximately_negative(otherTMatchEnd - oSpan->fT)) {
- #ifdef SK_DEBUG
- SkASSERT(originalWindValue == oSpan->fWindValue);
- #endif
- if (decrement) {
- other.decrementSpan(oSpan);
- } else if (track && oSpan->fT < 1 && testT < 1) {
- TrackOutside(oOutsideTs, oSpan->fT, testT);
- }
- if (!oIndex) {
- break;
- }
- oSpan = &other.fTs[--oIndex];
- }
- test = span;
- oTest = oSpan;
- } while (!approximately_negative(endT - test->fT));
- SkASSERT(!oIndex || approximately_negative(oTest->fT - oStartT));
- // FIXME: determine if canceled edges need outside ts added
- if (!done() && outsideTs.count()) {
- double tStart = outsideTs[0];
- double oStart = outsideTs[1];
- addCancelOutsides(tStart, oStart, other, oEndT);
- int count = outsideTs.count();
- if (count > 2) {
- double tStart = outsideTs[count - 2];
- double oStart = outsideTs[count - 1];
- addCancelOutsides(tStart, oStart, other, oEndT);
- }
- }
- if (!other.done() && oOutsideTs.count()) {
- double tStart = oOutsideTs[0];
- double oStart = oOutsideTs[1];
- other.addCancelOutsides(tStart, oStart, *this, endT);
- }
- }
-
- int addSelfT(Segment* other, const SkPoint& pt, double& newT) {
- int result = addT(other, pt, newT);
- Span* span = &fTs[result];
- span->fLoop = true;
- return result;
- }
-
- int addUnsortableT(Segment* other, bool start, const SkPoint& pt, double& newT) {
- int result = addT(other, pt, newT);
- Span* span = &fTs[result];
- if (start) {
- if (result > 0) {
- span[result - 1].fUnsortableEnd = true;
- }
- span[result].fUnsortableStart = true;
- } else {
- span[result].fUnsortableEnd = true;
- if (result + 1 < fTs.count()) {
- span[result + 1].fUnsortableStart = true;
- }
- }
- return result;
- }
-
- int bumpCoincidentThis(const Span* oTest, bool opp, int index,
- SkTDArray<double>& outsideTs) {
- int oWindValue = oTest->fWindValue;
- int oOppValue = oTest->fOppValue;
- if (opp) {
- SkTSwap<int>(oWindValue, oOppValue);
- }
- Span* const test = &fTs[index];
- Span* end = test;
- const double oStartT = oTest->fT;
- do {
- if (bumpSpan(end, oWindValue, oOppValue)) {
- TrackOutside(outsideTs, end->fT, oStartT);
- }
- end = &fTs[++index];
- } while (approximately_negative(end->fT - test->fT));
- return index;
- }
-
- // because of the order in which coincidences are resolved, this and other
- // may not have the same intermediate points. Compute the corresponding
- // intermediate T values (using this as the master, other as the follower)
- // and walk other conditionally -- hoping that it catches up in the end
- int bumpCoincidentOther(const Span* test, double oEndT, int& oIndex,
- SkTDArray<double>& oOutsideTs) {
- Span* const oTest = &fTs[oIndex];
- Span* oEnd = oTest;
- const double startT = test->fT;
- const double oStartT = oTest->fT;
- while (!approximately_negative(oEndT - oEnd->fT)
- && approximately_negative(oEnd->fT - oStartT)) {
- zeroSpan(oEnd);
- TrackOutside(oOutsideTs, oEnd->fT, startT);
- oEnd = &fTs[++oIndex];
- }
- return oIndex;
- }
-
- // FIXME: need to test this case:
- // contourA has two segments that are coincident
- // contourB has two segments that are coincident in the same place
- // each ends up with +2/0 pairs for winding count
- // since logic below doesn't transfer count (only increments/decrements) can this be
- // resolved to +4/0 ?
-
- // set spans from start to end to increment the greater by one and decrement
- // the lesser
- void addTCoincident(double startT, double endT, Segment& other, double oStartT, double oEndT) {
- SkASSERT(!approximately_negative(endT - startT));
- SkASSERT(!approximately_negative(oEndT - oStartT));
- bool opp = fOperand ^ other.fOperand;
- int index = 0;
- while (!approximately_negative(startT - fTs[index].fT)) {
- ++index;
- }
- int oIndex = 0;
- while (!approximately_negative(oStartT - other.fTs[oIndex].fT)) {
- ++oIndex;
- }
- Span* test = &fTs[index];
- Span* oTest = &other.fTs[oIndex];
- SkTDArray<double> outsideTs;
- SkTDArray<double> oOutsideTs;
- do {
- // if either span has an opposite value and the operands don't match, resolve first
- // SkASSERT(!test->fDone || !oTest->fDone);
- if (test->fDone || oTest->fDone) {
- index = advanceCoincidentThis(oTest, opp, index);
- oIndex = other.advanceCoincidentOther(test, oEndT, oIndex);
- } else {
- index = bumpCoincidentThis(oTest, opp, index, outsideTs);
- oIndex = other.bumpCoincidentOther(test, oEndT, oIndex, oOutsideTs);
- }
- test = &fTs[index];
- oTest = &other.fTs[oIndex];
- } while (!approximately_negative(endT - test->fT));
- SkASSERT(approximately_negative(oTest->fT - oEndT));
- SkASSERT(approximately_negative(oEndT - oTest->fT));
- if (!done() && outsideTs.count()) {
- addCoinOutsides(outsideTs, other, oEndT);
- }
- if (!other.done() && oOutsideTs.count()) {
- other.addCoinOutsides(oOutsideTs, *this, endT);
- }
- }
-
- // FIXME: this doesn't prevent the same span from being added twice
- // fix in caller, SkASSERT here?
- void addTPair(double t, Segment& other, double otherT, bool borrowWind, const SkPoint& pt) {
- int tCount = fTs.count();
- for (int tIndex = 0; tIndex < tCount; ++tIndex) {
- const Span& span = fTs[tIndex];
- if (!approximately_negative(span.fT - t)) {
- break;
- }
- if (approximately_negative(span.fT - t) && span.fOther == &other
- && approximately_equal(span.fOtherT, otherT)) {
-#if DEBUG_ADD_T_PAIR
- SkDebugf("%s addTPair duplicate this=%d %1.9g other=%d %1.9g\n",
- __FUNCTION__, fID, t, other.fID, otherT);
-#endif
- return;
- }
- }
-#if DEBUG_ADD_T_PAIR
- SkDebugf("%s addTPair this=%d %1.9g other=%d %1.9g\n",
- __FUNCTION__, fID, t, other.fID, otherT);
-#endif
- int insertedAt = addT(&other, pt, t);
- int otherInsertedAt = other.addT(this, pt, otherT);
- addOtherT(insertedAt, otherT, otherInsertedAt);
- other.addOtherT(otherInsertedAt, t, insertedAt);
- matchWindingValue(insertedAt, t, borrowWind);
- other.matchWindingValue(otherInsertedAt, otherT, borrowWind);
- }
-
- void addTwoAngles(int start, int end, SkTDArray<Angle>& angles) const {
- // add edge leading into junction
- int min = SkMin32(end, start);
- if (fTs[min].fWindValue > 0 || fTs[min].fOppValue > 0) {
- addAngle(angles, end, start);
- }
- // add edge leading away from junction
- int step = SkSign32(end - start);
- int tIndex = nextExactSpan(end, step);
- min = SkMin32(end, tIndex);
- if (tIndex >= 0 && (fTs[min].fWindValue > 0 || fTs[min].fOppValue > 0)) {
- addAngle(angles, end, tIndex);
- }
- }
-
- int advanceCoincidentThis(const Span* oTest, bool opp, int index) {
- Span* const test = &fTs[index];
- Span* end = test;
- do {
- end = &fTs[++index];
- } while (approximately_negative(end->fT - test->fT));
- return index;
- }
-
- int advanceCoincidentOther(const Span* test, double oEndT, int& oIndex) {
- Span* const oTest = &fTs[oIndex];
- Span* oEnd = oTest;
- const double oStartT = oTest->fT;
- while (!approximately_negative(oEndT - oEnd->fT)
- && approximately_negative(oEnd->fT - oStartT)) {
- oEnd = &fTs[++oIndex];
- }
- return oIndex;
- }
-
- bool betweenTs(int lesser, double testT, int greater) {
- if (lesser > greater) {
- SkTSwap<int>(lesser, greater);
- }
- return approximately_between(fTs[lesser].fT, testT, fTs[greater].fT);
- }
-
- const Bounds& bounds() const {
- return fBounds;
- }
-
- void buildAngles(int index, SkTDArray<Angle>& angles, bool includeOpp) const {
- double referenceT = fTs[index].fT;
- int lesser = index;
- while (--lesser >= 0 && (includeOpp || fTs[lesser].fOther->fOperand == fOperand)
- && precisely_negative(referenceT - fTs[lesser].fT)) {
- buildAnglesInner(lesser, angles);
- }
- do {
- buildAnglesInner(index, angles);
- } while (++index < fTs.count() && (includeOpp || fTs[index].fOther->fOperand == fOperand)
- && precisely_negative(fTs[index].fT - referenceT));
- }
-
- void buildAnglesInner(int index, SkTDArray<Angle>& angles) const {
- const Span* span = &fTs[index];
- Segment* other = span->fOther;
- // if there is only one live crossing, and no coincidence, continue
- // in the same direction
- // if there is coincidence, the only choice may be to reverse direction
- // find edge on either side of intersection
- int oIndex = span->fOtherIndex;
- // if done == -1, prior span has already been processed
- int step = 1;
- int next = other->nextExactSpan(oIndex, step);
- if (next < 0) {
- step = -step;
- next = other->nextExactSpan(oIndex, step);
- }
- // add candidate into and away from junction
- other->addTwoAngles(next, oIndex, angles);
- }
-
- int computeSum(int startIndex, int endIndex, bool binary) {
- SkTDArray<Angle> angles;
- addTwoAngles(startIndex, endIndex, angles);
- buildAngles(endIndex, angles, false);
- // OPTIMIZATION: check all angles to see if any have computed wind sum
- // before sorting (early exit if none)
- SkTDArray<Angle*> sorted;
- bool sortable = SortAngles(angles, sorted);
-#if DEBUG_SORT
- sorted[0]->segment()->debugShowSort(__FUNCTION__, sorted, 0, 0, 0);
-#endif
- if (!sortable) {
- return SK_MinS32;
- }
- int angleCount = angles.count();
- const Angle* angle;
- const Segment* base;
- int winding;
- int oWinding;
- int firstIndex = 0;
- do {
- angle = sorted[firstIndex];
- base = angle->segment();
- winding = base->windSum(angle);
- if (winding != SK_MinS32) {
- oWinding = base->oppSum(angle);
- break;
- }
- if (++firstIndex == angleCount) {
- return SK_MinS32;
- }
- } while (true);
- // turn winding into contourWinding
- int spanWinding = base->spanSign(angle);
- bool inner = useInnerWinding(winding + spanWinding, winding);
- #if DEBUG_WINDING
- SkDebugf("%s spanWinding=%d winding=%d sign=%d inner=%d result=%d\n", __FUNCTION__,
- spanWinding, winding, angle->sign(), inner,
- inner ? winding + spanWinding : winding);
- #endif
- if (inner) {
- winding += spanWinding;
- }
- #if DEBUG_SORT
- base->debugShowSort(__FUNCTION__, sorted, firstIndex, winding, oWinding);
- #endif
- int nextIndex = firstIndex + 1;
- int lastIndex = firstIndex != 0 ? firstIndex : angleCount;
- winding -= base->spanSign(angle);
- oWinding -= base->oppSign(angle);
- do {
- if (nextIndex == angleCount) {
- nextIndex = 0;
- }
- angle = sorted[nextIndex];
- Segment* segment = angle->segment();
- bool opp = base->fOperand ^ segment->fOperand;
- int maxWinding, oMaxWinding;
- int spanSign = segment->spanSign(angle);
- int oppoSign = segment->oppSign(angle);
- if (opp) {
- oMaxWinding = oWinding;
- oWinding -= spanSign;
- maxWinding = winding;
- if (oppoSign) {
- winding -= oppoSign;
- }
- } else {
- maxWinding = winding;
- winding -= spanSign;
- oMaxWinding = oWinding;
- if (oppoSign) {
- oWinding -= oppoSign;
- }
- }
- if (segment->windSum(angle) == SK_MinS32) {
- if (opp) {
- if (useInnerWinding(oMaxWinding, oWinding)) {
- oMaxWinding = oWinding;
- }
- if (oppoSign && useInnerWinding(maxWinding, winding)) {
- maxWinding = winding;
- }
- (void) segment->markAndChaseWinding(angle, oMaxWinding, maxWinding);
- } else {
- if (useInnerWinding(maxWinding, winding)) {
- maxWinding = winding;
- }
- if (oppoSign && useInnerWinding(oMaxWinding, oWinding)) {
- oMaxWinding = oWinding;
- }
- (void) segment->markAndChaseWinding(angle, maxWinding,
- binary ? oMaxWinding : 0);
- }
- }
- } while (++nextIndex != lastIndex);
- int minIndex = SkMin32(startIndex, endIndex);
- return windSum(minIndex);
- }
-
- int crossedSpanY(const SkPoint& basePt, SkScalar& bestY, double& hitT, bool& hitSomething,
- double mid, bool opp, bool current) const {
- SkScalar bottom = fBounds.fBottom;
- int bestTIndex = -1;
- if (bottom <= bestY) {
- return bestTIndex;
- }
- SkScalar top = fBounds.fTop;
- if (top >= basePt.fY) {
- return bestTIndex;
- }
- if (fBounds.fLeft > basePt.fX) {
- return bestTIndex;
- }
- if (fBounds.fRight < basePt.fX) {
- return bestTIndex;
- }
- if (fBounds.fLeft == fBounds.fRight) {
- // if vertical, and directly above test point, wait for another one
- return AlmostEqualUlps(basePt.fX, fBounds.fLeft) ? SK_MinS32 : bestTIndex;
- }
- // intersect ray starting at basePt with edge
- Intersections intersections;
- // OPTIMIZE: use specialty function that intersects ray with curve,
- // returning t values only for curve (we don't care about t on ray)
- int pts = (*VSegmentIntersect[fVerb])(fPts, top, bottom, basePt.fX, false, intersections);
- if (pts == 0 || (current && pts == 1)) {
- return bestTIndex;
- }
- if (current) {
- SkASSERT(pts > 1);
- int closestIdx = 0;
- double closest = fabs(intersections.fT[0][0] - mid);
- for (int idx = 1; idx < pts; ++idx) {
- double test = fabs(intersections.fT[0][idx] - mid);
- if (closest > test) {
- closestIdx = idx;
- closest = test;
- }
- }
- if (closestIdx < pts - 1) {
- intersections.fT[0][closestIdx] = intersections.fT[0][pts - 1];
- }
- --pts;
- }
- double bestT = -1;
- for (int index = 0; index < pts; ++index) {
- double foundT = intersections.fT[0][index];
- if (approximately_less_than_zero(foundT)
- || approximately_greater_than_one(foundT)) {
- continue;
- }
- SkScalar testY = (*SegmentYAtT[fVerb])(fPts, foundT);
- if (approximately_negative(testY - bestY)
- || approximately_negative(basePt.fY - testY)) {
- continue;
- }
- if (pts > 1 && fVerb == SkPath::kLine_Verb) {
- return SK_MinS32; // if the intersection is edge on, wait for another one
- }
- if (fVerb > SkPath::kLine_Verb) {
- SkScalar dx = (*SegmentDXAtT[fVerb])(fPts, foundT);
- if (approximately_zero(dx)) {
- return SK_MinS32; // hit vertical, wait for another one
- }
- }
- bestY = testY;
- bestT = foundT;
- }
- if (bestT < 0) {
- return bestTIndex;
- }
- SkASSERT(bestT >= 0);
- SkASSERT(bestT <= 1);
- int start;
- int end = 0;
- do {
- start = end;
- end = nextSpan(start, 1);
- } while (fTs[end].fT < bestT);
- // FIXME: see next candidate for a better pattern to find the next start/end pair
- while (start + 1 < end && fTs[start].fDone) {
- ++start;
- }
- if (!isCanceled(start)) {
- hitT = bestT;
- bestTIndex = start;
- hitSomething = true;
- }
- return bestTIndex;
- }
-
- void decrementSpan(Span* span) {
- SkASSERT(span->fWindValue > 0);
- if (--(span->fWindValue) == 0) {
- if (!span->fOppValue && !span->fDone) {
- span->fDone = true;
- ++fDoneSpans;
- }
- }
- }
-
- bool bumpSpan(Span* span, int windDelta, int oppDelta) {
- SkASSERT(!span->fDone);
- span->fWindValue += windDelta;
- SkASSERT(span->fWindValue >= 0);
- span->fOppValue += oppDelta;
- SkASSERT(span->fOppValue >= 0);
- if (fXor) {
- span->fWindValue &= 1;
- }
- if (fOppXor) {
- span->fOppValue &= 1;
- }
- if (!span->fWindValue && !span->fOppValue) {
- span->fDone = true;
- ++fDoneSpans;
- return true;
- }
- return false;
- }
-
- // OPTIMIZE
- // when the edges are initially walked, they don't automatically get the prior and next
- // edges assigned to positions t=0 and t=1. Doing that would remove the need for this check,
- // and would additionally remove the need for similar checks in condition edges. It would
- // also allow intersection code to assume end of segment intersections (maybe?)
- bool complete() const {
- int count = fTs.count();
- return count > 1 && fTs[0].fT == 0 && fTs[--count].fT == 1;
- }
-
- bool done() const {
- SkASSERT(fDoneSpans <= fTs.count());
- return fDoneSpans == fTs.count();
- }
-
- bool done(int min) const {
- return fTs[min].fDone;
- }
-
- bool done(const Angle* angle) const {
- return done(SkMin32(angle->start(), angle->end()));
- }
-
- SkVector dxdy(int index) const {
- return (*SegmentDXDYAtT[fVerb])(fPts, fTs[index].fT);
- }
-
- SkScalar dy(int index) const {
- return (*SegmentDYAtT[fVerb])(fPts, fTs[index].fT);
- }
-
- bool equalPoints(int greaterTIndex, int lesserTIndex) {
- SkASSERT(greaterTIndex >= lesserTIndex);
- double greaterT = fTs[greaterTIndex].fT;
- double lesserT = fTs[lesserTIndex].fT;
- if (greaterT == lesserT) {
- return true;
- }
- if (!approximately_negative(greaterT - lesserT)) {
- return false;
- }
- return xyAtT(greaterTIndex) == xyAtT(lesserTIndex);
- }
-
- /*
- The M and S variable name parts stand for the operators.
- Mi stands for Minuend (see wiki subtraction, analogous to difference)
- Su stands for Subtrahend
- The Opp variable name part designates that the value is for the Opposite operator.
- Opposite values result from combining coincident spans.
- */
-
- Segment* findNextOp(SkTDArray<Span*>& chase, int& nextStart, int& nextEnd,
- bool& unsortable, ShapeOp op, const int xorMiMask, const int xorSuMask) {
- const int startIndex = nextStart;
- const int endIndex = nextEnd;
- SkASSERT(startIndex != endIndex);
- const int count = fTs.count();
- SkASSERT(startIndex < endIndex ? startIndex < count - 1 : startIndex > 0);
- const int step = SkSign32(endIndex - startIndex);
- const int end = nextExactSpan(startIndex, step);
- SkASSERT(end >= 0);
- Span* endSpan = &fTs[end];
- Segment* other;
- if (isSimple(end)) {
- // mark the smaller of startIndex, endIndex done, and all adjacent
- // spans with the same T value (but not 'other' spans)
- #if DEBUG_WINDING
- SkDebugf("%s simple\n", __FUNCTION__);
- #endif
- int min = SkMin32(startIndex, endIndex);
- if (fTs[min].fDone) {
- return NULL;
- }
- markDoneBinary(min);
- other = endSpan->fOther;
- nextStart = endSpan->fOtherIndex;
- double startT = other->fTs[nextStart].fT;
- nextEnd = nextStart;
- do {
- nextEnd += step;
- }
- while (precisely_zero(startT - other->fTs[nextEnd].fT));
- SkASSERT(step < 0 ? nextEnd >= 0 : nextEnd < other->fTs.count());
- return other;
- }
- // more than one viable candidate -- measure angles to find best
- SkTDArray<Angle> angles;
- SkASSERT(startIndex - endIndex != 0);
- SkASSERT((startIndex - endIndex < 0) ^ (step < 0));
- addTwoAngles(startIndex, end, angles);
- buildAngles(end, angles, true);
- SkTDArray<Angle*> sorted;
- bool sortable = SortAngles(angles, sorted);
- int angleCount = angles.count();
- int firstIndex = findStartingEdge(sorted, startIndex, end);
- SkASSERT(firstIndex >= 0);
- #if DEBUG_SORT
- debugShowSort(__FUNCTION__, sorted, firstIndex);
- #endif
- if (!sortable) {
- unsortable = true;
- return NULL;
- }
- SkASSERT(sorted[firstIndex]->segment() == this);
- #if DEBUG_WINDING
- SkDebugf("%s firstIndex=[%d] sign=%d\n", __FUNCTION__, firstIndex,
- sorted[firstIndex]->sign());
- #endif
- int sumMiWinding = updateWinding(endIndex, startIndex);
- int sumSuWinding = updateOppWinding(endIndex, startIndex);
- if (operand()) {
- SkTSwap<int>(sumMiWinding, sumSuWinding);
- }
- int nextIndex = firstIndex + 1;
- int lastIndex = firstIndex != 0 ? firstIndex : angleCount;
- const Angle* foundAngle = NULL;
- bool foundDone = false;
- // iterate through the angle, and compute everyone's winding
- Segment* nextSegment;
- int activeCount = 0;
- do {
- SkASSERT(nextIndex != firstIndex);
- if (nextIndex == angleCount) {
- nextIndex = 0;
- }
- const Angle* nextAngle = sorted[nextIndex];
- nextSegment = nextAngle->segment();
- int maxWinding, sumWinding, oppMaxWinding, oppSumWinding;
- bool activeAngle = nextSegment->activeOp(xorMiMask, xorSuMask, nextAngle->start(),
- nextAngle->end(), op, sumMiWinding, sumSuWinding,
- maxWinding, sumWinding, oppMaxWinding, oppSumWinding);
- if (activeAngle) {
- ++activeCount;
- if (!foundAngle || (foundDone && activeCount & 1)) {
- if (nextSegment->tiny(nextAngle)) {
- unsortable = true;
- return NULL;
- }
- foundAngle = nextAngle;
- foundDone = nextSegment->done(nextAngle) && !nextSegment->tiny(nextAngle);
- }
- }
- if (nextSegment->done()) {
- continue;
- }
- if (nextSegment->windSum(nextAngle) != SK_MinS32) {
- continue;
- }
- Span* last = nextSegment->markAngle(maxWinding, sumWinding, oppMaxWinding,
- oppSumWinding, activeAngle, nextAngle);
- if (last) {
- *chase.append() = last;
-#if DEBUG_WINDING
- SkDebugf("%s chase.append id=%d\n", __FUNCTION__,
- last->fOther->fTs[last->fOtherIndex].fOther->debugID());
-#endif
- }
- } while (++nextIndex != lastIndex);
- markDoneBinary(SkMin32(startIndex, endIndex));
- if (!foundAngle) {
- return NULL;
- }
- nextStart = foundAngle->start();
- nextEnd = foundAngle->end();
- nextSegment = foundAngle->segment();
-
- #if DEBUG_WINDING
- SkDebugf("%s from:[%d] to:[%d] start=%d end=%d\n",
- __FUNCTION__, debugID(), nextSegment->debugID(), nextStart, nextEnd);
- #endif
- return nextSegment;
- }
-
- Segment* findNextWinding(SkTDArray<Span*>& chase, int& nextStart, int& nextEnd,
- bool& unsortable) {
- const int startIndex = nextStart;
- const int endIndex = nextEnd;
- SkASSERT(startIndex != endIndex);
- const int count = fTs.count();
- SkASSERT(startIndex < endIndex ? startIndex < count - 1 : startIndex > 0);
- const int step = SkSign32(endIndex - startIndex);
- const int end = nextExactSpan(startIndex, step);
- SkASSERT(end >= 0);
- Span* endSpan = &fTs[end];
- Segment* other;
- if (isSimple(end)) {
- // mark the smaller of startIndex, endIndex done, and all adjacent
- // spans with the same T value (but not 'other' spans)
- #if DEBUG_WINDING
- SkDebugf("%s simple\n", __FUNCTION__);
- #endif
- int min = SkMin32(startIndex, endIndex);
- if (fTs[min].fDone) {
- return NULL;
- }
- markDoneUnary(min);
- other = endSpan->fOther;
- nextStart = endSpan->fOtherIndex;
- double startT = other->fTs[nextStart].fT;
- nextEnd = nextStart;
- do {
- nextEnd += step;
- }
- while (precisely_zero(startT - other->fTs[nextEnd].fT));
- SkASSERT(step < 0 ? nextEnd >= 0 : nextEnd < other->fTs.count());
- return other;
- }
- // more than one viable candidate -- measure angles to find best
- SkTDArray<Angle> angles;
- SkASSERT(startIndex - endIndex != 0);
- SkASSERT((startIndex - endIndex < 0) ^ (step < 0));
- addTwoAngles(startIndex, end, angles);
- buildAngles(end, angles, true);
- SkTDArray<Angle*> sorted;
- bool sortable = SortAngles(angles, sorted);
- int angleCount = angles.count();
- int firstIndex = findStartingEdge(sorted, startIndex, end);
- SkASSERT(firstIndex >= 0);
- #if DEBUG_SORT
- debugShowSort(__FUNCTION__, sorted, firstIndex);
- #endif
- if (!sortable) {
- unsortable = true;
- return NULL;
- }
- SkASSERT(sorted[firstIndex]->segment() == this);
- #if DEBUG_WINDING
- SkDebugf("%s firstIndex=[%d] sign=%d\n", __FUNCTION__, firstIndex,
- sorted[firstIndex]->sign());
- #endif
- int sumWinding = updateWinding(endIndex, startIndex);
- int nextIndex = firstIndex + 1;
- int lastIndex = firstIndex != 0 ? firstIndex : angleCount;
- const Angle* foundAngle = NULL;
- bool foundDone = false;
- // iterate through the angle, and compute everyone's winding
- Segment* nextSegment;
- int activeCount = 0;
- do {
- SkASSERT(nextIndex != firstIndex);
- if (nextIndex == angleCount) {
- nextIndex = 0;
- }
- const Angle* nextAngle = sorted[nextIndex];
- nextSegment = nextAngle->segment();
- int maxWinding;
- bool activeAngle = nextSegment->activeWinding(nextAngle->start(), nextAngle->end(),
- maxWinding, sumWinding);
- if (activeAngle) {
- ++activeCount;
- if (!foundAngle || (foundDone && activeCount & 1)) {
- if (nextSegment->tiny(nextAngle)) {
- unsortable = true;
- return NULL;
- }
- foundAngle = nextAngle;
- foundDone = nextSegment->done(nextAngle);
- }
- }
- if (nextSegment->done()) {
- continue;
- }
- if (nextSegment->windSum(nextAngle) != SK_MinS32) {
- continue;
- }
- Span* last = nextSegment->markAngle(maxWinding, sumWinding, activeAngle, nextAngle);
- if (last) {
- *chase.append() = last;
-#if DEBUG_WINDING
- SkDebugf("%s chase.append id=%d\n", __FUNCTION__,
- last->fOther->fTs[last->fOtherIndex].fOther->debugID());
-#endif
- }
- } while (++nextIndex != lastIndex);
- markDoneUnary(SkMin32(startIndex, endIndex));
- if (!foundAngle) {
- return NULL;
- }
- nextStart = foundAngle->start();
- nextEnd = foundAngle->end();
- nextSegment = foundAngle->segment();
- #if DEBUG_WINDING
- SkDebugf("%s from:[%d] to:[%d] start=%d end=%d\n",
- __FUNCTION__, debugID(), nextSegment->debugID(), nextStart, nextEnd);
- #endif
- return nextSegment;
- }
-
- Segment* findNextXor(int& nextStart, int& nextEnd, bool& unsortable) {
- const int startIndex = nextStart;
- const int endIndex = nextEnd;
- SkASSERT(startIndex != endIndex);
- int count = fTs.count();
- SkASSERT(startIndex < endIndex ? startIndex < count - 1
- : startIndex > 0);
- int step = SkSign32(endIndex - startIndex);
- int end = nextExactSpan(startIndex, step);
- SkASSERT(end >= 0);
- Span* endSpan = &fTs[end];
- Segment* other;
- if (isSimple(end)) {
- #if DEBUG_WINDING
- SkDebugf("%s simple\n", __FUNCTION__);
- #endif
- int min = SkMin32(startIndex, endIndex);
- if (fTs[min].fDone) {
- return NULL;
- }
- markDone(min, 1);
- other = endSpan->fOther;
- nextStart = endSpan->fOtherIndex;
- double startT = other->fTs[nextStart].fT;
- #if 01 // FIXME: I don't know why the logic here is difference from the winding case
- SkDEBUGCODE(bool firstLoop = true;)
- if ((approximately_less_than_zero(startT) && step < 0)
- || (approximately_greater_than_one(startT) && step > 0)) {
- step = -step;
- SkDEBUGCODE(firstLoop = false;)
- }
- do {
- #endif
- nextEnd = nextStart;
- do {
- nextEnd += step;
- }
- while (precisely_zero(startT - other->fTs[nextEnd].fT));
- #if 01
- if (other->fTs[SkMin32(nextStart, nextEnd)].fWindValue) {
- break;
- }
- #ifdef SK_DEBUG
- SkASSERT(firstLoop);
- #endif
- SkDEBUGCODE(firstLoop = false;)
- step = -step;
- } while (true);
- #endif
- SkASSERT(step < 0 ? nextEnd >= 0 : nextEnd < other->fTs.count());
- return other;
- }
- SkTDArray<Angle> angles;
- SkASSERT(startIndex - endIndex != 0);
- SkASSERT((startIndex - endIndex < 0) ^ (step < 0));
- addTwoAngles(startIndex, end, angles);
- buildAngles(end, angles, false);
- SkTDArray<Angle*> sorted;
- bool sortable = SortAngles(angles, sorted);
- if (!sortable) {
- unsortable = true;
- #if DEBUG_SORT
- debugShowSort(__FUNCTION__, sorted, findStartingEdge(sorted, startIndex, end), 0, 0);
- #endif
- return NULL;
- }
- int angleCount = angles.count();
- int firstIndex = findStartingEdge(sorted, startIndex, end);
- SkASSERT(firstIndex >= 0);
- #if DEBUG_SORT
- debugShowSort(__FUNCTION__, sorted, firstIndex, 0, 0);
- #endif
- SkASSERT(sorted[firstIndex]->segment() == this);
- int nextIndex = firstIndex + 1;
- int lastIndex = firstIndex != 0 ? firstIndex : angleCount;
- const Angle* foundAngle = NULL;
- bool foundDone = false;
- Segment* nextSegment;
- int activeCount = 0;
- do {
- SkASSERT(nextIndex != firstIndex);
- if (nextIndex == angleCount) {
- nextIndex = 0;
- }
- const Angle* nextAngle = sorted[nextIndex];
- nextSegment = nextAngle->segment();
- ++activeCount;
- if (!foundAngle || (foundDone && activeCount & 1)) {
- if (nextSegment->tiny(nextAngle)) {
- unsortable = true;
- return NULL;
- }
- foundAngle = nextAngle;
- foundDone = nextSegment->done(nextAngle);
- }
- if (nextSegment->done()) {
- continue;
- }
- } while (++nextIndex != lastIndex);
- markDone(SkMin32(startIndex, endIndex), 1);
- if (!foundAngle) {
- return NULL;
- }
- nextStart = foundAngle->start();
- nextEnd = foundAngle->end();
- nextSegment = foundAngle->segment();
- #if DEBUG_WINDING
- SkDebugf("%s from:[%d] to:[%d] start=%d end=%d\n",
- __FUNCTION__, debugID(), nextSegment->debugID(), nextStart, nextEnd);
- #endif
- return nextSegment;
- }
-
- int findStartingEdge(SkTDArray<Angle*>& sorted, int start, int end) {
- int angleCount = sorted.count();
- int firstIndex = -1;
- for (int angleIndex = 0; angleIndex < angleCount; ++angleIndex) {
- const Angle* angle = sorted[angleIndex];
- if (angle->segment() == this && angle->start() == end &&
- angle->end() == start) {
- firstIndex = angleIndex;
- break;
- }
- }
- return firstIndex;
- }
-
- // FIXME: this is tricky code; needs its own unit test
- // note that fOtherIndex isn't computed yet, so it can't be used here
- void findTooCloseToCall() {
- int count = fTs.count();
- if (count < 3) { // require t=0, x, 1 at minimum
- return;
- }
- int matchIndex = 0;
- int moCount;
- Span* match;
- Segment* mOther;
- do {
- match = &fTs[matchIndex];
- mOther = match->fOther;
- // FIXME: allow quads, cubics to be near coincident?
- if (mOther->fVerb == SkPath::kLine_Verb) {
- moCount = mOther->fTs.count();
- if (moCount >= 3) {
- break;
- }
- }
- if (++matchIndex >= count) {
- return;
- }
- } while (true); // require t=0, x, 1 at minimum
- // OPTIMIZATION: defer matchPt until qualifying toCount is found?
- const SkPoint* matchPt = &xyAtT(match);
- // look for a pair of nearby T values that map to the same (x,y) value
- // if found, see if the pair of other segments share a common point. If
- // so, the span from here to there is coincident.
- for (int index = matchIndex + 1; index < count; ++index) {
- Span* test = &fTs[index];
- if (test->fDone) {
- continue;
- }
- Segment* tOther = test->fOther;
- if (tOther->fVerb != SkPath::kLine_Verb) {
- continue; // FIXME: allow quads, cubics to be near coincident?
- }
- int toCount = tOther->fTs.count();
- if (toCount < 3) { // require t=0, x, 1 at minimum
- continue;
- }
- const SkPoint* testPt = &xyAtT(test);
- if (*matchPt != *testPt) {
- matchIndex = index;
- moCount = toCount;
- match = test;
- mOther = tOther;
- matchPt = testPt;
- continue;
- }
- int moStart = -1;
- int moEnd = -1;
- double moStartT, moEndT;
- for (int moIndex = 0; moIndex < moCount; ++moIndex) {
- Span& moSpan = mOther->fTs[moIndex];
- if (moSpan.fDone) {
- continue;
- }
- if (moSpan.fOther == this) {
- if (moSpan.fOtherT == match->fT) {
- moStart = moIndex;
- moStartT = moSpan.fT;
- }
- continue;
- }
- if (moSpan.fOther == tOther) {
- if (tOther->windValueAt(moSpan.fOtherT) == 0) {
- moStart = -1;
- break;
- }
- SkASSERT(moEnd == -1);
- moEnd = moIndex;
- moEndT = moSpan.fT;
- }
- }
- if (moStart < 0 || moEnd < 0) {
- continue;
- }
- // FIXME: if moStartT, moEndT are initialized to NaN, can skip this test
- if (approximately_equal(moStartT, moEndT)) {
- continue;
- }
- int toStart = -1;
- int toEnd = -1;
- double toStartT, toEndT;
- for (int toIndex = 0; toIndex < toCount; ++toIndex) {
- Span& toSpan = tOther->fTs[toIndex];
- if (toSpan.fDone) {
- continue;
- }
- if (toSpan.fOther == this) {
- if (toSpan.fOtherT == test->fT) {
- toStart = toIndex;
- toStartT = toSpan.fT;
- }
- continue;
- }
- if (toSpan.fOther == mOther && toSpan.fOtherT == moEndT) {
- if (mOther->windValueAt(toSpan.fOtherT) == 0) {
- moStart = -1;
- break;
- }
- SkASSERT(toEnd == -1);
- toEnd = toIndex;
- toEndT = toSpan.fT;
- }
- }
- // FIXME: if toStartT, toEndT are initialized to NaN, can skip this test
- if (toStart <= 0 || toEnd <= 0) {
- continue;
- }
- if (approximately_equal(toStartT, toEndT)) {
- continue;
- }
- // test to see if the segment between there and here is linear
- if (!mOther->isLinear(moStart, moEnd)
- || !tOther->isLinear(toStart, toEnd)) {
- continue;
- }
- bool flipped = (moStart - moEnd) * (toStart - toEnd) < 1;
- if (flipped) {
- mOther->addTCancel(moStartT, moEndT, *tOther, toEndT, toStartT);
- } else {
- mOther->addTCoincident(moStartT, moEndT, *tOther, toStartT, toEndT);
- }
- }
- }
-
- // FIXME: either:
- // a) mark spans with either end unsortable as done, or
- // b) rewrite findTop / findTopSegment / findTopContour to iterate further
- // when encountering an unsortable span
-
- // OPTIMIZATION : for a pair of lines, can we compute points at T (cached)
- // and use more concise logic like the old edge walker code?
- // FIXME: this needs to deal with coincident edges
- Segment* findTop(int& tIndex, int& endIndex, bool& unsortable, bool onlySortable) {
- // iterate through T intersections and return topmost
- // topmost tangent from y-min to first pt is closer to horizontal
- SkASSERT(!done());
- int firstT = -1;
- /* SkPoint topPt = */ activeLeftTop(onlySortable, &firstT);
- if (firstT < 0) {
- unsortable = true;
- firstT = 0;
- while (fTs[firstT].fDone) {
- SkASSERT(firstT < fTs.count());
- ++firstT;
- }
- tIndex = firstT;
- endIndex = nextExactSpan(firstT, 1);
- return this;
- }
- // sort the edges to find the leftmost
- int step = 1;
- int end = nextSpan(firstT, step);
- if (end == -1) {
- step = -1;
- end = nextSpan(firstT, step);
- SkASSERT(end != -1);
- }
- // if the topmost T is not on end, or is three-way or more, find left
- // look for left-ness from tLeft to firstT (matching y of other)
- SkTDArray<Angle> angles;
- SkASSERT(firstT - end != 0);
- addTwoAngles(end, firstT, angles);
- buildAngles(firstT, angles, true);
- SkTDArray<Angle*> sorted;
- bool sortable = SortAngles(angles, sorted);
- int first = SK_MaxS32;
- SkScalar top = SK_ScalarMax;
- int count = sorted.count();
- for (int index = 0; index < count; ++index) {
- const Angle* angle = sorted[index];
- Segment* next = angle->segment();
- Bounds bounds;
- next->subDivideBounds(angle->end(), angle->start(), bounds);
- if (approximately_greater(top, bounds.fTop)) {
- top = bounds.fTop;
- first = index;
- }
- }
- SkASSERT(first < SK_MaxS32);
- #if DEBUG_SORT // || DEBUG_SWAP_TOP
- sorted[first]->segment()->debugShowSort(__FUNCTION__, sorted, first, 0, 0);
- #endif
- if (onlySortable && !sortable) {
- unsortable = true;
- return NULL;
- }
- // skip edges that have already been processed
- firstT = first - 1;
- Segment* leftSegment;
- do {
- if (++firstT == count) {
- firstT = 0;
- }
- const Angle* angle = sorted[firstT];
- SkASSERT(!onlySortable || !angle->unsortable());
- leftSegment = angle->segment();
- tIndex = angle->end();
- endIndex = angle->start();
- } while (leftSegment->fTs[SkMin32(tIndex, endIndex)].fDone);
- if (leftSegment->verb() >= SkPath::kQuad_Verb) {
- if (!leftSegment->clockwise(tIndex, endIndex)) {
- bool swap = leftSegment->verb() == SkPath::kQuad_Verb
- || (!leftSegment->monotonic_in_y(tIndex, endIndex)
- && !leftSegment->serpentine(tIndex, endIndex));
- #if DEBUG_SWAP_TOP
- SkDebugf("%s swap=%d serpentine=%d controls_contained_by_ends=%d\n", __FUNCTION__,
- swap,
- leftSegment->serpentine(tIndex, endIndex),
- leftSegment->controls_contained_by_ends(tIndex, endIndex),
- leftSegment->monotonic_in_y(tIndex, endIndex));
- #endif
- if (swap) {
- // FIXME: I doubt it makes sense to (necessarily) swap if the edge was not the first
- // sorted but merely the first not already processed (i.e., not done)
- SkTSwap(tIndex, endIndex);
- }
- }
- }
- SkASSERT(!leftSegment->fTs[SkMin32(tIndex, endIndex)].fTiny);
- return leftSegment;
- }
-
- // FIXME: not crazy about this
- // when the intersections are performed, the other index is into an
- // incomplete array. As the array grows, the indices become incorrect
- // while the following fixes the indices up again, it isn't smart about
- // skipping segments whose indices are already correct
- // assuming we leave the code that wrote the index in the first place
- void fixOtherTIndex() {
- int iCount = fTs.count();
- for (int i = 0; i < iCount; ++i) {
- Span& iSpan = fTs[i];
- double oT = iSpan.fOtherT;
- Segment* other = iSpan.fOther;
- int oCount = other->fTs.count();
- for (int o = 0; o < oCount; ++o) {
- Span& oSpan = other->fTs[o];
- if (oT == oSpan.fT && this == oSpan.fOther && oSpan.fOtherT == iSpan.fT) {
- iSpan.fOtherIndex = o;
- break;
- }
- }
- }
- }
-
- void init(const SkPoint pts[], SkPath::Verb verb, bool operand, bool evenOdd) {
- fDoneSpans = 0;
- fOperand = operand;
- fXor = evenOdd;
- fPts = pts;
- fVerb = verb;
- }
-
- void initWinding(int start, int end) {
- int local = spanSign(start, end);
- int oppLocal = oppSign(start, end);
- (void) markAndChaseWinding(start, end, local, oppLocal);
- // OPTIMIZATION: the reverse mark and chase could skip the first marking
- (void) markAndChaseWinding(end, start, local, oppLocal);
- }
-
- void initWinding(int start, int end, int winding, int oppWinding) {
- int local = spanSign(start, end);
- if (local * winding >= 0) {
- winding += local;
- }
- int oppLocal = oppSign(start, end);
- if (oppLocal * oppWinding >= 0) {
- oppWinding += oppLocal;
- }
- (void) markAndChaseWinding(start, end, winding, oppWinding);
- }
-
-/*
-when we start with a vertical intersect, we try to use the dx to determine if the edge is to
-the left or the right of vertical. This determines if we need to add the span's
-sign or not. However, this isn't enough.
-If the supplied sign (winding) is zero, then we didn't hit another vertical span, so dx is needed.
-If there was a winding, then it may or may not need adjusting. If the span the winding was borrowed
-from has the same x direction as this span, the winding should change. If the dx is opposite, then
-the same winding is shared by both.
-*/
- void initWinding(int start, int end, double tHit, int winding, SkScalar hitDx, int oppWind,
- SkScalar hitOppDx) {
- SkASSERT(hitDx || !winding);
- SkScalar dx = (*SegmentDXAtT[fVerb])(fPts, tHit);
- SkASSERT(dx);
- int windVal = windValue(SkMin32(start, end));
- #if DEBUG_WINDING_AT_T
- SkDebugf("%s oldWinding=%d hitDx=%c dx=%c windVal=%d", __FUNCTION__, winding,
- hitDx ? hitDx > 0 ? '+' : '-' : '0', dx > 0 ? '+' : '-', windVal);
- #endif
- if (!winding) {
- winding = dx < 0 ? windVal : -windVal;
- } else if (winding * dx < 0) {
- int sideWind = winding + (dx < 0 ? windVal : -windVal);
- if (abs(winding) < abs(sideWind)) {
- winding = sideWind;
- }
- }
- #if DEBUG_WINDING_AT_T
- SkDebugf(" winding=%d\n", winding);
- #endif
- int oppLocal = oppSign(start, end);
- SkASSERT(hitOppDx || !oppWind || !oppLocal);
- int oppWindVal = oppValue(SkMin32(start, end));
- if (!oppWind) {
- oppWind = dx < 0 ? oppWindVal : -oppWindVal;
- } else if (hitOppDx * dx >= 0) {
- int oppSideWind = oppWind + (dx < 0 ? oppWindVal : -oppWindVal);
- if (abs(oppWind) < abs(oppSideWind)) {
- oppWind = oppSideWind;
- }
- }
- (void) markAndChaseWinding(start, end, winding, oppWind);
- }
-
- bool intersected() const {
- return fTs.count() > 0;
- }
-
- bool isCanceled(int tIndex) const {
- return fTs[tIndex].fWindValue == 0 && fTs[tIndex].fOppValue == 0;
- }
-
- bool isConnected(int startIndex, int endIndex) const {
- return fTs[startIndex].fWindSum != SK_MinS32
- || fTs[endIndex].fWindSum != SK_MinS32;
- }
-
- bool isHorizontal() const {
- return fBounds.fTop == fBounds.fBottom;
- }
-
- bool isLinear(int start, int end) const {
- if (fVerb == SkPath::kLine_Verb) {
- return true;
- }
- if (fVerb == SkPath::kQuad_Verb) {
- SkPoint qPart[3];
- QuadSubDivide(fPts, fTs[start].fT, fTs[end].fT, qPart);
- return QuadIsLinear(qPart);
- } else {
- SkASSERT(fVerb == SkPath::kCubic_Verb);
- SkPoint cPart[4];
- CubicSubDivide(fPts, fTs[start].fT, fTs[end].fT, cPart);
- return CubicIsLinear(cPart);
- }
- }
-
- // OPTIMIZE: successive calls could start were the last leaves off
- // or calls could specialize to walk forwards or backwards
- bool isMissing(double startT) const {
- size_t tCount = fTs.count();
- for (size_t index = 0; index < tCount; ++index) {
- if (approximately_zero(startT - fTs[index].fT)) {
- return false;
- }
- }
- return true;
- }
-
- bool isSimple(int end) const {
- int count = fTs.count();
- if (count == 2) {
- return true;
- }
- double t = fTs[end].fT;
- if (approximately_less_than_zero(t)) {
- return !approximately_less_than_zero(fTs[1].fT);
- }
- if (approximately_greater_than_one(t)) {
- return !approximately_greater_than_one(fTs[count - 2].fT);
- }
- return false;
- }
-
- bool isVertical() const {
- return fBounds.fLeft == fBounds.fRight;
- }
-
- bool isVertical(int start, int end) const {
- return (*SegmentVertical[fVerb])(fPts, start, end);
- }
-
- SkScalar leftMost(int start, int end) const {
- return (*SegmentLeftMost[fVerb])(fPts, fTs[start].fT, fTs[end].fT);
- }
-
- // this span is excluded by the winding rule -- chase the ends
- // as long as they are unambiguous to mark connections as done
- // and give them the same winding value
- Span* markAndChaseDone(const Angle* angle, int winding) {
- int index = angle->start();
- int endIndex = angle->end();
- return markAndChaseDone(index, endIndex, winding);
- }
-
- Span* markAndChaseDone(int index, int endIndex, int winding) {
- int step = SkSign32(endIndex - index);
- int min = SkMin32(index, endIndex);
- markDone(min, winding);
- Span* last;
- Segment* other = this;
- while ((other = other->nextChase(index, step, min, last))) {
- other->markDone(min, winding);
- }
- return last;
- }
-
- Span* markAndChaseDoneBinary(const Angle* angle, int winding, int oppWinding) {
- int index = angle->start();
- int endIndex = angle->end();
- int step = SkSign32(endIndex - index);
- int min = SkMin32(index, endIndex);
- markDoneBinary(min, winding, oppWinding);
- Span* last;
- Segment* other = this;
- while ((other = other->nextChase(index, step, min, last))) {
- other->markDoneBinary(min, winding, oppWinding);
- }
- return last;
- }
-
- Span* markAndChaseDoneBinary(int index, int endIndex) {
- int step = SkSign32(endIndex - index);
- int min = SkMin32(index, endIndex);
- markDoneBinary(min);
- Span* last;
- Segment* other = this;
- while ((other = other->nextChase(index, step, min, last))) {
- if (other->done()) {
- return NULL;
- }
- other->markDoneBinary(min);
- }
- return last;
- }
-
- Span* markAndChaseDoneUnary(int index, int endIndex) {
- int step = SkSign32(endIndex - index);
- int min = SkMin32(index, endIndex);
- markDoneUnary(min);
- Span* last;
- Segment* other = this;
- while ((other = other->nextChase(index, step, min, last))) {
- if (other->done()) {
- return NULL;
- }
- other->markDoneUnary(min);
- }
- return last;
- }
-
- Span* markAndChaseDoneUnary(const Angle* angle, int winding) {
- int index = angle->start();
- int endIndex = angle->end();
- return markAndChaseDone(index, endIndex, winding);
- }
-
- Span* markAndChaseWinding(const Angle* angle, const int winding) {
- int index = angle->start();
- int endIndex = angle->end();
- int step = SkSign32(endIndex - index);
- int min = SkMin32(index, endIndex);
- markWinding(min, winding);
- Span* last;
- Segment* other = this;
- while ((other = other->nextChase(index, step, min, last))) {
- if (other->fTs[min].fWindSum != SK_MinS32) {
- SkASSERT(other->fTs[min].fWindSum == winding);
- return NULL;
- }
- other->markWinding(min, winding);
- }
- return last;
- }
-
- Span* markAndChaseWinding(int index, int endIndex, int winding, int oppWinding) {
- int min = SkMin32(index, endIndex);
- int step = SkSign32(endIndex - index);
- markWinding(min, winding, oppWinding);
- Span* last;
- Segment* other = this;
- while ((other = other->nextChase(index, step, min, last))) {
- if (other->fTs[min].fWindSum != SK_MinS32) {
- SkASSERT(other->fTs[min].fWindSum == winding || other->fTs[min].fLoop);
- return NULL;
- }
- other->markWinding(min, winding, oppWinding);
- }
- return last;
- }
-
- Span* markAndChaseWinding(const Angle* angle, int winding, int oppWinding) {
- int start = angle->start();
- int end = angle->end();
- return markAndChaseWinding(start, end, winding, oppWinding);
- }
-
- Span* markAngle(int maxWinding, int sumWinding, bool activeAngle, const Angle* angle) {
- SkASSERT(angle->segment() == this);
- if (useInnerWinding(maxWinding, sumWinding)) {
- maxWinding = sumWinding;
- }
- Span* last;
- if (activeAngle) {
- last = markAndChaseWinding(angle, maxWinding);
- } else {
- last = markAndChaseDoneUnary(angle, maxWinding);
- }
- return last;
- }
-
- Span* markAngle(int maxWinding, int sumWinding, int oppMaxWinding, int oppSumWinding,
- bool activeAngle, const Angle* angle) {
- SkASSERT(angle->segment() == this);
- if (useInnerWinding(maxWinding, sumWinding)) {
- maxWinding = sumWinding;
- }
- if (oppMaxWinding != oppSumWinding && useInnerWinding(oppMaxWinding, oppSumWinding)) {
- oppMaxWinding = oppSumWinding;
- }
- Span* last;
- if (activeAngle) {
- last = markAndChaseWinding(angle, maxWinding, oppMaxWinding);
- } else {
- last = markAndChaseDoneBinary(angle, maxWinding, oppMaxWinding);
- }
- return last;
- }
-
- // FIXME: this should also mark spans with equal (x,y)
- // This may be called when the segment is already marked done. While this
- // wastes time, it shouldn't do any more than spin through the T spans.
- // OPTIMIZATION: abort on first done found (assuming that this code is
- // always called to mark segments done).
- void markDone(int index, int winding) {
- // SkASSERT(!done());
- SkASSERT(winding);
- double referenceT = fTs[index].fT;
- int lesser = index;
- while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) {
- markOneDone(__FUNCTION__, lesser, winding);
- }
- do {
- markOneDone(__FUNCTION__, index, winding);
- } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenceT));
- }
-
- void markDoneBinary(int index, int winding, int oppWinding) {
- // SkASSERT(!done());
- SkASSERT(winding || oppWinding);
- double referenceT = fTs[index].fT;
- int lesser = index;
- while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) {
- markOneDoneBinary(__FUNCTION__, lesser, winding, oppWinding);
- }
- do {
- markOneDoneBinary(__FUNCTION__, index, winding, oppWinding);
- } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenceT));
- }
-
- void markDoneBinary(int index) {
- double referenceT = fTs[index].fT;
- int lesser = index;
- while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) {
- markOneDoneBinary(__FUNCTION__, lesser);
- }
- do {
- markOneDoneBinary(__FUNCTION__, index);
- } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenceT));
- }
-
- void markDoneUnary(int index, int winding) {
- // SkASSERT(!done());
- SkASSERT(winding);
- double referenceT = fTs[index].fT;
- int lesser = index;
- while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) {
- markOneDoneUnary(__FUNCTION__, lesser, winding);
- }
- do {
- markOneDoneUnary(__FUNCTION__, index, winding);
- } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenceT));
- }
-
- void markDoneUnary(int index) {
- double referenceT = fTs[index].fT;
- int lesser = index;
- while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) {
- markOneDoneUnary(__FUNCTION__, lesser);
- }
- do {
- markOneDoneUnary(__FUNCTION__, index);
- } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenceT));
- }
-
- void markOneDone(const char* funName, int tIndex, int winding) {
- Span* span = markOneWinding(funName, tIndex, winding);
- if (!span) {
- return;
- }
- span->fDone = true;
- fDoneSpans++;
- }
-
- void markOneDoneBinary(const char* funName, int tIndex) {
- Span* span = verifyOneWinding(funName, tIndex);
- if (!span) {
- return;
- }
- span->fDone = true;
- fDoneSpans++;
- }
-
- void markOneDoneBinary(const char* funName, int tIndex, int winding, int oppWinding) {
- Span* span = markOneWinding(funName, tIndex, winding, oppWinding);
- if (!span) {
- return;
- }
- span->fDone = true;
- fDoneSpans++;
- }
-
- void markOneDoneUnary(const char* funName, int tIndex) {
- Span* span = verifyOneWindingU(funName, tIndex);
- if (!span) {
- return;
- }
- span->fDone = true;
- fDoneSpans++;
- }
-
- void markOneDoneUnary(const char* funName, int tIndex, int winding) {
- Span* span = markOneWinding(funName, tIndex, winding);
- if (!span) {
- return;
- }
- span->fDone = true;
- fDoneSpans++;
- }
-
- Span* markOneWinding(const char* funName, int tIndex, int winding) {
- Span& span = fTs[tIndex];
- if (span.fDone) {
- return NULL;
- }
- #if DEBUG_MARK_DONE
- debugShowNewWinding(funName, span, winding);
- #endif
- SkASSERT(span.fWindSum == SK_MinS32 || span.fWindSum == winding);
- #ifdef SK_DEBUG
- SkASSERT(abs(winding) <= gDebugMaxWindSum);
- #endif
- span.fWindSum = winding;
- return &span;
- }
-
- Span* markOneWinding(const char* funName, int tIndex, int winding, int oppWinding) {
- Span& span = fTs[tIndex];
- if (span.fDone) {
- return NULL;
- }
- #if DEBUG_MARK_DONE
- debugShowNewWinding(funName, span, winding, oppWinding);
- #endif
- SkASSERT(span.fWindSum == SK_MinS32 || span.fWindSum == winding);
- #ifdef SK_DEBUG
- SkASSERT(abs(winding) <= gDebugMaxWindSum);
- #endif
- span.fWindSum = winding;
- SkASSERT(span.fOppSum == SK_MinS32 || span.fOppSum == oppWinding);
- #ifdef SK_DEBUG
- SkASSERT(abs(oppWinding) <= gDebugMaxWindSum);
- #endif
- span.fOppSum = oppWinding;
- return &span;
- }
-
- bool controls_contained_by_ends(int tStart, int tEnd) const {
- if (fVerb != SkPath::kCubic_Verb) {
- return false;
- }
- MAKE_CONST_CUBIC(aCubic, fPts);
- Cubic dst;
- sub_divide(aCubic, fTs[tStart].fT, fTs[tEnd].fT, dst);
- return ::controls_contained_by_ends(dst);
- }
-
- // from http://stackoverflow.com/questions/1165647/how-to-determine-if-a-list-of-polygon-points-are-in-clockwise-order
- bool clockwise(int tStart, int tEnd) const {
- SkASSERT(fVerb != SkPath::kLine_Verb);
- SkPoint edge[4];
- subDivide(tStart, tEnd, edge);
- double sum = (edge[0].fX - edge[fVerb].fX) * (edge[0].fY + edge[fVerb].fY);
- if (fVerb == SkPath::kCubic_Verb) {
- SkScalar lesser = SkTMin(edge[0].fY, edge[3].fY);
- if (edge[1].fY < lesser && edge[2].fY < lesser) {
- _Line tangent1 = { {edge[0].fX, edge[0].fY}, {edge[1].fX, edge[1].fY} };
- _Line tangent2 = { {edge[2].fX, edge[2].fY}, {edge[3].fX, edge[3].fY} };
- if (testIntersect(tangent1, tangent2)) {
- SkPoint topPt = CubicTop(fPts, fTs[tStart].fT, fTs[tEnd].fT);
- sum += (topPt.fX - edge[0].fX) * (topPt.fY + edge[0].fY);
- sum += (edge[3].fX - topPt.fX) * (edge[3].fY + topPt.fY);
- return sum <= 0;
- }
- }
- }
- for (int idx = 0; idx < fVerb; ++idx){
- sum += (edge[idx + 1].fX - edge[idx].fX) * (edge[idx + 1].fY + edge[idx].fY);
- }
- return sum <= 0;
- }
-
- bool monotonic_in_y(int tStart, int tEnd) const {
- if (fVerb != SkPath::kCubic_Verb) {
- return false;
- }
- MAKE_CONST_CUBIC(aCubic, fPts);
- Cubic dst;
- sub_divide(aCubic, fTs[tStart].fT, fTs[tEnd].fT, dst);
- return ::monotonic_in_y(dst);
- }
-
- bool serpentine(int tStart, int tEnd) const {
- if (fVerb != SkPath::kCubic_Verb) {
- return false;
- }
- MAKE_CONST_CUBIC(aCubic, fPts);
- Cubic dst;
- sub_divide(aCubic, fTs[tStart].fT, fTs[tEnd].fT, dst);
- return ::serpentine(dst);
- }
-
- Span* verifyOneWinding(const char* funName, int tIndex) {
- Span& span = fTs[tIndex];
- if (span.fDone) {
- return NULL;
- }
- #if DEBUG_MARK_DONE
- debugShowNewWinding(funName, span, span.fWindSum, span.fOppSum);
- #endif
- SkASSERT(span.fWindSum != SK_MinS32);
- SkASSERT(span.fOppSum != SK_MinS32);
- return &span;
- }
-
- Span* verifyOneWindingU(const char* funName, int tIndex) {
- Span& span = fTs[tIndex];
- if (span.fDone) {
- return NULL;
- }
- #if DEBUG_MARK_DONE
- debugShowNewWinding(funName, span, span.fWindSum);
- #endif
- SkASSERT(span.fWindSum != SK_MinS32);
- return &span;
- }
-
- // note that just because a span has one end that is unsortable, that's
- // not enough to mark it done. The other end may be sortable, allowing the
- // span to be added.
- // FIXME: if abs(start - end) > 1, mark intermediates as unsortable on both ends
- void markUnsortable(int start, int end) {
- Span* span = &fTs[start];
- if (start < end) {
-#if DEBUG_UNSORTABLE
- debugShowNewWinding(__FUNCTION__, *span, 0);
-#endif
- span->fUnsortableStart = true;
- } else {
- --span;
-#if DEBUG_UNSORTABLE
- debugShowNewWinding(__FUNCTION__, *span, 0);
-#endif
- span->fUnsortableEnd = true;
- }
- if (!span->fUnsortableStart || !span->fUnsortableEnd || span->fDone) {
- return;
- }
- span->fDone = true;
- fDoneSpans++;
- }
-
- void markWinding(int index, int winding) {
- // SkASSERT(!done());
- SkASSERT(winding);
- double referenceT = fTs[index].fT;
- int lesser = index;
- while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) {
- markOneWinding(__FUNCTION__, lesser, winding);
- }
- do {
- markOneWinding(__FUNCTION__, index, winding);
- } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenceT));
- }
-
- void markWinding(int index, int winding, int oppWinding) {
- // SkASSERT(!done());
- SkASSERT(winding || oppWinding);
- double referenceT = fTs[index].fT;
- int lesser = index;
- while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) {
- markOneWinding(__FUNCTION__, lesser, winding, oppWinding);
- }
- do {
- markOneWinding(__FUNCTION__, index, winding, oppWinding);
- } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenceT));
- }
-
- void matchWindingValue(int tIndex, double t, bool borrowWind) {
- int nextDoorWind = SK_MaxS32;
- int nextOppWind = SK_MaxS32;
- if (tIndex > 0) {
- const Span& below = fTs[tIndex - 1];
- if (approximately_negative(t - below.fT)) {
- nextDoorWind = below.fWindValue;
- nextOppWind = below.fOppValue;
- }
- }
- if (nextDoorWind == SK_MaxS32 && tIndex + 1 < fTs.count()) {
- const Span& above = fTs[tIndex + 1];
- if (approximately_negative(above.fT - t)) {
- nextDoorWind = above.fWindValue;
- nextOppWind = above.fOppValue;
- }
- }
- if (nextDoorWind == SK_MaxS32 && borrowWind && tIndex > 0 && t < 1) {
- const Span& below = fTs[tIndex - 1];
- nextDoorWind = below.fWindValue;
- nextOppWind = below.fOppValue;
- }
- if (nextDoorWind != SK_MaxS32) {
- Span& newSpan = fTs[tIndex];
- newSpan.fWindValue = nextDoorWind;
- newSpan.fOppValue = nextOppWind;
- if (!nextDoorWind && !nextOppWind && !newSpan.fDone) {
- newSpan.fDone = true;
- ++fDoneSpans;
- }
- }
- }
-
- bool moreHorizontal(int index, int endIndex, bool& unsortable) const {
- // find bounds
- Bounds bounds;
- bounds.setPoint(xyAtT(index));
- bounds.add(xyAtT(endIndex));
- SkScalar width = bounds.width();
- SkScalar height = bounds.height();
- if (width > height) {
- if (approximately_negative(width)) {
- unsortable = true; // edge is too small to resolve meaningfully
- }
- return false;
- } else {
- if (approximately_negative(height)) {
- unsortable = true; // edge is too small to resolve meaningfully
- }
- return true;
- }
- }
-
- // return span if when chasing, two or more radiating spans are not done
- // OPTIMIZATION: ? multiple spans is detected when there is only one valid
- // candidate and the remaining spans have windValue == 0 (canceled by
- // coincidence). The coincident edges could either be removed altogether,
- // or this code could be more complicated in detecting this case. Worth it?
- bool multipleSpans(int end) const {
- return end > 0 && end < fTs.count() - 1;
- }
-
- bool nextCandidate(int& start, int& end) const {
- while (fTs[end].fDone) {
- if (fTs[end].fT == 1) {
- return false;
- }
- ++end;
- }
- start = end;
- end = nextExactSpan(start, 1);
- return true;
- }
-
- Segment* nextChase(int& index, const int step, int& min, Span*& last) {
- int end = nextExactSpan(index, step);
- SkASSERT(end >= 0);
- if (multipleSpans(end)) {
- last = &fTs[end];
- return NULL;
- }
- const Span& endSpan = fTs[end];
- Segment* other = endSpan.fOther;
- index = endSpan.fOtherIndex;
- SkASSERT(index >= 0);
- int otherEnd = other->nextExactSpan(index, step);
- SkASSERT(otherEnd >= 0);
- min = SkMin32(index, otherEnd);
- return other;
- }
-
- // This has callers for two different situations: one establishes the end
- // of the current span, and one establishes the beginning of the next span
- // (thus the name). When this is looking for the end of the current span,
- // coincidence is found when the beginning Ts contain -step and the end
- // contains step. When it is looking for the beginning of the next, the
- // first Ts found can be ignored and the last Ts should contain -step.
- // OPTIMIZATION: probably should split into two functions
- int nextSpan(int from, int step) const {
- const Span& fromSpan = fTs[from];
- int count = fTs.count();
- int to = from;
- while (step > 0 ? ++to < count : --to >= 0) {
- const Span& span = fTs[to];
- if (approximately_zero(span.fT - fromSpan.fT)) {
- continue;
- }
- return to;
- }
- return -1;
- }
-
- // FIXME
- // this returns at any difference in T, vs. a preset minimum. It may be
- // that all callers to nextSpan should use this instead.
- // OPTIMIZATION splitting this into separate loops for up/down steps
- // would allow using precisely_negative instead of precisely_zero
- int nextExactSpan(int from, int step) const {
- const Span& fromSpan = fTs[from];
- int count = fTs.count();
- int to = from;
- while (step > 0 ? ++to < count : --to >= 0) {
- const Span& span = fTs[to];
- if (precisely_zero(span.fT - fromSpan.fT)) {
- continue;
- }
- return to;
- }
- return -1;
- }
-
- bool operand() const {
- return fOperand;
- }
-
- int oppSign(const Angle* angle) const {
- SkASSERT(angle->segment() == this);
- return oppSign(angle->start(), angle->end());
- }
-
- int oppSign(int startIndex, int endIndex) const {
- int result = startIndex < endIndex ? -fTs[startIndex].fOppValue
- : fTs[endIndex].fOppValue;
-#if DEBUG_WIND_BUMP
- SkDebugf("%s oppSign=%d\n", __FUNCTION__, result);
-#endif
- return result;
- }
-
- int oppSum(int tIndex) const {
- return fTs[tIndex].fOppSum;
- }
-
- int oppSum(const Angle* angle) const {
- int lesser = SkMin32(angle->start(), angle->end());
- return fTs[lesser].fOppSum;
- }
-
- int oppValue(int tIndex) const {
- return fTs[tIndex].fOppValue;
- }
-
- int oppValue(const Angle* angle) const {
- int lesser = SkMin32(angle->start(), angle->end());
- return fTs[lesser].fOppValue;
- }
-
- const SkPoint* pts() const {
- return fPts;
- }
-
- void reset() {
- init(NULL, (SkPath::Verb) -1, false, false);
- fBounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, SK_ScalarMax);
- fTs.reset();
- }
-
- void setOppXor(bool isOppXor) {
- fOppXor = isOppXor;
- }
-
- void setSpanT(int index, double t) {
- Span& span = fTs[index];
- span.fT = t;
- span.fOther->fTs[span.fOtherIndex].fOtherT = t;
- }
-
- void setUpWinding(int index, int endIndex, int& maxWinding, int& sumWinding) {
- int deltaSum = spanSign(index, endIndex);
- maxWinding = sumWinding;
- sumWinding = sumWinding -= deltaSum;
- }
-
- void setUpWindings(int index, int endIndex, int& sumMiWinding, int& sumSuWinding,
- int& maxWinding, int& sumWinding, int& oppMaxWinding, int& oppSumWinding) {
- int deltaSum = spanSign(index, endIndex);
- int oppDeltaSum = oppSign(index, endIndex);
- if (operand()) {
- maxWinding = sumSuWinding;
- sumWinding = sumSuWinding -= deltaSum;
- oppMaxWinding = sumMiWinding;
- oppSumWinding = sumMiWinding -= oppDeltaSum;
- } else {
- maxWinding = sumMiWinding;
- sumWinding = sumMiWinding -= deltaSum;
- oppMaxWinding = sumSuWinding;
- oppSumWinding = sumSuWinding -= oppDeltaSum;
- }
- }
-
- // This marks all spans unsortable so that this info is available for early
- // exclusion in find top and others. This could be optimized to only mark
- // adjacent spans that unsortable. However, this makes it difficult to later
- // determine starting points for edge detection in find top and the like.
- static bool SortAngles(SkTDArray<Angle>& angles, SkTDArray<Angle*>& angleList) {
- bool sortable = true;
- int angleCount = angles.count();
- int angleIndex;
- angleList.setReserve(angleCount);
- for (angleIndex = 0; angleIndex < angleCount; ++angleIndex) {
- Angle& angle = angles[angleIndex];
- *angleList.append() = &angle;
- sortable &= !angle.unsortable();
- }
- if (sortable) {
- QSort<Angle>(angleList.begin(), angleList.end() - 1);
- for (angleIndex = 0; angleIndex < angleCount; ++angleIndex) {
- if (angles[angleIndex].unsortable()) {
- sortable = false;
- break;
- }
- }
- }
- if (!sortable) {
- for (angleIndex = 0; angleIndex < angleCount; ++angleIndex) {
- Angle& angle = angles[angleIndex];
- angle.segment()->markUnsortable(angle.start(), angle.end());
- }
- }
- return sortable;
- }
-
- // OPTIMIZATION: mark as debugging only if used solely by tests
- const Span& span(int tIndex) const {
- return fTs[tIndex];
- }
-
- int spanSign(const Angle* angle) const {
- SkASSERT(angle->segment() == this);
- return spanSign(angle->start(), angle->end());
- }
-
- int spanSign(int startIndex, int endIndex) const {
- int result = startIndex < endIndex ? -fTs[startIndex].fWindValue
- : fTs[endIndex].fWindValue;
-#if DEBUG_WIND_BUMP
- SkDebugf("%s spanSign=%d\n", __FUNCTION__, result);
-#endif
- return result;
- }
-
- void subDivide(int start, int end, SkPoint edge[4]) const {
- edge[0] = fTs[start].fPt;
- edge[fVerb] = fTs[end].fPt;
- if (fVerb == SkPath::kQuad_Verb || fVerb == SkPath::kCubic_Verb) {
- _Point sub[2] = {{ edge[0].fX, edge[0].fY}, {edge[fVerb].fX, edge[fVerb].fY }};
- if (fVerb == SkPath::kQuad_Verb) {
- MAKE_CONST_QUAD(aQuad, fPts);
- edge[1] = sub_divide(aQuad, sub[0], sub[1], fTs[start].fT, fTs[end].fT).asSkPoint();
- } else {
- MAKE_CONST_CUBIC(aCubic, fPts);
- sub_divide(aCubic, sub[0], sub[1], fTs[start].fT, fTs[end].fT, sub);
- edge[1] = sub[0].asSkPoint();
- edge[2] = sub[1].asSkPoint();
- }
- }
- }
-
- void subDivideBounds(int start, int end, Bounds& bounds) const {
- SkPoint edge[4];
- subDivide(start, end, edge);
- (bounds.*setSegmentBounds[fVerb])(edge);
- }
-
- // OPTIMIZATION: mark as debugging only if used solely by tests
- double t(int tIndex) const {
- return fTs[tIndex].fT;
- }
-
- double tAtMid(int start, int end, double mid) const {
- return fTs[start].fT * (1 - mid) + fTs[end].fT * mid;
- }
-
- bool tiny(const Angle* angle) const {
- int start = angle->start();
- int end = angle->end();
- const Span& mSpan = fTs[SkMin32(start, end)];
- return mSpan.fTiny;
- }
-
- static void TrackOutside(SkTDArray<double>& outsideTs, double end,
- double start) {
- int outCount = outsideTs.count();
- if (outCount == 0 || !approximately_negative(end - outsideTs[outCount - 2])) {
- *outsideTs.append() = end;
- *outsideTs.append() = start;
- }
- }
-
- void undoneSpan(int& start, int& end) {
- size_t tCount = fTs.count();
- size_t index;
- for (index = 0; index < tCount; ++index) {
- if (!fTs[index].fDone) {
- break;
- }
- }
- SkASSERT(index < tCount - 1);
- start = index;
- double startT = fTs[index].fT;
- while (approximately_negative(fTs[++index].fT - startT))
- SkASSERT(index < tCount);
- SkASSERT(index < tCount);
- end = index;
- }
-
- bool unsortable(int index) const {
- return fTs[index].fUnsortableStart || fTs[index].fUnsortableEnd;
- }
-
- void updatePts(const SkPoint pts[]) {
- fPts = pts;
- }
-
- int updateOppWinding(int index, int endIndex) const {
- int lesser = SkMin32(index, endIndex);
- int oppWinding = oppSum(lesser);
- int oppSpanWinding = oppSign(index, endIndex);
- if (oppSpanWinding && useInnerWinding(oppWinding - oppSpanWinding, oppWinding)
- && oppWinding != SK_MaxS32) {
- oppWinding -= oppSpanWinding;
- }
- return oppWinding;
- }
-
- int updateOppWinding(const Angle* angle) const {
- int startIndex = angle->start();
- int endIndex = angle->end();
- return updateOppWinding(endIndex, startIndex);
- }
-
- int updateOppWindingReverse(const Angle* angle) const {
- int startIndex = angle->start();
- int endIndex = angle->end();
- return updateOppWinding(startIndex, endIndex);
- }
-
- int updateWinding(int index, int endIndex) const {
- int lesser = SkMin32(index, endIndex);
- int winding = windSum(lesser);
- int spanWinding = spanSign(index, endIndex);
- if (winding && useInnerWinding(winding - spanWinding, winding) && winding != SK_MaxS32) {
- winding -= spanWinding;
- }
- return winding;
- }
-
- int updateWinding(const Angle* angle) const {
- int startIndex = angle->start();
- int endIndex = angle->end();
- return updateWinding(endIndex, startIndex);
- }
-
- int updateWindingReverse(const Angle* angle) const {
- int startIndex = angle->start();
- int endIndex = angle->end();
- return updateWinding(startIndex, endIndex);
- }
-
- SkPath::Verb verb() const {
- return fVerb;
- }
-
- int windingAtT(double tHit, int tIndex, bool crossOpp, SkScalar& dx) const {
- if (approximately_zero(tHit - t(tIndex))) { // if we hit the end of a span, disregard
- return SK_MinS32;
- }
- int winding = crossOpp ? oppSum(tIndex) : windSum(tIndex);
- SkASSERT(winding != SK_MinS32);
- int windVal = crossOpp ? oppValue(tIndex) : windValue(tIndex);
- #if DEBUG_WINDING_AT_T
- SkDebugf("%s oldWinding=%d windValue=%d", __FUNCTION__, winding, windVal);
- #endif
- // see if a + change in T results in a +/- change in X (compute x'(T))
- dx = (*SegmentDXAtT[fVerb])(fPts, tHit);
- if (fVerb > SkPath::kLine_Verb && approximately_zero(dx)) {
- dx = fPts[2].fX - fPts[1].fX - dx;
- }
- if (dx == 0) {
- #if DEBUG_WINDING_AT_T
- SkDebugf(" dx=0 winding=SK_MinS32\n");
- #endif
- return SK_MinS32;
- }
- if (winding * dx > 0) { // if same signs, result is negative
- winding += dx > 0 ? -windVal : windVal;
- }
- #if DEBUG_WINDING_AT_T
- SkDebugf(" dx=%c winding=%d\n", dx > 0 ? '+' : '-', winding);
- #endif
- return winding;
- }
-
- int windSum(int tIndex) const {
- return fTs[tIndex].fWindSum;
- }
-
- int windSum(const Angle* angle) const {
- int start = angle->start();
- int end = angle->end();
- int index = SkMin32(start, end);
- return windSum(index);
- }
-
- int windValue(int tIndex) const {
- return fTs[tIndex].fWindValue;
- }
-
- int windValue(const Angle* angle) const {
- int start = angle->start();
- int end = angle->end();
- int index = SkMin32(start, end);
- return windValue(index);
- }
-
- int windValueAt(double t) const {
- int count = fTs.count();
- for (int index = 0; index < count; ++index) {
- if (fTs[index].fT == t) {
- return fTs[index].fWindValue;
- }
- }
- SkASSERT(0);
- return 0;
- }
-
- SkScalar xAtT(int index) const {
- return xAtT(&fTs[index]);
- }
-
- SkScalar xAtT(const Span* span) const {
- return xyAtT(span).fX;
- }
-
- const SkPoint& xyAtT(int index) const {
- return xyAtT(&fTs[index]);
- }
-
- const SkPoint& xyAtT(const Span* span) const {
- if (SkScalarIsNaN(span->fPt.fX)) {
- SkASSERT(0); // make sure this path is never used
- if (span->fT == 0) {
- span->fPt = fPts[0];
- } else if (span->fT == 1) {
- span->fPt = fPts[fVerb];
- } else {
- (*SegmentXYAtT[fVerb])(fPts, span->fT, &span->fPt);
- }
- }
- return span->fPt;
- }
-
- // used only by right angle winding finding
- void xyAtT(double mid, SkPoint& pt) const {
- (*SegmentXYAtT[fVerb])(fPts, mid, &pt);
- }
-
- SkScalar yAtT(int index) const {
- return yAtT(&fTs[index]);
- }
-
- SkScalar yAtT(const Span* span) const {
- return xyAtT(span).fY;
- }
-
- void zeroCoincidentOpp(Span* oTest, int index) {
- Span* const test = &fTs[index];
- Span* end = test;
- do {
- end->fOppValue = 0;
- end = &fTs[++index];
- } while (approximately_negative(end->fT - test->fT));
- }
-
- void zeroCoincidentOther(Span* test, const double tRatio, const double oEndT, int oIndex) {
- Span* const oTest = &fTs[oIndex];
- Span* oEnd = oTest;
- const double startT = test->fT;
- const double oStartT = oTest->fT;
- double otherTMatch = (test->fT - startT) * tRatio + oStartT;
- while (!approximately_negative(oEndT - oEnd->fT)
- && approximately_negative(oEnd->fT - otherTMatch)) {
- oEnd->fOppValue = 0;
- oEnd = &fTs[++oIndex];
- }
- }
-
- void zeroSpan(Span* span) {
- SkASSERT(span->fWindValue > 0 || span->fOppValue > 0);
- span->fWindValue = 0;
- span->fOppValue = 0;
- SkASSERT(!span->fDone);
- span->fDone = true;
- ++fDoneSpans;
- }
-
-#if DEBUG_DUMP
- void dump() const {
- const char className[] = "Segment";
- const int tab = 4;
- for (int i = 0; i < fTs.count(); ++i) {
- SkPoint out;
- (*SegmentXYAtT[fVerb])(fPts, t(i), &out);
- SkDebugf("%*s [%d] %s.fTs[%d]=%1.9g (%1.9g,%1.9g) other=%d"
- " otherT=%1.9g windSum=%d\n",
- tab + sizeof(className), className, fID,
- kLVerbStr[fVerb], i, fTs[i].fT, out.fX, out.fY,
- fTs[i].fOther->fID, fTs[i].fOtherT, fTs[i].fWindSum);
- }
- SkDebugf("%*s [%d] fBounds=(l:%1.9g, t:%1.9g r:%1.9g, b:%1.9g)",
- tab + sizeof(className), className, fID,
- fBounds.fLeft, fBounds.fTop, fBounds.fRight, fBounds.fBottom);
- }
-#endif
-
-#if DEBUG_CONCIDENT
- // SkASSERT if pair has not already been added
- void debugAddTPair(double t, const Segment& other, double otherT) const {
- for (int i = 0; i < fTs.count(); ++i) {
- if (fTs[i].fT == t && fTs[i].fOther == &other && fTs[i].fOtherT == otherT) {
- return;
- }
- }
- SkASSERT(0);
- }
-#endif
-
-#if DEBUG_DUMP
- int debugID() const {
- return fID;
- }
-#endif
-
-#if DEBUG_WINDING
- void debugShowSums() const {
- SkDebugf("%s id=%d (%1.9g,%1.9g %1.9g,%1.9g)", __FUNCTION__, fID,
- fPts[0].fX, fPts[0].fY, fPts[fVerb].fX, fPts[fVerb].fY);
- for (int i = 0; i < fTs.count(); ++i) {
- const Span& span = fTs[i];
- SkDebugf(" [t=%1.3g %1.9g,%1.9g w=", span.fT, xAtT(&span), yAtT(&span));
- if (span.fWindSum == SK_MinS32) {
- SkDebugf("?");
- } else {
- SkDebugf("%d", span.fWindSum);
- }
- SkDebugf("]");
- }
- SkDebugf("\n");
- }
-#endif
-
-#if DEBUG_CONCIDENT
- void debugShowTs() const {
- SkDebugf("%s id=%d", __FUNCTION__, fID);
- int lastWind = -1;
- int lastOpp = -1;
- double lastT = -1;
- int i;
- for (i = 0; i < fTs.count(); ++i) {
- bool change = lastT != fTs[i].fT || lastWind != fTs[i].fWindValue
- || lastOpp != fTs[i].fOppValue;
- if (change && lastWind >= 0) {
- SkDebugf(" t=%1.3g %1.9g,%1.9g w=%d o=%d]",
- lastT, xyAtT(i - 1).fX, xyAtT(i - 1).fY, lastWind, lastOpp);
- }
- if (change) {
- SkDebugf(" [o=%d", fTs[i].fOther->fID);
- lastWind = fTs[i].fWindValue;
- lastOpp = fTs[i].fOppValue;
- lastT = fTs[i].fT;
- } else {
- SkDebugf(",%d", fTs[i].fOther->fID);
- }
- }
- if (i <= 0) {
- return;
- }
- SkDebugf(" t=%1.3g %1.9g,%1.9g w=%d o=%d]",
- lastT, xyAtT(i - 1).fX, xyAtT(i - 1).fY, lastWind, lastOpp);
- if (fOperand) {
- SkDebugf(" operand");
- }
- if (done()) {
- SkDebugf(" done");
- }
- SkDebugf("\n");
- }
-#endif
-
-#if DEBUG_ACTIVE_SPANS
- void debugShowActiveSpans() const {
- if (done()) {
- return;
- }
-#if DEBUG_ACTIVE_SPANS_SHORT_FORM
- int lastId = -1;
- double lastT = -1;
-#endif
- for (int i = 0; i < fTs.count(); ++i) {
- SkASSERT(&fTs[i] == &fTs[i].fOther->fTs[fTs[i].fOtherIndex].fOther->
- fTs[fTs[i].fOther->fTs[fTs[i].fOtherIndex].fOtherIndex]);
- if (fTs[i].fDone) {
- continue;
- }
-#if DEBUG_ACTIVE_SPANS_SHORT_FORM
- if (lastId == fID && lastT == fTs[i].fT) {
- continue;
- }
- lastId = fID;
- lastT = fTs[i].fT;
-#endif
- SkDebugf("%s id=%d", __FUNCTION__, fID);
- SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY);
- for (int vIndex = 1; vIndex <= fVerb; ++vIndex) {
- SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY);
- }
- const Span* span = &fTs[i];
- SkDebugf(") t=%1.9g (%1.9g,%1.9g)", fTs[i].fT,
- xAtT(span), yAtT(span));
- int iEnd = i + 1;
- while (fTs[iEnd].fT < 1 && approximately_equal(fTs[i].fT, fTs[iEnd].fT)) {
- ++iEnd;
- }
- SkDebugf(" tEnd=%1.9g", fTs[iEnd].fT);
- const Segment* other = fTs[i].fOther;
- SkDebugf(" other=%d otherT=%1.9g otherIndex=%d windSum=",
- other->fID, fTs[i].fOtherT, fTs[i].fOtherIndex);
- if (fTs[i].fWindSum == SK_MinS32) {
- SkDebugf("?");
- } else {
- SkDebugf("%d", fTs[i].fWindSum);
- }
- SkDebugf(" windValue=%d oppValue=%d\n", fTs[i].fWindValue, fTs[i].fOppValue);
- }
- }
-
- // This isn't useful yet -- but leaving it in for now in case i think of something
- // to use it for
- void validateActiveSpans() const {
- if (done()) {
- return;
- }
- int tCount = fTs.count();
- for (int index = 0; index < tCount; ++index) {
- if (fTs[index].fDone) {
- continue;
- }
- // count number of connections which are not done
- int first = index;
- double baseT = fTs[index].fT;
- while (first > 0 && approximately_equal(fTs[first - 1].fT, baseT)) {
- --first;
- }
- int last = index;
- while (last < tCount - 1 && approximately_equal(fTs[last + 1].fT, baseT)) {
- ++last;
- }
- int connections = 0;
- connections += first > 0 && !fTs[first - 1].fDone;
- for (int test = first; test <= last; ++test) {
- connections += !fTs[test].fDone;
- const Segment* other = fTs[test].fOther;
- int oIndex = fTs[test].fOtherIndex;
- connections += !other->fTs[oIndex].fDone;
- connections += oIndex > 0 && !other->fTs[oIndex - 1].fDone;
- }
- // SkASSERT(!(connections & 1));
- }
- }
-#endif
-
-#if DEBUG_MARK_DONE || DEBUG_UNSORTABLE
- void debugShowNewWinding(const char* fun, const Span& span, int winding) {
- const SkPoint& pt = xyAtT(&span);
- SkDebugf("%s id=%d", fun, fID);
- SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY);
- for (int vIndex = 1; vIndex <= fVerb; ++vIndex) {
- SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY);
- }
- SkASSERT(&span == &span.fOther->fTs[span.fOtherIndex].fOther->
- fTs[span.fOther->fTs[span.fOtherIndex].fOtherIndex]);
- SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=%d windSum=",
- span.fT, span.fOther->fTs[span.fOtherIndex].fOtherIndex, pt.fX, pt.fY,
- (&span)[1].fT, winding);
- if (span.fWindSum == SK_MinS32) {
- SkDebugf("?");
- } else {
- SkDebugf("%d", span.fWindSum);
- }
- SkDebugf(" windValue=%d\n", span.fWindValue);
- }
-
- void debugShowNewWinding(const char* fun, const Span& span, int winding, int oppWinding) {
- const SkPoint& pt = xyAtT(&span);
- SkDebugf("%s id=%d", fun, fID);
- SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY);
- for (int vIndex = 1; vIndex <= fVerb; ++vIndex) {
- SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY);
- }
- SkASSERT(&span == &span.fOther->fTs[span.fOtherIndex].fOther->
- fTs[span.fOther->fTs[span.fOtherIndex].fOtherIndex]);
- SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=%d newOppSum=%d oppSum=",
- span.fT, span.fOther->fTs[span.fOtherIndex].fOtherIndex, pt.fX, pt.fY,
- (&span)[1].fT, winding, oppWinding);
- if (span.fOppSum == SK_MinS32) {
- SkDebugf("?");
- } else {
- SkDebugf("%d", span.fOppSum);
- }
- SkDebugf(" windSum=");
- if (span.fWindSum == SK_MinS32) {
- SkDebugf("?");
- } else {
- SkDebugf("%d", span.fWindSum);
- }
- SkDebugf(" windValue=%d\n", span.fWindValue);
- }
-#endif
-
-#if DEBUG_SORT || DEBUG_SWAP_TOP
- void debugShowSort(const char* fun, const SkTDArray<Angle*>& angles, int first,
- const int contourWinding, const int oppContourWinding) const {
- if (--gDebugSortCount < 0) {
- return;
- }
- SkASSERT(angles[first]->segment() == this);
- SkASSERT(angles.count() > 1);
- int lastSum = contourWinding;
- int oppLastSum = oppContourWinding;
- const Angle* firstAngle = angles[first];
- int windSum = lastSum - spanSign(firstAngle);
- int oppoSign = oppSign(firstAngle);
- int oppWindSum = oppLastSum - oppoSign;
- #define WIND_AS_STRING(x) char x##Str[12]; if (!valid_wind(x)) strcpy(x##Str, "?"); \
- else snprintf(x##Str, sizeof(x##Str), "%d", x)
- WIND_AS_STRING(contourWinding);
- WIND_AS_STRING(oppContourWinding);
- SkDebugf("%s %s contourWinding=%s oppContourWinding=%s sign=%d\n", fun, __FUNCTION__,
- contourWindingStr, oppContourWindingStr, spanSign(angles[first]));
- int index = first;
- bool firstTime = true;
- do {
- const Angle& angle = *angles[index];
- const Segment& segment = *angle.segment();
- int start = angle.start();
- int end = angle.end();
- const Span& sSpan = segment.fTs[start];
- const Span& eSpan = segment.fTs[end];
- const Span& mSpan = segment.fTs[SkMin32(start, end)];
- bool opp = segment.fOperand ^ fOperand;
- if (!firstTime) {
- oppoSign = segment.oppSign(&angle);
- if (opp) {
- oppLastSum = oppWindSum;
- oppWindSum -= segment.spanSign(&angle);
- if (oppoSign) {
- lastSum = windSum;
- windSum -= oppoSign;
- }
- } else {
- lastSum = windSum;
- windSum -= segment.spanSign(&angle);
- if (oppoSign) {
- oppLastSum = oppWindSum;
- oppWindSum -= oppoSign;
- }
- }
- }
- SkDebugf("%s [%d] %s", __FUNCTION__, index,
- angle.unsortable() ? "*** UNSORTABLE *** " : "");
- #if COMPACT_DEBUG_SORT
- SkDebugf("id=%d %s start=%d (%1.9g,%,1.9g) end=%d (%1.9g,%,1.9g)",
- segment.fID, kLVerbStr[segment.fVerb],
- start, segment.xAtT(&sSpan), segment.yAtT(&sSpan), end,
- segment.xAtT(&eSpan), segment.yAtT(&eSpan));
- #else
- switch (segment.fVerb) {
- case SkPath::kLine_Verb:
- SkDebugf(LINE_DEBUG_STR, LINE_DEBUG_DATA(segment.fPts));
- break;
- case SkPath::kQuad_Verb:
- SkDebugf(QUAD_DEBUG_STR, QUAD_DEBUG_DATA(segment.fPts));
- break;
- case SkPath::kCubic_Verb:
- SkDebugf(CUBIC_DEBUG_STR, CUBIC_DEBUG_DATA(segment.fPts));
- break;
- default:
- SkASSERT(0);
- }
- SkDebugf(" tStart=%1.9g tEnd=%1.9g", sSpan.fT, eSpan.fT);
- #endif
- SkDebugf(" sign=%d windValue=%d windSum=", angle.sign(), mSpan.fWindValue);
- winding_printf(mSpan.fWindSum);
- int last, wind;
- if (opp) {
- last = oppLastSum;
- wind = oppWindSum;
- } else {
- last = lastSum;
- wind = windSum;
- }
- bool useInner = valid_wind(last) && valid_wind(wind) && useInnerWinding(last, wind);
- WIND_AS_STRING(last);
- WIND_AS_STRING(wind);
- WIND_AS_STRING(lastSum);
- WIND_AS_STRING(oppLastSum);
- WIND_AS_STRING(windSum);
- WIND_AS_STRING(oppWindSum);
- #undef WIND_AS_STRING
- if (!oppoSign) {
- SkDebugf(" %s->%s (max=%s)", lastStr, windStr, useInner ? windStr : lastStr);
- } else {
- SkDebugf(" %s->%s (%s->%s)", lastStr, windStr, opp ? lastSumStr : oppLastSumStr,
- opp ? windSumStr : oppWindSumStr);
- }
- SkDebugf(" done=%d tiny=%d opp=%d\n", mSpan.fDone, mSpan.fTiny, opp);
-#if false && DEBUG_ANGLE
- angle.debugShow(segment.xyAtT(&sSpan));
-#endif
- ++index;
- if (index == angles.count()) {
- index = 0;
- }
- if (firstTime) {
- firstTime = false;
- }
- } while (index != first);
- }
-
- void debugShowSort(const char* fun, const SkTDArray<Angle*>& angles, int first) {
- const Angle* firstAngle = angles[first];
- const Segment* segment = firstAngle->segment();
- int winding = segment->updateWinding(firstAngle);
- int oppWinding = segment->updateOppWinding(firstAngle);
- debugShowSort(fun, angles, first, winding, oppWinding);
- }
-
-#endif
-
-#if DEBUG_WINDING
- static char as_digit(int value) {
- return value < 0 ? '?' : value <= 9 ? '0' + value : '+';
- }
-#endif
-
-#if DEBUG_SHOW_WINDING
- int debugShowWindingValues(int slotCount, int ofInterest) const {
- if (!(1 << fID & ofInterest)) {
- return 0;
- }
- int sum = 0;
- SkTDArray<char> slots;
- slots.setCount(slotCount * 2);
- memset(slots.begin(), ' ', slotCount * 2);
- for (int i = 0; i < fTs.count(); ++i) {
- // if (!(1 << fTs[i].fOther->fID & ofInterest)) {
- // continue;
- // }
- sum += fTs[i].fWindValue;
- slots[fTs[i].fOther->fID - 1] = as_digit(fTs[i].fWindValue);
- sum += fTs[i].fOppValue;
- slots[slotCount + fTs[i].fOther->fID - 1] = as_digit(fTs[i].fOppValue);
- }
- SkDebugf("%s id=%2d %.*s | %.*s\n", __FUNCTION__, fID, slotCount, slots.begin(), slotCount,
- slots.begin() + slotCount);
- return sum;
- }
-#endif
-
-private:
- const SkPoint* fPts;
- Bounds fBounds;
- SkTDArray<Span> fTs; // two or more (always includes t=0 t=1)
- // OPTIMIZATION: could pack donespans, verb, operand, xor into 1 int-sized value
- int fDoneSpans; // quick check that segment is finished
- // OPTIMIZATION: force the following to be byte-sized
- SkPath::Verb fVerb;
- bool fOperand;
- bool fXor; // set if original contour had even-odd fill
- bool fOppXor; // set if opposite operand had even-odd fill
-#if DEBUG_DUMP
- int fID;
-#endif
-};
-
-class Contour;
-
-struct Coincidence {
- Contour* fContours[2];
- int fSegments[2];
- double fTs[2][2];
- SkPoint fPts[2];
-};
-
-class Contour {
-public:
- Contour() {
- reset();
-#if DEBUG_DUMP
- fID = ++gContourID;
-#endif
- }
-
- bool operator<(const Contour& rh) const {
- return fBounds.fTop == rh.fBounds.fTop
- ? fBounds.fLeft < rh.fBounds.fLeft
- : fBounds.fTop < rh.fBounds.fTop;
- }
-
- void addCoincident(int index, Contour* other, int otherIndex,
- const Intersections& ts, bool swap) {
- Coincidence& coincidence = *fCoincidences.append();
- coincidence.fContours[0] = this; // FIXME: no need to store
- coincidence.fContours[1] = other;
- coincidence.fSegments[0] = index;
- coincidence.fSegments[1] = otherIndex;
- coincidence.fTs[swap][0] = ts.fT[0][0];
- coincidence.fTs[swap][1] = ts.fT[0][1];
- coincidence.fTs[!swap][0] = ts.fT[1][0];
- coincidence.fTs[!swap][1] = ts.fT[1][1];
- coincidence.fPts[0] = ts.fPt[0].asSkPoint();
- coincidence.fPts[1] = ts.fPt[1].asSkPoint();
- }
-
- void addCross(const Contour* crosser) {
-#ifdef DEBUG_CROSS
- for (int index = 0; index < fCrosses.count(); ++index) {
- SkASSERT(fCrosses[index] != crosser);
- }
-#endif
- *fCrosses.append() = crosser;
- }
-
- void addCubic(const SkPoint pts[4]) {
- fSegments.push_back().addCubic(pts, fOperand, fXor);
- fContainsCurves = fContainsCubics = true;
- }
-
- int addLine(const SkPoint pts[2]) {
- fSegments.push_back().addLine(pts, fOperand, fXor);
- return fSegments.count();
- }
-
- void addOtherT(int segIndex, int tIndex, double otherT, int otherIndex) {
- fSegments[segIndex].addOtherT(tIndex, otherT, otherIndex);
- }
-
- int addQuad(const SkPoint pts[3]) {
- fSegments.push_back().addQuad(pts, fOperand, fXor);
- fContainsCurves = true;
- return fSegments.count();
- }
-
- int addT(int segIndex, Contour* other, int otherIndex, const SkPoint& pt, double& newT) {
- setContainsIntercepts();
- return fSegments[segIndex].addT(&other->fSegments[otherIndex], pt, newT);
- }
-
- int addSelfT(int segIndex, Contour* other, int otherIndex, const SkPoint& pt, double& newT) {
- setContainsIntercepts();
- return fSegments[segIndex].addSelfT(&other->fSegments[otherIndex], pt, newT);
- }
-
- int addUnsortableT(int segIndex, Contour* other, int otherIndex, bool start,
- const SkPoint& pt, double& newT) {
- return fSegments[segIndex].addUnsortableT(&other->fSegments[otherIndex], start, pt, newT);
- }
-
- const Bounds& bounds() const {
- return fBounds;
- }
-
- void complete() {
- setBounds();
- fContainsIntercepts = false;
- }
-
- bool containsCubics() const {
- return fContainsCubics;
- }
-
- bool crosses(const Contour* crosser) const {
- for (int index = 0; index < fCrosses.count(); ++index) {
- if (fCrosses[index] == crosser) {
- return true;
- }
- }
- return false;
- }
-
- bool done() const {
- return fDone;
- }
-
- const SkPoint& end() const {
- const Segment& segment = fSegments.back();
- return segment.pts()[segment.verb()];
- }
-
- void findTooCloseToCall() {
- int segmentCount = fSegments.count();
- for (int sIndex = 0; sIndex < segmentCount; ++sIndex) {
- fSegments[sIndex].findTooCloseToCall();
- }
- }
-
- void fixOtherTIndex() {
- int segmentCount = fSegments.count();
- for (int sIndex = 0; sIndex < segmentCount; ++sIndex) {
- fSegments[sIndex].fixOtherTIndex();
- }
- }
-
- Segment* nonVerticalSegment(int& start, int& end) {
- int segmentCount = fSortedSegments.count();
- SkASSERT(segmentCount > 0);
- for (int sortedIndex = fFirstSorted; sortedIndex < segmentCount; ++sortedIndex) {
- Segment* testSegment = fSortedSegments[sortedIndex];
- if (testSegment->done()) {
- continue;
- }
- start = end = 0;
- while (testSegment->nextCandidate(start, end)) {
- if (!testSegment->isVertical(start, end)) {
- return testSegment;
- }
- }
- }
- return NULL;
- }
-
- bool operand() const {
- return fOperand;
- }
-
- void reset() {
- fSegments.reset();
- fBounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, SK_ScalarMax);
- fContainsCurves = fContainsCubics = fContainsIntercepts = fDone = false;
- }
-
- void resolveCoincidence(SkTDArray<Contour*>& contourList) {
- int count = fCoincidences.count();
- for (int index = 0; index < count; ++index) {
- Coincidence& coincidence = fCoincidences[index];
- SkASSERT(coincidence.fContours[0] == this);
- int thisIndex = coincidence.fSegments[0];
- Segment& thisOne = fSegments[thisIndex];
- Contour* otherContour = coincidence.fContours[1];
- int otherIndex = coincidence.fSegments[1];
- Segment& other = otherContour->fSegments[otherIndex];
- if ((thisOne.done() || other.done()) && thisOne.complete() && other.complete()) {
- continue;
- }
- #if DEBUG_CONCIDENT
- thisOne.debugShowTs();
- other.debugShowTs();
- #endif
- double startT = coincidence.fTs[0][0];
- double endT = coincidence.fTs[0][1];
- bool cancelers = false;
- if (startT > endT) {
- SkTSwap<double>(startT, endT);
- cancelers ^= true; // FIXME: just assign true
- }
- SkASSERT(!approximately_negative(endT - startT));
- double oStartT = coincidence.fTs[1][0];
- double oEndT = coincidence.fTs[1][1];
- if (oStartT > oEndT) {
- SkTSwap<double>(oStartT, oEndT);
- cancelers ^= true;
- }
- SkASSERT(!approximately_negative(oEndT - oStartT));
- bool opp = fOperand ^ otherContour->fOperand;
- if (cancelers && !opp) {
- // make sure startT and endT have t entries
- if (startT > 0 || oEndT < 1
- || thisOne.isMissing(startT) || other.isMissing(oEndT)) {
- thisOne.addTPair(startT, other, oEndT, true, coincidence.fPts[0]);
- }
- if (oStartT > 0 || endT < 1
- || thisOne.isMissing(endT) || other.isMissing(oStartT)) {
- other.addTPair(oStartT, thisOne, endT, true, coincidence.fPts[1]);
- }
- if (!thisOne.done() && !other.done()) {
- thisOne.addTCancel(startT, endT, other, oStartT, oEndT);
- }
- } else {
- if (startT > 0 || oStartT > 0
- || thisOne.isMissing(startT) || other.isMissing(oStartT)) {
- thisOne.addTPair(startT, other, oStartT, true, coincidence.fPts[0]);
- }
- if (endT < 1 || oEndT < 1
- || thisOne.isMissing(endT) || other.isMissing(oEndT)) {
- other.addTPair(oEndT, thisOne, endT, true, coincidence.fPts[1]);
- }
- if (!thisOne.done() && !other.done()) {
- thisOne.addTCoincident(startT, endT, other, oStartT, oEndT);
- }
- }
- #if DEBUG_CONCIDENT
- thisOne.debugShowTs();
- other.debugShowTs();
- #endif
- #if DEBUG_SHOW_WINDING
- debugShowWindingValues(contourList);
- #endif
- }
- }
-
- // first pass, add missing T values
- // second pass, determine winding values of overlaps
- void addCoincidentPoints() {
- int count = fCoincidences.count();
- for (int index = 0; index < count; ++index) {
- Coincidence& coincidence = fCoincidences[index];
- SkASSERT(coincidence.fContours[0] == this);
- int thisIndex = coincidence.fSegments[0];
- Segment& thisOne = fSegments[thisIndex];
- Contour* otherContour = coincidence.fContours[1];
- int otherIndex = coincidence.fSegments[1];
- Segment& other = otherContour->fSegments[otherIndex];
- if ((thisOne.done() || other.done()) && thisOne.complete() && other.complete()) {
- // OPTIMIZATION: remove from array
- continue;
- }
- #if DEBUG_CONCIDENT
- thisOne.debugShowTs();
- other.debugShowTs();
- #endif
- double startT = coincidence.fTs[0][0];
- double endT = coincidence.fTs[0][1];
- bool cancelers;
- if ((cancelers = startT > endT)) {
- SkTSwap(startT, endT);
- SkTSwap(coincidence.fPts[0], coincidence.fPts[1]);
- }
- SkASSERT(!approximately_negative(endT - startT));
- double oStartT = coincidence.fTs[1][0];
- double oEndT = coincidence.fTs[1][1];
- if (oStartT > oEndT) {
- SkTSwap<double>(oStartT, oEndT);
- cancelers ^= true;
- }
- SkASSERT(!approximately_negative(oEndT - oStartT));
- bool opp = fOperand ^ otherContour->fOperand;
- if (cancelers && !opp) {
- // make sure startT and endT have t entries
- if (startT > 0 || oEndT < 1
- || thisOne.isMissing(startT) || other.isMissing(oEndT)) {
- thisOne.addTPair(startT, other, oEndT, true, coincidence.fPts[0]);
- }
- if (oStartT > 0 || endT < 1
- || thisOne.isMissing(endT) || other.isMissing(oStartT)) {
- other.addTPair(oStartT, thisOne, endT, true, coincidence.fPts[1]);
- }
- } else {
- if (startT > 0 || oStartT > 0
- || thisOne.isMissing(startT) || other.isMissing(oStartT)) {
- thisOne.addTPair(startT, other, oStartT, true, coincidence.fPts[0]);
- }
- if (endT < 1 || oEndT < 1
- || thisOne.isMissing(endT) || other.isMissing(oEndT)) {
- other.addTPair(oEndT, thisOne, endT, true, coincidence.fPts[1]);
- }
- }
- #if DEBUG_CONCIDENT
- thisOne.debugShowTs();
- other.debugShowTs();
- #endif
- }
- }
-
- void calcCoincidentWinding() {
- int count = fCoincidences.count();
- for (int index = 0; index < count; ++index) {
- Coincidence& coincidence = fCoincidences[index];
- SkASSERT(coincidence.fContours[0] == this);
- int thisIndex = coincidence.fSegments[0];
- Segment& thisOne = fSegments[thisIndex];
- if (thisOne.done()) {
- continue;
- }
- Contour* otherContour = coincidence.fContours[1];
- int otherIndex = coincidence.fSegments[1];
- Segment& other = otherContour->fSegments[otherIndex];
- if (other.done()) {
- continue;
- }
- double startT = coincidence.fTs[0][0];
- double endT = coincidence.fTs[0][1];
- bool cancelers;
- if ((cancelers = startT > endT)) {
- SkTSwap<double>(startT, endT);
- }
- SkASSERT(!approximately_negative(endT - startT));
- double oStartT = coincidence.fTs[1][0];
- double oEndT = coincidence.fTs[1][1];
- if (oStartT > oEndT) {
- SkTSwap<double>(oStartT, oEndT);
- cancelers ^= true;
- }
- SkASSERT(!approximately_negative(oEndT - oStartT));
- bool opp = fOperand ^ otherContour->fOperand;
- if (cancelers && !opp) {
- // make sure startT and endT have t entries
- if (!thisOne.done() && !other.done()) {
- thisOne.addTCancel(startT, endT, other, oStartT, oEndT);
- }
- } else {
- if (!thisOne.done() && !other.done()) {
- thisOne.addTCoincident(startT, endT, other, oStartT, oEndT);
- }
- }
- #if DEBUG_CONCIDENT
- thisOne.debugShowTs();
- other.debugShowTs();
- #endif
- }
- }
-
- SkTArray<Segment>& segments() {
- return fSegments;
- }
-
- void setContainsIntercepts() {
- fContainsIntercepts = true;
- }
-
- void setOperand(bool isOp) {
- fOperand = isOp;
- }
-
- void setOppXor(bool isOppXor) {
- fOppXor = isOppXor;
- int segmentCount = fSegments.count();
- for (int test = 0; test < segmentCount; ++test) {
- fSegments[test].setOppXor(isOppXor);
- }
- }
-
- void setXor(bool isXor) {
- fXor = isXor;
- }
-
- void sortSegments() {
- int segmentCount = fSegments.count();
- fSortedSegments.setReserve(segmentCount);
- for (int test = 0; test < segmentCount; ++test) {
- *fSortedSegments.append() = &fSegments[test];
- }
- QSort<Segment>(fSortedSegments.begin(), fSortedSegments.end() - 1);
- fFirstSorted = 0;
- }
-
- const SkPoint& start() const {
- return fSegments.front().pts()[0];
- }
-
- void toPath(PathWrapper& path) const {
- int segmentCount = fSegments.count();
- const SkPoint& pt = fSegments.front().pts()[0];
- path.deferredMove(pt);
- for (int test = 0; test < segmentCount; ++test) {
- fSegments[test].addCurveTo(0, 1, path, true);
- }
- path.close();
- }
-
- void toPartialBackward(PathWrapper& path) const {
- int segmentCount = fSegments.count();
- for (int test = segmentCount - 1; test >= 0; --test) {
- fSegments[test].addCurveTo(1, 0, path, true);
- }
- }
-
- void toPartialForward(PathWrapper& path) const {
- int segmentCount = fSegments.count();
- for (int test = 0; test < segmentCount; ++test) {
- fSegments[test].addCurveTo(0, 1, path, true);
- }
- }
-
- void topSortableSegment(const SkPoint& topLeft, SkPoint& bestXY, Segment*& topStart) {
- int segmentCount = fSortedSegments.count();
- SkASSERT(segmentCount > 0);
- int sortedIndex = fFirstSorted;
- fDone = true; // may be cleared below
- for ( ; sortedIndex < segmentCount; ++sortedIndex) {
- Segment* testSegment = fSortedSegments[sortedIndex];
- if (testSegment->done()) {
- if (sortedIndex == fFirstSorted) {
- ++fFirstSorted;
- }
- continue;
- }
- fDone = false;
- SkPoint testXY = testSegment->activeLeftTop(true, NULL);
- if (topStart) {
- if (testXY.fY < topLeft.fY) {
- continue;
- }
- if (testXY.fY == topLeft.fY && testXY.fX < topLeft.fX) {
- continue;
- }
- if (bestXY.fY < testXY.fY) {
- continue;
- }
- if (bestXY.fY == testXY.fY && bestXY.fX < testXY.fX) {
- continue;
- }
- }
- topStart = testSegment;
- bestXY = testXY;
- }
- }
-
- Segment* undoneSegment(int& start, int& end) {
- int segmentCount = fSegments.count();
- for (int test = 0; test < segmentCount; ++test) {
- Segment* testSegment = &fSegments[test];
- if (testSegment->done()) {
- continue;
- }
- testSegment->undoneSpan(start, end);
- return testSegment;
- }
- return NULL;
- }
-
- int updateSegment(int index, const SkPoint* pts) {
- Segment& segment = fSegments[index];
- segment.updatePts(pts);
- return segment.verb() + 1;
- }
-
-#if DEBUG_TEST
- SkTArray<Segment>& debugSegments() {
- return fSegments;
- }
-#endif
-
-#if DEBUG_DUMP
- void dump() {
- int i;
- const char className[] = "Contour";
- const int tab = 4;
- SkDebugf("%s %p (contour=%d)\n", className, this, fID);
- for (i = 0; i < fSegments.count(); ++i) {
- SkDebugf("%*s.fSegments[%d]:\n", tab + sizeof(className),
- className, i);
- fSegments[i].dump();
- }
- SkDebugf("%*s.fBounds=(l:%1.9g, t:%1.9g r:%1.9g, b:%1.9g)\n",
- tab + sizeof(className), className,
- fBounds.fLeft, fBounds.fTop,
- fBounds.fRight, fBounds.fBottom);
- SkDebugf("%*s.fContainsIntercepts=%d\n", tab + sizeof(className),
- className, fContainsIntercepts);
- SkDebugf("%*s.fContainsCurves=%d\n", tab + sizeof(className),
- className, fContainsCurves);
- }
-#endif
-
-#if DEBUG_ACTIVE_SPANS
- void debugShowActiveSpans() {
- for (int index = 0; index < fSegments.count(); ++index) {
- fSegments[index].debugShowActiveSpans();
- }
- }
-
- void validateActiveSpans() {
- for (int index = 0; index < fSegments.count(); ++index) {
- fSegments[index].validateActiveSpans();
- }
- }
-#endif
-
-#if DEBUG_SHOW_WINDING
- int debugShowWindingValues(int totalSegments, int ofInterest) {
- int count = fSegments.count();
- int sum = 0;
- for (int index = 0; index < count; ++index) {
- sum += fSegments[index].debugShowWindingValues(totalSegments, ofInterest);
- }
- // SkDebugf("%s sum=%d\n", __FUNCTION__, sum);
- return sum;
- }
-
- static void debugShowWindingValues(SkTDArray<Contour*>& contourList) {
- // int ofInterest = 1 << 1 | 1 << 5 | 1 << 9 | 1 << 13;
- // int ofInterest = 1 << 4 | 1 << 8 | 1 << 12 | 1 << 16;
- int ofInterest = 1 << 5 | 1 << 8;
- int total = 0;
- int index;
- for (index = 0; index < contourList.count(); ++index) {
- total += contourList[index]->segments().count();
- }
- int sum = 0;
- for (index = 0; index < contourList.count(); ++index) {
- sum += contourList[index]->debugShowWindingValues(total, ofInterest);
- }
- // SkDebugf("%s total=%d\n", __FUNCTION__, sum);
- }
-#endif
-
-protected:
- void setBounds() {
- int count = fSegments.count();
- if (count == 0) {
- SkDebugf("%s empty contour\n", __FUNCTION__);
- SkASSERT(0);
- // FIXME: delete empty contour?
- return;
- }
- fBounds = fSegments.front().bounds();
- for (int index = 1; index < count; ++index) {
- fBounds.add(fSegments[index].bounds());
- }
- }
-
-private:
- SkTArray<Segment> fSegments;
- SkTDArray<Segment*> fSortedSegments;
- int fFirstSorted;
- SkTDArray<Coincidence> fCoincidences;
- SkTDArray<const Contour*> fCrosses;
- Bounds fBounds;
- bool fContainsIntercepts; // FIXME: is this used by anybody?
- bool fContainsCubics;
- bool fContainsCurves;
- bool fDone;
- bool fOperand; // true for the second argument to a binary operator
- bool fXor;
- bool fOppXor;
-#if DEBUG_DUMP
- int fID;
-#endif
-};
-
-class EdgeBuilder {
-public:
-
-EdgeBuilder(const PathWrapper& path, SkTArray<Contour>& contours)
- : fPath(path.nativePath())
- , fContours(contours)
-{
- init();
-}
-
-EdgeBuilder(const SkPath& path, SkTArray<Contour>& contours)
- : fPath(&path)
- , fContours(contours)
-{
- init();
-}
-
-void init() {
- fCurrentContour = NULL;
- fOperand = false;
- fXorMask[0] = fXorMask[1] = (fPath->getFillType() & 1) ? kEvenOdd_Mask : kWinding_Mask;
-#if DEBUG_DUMP
- gContourID = 0;
- gSegmentID = 0;
-#endif
- fSecondHalf = preFetch();
-}
-
-void addOperand(const SkPath& path) {
- SkASSERT(fPathVerbs.count() > 0 && fPathVerbs.end()[-1] == SkPath::kDone_Verb);
- fPathVerbs.pop();
- fPath = &path;
- fXorMask[1] = (fPath->getFillType() & 1) ? kEvenOdd_Mask : kWinding_Mask;
- preFetch();
-}
-
-void finish() {
- walk();
- complete();
- if (fCurrentContour && !fCurrentContour->segments().count()) {
- fContours.pop_back();
- }
- // correct pointers in contours since fReducePts may have moved as it grew
- int cIndex = 0;
- int extraCount = fExtra.count();
- SkASSERT(extraCount == 0 || fExtra[0] == -1);
- int eIndex = 0;
- int rIndex = 0;
- while (++eIndex < extraCount) {
- int offset = fExtra[eIndex];
- if (offset < 0) {
- ++cIndex;
- continue;
- }
- fCurrentContour = &fContours[cIndex];
- rIndex += fCurrentContour->updateSegment(offset - 1,
- &fReducePts[rIndex]);
- }
- fExtra.reset(); // we're done with this
-}
-
-ShapeOpMask xorMask() const {
- return fXorMask[fOperand];
-}
-
-protected:
-
-void complete() {
- if (fCurrentContour && fCurrentContour->segments().count()) {
- fCurrentContour->complete();
- fCurrentContour = NULL;
- }
-}
-
-// FIXME:remove once we can access path pts directly
-int preFetch() {
- SkPath::RawIter iter(*fPath); // FIXME: access path directly when allowed
- SkPoint pts[4];
- SkPath::Verb verb;
- do {
- verb = iter.next(pts);
- *fPathVerbs.append() = verb;
- if (verb == SkPath::kMove_Verb) {
- *fPathPts.append() = pts[0];
- } else if (verb >= SkPath::kLine_Verb && verb <= SkPath::kCubic_Verb) {
- fPathPts.append(verb, &pts[1]);
- }
- } while (verb != SkPath::kDone_Verb);
- return fPathVerbs.count() - 1;
-}
-
-void walk() {
- SkPath::Verb reducedVerb;
- uint8_t* verbPtr = fPathVerbs.begin();
- uint8_t* endOfFirstHalf = &verbPtr[fSecondHalf];
- const SkPoint* pointsPtr = fPathPts.begin();
- const SkPoint* finalCurveStart = NULL;
- const SkPoint* finalCurveEnd = NULL;
- SkPath::Verb verb;
- while ((verb = (SkPath::Verb) *verbPtr++) != SkPath::kDone_Verb) {
- switch (verb) {
- case SkPath::kMove_Verb:
- complete();
- if (!fCurrentContour) {
- fCurrentContour = fContours.push_back_n(1);
- fCurrentContour->setOperand(fOperand);
- fCurrentContour->setXor(fXorMask[fOperand] == kEvenOdd_Mask);
- *fExtra.append() = -1; // start new contour
- }
- finalCurveEnd = pointsPtr++;
- goto nextVerb;
- case SkPath::kLine_Verb:
- // skip degenerate points
- if (pointsPtr[-1].fX != pointsPtr[0].fX
- || pointsPtr[-1].fY != pointsPtr[0].fY) {
- fCurrentContour->addLine(&pointsPtr[-1]);
- }
- break;
- case SkPath::kQuad_Verb:
-
- reducedVerb = QuadReduceOrder(&pointsPtr[-1], fReducePts);
- if (reducedVerb == 0) {
- break; // skip degenerate points
- }
- if (reducedVerb == 1) {
- *fExtra.append() =
- fCurrentContour->addLine(fReducePts.end() - 2);
- break;
- }
- fCurrentContour->addQuad(&pointsPtr[-1]);
- break;
- case SkPath::kCubic_Verb:
- reducedVerb = CubicReduceOrder(&pointsPtr[-1], fReducePts);
- if (reducedVerb == 0) {
- break; // skip degenerate points
- }
- if (reducedVerb == 1) {
- *fExtra.append() =
- fCurrentContour->addLine(fReducePts.end() - 2);
- break;
- }
- if (reducedVerb == 2) {
- *fExtra.append() =
- fCurrentContour->addQuad(fReducePts.end() - 3);
- break;
- }
- fCurrentContour->addCubic(&pointsPtr[-1]);
- break;
- case SkPath::kClose_Verb:
- SkASSERT(fCurrentContour);
- if (finalCurveStart && finalCurveEnd
- && *finalCurveStart != *finalCurveEnd) {
- *fReducePts.append() = *finalCurveStart;
- *fReducePts.append() = *finalCurveEnd;
- *fExtra.append() =
- fCurrentContour->addLine(fReducePts.end() - 2);
- }
- complete();
- goto nextVerb;
- default:
- SkDEBUGFAIL("bad verb");
- return;
- }
- finalCurveStart = &pointsPtr[verb - 1];
- pointsPtr += verb;
- SkASSERT(fCurrentContour);
- nextVerb:
- if (verbPtr == endOfFirstHalf) {
- fOperand = true;
- }
- }
-}
-
-private:
- const SkPath* fPath;
- SkTDArray<SkPoint> fPathPts; // FIXME: point directly to path pts instead
- SkTDArray<uint8_t> fPathVerbs; // FIXME: remove
- Contour* fCurrentContour;
- SkTArray<Contour>& fContours;
- SkTDArray<SkPoint> fReducePts; // segments created on the fly
- SkTDArray<int> fExtra; // -1 marks new contour, > 0 offsets into contour
- ShapeOpMask fXorMask[2];
- int fSecondHalf;
- bool fOperand;
-};
-
-class Work {
-public:
- enum SegmentType {
- kHorizontalLine_Segment = -1,
- kVerticalLine_Segment = 0,
- kLine_Segment = SkPath::kLine_Verb,
- kQuad_Segment = SkPath::kQuad_Verb,
- kCubic_Segment = SkPath::kCubic_Verb,
- };
-
- void addCoincident(Work& other, const Intersections& ts, bool swap) {
- fContour->addCoincident(fIndex, other.fContour, other.fIndex, ts, swap);
- }
-
- // FIXME: does it make sense to write otherIndex now if we're going to
- // fix it up later?
- void addOtherT(int index, double otherT, int otherIndex) {
- fContour->addOtherT(fIndex, index, otherT, otherIndex);
- }
-
- // Avoid collapsing t values that are close to the same since
- // we walk ts to describe consecutive intersections. Since a pair of ts can
- // be nearly equal, any problems caused by this should be taken care
- // of later.
- // On the edge or out of range values are negative; add 2 to get end
- int addT(const Work& other, const SkPoint& pt, double& newT) {
- return fContour->addT(fIndex, other.fContour, other.fIndex, pt, newT);
- }
-
- int addSelfT(const Work& other, const SkPoint& pt, double& newT) {
- return fContour->addSelfT(fIndex, other.fContour, other.fIndex, pt, newT);
- }
-
- int addUnsortableT(const Work& other, bool start, const SkPoint& pt, double& newT) {
- return fContour->addUnsortableT(fIndex, other.fContour, other.fIndex, start, pt, newT);
- }
-
- bool advance() {
- return ++fIndex < fLast;
- }
-
- SkScalar bottom() const {
- return bounds().fBottom;
- }
-
- const Bounds& bounds() const {
- return fContour->segments()[fIndex].bounds();
- }
-
-#if !APPROXIMATE_CUBICS
- const SkPoint* cubic() const {
- return fCubic;
- }
-#endif
-
- void init(Contour* contour) {
- fContour = contour;
- fIndex = 0;
- fLast = contour->segments().count();
- }
-
- bool isAdjacent(const Work& next) {
- return fContour == next.fContour && fIndex + 1 == next.fIndex;
- }
-
- bool isFirstLast(const Work& next) {
- return fContour == next.fContour && fIndex == 0
- && next.fIndex == fLast - 1;
- }
-
- SkScalar left() const {
- return bounds().fLeft;
- }
-
-#if !APPROXIMATE_CUBICS
- void promoteToCubic() {
- fCubic[0] = pts()[0];
- fCubic[2] = pts()[1];
- fCubic[3] = pts()[2];
- fCubic[1].fX = (fCubic[0].fX + fCubic[2].fX * 2) / 3;
- fCubic[1].fY = (fCubic[0].fY + fCubic[2].fY * 2) / 3;
- fCubic[2].fX = (fCubic[3].fX + fCubic[2].fX * 2) / 3;
- fCubic[2].fY = (fCubic[3].fY + fCubic[2].fY * 2) / 3;
- }
-#endif
-
- const SkPoint* pts() const {
- return fContour->segments()[fIndex].pts();
- }
-
- SkScalar right() const {
- return bounds().fRight;
- }
-
- ptrdiff_t segmentIndex() const {
- return fIndex;
- }
-
- SegmentType segmentType() const {
- const Segment& segment = fContour->segments()[fIndex];
- SegmentType type = (SegmentType) segment.verb();
- if (type != kLine_Segment) {
- return type;
- }
- if (segment.isHorizontal()) {
- return kHorizontalLine_Segment;
- }
- if (segment.isVertical()) {
- return kVerticalLine_Segment;
- }
- return kLine_Segment;
- }
-
- bool startAfter(const Work& after) {
- fIndex = after.fIndex;
- return advance();
- }
-
- SkScalar top() const {
- return bounds().fTop;
- }
-
- SkPath::Verb verb() const {
- return fContour->segments()[fIndex].verb();
- }
-
- SkScalar x() const {
- return bounds().fLeft;
- }
-
- bool xFlipped() const {
- return x() != pts()[0].fX;
- }
-
- SkScalar y() const {
- return bounds().fTop;
- }
-
- bool yFlipped() const {
- return y() != pts()[0].fY;
- }
-
-protected:
- Contour* fContour;
-#if !APPROXIMATE_CUBICS
- SkPoint fCubic[4];
-#endif
- int fIndex;
- int fLast;
-};
-
-#if DEBUG_ADD_INTERSECTING_TS
-
-static void debugShowLineIntersection(int pts, const Work& wt, const Work& wn,
- const Intersections& i) {
- SkASSERT(i.used() == pts);
- if (!pts) {
- SkDebugf("%s no intersect " LINE_DEBUG_STR " " LINE_DEBUG_STR "\n",
- __FUNCTION__, LINE_DEBUG_DATA(wt.pts()), LINE_DEBUG_DATA(wn.pts()));
- return;
- }
- SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " LINE_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__,
- i.fT[0][0], LINE_DEBUG_DATA(wt.pts()), PT_DEBUG_DATA(i, 0));
- if (pts == 2) {
- SkDebugf(" " T_DEBUG_STR(wtTs, 1) " " PT_DEBUG_STR, i.fT[0][1], PT_DEBUG_DATA(i, 1));
- }
- SkDebugf(" wnTs[0]=%g " LINE_DEBUG_STR, i.fT[1][0], LINE_DEBUG_DATA(wn.pts()));
- if (pts == 2) {
- SkDebugf(" " T_DEBUG_STR(wnTs, 1), i.fT[1][1]);
- }
- SkDebugf("\n");
-}
-
-static void debugShowQuadLineIntersection(int pts, const Work& wt,
- const Work& wn, const Intersections& i) {
- SkASSERT(i.used() == pts);
- if (!pts) {
- SkDebugf("%s no intersect " QUAD_DEBUG_STR " " LINE_DEBUG_STR "\n",
- __FUNCTION__, QUAD_DEBUG_DATA(wt.pts()), LINE_DEBUG_DATA(wn.pts()));
- return;
- }
- SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " QUAD_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__,
- i.fT[0][0], QUAD_DEBUG_DATA(wt.pts()), PT_DEBUG_DATA(i, 0));
- for (int n = 1; n < pts; ++n) {
- SkDebugf(" " TX_DEBUG_STR(wtTs) " " PT_DEBUG_STR, n, i.fT[0][n], PT_DEBUG_DATA(i, n));
- }
- SkDebugf(" wnTs[0]=%g " LINE_DEBUG_STR, i.fT[1][0], LINE_DEBUG_DATA(wn.pts()));
- for (int n = 1; n < pts; ++n) {
- SkDebugf(" " TX_DEBUG_STR(wnTs), n, i.fT[1][n]);
- }
- SkDebugf("\n");
-}
-
-static void debugShowQuadIntersection(int pts, const Work& wt,
- const Work& wn, const Intersections& i) {
- SkASSERT(i.used() == pts);
- if (!pts) {
- SkDebugf("%s no intersect " QUAD_DEBUG_STR " " QUAD_DEBUG_STR "\n",
- __FUNCTION__, QUAD_DEBUG_DATA(wt.pts()), QUAD_DEBUG_DATA(wn.pts()));
- return;
- }
- SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " QUAD_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__,
- i.fT[0][0], QUAD_DEBUG_DATA(wt.pts()), PT_DEBUG_DATA(i, 0));
- for (int n = 1; n < pts; ++n) {
- SkDebugf(" " TX_DEBUG_STR(wtTs) " " PT_DEBUG_STR, n, i.fT[0][n], PT_DEBUG_DATA(i, n));
- }
- SkDebugf(" wnTs[0]=%g " QUAD_DEBUG_STR, i.fT[1][0], QUAD_DEBUG_DATA(wn.pts()));
- for (int n = 1; n < pts; ++n) {
- SkDebugf(" " TX_DEBUG_STR(wnTs), n, i.fT[1][n]);
- }
- SkDebugf("\n");
-}
-
-static void debugShowCubicLineIntersection(int pts, const Work& wt,
- const Work& wn, const Intersections& i) {
- SkASSERT(i.used() == pts);
- if (!pts) {
- SkDebugf("%s no intersect " CUBIC_DEBUG_STR " " LINE_DEBUG_STR "\n",
- __FUNCTION__, CUBIC_DEBUG_DATA(wt.pts()), LINE_DEBUG_DATA(wn.pts()));
- return;
- }
- SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " CUBIC_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__,
- i.fT[0][0], CUBIC_DEBUG_DATA(wt.pts()), PT_DEBUG_DATA(i, 0));
- for (int n = 1; n < pts; ++n) {
- SkDebugf(" " TX_DEBUG_STR(wtTs) " " PT_DEBUG_STR, n, i.fT[0][n], PT_DEBUG_DATA(i, n));
- }
- SkDebugf(" wnTs[0]=%g " LINE_DEBUG_STR, i.fT[1][0], LINE_DEBUG_DATA(wn.pts()));
- for (int n = 1; n < pts; ++n) {
- SkDebugf(" " TX_DEBUG_STR(wnTs), n, i.fT[1][n]);
- }
- SkDebugf("\n");
-}
-
-static void debugShowCubicQuadIntersection(int pts, const Work& wt,
- const Work& wn, const Intersections& i) {
- SkASSERT(i.used() == pts);
- if (!pts) {
- SkDebugf("%s no intersect " CUBIC_DEBUG_STR " " QUAD_DEBUG_STR "\n",
- __FUNCTION__, CUBIC_DEBUG_DATA(wt.pts()), QUAD_DEBUG_DATA(wn.pts()));
- return;
- }
- SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " CUBIC_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__,
- i.fT[0][0], CUBIC_DEBUG_DATA(wt.pts()), PT_DEBUG_DATA(i, 0));
- for (int n = 1; n < pts; ++n) {
- SkDebugf(" " TX_DEBUG_STR(wtTs) " " PT_DEBUG_STR, n, i.fT[0][n], PT_DEBUG_DATA(i, n));
- }
- SkDebugf(" wnTs[0]=%g " QUAD_DEBUG_STR, i.fT[1][0], QUAD_DEBUG_DATA(wn.pts()));
- for (int n = 1; n < pts; ++n) {
- SkDebugf(" " TX_DEBUG_STR(wnTs), n, i.fT[1][n]);
- }
- SkDebugf("\n");
-}
-
-static void debugShowCubicIntersection(int pts, const Work& wt,
- const Work& wn, const Intersections& i) {
- SkASSERT(i.used() == pts);
- if (!pts) {
- SkDebugf("%s no intersect " CUBIC_DEBUG_STR " " CUBIC_DEBUG_STR "\n",
- __FUNCTION__, CUBIC_DEBUG_DATA(wt.pts()), CUBIC_DEBUG_DATA(wn.pts()));
- return;
- }
- SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " CUBIC_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__,
- i.fT[0][0], CUBIC_DEBUG_DATA(wt.pts()), PT_DEBUG_DATA(i, 0));
- for (int n = 1; n < pts; ++n) {
- SkDebugf(" " TX_DEBUG_STR(wtTs) " " PT_DEBUG_STR, n, i.fT[0][n], PT_DEBUG_DATA(i, n));
- }
- SkDebugf(" wnTs[0]=%g " CUBIC_DEBUG_STR, i.fT[1][0], CUBIC_DEBUG_DATA(wn.pts()));
- for (int n = 1; n < pts; ++n) {
- SkDebugf(" " TX_DEBUG_STR(wnTs), n, i.fT[1][n]);
- }
- SkDebugf("\n");
-}
-
-static void debugShowCubicIntersection(int pts, const Work& wt, const Intersections& i) {
- SkASSERT(i.used() == pts);
- if (!pts) {
- SkDebugf("%s no self intersect " CUBIC_DEBUG_STR "\n", __FUNCTION__,
- CUBIC_DEBUG_DATA(wt.pts()));
- return;
- }
- SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " CUBIC_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__,
- i.fT[0][0], CUBIC_DEBUG_DATA(wt.pts()), PT_DEBUG_DATA(i, 0));
- SkDebugf(" " T_DEBUG_STR(wtTs, 1), i.fT[1][0]);
- SkDebugf("\n");
-}
-
-#else
-static void debugShowLineIntersection(int , const Work& , const Work& , const Intersections& ) {
-}
-
-static void debugShowQuadLineIntersection(int , const Work& , const Work& , const Intersections& ) {
-}
-
-static void debugShowQuadIntersection(int , const Work& , const Work& , const Intersections& ) {
-}
-
-static void debugShowCubicLineIntersection(int , const Work& , const Work& ,
- const Intersections& ) {
-}
-
-static void debugShowCubicQuadIntersection(int , const Work& , const Work& ,
- const Intersections& ) {
-}
-
-static void debugShowCubicIntersection(int , const Work& , const Work& , const Intersections& ) {
-}
-
-static void debugShowCubicIntersection(int , const Work& , const Intersections& ) {
-}
-#endif
-
-static bool addIntersectTs(Contour* test, Contour* next) {
-
- if (test != next) {
- if (test->bounds().fBottom < next->bounds().fTop) {
- return false;
- }
- if (!Bounds::Intersects(test->bounds(), next->bounds())) {
- return true;
- }
- }
- Work wt;
- wt.init(test);
- bool foundCommonContour = test == next;
- do {
- Work wn;
- wn.init(next);
- if (test == next && !wn.startAfter(wt)) {
- continue;
- }
- do {
- if (!Bounds::Intersects(wt.bounds(), wn.bounds())) {
- continue;
- }
- int pts;
- Intersections ts;
- bool swap = false;
- switch (wt.segmentType()) {
- case Work::kHorizontalLine_Segment:
- swap = true;
- switch (wn.segmentType()) {
- case Work::kHorizontalLine_Segment:
- case Work::kVerticalLine_Segment:
- case Work::kLine_Segment: {
- pts = HLineIntersect(wn.pts(), wt.left(),
- wt.right(), wt.y(), wt.xFlipped(), ts);
- debugShowLineIntersection(pts, wt, wn, ts);
- break;
- }
- case Work::kQuad_Segment: {
- pts = HQuadIntersect(wn.pts(), wt.left(),
- wt.right(), wt.y(), wt.xFlipped(), ts);
- break;
- }
- case Work::kCubic_Segment: {
- pts = HCubicIntersect(wn.pts(), wt.left(),
- wt.right(), wt.y(), wt.xFlipped(), ts);
- debugShowCubicLineIntersection(pts, wn, wt, ts);
- break;
- }
- default:
- SkASSERT(0);
- }
- break;
- case Work::kVerticalLine_Segment:
- swap = true;
- switch (wn.segmentType()) {
- case Work::kHorizontalLine_Segment:
- case Work::kVerticalLine_Segment:
- case Work::kLine_Segment: {
- pts = VLineIntersect(wn.pts(), wt.top(),
- wt.bottom(), wt.x(), wt.yFlipped(), ts);
- debugShowLineIntersection(pts, wt, wn, ts);
- break;
- }
- case Work::kQuad_Segment: {
- pts = VQuadIntersect(wn.pts(), wt.top(),
- wt.bottom(), wt.x(), wt.yFlipped(), ts);
- break;
- }
- case Work::kCubic_Segment: {
- pts = VCubicIntersect(wn.pts(), wt.top(),
- wt.bottom(), wt.x(), wt.yFlipped(), ts);
- debugShowCubicLineIntersection(pts, wn, wt, ts);
- break;
- }
- default:
- SkASSERT(0);
- }
- break;
- case Work::kLine_Segment:
- switch (wn.segmentType()) {
- case Work::kHorizontalLine_Segment:
- pts = HLineIntersect(wt.pts(), wn.left(),
- wn.right(), wn.y(), wn.xFlipped(), ts);
- debugShowLineIntersection(pts, wt, wn, ts);
- break;
- case Work::kVerticalLine_Segment:
- pts = VLineIntersect(wt.pts(), wn.top(),
- wn.bottom(), wn.x(), wn.yFlipped(), ts);
- debugShowLineIntersection(pts, wt, wn, ts);
- break;
- case Work::kLine_Segment: {
- pts = LineIntersect(wt.pts(), wn.pts(), ts);
- debugShowLineIntersection(pts, wt, wn, ts);
- break;
- }
- case Work::kQuad_Segment: {
- swap = true;
- pts = QuadLineIntersect(wn.pts(), wt.pts(), ts);
- debugShowQuadLineIntersection(pts, wn, wt, ts);
- break;
- }
- case Work::kCubic_Segment: {
- swap = true;
- pts = CubicLineIntersect(wn.pts(), wt.pts(), ts);
- debugShowCubicLineIntersection(pts, wn, wt, ts);
- break;
- }
- default:
- SkASSERT(0);
- }
- break;
- case Work::kQuad_Segment:
- switch (wn.segmentType()) {
- case Work::kHorizontalLine_Segment:
- pts = HQuadIntersect(wt.pts(), wn.left(),
- wn.right(), wn.y(), wn.xFlipped(), ts);
- break;
- case Work::kVerticalLine_Segment:
- pts = VQuadIntersect(wt.pts(), wn.top(),
- wn.bottom(), wn.x(), wn.yFlipped(), ts);
- break;
- case Work::kLine_Segment: {
- pts = QuadLineIntersect(wt.pts(), wn.pts(), ts);
- debugShowQuadLineIntersection(pts, wt, wn, ts);
- break;
- }
- case Work::kQuad_Segment: {
- pts = QuadIntersect(wt.pts(), wn.pts(), ts);
- debugShowQuadIntersection(pts, wt, wn, ts);
- break;
- }
- case Work::kCubic_Segment: {
- #if APPROXIMATE_CUBICS
- swap = true;
- pts = CubicQuadIntersect(wn.pts(), wt.pts(), ts);
- debugShowCubicQuadIntersection(pts, wn, wt, ts);
- #else
- wt.promoteToCubic();
- pts = CubicIntersect(wt.cubic(), wn.pts(), ts);
- debugShowCubicIntersection(pts, wt, wn, ts);
- #endif
- break;
- }
- default:
- SkASSERT(0);
- }
- break;
- case Work::kCubic_Segment:
- switch (wn.segmentType()) {
- case Work::kHorizontalLine_Segment:
- pts = HCubicIntersect(wt.pts(), wn.left(),
- wn.right(), wn.y(), wn.xFlipped(), ts);
- debugShowCubicLineIntersection(pts, wt, wn, ts);
- break;
- case Work::kVerticalLine_Segment:
- pts = VCubicIntersect(wt.pts(), wn.top(),
- wn.bottom(), wn.x(), wn.yFlipped(), ts);
- debugShowCubicLineIntersection(pts, wt, wn, ts);
- break;
- case Work::kLine_Segment: {
- pts = CubicLineIntersect(wt.pts(), wn.pts(), ts);
- debugShowCubicLineIntersection(pts, wt, wn, ts);
- break;
- }
- case Work::kQuad_Segment: {
- #if APPROXIMATE_CUBICS
- pts = CubicQuadIntersect(wt.pts(), wn.pts(), ts);
- debugShowCubicQuadIntersection(pts, wt, wn, ts);
- #else
- wn.promoteToCubic();
- pts = CubicIntersect(wt.pts(), wn.cubic(), ts);
- debugShowCubicIntersection(pts, wt, wn, ts);
- #endif
- break;
- }
- case Work::kCubic_Segment: {
- pts = CubicIntersect(wt.pts(), wn.pts(), ts);
- debugShowCubicIntersection(pts, wt, wn, ts);
- break;
- }
- default:
- SkASSERT(0);
- }
- break;
- default:
- SkASSERT(0);
- }
- if (!foundCommonContour && pts > 0) {
- test->addCross(next);
- next->addCross(test);
- foundCommonContour = true;
- }
- // in addition to recording T values, record matching segment
- if (ts.unsortable()) {
- bool start = true;
- for (int pt = 0; pt < ts.used(); ++pt) {
- // FIXME: if unsortable, the other points to the original. This logic is
- // untested downstream.
- SkPoint point = ts.fPt[pt].asSkPoint();
- int testTAt = wt.addUnsortableT(wt, start, point, ts.fT[swap][pt]);
- wt.addOtherT(testTAt, ts.fT[swap][pt], testTAt);
- testTAt = wn.addUnsortableT(wn, start ^ ts.fFlip, point, ts.fT[!swap][pt]);
- wn.addOtherT(testTAt, ts.fT[!swap][pt], testTAt);
- start ^= true;
- }
- continue;
- }
- if (pts == 2) {
- if (wn.segmentType() <= Work::kLine_Segment
- && wt.segmentType() <= Work::kLine_Segment) {
- wt.addCoincident(wn, ts, swap);
- continue;
- }
- if (wn.segmentType() >= Work::kQuad_Segment
- && wt.segmentType() >= Work::kQuad_Segment
- && ts.fIsCoincident[0]) {
- SkASSERT(ts.coincidentUsed() == 2);
- wt.addCoincident(wn, ts, swap);
- continue;
- }
-
- }
- for (int pt = 0; pt < pts; ++pt) {
- SkASSERT(ts.fT[0][pt] >= 0 && ts.fT[0][pt] <= 1);
- SkASSERT(ts.fT[1][pt] >= 0 && ts.fT[1][pt] <= 1);
- SkPoint point = ts.fPt[pt].asSkPoint();
- int testTAt = wt.addT(wn, point, ts.fT[swap][pt]);
- int nextTAt = wn.addT(wt, point, ts.fT[!swap][pt]);
- wt.addOtherT(testTAt, ts.fT[!swap][pt ^ ts.fFlip], nextTAt);
- wn.addOtherT(nextTAt, ts.fT[swap][pt ^ ts.fFlip], testTAt);
- }
- } while (wn.advance());
- } while (wt.advance());
- return true;
-}
-
-static void addSelfIntersectTs(Contour* test) {
- Work wt;
- wt.init(test);
- do {
- if (wt.segmentType() != Work::kCubic_Segment) {
- continue;
- }
- Intersections ts;
- int pts = CubicIntersect(wt.pts(), ts);
- debugShowCubicIntersection(pts, wt, ts);
- if (!pts) {
- continue;
- }
- SkASSERT(pts == 1);
- SkASSERT(ts.fT[0][0] >= 0 && ts.fT[0][0] <= 1);
- SkASSERT(ts.fT[1][0] >= 0 && ts.fT[1][0] <= 1);
- SkPoint point = ts.fPt[0].asSkPoint();
- int testTAt = wt.addSelfT(wt, point, ts.fT[0][0]);
- int nextTAt = wt.addT(wt, point, ts.fT[1][0]);
- wt.addOtherT(testTAt, ts.fT[1][0], nextTAt);
- wt.addOtherT(nextTAt, ts.fT[0][0], testTAt);
- } while (wt.advance());
-}
-
-// resolve any coincident pairs found while intersecting, and
-// see if coincidence is formed by clipping non-concident segments
-static void coincidenceCheck(SkTDArray<Contour*>& contourList, int total) {
- int contourCount = contourList.count();
-#if ONE_PASS_COINCIDENCE_CHECK
- for (int cIndex = 0; cIndex < contourCount; ++cIndex) {
- Contour* contour = contourList[cIndex];
- contour->resolveCoincidence(contourList);
- }
-#else
- for (int cIndex = 0; cIndex < contourCount; ++cIndex) {
- Contour* contour = contourList[cIndex];
- contour->addCoincidentPoints();
- }
- for (int cIndex = 0; cIndex < contourCount; ++cIndex) {
- Contour* contour = contourList[cIndex];
- contour->calcCoincidentWinding();
- }
-#endif
- for (int cIndex = 0; cIndex < contourCount; ++cIndex) {
- Contour* contour = contourList[cIndex];
- contour->findTooCloseToCall();
- }
-}
-
-static int contourRangeCheckY(SkTDArray<Contour*>& contourList, Segment*& current, int& index,
- int& endIndex, double& bestHit, SkScalar& bestDx, bool& tryAgain, double& mid, bool opp) {
- SkPoint basePt;
- double tAtMid = current->tAtMid(index, endIndex, mid);
- current->xyAtT(tAtMid, basePt);
- int contourCount = contourList.count();
- SkScalar bestY = SK_ScalarMin;
- Segment* bestSeg = NULL;
- int bestTIndex;
- bool bestOpp;
- bool hitSomething = false;
- for (int cTest = 0; cTest < contourCount; ++cTest) {
- Contour* contour = contourList[cTest];
- bool testOpp = contour->operand() ^ current->operand() ^ opp;
- if (basePt.fY < contour->bounds().fTop) {
- continue;
- }
- if (bestY > contour->bounds().fBottom) {
- continue;
- }
- int segmentCount = contour->segments().count();
- for (int test = 0; test < segmentCount; ++test) {
- Segment* testSeg = &contour->segments()[test];
- SkScalar testY = bestY;
- double testHit;
- int testTIndex = testSeg->crossedSpanY(basePt, testY, testHit, hitSomething, tAtMid,
- testOpp, testSeg == current);
- if (testTIndex < 0) {
- if (testTIndex == SK_MinS32) {
- hitSomething = true;
- bestSeg = NULL;
- goto abortContours; // vertical encountered, return and try different point
- }
- continue;
- }
- if (testSeg == current && current->betweenTs(index, testHit, endIndex)) {
- double baseT = current->t(index);
- double endT = current->t(endIndex);
- double newMid = (testHit - baseT) / (endT - baseT);
-#if DEBUG_WINDING
- SkPoint midXY, newXY;
- double midT = current->tAtMid(index, endIndex, mid);
- current->xyAtT(midT, midXY);
- double newMidT = current->tAtMid(index, endIndex, newMid);
- current->xyAtT(newMidT, newXY);
- SkDebugf("%s [%d] mid=%1.9g->%1.9g s=%1.9g (%1.9g,%1.9g) m=%1.9g (%1.9g,%1.9g)"
- " n=%1.9g (%1.9g,%1.9g) e=%1.9g (%1.9g,%1.9g)\n", __FUNCTION__,
- current->debugID(), mid, newMid,
- baseT, current->xAtT(index), current->yAtT(index),
- baseT + mid * (endT - baseT), midXY.fX, midXY.fY,
- baseT + newMid * (endT - baseT), newXY.fX, newXY.fY,
- endT, current->xAtT(endIndex), current->yAtT(endIndex));
-#endif
- mid = newMid * 2; // calling loop with divide by 2 before continuing
- return SK_MinS32;
- }
- bestSeg = testSeg;
- bestHit = testHit;
- bestOpp = testOpp;
- bestTIndex = testTIndex;
- bestY = testY;
- }
- }
-abortContours:
- int result;
- if (!bestSeg) {
- result = hitSomething ? SK_MinS32 : 0;
- } else {
- if (bestSeg->windSum(bestTIndex) == SK_MinS32) {
- current = bestSeg;
- index = bestTIndex;
- endIndex = bestSeg->nextSpan(bestTIndex, 1);
- SkASSERT(index != endIndex && index >= 0 && endIndex >= 0);
- tryAgain = true;
- return 0;
- }
- result = bestSeg->windingAtT(bestHit, bestTIndex, bestOpp, bestDx);
- SkASSERT(bestDx);
- }
- double baseT = current->t(index);
- double endT = current->t(endIndex);
- bestHit = baseT + mid * (endT - baseT);
- return result;
-}
-
-static Segment* findUndone(SkTDArray<Contour*>& contourList, int& start, int& end) {
- int contourCount = contourList.count();
- Segment* result;
- for (int cIndex = 0; cIndex < contourCount; ++cIndex) {
- Contour* contour = contourList[cIndex];
- result = contour->undoneSegment(start, end);
- if (result) {
- return result;
- }
- }
- return NULL;
-}
-
-#define OLD_FIND_CHASE 1
-
-static Segment* findChase(SkTDArray<Span*>& chase, int& tIndex, int& endIndex) {
- while (chase.count()) {
- Span* span;
- chase.pop(&span);
- const Span& backPtr = span->fOther->span(span->fOtherIndex);
- Segment* segment = backPtr.fOther;
- tIndex = backPtr.fOtherIndex;
- SkTDArray<Angle> angles;
- int done = 0;
- if (segment->activeAngle(tIndex, done, angles)) {
- Angle* last = angles.end() - 1;
- tIndex = last->start();
- endIndex = last->end();
- #if TRY_ROTATE
- *chase.insert(0) = span;
- #else
- *chase.append() = span;
- #endif
- return last->segment();
- }
- if (done == angles.count()) {
- continue;
- }
- SkTDArray<Angle*> sorted;
- bool sortable = Segment::SortAngles(angles, sorted);
- int angleCount = sorted.count();
-#if DEBUG_SORT
- sorted[0]->segment()->debugShowSort(__FUNCTION__, sorted, 0, 0, 0);
-#endif
- if (!sortable) {
- continue;
- }
- // find first angle, initialize winding to computed fWindSum
- int firstIndex = -1;
- const Angle* angle;
-#if OLD_FIND_CHASE
- int winding;
- do {
- angle = sorted[++firstIndex];
- segment = angle->segment();
- winding = segment->windSum(angle);
- } while (winding == SK_MinS32);
- int spanWinding = segment->spanSign(angle->start(), angle->end());
- #if DEBUG_WINDING
- SkDebugf("%s winding=%d spanWinding=%d\n",
- __FUNCTION__, winding, spanWinding);
- #endif
- // turn span winding into contour winding
- if (spanWinding * winding < 0) {
- winding += spanWinding;
- }
- #if DEBUG_SORT
- segment->debugShowSort(__FUNCTION__, sorted, firstIndex, winding, 0);
- #endif
- // we care about first sign and whether wind sum indicates this
- // edge is inside or outside. Maybe need to pass span winding
- // or first winding or something into this function?
- // advance to first undone angle, then return it and winding
- // (to set whether edges are active or not)
- int nextIndex = firstIndex + 1;
- int lastIndex = firstIndex != 0 ? firstIndex : angleCount;
- angle = sorted[firstIndex];
- winding -= angle->segment()->spanSign(angle);
-#else
- do {
- angle = sorted[++firstIndex];
- segment = angle->segment();
- } while (segment->windSum(angle) == SK_MinS32);
- #if DEBUG_SORT
- segment->debugShowSort(__FUNCTION__, sorted, firstIndex);
- #endif
- int sumWinding = segment->updateWindingReverse(angle);
- int nextIndex = firstIndex + 1;
- int lastIndex = firstIndex != 0 ? firstIndex : angleCount;
- Segment* first = NULL;
-#endif
- do {
- SkASSERT(nextIndex != firstIndex);
- if (nextIndex == angleCount) {
- nextIndex = 0;
- }
- angle = sorted[nextIndex];
- segment = angle->segment();
-#if OLD_FIND_CHASE
- int maxWinding = winding;
- winding -= segment->spanSign(angle);
- #if DEBUG_SORT
- SkDebugf("%s id=%d maxWinding=%d winding=%d sign=%d\n", __FUNCTION__,
- segment->debugID(), maxWinding, winding, angle->sign());
- #endif
- tIndex = angle->start();
- endIndex = angle->end();
- int lesser = SkMin32(tIndex, endIndex);
- const Span& nextSpan = segment->span(lesser);
- if (!nextSpan.fDone) {
-#if 1
- // FIXME: this be wrong? assign startWinding if edge is in
- // same direction. If the direction is opposite, winding to
- // assign is flipped sign or +/- 1?
- if (useInnerWinding(maxWinding, winding)) {
- maxWinding = winding;
- }
- segment->markAndChaseWinding(angle, maxWinding, 0);
-#endif
- break;
- }
-#else
- int start = angle->start();
- int end = angle->end();
- int maxWinding;
- segment->setUpWinding(start, end, maxWinding, sumWinding);
- if (!segment->done(angle)) {
- if (!first) {
- first = segment;
- tIndex = start;
- endIndex = end;
- }
- (void) segment->markAngle(maxWinding, sumWinding, true, angle);
- }
-#endif
- } while (++nextIndex != lastIndex);
- #if TRY_ROTATE
- *chase.insert(0) = span;
- #else
- *chase.append() = span;
- #endif
- return segment;
- }
- return NULL;
-}
-
-#if DEBUG_ACTIVE_SPANS
-static void debugShowActiveSpans(SkTDArray<Contour*>& contourList) {
- int index;
- for (index = 0; index < contourList.count(); ++ index) {
- contourList[index]->debugShowActiveSpans();
- }
- for (index = 0; index < contourList.count(); ++ index) {
- contourList[index]->validateActiveSpans();
- }
-}
-#endif
-
-static Segment* findSortableTop(SkTDArray<Contour*>& contourList, int& index,
- int& endIndex, SkPoint& topLeft, bool& unsortable, bool& done, bool onlySortable) {
- Segment* result;
- do {
- SkPoint bestXY = {SK_ScalarMax, SK_ScalarMax};
- int contourCount = contourList.count();
- Segment* topStart = NULL;
- done = true;
- for (int cIndex = 0; cIndex < contourCount; ++cIndex) {
- Contour* contour = contourList[cIndex];
- if (contour->done()) {
- continue;
- }
- const Bounds& bounds = contour->bounds();
- if (bounds.fBottom < topLeft.fY) {
- done = false;
- continue;
- }
- if (bounds.fBottom == topLeft.fY && bounds.fRight < topLeft.fX) {
- done = false;
- continue;
- }
- contour->topSortableSegment(topLeft, bestXY, topStart);
- if (!contour->done()) {
- done = false;
- }
- }
- if (!topStart) {
- return NULL;
- }
- topLeft = bestXY;
- result = topStart->findTop(index, endIndex, unsortable, onlySortable);
- } while (!result);
- return result;
-}
-
-static int rightAngleWinding(SkTDArray<Contour*>& contourList,
- Segment*& current, int& index, int& endIndex, double& tHit, SkScalar& hitDx, bool& tryAgain,
- bool opp) {
- double test = 0.9;
- int contourWinding;
- do {
- contourWinding = contourRangeCheckY(contourList, current, index, endIndex, tHit, hitDx,
- tryAgain, test, opp);
- if (contourWinding != SK_MinS32 || tryAgain) {
- return contourWinding;
- }
- test /= 2;
- } while (!approximately_negative(test));
- SkASSERT(0); // should be OK to comment out, but interested when this hits
- return contourWinding;
-}
-
-static void skipVertical(SkTDArray<Contour*>& contourList,
- Segment*& current, int& index, int& endIndex) {
- if (!current->isVertical(index, endIndex)) {
- return;
- }
- int contourCount = contourList.count();
- for (int cIndex = 0; cIndex < contourCount; ++cIndex) {
- Contour* contour = contourList[cIndex];
- if (contour->done()) {
- continue;
- }
- current = contour->nonVerticalSegment(index, endIndex);
- if (current) {
- return;
- }
- }
-}
-
-static Segment* findSortableTop(SkTDArray<Contour*>& contourList, bool& firstContour, int& index,
- int& endIndex, SkPoint& topLeft, bool& unsortable, bool& done, bool binary) {
- Segment* current = findSortableTop(contourList, index, endIndex, topLeft, unsortable, done,
- true);
- if (!current) {
- return NULL;
- }
- if (firstContour) {
- current->initWinding(index, endIndex);
- firstContour = false;
- return current;
- }
- int minIndex = SkMin32(index, endIndex);
- int sumWinding = current->windSum(minIndex);
- if (sumWinding != SK_MinS32) {
- return current;
- }
- sumWinding = current->computeSum(index, endIndex, binary);
- if (sumWinding != SK_MinS32) {
- return current;
- }
- int contourWinding;
- int oppContourWinding = 0;
- // the simple upward projection of the unresolved points hit unsortable angles
- // shoot rays at right angles to the segment to find its winding, ignoring angle cases
- bool tryAgain;
- double tHit;
- SkScalar hitDx = 0;
- SkScalar hitOppDx = 0;
- do {
- // if current is vertical, find another candidate which is not
- // if only remaining candidates are vertical, then they can be marked done
- SkASSERT(index != endIndex && index >= 0 && endIndex >= 0);
- skipVertical(contourList, current, index, endIndex);
- SkASSERT(index != endIndex && index >= 0 && endIndex >= 0);
- tryAgain = false;
- contourWinding = rightAngleWinding(contourList, current, index, endIndex, tHit, hitDx,
- tryAgain, false);
- if (tryAgain) {
- continue;
- }
- if (!binary) {
- break;
- }
- oppContourWinding = rightAngleWinding(contourList, current, index, endIndex, tHit, hitOppDx,
- tryAgain, true);
- } while (tryAgain);
-
- current->initWinding(index, endIndex, tHit, contourWinding, hitDx, oppContourWinding, hitOppDx);
- return current;
-}
-
-// rewrite that abandons keeping local track of winding
-static bool bridgeWinding(SkTDArray<Contour*>& contourList, PathWrapper& simple) {
- bool firstContour = true;
- bool unsortable = false;
- bool topUnsortable = false;
- SkPoint topLeft = {SK_ScalarMin, SK_ScalarMin};
- do {
- int index, endIndex;
- bool topDone;
- Segment* current = findSortableTop(contourList, firstContour, index, endIndex, topLeft,
- topUnsortable, topDone, false);
- if (!current) {
- if (topUnsortable || !topDone) {
- topUnsortable = false;
- SkASSERT(topLeft.fX != SK_ScalarMin && topLeft.fY != SK_ScalarMin);
- topLeft.fX = topLeft.fY = SK_ScalarMin;
- continue;
- }
- break;
- }
- SkTDArray<Span*> chaseArray;
- do {
- if (current->activeWinding(index, endIndex)) {
- do {
- #if DEBUG_ACTIVE_SPANS
- if (!unsortable && current->done()) {
- debugShowActiveSpans(contourList);
- }
- #endif
- SkASSERT(unsortable || !current->done());
- int nextStart = index;
- int nextEnd = endIndex;
- Segment* next = current->findNextWinding(chaseArray, nextStart, nextEnd,
- unsortable);
- if (!next) {
- if (!unsortable && simple.hasMove()
- && current->verb() != SkPath::kLine_Verb
- && !simple.isClosed()) {
- current->addCurveTo(index, endIndex, simple, true);
- SkASSERT(simple.isClosed());
- }
- break;
- }
- #if DEBUG_FLOW
- SkDebugf("%s current id=%d from=(%1.9g,%1.9g) to=(%1.9g,%1.9g)\n", __FUNCTION__,
- current->debugID(), current->xyAtT(index).fX, current->xyAtT(index).fY,
- current->xyAtT(endIndex).fX, current->xyAtT(endIndex).fY);
- #endif
- current->addCurveTo(index, endIndex, simple, true);
- current = next;
- index = nextStart;
- endIndex = nextEnd;
- } while (!simple.isClosed() && (!unsortable
- || !current->done(SkMin32(index, endIndex))));
- if (current->activeWinding(index, endIndex) && !simple.isClosed()) {
- SkASSERT(unsortable);
- int min = SkMin32(index, endIndex);
- if (!current->done(min)) {
- current->addCurveTo(index, endIndex, simple, true);
- current->markDoneUnary(min);
- }
- }
- simple.close();
- } else {
- Span* last = current->markAndChaseDoneUnary(index, endIndex);
- if (last && !last->fLoop) {
- *chaseArray.append() = last;
- }
- }
- current = findChase(chaseArray, index, endIndex);
- #if DEBUG_ACTIVE_SPANS
- debugShowActiveSpans(contourList);
- #endif
- if (!current) {
- break;
- }
- } while (true);
- } while (true);
- return simple.someAssemblyRequired();
-}
-
-// returns true if all edges were processed
-static bool bridgeXor(SkTDArray<Contour*>& contourList, PathWrapper& simple) {
- Segment* current;
- int start, end;
- bool unsortable = false;
- bool closable = true;
- while ((current = findUndone(contourList, start, end))) {
- do {
- #if DEBUG_ACTIVE_SPANS
- if (!unsortable && current->done()) {
- debugShowActiveSpans(contourList);
- }
- #endif
- SkASSERT(unsortable || !current->done());
- int nextStart = start;
- int nextEnd = end;
- Segment* next = current->findNextXor(nextStart, nextEnd, unsortable);
- if (!next) {
- if (!unsortable && simple.hasMove()
- && current->verb() != SkPath::kLine_Verb
- && !simple.isClosed()) {
- current->addCurveTo(start, end, simple, true);
- SkASSERT(simple.isClosed());
- }
- break;
- }
- #if DEBUG_FLOW
- SkDebugf("%s current id=%d from=(%1.9g,%1.9g) to=(%1.9g,%1.9g)\n", __FUNCTION__,
- current->debugID(), current->xyAtT(start).fX, current->xyAtT(start).fY,
- current->xyAtT(end).fX, current->xyAtT(end).fY);
- #endif
- current->addCurveTo(start, end, simple, true);
- current = next;
- start = nextStart;
- end = nextEnd;
- } while (!simple.isClosed() && (!unsortable || !current->done(SkMin32(start, end))));
- if (!simple.isClosed()) {
- SkASSERT(unsortable);
- int min = SkMin32(start, end);
- if (!current->done(min)) {
- current->addCurveTo(start, end, simple, true);
- current->markDone(min, 1);
- }
- closable = false;
- }
- simple.close();
- #if DEBUG_ACTIVE_SPANS
- debugShowActiveSpans(contourList);
- #endif
- }
- return closable;
-}
-
-static void fixOtherTIndex(SkTDArray<Contour*>& contourList) {
- int contourCount = contourList.count();
- for (int cTest = 0; cTest < contourCount; ++cTest) {
- Contour* contour = contourList[cTest];
- contour->fixOtherTIndex();
- }
-}
-
-static void sortSegments(SkTDArray<Contour*>& contourList) {
- int contourCount = contourList.count();
- for (int cTest = 0; cTest < contourCount; ++cTest) {
- Contour* contour = contourList[cTest];
- contour->sortSegments();
- }
-}
-
-static void makeContourList(SkTArray<Contour>& contours, SkTDArray<Contour*>& list,
- bool evenOdd, bool oppEvenOdd) {
- int count = contours.count();
- if (count == 0) {
- return;
- }
- for (int index = 0; index < count; ++index) {
- Contour& contour = contours[index];
- contour.setOppXor(contour.operand() ? evenOdd : oppEvenOdd);
- *list.append() = &contour;
- }
- QSort<Contour>(list.begin(), list.end() - 1);
-}
-
-static bool approximatelyEqual(const SkPoint& a, const SkPoint& b) {
- return AlmostEqualUlps(a.fX, b.fX) && AlmostEqualUlps(a.fY, b.fY);
-}
-
-static bool lessThan(SkTDArray<double>& distances, const int one, const int two) {
- return distances[one] < distances[two];
-}
- /*
- check start and end of each contour
- if not the same, record them
- match them up
- connect closest
- reassemble contour pieces into new path
- */
-static void assemble(const PathWrapper& path, PathWrapper& simple) {
-#if DEBUG_PATH_CONSTRUCTION
- SkDebugf("%s\n", __FUNCTION__);
-#endif
- SkTArray<Contour> contours;
- EdgeBuilder builder(path, contours);
- builder.finish();
- int count = contours.count();
- int outer;
- SkTDArray<int> runs; // indices of partial contours
- for (outer = 0; outer < count; ++outer) {
- const Contour& eContour = contours[outer];
- const SkPoint& eStart = eContour.start();
- const SkPoint& eEnd = eContour.end();
-#if DEBUG_ASSEMBLE
- SkDebugf("%s contour", __FUNCTION__);
- if (!approximatelyEqual(eStart, eEnd)) {
- SkDebugf("[%d]", runs.count());
- } else {
- SkDebugf(" ");
- }
- SkDebugf(" start=(%1.9g,%1.9g) end=(%1.9g,%1.9g)\n",
- eStart.fX, eStart.fY, eEnd.fX, eEnd.fY);
-#endif
- if (approximatelyEqual(eStart, eEnd)) {
- eContour.toPath(simple);
- continue;
- }
- *runs.append() = outer;
- }
- count = runs.count();
- if (count == 0) {
- return;
- }
- SkTDArray<int> sLink, eLink;
- sLink.setCount(count);
- eLink.setCount(count);
- int rIndex, iIndex;
- for (rIndex = 0; rIndex < count; ++rIndex) {
- sLink[rIndex] = eLink[rIndex] = SK_MaxS32;
- }
- SkTDArray<double> distances;
- const int ends = count * 2; // all starts and ends
- const int entries = (ends - 1) * count; // folded triangle : n * (n - 1) / 2
- distances.setCount(entries);
- for (rIndex = 0; rIndex < ends - 1; ++rIndex) {
- outer = runs[rIndex >> 1];
- const Contour& oContour = contours[outer];
- const SkPoint& oPt = rIndex & 1 ? oContour.end() : oContour.start();
- const int row = rIndex < count - 1 ? rIndex * ends : (ends - rIndex - 2)
- * ends - rIndex - 1;
- for (iIndex = rIndex + 1; iIndex < ends; ++iIndex) {
- int inner = runs[iIndex >> 1];
- const Contour& iContour = contours[inner];
- const SkPoint& iPt = iIndex & 1 ? iContour.end() : iContour.start();
- double dx = iPt.fX - oPt.fX;
- double dy = iPt.fY - oPt.fY;
- double dist = dx * dx + dy * dy;
- distances[row + iIndex] = dist; // oStart distance from iStart
- }
- }
- SkTDArray<int> sortedDist;
- sortedDist.setCount(entries);
- for (rIndex = 0; rIndex < entries; ++rIndex) {
- sortedDist[rIndex] = rIndex;
- }
- QSort<SkTDArray<double>, int>(distances, sortedDist.begin(), sortedDist.end() - 1, lessThan);
- int remaining = count; // number of start/end pairs
- for (rIndex = 0; rIndex < entries; ++rIndex) {
- int pair = sortedDist[rIndex];
- int row = pair / ends;
- int col = pair - row * ends;
- int thingOne = row < col ? row : ends - row - 2;
- int ndxOne = thingOne >> 1;
- bool endOne = thingOne & 1;
- int* linkOne = endOne ? eLink.begin() : sLink.begin();
- if (linkOne[ndxOne] != SK_MaxS32) {
- continue;
- }
- int thingTwo = row < col ? col : ends - row + col - 1;
- int ndxTwo = thingTwo >> 1;
- bool endTwo = thingTwo & 1;
- int* linkTwo = endTwo ? eLink.begin() : sLink.begin();
- if (linkTwo[ndxTwo] != SK_MaxS32) {
- continue;
- }
- SkASSERT(&linkOne[ndxOne] != &linkTwo[ndxTwo]);
- bool flip = endOne == endTwo;
- linkOne[ndxOne] = flip ? ~ndxTwo : ndxTwo;
- linkTwo[ndxTwo] = flip ? ~ndxOne : ndxOne;
- if (!--remaining) {
- break;
- }
- }
- SkASSERT(!remaining);
-#if DEBUG_ASSEMBLE
- for (rIndex = 0; rIndex < count; ++rIndex) {
- int s = sLink[rIndex];
- int e = eLink[rIndex];
- SkDebugf("%s %c%d <- s%d - e%d -> %c%d\n", __FUNCTION__, s < 0 ? 's' : 'e',
- s < 0 ? ~s : s, rIndex, rIndex, e < 0 ? 'e' : 's', e < 0 ? ~e : e);
- }
-#endif
- rIndex = 0;
- do {
- bool forward = true;
- bool first = true;
- int sIndex = sLink[rIndex];
- SkASSERT(sIndex != SK_MaxS32);
- sLink[rIndex] = SK_MaxS32;
- int eIndex;
- if (sIndex < 0) {
- eIndex = sLink[~sIndex];
- sLink[~sIndex] = SK_MaxS32;
- } else {
- eIndex = eLink[sIndex];
- eLink[sIndex] = SK_MaxS32;
- }
- SkASSERT(eIndex != SK_MaxS32);
-#if DEBUG_ASSEMBLE
- SkDebugf("%s sIndex=%c%d eIndex=%c%d\n", __FUNCTION__, sIndex < 0 ? 's' : 'e',
- sIndex < 0 ? ~sIndex : sIndex, eIndex < 0 ? 's' : 'e',
- eIndex < 0 ? ~eIndex : eIndex);
-#endif
- do {
- outer = runs[rIndex];
- const Contour& contour = contours[outer];
- if (first) {
- first = false;
- const SkPoint* startPtr = &contour.start();
- simple.deferredMove(startPtr[0]);
- }
- if (forward) {
- contour.toPartialForward(simple);
- } else {
- contour.toPartialBackward(simple);
- }
-#if DEBUG_ASSEMBLE
- SkDebugf("%s rIndex=%d eIndex=%s%d close=%d\n", __FUNCTION__, rIndex,
- eIndex < 0 ? "~" : "", eIndex < 0 ? ~eIndex : eIndex,
- sIndex == ((rIndex != eIndex) ^ forward ? eIndex : ~eIndex));
-#endif
- if (sIndex == ((rIndex != eIndex) ^ forward ? eIndex : ~eIndex)) {
- simple.close();
- break;
- }
- if (forward) {
- eIndex = eLink[rIndex];
- SkASSERT(eIndex != SK_MaxS32);
- eLink[rIndex] = SK_MaxS32;
- if (eIndex >= 0) {
- SkASSERT(sLink[eIndex] == rIndex);
- sLink[eIndex] = SK_MaxS32;
- } else {
- SkASSERT(eLink[~eIndex] == ~rIndex);
- eLink[~eIndex] = SK_MaxS32;
- }
- } else {
- eIndex = sLink[rIndex];
- SkASSERT(eIndex != SK_MaxS32);
- sLink[rIndex] = SK_MaxS32;
- if (eIndex >= 0) {
- SkASSERT(eLink[eIndex] == rIndex);
- eLink[eIndex] = SK_MaxS32;
- } else {
- SkASSERT(sLink[~eIndex] == ~rIndex);
- sLink[~eIndex] = SK_MaxS32;
- }
- }
- rIndex = eIndex;
- if (rIndex < 0) {
- forward ^= 1;
- rIndex = ~rIndex;
- }
- } while (true);
- for (rIndex = 0; rIndex < count; ++rIndex) {
- if (sLink[rIndex] != SK_MaxS32) {
- break;
- }
- }
- } while (rIndex < count);
-#if DEBUG_ASSEMBLE
- for (rIndex = 0; rIndex < count; ++rIndex) {
- SkASSERT(sLink[rIndex] == SK_MaxS32);
- SkASSERT(eLink[rIndex] == SK_MaxS32);
- }
-#endif
-}
-
-void simplifyx(const SkPath& path, SkPath& result) {
-#if DEBUG_SORT || DEBUG_SWAP_TOP
- gDebugSortCount = gDebugSortCountDefault;
-#endif
- // returns 1 for evenodd, -1 for winding, regardless of inverse-ness
- result.reset();
- result.setFillType(SkPath::kEvenOdd_FillType);
- PathWrapper simple(result);
-
- // turn path into list of segments
- SkTArray<Contour> contours;
- EdgeBuilder builder(path, contours);
- builder.finish();
- SkTDArray<Contour*> contourList;
- makeContourList(contours, contourList, false, false);
- Contour** currentPtr = contourList.begin();
- if (!currentPtr) {
- return;
- }
- Contour** listEnd = contourList.end();
- // find all intersections between segments
- do {
- Contour** nextPtr = currentPtr;
- Contour* current = *currentPtr++;
- if (current->containsCubics()) {
- addSelfIntersectTs(current);
- }
- Contour* next;
- do {
- next = *nextPtr++;
- } while (addIntersectTs(current, next) && nextPtr != listEnd);
- } while (currentPtr != listEnd);
- // eat through coincident edges
- coincidenceCheck(contourList, 0);
- fixOtherTIndex(contourList);
- sortSegments(contourList);
-#if DEBUG_ACTIVE_SPANS
- debugShowActiveSpans(contourList);
-#endif
- // construct closed contours
- if (builder.xorMask() == kWinding_Mask ? bridgeWinding(contourList, simple)
- : !bridgeXor(contourList, simple))
- { // if some edges could not be resolved, assemble remaining fragments
- SkPath temp;
- temp.setFillType(SkPath::kEvenOdd_FillType);
- PathWrapper assembled(temp);
- assemble(simple, assembled);
- result = *assembled.nativePath();
- }
-}
diff --git a/experimental/Intersection/Simplify.h b/experimental/Intersection/Simplify.h
deleted file mode 100644
index d2e238f35d..0000000000
--- a/experimental/Intersection/Simplify.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "CurveIntersection.h"
-#include "CurveUtilities.h"
-#include "Intersections.h"
-#include "LineIntersection.h"
-#include "LineParameters.h"
-#include "SkPath.h"
-#include "SkRect.h"
-#include "SkTArray.h"
-#include "SkTDArray.h"
-#include "ShapeOps.h"
-#include "TSearch.h"
diff --git a/experimental/Intersection/SimplifyAddIntersectingTs_Test.cpp b/experimental/Intersection/SimplifyAddIntersectingTs_Test.cpp
deleted file mode 100644
index 89046a86b1..0000000000
--- a/experimental/Intersection/SimplifyAddIntersectingTs_Test.cpp
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "Simplify.h"
-
-namespace SimplifyAddIntersectingTsTest {
-
-#include "Simplify.cpp"
-
-} // end of SimplifyAddIntersectingTsTest namespace
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "Intersection_Tests.h"
-
-static const SkPoint lines[][2] = {
- {{ 1, 1}, { 1, 1}}, // degenerate
- {{ 1, 1}, { 4, 1}}, // horizontal
- {{ 4, 1}, { 9, 1}},
- {{ 2, 1}, { 3, 1}},
- {{ 2, 1}, { 6, 1}},
- {{ 5, 1}, { 9, 1}},
- {{ 1, 1}, { 1, 4}}, // vertical
- {{ 1, 2}, { 1, 3}},
- {{ 1, 2}, { 1, 6}},
- {{ 1, 5}, { 1, 9}},
- {{ 1, 1}, { 3, 3}}, // diagonal
- {{ 2, 2}, { 4, 4}},
- {{ 2, 4}, { 4, 2}},
-};
-
-static const size_t lineCount = sizeof(lines) / sizeof(lines[0]);
-
-static const SkPoint quads[][3] = {
- {{ 1, 1}, { 1, 1}, { 1, 1}}, // degenerate
- {{ 1, 1}, { 4, 1}, { 5, 1}}, // line
- {{ 1, 1}, { 4, 1}, { 4, 4}}, // curve
-};
-
-static const size_t quadCount = sizeof(quads) / sizeof(quads[0]);
-
-static const SkPoint cubics[][4] = {
- {{ 1, 1}, { 1, 1}, { 1, 1}, { 1, 1}}, // degenerate
- {{ 1, 1}, { 4, 1}, { 5, 1}, { 6, 1}}, // line
- {{ 1, 1}, { 3, 1}, { 4, 2}, { 4, 4}}, // curve
-};
-
-static const size_t cubicCount = sizeof(cubics) / sizeof(cubics[0]);
-static const size_t testCount = lineCount + quadCount + cubicCount;
-
-static SkPath::Verb setPath(size_t outer, SkPath& path, const SkPoint*& pts1) {
- SkPath::Verb c1Type;
- if (outer < lineCount) {
- path.moveTo(lines[outer][0].fX, lines[outer][0].fY);
- path.lineTo(lines[outer][1].fX, lines[outer][1].fY);
- c1Type = SkPath::kLine_Verb;
- pts1 = lines[outer];
- } else {
- outer -= lineCount;
- if (outer < quadCount) {
- path.moveTo(quads[outer][0].fX, quads[outer][0].fY);
- path.quadTo(quads[outer][1].fX, quads[outer][1].fY,
- quads[outer][2].fX, quads[outer][2].fY);
- c1Type = SkPath::kQuad_Verb;
- pts1 = quads[outer];
- } else {
- outer -= quadCount;
- path.moveTo(cubics[outer][0].fX, cubics[outer][0].fY);
- path.cubicTo(cubics[outer][1].fX, cubics[outer][1].fY,
- cubics[outer][2].fX, cubics[outer][2].fY,
- cubics[outer][3].fX, cubics[outer][3].fY);
- c1Type = SkPath::kCubic_Verb;
- pts1 = cubics[outer];
- }
- }
- return c1Type;
-}
-
-static void testPath(const SkPath& path, const SkPoint* pts1, SkPath::Verb c1Type,
- const SkPoint* pts2, SkPath::Verb c2Type) {
- SkTArray<SimplifyAddIntersectingTsTest::Contour> contour;
- SimplifyAddIntersectingTsTest::EdgeBuilder builder(path, contour);
- if (contour.count() < 2) {
- return;
- }
- SimplifyAddIntersectingTsTest::Contour& c1 = contour[0];
- SimplifyAddIntersectingTsTest::Contour& c2 = contour[1];
- addIntersectTs(&c1, &c2);
-#if DEBUG_DUMP
- bool c1Intersected = c1.segments()[0].intersected();
- // bool c2Intersected = c2.fSegments[0].intersected();
- SkDebugf("%s %s (%1.9g,%1.9g %1.9g,%1.9g) %s %s (%1.9g,%1.9g %1.9g,%1.9g)\n",
- __FUNCTION__, SimplifyAddIntersectingTsTest::kLVerbStr[c1Type],
- pts1[0].fX, pts1[0].fY,
- pts1[c1Type].fX, pts1[c1Type].fY,
- c1Intersected ? "intersects" : "does not intersect",
- SimplifyAddIntersectingTsTest::kLVerbStr[c2Type],
- pts2[0].fX, pts2[0].fY,
- pts2[c2Type].fX, pts2[c2Type].fY);
- if (c1Intersected) {
- c1.dump();
- c2.dump();
- }
-#endif
-}
-
-static const size_t firstO = 6;
-static const size_t firstI = 1;
-
-void SimplifyAddIntersectingTs_Test() {
- const SkPoint* pts1, * pts2;
- if (firstO > 0 || firstI > 0) {
- SkPath path;
- SkPath::Verb c1Type = setPath(firstO, path, pts1);
- SkPath path2(path);
- SkPath::Verb c2Type = setPath(firstI, path2, pts2);
- testPath(path2, pts1, c1Type, pts2, c2Type);
- }
- for (size_t o = 0; o < testCount; ++o) {
- SkPath path;
- SkPath::Verb c1Type = setPath(o, path, pts1);
- for (size_t i = 0; i < testCount; ++i) {
- SkPath path2(path);
- SkPath::Verb c2Type = setPath(i, path2, pts2);
- testPath(path2, pts1, c1Type, pts2, c2Type);
- }
- }
-}
diff --git a/experimental/Intersection/SimplifyAngle_Test.cpp b/experimental/Intersection/SimplifyAngle_Test.cpp
deleted file mode 100644
index e83a52f650..0000000000
--- a/experimental/Intersection/SimplifyAngle_Test.cpp
+++ /dev/null
@@ -1,342 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "Simplify.h"
-
-namespace SimplifyAngleTest {
-
-#include "Simplify.cpp"
-
-} // end of SimplifyAngleTest namespace
-
-#include "Intersection_Tests.h"
-
-static const SkPoint lines[][2] = {
- { { 10, 10}, { 10, 20} },
- { { 10, 10}, { 20, 10} },
- { { 10, 10}, {-20, 10} },
- { { 10, 10}, { 10, -20} },
- { { 10, 10}, { 20, 20} },
- { { 10, 10}, {-20, -20} },
- { { 10, 10}, {-20, 40} },
- { { 10, 10}, { 40, -20} }
-};
-
-static const size_t lineCount = sizeof(lines) / sizeof(lines[0]);
-
-static const SkPoint quads[][3] = {
- {{ 1, 1}, { 2, 2}, { 1, 3}}, // 0
- {{ 1, 1}, { 3, 3}, { 1, 5}}, // 1
- {{ 1, 1}, { 4, 4}, { 1, 7}}, // 2
- {{ 1, 1}, { 5, 5}, { 9, 9}}, // 3
- {{ 1, 1}, { 4, 4}, { 7, 1}}, // 4
- {{ 1, 1}, { 3, 3}, { 5, 1}}, // 5
- {{ 1, 1}, { 2, 2}, { 3, 1}}, // 6
-};
-
-static const size_t quadCount = sizeof(quads) / sizeof(quads[0]);
-
-static const SkPoint cubics[][4] = {
- {{ 1, 1}, { 2, 2}, { 2, 3}, { 1, 4}},
- {{ 1, 1}, { 3, 3}, { 3, 5}, { 1, 7}},
- {{ 1, 1}, { 4, 4}, { 4, 7}, { 1, 10}},
- {{ 1, 1}, { 5, 5}, { 8, 8}, { 9, 9}},
- {{ 1, 1}, { 4, 4}, { 7, 4}, { 10, 1}},
- {{ 1, 1}, { 3, 3}, { 5, 3}, { 7, 1}},
- {{ 1, 1}, { 2, 2}, { 3, 2}, { 4, 1}},
-};
-
-static const size_t cubicCount = sizeof(cubics) / sizeof(cubics[0]);
-
-struct segment {
- SkPath::Verb verb;
- SkPoint pts[4];
-};
-
-static const segment segmentTest1[] = {
- {SkPath::kLine_Verb, {{2, 1}, {1, 0} }},
- {SkPath::kQuad_Verb, {{2, 1}, {1, 0}, {0, 0}}},
- {SkPath::kQuad_Verb, {{2, 1}, {3, 2}, {2, 3}}},
- {SkPath::kLine_Verb, {{2, 1}, {3, 2} }},
- {SkPath::kMove_Verb }
-};
-
-static const segment segmentTest2[] = {
- {SkPath::kLine_Verb, {{1, 0}, {0, 0} }},
- {SkPath::kQuad_Verb, {{1, 0}, {1.89897954f, 0.898979485f}, {2.39387703f, 1.59591794f}}},
- {SkPath::kLine_Verb, {{1, 0}, {3, 2} }},
- {SkPath::kMove_Verb }
-};
-
-static const segment segmentTest3[] = {
- {SkPath::kQuad_Verb, {{0, 0}, {2, 0}, {0, 1}}},
- {SkPath::kQuad_Verb, {{0, 0}, {1, 0}, {0, 1}}},
- {SkPath::kMove_Verb }
-};
-
-static const segment* segmentTests[] = {
- segmentTest3,
- segmentTest2,
- segmentTest1,
-};
-
-static const size_t segmentTestCount = sizeof(segmentTests) / sizeof(segmentTests[0]);
-
-static void testSegments(bool testFlat) {
- for (size_t testIndex = 0; testIndex < segmentTestCount; ++testIndex) {
- const segment* segPtr = segmentTests[testIndex];
- SimplifyAngleTest::Angle lesser, greater;
- int index = 0;
- do {
- int next = index + 1;
- SkTDArray<SimplifyAngleTest::Span> dummy;
- lesser.set(segPtr[index].pts, segPtr[index].verb, NULL, index, next, dummy);
- if (segPtr[next].verb == SkPath::kMove_Verb) {
- break;
- }
- greater.set(segPtr[next].pts, segPtr[next].verb, NULL, index, next, dummy);
- bool result = lesser < greater;
- SkASSERT(result);
- index = next;
- } while (true);
- }
-}
-
-static void testLines(bool testFlat) {
- // create angles in a circle
- SkTDArray<SimplifyAngleTest::Angle> angles;
- SkTDArray<SimplifyAngleTest::Angle* > angleList;
- SkTDArray<double> arcTans;
- size_t x;
- for (x = 0; x < lineCount; ++x) {
- SimplifyAngleTest::Angle* angle = angles.append();
- SkTDArray<SimplifyAngleTest::Span> dummy;
- angle->set(lines[x], SkPath::kLine_Verb, 0, x, x + 1, dummy);
- double arcTan = atan2(lines[x][0].fX - lines[x][1].fX,
- lines[x][0].fY - lines[x][1].fY);
- arcTans.push(arcTan);
- }
- for (x = 0; x < lineCount; ++x) {
- angleList.push(&angles[x]);
- }
- QSort<SimplifyAngleTest::Angle>(angleList.begin(), angleList.end() - 1);
- bool first = true;
- bool wrap = false;
- double base, last;
- for (size_t x = 0; x < lineCount; ++x) {
- const SimplifyAngleTest::Angle* angle = angleList[x];
- int span = angle->start();
-// SkDebugf("%s [%d] %1.9g (%1.9g,%1.9g %1.9g,%1.9g)\n", __FUNCTION__,
-// span, arcTans[span], lines[span][0].fX, lines[span][0].fY,
-// lines[span][1].fX, lines[span][1].fY);
- if (first) {
- base = last = arcTans[span];
- first = false;
- continue;
- }
- if (last < arcTans[span]) {
- last = arcTans[span];
- continue;
- }
- if (!wrap) {
- if (base < arcTans[span]) {
- SkDebugf("%s !wrap [%d] %g\n", __FUNCTION__, span, arcTans[span]);
- SkASSERT(0);
- }
- last = arcTans[span];
- wrap = true;
- continue;
- }
- SkDebugf("%s wrap [%d] %g\n", __FUNCTION__, span, arcTans[span]);
- SkASSERT(0);
- }
-}
-
-static void testQuads(bool testFlat) {
- SkTDArray<SimplifyAngleTest::Angle> angles;
- SkTDArray<SimplifyAngleTest::Angle* > angleList;
- size_t x;
- for (x = 0; x < quadCount; ++x) {
- SimplifyAngleTest::Angle* angle = angles.append();
- SkTDArray<SimplifyAngleTest::Span> dummy;
- angle->set(quads[x], SkPath::kQuad_Verb, 0, x, x + 1, dummy);
- }
- for (x = 0; x < quadCount; ++x) {
- angleList.push(&angles[x]);
- }
- QSort<SimplifyAngleTest::Angle>(angleList.begin(), angleList.end() - 1);
- for (size_t x = 0; x < quadCount; ++x) {
- *angleList[x] < *angleList[x + 1];
- SkASSERT(x == quadCount - 1 || *angleList[x] < *angleList[x + 1]);
- const SimplifyAngleTest::Angle* angle = angleList[x];
- if ((int) x != angle->start()) {
- SkDebugf("%s [%d] [%d]\n", __FUNCTION__, x, angle->start());
- SkASSERT(0);
- }
- }
-}
-
-static void testCubics(bool testFlat) {
- SkTDArray<SimplifyAngleTest::Angle> angles;
- SkTDArray<SimplifyAngleTest::Angle* > angleList;
- for (size_t x = 0; x < cubicCount; ++x) {
- SimplifyAngleTest::Angle* angle = angles.append();
- SkTDArray<SimplifyAngleTest::Span> dummy;
- angle->set(cubics[x], SkPath::kCubic_Verb, 0, x, x + 1, dummy);
- angleList.push(angle);
- }
- QSort<SimplifyAngleTest::Angle>(angleList.begin(), angleList.end() - 1);
- for (size_t x = 0; x < cubicCount; ++x) {
- const SimplifyAngleTest::Angle* angle = angleList[x];
- if ((int) x != angle->start()) {
- SkDebugf("%s [%d] [%d]\n", __FUNCTION__, x, angle->start());
- SkASSERT(0);
- }
- }
-}
-
-struct segmentWithT {
- SkPath::Verb verb;
- SkPoint pts[4];
- double ts[2];
-};
-
-
-static const segmentWithT oneOffTest1[] = {
- {SkPath::kQuad_Verb, {{391.653534f, 183.286819f}, {391.653534f, 157.724487f}, {405.469604f, 141.372879f}},
- {0.62346946335026932, 0.62344389027237135}},
- {SkPath::kQuad_Verb, {{399.365234f, 171.695801f}, {399.365234f, 140.337967f}, {375.976227f, 140.337967f}},
- {0.31638302676995866, 0.31637992418411398}},
- {SkPath::kMove_Verb }
-};
-
-static const segmentWithT oneOffTest2[] = {
- {SkPath::kQuad_Verb, {{399.070374f, 151.722f}, {391.101532f, 163.002533f}, {391.101532f, 182.665863f}},
- {0.13793711854916513, 0.13790171160614006}},
- {SkPath::kQuad_Verb, {{391.653534f, 183.286819f}, {391.653534f, 157.724487f}, {405.469604f, 141.372879f}},
- {0.62344389027237135, 0.62346946335026932}},
- {SkPath::kMove_Verb }
-};
-
-static const segmentWithT oneOffTest3[] = {
- {SkPath::kQuad_Verb, {{399.365234f, 171.695801f}, {399.365234f, 140.337967f}, {375.976227f, 140.337967f}},
- {0.31637992418411398, 0.31638302676995866, }},
- {SkPath::kQuad_Verb, {{399.070374f, 151.722f}, {391.101532f, 163.002533f}, {391.101532f, 182.665863f}},
- {0.13790171160614006, 0.13793711854916513}},
- {SkPath::kMove_Verb }
-};
-
-static const segmentWithT oneOffTest4[] = {
- {SkPath::kCubic_Verb, {{1,2}, {1,3}, {1,0}, {5,3}}, {0.134792, 0}},
- {SkPath::kCubic_Verb, {{0,1}, {3,5}, {2,1}, {3,1}}, {0.134792094, 0}},
- {SkPath::kCubic_Verb, {{0,1}, {3,5}, {2,1}, {3,1}}, {0.134792094, 0.551812363}},
- {SkPath::kCubic_Verb, {{1,2}, {1,3}, {1,0}, {5,3}}, {0.134792, 0.333333333}},
- {SkPath::kMove_Verb }
-};
-
-static const segmentWithT* oneOffTests[] = {
- oneOffTest1,
- oneOffTest2,
- oneOffTest3,
- oneOffTest4,
-};
-
-static const size_t oneOffTestCount = sizeof(oneOffTests) / sizeof(oneOffTests[0]);
-
-static void oneOffTest(bool testFlat) {
- for (size_t testIndex = 0; testIndex < oneOffTestCount; ++testIndex) {
- const segmentWithT* segPtr = oneOffTests[testIndex];
- SimplifyAngleTest::Angle lesser, greater;
- int index = 0;
- do {
- int next = index + 1;
- SkTDArray<SimplifyAngleTest::Span> dummy; // FIXME
- lesser.set(segPtr[index].pts, segPtr[index].verb, 0, index, next, dummy); // FIXME: segPtr[index].ts[0], segPtr[index].ts[1]);
- if (segPtr[next].verb == SkPath::kMove_Verb) {
- break;
- }
- greater.set(segPtr[next].pts, segPtr[next].verb, 0, index, next, dummy); // FIXME: segPtr[next].ts[0], segPtr[next].ts[1]);
- bool result = lesser < greater;
- SkASSERT(result);
- index = next;
- } while (true);
- }
- SkDebugf("%s finished\n", __FUNCTION__);
-}
-
-#if 0 // seems too complicated for this to be useful (didn't finish writing/debugging this)
-// this (trys to) take a pair of curves, construct segments/spans, and verify that they sort correctly
-static void oneOffTestNew() {
- const segmentWithT* segPtr = oneOffTest4;
- SimplifyAngleTest::Segment segOne, segTwo;
- segOne.init(segPtr[0].pts, segPtr[0].verb, false, false);
- segTwo.init(segPtr[1].pts, segPtr[1].verb, false, false);
- int index = 0;
- do {
- int next = index + 1;
- if (segPtr[index].verb == SkPath::kMove_Verb) {
- break;
- }
- SkPoint sub[4];
- (*SegmentSubDivide[segPtr[index].verb])(segPtr[index].pts, segPtr[index].ts[0],
- segPtr[index].ts[1], sub);
- if (memcmp(segPtr[index].pts, segPtr[0].pts, sizeof(SkPoint) * (segPtr[index].verb + 1) == 0) {
- segOne.addT(&segTwo, sub[0], segPtr[index].ts[0]);
- segOne.addT(&segTwo, sub[segPtr[index].verb], segPtr[index].ts[1]);
- } else {
- segTwo.addT(&segOne, sub[0], segPtr[index].ts[0]);
- segTwo.addT(&v, sub[segPtr[index].verb], segPtr[index].ts[1]);
- }
- } while (true);
- SimplifyAngleTest::Angle lesser, greater;
- do {
- int next = index + 1;
- if (segPtr[next].verb == SkPath::kMove_Verb) {
- break;
- }
- SkPoint one[4], two[4];
- bool use1 = memcmp(segPtr[index].pts, segPtr[0].pts, sizeof(SkPoint) * (segPtr[index].verb + 1) == 0;
- lesser.set(segPtr[index].pts, segPtr[index].verb, use1 ? &segOne : &segTwo, index, next, dummy);
- use1 = memcmp(segPtr[next].pts, segPtr[0].pts, sizeof(SkPoint) * (segPtr[next].verb + 1) == 0;
- greater.set(segPtr[next].pts, segPtr[next].verb, use1 ? &segOne : &segTwo, index, next, dummy);
- bool result = lesser < greater;
- SkASSERT(result);
- index = next;
- } while (true);
- SkDebugf("%s finished\n", __FUNCTION__);
-}
-#endif
-
-static void (*tests[])(bool) = {
- oneOffTest,
- testSegments,
- testLines,
- testQuads,
- testCubics
-};
-
-static const size_t testCount = sizeof(tests) / sizeof(tests[0]);
-
-static void (*firstTest)(bool) = 0;
-static bool skipAll = false;
-
-void SimplifyAngle_Test() {
- if (skipAll) {
- return;
- }
- size_t index = 0;
- if (firstTest) {
- while (index < testCount && tests[index] != firstTest) {
- ++index;
- }
- }
- bool firstTestComplete = false;
- for ( ; index < testCount; ++index) {
- (*tests[index])(false); // set to true to exercise setFlat
- firstTestComplete = true;
- }
-}
diff --git a/experimental/Intersection/SimplifyFindNext_Test.cpp b/experimental/Intersection/SimplifyFindNext_Test.cpp
deleted file mode 100644
index 0a04747bbb..0000000000
--- a/experimental/Intersection/SimplifyFindNext_Test.cpp
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#define DEBUG_TEST 1
-
-#include "Simplify.h"
-
-namespace SimplifyFindNextTest {
-
-#include "Simplify.cpp"
-
-} // end of SimplifyFindNextTest namespace
-
-#include "Intersection_Tests.h"
-
-static const SimplifyFindNextTest::Segment* testCommon(
- int contourWinding, int spanWinding, int startIndex, int endIndex,
- SkTArray<SimplifyFindNextTest::Contour>& contours) {
- SkTDArray<SimplifyFindNextTest::Contour*> contourList;
- makeContourList(contours, contourList, false, false);
- addIntersectTs(contourList[0], contourList[0]);
- if (contours.count() > 1) {
- SkASSERT(contours.count() == 2);
- addIntersectTs(contourList[0], contourList[1]);
- addIntersectTs(contourList[1], contourList[1]);
- }
- fixOtherTIndex(contourList);
- SimplifyFindNextTest::Segment& segment = contours[0].debugSegments()[0];
- SkPoint pts[2];
- pts[0] = segment.xyAtT(&segment.span(endIndex));
- int nextStart = startIndex;
- int nextEnd = endIndex;
- SkTDArray<SimplifyFindNextTest::Span*> chaseArray;
- bool unsortable = false;
- SimplifyFindNextTest::Segment* next = segment.findNextWinding(chaseArray,
- nextStart, nextEnd, unsortable);
- pts[1] = next->xyAtT(&next->span(nextStart));
- SkASSERT(pts[0] == pts[1]);
- return next;
-}
-
-static void test(const SkPath& path) {
- SkTArray<SimplifyFindNextTest::Contour> contours;
- SimplifyFindNextTest::EdgeBuilder builder(path, contours);
- int contourWinding = 0;
- int spanWinding = 1;
- int start = 0;
- int end = 1;
- testCommon(contourWinding, spanWinding, start, end, contours);
-}
-
-static void test(const SkPath& path, int start, int end) {
- SkTArray<SimplifyFindNextTest::Contour> contours;
- SimplifyFindNextTest::EdgeBuilder builder(path, contours);
- int contourWinding = 0;
- int spanWinding = 1;
- testCommon(contourWinding, spanWinding, start, end, contours);
-}
-
-static void testLine1() {
- SkPath path;
- path.moveTo(2,0);
- path.lineTo(1,1);
- path.lineTo(0,0);
- path.close();
- test(path);
-}
-
-static void addInnerCWTriangle(SkPath& path) {
- path.moveTo(3,0);
- path.lineTo(4,1);
- path.lineTo(2,1);
- path.close();
-}
-
-#if DEBUG_UNUSED
-static void addInnerCCWTriangle(SkPath& path) {
- path.moveTo(3,0);
- path.lineTo(2,1);
- path.lineTo(4,1);
- path.close();
-}
-#endif
-
-static void addOuterCWTriangle(SkPath& path) {
- path.moveTo(3,0);
- path.lineTo(6,2);
- path.lineTo(0,2);
- path.close();
-}
-
-#if DEBUG_UNUSED
-static void addOuterCCWTriangle(SkPath& path) {
- path.moveTo(3,0);
- path.lineTo(0,2);
- path.lineTo(6,2);
- path.close();
-}
-#endif
-
-static void testLine2() {
- SkPath path;
- addInnerCWTriangle(path);
- addOuterCWTriangle(path);
- test(path, 0, 3);
-}
-
-static void testLine3() {
- SkPath path;
- addInnerCWTriangle(path);
- addOuterCWTriangle(path);
- test(path, 3, 0);
-}
-
-static void testLine4() {
- SkPath path;
- addInnerCWTriangle(path);
- addOuterCWTriangle(path);
- test(path, 3, 2);
-}
-
-static void (*tests[])() = {
- testLine1,
- testLine2,
- testLine3,
- testLine4,
-};
-
-static const size_t testCount = sizeof(tests) / sizeof(tests[0]);
-
-static void (*firstTest)() = 0;
-static bool skipAll = false;
-
-void SimplifyFindNext_Test() {
- if (skipAll) {
- return;
- }
- size_t index = 0;
- if (firstTest) {
- while (index < testCount && tests[index] != firstTest) {
- ++index;
- }
- }
- bool firstTestComplete = false;
- for ( ; index < testCount; ++index) {
- (*tests[index])();
- firstTestComplete = true;
- }
-}
diff --git a/experimental/Intersection/SimplifyFindTop_Test.cpp b/experimental/Intersection/SimplifyFindTop_Test.cpp
deleted file mode 100644
index 5f267503a9..0000000000
--- a/experimental/Intersection/SimplifyFindTop_Test.cpp
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "Simplify.h"
-
-namespace SimplifyFindTopTest {
-
-#include "Simplify.cpp"
-
-} // end of SimplifyFindTopTest namespace
-
-#include "Intersection_Tests.h"
-
-static const SimplifyFindTopTest::Segment* testCommon(
- SkTArray<SimplifyFindTopTest::Contour>& contours,
- int& index, int& end) {
- SkTDArray<SimplifyFindTopTest::Contour*> contourList;
- makeContourList(contours, contourList, false, false);
- addIntersectTs(contourList[0], contourList[0]);
- if (contours.count() > 1) {
- SkASSERT(contours.count() == 2);
- addIntersectTs(contourList[0], contourList[1]);
- addIntersectTs(contourList[1], contourList[1]);
- }
- fixOtherTIndex(contourList);
-#if SORTABLE_CONTOURS // old way
- SimplifyFindTopTest::Segment* topStart = findTopContour(contourList);
- const SimplifyFindTopTest::Segment* topSegment = topStart->findTop(index,
- end);
-#else
- SkPoint bestXY = {SK_ScalarMin, SK_ScalarMin};
- bool done, unsortable = false;
- const SimplifyFindTopTest::Segment* topSegment =
- findSortableTop(contourList, index, end, bestXY, unsortable, done, true);
-#endif
- return topSegment;
-}
-
-static void test(const SkPath& path) {
- SkTArray<SimplifyFindTopTest::Contour> contours;
- SimplifyFindTopTest::EdgeBuilder builder(path, contours);
- int index, end;
- testCommon(contours, index, end);
- SkASSERT(index + 1 == end);
-}
-
-static void test(const SkPath& path, SkScalar x1, SkScalar y1,
- SkScalar x2, SkScalar y2) {
- SkTArray<SimplifyFindTopTest::Contour> contours;
- SimplifyFindTopTest::EdgeBuilder builder(path, contours);
- int index, end;
- const SimplifyFindTopTest::Segment* topSegment =
- testCommon(contours, index, end);
- SkPoint pts[2];
- double firstT = topSegment->t(index);
- pts[0] = topSegment->xyAtT(&topSegment->span(index));
- int direction = index < end ? 1 : -1;
- do {
- index += direction;
- double nextT = topSegment->t(index);
- if (nextT == firstT) {
- continue;
- }
- pts[1] = topSegment->xyAtT(&topSegment->span(index));
- if (pts[0] != pts[1]) {
- break;
- }
- } while (true);
- SkASSERT(pts[0].fX == x1);
- SkASSERT(pts[0].fY == y1);
- SkASSERT(pts[1].fX == x2);
- SkASSERT(pts[1].fY == y2);
-}
-
-static void testLine1() {
- SkPath path;
- path.moveTo(2,0);
- path.lineTo(1,1);
- path.lineTo(0,0);
- path.close();
- test(path);
-}
-
-static void addInnerCWTriangle(SkPath& path) {
- path.moveTo(3,0);
- path.lineTo(4,1);
- path.lineTo(2,1);
- path.close();
-}
-
-static void addInnerCCWTriangle(SkPath& path) {
- path.moveTo(3,0);
- path.lineTo(2,1);
- path.lineTo(4,1);
- path.close();
-}
-
-static void addOuterCWTriangle(SkPath& path) {
- path.moveTo(3,0);
- path.lineTo(6,2);
- path.lineTo(0,2);
- path.close();
-}
-
-static void addOuterCCWTriangle(SkPath& path) {
- path.moveTo(3,0);
- path.lineTo(0,2);
- path.lineTo(6,2);
- path.close();
-}
-
-static void testLine2() {
- SkPath path;
- addInnerCWTriangle(path);
- addOuterCWTriangle(path);
- test(path, 0, 2, 3, 0);
-}
-
-static void testLine3() {
- SkPath path;
- addOuterCWTriangle(path);
- addInnerCWTriangle(path);
- test(path, 0, 2, 3, 0);
-}
-
-static void testLine4() {
- SkPath path;
- addInnerCCWTriangle(path);
- addOuterCWTriangle(path);
- test(path, 0, 2, 3, 0);
-}
-
-static void testLine5() {
- SkPath path;
- addOuterCWTriangle(path);
- addInnerCCWTriangle(path);
- test(path, 0, 2, 3, 0);
-}
-
-static void testLine6() {
- SkPath path;
- addInnerCWTriangle(path);
- addOuterCCWTriangle(path);
- test(path, 0, 2, 3, 0);
-}
-
-static void testLine7() {
- SkPath path;
- addOuterCCWTriangle(path);
- addInnerCWTriangle(path);
- test(path, 0, 2, 3, 0);
-}
-
-static void testLine8() {
- SkPath path;
- addInnerCCWTriangle(path);
- addOuterCCWTriangle(path);
- test(path, 0, 2, 3, 0);
-}
-
-static void testLine9() {
- SkPath path;
- addOuterCCWTriangle(path);
- addInnerCCWTriangle(path);
- test(path, 0, 2, 3, 0);
-}
-
-static void testQuads() {
- SkPath path;
- path.moveTo(2,0);
- path.quadTo(1,1, 0,0);
- path.close();
- test(path);
-}
-
-static void testCubics() {
- SkPath path;
- path.moveTo(2,0);
- path.cubicTo(2,3, 1,1, 0,0);
- path.close();
- test(path);
-}
-
-static void (*tests[])() = {
- testLine1,
- testLine2,
- testLine3,
- testLine4,
- testLine5,
- testLine6,
- testLine7,
- testLine8,
- testLine9,
- testQuads,
- testCubics
-};
-
-static const size_t testCount = sizeof(tests) / sizeof(tests[0]);
-
-static void (*firstTest)() = 0;
-static bool skipAll = false;
-
-void SimplifyFindTop_Test() {
- if (skipAll) {
- return;
- }
- size_t index = 0;
- if (firstTest) {
- while (index < testCount && tests[index] != firstTest) {
- ++index;
- }
- }
- bool firstTestComplete = false;
- for ( ; index < testCount; ++index) {
- (*tests[index])();
- firstTestComplete = true;
- }
-}
diff --git a/experimental/Intersection/SimplifyNew_Test.cpp b/experimental/Intersection/SimplifyNew_Test.cpp
deleted file mode 100644
index dc04cadc26..0000000000
--- a/experimental/Intersection/SimplifyNew_Test.cpp
+++ /dev/null
@@ -1,5194 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "EdgeWalker_Test.h"
-#include "Intersection_Tests.h"
-#include "ShapeOps.h"
-
-#define TEST(name) { name, #name }
-
-static void testLine1() {
- SkPath path;
- path.moveTo(2,0);
- path.lineTo(1,1);
- path.lineTo(0,0);
- path.close();
- testSimplifyx(path);
-}
-
-static void testLine1x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(2,0);
- path.lineTo(1,1);
- path.lineTo(0,0);
- path.close();
- testSimplifyx(path);
-}
-
-static void addInnerCWTriangle(SkPath& path) {
- path.moveTo(3,0);
- path.lineTo(4,1);
- path.lineTo(2,1);
- path.close();
-}
-
-static void addInnerCCWTriangle(SkPath& path) {
- path.moveTo(3,0);
- path.lineTo(2,1);
- path.lineTo(4,1);
- path.close();
-}
-
-static void addOuterCWTriangle(SkPath& path) {
- path.moveTo(3,0);
- path.lineTo(6,2);
- path.lineTo(0,2);
- path.close();
-}
-
-static void addOuterCCWTriangle(SkPath& path) {
- path.moveTo(3,0);
- path.lineTo(0,2);
- path.lineTo(6,2);
- path.close();
-}
-
-static void testLine2() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- addInnerCWTriangle(path);
- addOuterCWTriangle(path);
- testSimplifyx(path);
-}
-
-static void testLine2x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- addInnerCWTriangle(path);
- addOuterCWTriangle(path);
- testSimplifyx(path);
-}
-
-static void testLine3() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- addInnerCCWTriangle(path);
- addOuterCWTriangle(path);
- testSimplifyx(path);
-}
-
-static void testLine3x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- addInnerCCWTriangle(path);
- addOuterCWTriangle(path);
- testSimplifyx(path);
-}
-
-static void testLine3a() {
- SkPath path;
- addInnerCWTriangle(path);
- addOuterCCWTriangle(path);
- testSimplifyx(path);
-}
-
-static void testLine3ax() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- addInnerCWTriangle(path);
- addOuterCCWTriangle(path);
- testSimplifyx(path);
-}
-
-static void testLine3b() {
- SkPath path;
- addInnerCCWTriangle(path);
- addOuterCCWTriangle(path);
- testSimplifyx(path);
-}
-
-static void testLine3bx() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- addInnerCCWTriangle(path);
- addOuterCCWTriangle(path);
- testSimplifyx(path);
-}
-
-static void testLine4() {
- SkPath path;
- addOuterCCWTriangle(path);
- addOuterCWTriangle(path);
- testSimplifyx(path);
-}
-
-static void testLine4x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- addOuterCCWTriangle(path);
- addOuterCWTriangle(path);
- testSimplifyx(path);
-}
-
-static void testLine5() {
- SkPath path;
- addOuterCWTriangle(path);
- addOuterCWTriangle(path);
- testSimplifyx(path);
-}
-
-static void testLine5x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- addOuterCWTriangle(path);
- addOuterCWTriangle(path);
- testSimplifyx(path);
-}
-
-static void testLine6() {
- SkPath path;
- path.moveTo(0,0);
- path.lineTo(4,0);
- path.lineTo(2,2);
- path.close();
- path.moveTo(2,0);
- path.lineTo(6,0);
- path.lineTo(4,2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testLine6x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0,0);
- path.lineTo(4,0);
- path.lineTo(2,2);
- path.close();
- path.moveTo(2,0);
- path.lineTo(6,0);
- path.lineTo(4,2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testLine7() {
- SkPath path;
- path.moveTo(0,0);
- path.lineTo(4,0);
- path.lineTo(2,2);
- path.close();
- path.moveTo(6,0);
- path.lineTo(2,0);
- path.lineTo(4,2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testLine7x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0,0);
- path.lineTo(4,0);
- path.lineTo(2,2);
- path.close();
- path.moveTo(6,0);
- path.lineTo(2,0);
- path.lineTo(4,2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testLine7a() {
- SkPath path;
- path.moveTo(0,0);
- path.lineTo(4,0);
- path.lineTo(2,2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testLine7ax() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0,0);
- path.lineTo(4,0);
- path.lineTo(2,2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testLine7b() {
- SkPath path;
- path.moveTo(0,0);
- path.lineTo(4,0);
- path.close();
- path.moveTo(6,0);
- path.lineTo(2,0);
- path.lineTo(4,2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testLine7bx() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0,0);
- path.lineTo(4,0);
- path.close();
- path.moveTo(6,0);
- path.lineTo(2,0);
- path.lineTo(4,2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testLine8() {
- SkPath path;
- path.moveTo(0,4);
- path.lineTo(4,4);
- path.lineTo(2,2);
- path.close();
- path.moveTo(2,4);
- path.lineTo(6,4);
- path.lineTo(4,2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testLine8x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0,4);
- path.lineTo(4,4);
- path.lineTo(2,2);
- path.close();
- path.moveTo(2,4);
- path.lineTo(6,4);
- path.lineTo(4,2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testLine9() {
- SkPath path;
- path.moveTo(0,4);
- path.lineTo(4,4);
- path.lineTo(2,2);
- path.close();
- path.moveTo(6,4);
- path.lineTo(2,4);
- path.lineTo(4,2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testLine9x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0,4);
- path.lineTo(4,4);
- path.lineTo(2,2);
- path.close();
- path.moveTo(6,4);
- path.lineTo(2,4);
- path.lineTo(4,2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testLine10() {
- SkPath path;
- path.moveTo(0,4);
- path.lineTo(4,4);
- path.lineTo(2,2);
- path.close();
- path.moveTo(2,1);
- path.lineTo(3,4);
- path.lineTo(6,1);
- path.close();
- testSimplifyx(path);
-}
-
-static void testLine10x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0,4);
- path.lineTo(4,4);
- path.lineTo(2,2);
- path.close();
- path.moveTo(2,1);
- path.lineTo(3,4);
- path.lineTo(6,1);
- path.close();
- testSimplifyx(path);
-}
-
-static void testLine10a() {
- SkPath path;
- path.moveTo(0,4);
- path.lineTo(8,4);
- path.lineTo(4,0);
- path.close();
- path.moveTo(2,2);
- path.lineTo(3,3);
- path.lineTo(4,2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testLine10ax() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0,4);
- path.lineTo(8,4);
- path.lineTo(4,0);
- path.close();
- path.moveTo(2,2);
- path.lineTo(3,3);
- path.lineTo(4,2);
- path.close();
- testSimplifyx(path);
-}
-
-static void addCWContainer(SkPath& path) {
- path.moveTo(6,4);
- path.lineTo(0,4);
- path.lineTo(3,1);
- path.close();
-}
-
-static void addCCWContainer(SkPath& path) {
- path.moveTo(0,4);
- path.lineTo(6,4);
- path.lineTo(3,1);
- path.close();
-}
-
-static void addCWContents(SkPath& path) {
- path.moveTo(2,3);
- path.lineTo(3,2);
- path.lineTo(4,3);
- path.close();
-}
-
-static void addCCWContents(SkPath& path) {
- path.moveTo(3,2);
- path.lineTo(2,3);
- path.lineTo(4,3);
- path.close();
-}
-
-static void testLine11() {
- SkPath path;
- addCWContainer(path);
- addCWContents(path);
- testSimplifyx(path);
-}
-
-static void testLine11x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- addCWContainer(path);
- addCWContents(path);
- testSimplifyx(path);
-}
-
-static void testLine12() {
- SkPath path;
- addCCWContainer(path);
- addCWContents(path);
- testSimplifyx(path);
-}
-
-static void testLine12x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- addCCWContainer(path);
- addCWContents(path);
- testSimplifyx(path);
-}
-
-static void testLine13() {
- SkPath path;
- addCWContainer(path);
- addCCWContents(path);
- testSimplifyx(path);
-}
-
-static void testLine13x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- addCWContainer(path);
- addCCWContents(path);
- testSimplifyx(path);
-}
-
-static void testLine14() {
- SkPath path;
- addCCWContainer(path);
- addCCWContents(path);
- testSimplifyx(path);
-}
-
-static void testLine14x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- addCCWContainer(path);
- addCCWContents(path);
- testSimplifyx(path);
-}
-
-static void testLine15() {
- SkPath path;
- path.addRect(0, 0, 9, 9, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine15x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 9, 9, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine16() {
- SkPath path;
- path.addRect(0, 0, 12, 12, SkPath::kCW_Direction);
- path.addRect(0, 4, 9, 9, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine16x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 12, 12, SkPath::kCW_Direction);
- path.addRect(0, 4, 9, 9, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine17() {
- SkPath path;
- path.addRect(0, 0, 12, 12, SkPath::kCW_Direction);
- path.addRect(4, 12, 13, 13, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine17x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 12, 12, SkPath::kCW_Direction);
- path.addRect(4, 12, 13, 13, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine18() {
- SkPath path;
- path.addRect(0, 0, 12, 12, SkPath::kCW_Direction);
- path.addRect(12, 4, 21, 21, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine18x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 12, 12, SkPath::kCW_Direction);
- path.addRect(12, 4, 21, 21, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine19() {
- SkPath path;
- path.addRect(0, 0, 12, 12, SkPath::kCW_Direction);
- path.addRect(12, 16, 21, 21, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine19x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 12, 12, SkPath::kCW_Direction);
- path.addRect(12, 16, 21, 21, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine20() {
- SkPath path;
- path.addRect(0, 12, 12, 12, SkPath::kCW_Direction);
- path.addRect(0, 12, 9, 9, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine20x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 12, 12, 12, SkPath::kCW_Direction);
- path.addRect(0, 12, 9, 9, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine21() {
- SkPath path;
- path.addRect(0, 12, 12, 12, SkPath::kCW_Direction);
- path.addRect(0, 16, 9, 9, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine21x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 12, 12, 12, SkPath::kCW_Direction);
- path.addRect(0, 16, 9, 9, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine22() {
- SkPath path;
- path.addRect(0, 12, 12, 12, SkPath::kCW_Direction);
- path.addRect(4, 12, 13, 13, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine22x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 12, 12, 12, SkPath::kCW_Direction);
- path.addRect(4, 12, 13, 13, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine23() {
- SkPath path;
- path.addRect(0, 12, 12, 12, SkPath::kCW_Direction);
- path.addRect(12, 0, 21, 21, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine23x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 12, 12, 12, SkPath::kCW_Direction);
- path.addRect(12, 0, 21, 21, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine24a() {
- SkPath path;
- path.moveTo(2,0);
- path.lineTo(4,4);
- path.lineTo(0,4);
- path.close();
- path.moveTo(2,0);
- path.lineTo(1,2);
- path.lineTo(2,2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testLine24ax() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(2,0);
- path.lineTo(4,4);
- path.lineTo(0,4);
- path.close();
- path.moveTo(2,0);
- path.lineTo(1,2);
- path.lineTo(2,2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testLine24() {
- SkPath path;
- path.addRect(0, 18, 12, 12, SkPath::kCW_Direction);
- path.addRect(4, 12, 13, 13, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine24x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 18, 12, 12, SkPath::kCW_Direction);
- path.addRect(4, 12, 13, 13, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine25() {
- SkPath path;
- path.addRect(0, 6, 12, 12, SkPath::kCW_Direction);
- path.addRect(12, 0, 21, 21, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine25x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 6, 12, 12, SkPath::kCW_Direction);
- path.addRect(12, 0, 21, 21, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine26() {
- SkPath path;
- path.addRect(0, 18, 12, 12, SkPath::kCW_Direction);
- path.addRect(0, 12, 9, 9, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine26x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 18, 12, 12, SkPath::kCW_Direction);
- path.addRect(0, 12, 9, 9, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine27() {
- SkPath path;
- path.addRect(0, 18, 12, 12, SkPath::kCW_Direction);
- path.addRect(12, 8, 21, 21, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine27x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 18, 12, 12, SkPath::kCW_Direction);
- path.addRect(12, 8, 21, 21, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine28() {
- SkPath path;
- path.addRect(0, 6, 12, 12, SkPath::kCW_Direction);
- path.addRect(0, 0, 9, 9, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine28x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 6, 12, 12, SkPath::kCW_Direction);
- path.addRect(0, 0, 9, 9, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine29() {
- SkPath path;
- path.addRect(0, 18, 12, 12, SkPath::kCW_Direction);
- path.addRect(12, 12, 21, 21, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine29x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 18, 12, 12, SkPath::kCW_Direction);
- path.addRect(12, 12, 21, 21, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine30() {
- SkPath path;
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 0, 12, 12, SkPath::kCW_Direction);
- path.addRect(4, 4, 13, 13, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine30x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 0, 12, 12, SkPath::kCW_Direction);
- path.addRect(4, 4, 13, 13, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine31() {
- SkPath path;
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 0, 12, 12, SkPath::kCW_Direction);
- path.addRect(0, 4, 9, 9, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine31x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 0, 12, 12, SkPath::kCW_Direction);
- path.addRect(0, 4, 9, 9, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine32() {
- SkPath path;
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 0, 12, 12, SkPath::kCW_Direction);
- path.addRect(4, 12, 13, 13, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine32x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 0, 12, 12, SkPath::kCW_Direction);
- path.addRect(4, 12, 13, 13, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine33() {
- SkPath path;
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 0, 12, 12, SkPath::kCW_Direction);
- path.addRect(4, 16, 13, 13, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine33x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 0, 12, 12, SkPath::kCW_Direction);
- path.addRect(4, 16, 13, 13, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine34() {
- SkPath path;
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 6, 12, 12, SkPath::kCW_Direction);
- path.addRect(4, 12, 13, 13, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine34x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 6, 12, 12, SkPath::kCW_Direction);
- path.addRect(4, 12, 13, 13, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine35() {
- SkPath path;
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(6, 0, 18, 18, SkPath::kCW_Direction);
- path.addRect(4, 16, 13, 13, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine35x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(6, 0, 18, 18, SkPath::kCW_Direction);
- path.addRect(4, 16, 13, 13, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine36() {
- SkPath path;
- path.addRect(0, 10, 20, 20, SkPath::kCW_Direction);
- path.addRect(6, 12, 18, 18, SkPath::kCW_Direction);
- path.addRect(4, 16, 13, 13, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine36x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 10, 20, 20, SkPath::kCW_Direction);
- path.addRect(6, 12, 18, 18, SkPath::kCW_Direction);
- path.addRect(4, 16, 13, 13, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine37() {
- SkPath path;
- path.addRect(0, 20, 20, 20, SkPath::kCW_Direction);
- path.addRect(18, 24, 30, 30, SkPath::kCW_Direction);
- path.addRect(0, 0, 9, 9, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine37x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 20, 20, 20, SkPath::kCW_Direction);
- path.addRect(18, 24, 30, 30, SkPath::kCW_Direction);
- path.addRect(0, 0, 9, 9, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine38() {
- SkPath path;
- path.addRect(10, 0, 30, 30, SkPath::kCW_Direction);
- path.addRect(6, 12, 18, 18, SkPath::kCW_Direction);
- path.addRect(12, 12, 21, 21, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine38x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(10, 0, 30, 30, SkPath::kCW_Direction);
- path.addRect(6, 12, 18, 18, SkPath::kCW_Direction);
- path.addRect(12, 12, 21, 21, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine40() {
- SkPath path;
- path.addRect(10, 0, 30, 30, SkPath::kCW_Direction);
- path.addRect(12, 18, 24, 24, SkPath::kCW_Direction);
- path.addRect(4, 16, 13, 13, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine40x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(10, 0, 30, 30, SkPath::kCW_Direction);
- path.addRect(12, 18, 24, 24, SkPath::kCW_Direction);
- path.addRect(4, 16, 13, 13, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine41() {
- SkPath path;
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(18, 24, 30, 30, SkPath::kCW_Direction);
- path.addRect(12, 0, 21, 21, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine41x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(18, 24, 30, 30, SkPath::kCW_Direction);
- path.addRect(12, 0, 21, 21, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine42() {
- SkPath path;
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 0, 12, 12, SkPath::kCW_Direction);
- path.addRect(8, 16, 17, 17, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine42x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 0, 12, 12, SkPath::kCW_Direction);
- path.addRect(8, 16, 17, 17, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine43() {
- SkPath path;
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(6, 24, 18, 18, SkPath::kCW_Direction);
- path.addRect(0, 32, 9, 36, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine43x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(6, 24, 18, 18, SkPath::kCW_Direction);
- path.addRect(0, 32, 9, 36, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine44() {
- SkPath path;
- path.addRect(10, 40, 30, 30, SkPath::kCW_Direction);
- path.addRect(18, 0, 30, 30, SkPath::kCW_Direction);
- path.addRect(18, 32, 27, 36, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine44x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(10, 40, 30, 30, SkPath::kCW_Direction);
- path.addRect(18, 0, 30, 30, SkPath::kCW_Direction);
- path.addRect(18, 32, 27, 36, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine45() {
- SkPath path;
- path.addRect(10, 0, 30, 30, SkPath::kCW_Direction);
- path.addRect(18, 0, 30, 30, SkPath::kCW_Direction);
- path.addRect(24, 32, 33, 36, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine45x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(10, 0, 30, 30, SkPath::kCW_Direction);
- path.addRect(18, 0, 30, 30, SkPath::kCW_Direction);
- path.addRect(24, 32, 33, 36, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine46() {
- SkPath path;
- path.addRect(10, 40, 30, 30, SkPath::kCW_Direction);
- path.addRect(24, 0, 36, 36, SkPath::kCW_Direction);
- path.addRect(24, 32, 33, 36, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine46x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(10, 40, 30, 30, SkPath::kCW_Direction);
- path.addRect(24, 0, 36, 36, SkPath::kCW_Direction);
- path.addRect(24, 32, 33, 36, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine47() {
- SkPath path;
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 0, 12, 12, SkPath::kCW_Direction);
- path.addRect(0, 0, 9, 9, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine47x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 0, 12, 12, SkPath::kCW_Direction);
- path.addRect(0, 0, 9, 9, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine48() {
- SkPath path;
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 6, 12, 12, SkPath::kCW_Direction);
- path.addRect(0, 0, 9, 9, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine48x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 6, 12, 12, SkPath::kCW_Direction);
- path.addRect(0, 0, 9, 9, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine49() {
- SkPath path;
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 0, 12, 12, SkPath::kCW_Direction);
- path.addRect(0, 0, 9, 9, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine49x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 0, 12, 12, SkPath::kCW_Direction);
- path.addRect(0, 0, 9, 9, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine50() {
- SkPath path;
- path.addRect(10, 30, 30, 30, SkPath::kCW_Direction);
- path.addRect(24, 20, 36, 30, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine50x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(10, 30, 30, 30, SkPath::kCW_Direction);
- path.addRect(24, 20, 36, 30, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine51() {
- SkPath path;
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 12, 12, 12, SkPath::kCW_Direction);
- path.addRect(4, 12, 13, 13, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine51x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 12, 12, 12, SkPath::kCW_Direction);
- path.addRect(4, 12, 13, 13, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine52() {
- SkPath path;
- path.addRect(0, 30, 20, 20, SkPath::kCW_Direction);
- path.addRect(6, 20, 18, 30, SkPath::kCW_Direction);
- path.addRect(32, 0, 36, 41, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine52x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 30, 20, 20, SkPath::kCW_Direction);
- path.addRect(6, 20, 18, 30, SkPath::kCW_Direction);
- path.addRect(32, 0, 36, 41, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine53() {
- SkPath path;
- path.addRect(10, 30, 30, 30, SkPath::kCW_Direction);
- path.addRect(12, 20, 24, 30, SkPath::kCW_Direction);
- path.addRect(12, 32, 21, 36, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine53x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(10, 30, 30, 30, SkPath::kCW_Direction);
- path.addRect(12, 20, 24, 30, SkPath::kCW_Direction);
- path.addRect(12, 32, 21, 36, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine54() {
- SkPath path;
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(6, 0, 18, 18, SkPath::kCW_Direction);
- path.addRect(8, 4, 17, 17, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine54x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(6, 0, 18, 18, SkPath::kCW_Direction);
- path.addRect(8, 4, 17, 17, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine55() {
- SkPath path;
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(6, 6, 18, 18, SkPath::kCW_Direction);
- path.addRect(4, 4, 13, 13, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine55x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(6, 6, 18, 18, SkPath::kCW_Direction);
- path.addRect(4, 4, 13, 13, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine56() {
- SkPath path;
- path.addRect(0, 20, 20, 20, SkPath::kCW_Direction);
- path.addRect(18, 20, 30, 30, SkPath::kCW_Direction);
- path.addRect(12, 0, 21, 21, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine56x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 20, 20, 20, SkPath::kCW_Direction);
- path.addRect(18, 20, 30, 30, SkPath::kCW_Direction);
- path.addRect(12, 0, 21, 21, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine57() {
- SkPath path;
- path.addRect(20, 0, 40, 40, SkPath::kCW_Direction);
- path.addRect(20, 0, 30, 40, SkPath::kCW_Direction);
- path.addRect(12, 0, 21, 21, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine57x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(20, 0, 40, 40, SkPath::kCW_Direction);
- path.addRect(20, 0, 30, 40, SkPath::kCW_Direction);
- path.addRect(12, 0, 21, 21, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine58() {
- SkPath path;
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 0, 12, 12, SkPath::kCCW_Direction);
- path.addRect(0, 12, 9, 9, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine58x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 0, 12, 12, SkPath::kCCW_Direction);
- path.addRect(0, 12, 9, 9, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine59() {
- SkPath path;
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(6, 6, 18, 18, SkPath::kCCW_Direction);
- path.addRect(4, 4, 13, 13, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine59x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(6, 6, 18, 18, SkPath::kCCW_Direction);
- path.addRect(4, 4, 13, 13, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine60() {
- SkPath path;
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(6, 12, 18, 18, SkPath::kCCW_Direction);
- path.addRect(4, 12, 13, 13, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine60x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(6, 12, 18, 18, SkPath::kCCW_Direction);
- path.addRect(4, 12, 13, 13, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine61() {
- SkPath path;
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(12, 0, 24, 24, SkPath::kCCW_Direction);
- path.addRect(12, 0, 21, 21, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine61x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(12, 0, 24, 24, SkPath::kCCW_Direction);
- path.addRect(12, 0, 21, 21, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine62() {
- SkPath path;
- path.addRect(0, 0, 60, 60, SkPath::kCW_Direction);
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 12, 12, 12, SkPath::kCW_Direction);
- path.addRect(4, 12, 13, 13, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine62x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 60, 60, SkPath::kCW_Direction);
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 12, 12, 12, SkPath::kCW_Direction);
- path.addRect(4, 12, 13, 13, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine63() {
- SkPath path;
- path.addRect(0, 0, 60, 60, SkPath::kCW_Direction);
- path.addRect(0, 10, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 6, 12, 12, SkPath::kCCW_Direction);
- path.addRect(0, 32, 9, 36, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine63x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 60, 60, SkPath::kCW_Direction);
- path.addRect(0, 10, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 6, 12, 12, SkPath::kCCW_Direction);
- path.addRect(0, 32, 9, 36, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine64() {
- SkPath path;
- path.addRect(0, 0, 60, 60, SkPath::kCW_Direction);
- path.addRect(10, 40, 30, 30, SkPath::kCW_Direction);
- path.addRect(18, 6, 30, 30, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine64x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 60, 60, SkPath::kCW_Direction);
- path.addRect(10, 40, 30, 30, SkPath::kCW_Direction);
- path.addRect(18, 6, 30, 30, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine65() {
- SkPath path;
- path.addRect(0, 0, 60, 60, SkPath::kCW_Direction);
- path.addRect(10, 0, 30, 30, SkPath::kCW_Direction);
- path.addRect(24, 0, 36, 36, SkPath::kCW_Direction);
- path.addRect(32, 6, 36, 41, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine65x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 60, 60, SkPath::kCW_Direction);
- path.addRect(10, 0, 30, 30, SkPath::kCW_Direction);
- path.addRect(24, 0, 36, 36, SkPath::kCW_Direction);
- path.addRect(32, 6, 36, 41, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine66() {
- SkPath path;
- path.addRect(0, 0, 60, 60, SkPath::kCW_Direction);
- path.addRect(0, 30, 20, 20, SkPath::kCW_Direction);
- path.addRect(12, 20, 24, 30, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine66x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 60, 60, SkPath::kCW_Direction);
- path.addRect(0, 30, 20, 20, SkPath::kCW_Direction);
- path.addRect(12, 20, 24, 30, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine67() {
- SkPath path;
- path.addRect(0, 0, 60, 60, SkPath::kCW_Direction);
- path.addRect(10, 40, 30, 30, SkPath::kCW_Direction);
- path.addRect(24, 20, 36, 30, SkPath::kCW_Direction);
- path.addRect(32, 0, 36, 41, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine67x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 60, 60, SkPath::kCW_Direction);
- path.addRect(10, 40, 30, 30, SkPath::kCW_Direction);
- path.addRect(24, 20, 36, 30, SkPath::kCW_Direction);
- path.addRect(32, 0, 36, 41, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine68a() {
- SkPath path;
- path.addRect(0, 0, 8, 8, SkPath::kCW_Direction);
- path.addRect(2, 2, 6, 6, SkPath::kCW_Direction);
- path.addRect(1, 2, 4, 2, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine68ax() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 8, 8, SkPath::kCW_Direction);
- path.addRect(2, 2, 6, 6, SkPath::kCW_Direction);
- path.addRect(1, 2, 4, 2, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine68b() {
- SkPath path;
- path.addRect(0, 0, 8, 8, SkPath::kCW_Direction);
- path.addRect(2, 2, 6, 6, SkPath::kCCW_Direction);
- path.addRect(1, 2, 2, 2, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine68bx() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 8, 8, SkPath::kCW_Direction);
- path.addRect(2, 2, 6, 6, SkPath::kCCW_Direction);
- path.addRect(1, 2, 2, 2, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine68c() {
- SkPath path;
- path.addRect(0, 0, 8, 8, SkPath::kCCW_Direction);
- path.addRect(2, 2, 6, 6, SkPath::kCW_Direction);
- path.addRect(1, 2, 4, 2, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine68cx() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 8, 8, SkPath::kCCW_Direction);
- path.addRect(2, 2, 6, 6, SkPath::kCW_Direction);
- path.addRect(1, 2, 4, 2, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine68d() {
- SkPath path;
- path.addRect(0, 0, 8, 8, SkPath::kCCW_Direction);
- path.addRect(2, 2, 6, 6, SkPath::kCCW_Direction);
- path.addRect(1, 2, 4, 2, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine68dx() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 8, 8, SkPath::kCCW_Direction);
- path.addRect(2, 2, 6, 6, SkPath::kCCW_Direction);
- path.addRect(1, 2, 4, 2, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine68e() {
- SkPath path;
- path.addRect(0, 0, 8, 8, SkPath::kCW_Direction);
- path.addRect(0, 0, 8, 8, SkPath::kCW_Direction);
- path.addRect(2, 2, 6, 6, SkPath::kCCW_Direction);
- path.addRect(1, 2, 2, 2, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine68ex() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 8, 8, SkPath::kCW_Direction);
- path.addRect(0, 0, 8, 8, SkPath::kCW_Direction);
- path.addRect(2, 2, 6, 6, SkPath::kCCW_Direction);
- path.addRect(1, 2, 2, 2, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine68f() {
- SkPath path;
- path.addRect(0, 0, 8, 8, SkPath::kCW_Direction);
- path.addRect(2, 2, 6, 6, SkPath::kCCW_Direction);
- path.addRect(2, 2, 6, 6, SkPath::kCCW_Direction);
- path.addRect(1, 2, 2, 2, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine68fx() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 8, 8, SkPath::kCW_Direction);
- path.addRect(2, 2, 6, 6, SkPath::kCCW_Direction);
- path.addRect(2, 2, 6, 6, SkPath::kCCW_Direction);
- path.addRect(1, 2, 2, 2, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine68g() {
- SkPath path;
- path.addRect(0, 0, 8, 8, SkPath::kCW_Direction);
- path.addRect(0, 0, 8, 8, SkPath::kCW_Direction);
- path.addRect(2, 2, 6, 6, SkPath::kCCW_Direction);
- path.addRect(2, 2, 6, 6, SkPath::kCCW_Direction);
- path.addRect(1, 2, 2, 2, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine68gx() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 8, 8, SkPath::kCW_Direction);
- path.addRect(0, 0, 8, 8, SkPath::kCW_Direction);
- path.addRect(2, 2, 6, 6, SkPath::kCCW_Direction);
- path.addRect(2, 2, 6, 6, SkPath::kCCW_Direction);
- path.addRect(1, 2, 2, 2, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine68h() {
- SkPath path;
- path.addRect(0, 0, 8, 8, SkPath::kCW_Direction);
- path.addRect(2, 2, 6, 6, SkPath::kCCW_Direction);
- path.addRect(2, 2, 6, 6, SkPath::kCCW_Direction);
- path.addRect(2, 2, 6, 6, SkPath::kCCW_Direction);
- path.addRect(1, 2, 2, 2, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine68hx() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 8, 8, SkPath::kCW_Direction);
- path.addRect(2, 2, 6, 6, SkPath::kCCW_Direction);
- path.addRect(2, 2, 6, 6, SkPath::kCCW_Direction);
- path.addRect(2, 2, 6, 6, SkPath::kCCW_Direction);
- path.addRect(1, 2, 2, 2, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine69() {
- SkPath path;
- path.addRect(0, 20, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 20, 12, 30, SkPath::kCW_Direction);
- path.addRect(12, 32, 21, 36, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine69x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 20, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 20, 12, 30, SkPath::kCW_Direction);
- path.addRect(12, 32, 21, 36, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine70() {
- SkPath path;
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 24, 12, 12, SkPath::kCW_Direction);
- path.addRect(12, 32, 21, 36, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine70x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 24, 12, 12, SkPath::kCW_Direction);
- path.addRect(12, 32, 21, 36, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine71() {
- SkPath path;
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(12, 0, 24, 24, SkPath::kCW_Direction);
- path.addRect(12, 32, 21, 36, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine71x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(12, 0, 24, 24, SkPath::kCW_Direction);
- path.addRect(12, 32, 21, 36, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine72() {
- SkPath path;
- path.addRect(0, 0, 60, 60, SkPath::kCW_Direction);
- path.addRect(10, 40, 30, 30, SkPath::kCW_Direction);
- path.addRect(6, 20, 18, 30, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine72x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 60, 60, SkPath::kCW_Direction);
- path.addRect(10, 40, 30, 30, SkPath::kCW_Direction);
- path.addRect(6, 20, 18, 30, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine73() {
- SkPath path;
- path.addRect(0, 0, 60, 60, SkPath::kCW_Direction);
- path.addRect(0, 40, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 20, 12, 30, SkPath::kCW_Direction);
- path.addRect(0, 0, 9, 9, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine73x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 60, 60, SkPath::kCW_Direction);
- path.addRect(0, 40, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 20, 12, 30, SkPath::kCW_Direction);
- path.addRect(0, 0, 9, 9, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine74() {
- SkPath path;
- path.addRect(20, 30, 40, 40, SkPath::kCW_Direction);
- path.addRect(24, 20, 36, 30, SkPath::kCCW_Direction);
- path.addRect(32, 24, 36, 41, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine74x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(20, 30, 40, 40, SkPath::kCW_Direction);
- path.addRect(24, 20, 36, 30, SkPath::kCCW_Direction);
- path.addRect(32, 24, 36, 41, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine75() {
- SkPath path;
- path.addRect(0, 0, 60, 60, SkPath::kCW_Direction);
- path.addRect(10, 0, 30, 30, SkPath::kCCW_Direction);
- path.addRect(18, 0, 30, 30, SkPath::kCCW_Direction);
- path.addRect(12, 0, 21, 21, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine75x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 60, 60, SkPath::kCW_Direction);
- path.addRect(10, 0, 30, 30, SkPath::kCCW_Direction);
- path.addRect(18, 0, 30, 30, SkPath::kCCW_Direction);
- path.addRect(12, 0, 21, 21, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine76() {
- SkPath path;
- path.addRect(36, 0, 66, 60, SkPath::kCW_Direction);
- path.addRect(10, 20, 40, 30, SkPath::kCW_Direction);
- path.addRect(24, 20, 36, 30, SkPath::kCCW_Direction);
- path.addRect(32, 6, 36, 41, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine76x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(36, 0, 66, 60, SkPath::kCW_Direction);
- path.addRect(10, 20, 40, 30, SkPath::kCW_Direction);
- path.addRect(24, 20, 36, 30, SkPath::kCCW_Direction);
- path.addRect(32, 6, 36, 41, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine77() {
- SkPath path;
- path.addRect(20, 0, 40, 40, SkPath::kCW_Direction);
- path.addRect(24, 6, 36, 36, SkPath::kCCW_Direction);
- path.addRect(24, 32, 33, 36, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine77x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(20, 0, 40, 40, SkPath::kCW_Direction);
- path.addRect(24, 6, 36, 36, SkPath::kCCW_Direction);
- path.addRect(24, 32, 33, 36, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine78() {
- SkPath path;
- path.addRect(0, 0, 30, 60, SkPath::kCW_Direction);
- path.addRect(10, 20, 30, 30, SkPath::kCCW_Direction);
- path.addRect(18, 20, 30, 30, SkPath::kCCW_Direction);
- path.addRect(32, 0, 36, 41, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine78x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 30, 60, SkPath::kCW_Direction);
- path.addRect(10, 20, 30, 30, SkPath::kCCW_Direction);
- path.addRect(18, 20, 30, 30, SkPath::kCCW_Direction);
- path.addRect(32, 0, 36, 41, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine79() {
- SkPath path;
- path.addRect(0, 36, 60, 30, SkPath::kCW_Direction);
- path.addRect(10, 30, 40, 30, SkPath::kCW_Direction);
- path.addRect(0, 20, 12, 30, SkPath::kCCW_Direction);
- path.addRect(0, 32, 9, 36, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine79x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 36, 60, 30, SkPath::kCW_Direction);
- path.addRect(10, 30, 40, 30, SkPath::kCW_Direction);
- path.addRect(0, 20, 12, 30, SkPath::kCCW_Direction);
- path.addRect(0, 32, 9, 36, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine81() {
- SkPath path;
- path.addRect(-1, -1, 3, 3, SkPath::kCW_Direction);
- path.addRect(0, 0, 1, 1, SkPath::kCW_Direction);
- path.addRect(0, 0, 1, 1, SkPath::kCW_Direction);
- path.addRect(0, 0, 1, 1, SkPath::kCW_Direction);
- path.addRect(1, 1, 2, 2, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testDegenerate1() {
- SkPath path;
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.lineTo(2, 0);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(2, 0);
- path.close();
- testSimplifyx(path);
-}
-
-static void testDegenerate1x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.lineTo(2, 0);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(2, 0);
- path.close();
- testSimplifyx(path);
-}
-
-static void testDegenerate2() {
- SkPath path;
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.lineTo(0, 0);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(0, 1);
- path.close();
- testSimplifyx(path);
-}
-
-static void testDegenerate2x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.lineTo(0, 0);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(0, 1);
- path.close();
- testSimplifyx(path);
-}
-
-static void testDegenerate3() {
- SkPath path;
- path.moveTo(0, 0);
- path.lineTo(2, 0);
- path.lineTo(1, 0);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.lineTo(3, 0);
- path.close();
- testSimplifyx(path);
-}
-
-static void testDegenerate3x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0, 0);
- path.lineTo(2, 0);
- path.lineTo(1, 0);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.lineTo(3, 0);
- path.close();
- testSimplifyx(path);
-}
-
-static void testDegenerate4() {
- SkPath path;
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(1, 3);
- path.close();
- path.moveTo(1, 0);
- path.lineTo(1, 1);
- path.lineTo(1, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testDegenerate4x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(1, 3);
- path.close();
- path.moveTo(1, 0);
- path.lineTo(1, 1);
- path.lineTo(1, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testNondegenerate1() {
- SkPath path;
- path.moveTo(0, 0);
- path.lineTo(3, 0);
- path.lineTo(1, 3);
- path.close();
- path.moveTo(1, 1);
- path.lineTo(2, 1);
- path.lineTo(1, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testNondegenerate1x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0, 0);
- path.lineTo(3, 0);
- path.lineTo(1, 3);
- path.close();
- path.moveTo(1, 1);
- path.lineTo(2, 1);
- path.lineTo(1, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testNondegenerate2() {
- SkPath path;
- path.moveTo(1, 0);
- path.lineTo(0, 1);
- path.lineTo(1, 1);
- path.close();
- path.moveTo(0, 2);
- path.lineTo(0, 3);
- path.lineTo(1, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testNondegenerate2x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(1, 0);
- path.lineTo(0, 1);
- path.lineTo(1, 1);
- path.close();
- path.moveTo(0, 2);
- path.lineTo(0, 3);
- path.lineTo(1, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testNondegenerate3() {
- SkPath path;
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(2, 1);
- path.close();
- path.moveTo(0, 1);
- path.lineTo(1, 1);
- path.lineTo(0, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testNondegenerate3x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(2, 1);
- path.close();
- path.moveTo(0, 1);
- path.lineTo(1, 1);
- path.lineTo(0, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testNondegenerate4() {
- SkPath path;
- path.moveTo(1, 0);
- path.lineTo(0, 1);
- path.lineTo(1, 2);
- path.close();
- path.moveTo(0, 2);
- path.lineTo(0, 3);
- path.lineTo(1, 3);
- path.close();
- testSimplifyx(path);
-}
-
-static void testNondegenerate4x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(1, 0);
- path.lineTo(0, 1);
- path.lineTo(1, 2);
- path.close();
- path.moveTo(0, 2);
- path.lineTo(0, 3);
- path.lineTo(1, 3);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadralateral5() {
- SkPath path;
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(1, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(2, 2);
- path.lineTo(3, 2);
- path.lineTo(3, 3);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadralateral5x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(1, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(2, 2);
- path.lineTo(3, 2);
- path.lineTo(3, 3);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadralateral6() {
- SkPath path;
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(1, 1);
- path.close();
- path.moveTo(1, 0);
- path.lineTo(2, 0);
- path.lineTo(0, 2);
- path.lineTo(2, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadralateral6x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(1, 1);
- path.close();
- path.moveTo(1, 0);
- path.lineTo(2, 0);
- path.lineTo(0, 2);
- path.lineTo(2, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testFauxQuadralateral6() {
- SkPath path;
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(1, 1);
- path.close();
- path.moveTo(1, 0);
- path.lineTo(2, 0);
- path.lineTo(1 + 1.0f/3, 2.0f/3);
- path.close();
- path.moveTo(1 + 1.0f/3, 2.0f/3);
- path.lineTo(0, 2);
- path.lineTo(2, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testFauxQuadralateral6x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(1, 1);
- path.close();
- path.moveTo(1, 0);
- path.lineTo(2, 0);
- path.lineTo(1 + 1.0f/3, 2.0f/3);
- path.close();
- path.moveTo(1 + 1.0f/3, 2.0f/3);
- path.lineTo(0, 2);
- path.lineTo(2, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testFauxQuadralateral6a() {
- SkPath path;
- path.moveTo(0, 0);
- path.lineTo(3, 0);
- path.lineTo(3, 3);
- path.close();
- path.moveTo(3, 0);
- path.lineTo(6, 0);
- path.lineTo(4, 2);
- path.close();
- path.moveTo(4, 2);
- path.lineTo(0, 6);
- path.lineTo(6, 6);
- path.close();
- testSimplifyx(path);
-}
-
-static void testFauxQuadralateral6ax() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0, 0);
- path.lineTo(3, 0);
- path.lineTo(3, 3);
- path.close();
- path.moveTo(3, 0);
- path.lineTo(6, 0);
- path.lineTo(4, 2);
- path.close();
- path.moveTo(4, 2);
- path.lineTo(0, 6);
- path.lineTo(6, 6);
- path.close();
- testSimplifyx(path);
-}
-
-static void testFauxQuadralateral6b() {
- SkPath path;
- path.moveTo(0, 0);
- path.lineTo(3, 0);
- path.lineTo(3, 3);
- path.close();
- path.moveTo(3, 0);
- path.lineTo(6, 0);
- path.lineTo(4, 2);
- path.close();
- path.moveTo(4, 2);
- path.lineTo(6, 6);
- path.lineTo(0, 6);
- path.close();
- testSimplifyx(path);
-}
-
-static void testFauxQuadralateral6bx() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0, 0);
- path.lineTo(3, 0);
- path.lineTo(3, 3);
- path.close();
- path.moveTo(3, 0);
- path.lineTo(6, 0);
- path.lineTo(4, 2);
- path.close();
- path.moveTo(4, 2);
- path.lineTo(6, 6);
- path.lineTo(0, 6);
- path.close();
- testSimplifyx(path);
-}
-
-static void testFauxQuadralateral6c() {
- SkPath path;
- path.moveTo(0, 0);
- path.lineTo(3, 3);
- path.lineTo(3, 0);
- path.close();
- path.moveTo(3, 0);
- path.lineTo(6, 0);
- path.lineTo(4, 2);
- path.close();
- path.moveTo(4, 2);
- path.lineTo(0, 6);
- path.lineTo(6, 6);
- path.close();
- testSimplifyx(path);
-}
-
-static void testFauxQuadralateral6cx() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0, 0);
- path.lineTo(3, 3);
- path.lineTo(3, 0);
- path.close();
- path.moveTo(3, 0);
- path.lineTo(6, 0);
- path.lineTo(4, 2);
- path.close();
- path.moveTo(4, 2);
- path.lineTo(0, 6);
- path.lineTo(6, 6);
- path.close();
- testSimplifyx(path);
-}
-
-static void testFauxQuadralateral6d() {
- SkPath path;
- path.moveTo(0, 0);
- path.lineTo(3, 3);
- path.lineTo(3, 0);
- path.close();
- path.moveTo(3, 0);
- path.lineTo(6, 0);
- path.lineTo(4, 2);
- path.close();
- path.moveTo(4, 2);
- path.lineTo(6, 6);
- path.lineTo(0, 6);
- path.close();
- testSimplifyx(path);
-}
-
-static void testFauxQuadralateral6dx() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0, 0);
- path.lineTo(3, 3);
- path.lineTo(3, 0);
- path.close();
- path.moveTo(3, 0);
- path.lineTo(6, 0);
- path.lineTo(4, 2);
- path.close();
- path.moveTo(4, 2);
- path.lineTo(6, 6);
- path.lineTo(0, 6);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadralateral6a() {
- SkPath path;
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.lineTo(3, 0);
- path.lineTo(3, 3);
- path.close();
- path.moveTo(3, 0);
- path.lineTo(6, 0);
- path.lineTo(0, 6);
- path.lineTo(6, 6);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadralateral6ax() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.lineTo(3, 0);
- path.lineTo(3, 3);
- path.close();
- path.moveTo(3, 0);
- path.lineTo(6, 0);
- path.lineTo(0, 6);
- path.lineTo(6, 6);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadralateral7() {
- SkPath path;
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(2, 1);
- path.close();
- path.moveTo(1, 0);
- path.lineTo(1, 1);
- path.lineTo(2, 2);
- path.lineTo(1, 3);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadralateral7x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(2, 1);
- path.close();
- path.moveTo(1, 0);
- path.lineTo(1, 1);
- path.lineTo(2, 2);
- path.lineTo(1, 3);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadralateral8() {
- SkPath path;
- path.moveTo(0, 0);
- path.lineTo(3, 1);
- path.lineTo(1, 3);
- path.lineTo(3, 3);
- path.close();
- path.moveTo(2, 1);
- path.lineTo(0, 2);
- path.lineTo(3, 2);
- path.lineTo(2, 3);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadralateral8x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0, 0);
- path.lineTo(3, 1);
- path.lineTo(1, 3);
- path.lineTo(3, 3);
- path.close();
- path.moveTo(2, 1);
- path.lineTo(0, 2);
- path.lineTo(3, 2);
- path.lineTo(2, 3);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadralateral9() {
- SkPath path;
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(1, 2);
- path.lineTo(2, 2);
- path.close();
- path.moveTo(1, 1);
- path.lineTo(2, 1);
- path.lineTo(1, 3);
- path.lineTo(2, 3);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadralateral9x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(1, 2);
- path.lineTo(2, 2);
- path.close();
- path.moveTo(1, 1);
- path.lineTo(2, 1);
- path.lineTo(1, 3);
- path.lineTo(2, 3);
- path.close();
- testSimplifyx(path);
-}
-
-static void testLine1a() {
- SkPath path;
- path.setFillType(SkPath::kWinding_FillType);
- path.addRect(0, 0, 12, 12, SkPath::kCW_Direction);
- path.addRect(4, 0, 13, 13, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine1ax() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 12, 12, SkPath::kCW_Direction);
- path.addRect(4, 0, 13, 13, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine2ax() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 20, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 20, 12, 30, SkPath::kCW_Direction);
- path.addRect(12, 0, 21, 21, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine3aax() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(10, 30, 30, 30, SkPath::kCW_Direction);
- path.addRect(18, 20, 30, 30, SkPath::kCCW_Direction);
- path.addRect(0, 32, 9, 36, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine4ax() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(10, 30, 30, 30, SkPath::kCW_Direction);
- path.addRect(24, 20, 36, 30, SkPath::kCCW_Direction);
- path.addRect(0, 32, 9, 36, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testQuadratic1() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.lineTo(1, 0);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic1x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.lineTo(1, 0);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic2() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.lineTo(3, 0);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(1, 0, 0, 1);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic2x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.lineTo(3, 0);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(1, 0, 0, 1);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic3() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(0, 0, 1, 0);
- path.lineTo(0, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(1, 0, 0, 1);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic3x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0, 0);
- path.quadTo(0, 0, 1, 0);
- path.lineTo(0, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(1, 0, 0, 1);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic4() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(0, 0, 1, 0);
- path.lineTo(0, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(1, 0, 0, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic4x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0, 0);
- path.quadTo(0, 0, 1, 0);
- path.lineTo(0, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(1, 0, 0, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic5() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.lineTo(0, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.quadTo(0, 1, 0, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic6() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(0, 0, 1, 0);
- path.lineTo(2, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(2, 0, 0, 1);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic7() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(0, 0, 1, 0);
- path.lineTo(3, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(3, 0, 1, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic8() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(0, 0, 1, 0);
- path.lineTo(0, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.quadTo(0, 1, 1, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic9() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(0, 0, 1, 0);
- path.lineTo(3, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.quadTo(1, 2, 3, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic14() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(0, 0, 1, 0);
- path.lineTo(3, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.quadTo(3, 2, 3, 3);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic15() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(0, 0, 1, 0);
- path.lineTo(1, 3);
- path.close();
- path.moveTo(1, 0);
- path.lineTo(0, 1);
- path.quadTo(1, 1, 0, 3);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic17x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0, 0);
- path.quadTo(0, 0, 3, 1);
- path.lineTo(0, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.quadTo(3, 1, 0, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic18() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(1, 0, 0, 1);
- path.lineTo(0, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(1, 0, 1, 1);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic19() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(1, 0, 0, 1);
- path.lineTo(0, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(2, 0, 0, 1);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic20() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(1, 0, 0, 1);
- path.lineTo(0, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(1, 0, 0, 1);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic21() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(1, 0, 0, 1);
- path.lineTo(0, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(1, 0, 0, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic22() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(1, 0, 0, 1);
- path.lineTo(0, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(0, 1, 2, 1);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic23() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(1, 0, 0, 1);
- path.lineTo(0, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(0, 2, 1, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic24() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(1, 0, 0, 1);
- path.lineTo(0, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.quadTo(2, 0, 0, 1);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic25() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(1, 0, 1, 1);
- path.lineTo(1, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(2, 1, 0, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic26() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(1, 0, 1, 1);
- path.lineTo(0, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(1, 0, 0, 1);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic27() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(1, 0, 1, 1);
- path.lineTo(2, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(2, 1, 0, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic28() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(1, 0, 0, 1);
- path.lineTo(0, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 2);
- path.quadTo(1, 2, 0, 3);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic29() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(1, 0, 2, 1);
- path.lineTo(0, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(1, 0, 0, 1);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic30() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(1, 0, 1, 2);
- path.lineTo(1, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.quadTo(0, 1, 1, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic31() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(1, 0, 1, 2);
- path.lineTo(1, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.quadTo(0, 1, 1, 3);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic32() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(1, 0, 2, 3);
- path.lineTo(2, 3);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(3, 1, 0, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic33() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(2, 0, 0, 1);
- path.lineTo(0, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 1);
- path.quadTo(2, 1, 2, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic34() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(2, 0, 0, 1);
- path.lineTo(0, 1);
- path.close();
- path.moveTo(1, 0);
- path.lineTo(1, 1);
- path.quadTo(2, 1, 1, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic35() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(0, 1, 1, 1);
- path.lineTo(1, 3);
- path.close();
- path.moveTo(2, 0);
- path.lineTo(3, 0);
- path.quadTo(0, 1, 1, 1);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic36() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(2, 1, 2, 3);
- path.lineTo(2, 3);
- path.close();
- path.moveTo(3, 1);
- path.lineTo(1, 2);
- path.quadTo(3, 2, 1, 3);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic37() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(0, 2, 1, 2);
- path.lineTo(1, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(3, 1);
- path.quadTo(0, 2, 1, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic38() {
- SkPath path;
- path.moveTo(1, 0);
- path.quadTo(0, 1, 1, 1);
- path.lineTo(1, 1);
- path.close();
- path.moveTo(1, 0);
- path.lineTo(1, 2);
- path.quadTo(2, 2, 1, 3);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic51() {
- SkPath path;
- path.moveTo(369.863983f, 145.645813f);
- path.quadTo(382.380371f, 121.254936f, 406.236359f, 121.254936f);
- path.lineTo(369.863983f, 145.645813f);
- path.close();
- path.moveTo(369.970581f, 137.94342f);
- path.quadTo(383.98465f, 121.254936f, 406.235992f, 121.254936f);
- path.lineTo(369.970581f, 137.94342f);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic53() {
- SkPath path;
- path.moveTo(303.12088f, 141.299606f);
- path.lineTo(330.463562f, 217.659027f);
- path.lineTo(303.12088f, 141.299606f);
- path.close();
- path.moveTo(371.919067f, 205.854996f);
- path.lineTo(326.236786f, 205.854996f);
- path.quadTo(329.104431f, 231.663818f, 351.512085f, 231.663818f);
- path.lineTo(371.919067f, 205.854996f);
- path.close();
- testSimplifyx(path);
-}
-static void testQuadratic55() {
- SkPath path;
-path.moveTo(303.12088f, 141.299606f);
-path.lineTo(330.463562f, 217.659027f);
-path.lineTo(358.606506f, 141.299606f);
-path.lineTo(303.12088f, 141.299606f);
-path.close();
-path.moveTo(326.236786f, 205.854996f);
-path.quadTo(329.104431f, 231.663818f, 351.512085f, 231.663818f);
-path.lineTo(326.236786f, 205.854996f);
-path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic56() {
- SkPath path;
-path.moveTo(366.608826f, 151.196014f);
-path.quadTo(378.803101f, 136.674606f, 398.164948f, 136.674606f);
-path.lineTo(354.009216f, 208.816208f);
-path.lineTo(393.291473f, 102.232819f);
-path.lineTo(359.978058f, 136.581512f);
-path.quadTo(378.315979f, 136.581512f, 388.322723f, 149.613556f);
-path.lineTo(364.390686f, 157.898193f);
-path.quadTo(375.281769f, 136.674606f, 396.039917f, 136.674606f);
-path.lineTo(350, 120);
-path.lineTo(366.608826f, 151.196014f);
-path.close();
- testSimplifyx(path);
-}
-
-static void testLine80() {
- SkPath path;
-path.moveTo(4, 0);
-path.lineTo(3, 7);
-path.lineTo(7, 5);
-path.lineTo(2, 2);
-path.close();
-path.moveTo(0, 6);
-path.lineTo(6, 12);
-path.lineTo(8, 3);
-path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic58() {
- SkPath path;
-path.moveTo(283.714233f, 240);
-path.lineTo(283.714233f, 141.299606f);
-path.lineTo(303.12088f, 141.299606f);
-path.lineTo(330.463562f, 217.659027f);
-path.lineTo(358.606506f, 141.299606f);
-path.lineTo(362.874634f, 159.705902f);
-path.lineTo(335.665344f, 233.397751f);
-path.lineTo(322.12738f, 233.397751f);
-path.lineTo(295.718353f, 159.505829f);
-path.lineTo(295.718353f, 240);
-path.lineTo(283.714233f, 240);
-path.close();
-path.moveTo(322.935669f, 231.030273f);
-path.quadTo(312.832214f, 220.393295f, 312.832214f, 203.454178f);
-path.quadTo(312.832214f, 186.981888f, 321.73526f, 176.444946f);
-path.quadTo(330.638306f, 165.90802f, 344.509705f, 165.90802f);
-path.quadTo(357.647522f, 165.90802f, 364.81665f, 175.244537f);
-path.lineTo(371.919067f, 205.854996f);
-path.lineTo(326.236786f, 205.854996f);
-path.quadTo(329.104431f, 231.663818f, 351.512085f, 231.663818f);
-path.lineTo(322.935669f, 231.030273f);
-path.close();
-path.moveTo(326.837006f, 195.984955f);
-path.lineTo(358.78125f, 195.984955f);
-path.quadTo(358.78125f, 175.778046f, 343.709442f, 175.778046f);
-path.quadTo(328.570923f, 175.778046f, 326.837006f, 195.984955f);
-path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic59x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.lineTo(2, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(2, 0);
- path.quadTo(3, 1, 1, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic59() {
- SkPath path;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.lineTo(2, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(2, 0);
- path.quadTo(3, 1, 1, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic63() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.lineTo(3, 2);
- path.close();
- path.moveTo(1, 0);
- path.lineTo(2, 1);
- path.quadTo(2, 1, 2, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic64() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.lineTo(2, 3);
- path.close();
- path.moveTo(1, 2);
- path.lineTo(2, 2);
- path.quadTo(0, 3, 3, 3);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic65() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.lineTo(3, 2);
- path.close();
- path.moveTo(2, 1);
- path.lineTo(2, 2);
- path.quadTo(0, 3, 1, 3);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic67x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0, 0);
- path.quadTo(0, 0, 2, 1);
- path.lineTo(2, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(2, 0);
- path.quadTo(1, 1, 3, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic68() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(1, 0, 0, 1);
- path.lineTo(1, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(0, 1, 2, 1);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic69() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 1);
- path.lineTo(3, 2);
- path.close();
- path.moveTo(2, 0);
- path.lineTo(1, 1);
- path.quadTo(3, 2, 2, 3);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic70x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0, 0);
- path.quadTo(1, 0, 0, 1);
- path.lineTo(1, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(0, 1, 2, 1);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic71() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(1, 0, 1, 1);
- path.lineTo(3, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(1, 1, 3, 1);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic72() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(1, 0, 1, 2);
- path.lineTo(1, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.quadTo(0, 1, 3, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic73() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(1, 0, 0, 3);
- path.lineTo(0, 3);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.quadTo(0, 1, 1, 1);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic74() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(1, 0, 1, 3);
- path.lineTo(1, 3);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 1);
- path.quadTo(3, 2, 2, 3);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic75() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(1, 0, 1, 3);
- path.lineTo(2, 3);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 1);
- path.quadTo(3, 2, 2, 3);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic76() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.lineTo(2, 3);
- path.close();
- path.moveTo(1, 0);
- path.lineTo(1, 2);
- path.quadTo(1, 2, 2, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic77() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(1, 0, 1, 1);
- path.lineTo(3, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.quadTo(0, 1, 3, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic78() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(1, 0, 1, 2);
- path.lineTo(3, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(2, 1, 0, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic79() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(1, 0, 1, 2);
- path.lineTo(3, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.quadTo(0, 1, 3, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testEight1() {
- SkPath path;
- path.moveTo(0, 0);
- path.lineTo(2, 2);
- path.lineTo(0, 2);
- path.lineTo(2, 0);
- path.close();
- testSimplifyx(path);
-}
-
-static void testEight2() {
- SkPath path;
- path.moveTo(0, 0);
- path.lineTo(2, 0);
- path.lineTo(0, 2);
- path.lineTo(2, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testEight3() {
- SkPath path;
- path.moveTo(0, 0);
- path.lineTo(0, 2);
- path.lineTo(2, 0);
- path.lineTo(2, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testEight4() {
- SkPath path;
- path.moveTo(0, 0);
- path.lineTo(2, 2);
- path.lineTo(2, 0);
- path.lineTo(0, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testEight5() {
- SkPath path;
- path.moveTo(1, 0);
- path.lineTo(1, 2);
- path.lineTo(0, 2);
- path.lineTo(2, 0);
- path.close();
- testSimplifyx(path);
-}
-
-static void testEight6() {
- SkPath path;
- path.moveTo(1, 0);
- path.lineTo(2, 0);
- path.lineTo(0, 2);
- path.lineTo(1, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testEight7() {
- SkPath path;
- path.moveTo(0, 0);
- path.lineTo(0, 1);
- path.lineTo(2, 1);
- path.lineTo(2, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testEight8() {
- SkPath path;
- path.moveTo(0, 0);
- path.lineTo(2, 2);
- path.lineTo(2, 1);
- path.lineTo(0, 1);
- path.close();
- testSimplifyx(path);
-}
-
-static void testEight9() {
- SkPath path;
- path.moveTo(1, 0);
- path.lineTo(1, 2);
- path.lineTo(2, 1);
- path.lineTo(0, 1);
- path.close();
- testSimplifyx(path);
-}
-
-static void testEight10() {
- SkPath path;
- path.moveTo(1, 0);
- path.lineTo(0, 1);
- path.lineTo(2, 1);
- path.lineTo(1, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic80() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(1, 0, 2, 3);
- path.lineTo(2, 3);
- path.close();
- path.moveTo(1, 0);
- path.lineTo(3, 0);
- path.quadTo(0, 1, 1, 1);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic81() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(2, 0, 1, 1);
- path.lineTo(1, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(2, 1, 0, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic82() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(2, 0, 1, 1);
- path.lineTo(0, 3);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(2, 1, 0, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic83() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(0, 0, 2, 0);
- path.lineTo(2, 2);
- path.close();
- path.moveTo(0, 1);
- path.lineTo(0, 2);
- path.quadTo(2, 2, 1, 3);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic84() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(2, 0, 1, 1);
- path.lineTo(2, 1);
- path.close();
- path.moveTo(1, 0);
- path.lineTo(2, 0);
- path.quadTo(0, 1, 2, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic85() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(3, 0, 1, 1);
- path.lineTo(1, 1);
- path.close();
- path.moveTo(1, 0);
- path.lineTo(3, 0);
- path.quadTo(0, 1, 1, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic86() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(0, 1, 1, 1);
- path.lineTo(2, 3);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(1, 1, 1, 3);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic87() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(2, 1, 0, 2);
- path.lineTo(2, 3);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 1);
- path.quadTo(0, 2, 3, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic88() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(2, 1, 0, 2);
- path.lineTo(2, 2);
- path.close();
- path.moveTo(1, 0);
- path.lineTo(1, 1);
- path.quadTo(0, 2, 2, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic89x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0, 0);
- path.quadTo(3, 1, 2, 2);
- path.lineTo(0, 3);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(2, 1);
- path.quadTo(3, 1, 3, 3);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic90x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0, 0);
- path.quadTo(3, 0, 2, 2);
- path.lineTo(1, 3);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 1);
- path.quadTo(3, 2, 2, 3);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic91() {
- SkPath path;
- path.moveTo(0, 0);
- path.quadTo(3, 2, 2, 3);
- path.lineTo(2, 3);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 1);
- path.quadTo(2, 1, 2, 3);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic92x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(1, 0);
- path.quadTo(3, 0, 2, 2);
- path.lineTo(2, 2);
- path.close();
- path.moveTo(2, 0);
- path.lineTo(0, 1);
- path.quadTo(3, 2, 2, 3);
- path.close();
- testSimplifyx(path);
-}
-
-static void testLine82() {
- SkPath path;
- path.addRect(20, 0, 40, 40, SkPath::kCCW_Direction);
- path.addRect(24, 20, 36, 30, SkPath::kCCW_Direction);
- path.addRect(24, 32, 33, 36, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine82a() {
- SkPath path;
- path.addRect(0, 0, 6, 10, SkPath::kCW_Direction);
- path.addRect(2, 2, 4, 4, SkPath::kCW_Direction);
- path.addRect(2, 6, 4, 8, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine82b() {
- SkPath path;
- path.addRect(0, 0, 6, 10, SkPath::kCW_Direction);
- path.addRect(2, 2, 4, 4, SkPath::kCW_Direction);
- path.addRect(2, 6, 4, 8, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine82c() {
- SkPath path;
- path.addRect(0, 0, 6, 10, SkPath::kCW_Direction);
- path.addRect(2, 2, 4, 4, SkPath::kCCW_Direction);
- path.addRect(2, 6, 4, 8, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine82d() {
- SkPath path;
- path.addRect(0, 0, 6, 10, SkPath::kCW_Direction);
- path.addRect(2, 2, 4, 4, SkPath::kCCW_Direction);
- path.addRect(2, 6, 4, 8, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine82e() {
- SkPath path;
- path.addRect(0, 0, 6, 10, SkPath::kCCW_Direction);
- path.addRect(2, 2, 4, 4, SkPath::kCW_Direction);
- path.addRect(2, 6, 4, 8, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine82f() {
- SkPath path;
- path.addRect(0, 0, 6, 10, SkPath::kCCW_Direction);
- path.addRect(2, 2, 4, 4, SkPath::kCW_Direction);
- path.addRect(2, 6, 4, 8, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine82g() {
- SkPath path;
- path.addRect(0, 0, 6, 10, SkPath::kCCW_Direction);
- path.addRect(2, 2, 4, 4, SkPath::kCCW_Direction);
- path.addRect(2, 6, 4, 8, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine82h() {
- SkPath path;
- path.addRect(0, 0, 6, 10, SkPath::kCCW_Direction);
- path.addRect(2, 2, 4, 4, SkPath::kCCW_Direction);
- path.addRect(2, 6, 4, 8, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine83() {
- SkPath path;
-path.addRect(10, 30, 30, 40, SkPath::kCCW_Direction);
-path.addRect(0, 12, 12, 18, SkPath::kCCW_Direction);
-path.addRect(4, 13, 13, 16, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine84() {
- SkPath path;
- path.addRect(0, 12, 60, 30, SkPath::kCCW_Direction);
- path.addRect(10, 20, 40, 30, SkPath::kCW_Direction);
- path.addRect(0, 12, 12, 12, SkPath::kCW_Direction);
- path.addRect(4, 12, 13, 13, SkPath::kCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine84x() {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 12, 60, 30, SkPath::kCCW_Direction);
- path.addRect(10, 20, 40, 30, SkPath::kCCW_Direction);
- path.addRect(0, 12, 12, 12, SkPath::kCCW_Direction);
- path.addRect(4, 12, 13, 13, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testLine85() {
- SkPath path;
- path.addRect(36, 0, 66, 60, SkPath::kCCW_Direction);
- path.addRect(20, 0, 40, 40, SkPath::kCCW_Direction);
- path.addRect(12, 0, 24, 24, SkPath::kCCW_Direction);
- path.addRect(32, 0, 36, 41, SkPath::kCCW_Direction);
- testSimplifyx(path);
-}
-
-static void testQuadralateral1() {
- SkPath path;
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.lineTo(0, 0);
- path.lineTo(3, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(2, 1);
- path.lineTo(2, 2);
- path.lineTo(2, 3);
- path.close();
- testSimplifyx(path);
-}
-
-static void testCubic1() {
- SkPath path;
- path.moveTo(0, 0);
- path.cubicTo(0, 1, 1, 1, 1, 0);
- path.close();
- path.moveTo(1, 0);
- path.cubicTo(0, 0, 0, 1, 1, 1);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuadratic93() {
- SkPath path;
- path.moveTo(3, 0);
- path.quadTo(0, 1, 3, 2);
- path.lineTo(0, 3);
- path.close();
- path.moveTo(1, 0);
- path.lineTo(2, 0);
- path.quadTo(1, 1, 2, 2);
- path.close();
- testSimplifyx(path);
-}
-
-static void cubicOp1d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(0,2, 1,0, 1,0);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,1);
- pathB.cubicTo(0,1, 1,0, 2,0);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp2d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,2);
- path.cubicTo(0,1, 1,0, 1,0);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,1);
- pathB.cubicTo(0,1, 2,0, 1,0);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp3d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(2,3, 1,0, 1,0);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,1);
- pathB.cubicTo(0,1, 1,0, 3,2);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp5d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(0,2, 1,0, 2,0);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,1);
- pathB.cubicTo(0,2, 1,0, 2,0);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp6d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(0,6, 1,0, 3,0);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,1);
- pathB.cubicTo(0,3, 1,0, 6,0);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp7d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(3,4, 1,0, 3,0);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,1);
- pathB.cubicTo(0,3, 1,0, 4,3);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp8d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(0,5, 1,0, 4,0);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,1);
- pathB.cubicTo(0,4, 1,0, 5,0);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp9d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(1,6, 1,0, 2,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,1);
- pathB.cubicTo(1,2, 1,0, 6,1);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void quadOp9d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.quadTo(1,6, 1.5f,1);
- path.quadTo(1.5f,0.5f, 2,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,1);
- pathB.quadTo(1,2, 1.4f,1);
- pathB.quadTo(3,0.4f, 6,1);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void lineOp9d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.lineTo(1,6);
- path.lineTo(1.5f,1);
- path.lineTo(1.8f,0.8f);
- path.lineTo(2,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,1);
- pathB.lineTo(1,2);
- pathB.lineTo(1.4f,1);
- pathB.lineTo(3,0.4f);
- pathB.lineTo(6,1);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp1i() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(1,2, 1,0, 2,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,1);
- pathB.cubicTo(1,2, 1,0, 2,1);
- pathB.close();
- testShapeOp(path, pathB, kIntersect_Op);
-}
-
-static void cubicOp10d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(1,3, 1,0, 4,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,1);
- pathB.cubicTo(1,4, 1,0, 3,1);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp11d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(3,4, 1,0, 5,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,1);
- pathB.cubicTo(1,5, 1,0, 4,3);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp12d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(1,6, 1,0, 1,0);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,1);
- pathB.cubicTo(0,1, 1,0, 6,1);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp13d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(4,5, 1,0, 5,3);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,1);
- pathB.cubicTo(3,5, 1,0, 5,4);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp14d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(0,2, 2,0, 2,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,2);
- pathB.cubicTo(1,2, 1,0, 2,0);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp15d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(3,6, 2,0, 2,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,2);
- pathB.cubicTo(1,2, 1,0, 6,3);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp16d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,2);
- path.cubicTo(0,1, 3,0, 1,0);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,3);
- pathB.cubicTo(0,1, 2,0, 1,0);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp17d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,2);
- path.cubicTo(0,2, 4,0, 2,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,4);
- pathB.cubicTo(1,2, 2,0, 2,0);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp18d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(3,5, 2,0, 2,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,2);
- pathB.cubicTo(1,2, 1,0, 5,3);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp19i() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,2);
- path.cubicTo(0,1, 2,1, 6,2);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(1,2);
- pathB.cubicTo(2,6, 2,0, 1,0);
- pathB.close();
- testShapeOp(path, pathB, kIntersect_Op);
-}
-
-static void cubicOp20d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(0,1, 6,0, 2,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,6);
- pathB.cubicTo(1,2, 1,0, 1,0);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp21d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(0,1, 2,1, 6,5);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(1,2);
- pathB.cubicTo(5,6, 1,0, 1,0);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp22d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(2,3, 3,0, 2,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,3);
- pathB.cubicTo(1,2, 1,0, 3,2);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp23d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(1,2, 4,0, 2,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,4);
- pathB.cubicTo(1,2, 1,0, 2,1);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp24d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(1,2, 2,0, 3,2);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,2);
- pathB.cubicTo(2,3, 1,0, 2,1);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void testIntersect1() {
- SkPath one, two;
- one.addRect(0, 0, 6, 6, SkPath::kCW_Direction);
- two.addRect(3, 3, 9, 9, SkPath::kCW_Direction);
- testShapeOp(one, two, kIntersect_Op);
-}
-
-static void testUnion1() {
- SkPath one, two;
- one.addRect(0, 0, 6, 6, SkPath::kCW_Direction);
- two.addRect(3, 3, 9, 9, SkPath::kCW_Direction);
- testShapeOp(one, two, kUnion_Op);
-}
-
-static void testDiff1() {
- SkPath one, two;
- one.addRect(0, 0, 6, 6, SkPath::kCW_Direction);
- two.addRect(3, 3, 9, 9, SkPath::kCW_Direction);
- testShapeOp(one, two, kDifference_Op);
-}
-
-static void testXor1() {
- SkPath one, two;
- one.addRect(0, 0, 6, 6, SkPath::kCW_Direction);
- two.addRect(3, 3, 9, 9, SkPath::kCW_Direction);
- testShapeOp(one, two, kXor_Op);
-}
-
-static void testIntersect2() {
- SkPath one, two;
- one.addRect(0, 0, 6, 6, SkPath::kCW_Direction);
- two.addRect(0, 3, 9, 9, SkPath::kCW_Direction);
- testShapeOp(one, two, kIntersect_Op);
-}
-
-static void testUnion2() {
- SkPath one, two;
- one.addRect(0, 0, 6, 6, SkPath::kCW_Direction);
- two.addRect(0, 3, 9, 9, SkPath::kCW_Direction);
- testShapeOp(one, two, kUnion_Op);
-}
-
-static void testDiff2() {
- SkPath one, two;
- one.addRect(0, 0, 6, 6, SkPath::kCW_Direction);
- two.addRect(0, 3, 9, 9, SkPath::kCW_Direction);
- testShapeOp(one, two, kDifference_Op);
-}
-
-static void testXor2() {
- SkPath one, two;
- one.addRect(0, 0, 6, 6, SkPath::kCW_Direction);
- two.addRect(0, 3, 9, 9, SkPath::kCW_Direction);
- testShapeOp(one, two, kXor_Op);
-}
-
-static void testOp1d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.addRect(0, 0, 1, 1, SkPath::kCW_Direction);
- path.addRect(0, 0, 2, 2, SkPath::kCW_Direction);
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.addRect(0, 0, 1, 1, SkPath::kCW_Direction);
- pathB.addRect(0, 0, 1, 1, SkPath::kCW_Direction);
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void testOp2d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.addRect(0, 0, 1, 1, SkPath::kCW_Direction);
- path.addRect(0, 0, 2, 2, SkPath::kCW_Direction);
- pathB.setFillType(SkPath::kEvenOdd_FillType);
- pathB.addRect(0, 0, 1, 1, SkPath::kCW_Direction);
- pathB.addRect(0, 0, 1, 1, SkPath::kCW_Direction);
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void testOp3d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.addRect(0, 0, 1, 1, SkPath::kCW_Direction);
- path.addRect(1, 1, 2, 2, SkPath::kCW_Direction);
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.addRect(0, 0, 1, 1, SkPath::kCW_Direction);
- pathB.addRect(0, 0, 1, 1, SkPath::kCW_Direction);
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void testOp1u() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.addRect(0, 0, 1, 1, SkPath::kCW_Direction);
- path.addRect(0, 0, 3, 3, SkPath::kCW_Direction);
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.addRect(0, 0, 1, 1, SkPath::kCW_Direction);
- pathB.addRect(0, 0, 1, 1, SkPath::kCW_Direction);
- testShapeOp(path, pathB, kUnion_Op);
-}
-
-static void testOp4d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.addRect(0, 0, 1, 1, SkPath::kCW_Direction);
- path.addRect(2, 2, 4, 4, SkPath::kCW_Direction);
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.addRect(0, 0, 1, 1, SkPath::kCW_Direction);
- pathB.addRect(0, 0, 1, 1, SkPath::kCW_Direction);
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void testOp5d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 2, 2, SkPath::kCW_Direction);
- path.addRect(0, 0, 3, 3, SkPath::kCW_Direction);
- pathB.setFillType(SkPath::kEvenOdd_FillType);
- pathB.addRect(0, 0, 1, 1, SkPath::kCW_Direction);
- pathB.addRect(0, 0, 1, 1, SkPath::kCW_Direction);
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void testOp6d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 1, 1, SkPath::kCW_Direction);
- path.addRect(0, 0, 3, 3, SkPath::kCW_Direction);
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.addRect(0, 0, 1, 1, SkPath::kCW_Direction);
- pathB.addRect(0, 0, 1, 1, SkPath::kCW_Direction);
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void testOp7d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 2, 2, SkPath::kCW_Direction);
- path.addRect(0, 0, 1, 1, SkPath::kCW_Direction);
- pathB.setFillType(SkPath::kEvenOdd_FillType);
- pathB.addRect(0, 0, 1, 1, SkPath::kCW_Direction);
- pathB.addRect(0, 0, 1, 1, SkPath::kCW_Direction);
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void testOp2u() {
- SkPath path, pathB;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 2, 2, SkPath::kCW_Direction);
- path.addRect(0, 0, 2, 2, SkPath::kCW_Direction);
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.addRect(0, 0, 3, 3, SkPath::kCW_Direction);
- pathB.addRect(1, 1, 2, 2, SkPath::kCW_Direction);
- testShapeOp(path, pathB, kUnion_Op);
-}
-
-static void testOp8d() {
- SkPath path, pathB;
- path.addRect(0, 0, 640, 480);
- pathB.moveTo(577330, 1971.72f);
- pathB.cubicTo(10.7082f, -116.596f, 262.057f, 45.6468f, 294.694f, 1.96237f);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-static void cubicOp25i() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(2,4, 5,0, 3,2);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,5);
- pathB.cubicTo(2,3, 1,0, 4,2);
- pathB.close();
- testShapeOp(path, pathB, kIntersect_Op);
-}
-
-static void cubicOp26d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(3,4, 4,0, 3,2);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,4);
- pathB.cubicTo(2,3, 1,0, 4,3);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp27d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(3,6, 1,0, 5,2);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,1);
- pathB.cubicTo(2,5, 1,0, 6,3);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp28u() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(1,4, 6,0, 3,2);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,6);
- pathB.cubicTo(2,3, 1,0, 4,1);
- pathB.close();
- testShapeOp(path, pathB, kUnion_Op);
-}
-
-static void cubicOp29d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(2,5, 6,0, 4,2);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,6);
- pathB.cubicTo(2,4, 1,0, 5,2);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp30d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(2,5, 6,0, 5,3);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,6);
- pathB.cubicTo(3,5, 1,0, 5,2);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp31d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,2);
- path.cubicTo(0,3, 2,1, 4,0);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(1,2);
- pathB.cubicTo(0,4, 2,0, 3,0);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp31u() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,2);
- path.cubicTo(0,3, 2,1, 4,0);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(1,2);
- pathB.cubicTo(0,4, 2,0, 3,0);
- pathB.close();
- testShapeOp(path, pathB, kUnion_Op);
-}
-
-static void cubicOp31x() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,2);
- path.cubicTo(0,3, 2,1, 4,0);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(1,2);
- pathB.cubicTo(0,4, 2,0, 3,0);
- pathB.close();
- testShapeOp(path, pathB, kXor_Op);
-}
-
-static void testCubic2() {
- SkPath path;
- path.moveTo(0,2);
- path.cubicTo(0,3, 2,1, 4,0);
- path.close();
- path.moveTo(1,2);
- path.cubicTo(0,4, 2,0, 3,0);
- path.close();
- testSimplifyx(path);
-}
-
-static void cubicOp32d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(1,2, 6,0, 3,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,6);
- pathB.cubicTo(1,3, 1,0, 2,1);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp33i() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(1,2, 6,0, 3,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,6);
- pathB.cubicTo(1,3, 1,0, 2,1);
- pathB.close();
- testShapeOp(path, pathB, kIntersect_Op);
-}
-
-static void cubicOp34d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(3,5, 2,1, 3,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(1,2);
- pathB.cubicTo(1,3, 1,0, 5,3);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp35d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(1,5, 2,1, 4,0);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(1,2);
- pathB.cubicTo(0,4, 1,0, 5,1);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp36u() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(1,6, 2,0, 5,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,2);
- pathB.cubicTo(1,5, 1,0, 6,1);
- pathB.close();
- testShapeOp(path, pathB, kUnion_Op);
-}
-
-static void cubicOp37d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(2,6, 6,1, 4,3);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(1,6);
- pathB.cubicTo(3,4, 1,0, 6,2);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-#if 1
-// this fails to detect a cubic/cubic intersection
-// the slight overlap is missed when the cubics are approximated by quadratics
-// and the subsequent line/cubic intersection also (correctly) misses the intersection
-// if the line/cubic was a matching line/approx.quadratic then the missing intersection
-// could have been detected
-static void cubicOp38d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(0,6, 3,2, 4,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(2,3);
- pathB.cubicTo(1,4, 1,0, 6,0);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-#endif
-
-static void cubicOp39d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(2,3, 5,1, 4,3);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(1,5);
- pathB.cubicTo(3,4, 1,0, 3,2);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp40d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(1,5, 3,2, 4,2);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(2,3);
- pathB.cubicTo(2,4, 1,0, 5,1);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp41i() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(2,6, 4,3, 6,4);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(3,4);
- pathB.cubicTo(4,6, 1,0, 6,2);
- pathB.close();
- testShapeOp(path, pathB, kIntersect_Op);
-}
-
-static void cubicOp42d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(1,2, 6,5, 5,4);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(5,6);
- pathB.cubicTo(4,5, 1,0, 2,1);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp43d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,2);
- path.cubicTo(1,2, 4,0, 3,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,4);
- pathB.cubicTo(1,3, 2,0, 2,1);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp44d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,2);
- path.cubicTo(3,6, 4,0, 3,2);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,4);
- pathB.cubicTo(2,3, 2,0, 6,3);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp45d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,2);
- path.cubicTo(2,4, 4,0, 3,2);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,4);
- pathB.cubicTo(2,3, 2,0, 4,2);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp46d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,2);
- path.cubicTo(3,5, 5,0, 4,2);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,5);
- pathB.cubicTo(2,4, 2,0, 5,3);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp47d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(1,6, 6,2, 5,4);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(2,6);
- pathB.cubicTo(4,5, 1,0, 6,1);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp48d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,2);
- path.cubicTo(2,3, 5,1, 3,2);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(1,5);
- pathB.cubicTo(2,3, 2,0, 3,2);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp49d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,2);
- path.cubicTo(1,5, 3,2, 4,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(2,3);
- pathB.cubicTo(1,4, 2,0, 5,1);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp50d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,3);
- path.cubicTo(1,6, 5,0, 5,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,5);
- pathB.cubicTo(1,5, 3,0, 6,1);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp51d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,3);
- path.cubicTo(1,2, 4,1, 6,0);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(1,4);
- pathB.cubicTo(0,6, 3,0, 2,1);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp52d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,2);
- path.cubicTo(1,2, 5,4, 4,3);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(4,5);
- pathB.cubicTo(3,4, 2,0, 2,1);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp53d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,3);
- path.cubicTo(1,2, 5,3, 2,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(3,5);
- pathB.cubicTo(1,2, 3,0, 2,1);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp54d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,4);
- path.cubicTo(1,3, 5,4, 4,2);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(4,5);
- pathB.cubicTo(2,4, 4,0, 3,1);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp55d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,5);
- path.cubicTo(1,3, 3,2, 5,0);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(2,3);
- pathB.cubicTo(0,5, 5,0, 3,1);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp56d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(2,6, 5,0, 2,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,5);
- pathB.cubicTo(1,2, 1,0, 6,2);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp57d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,5);
- path.cubicTo(0,5, 5,4, 6,4);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(4,5);
- pathB.cubicTo(4,6, 5,0, 5,0);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp58d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,5);
- path.cubicTo(3,4, 6,5, 5,3);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(5,6);
- pathB.cubicTo(3,5, 5,0, 4,3);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp59d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(5,6, 4,0, 4,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,4);
- pathB.cubicTo(1,4, 1,0, 6,5);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp60d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,2);
- path.cubicTo(4,6, 6,0, 5,2);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,6);
- pathB.cubicTo(2,5, 2,0, 6,4);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp61d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(1,2);
- path.cubicTo(0,5, 3,2, 6,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(2,3);
- pathB.cubicTo(1,6, 2,1, 5,0);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp62d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(1,3);
- path.cubicTo(5,6, 5,3, 5,4);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(3,5);
- pathB.cubicTo(4,5, 3,1, 6,5);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void cubicOp63d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(2,3);
- path.cubicTo(0,4, 3,2, 5,3);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(2,3);
- pathB.cubicTo(3,5, 3,2, 4,0);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void testQuad1() {
- SkPath path;
- path.moveTo(0,0);
- path.quadTo(0,0, 0,1);
- path.lineTo(1,1);
- path.close();
- path.moveTo(0,0);
- path.quadTo(1,1, 0,2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuad1z() {
- SkPath path;
- path.moveTo(0,0);
- path.quadTo(0,0, 0,1);
- path.lineTo(1,1);
- path.close();
- path.moveTo(0,0);
- path.lineTo(0.5f,1);
- path.lineTo(0,2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testQuad1c() {
- SkPath path;
- path.moveTo(0,0);
- path.quadTo(0,0, 0,1);
- path.lineTo(1,1);
- path.close();
- path.moveTo(0,0);
- path.cubicTo(0.5f,0.5f, 0.5f,1.5f, 0,2);
- path.close();
- testSimplifyx(path);
-}
-
-static void testRectOp1d() {
- SkPath path, pathB;
- path.moveTo(0,1);
- path.cubicTo(0,1, 1,0, 3,0);
- path.lineTo(0,1);
- path.close();
- pathB.moveTo(0,1);
- pathB.cubicTo(0,3, 1,0, 1,0);
- pathB.lineTo(0,1);
- pathB.close();
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void testCubicOp64d() {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.addRect(0, 0, 1, 1, SkPath::kCW_Direction);
- path.addRect(2, 2, 3, 3, SkPath::kCW_Direction);
- pathB.setFillType(SkPath::kEvenOdd_FillType);
- pathB.addRect(0, 0, 4, 4, SkPath::kCW_Direction);
- pathB.addRect(0, 0, 3, 3, SkPath::kCW_Direction);
- testShapeOp(path, pathB, kDifference_Op);
-}
-
-static void (*firstTest)() = testRectOp1d;
-
-static struct {
- void (*fun)();
- const char* str;
-} tests[] = {
- TEST(testRectOp1d),
- TEST(testCubicOp64d),
- TEST(testQuad1c),
- TEST(testQuad1z),
- TEST(testQuad1),
- TEST(testQuadratic93), // FIXME: gets stuck in a loop because top is unsortable
- TEST(cubicOp63d),
- TEST(cubicOp62d),
- TEST(cubicOp61d),
- TEST(cubicOp60d),
- TEST(cubicOp59d),
- TEST(cubicOp58d),
- TEST(cubicOp57d),
- TEST(cubicOp56d),
- TEST(cubicOp55d),
- TEST(cubicOp54d),
- TEST(cubicOp53d),
- TEST(cubicOp52d),
- TEST(cubicOp51d),
- TEST(cubicOp50d),
- TEST(cubicOp49d),
- TEST(cubicOp48d),
- TEST(cubicOp47d),
- TEST(cubicOp46d),
- TEST(cubicOp45d),
- TEST(cubicOp44d),
- TEST(cubicOp43d),
- TEST(cubicOp42d),
- TEST(cubicOp41i),
- TEST(cubicOp40d),
- TEST(cubicOp39d),
- TEST(cubicOp38d),
- TEST(cubicOp37d),
- TEST(cubicOp36u),
- TEST(cubicOp35d),
- TEST(cubicOp34d),
- TEST(cubicOp33i),
- TEST(cubicOp32d),
- TEST(cubicOp31d),
- TEST(testCubic2),
- TEST(cubicOp31x),
- TEST(cubicOp31u),
- TEST(cubicOp30d),
- TEST(cubicOp29d),
- TEST(cubicOp28u),
- TEST(cubicOp27d),
- TEST(cubicOp26d),
- TEST(cubicOp25i),
- TEST(testOp8d),
- TEST(testDiff1),
- TEST(testIntersect1),
- TEST(testUnion1),
- TEST(testXor1),
- TEST(testDiff2),
- TEST(testIntersect2),
- TEST(testUnion2),
- TEST(testXor2),
- TEST(testOp1d),
- TEST(testOp2d),
- TEST(testOp3d),
- TEST(testOp1u),
- TEST(testOp4d),
- TEST(testOp5d),
- TEST(testOp6d),
- TEST(testOp7d),
- TEST(testOp2u),
-
- TEST(cubicOp24d),
- TEST(cubicOp23d),
- TEST(cubicOp22d),
- TEST(cubicOp21d),
- TEST(cubicOp20d),
- TEST(cubicOp19i),
- TEST(cubicOp18d),
- TEST(cubicOp17d),
- TEST(cubicOp16d),
- TEST(cubicOp15d),
- TEST(cubicOp14d),
- TEST(cubicOp13d),
- TEST(cubicOp12d),
- TEST(cubicOp11d),
- TEST(cubicOp10d),
- TEST(cubicOp1i),
- TEST(cubicOp9d),
- TEST(quadOp9d),
- TEST(lineOp9d),
- TEST(cubicOp8d),
- TEST(cubicOp7d),
- TEST(cubicOp6d),
- TEST(cubicOp5d),
- TEST(cubicOp3d),
- TEST(cubicOp2d),
- TEST(cubicOp1d),
- TEST(testCubic1),
- TEST(testQuadralateral1),
- TEST(testLine85),
- TEST(testLine84),
- TEST(testLine84x),
- TEST(testLine83),
- TEST(testLine82h),
- TEST(testLine82g),
- TEST(testLine82f),
- TEST(testLine82e),
- TEST(testLine82d),
- TEST(testLine82c),
- TEST(testLine82b),
- TEST(testLine82a),
- TEST(testLine82),
- TEST(testQuadratic92x),
- TEST(testQuadratic91),
- TEST(testQuadratic90x),
- TEST(testQuadratic89x),
- TEST(testQuadratic88),
- TEST(testQuadratic87),
- TEST(testQuadratic86),
- TEST(testQuadratic85),
- TEST(testQuadratic84),
- TEST(testQuadratic83),
- TEST(testQuadratic82),
- TEST(testQuadratic81),
- TEST(testQuadratic80),
- TEST(testEight1),
- TEST(testEight2),
- TEST(testEight3),
- TEST(testEight4),
- TEST(testEight5),
- TEST(testEight6),
- TEST(testEight7),
- TEST(testEight8),
- TEST(testEight9),
- TEST(testEight10),
- TEST(testQuadratic79),
- TEST(testQuadratic78),
- TEST(testQuadratic77),
- TEST(testQuadratic76),
- TEST(testQuadratic75),
- TEST(testQuadratic74),
- TEST(testQuadratic73),
- TEST(testQuadratic72),
- TEST(testQuadratic71),
- TEST(testQuadratic70x),
- TEST(testQuadratic69),
- TEST(testQuadratic68),
- TEST(testQuadratic67x),
- TEST(testQuadratic65),
- TEST(testQuadratic64),
- TEST(testQuadratic63),
- TEST(testLine1a),
- TEST(testLine1ax),
- TEST(testQuadratic59),
- TEST(testQuadratic59x),
- TEST(testQuadratic58),
- TEST(testQuadratic56),
- TEST(testQuadratic55),
- TEST(testQuadratic53),
- TEST(testQuadratic51),
- TEST(testQuadratic38),
- TEST(testQuadratic37),
- TEST(testQuadratic36),
- TEST(testQuadratic35),
- TEST(testQuadratic34),
- TEST(testQuadratic33),
- TEST(testQuadratic32),
- TEST(testQuadratic31),
- TEST(testQuadratic30),
- TEST(testQuadratic29),
- TEST(testQuadratic28),
- TEST(testQuadratic27),
- TEST(testQuadratic26),
- TEST(testQuadratic25),
- TEST(testQuadratic24),
- TEST(testQuadratic23),
- TEST(testQuadratic22),
- TEST(testQuadratic21),
- TEST(testQuadratic20),
- TEST(testQuadratic19),
- TEST(testQuadratic18),
- TEST(testQuadratic17x),
- TEST(testQuadratic15),
- TEST(testQuadratic14),
- TEST(testQuadratic9),
- TEST(testQuadratic8),
- TEST(testQuadratic7),
- TEST(testQuadratic6),
- TEST(testQuadratic5),
- TEST(testQuadratic4x),
- TEST(testQuadratic3x),
- TEST(testQuadratic2x),
- TEST(testQuadratic1x),
- TEST(testQuadratic4),
- TEST(testQuadratic3),
- TEST(testQuadratic2),
- TEST(testQuadratic1),
- TEST(testLine4ax),
- TEST(testLine3aax),
- TEST(testLine2ax),
- TEST(testLine1ax),
- TEST(testQuadralateral9x),
- TEST(testQuadralateral8x),
- TEST(testQuadralateral7x),
- TEST(testQuadralateral6x),
- TEST(testQuadralateral6ax),
- TEST(testQuadralateral9),
- TEST(testQuadralateral8),
- TEST(testQuadralateral7),
- TEST(testQuadralateral6),
- TEST(testQuadralateral6a),
- TEST(testFauxQuadralateral6dx),
- TEST(testFauxQuadralateral6cx),
- TEST(testFauxQuadralateral6bx),
- TEST(testFauxQuadralateral6ax),
- TEST(testFauxQuadralateral6x),
- TEST(testFauxQuadralateral6d),
- TEST(testFauxQuadralateral6c),
- TEST(testFauxQuadralateral6b),
- TEST(testFauxQuadralateral6a),
- TEST(testFauxQuadralateral6),
- TEST(testQuadralateral5x),
- TEST(testQuadralateral5),
- TEST(testNondegenerate4x),
- TEST(testNondegenerate3x),
- TEST(testNondegenerate2x),
- TEST(testNondegenerate1x),
- TEST(testNondegenerate4),
- TEST(testNondegenerate3),
- TEST(testNondegenerate2),
- TEST(testNondegenerate1),
- TEST(testDegenerate4x),
- TEST(testDegenerate3x),
- TEST(testDegenerate2x),
- TEST(testDegenerate1x),
- TEST(testDegenerate4),
- TEST(testDegenerate3),
- TEST(testDegenerate2),
- TEST(testDegenerate1),
- TEST(testLine79x),
- TEST(testLine78x),
- TEST(testLine77x),
- TEST(testLine76x),
- TEST(testLine75x),
- TEST(testLine74x),
- TEST(testLine73x),
- TEST(testLine72x),
- TEST(testLine71x),
- TEST(testLine70x),
- TEST(testLine69x),
- TEST(testLine68hx),
- TEST(testLine68gx),
- TEST(testLine68fx),
- TEST(testLine68ex),
- TEST(testLine68dx),
- TEST(testLine68cx),
- TEST(testLine68bx),
- TEST(testLine68ax),
- TEST(testLine67x),
- TEST(testLine66x),
- TEST(testLine65x),
- TEST(testLine64x),
- TEST(testLine63x),
- TEST(testLine62x),
- TEST(testLine61x),
- TEST(testLine60x),
- TEST(testLine59x),
- TEST(testLine58x),
- TEST(testLine57x),
- TEST(testLine56x),
- TEST(testLine55x),
- TEST(testLine54x),
- TEST(testLine53x),
- TEST(testLine52x),
- TEST(testLine51x),
- TEST(testLine50x),
- TEST(testLine49x),
- TEST(testLine48x),
- TEST(testLine47x),
- TEST(testLine46x),
- TEST(testLine45x),
- TEST(testLine44x),
- TEST(testLine43x),
- TEST(testLine42x),
- TEST(testLine41x),
- TEST(testLine40x),
- TEST(testLine38x),
- TEST(testLine37x),
- TEST(testLine36x),
- TEST(testLine35x),
- TEST(testLine34x),
- TEST(testLine33x),
- TEST(testLine32x),
- TEST(testLine31x),
- TEST(testLine30x),
- TEST(testLine29x),
- TEST(testLine28x),
- TEST(testLine27x),
- TEST(testLine26x),
- TEST(testLine25x),
- TEST(testLine24ax),
- TEST(testLine24x),
- TEST(testLine23x),
- TEST(testLine22x),
- TEST(testLine21x),
- TEST(testLine20x),
- TEST(testLine19x),
- TEST(testLine18x),
- TEST(testLine17x),
- TEST(testLine16x),
- TEST(testLine15x),
- TEST(testLine14x),
- TEST(testLine13x),
- TEST(testLine12x),
- TEST(testLine11x),
- TEST(testLine10ax),
- TEST(testLine10x),
- TEST(testLine9x),
- TEST(testLine8x),
- TEST(testLine7bx),
- TEST(testLine7ax),
- TEST(testLine7x),
- TEST(testLine6x),
- TEST(testLine5x),
- TEST(testLine4x),
- TEST(testLine3bx),
- TEST(testLine3ax),
- TEST(testLine3x),
- TEST(testLine2x),
- TEST(testLine1x),
- TEST(testLine81),
- TEST(testLine80),
- TEST(testLine79),
- TEST(testLine78),
- TEST(testLine77),
- TEST(testLine76),
- TEST(testLine75),
- TEST(testLine74),
- TEST(testLine73),
- TEST(testLine72),
- TEST(testLine71),
- TEST(testLine70),
- TEST(testLine69),
- TEST(testLine68h),
- TEST(testLine68g),
- TEST(testLine68f),
- TEST(testLine68e),
- TEST(testLine68d),
- TEST(testLine68c),
- TEST(testLine68b),
- TEST(testLine68a),
- TEST(testLine67),
- TEST(testLine66),
- TEST(testLine65),
- TEST(testLine64),
- TEST(testLine63),
- TEST(testLine62),
- TEST(testLine61),
- TEST(testLine60),
- TEST(testLine59),
- TEST(testLine58),
- TEST(testLine57),
- TEST(testLine56),
- TEST(testLine55),
- TEST(testLine54),
- TEST(testLine53),
- TEST(testLine52),
- TEST(testLine51),
- TEST(testLine50),
- TEST(testLine49),
- TEST(testLine48),
- TEST(testLine47),
- TEST(testLine46),
- TEST(testLine45),
- TEST(testLine44),
- TEST(testLine43),
- TEST(testLine42),
- TEST(testLine41),
- TEST(testLine40),
- TEST(testLine38),
- TEST(testLine37),
- TEST(testLine36),
- TEST(testLine35),
- TEST(testLine34),
- TEST(testLine33),
- TEST(testLine32),
- TEST(testLine31),
- TEST(testLine30),
- TEST(testLine29),
- TEST(testLine28),
- TEST(testLine27),
- TEST(testLine26),
- TEST(testLine25),
- TEST(testLine24a),
- TEST(testLine24),
- TEST(testLine23),
- TEST(testLine22),
- TEST(testLine21),
- TEST(testLine20),
- TEST(testLine19),
- TEST(testLine18),
- TEST(testLine17),
- TEST(testLine16),
- TEST(testLine15),
- TEST(testLine14),
- TEST(testLine13),
- TEST(testLine12),
- TEST(testLine11),
- TEST(testLine10a),
- TEST(testLine10),
- TEST(testLine9),
- TEST(testLine8),
- TEST(testLine7b),
- TEST(testLine7a),
- TEST(testLine7),
- TEST(testLine6),
- TEST(testLine5),
- TEST(testLine4),
- TEST(testLine3b),
- TEST(testLine3a),
- TEST(testLine3),
- TEST(testLine2),
- TEST(testLine1),
-};
-
-static const size_t testCount = sizeof(tests) / sizeof(tests[0]);
-
-
-static struct {
- void (*fun)();
- const char* str;
-} subTests[] = {
- TEST(cubicOp43d),
- TEST(quadOp9d),
- TEST(cubicOp9d),
- TEST(cubicOp1i),
- TEST(cubicOp10d),
- TEST(cubicOp11d),
- TEST(cubicOp15d),
- TEST(cubicOp18d),
- TEST(cubicOp22d),
- TEST(cubicOp23d),
- TEST(cubicOp24d),
- TEST(cubicOp28u),
- TEST(cubicOp33i),
- TEST(cubicOp36u),
- TEST(cubicOp40d),
-};
-
-static const size_t subTestCount = sizeof(subTests) / sizeof(subTests[0]);
-
-static void (*firstSubTest)() = 0;
-
-static bool skipAll = false;
-static bool runSubTestsFirst = false;
-static bool runReverse = false;
-static void (*stopTest)() = 0;
-
-void SimplifyNew_Test() {
- if (skipAll) {
- return;
- }
-#ifdef SK_DEBUG
- gDebugMaxWindSum = 4;
- gDebugMaxWindValue = 4;
-#endif
- size_t index;
- if (runSubTestsFirst && firstSubTest) {
- index = subTestCount - 1;
- while (index > 0 && subTests[index].fun != firstSubTest) {
- --index;
- }
- SkDebugf(" %s [%s]\n", __FUNCTION__, subTests[index].str);
- (*subTests[index].fun)();
- }
- if (runSubTestsFirst) {
- index = subTestCount - 1;
- do {
- SkDebugf(" %s [%s]\n", __FUNCTION__, subTests[index].str);
- (*subTests[index].fun)();
- } while (index--);
- }
- index = testCount - 1;
- if (firstTest) {
- while (index > 0 && tests[index].fun != firstTest) {
- --index;
- }
- #if FORCE_RELEASE == 0
- SkDebugf("<div id=\"%s\">\n", tests[index].str);
- #endif
- SkDebugf(" %s [%s]\n", __FUNCTION__, tests[index].str);
- (*tests[index].fun)();
- }
- index = runReverse ? testCount - 1 : 0;
- size_t last = runReverse ? 0 : testCount - 1;
- bool firstTestComplete = false;
- do {
- SkDebugf(" %s [%s]\n", __FUNCTION__, tests[index].str);
- (*tests[index].fun)();
- firstTestComplete = true;
- if (tests[index].fun == stopTest) {
- SkDebugf("lastTest\n");
- }
- if (index == last) {
- break;
- }
- index += runReverse ? -1 : 1;
- } while (true);
- if (!runSubTestsFirst) {
- index = subTestCount - 1;
- do {
- SkDebugf(" %s [%s]\n", __FUNCTION__, subTests[index].str);
- (*subTests[index].fun)();
- } while (index--);
- }
-#ifdef SK_DEBUG
- gDebugMaxWindSum = SK_MaxS32;
- gDebugMaxWindValue = SK_MaxS32;
-#endif
-}
diff --git a/experimental/Intersection/SimplifyRect4x4_Test.cpp b/experimental/Intersection/SimplifyRect4x4_Test.cpp
deleted file mode 100644
index caa4597e20..0000000000
--- a/experimental/Intersection/SimplifyRect4x4_Test.cpp
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "EdgeWalker_Test.h"
-#include "Intersection_Tests.h"
-#include "ShapeOps.h"
-
-// four rects, of four sizes
-// for 3 smaller sizes, tall, wide
- // top upper mid lower bottom aligned (3 bits, 5 values)
- // same with x (3 bits, 5 values)
-// not included, square, tall, wide (2 bits)
-// cw or ccw (1 bit)
-
-static void* testSimplify4x4RectsMain(void* data)
-{
- SkASSERT(data);
- State4& state = *(State4*) data;
- char pathStr[1024]; // gdb: set print elements 400
- bzero(pathStr, sizeof(pathStr));
- do {
- int aShape = state.a & 0x03;
- SkPath::Direction aCW = state.a >> 2 ? SkPath::kCCW_Direction : SkPath::kCW_Direction;
- int bShape = state.b & 0x03;
- SkPath::Direction bCW = state.b >> 2 ? SkPath::kCCW_Direction : SkPath::kCW_Direction;
- int cShape = state.c & 0x03;
- SkPath::Direction cCW = state.c >> 2 ? SkPath::kCCW_Direction : SkPath::kCW_Direction;
- int dShape = state.d & 0x03;
- SkPath::Direction dCW = state.d >> 2 ? SkPath::kCCW_Direction : SkPath::kCW_Direction;
- for (int aXAlign = 0 ; aXAlign < 5; ++aXAlign) {
- for (int aYAlign = 0 ; aYAlign < 5; ++aYAlign) {
- for (int bXAlign = 0 ; bXAlign < 5; ++bXAlign) {
- for (int bYAlign = 0 ; bYAlign < 5; ++bYAlign) {
- for (int cXAlign = 0 ; cXAlign < 5; ++cXAlign) {
- for (int cYAlign = 0 ; cYAlign < 5; ++cYAlign) {
- for (int dXAlign = 0 ; dXAlign < 5; ++dXAlign) {
- for (int dYAlign = 0 ; dYAlign < 5; ++dYAlign) {
- SkPath path, out;
- char* str = pathStr;
- path.setFillType(SkPath::kWinding_FillType);
- int l, t, r, b;
- if (aShape) {
- switch (aShape) {
- case 1: // square
- l = 0; r = 60;
- t = 0; b = 60;
- aXAlign = 5;
- aYAlign = 5;
- break;
- case 2:
- l = aXAlign * 12;
- r = l + 30;
- t = 0; b = 60;
- aYAlign = 5;
- break;
- case 3:
- l = 0; r = 60;
- t = aYAlign * 12;
- b = l + 30;
- aXAlign = 5;
- break;
- }
- path.addRect(l, t, r, b, aCW);
- str += sprintf(str, " path.addRect(%d, %d, %d, %d,"
- " SkPath::kC%sW_Direction);\n", l, t, r, b, aCW ? "C" : "");
- } else {
- aXAlign = 5;
- aYAlign = 5;
- }
- if (bShape) {
- switch (bShape) {
- case 1: // square
- l = bXAlign * 10;
- r = l + 20;
- t = bYAlign * 10;
- b = l + 20;
- break;
- case 2:
- l = bXAlign * 10;
- r = l + 20;
- t = 10; b = 40;
- bYAlign = 5;
- break;
- case 3:
- l = 10; r = 40;
- t = bYAlign * 10;
- b = l + 20;
- bXAlign = 5;
- break;
- }
- path.addRect(l, t, r, b, bCW);
- str += sprintf(str, " path.addRect(%d, %d, %d, %d,"
- " SkPath::kC%sW_Direction);\n", l, t, r, b, bCW ? "C" : "");
- } else {
- bXAlign = 5;
- bYAlign = 5;
- }
- if (cShape) {
- switch (cShape) {
- case 1: // square
- l = cXAlign * 6;
- r = l + 12;
- t = cYAlign * 6;
- b = l + 12;
- break;
- case 2:
- l = cXAlign * 6;
- r = l + 12;
- t = 20; b = 30;
- cYAlign = 5;
- break;
- case 3:
- l = 20; r = 30;
- t = cYAlign * 6;
- b = l + 20;
- cXAlign = 5;
- break;
- }
- path.addRect(l, t, r, b, cCW);
- str += sprintf(str, " path.addRect(%d, %d, %d, %d,"
- " SkPath::kC%sW_Direction);\n", l, t, r, b, cCW ? "C" : "");
- } else {
- cXAlign = 5;
- cYAlign = 5;
- }
- if (dShape) {
- switch (dShape) {
- case 1: // square
- l = dXAlign * 4;
- r = l + 9;
- t = dYAlign * 4;
- b = l + 9;
- break;
- case 2:
- l = dXAlign * 6;
- r = l + 9;
- t = 32; b = 36;
- dYAlign = 5;
- break;
- case 3:
- l = 32; r = 36;
- t = dYAlign * 6;
- b = l + 9;
- dXAlign = 5;
- break;
- }
- path.addRect(l, t, r, b, dCW);
- str += sprintf(str, " path.addRect(%d, %d, %d, %d,"
- " SkPath::kC%sW_Direction);\n", l, t, r, b, dCW ? "C" : "");
- } else {
- dXAlign = 5;
- dYAlign = 5;
- }
- path.close();
- outputProgress(state, pathStr, SkPath::kWinding_FillType);
- testSimplifyx(path, false, out, state, pathStr);
- state.testsRun++;
- outputProgress(state, pathStr, SkPath::kEvenOdd_FillType);
- testSimplifyx(path, true, out, state, pathStr);
- state.testsRun++;
- }
- }
- }
- }
- }
- }
- }
- }
- } while (runNextTestSet(state));
- return NULL;
-}
-
-void Simplify4x4RectsThreaded_Test(int& testsRun)
-{
- SkDebugf("%s\n", __FUNCTION__);
-#ifdef SK_DEBUG
- gDebugMaxWindSum = 4;
- gDebugMaxWindValue = 4;
-#endif
- const char testLineStr[] = "testLine";
- initializeTests(testLineStr, sizeof(testLineStr));
- int testsStart = testsRun;
- for (int a = 0; a < 8; ++a) { // outermost
- for (int b = a ; b < 8; ++b) {
- for (int c = b ; c < 8; ++c) {
- for (int d = c; d < 8; ++d) {
- testsRun += dispatchTest4(testSimplify4x4RectsMain, a, b, c, d);
- }
- if (!gRunTestsInOneThread) SkDebugf(".");
- }
- if (!gRunTestsInOneThread) SkDebugf("%d", b);
- }
- if (!gRunTestsInOneThread) SkDebugf("\n%d", a);
- }
- testsRun += waitForCompletion();
- SkDebugf("%s tests=%d total=%d\n", __FUNCTION__, testsRun - testsStart, testsRun);
-}
diff --git a/experimental/Intersection/SkAntiEdge.cpp b/experimental/Intersection/SkAntiEdge.cpp
deleted file mode 100644
index 2cce960e52..0000000000
--- a/experimental/Intersection/SkAntiEdge.cpp
+++ /dev/null
@@ -1,1086 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "SkAntiEdge.h"
-#include "SkPoint.h"
-
-/** Returns the signed fraction of a SkFixed
- */
-static inline SkFixed SkFixedFraction(SkFixed x)
-{
- SkFixed mask = x >> 31 << 16;
- return (x & 0xFFFF) | mask;
-}
-
-void SkAntiEdge::pointOnLine(SkFixed x, SkFixed y) {
- float x0 = SkFixedToFloat(x);
- float y0 = SkFixedToFloat(y);
- float x1 = SkFixedToFloat(fFirstX);
- float y1 = SkFixedToFloat(fFirstY);
- float x2 = SkFixedToFloat(fLastX);
- float y2 = SkFixedToFloat(fLastY);
- float numer = (x2 - x1) * (y1 - y0) - (x1 - x0) * (y2 - y1);
- float denom = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);
- double dist = fabs(numer) / sqrt(denom);
- SkAssertResult(dist < 0.01);
-}
-
-void SkAntiEdge::pointInLine(SkFixed x, SkFixed y) {
- if (y == SK_MaxS32) {
- return;
- }
- pointOnLine(x, y);
- SkAssertResult(y >= fFirstY && y <= fLastY);
-}
-
-void SkAntiEdge::validate() {
- pointOnLine(fWalkX, fY);
- pointOnLine(fX, fWalkY);
-}
-
-bool SkAntiEdge::setLine(const SkPoint& p0, const SkPoint& p1) {
- fFirstY = SkScalarToFixed(p0.fY);
- fLastY = SkScalarToFixed(p1.fY);
- if (fFirstY == fLastY) {
- return false;
- }
- fFirstX = SkScalarToFixed(p0.fX);
- fLastX = SkScalarToFixed(p1.fX);
- if (fFirstY > fLastY) {
- SkTSwap(fFirstX, fLastX);
- SkTSwap(fFirstY, fLastY);
- fWinding = -1;
- } else {
- fWinding = 1;
- }
- SkFixed dx = fLastX - fFirstX;
- fDXFlipped = dx < 0;
- SkFixed dy = fLastY - fFirstY;
- fDX = SkFixedDiv(dx, dy);
- fDY = dx == 0 ? SK_MaxS32 : SkFixedDiv(dy, SkFixedAbs(dx));
- fLink = NULL;
- fLinkSet = false;
- return true;
-}
-
-void SkAntiEdge::calcLine() {
- SkFixed yStartFrac = SkFixedFraction(fFirstY);
- if (fDXFlipped) {
- SkFixed vert = SK_Fixed1 - yStartFrac; // distance from y start to x-axis
- fX0 = fFirstX + SkFixedMul(fDX, vert);
- SkFixed backupX = fFirstX + SkFixedMul(vert, fDX); // x cell to back up to
- SkFixed cellX = SkIntToFixed(SkFixedFloor(backupX));
- SkFixed endX = SkIntToFixed(SkFixedFloor(fLastX));
- if (cellX < endX) {
- cellX = endX;
- }
- SkFixed distX = fFirstX - cellX; // to y-axis
- fY0 = fFirstY + SkFixedMul(fDY, distX);
- SkFixed rowBottom = SkIntToFixed(SkFixedCeil(fFirstY + 1));
- if (fLastY > rowBottom) {
- fPartialY = 0;
- fX = fX0;
- fY = rowBottom;
- } else {
- fPartialY = SkFixedFraction(fLastY);
- fX = fLastX;
- fY = fLastY;
- }
- } else {
- fPartialY = yStartFrac;
- fX0 = fFirstX - SkFixedMul(fDX, yStartFrac);
- fY0 = fFirstY;
- if (fDY != SK_MaxS32) {
- SkFixed xStartFrac = SkFixedFraction(fFirstX);
- fY0 -= SkFixedMul(fDY, xStartFrac);
- }
- fX = fFirstX;
- fY = fFirstY;
- }
- fWalkX = fX;
- fWalkY = fY;
- fFinished = false;
-}
-
-static SkFixed SkFixedAddPin(SkFixed a, SkFixed b) {
- SkFixed result = a + b;
- if (((a ^ ~b) & (a ^ result)) >= 0) { // one positive, one negative
- return result; // or all three same sign
- }
- return a < 0 ? -SK_FixedMax : SK_FixedMax;
-}
-
-// edge is increasing in x and y
-uint16_t SkAntiEdge::advanceX(SkFixed left) {
- validate();
- SkFixed x = SkFixedAddPin(fX0, fDX);
- SkFixed wy = SkIntToFixed(SkFixedFloor(fWalkY + SK_Fixed1));
- pointOnLine(x, wy);
- SkFixed partial = SK_Fixed1 - fPartialY;
- SkFixed bottomPartial = wy - fLastY;
- if (bottomPartial > 0) {
- partial -= bottomPartial;
- }
- if (x > fLastX) {
- x = fLastX;
- wy = fLastY;
- }
- uint16_t coverage;
- if (left >= x) {
- fFinished = true;
- coverage = partial - 1; // walker is to the right of edge
- } else {
- SkFixed y = SkFixedAddPin(fY0, fDY);
- SkFixed wx = SkIntToFixed(SkFixedFloor(fWalkX + SK_Fixed1));
- if (fDY != SK_MaxS32) {
- pointOnLine(wx, y);
- }
- if (y > fLastY) {
- y = fLastY;
- wx = fLastX;
- }
- bool topCorner = fWalkX <= fX;
- bool bottomCorner = x <= wx;
- bool halfPlane = !(topCorner ^ bottomCorner);
- if (halfPlane) {
- if (x - SkIntToFixed(SkFixedFloor(fX)) <= SK_Fixed1) {
- coverage = ~((fX + x) >> 1); // avg of fx, fx+dx
- fFinished = true;
- if (x >= left + SK_Fixed1) {
- fWalkX = wx;
- fY = fY0 = y;
- }
- } else {
- SkAssertResult(y - SkIntToFixed(SkFixedFloor(fY)) <= SK_Fixed1);
- coverage = ((fY + y) >> 1);
- fFinished = y == fLastY;
- fWalkX = wx;
- fY = fY0 = y;
- }
- coverage = coverage * partial >> 16;
- } else if (topCorner) {
- SkFixed xDiff = wx - fX;
- SkAssertResult(xDiff >= 0);
- SkAssertResult(xDiff <= SK_Fixed1);
- SkFixed yDiff = y - fWalkY;
- // This may be a very small negative number if error accumulates
- // FIXME: for now, try setting it to zero in that case.
- if (yDiff < 0) {
- fX = fX0 = SkIntToFixed(SkFixedCeil(fX));
- yDiff = 0;
- }
- SkAssertResult(yDiff >= 0);
- SkAssertResult(yDiff <= SK_Fixed1);
- int xCoverage = xDiff >> 1; // throw away 1 bit so multiply
- int yCoverage = yDiff >> 1; // stays in range
- int triangle = xCoverage * yCoverage; // 30 bits
- SkFixed bottomPartial = y - fLastY;
- fFinished = bottomPartial >= 0;
- if (fFinished) {
- yCoverage = bottomPartial >> 1;
- xCoverage = (wx - fLastX) >> 1;
- triangle -= xCoverage * yCoverage;
- }
- coverage = triangle >> 15;
- fWalkX = wx;
- fY = fY0 = y;
- } else {
- SkAssertResult(bottomCorner);
- SkFixed xDiff = x - fWalkX;
- SkAssertResult(xDiff >= 0);
- SkAssertResult(xDiff <= SK_Fixed1);
- SkFixed yDiff = wy - fY;
- SkAssertResult(yDiff >= 0);
- SkAssertResult(yDiff <= SK_Fixed1);
- int xCoverage = xDiff >> 1; // throw away 1 bit so multiply
- int yCoverage = yDiff >> 1; // stays in range
- int triangle = xCoverage * yCoverage >> 15;
- coverage = partial - 1 - triangle;
- fFinished = true;
- }
- }
- validate();
- return coverage;
-}
-
-// edge is increasing in x, but decreasing in y
-uint16_t SkAntiEdge::advanceFlippedX(SkFixed left) {
- validate();
- SkFixed x = SkFixedAddPin(fX0, -fDX);
- SkFixed wy = SkIntToFixed(SkFixedFloor(fWalkY - 1));
- pointOnLine(x, wy);
- SkFixed partial = fPartialY ? fPartialY : SK_Fixed1;
- SkFixed topPartial = fFirstY - wy;
- if (topPartial > 0) {
- partial -= topPartial;
- }
- if (x > fFirstX) {
- x = fFirstX;
- wy = fFirstY;
- }
- uint16_t coverage;
- if (left >= x) {
- fFinished = true;
- coverage = partial - 1; // walker is to the right of edge
- } else {
- SkFixed y = SkFixedAddPin(fY0, -fDY);
- SkFixed wx = SkIntToFixed(SkFixedFloor(fWalkX + SK_Fixed1));
- pointOnLine(wx, y);
- if (y < fFirstY) {
- y = fFirstY;
- wx = fFirstX;
- }
- bool bottomCorner = fWalkX <= fX;
- bool topCorner = x <= wx;
- bool halfPlane = !(topCorner ^ bottomCorner);
- if (halfPlane) {
- if (x - SkIntToFixed(SkFixedFloor(fX)) <= SK_Fixed1) {
- coverage = ~((fX + x) >> 1); // avg of fx, fx+dx
- fFinished = true;
- } else {
- SkAssertResult(y - SkIntToFixed(SkFixedFloor(fY)) <= SK_Fixed1);
- coverage = ~((fY + y) >> 1);
- fFinished = y == fY;
- fWalkX = wx;
- fY = fY0 = y;
- }
- coverage = coverage * partial >> 16;
- } else if (bottomCorner) {
- SkFixed xDiff = wx - fX;
- SkAssertResult(xDiff >= 0);
- SkAssertResult(xDiff <= SK_Fixed1);
- SkFixed yDiff = fWalkY - y;
- SkAssertResult(yDiff >= 0);
- SkAssertResult(yDiff <= SK_Fixed1);
- int xCoverage = xDiff >> 1; // throw away 1 bit so multiply
- int yCoverage = yDiff >> 1; // stays in range
- int triangle = xCoverage * yCoverage; // 30 bits
- SkFixed bottomPartial = fFirstY - y;
- fFinished = bottomPartial >= 0;
- if (fFinished) {
- yCoverage = bottomPartial >> 1;
- xCoverage = (wx - fFirstX) >> 1;
- triangle -= xCoverage * yCoverage;
- }
- coverage = triangle >> 15;
- fWalkX = wx;
- fY = fY0 = y;
- } else {
- SkAssertResult(topCorner);
- SkFixed xDiff = x - fWalkX;
- SkAssertResult(xDiff >= 0);
- SkAssertResult(xDiff <= SK_Fixed1);
- SkFixed yDiff = fY - wy;
- SkAssertResult(yDiff >= 0);
- SkAssertResult(yDiff <= SK_Fixed1);
- int xCoverage = xDiff >> 1; // throw away 1 bit so multiply
- int yCoverage = yDiff >> 1; // stays in range
- int triangle = xCoverage * yCoverage >> 15;
- coverage = partial - 1 - triangle;
- fFinished = true;
- }
- }
- validate();
- return coverage;
-}
-
-void SkAntiEdge::advanceY(SkFixed top) {
- validate();
- fX0 = SkFixedAddPin(fX0, fDX);
- fPartialY = 0;
- if (fDXFlipped) {
- if (fX0 < fLastX) {
- fWalkX = fX = fLastX;
- } else {
- fWalkX = fX = fX0;
- }
- SkFixed bottom = top + SK_Fixed1;
- if (bottom > fLastY) {
- bottom = fLastY;
- }
- SkFixed vert = bottom - fFirstY; // distance from y start to x-axis
- SkFixed backupX = fFirstX + SkFixedMul(vert, fDX); // x cell to back up to
- SkFixed distX = fFirstX - SkIntToFixed(SkFixedFloor(backupX)); // to y-axis
- fY0 = fFirstY + SkFixedMul(fDY, distX);
-
- fY = top + SK_Fixed1;
- if (fY > fLastY) {
- fY = fLastY;
- }
- if (fLastY < top + SK_Fixed1) {
- fPartialY = SkFixedFraction(fLastY);
- }
- } else {
- if (fX0 > fLastX) {
- fX0 = fLastX;
- }
- fX = fX0;
- }
- fWalkY = SkIntToFixed(SkFixedFloor(fWalkY + SK_Fixed1));
- if (fWalkY > fLastY) {
- fWalkY = fLastY;
- }
- validate();
- fFinished = false;
-}
-
-int SkAntiEdgeBuilder::build(const SkPoint pts[], int count) {
- SkAntiEdge* edge = fEdges.append();
- for (int index = 0; index < count; ++index) {
- if (edge->setLine(pts[index], pts[(index + 1) % count])) {
- edge = fEdges.append();
- }
- }
- int result = fEdges.count();
- fEdges.setCount(--result);
- if (result > 0) {
- sk_bzero(&fHeadEdge, sizeof(fHeadEdge));
- sk_bzero(&fTailEdge, sizeof(fTailEdge));
- for (int index = 0; index < result; ++index) {
- *fList.append() = &fEdges[index];
- }
- }
- return result;
-}
-
-void SkAntiEdgeBuilder::calc() {
- for (SkAntiEdge* active = fEdges.begin(); active != fEdges.end(); ++active) {
- active->calcLine();
- }
- // compute winding sum for edges
- SkAntiEdge* first = fHeadEdge.fNext;
- SkAntiEdge* active;
- SkAntiEdge* listTop = first;
- for (active = first; active != &fTailEdge; active = active->fNext) {
- active->fWindingSum = active->fWinding;
- while (listTop->fLastY < active->fFirstY) {
- listTop = listTop->fNext;
- }
- for (SkAntiEdge* check = listTop; check->fFirstY <= active->fFirstY; check = check->fNext) {
- if (check == active) {
- continue;
- }
- if (check->fLastY <= active->fFirstY) {
- continue;
- }
- if (check->fFirstX > active->fFirstX) {
- continue;
- }
- if (check->fFirstX == active->fFirstX && check->fDX > active->fDX) {
- continue;
- }
- active->fWindingSum += check->fWinding;
- }
- }
-}
-
-extern "C" {
- static int edge_compare(const void* a, const void* b) {
- const SkAntiEdge* edgea = *(const SkAntiEdge**)a;
- const SkAntiEdge* edgeb = *(const SkAntiEdge**)b;
-
- int valuea = edgea->fFirstY;
- int valueb = edgeb->fFirstY;
-
- if (valuea == valueb) {
- valuea = edgea->fFirstX;
- valueb = edgeb->fFirstX;
- }
-
- if (valuea == valueb) {
- valuea = edgea->fDX;
- valueb = edgeb->fDX;
- }
-
- return valuea - valueb;
- }
-}
-
-void SkAntiEdgeBuilder::sort(SkTDArray<SkAntiEdge*>& listOfEdges) {
- SkAntiEdge** list = listOfEdges.begin();
- int count = listOfEdges.count();
- qsort(list, count, sizeof(SkAntiEdge*), edge_compare);
-
- // link the edges in sorted order
- for (int i = 1; i < count; i++) {
- list[i - 1]->fNext = list[i];
- list[i]->fPrev = list[i - 1];
- }
-}
-
-#define kEDGE_HEAD_XY SK_MinS32
-#define kEDGE_TAIL_XY SK_MaxS32
-
-void SkAntiEdgeBuilder::sort() {
- sort(fList);
- SkAntiEdge* last = fList.end()[-1];
- fHeadEdge.fNext = fList[0];
- fHeadEdge.fFirstX = fHeadEdge.fFirstY = fHeadEdge.fWalkY = fHeadEdge.fLastY = kEDGE_HEAD_XY;
- fList[0]->fPrev = &fHeadEdge;
-
- fTailEdge.fPrev = last;
- fTailEdge.fFirstX = fTailEdge.fFirstY = fTailEdge.fWalkY = fTailEdge.fLastY = kEDGE_TAIL_XY;
- last->fNext = &fTailEdge;
-}
-
-static inline void remove_edge(SkAntiEdge* edge) {
- edge->fPrev->fNext = edge->fNext;
- edge->fNext->fPrev = edge->fPrev;
-}
-
-static inline void swap_edges(SkAntiEdge* prev, SkAntiEdge* next) {
- SkASSERT(prev->fNext == next && next->fPrev == prev);
-
- // remove prev from the list
- prev->fPrev->fNext = next;
- next->fPrev = prev->fPrev;
-
- // insert prev after next
- prev->fNext = next->fNext;
- next->fNext->fPrev = prev;
- next->fNext = prev;
- prev->fPrev = next;
-}
-
-static void backward_insert_edge_based_on_x(SkAntiEdge* edge SkDECLAREPARAM(int, y)) {
- SkFixed x = edge->fFirstX;
-
- for (;;) {
- SkAntiEdge* prev = edge->fPrev;
-
- // add 1 to curr_y since we may have added new edges (built from curves)
- // that start on the next scanline
- SkASSERT(prev && SkFixedFloor(prev->fWalkY - prev->fDXFlipped) <= y + 1);
-
- if (prev->fFirstX <= x) {
- break;
- }
- swap_edges(prev, edge);
- }
-}
-
-static void insert_new_edges(SkAntiEdge* newEdge, SkFixed curr_y) {
- int y = SkFixedFloor(curr_y);
- if (SkFixedFloor(newEdge->fWalkY - newEdge->fDXFlipped) < y) {
- return;
- }
- while (SkFixedFloor(newEdge->fWalkY - newEdge->fDXFlipped) == y) {
- SkAntiEdge* next = newEdge->fNext;
- backward_insert_edge_based_on_x(newEdge SkPARAM(y));
- newEdge = next;
- }
-}
-
-static int find_active_edges(int y, SkAntiEdge** activeLeft,
- SkAntiEdge** activeLast) {
- SkAntiEdge* first = *activeLeft;
- SkFixed bottom = first->fLastY;
- SkAntiEdge* active = first->fNext;
- first->fLinkSet = false;
- SkFixed yLimit = SkIntToFixed(y + 1); // limiting pixel edge
- for ( ; active->fWalkY != kEDGE_TAIL_XY; active = active->fNext) {
- active->fLinkSet = false;
- if (yLimit <= active->fWalkY - active->fDXFlipped) {
- break;
- }
- if ((*activeLeft)->fWalkX > active->fWalkX) {
- *activeLeft = active;
- }
- if (bottom > active->fLastY) {
- bottom = active->fLastY;
- }
- }
- *activeLast = active;
- return SkFixedCeil(bottom);
-}
-
-// All edges are oriented to increase in y. Link edges with common tops and
-// bottoms so the links can share their winding sum.
-void SkAntiEdgeBuilder::link() {
- SkAntiEdge* tail = fEdges.end();
- // look for links forwards and backwards
- SkAntiEdge* prev = fEdges.begin();
- SkAntiEdge* active;
- for (active = prev + 1; active != tail; ++active) {
- if (prev->fWinding == active->fWinding) {
- if (prev->fLastX == active->fFirstX && prev->fLastY == active->fFirstY) {
- prev->fLink = active;
- active->fLinkSet = true;
- } else if (active->fLastX == prev->fFirstX && active->fLastY == prev->fFirstY) {
- active->fLink = prev;
- prev->fLinkSet = true;
- }
- }
- prev = active;
- }
- // look for stragglers
- prev = fEdges.begin() - 1;
- do {
- do {
- if (++prev == tail) {
- return;
- }
- } while (prev->fLinkSet || NULL != prev->fLink);
- for (active = prev + 1; active != tail; ++active) {
- if (active->fLinkSet || NULL != active->fLink) {
- continue;
- }
- if (prev->fWinding != active->fWinding) {
- continue;
- }
- if (prev->fLastX == active->fFirstX && prev->fLastY == active->fFirstY) {
- prev->fLink = active;
- active->fLinkSet = true;
- break;
- }
- if (active->fLastX == prev->fFirstX && active->fLastY == prev->fFirstY) {
- active->fLink = prev;
- prev->fLinkSet = true;
- break;
- }
- }
- } while (true);
-}
-
-void SkAntiEdgeBuilder::split(SkAntiEdge* edge, SkFixed y) {
- SkPoint upperPoint = {edge->fFirstX, edge->fFirstY};
- SkPoint midPoint = {edge->fFirstX + SkMulDiv(y - edge->fFirstY,
- edge->fLastX - edge->fFirstX, edge->fLastY - edge->fFirstY), y};
- SkPoint lowerPoint = {edge->fLastX, edge->fLastY};
- int8_t winding = edge->fWinding;
- edge->setLine(upperPoint, midPoint);
- edge->fWinding = winding;
- SkAntiEdge* lower = fEdges.append();
- lower->setLine(midPoint, lowerPoint);
- lower->fWinding = winding;
- insert_new_edges(lower, y);
-}
-
-// An edge computes pixel coverage by considering the integral winding value
-// to its left. If an edge is enclosed by fractional winding, split it.
-// FIXME: This is also a good time to find crossing edges and split them, too.
-void SkAntiEdgeBuilder::split() {
- // create a new set of edges that describe the whole link
- SkTDArray<SkAntiEdge> links;
- SkAntiEdge* first = fHeadEdge.fNext;
- SkAntiEdge* active;
- for (active = first; active != &fTailEdge; active = active->fNext) {
- if (active->fLinkSet || NULL == active->fLink) {
- continue;
- }
- SkAntiEdge* link = links.append();
- link->fFirstX = active->fFirstX;
- link->fFirstY = active->fFirstY;
- SkAntiEdge* linkEnd;
- SkAntiEdge* next = active;
- do {
- linkEnd = next;
- next = next->fLink;
- } while (NULL != next);
- link->fLastX = linkEnd->fLastX;
- link->fLastY = linkEnd->fLastY;
- }
- // create a list of all edges, links and singletons
- SkTDArray<SkAntiEdge*> list;
- for (active = links.begin(); active != links.end(); ++active) {
- *list.append() = active;
- }
- for (active = first; active != &fTailEdge; active = active->fNext) {
- if (!active->fLinkSet && NULL == active->fLink) {
- SkAntiEdge* link = links.append();
- link->fFirstX = active->fFirstX;
- link->fFirstY = active->fFirstY;
- link->fLastX = active->fLastX;
- link->fLastY = active->fLastY;
- *list.append() = link;
- }
- }
- SkAntiEdge tail;
- tail.fFirstY = tail.fLastY = kEDGE_TAIL_XY;
- *list.append() = &tail;
- sort(list);
- // walk the list, splitting edges partially occluded on the left
- SkAntiEdge* listTop = list[0];
- for (active = first; active != &fTailEdge; active = active->fNext) {
- while (listTop->fLastY < active->fFirstY) {
- listTop = listTop->fNext;
- }
- for (SkAntiEdge* check = listTop; check->fFirstY < active->fLastY; check = check->fNext) {
- if (check->fFirstX > active->fFirstX) {
- continue;
- }
- if (check->fFirstX == active->fFirstX && check->fDX > active->fDX) {
- continue;
- }
- if (check->fFirstY > active->fFirstY) {
- split(active, check->fFirstY);
- }
- if (check->fLastY < active->fLastY) {
- split(active, check->fLastY);
- }
- }
- }
-}
-
-static inline uint8_t coverage_to_8(int coverage) {
- uint16_t x = coverage < 0 ? 0 : coverage > 0xFFFF ? 0xFFFF : coverage;
- // for values 0x7FFF and smaller, add (0x7F - high byte) and trunc
- // for values 0x8000 and larger, subtract (high byte - 0x80) and trunc
- return (x + 0x7f + (x >> 15) - (x >> 8)) >> 8;
-}
-
-void SkAntiEdgeBuilder::walk(uint8_t* result, int rowBytes, int height) {
- SkAntiEdge* first = fHeadEdge.fNext;
- SkFixed top = first->fWalkY - first->fDXFlipped;
- int y = SkFixedFloor(top);
- do {
- SkAntiEdge* activeLeft = first;
- SkAntiEdge* activeLast, * active;
- int yLast = find_active_edges(y, &activeLeft, &activeLast);
- while (y < yLast) {
- SkAssertResult(y >= 0);
- SkAssertResult(y < height);
- SkFixed left = activeLeft->fWalkX;
- int x = SkFixedFloor(left);
- uint8_t* resultPtr = &result[y * rowBytes + x];
- bool finished;
- do {
- left = SkIntToFixed(x);
- SkAssertResult(x >= 0);
- // SkAssertResult(x < pixelCol);
- if (x >= rowBytes) { // FIXME: cumulative error in fX += fDX
- break; // fails to set fFinished early enough
- } // see test 6 (dy<dx)
- finished = true;
- int coverage = 0;
- for (active = first; active != activeLast; active = active->fNext) {
- if (left + SK_Fixed1 <= active->fX) {
- finished = false;
- continue; // walker is to the left of edge
- }
- int cover = active->fDXFlipped ?
- active->advanceFlippedX(left) : active->advanceX(left);
- if (0 == active->fWindingSum) {
- cover = -cover;
- }
- coverage += cover;
- finished &= active->fFinished;
- }
- uint8_t old = *resultPtr;
- uint8_t pix = coverage_to_8(coverage);
- uint8_t blend = old > pix ? old : pix;
- *resultPtr++ = blend;
- ++x;
- } while (!finished);
- ++y;
- top = SkIntToFixed(y);
- SkFixed topLimit = top + SK_Fixed1;
- SkFixed xSort = -SK_FixedMax;
- for (active = first; active != activeLast; active = active->fNext) {
- if (xSort > active->fX || topLimit > active->fLastY) {
- yLast = y; // recompute bottom after all Ys are advanced
- }
- xSort = active->fX;
- if (active->fWalkY < active->fLastY) {
- active->advanceY(top);
- }
- }
- for (active = first; active != activeLast; ) {
- SkAntiEdge* next = active->fNext;
- if (top >= active->fLastY) {
- remove_edge(active);
- }
- active = next;
- }
- first = fHeadEdge.fNext;
- }
- SkAntiEdge* prev = activeLast->fPrev;
- if (prev != &fHeadEdge) {
- insert_new_edges(prev, top);
- first = fHeadEdge.fNext;
- }
- } while (first->fWalkY < kEDGE_TAIL_XY);
-}
-
-void SkAntiEdgeBuilder::process(const SkPoint* points, int ptCount,
- uint8_t* result, int pixelCol, int pixelRow) {
- if (ptCount < 3) {
- return;
- }
- int count = build(points, ptCount);
- if (count == 0) {
- return;
- }
- SkAssertResult(count > 1);
- link();
- sort();
- split();
- calc();
- walk(result, pixelCol, pixelRow);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-int test3by3_test;
-
-// input is a rectangle
-static void test_3_by_3() {
- const int pixelRow = 3;
- const int pixelCol = 3;
- const int ptCount = 4;
- const int pixelCount = pixelRow * pixelCol;
- const SkPoint tests[][ptCount] = {
- {{2.0f, 1.0f}, {1.0f, 1.0f}, {1.0f, 2.0f}, {2.0f, 2.0f}}, // 0: full rect
- {{2.5f, 1.0f}, {1.5f, 1.0f}, {1.5f, 2.0f}, {2.5f, 2.0f}}, // 1: y edge
- {{2.0f, 1.5f}, {1.0f, 1.5f}, {1.0f, 2.5f}, {2.0f, 2.5f}}, // 2: x edge
- {{2.5f, 1.5f}, {1.5f, 1.5f}, {1.5f, 2.5f}, {2.5f, 2.5f}}, // 3: x/y edge
- {{2.8f, 0.2f}, {0.2f, 0.2f}, {0.2f, 2.8f}, {2.8f, 2.8f}}, // 4: large
- {{1.8f, 1.2f}, {1.2f, 1.2f}, {1.2f, 1.8f}, {1.8f, 1.8f}}, // 5: small
- {{0.0f, 0.0f}, {0.0f, 1.0f}, {3.0f, 2.0f}, {3.0f, 1.0f}}, // 6: dy<dx
- {{3.0f, 0.0f}, {0.0f, 1.0f}, {0.0f, 2.0f}, {3.0f, 1.0f}}, // 7: dy<-dx
- {{1.0f, 0.0f}, {0.0f, 0.0f}, {1.0f, 3.0f}, {2.0f, 3.0f}}, // 8: dy>dx
- {{2.0f, 0.0f}, {1.0f, 0.0f}, {0.0f, 3.0f}, {1.0f, 3.0f}}, // 9: dy>-dx
- {{0.5f, 0.5f}, {0.5f, 1.5f}, {2.5f, 2.5f}, {2.5f, 1.5f}}, // 10: dy<dx 2
- {{2.5f, 0.5f}, {0.5f, 1.5f}, {0.5f, 2.5f}, {2.5f, 1.5f}}, // 11: dy<-dx 2
- {{0.0f, 0.0f}, {2.0f, 0.0f}, {2.0f, 2.0f}, {0.0f, 2.0f}}, // 12: 2x2
- {{0.0f, 0.0f}, {3.0f, 0.0f}, {3.0f, 3.0f}, {0.0f, 3.0f}}, // 13: 3x3
- {{1.75f, 0.25f}, {2.75f, 1.25f}, {1.25f, 2.75f}, {0.25f, 1.75f}}, // 14
- {{2.25f, 0.25f}, {2.75f, 0.75f}, {0.75f, 2.75f}, {0.25f, 2.25f}}, // 15
- {{0.25f, 0.75f}, {0.75f, 0.25f}, {2.75f, 2.25f}, {2.25f, 2.75f}}, // 16
- {{1.25f, 0.50f}, {1.75f, 0.25f}, {2.75f, 2.25f}, {2.25f, 2.50f}}, // 17
- {{1.00f, 0.75f}, {2.00f, 0.50f}, {2.00f, 1.50f}, {1.00f, 1.75f}}, // 18
- {{1.00f, 0.50f}, {2.00f, 0.75f}, {2.00f, 1.75f}, {1.00f, 1.50f}}, // 19
- {{1.00f, 0.75f}, {1.00f, 1.75f}, {2.00f, 1.50f}, {2.00f, 0.50f}}, // 20
- {{1.00f, 0.50f}, {1.00f, 1.50f}, {2.00f, 1.75f}, {2.00f, 0.75f}}, // 21
- };
- const uint8_t results[][pixelCount] = {
- {0x00, 0x00, 0x00, // 0: 1 pixel rect
- 0x00, 0xFF, 0x00,
- 0x00, 0x00, 0x00},
- {0x00, 0x00, 0x00, // 1: y edge
- 0x00, 0x7F, 0x80,
- 0x00, 0x00, 0x00},
- {0x00, 0x00, 0x00, // 2: x edge
- 0x00, 0x7F, 0x00,
- 0x00, 0x7F, 0x00},
- {0x00, 0x00, 0x00, // 3: x/y edge
- 0x00, 0x40, 0x40,
- 0x00, 0x40, 0x40},
- {0xA3, 0xCC, 0xA3, // 4: large
- 0xCC, 0xFF, 0xCC,
- 0xA3, 0xCC, 0xA3},
- {0x00, 0x00, 0x00, // 5: small
- 0x00, 0x5C, 0x00,
- 0x00, 0x00, 0x00},
- {0xD5, 0x80, 0x2B, // 6: dy<dx
- 0x2A, 0x7F, 0xD4,
- 0x00, 0x00, 0x00},
- {0x2B, 0x80, 0xD5, // 7: dy<-dx
- 0xD4, 0x7F, 0x2A,
- 0x00, 0x00, 0x00},
- {0xD5, 0x2A, 0x00, // 8: dy>dx
- 0x80, 0x7F, 0x00,
- 0x2B, 0xD4, 0x00},
- {0x2A, 0xD5, 0x00, // 9: dy>-dx
- 0x7F, 0x80, 0x00,
- 0xD4, 0x2B, 0x00},
- {0x30, 0x10, 0x00, // 10: dy<dx 2
- 0x50, 0xDF, 0x50,
- 0x00, 0x10, 0x30},
- {0x00, 0x10, 0x30, // 11: dy<-dx 2
- 0x50, 0xDF, 0x50,
- 0x30, 0x10, 0x00},
- {0xFF, 0xFF, 0x00, // 12: 2x2
- 0xFF, 0xFF, 0x00,
- 0x00, 0x00, 0x00},
- {0xFF, 0xFF, 0xFF, // 13: 3x3
- 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF},
- {0x00, 0x70, 0x20, // 14
- 0x70, 0xFF, 0x70,
- 0x20, 0x70, 0x00},
- {0x00, 0x20, 0x60, // 15
- 0x20, 0xBF, 0x20,
- 0x60, 0x20, 0x00},
- {0x60, 0x20, 0x00, // 16
- 0x20, 0xBF, 0x20,
- 0x00, 0x20, 0x60},
- {0x00, 0x60, 0x04, // 17
- 0x00, 0x40, 0x60,
- 0x00, 0x00, 0x3C},
- {0x00, 0x60, 0x00, // 18
- 0x00, 0x9F, 0x00,
- 0x00, 0x00, 0x00},
- {0x00, 0x60, 0x00, // 19
- 0x00, 0x9F, 0x00,
- 0x00, 0x00, 0x00},
- {0x00, 0x60, 0x00, // 20
- 0x00, 0x9F, 0x00,
- 0x00, 0x00, 0x00},
- {0x00, 0x60, 0x00, // 21
- 0x00, 0x9F, 0x00,
- 0x00, 0x00, 0x00},
- };
- const int testCount = sizeof(tests) / sizeof(tests[0]);
- SkAssertResult(testCount == sizeof(results) / sizeof(results[0]));
- int testFirst = test3by3_test < 0 ? 0 : test3by3_test;
- int testLast = test3by3_test < 0 ? testCount : test3by3_test + 1;
- for (int testIndex = testFirst; testIndex < testLast; ++testIndex) {
- uint8_t result[pixelRow][pixelCol];
- sk_bzero(result, sizeof(result));
- const SkPoint* rect = tests[testIndex];
- SkAntiEdgeBuilder builder;
- builder.process(rect, ptCount, result[0], pixelCol, pixelRow);
- SkAssertResult(memcmp(results[testIndex], result[0], pixelCount) == 0);
- }
-}
-
-// input has arbitrary number of points
-static void test_arbitrary_3_by_3() {
- const int pixelRow = 3;
- const int pixelCol = 3;
- const int pixelCount = pixelRow * pixelCol;
- const SkPoint t1[] = { {1,1}, {2,1}, {2,1.5f}, {1,1.5f}, {1,2}, {2,2},
- {2,1.5f}, {1,1.5f}, {1,1} };
- const SkPoint* tests[] = { t1 };
- size_t testPts[] = { sizeof(t1) / sizeof(t1[0]) };
- const uint8_t results[][pixelCount] = {
- {0x00, 0x00, 0x00, // 0: 1 pixel rect
- 0x00, 0xFF, 0x00,
- 0x00, 0x00, 0x00},
- };
- const int testCount = sizeof(tests) / sizeof(tests[0]);
- SkAssertResult(testCount == sizeof(results) / sizeof(results[0]));
- int testFirst = test3by3_test < 0 ? 0 : test3by3_test;
- int testLast = test3by3_test < 0 ? testCount : test3by3_test + 1;
- for (int testIndex = testFirst; testIndex < testLast; ++testIndex) {
- uint8_t result[pixelRow][pixelCol];
- sk_bzero(result, sizeof(result));
- const SkPoint* pts = tests[testIndex];
- size_t ptCount = testPts[testIndex];
- SkAntiEdgeBuilder builder;
- builder.process(pts, ptCount, result[0], pixelCol, pixelRow);
- SkAssertResult(memcmp(results[testIndex], result[0], pixelCount) == 0);
- }
-}
-
-#include "SkRect.h"
-#include "SkPath.h"
-
-int testsweep_test;
-
-static void create_sweep(uint8_t* result, int pixelRow, int pixelCol, SkScalar rectWidth) {
- const int ptCount = 4;
- SkRect refRect = {pixelCol / 2 - rectWidth / 2, 5,
- pixelCol / 2 + rectWidth / 2, pixelRow / 2 - 5};
- SkPath refPath;
- refPath.addRect(refRect);
- SkScalar angleFirst = testsweep_test < 0 ? 0 : testsweep_test;
- SkScalar angleLast = testsweep_test < 0 ? 360 : testsweep_test + 1;
- for (SkScalar angle = angleFirst; angle < angleLast; angle += 12) {
- SkPath rotPath;
- SkMatrix matrix;
- matrix.setRotate(angle, SkIntToScalar(pixelCol) / 2,
- SkIntToScalar(pixelRow) / 2);
- refPath.transform(matrix, &rotPath);
- SkPoint rect[ptCount], temp[2];
- SkPath::Iter iter(rotPath, false);
- int index = 0;
- for (;;) {
- SkPath::Verb verb = iter.next(temp);
- if (verb == SkPath::kMove_Verb) {
- continue;
- }
- if (verb == SkPath::kClose_Verb) {
- break;
- }
- SkAssertResult(SkPath::kLine_Verb == verb);
- rect[index++] = temp[0];
- }
- SkAntiEdgeBuilder builder;
- builder.process(rect, ptCount, result, pixelCol, pixelRow);
- }
-}
-
-static void create_horz(uint8_t* result, int pixelRow, int pixelCol) {
- const int ptCount = 4;
- for (SkScalar x = 0; x < 100; x += 5) {
- SkPoint rect[ptCount];
- rect[0].fX = 0; rect[0].fY = x;
- rect[1].fX = 100; rect[1].fY = x;
- rect[2].fX = 100; rect[2].fY = x + x / 50;
- rect[3].fX = 0; rect[3].fY = x + x / 50;
- SkAntiEdgeBuilder builder;
- builder.process(rect, ptCount, result, pixelCol, pixelRow);
- }
-}
-
-static void create_vert(uint8_t* result, int pixelRow, int pixelCol) {
- const int ptCount = 4;
- for (SkScalar x = 0; x < 100; x += 5) {
- SkPoint rect[ptCount];
- rect[0].fY = 0; rect[0].fX = x;
- rect[1].fY = 100; rect[1].fX = x;
- rect[2].fY = 100; rect[2].fX = x + x / 50;
- rect[3].fY = 0; rect[3].fX = x + x / 50;
- SkAntiEdgeBuilder builder;
- builder.process(rect, ptCount, result, pixelCol, pixelRow);
- }
-}
-
-static void create_angle(uint8_t* result, int pixelRow, int pixelCol, SkScalar angle) {
- const int ptCount = 4;
- SkRect refRect = {25, 25, 125, 125};
- SkPath refPath;
- for (SkScalar x = 30; x < 125; x += 5) {
- refRect.fTop = x;
- refRect.fBottom = x + (x - 25) / 50;
- refPath.addRect(refRect);
- }
- SkPath rotPath;
- SkMatrix matrix;
- matrix.setRotate(angle, 75, 75);
- refPath.transform(matrix, &rotPath);
- SkPath::Iter iter(rotPath, false);
- for (SkScalar x = 30; x < 125; x += 5) {
- SkPoint rect[ptCount], temp[2];
- int index = 0;
- for (;;) {
- SkPath::Verb verb = iter.next(temp);
- if (verb == SkPath::kMove_Verb) {
- continue;
- }
- if (verb == SkPath::kClose_Verb) {
- break;
- }
- SkAssertResult(SkPath::kLine_Verb == verb);
- rect[index++] = temp[0];
- }
- // if ((x == 30 || x == 75) && angle == 12) continue;
- SkAntiEdgeBuilder builder;
- builder.process(rect, ptCount, result, pixelCol, pixelRow);
- }
-}
-
-static void test_sweep() {
- const int pixelRow = 100;
- const int pixelCol = 100;
- uint8_t result[pixelRow][pixelCol];
- sk_bzero(result, sizeof(result));
- create_sweep(result[0], pixelRow, pixelCol, 1);
-}
-
-static void test_horz() {
- const int pixelRow = 100;
- const int pixelCol = 100;
- uint8_t result[pixelRow][pixelCol];
- sk_bzero(result, sizeof(result));
- create_horz(result[0], pixelRow, pixelCol);
-}
-
-static void test_vert() {
- const int pixelRow = 100;
- const int pixelCol = 100;
- uint8_t result[pixelRow][pixelCol];
- sk_bzero(result, sizeof(result));
- create_vert(result[0], pixelRow, pixelCol);
-}
-
-static void test_angle(SkScalar angle) {
- const int pixelRow = 150;
- const int pixelCol = 150;
- uint8_t result[pixelRow][pixelCol];
- sk_bzero(result, sizeof(result));
- create_angle(result[0], pixelRow, pixelCol, angle);
-}
-
-#include "SkBitmap.h"
-
-void CreateSweep(SkBitmap* sweep, SkScalar rectWidth) {
- const int pixelRow = 100;
- const int pixelCol = 100;
- sweep->setConfig(SkBitmap::kA8_Config, pixelCol, pixelRow);
- sweep->allocPixels();
- sweep->eraseColor(SK_ColorTRANSPARENT);
- sweep->lockPixels();
- void* pixels = sweep->getPixels();
- create_sweep((uint8_t*) pixels, pixelRow, pixelCol, rectWidth);
- sweep->unlockPixels();
-}
-
-void CreateHorz(SkBitmap* sweep) {
- const int pixelRow = 100;
- const int pixelCol = 100;
- sweep->setConfig(SkBitmap::kA8_Config, pixelCol, pixelRow);
- sweep->allocPixels();
- sweep->eraseColor(SK_ColorTRANSPARENT);
- sweep->lockPixels();
- void* pixels = sweep->getPixels();
- create_horz((uint8_t*) pixels, pixelRow, pixelCol);
- sweep->unlockPixels();
-}
-
-void CreateVert(SkBitmap* sweep) {
- const int pixelRow = 100;
- const int pixelCol = 100;
- sweep->setConfig(SkBitmap::kA8_Config, pixelCol, pixelRow);
- sweep->allocPixels();
- sweep->eraseColor(SK_ColorTRANSPARENT);
- sweep->lockPixels();
- void* pixels = sweep->getPixels();
- create_vert((uint8_t*) pixels, pixelRow, pixelCol);
- sweep->unlockPixels();
-}
-
-void CreateAngle(SkBitmap* sweep, SkScalar angle) {
- const int pixelRow = 150;
- const int pixelCol = 150;
- sweep->setConfig(SkBitmap::kA8_Config, pixelCol, pixelRow);
- sweep->allocPixels();
- sweep->eraseColor(SK_ColorTRANSPARENT);
- sweep->lockPixels();
- void* pixels = sweep->getPixels();
- create_angle((uint8_t*) pixels, pixelRow, pixelCol, angle);
- sweep->unlockPixels();
-}
-
-#include "SkCanvas.h"
-
-static void testPng() {
- SkBitmap device;
- device.setConfig(SkBitmap::kARGB_8888_Config, 4, 4);
- device.allocPixels();
- device.eraseColor(0xFFFFFFFF);
-
- SkCanvas canvas(device);
- canvas.drawARGB(167, 0, 0, 0);
-
- device.lockPixels();
- unsigned char* pixels = (unsigned char*) device.getPixels();
- SkDebugf("%02x%02x%02x%02x", pixels[3], pixels[2], pixels[1], pixels[0]);
-}
-
-void SkAntiEdge_Test() {
- testPng();
- test_arbitrary_3_by_3();
- test_angle(12);
-#if 0
- test3by3_test = 18;
-#else
- test3by3_test = -1;
-#endif
-#if 0
- testsweep_test = 7 * 12;
-#else
- testsweep_test = -1;
-#endif
- if (testsweep_test == -1) {
- test_3_by_3();
- }
- test_sweep();
- test_horz();
- test_vert();
-}
diff --git a/experimental/Intersection/SkAntiEdge.h b/experimental/Intersection/SkAntiEdge.h
deleted file mode 100644
index 17baca6d4d..0000000000
--- a/experimental/Intersection/SkAntiEdge.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#ifndef SkAntiEdge_DEFINED
-#define SkAntiEdge_DEFINED
-
-#include "SkFixed.h"
-#include "SkTDArray.h"
-
-struct SkBitmap;
-struct SkPoint;
-
-struct SkAntiEdge {
- SkAntiEdge* fNext; // list in walking order (y, then x, then diag)
- SkAntiEdge* fPrev; // reverse in walking order
- SkAntiEdge* fLink; // list in connected order, top to bottom
-
- SkFixed fFirstX; // starting X
- SkFixed fFirstY; // starting Y
- SkFixed fLastX; // ending X
- SkFixed fLastY; // ending Y
- SkFixed fX0; // computed edge current value (may be off end)
- SkFixed fY0;
- SkFixed fX; // edge current value (always on edge)
- SkFixed fY;
- SkFixed fDX; // change in X per unit step in Y
- SkFixed fDY; // change in Y per unit step in X
- SkFixed fWalkX; // unit step position (integer after initial step)
- SkFixed fWalkY;
- uint16_t fPartialY; // initial partial coverage in Y (0 .. SkFixed1]
- int16_t fWindingSum; // winding including contributions to the left
- int8_t fWinding; // 1 or -1 (could be 2 bits)
- bool fFinished : 1;
- unsigned fDXFlipped : 1; // used as bool and to adjust calculations (0/1)
- bool fLinkSet : 1; // set if edge has been attached to another edge
-
- void calcLine();
- bool setLine(const SkPoint& p0, const SkPoint& p1);
- uint16_t advanceX(SkFixed left);
- uint16_t advanceFlippedX(SkFixed left);
- void advanceY(SkFixed top);
-// FIXME: mark DEBUG
- void pointInLine(SkFixed x, SkFixed y);
- void pointOnLine(SkFixed x, SkFixed y);
- void validate();
-};
-
-class SkAntiEdgeBuilder {
-public:
-void process(const SkPoint* points, int ptCount,
- uint8_t* result, int pixelCol, int pixelRow);
-private:
- int build(const SkPoint pts[], int count);
- void calc();
- void link();
- void sort();
- void sort(SkTDArray<SkAntiEdge*>&);
- void split();
- void split(SkAntiEdge* edge, SkFixed y);
- void walk(uint8_t* result, int rowBytes, int height);
- SkAntiEdge fHeadEdge;
- SkAntiEdge fTailEdge;
- SkTDArray<SkAntiEdge> fEdges;
- SkTDArray<SkAntiEdge*> fList;
-};
-
-void SkAntiEdge_Test();
-void CreateSweep(SkBitmap* , float width);
-void CreateHorz(SkBitmap* );
-void CreateVert(SkBitmap* );
-void CreateAngle(SkBitmap* sweep, float angle);
-
-#endif
diff --git a/experimental/Intersection/TSearch.h b/experimental/Intersection/TSearch.h
deleted file mode 100644
index 2635470f53..0000000000
--- a/experimental/Intersection/TSearch.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#ifndef TSearch_DEFINED
-#define TSearch_DEFINED
-
-// FIXME: Move this templated version into SKTSearch.h
-
-template <typename T>
-static T* QSort_Partition(T* left, T* right, T* pivot)
-{
- T pivotValue = *pivot;
- SkTSwap(*pivot, *right);
- T* newPivot = left;
- while (left < right) {
- if (*left < pivotValue) {
- SkTSwap(*left, *newPivot);
- newPivot += 1;
- }
- left += 1;
- }
- SkTSwap(*newPivot, *right);
- return newPivot;
-}
-
-template <typename T>
-void QSort(T* left, T* right)
-{
- if (left >= right) {
- return;
- }
- T* pivot = left + (right - left >> 1);
- pivot = QSort_Partition(left, right, pivot);
- QSort(left, pivot - 1);
- QSort(pivot + 1, right);
-}
-
-template <typename T>
-static T** QSort_Partition(T** left, T** right, T** pivot)
-{
- T* pivotValue = *pivot;
- SkTSwap(*pivot, *right);
- T** newPivot = left;
- while (left < right) {
- if (**left < *pivotValue) {
- SkTSwap(*left, *newPivot);
- newPivot += 1;
- }
- left += 1;
- }
- SkTSwap(*newPivot, *right);
- return newPivot;
-}
-
-template <typename T>
-void QSort(T** left, T** right)
-{
- if (left >= right) {
- return;
- }
- T** pivot = left + (right - left >> 1);
- pivot = QSort_Partition(left, right, pivot);
- QSort(left, pivot - 1);
- QSort(pivot + 1, right);
-}
-
-template <typename S, typename T>
-static T* QSort_Partition(S& context, T* left, T* right, T* pivot,
- bool (*lessThan)(S&, const T, const T))
-{
- T pivotValue = *pivot;
- SkTSwap(*pivot, *right);
- T* newPivot = left;
- while (left < right) {
- if (lessThan(context, *left, pivotValue)) {
- SkTSwap(*left, *newPivot);
- newPivot += 1;
- }
- left += 1;
- }
- SkTSwap(*newPivot, *right);
- return newPivot;
-}
-
-template <typename S, typename T>
-void QSort(S& context, T* left, T* right,
- bool (*lessThan)(S& , const T, const T))
-{
- if (left >= right) {
- return;
- }
- T* pivot = left + (right - left >> 1);
- pivot = QSort_Partition(context, left, right, pivot, lessThan);
- QSort(context, left, pivot - 1, lessThan);
- QSort(context, pivot + 1, right, lessThan);
-}
-
-#endif
diff --git a/experimental/Intersection/TestUtilities.cpp b/experimental/Intersection/TestUtilities.cpp
deleted file mode 100644
index 3ae10d216a..0000000000
--- a/experimental/Intersection/TestUtilities.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "CubicUtilities.h"
-#include "CurveIntersection.h"
-#include "TestUtilities.h"
-
-void quad_to_cubic(const Quadratic& quad, Cubic& cubic) {
- cubic[0] = quad[0];
- cubic[1].x = quad[0].x / 3 + quad[1].x * 2 / 3;
- cubic[1].y = quad[0].y / 3 + quad[1].y * 2 / 3;
- cubic[2].x = quad[2].x / 3 + quad[1].x * 2 / 3;
- cubic[2].y = quad[2].y / 3 + quad[1].y * 2 / 3;
- cubic[3] = quad[2];
-}
-
-static bool tiny(const Cubic& cubic) {
- int index, minX, maxX, minY, maxY;
- minX = maxX = minY = maxY = 0;
- for (index = 1; index < 4; ++index) {
- if (cubic[minX].x > cubic[index].x) {
- minX = index;
- }
- if (cubic[minY].y > cubic[index].y) {
- minY = index;
- }
- if (cubic[maxX].x < cubic[index].x) {
- maxX = index;
- }
- if (cubic[maxY].y < cubic[index].y) {
- maxY = index;
- }
- }
- return approximately_equal(cubic[maxX].x, cubic[minX].x)
- && approximately_equal(cubic[maxY].y, cubic[minY].y);
-}
-
-void find_tight_bounds(const Cubic& cubic, _Rect& bounds) {
- CubicPair cubicPair;
- chop_at(cubic, cubicPair, 0.5);
- if (!tiny(cubicPair.first()) && !controls_inside(cubicPair.first())) {
- find_tight_bounds(cubicPair.first(), bounds);
- } else {
- bounds.add(cubicPair.first()[0]);
- bounds.add(cubicPair.first()[3]);
- }
- if (!tiny(cubicPair.second()) && !controls_inside(cubicPair.second())) {
- find_tight_bounds(cubicPair.second(), bounds);
- } else {
- bounds.add(cubicPair.second()[0]);
- bounds.add(cubicPair.second()[3]);
- }
-}
-
-bool controls_inside(const Cubic& cubic) {
- return
- ((cubic[0].x <= cubic[1].x && cubic[0].x <= cubic[2].x && cubic[1].x <= cubic[3].x && cubic[2].x <= cubic[3].x)
- || (cubic[0].x >= cubic[1].x && cubic[0].x >= cubic[2].x && cubic[1].x >= cubic[3].x && cubic[2].x >= cubic[3].x))
- && ((cubic[0].y <= cubic[1].y && cubic[0].y <= cubic[2].y && cubic[1].y <= cubic[3].y && cubic[2].y <= cubic[3].y)
- || (cubic[0].y >= cubic[1].y && cubic[0].y >= cubic[2].y && cubic[1].y >= cubic[3].y && cubic[2].x >= cubic[3].y));
-}
diff --git a/experimental/Intersection/TestUtilities.h b/experimental/Intersection/TestUtilities.h
deleted file mode 100644
index 2bce308ade..0000000000
--- a/experimental/Intersection/TestUtilities.h
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "DataTypes.h"
-
-bool controls_inside(const Cubic& );
-void find_tight_bounds(const Cubic& , _Rect& );
-void quad_to_cubic(const Quadratic& , Cubic& );
diff --git a/experimental/Intersection/TriangleUtilities.cpp b/experimental/Intersection/TriangleUtilities.cpp
deleted file mode 100644
index 9889368079..0000000000
--- a/experimental/Intersection/TriangleUtilities.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "TriangleUtilities.h"
-
-// http://www.blackpawn.com/texts/pointinpoly/default.html
-bool pointInTriangle(const Triangle& triangle, const _Point& pt) {
-// Compute vectors
- _Vector v0 = triangle[2] - triangle[0];
- _Vector v1 = triangle[1] - triangle[0];
- _Vector v2 = pt - triangle[0];
-
-// Compute dot products
- double dot00 = v0.dot(v0);
- double dot01 = v0.dot(v1);
- double dot02 = v0.dot(v2);
- double dot11 = v1.dot(v1);
- double dot12 = v1.dot(v2);
-
-// Compute barycentric coordinates
- double invDenom = 1 / (dot00 * dot11 - dot01 * dot01);
- double u = (dot11 * dot02 - dot01 * dot12) * invDenom;
- double v = (dot00 * dot12 - dot01 * dot02) * invDenom;
-
-// Check if point is in triangle
- return (u >= 0) && (v >= 0) && (u + v < 1);
-}
diff --git a/experimental/Intersection/TriangleUtilities.h b/experimental/Intersection/TriangleUtilities.h
deleted file mode 100644
index b09dbc6ef6..0000000000
--- a/experimental/Intersection/TriangleUtilities.h
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "DataTypes.h"
-
-bool pointInTriangle(const Triangle& triangle, const _Point& pt);
diff --git a/experimental/Intersection/as.htm b/experimental/Intersection/as.htm
deleted file mode 100644
index 595ab4d0f6..0000000000
--- a/experimental/Intersection/as.htm
+++ /dev/null
@@ -1,7027 +0,0 @@
-<html>
-<head>
-<div style="height:0">
-
-<div id="cubicOp36u">
- SimplifyNew_Test [cubicOp36u]
-{{0,1}, {1,6}, {2,0}, {5,1}},
-{{5,1}, {0,1}},
-op union
-{{0,2}, {1,5}, {1,0}, {6,1}},
-{{6,1}, {0,2}},
-debugShowCubicIntersection no self intersect {{0,2}, {1,5}, {1,0}, {6,1}}
-debugShowCubicLineIntersection wtTs[0]=0 {{0,2}, {1,5}, {1,0}, {6,1}} {{0,2}} wtTs[1]=0.633333333 {{2.2208888888888882,1.6298518518518521}} wtTs[2]=1 {{6,1}} wnTs[0]=1 {{6,1}, {0,2}} wnTs[1]=0.629851852 wnTs[2]=0
-debugShowCubicIntersection wtTs[0]=0.281761651 {{0,2}, {1,5}, {1,0}, {6,1}} {{0.74132978521392334,2.9436691246202122}} wtTs[1]=0.83051493 {{3.8593908381032738,0.94043932231067462}} wtTs[2]=0.830515061 {{3.8593922073023155,0.94043907360367252}} wtTs[3]=0.867315861 {{4.2597986321159249,0.88613622701319239}} wtTs[4]=0.867316009 {{4.2598003089230945,0.88613607359480184}} wnTs[0]=0.23811 {{0,1}, {1,6}, {2,0}, {5,1}} wnTs[1]=0.860977989 wnTs[2]=0.860978176 wnTs[3]=0.912837717 wnTs[4]=0.912837923
-debugShowCubicLineIntersection wtTs[0]=0.803214143 {{0,2}, {1,5}, {1,0}, {6,1}} {{3.5833594368204942,1}} wnTs[0]=0.283328 {{5,1}, {0,1}}
-debugShowCubicLineIntersection wtTs[0]=0.0764226429 {{0,1}, {1,6}, {2,0}, {5,1}} {{0.23016060940409022,1.9616398984326517}} wtTs[1]=0.691654855 {{2.7367211708698314,1.543879804855028}} wnTs[0]=0.96164 {{6,1}, {0,2}} wnTs[1]=0.543879805
-debugShowLineIntersection no intersect {{6,1}, {0,2}} {{5,1}, {0,1}}
-debugShowCubicIntersection no self intersect {{0,1}, {1,6}, {2,0}, {5,1}}
-debugShowCubicLineIntersection wtTs[0]=0 {{0,1}, {1,6}, {2,0}, {5,1}} {{0,1}} wtTs[1]=0.833333333 {{3.6574074074074132,0.99999999999999789}} wtTs[2]=1 {{5,1}} wnTs[0]=1 {{5,1}, {0,1}} wnTs[1]=0.268518519 wnTs[2]=0
-debugShowActiveSpans id=3 (0,2 1,5 1,0 6,1) t=0 (0,2) tEnd=0.281761651 other=4 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,2 1,5 1,0 6,1) t=0.281761651 (0.741329789,2.94366908) tEnd=0.633333333 other=1 otherT=0.238109917 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,2 1,5 1,0 6,1) t=0.633333333 (2.22088885,1.62985182) tEnd=0.803214143 other=4 otherT=0.629851852 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,2 1,5 1,0 6,1) t=0.803214143 (3.58335948,1) tEnd=0.83051493 other=2 otherT=0.283328113 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,2 1,5 1,0 6,1) t=0.83051493 (3.85939074,0.940439343) tEnd=0.830515061 other=1 otherT=0.860977989 otherIndex=5 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,2 1,5 1,0 6,1) t=0.830515061 (3.85939217,0.940439045) tEnd=0.867315861 other=1 otherT=0.860978176 otherIndex=6 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,2 1,5 1,0 6,1) t=0.867315861 (4.25979853,0.886136234) tEnd=0.867316009 other=1 otherT=0.912837717 otherIndex=7 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,2 1,5 1,0 6,1) t=0.867316009 (4.25980043,0.886136055) tEnd=1 other=1 otherT=0.912837923 otherIndex=8 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (6,1 0,2) t=0 (6,1) tEnd=0.543879805 other=3 otherT=1 otherIndex=8 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (6,1 0,2) t=0.543879805 (2.73672128,1.54387975) tEnd=0.629851852 other=1 otherT=0.691654855 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (6,1 0,2) t=0.629851852 (2.22088885,1.62985182) tEnd=0.961639898 other=3 otherT=0.633333333 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (6,1 0,2) t=0.961639898 (0.230160609,1.96163988) tEnd=1 other=1 otherT=0.0764226429 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,1 1,6 2,0 5,1) t=0 (0,1) tEnd=0.0764226429 other=2 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,1 1,6 2,0 5,1) t=0.0764226429 (0.230160609,1.96163988) tEnd=0.238109917 other=4 otherT=0.961639898 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,1 1,6 2,0 5,1) t=0.238109917 (0.741329789,2.94366908) tEnd=0.691654855 other=3 otherT=0.281761651 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,1 1,6 2,0 5,1) t=0.691654855 (2.73672128,1.54387975) tEnd=0.833333333 other=4 otherT=0.543879805 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,1 1,6 2,0 5,1) t=0.833333333 (3.65740752,1) tEnd=0.860977989 other=2 otherT=0.268518519 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,1 1,6 2,0 5,1) t=0.860977989 (3.85939074,0.940439343) tEnd=0.860978176 other=3 otherT=0.83051493 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,1 1,6 2,0 5,1) t=0.860978176 (3.85939217,0.940439045) tEnd=0.912837717 other=3 otherT=0.830515061 otherIndex=5 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,1 1,6 2,0 5,1) t=0.912837717 (4.25979853,0.886136234) tEnd=0.912837923 other=3 otherT=0.867315861 otherIndex=6 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,1 1,6 2,0 5,1) t=0.912837923 (4.25980043,0.886136055) tEnd=1 other=3 otherT=0.867316009 otherIndex=7 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,1 0,1) t=0 (5,1) tEnd=0.268518519 other=1 otherT=1 otherIndex=9 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,1 0,1) t=0.268518519 (3.65740752,1) tEnd=0.283328113 other=1 otherT=0.833333333 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,1 0,1) t=0.283328113 (3.58335948,1) tEnd=1 other=3 otherT=0.803214143 otherIndex=3 windSum=? windValue=1 oppValue=0
-findTop debugShowSort contourWinding=0 oppContourWinding=0 sign=1
-debugShowSort [0] {{0,2}, {1,5}, {1,0}, {6,1}} tStart=1 tEnd=0.867316009 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [1] {{6,1}, {0,2}} tStart=0 tEnd=0.543879805 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-findTop xyE=(6,1) xyS=(4.25980043,0.886136055)
-findTop dxyE=(15,3) dxyS=(11.3363714,-1.03721189) cross=-49.5672913 bumpsUp=true
-markWinding id=3 (0,2 1,5 1,0 6,1) t=0.867316009 [7] (4.25980043,0.886136055) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=4 (6,1 0,2) t=0 [0] (6,1) tEnd=0.543879805 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=3 (0,2 1,5 1,0 6,1) t=0.867316009 [7] (4.25980043,0.886136055) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-activeOp op=union miFrom=0 miTo=0 suFrom=1 suTo=0 result=1
-findNextOp simple
-markDoneBinary id=3 (0,2 1,5 1,0 6,1) t=0.867316009 [7] (4.25980043,0.886136055) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-bridgeOp current id=3 from=(4.25980043,0.886136055) to=(6,1)
-path.moveTo(4.25980043,0.886136055);
-path.cubicTo(4.76118517,0.840262294, 5.33658028,0.867316008, 6,1);
-findNextOp debugShowSort contourWinding=0 oppContourWinding=0 sign=1
-debugShowSort [0] {{6,1}, {0,2}} tStart=0.543879805 tEnd=0 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [1] {{0,1}, {1,6}, {2,0}, {5,1}} tStart=0.691654855 tEnd=0.833333333 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=1
-debugShowSort [2] {{6,1}, {0,2}} tStart=0.543879805 tEnd=0.629851852 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [3] {{0,1}, {1,6}, {2,0}, {5,1}} tStart=0.691654855 tEnd=0.238109917 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=1
-findNextOp firstIndex=[0] sign=1
-activeOp op=union miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=1 (0,1 1,6 2,0 5,1) t=0.691654855 [3] (2.73672128,1.54387975) tEnd=0.833333333 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=1
-activeOp op=union miFrom=1 miTo=1 suFrom=1 suTo=0 result=0
-markDoneBinary id=4 (6,1 0,2) t=0.543879805 [1] (2.73672128,1.54387975) tEnd=0.629851852 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=4
-activeOp op=union miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-markWinding id=1 (0,1 1,6 2,0 5,1) t=0.238109917 [2] (0.741329789,2.94366908) tEnd=0.691654855 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=1
-markDoneBinary id=4 (6,1 0,2) t=0 [0] (6,1) tEnd=0.543879805 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-findNextOp from:[4] to:[1] start=3 end=2
-bridgeOp current id=4 from=(6,1) to=(2.73672128,1.54387975)
-findNextOp debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [3] {{0,1}, {1,6}, {2,0}, {5,1}} tStart=0.238109917 tEnd=0.691654855 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [0] {{0,2}, {1,5}, {1,0}, {6,1}} tStart=0.281761651 tEnd=0.633333333 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=1
-debugShowSort [1] {{0,1}, {1,6}, {2,0}, {5,1}} tStart=0.238109917 tEnd=0.0764226429 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [2] {{0,2}, {1,5}, {1,0}, {6,1}} tStart=0.281761651 tEnd=0 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=1
-findNextOp firstIndex=[3] sign=-1
-activeOp op=union miFrom=1 miTo=1 suFrom=0 suTo=1 result=0
-markDoneBinary id=3 (0,2 1,5 1,0 6,1) t=0.281761651 [1] (0.741329789,2.94366908) tEnd=0.633333333 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-activeOp op=union miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
-markDoneBinary id=1 (0,1 1,6 2,0 5,1) t=0.0764226429 [1] (0.230160609,1.96163988) tEnd=0.238109917 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=1
-activeOp op=union miFrom=0 miTo=0 suFrom=1 suTo=0 result=1
-markWinding id=3 (0,2 1,5 1,0 6,1) t=0 [0] (0,2) tEnd=0.281761651 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=4 (6,1 0,2) t=0.961639898 [3] (0.230160609,1.96163988) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=4
-markDoneBinary id=1 (0,1 1,6 2,0 5,1) t=0.238109917 [2] (0.741329789,2.94366908) tEnd=0.691654855 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-findNextOp from:[1] to:[3] start=1 end=0
-bridgeOp current id=1 from=(2.73672128,1.54387975) to=(0.741329789,2.94366908)
-path.lineTo(2.73672128,1.54387975);
-path.cubicTo(1.84923673,2.27202392, 1.2463032,3.29839373, 0.741329789,2.94366908);
-findNextOp simple
-markDoneBinary id=3 (0,2 1,5 1,0 6,1) t=0 [0] (0,2) tEnd=0.281761651 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-bridgeOp current id=3 from=(0.741329789,2.94366908) to=(0,2)
-path.cubicTo(0.484133661,3.05545282, 0.281761646,2.84528494, 0,2);
-findNextOp debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [2] {{6,1}, {0,2}} tStart=0.961639898 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [3] {{0,1}, {1,6}, {2,0}, {5,1}} tStart=0.0764226429 tEnd=0.238109917 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=1
-debugShowSort [0] {{6,1}, {0,2}} tStart=0.961639898 tEnd=0.629851852 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] {{0,1}, {1,6}, {2,0}, {5,1}} tStart=0.0764226429 tEnd=0 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=1
-findNextOp firstIndex=[2] sign=-1
-activeOp op=union miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-activeOp op=union miFrom=1 miTo=1 suFrom=1 suTo=0 result=0
-markDoneBinary id=4 (6,1 0,2) t=0.629851852 [2] (2.22088885,1.62985182) tEnd=0.961639898 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=4
-activeOp op=union miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-markWinding id=1 (0,1 1,6 2,0 5,1) t=0 [0] (0,1) tEnd=0.0764226429 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=2 (5,1 0,1) t=0.283328113 [2] (3.58335948,1) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=2
-markDoneBinary id=4 (6,1 0,2) t=0.961639898 [3] (0.230160609,1.96163988) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-findNextOp from:[4] to:[1] start=1 end=0
-bridgeOp current id=4 from=(0,2) to=(0.230160609,1.96163988)
-findNextOp simple
-markDoneBinary id=1 (0,1 1,6 2,0 5,1) t=0 [0] (0,1) tEnd=0.0764226429 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-bridgeOp current id=1 from=(0.230160609,1.96163988) to=(0,1)
-path.lineTo(0.230160609,1.96163988);
-path.cubicTo(0.152845293,1.69998181, 0.0764226392,1.38211322, 0,1);
-findNextOp debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [1] {{5,1}, {0,1}} tStart=0.283328113 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [2] {{0,2}, {1,5}, {1,0}, {6,1}} tStart=0.803214143 tEnd=0.633333333 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=1
-debugShowSort [3] {{5,1}, {0,1}} tStart=0.283328113 tEnd=0.268518519 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [0] {{0,2}, {1,5}, {1,0}, {6,1}} tStart=0.803214143 tEnd=0.83051493 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=1
-findNextOp firstIndex=[1] sign=-1
-activeOp op=union miFrom=1 miTo=1 suFrom=0 suTo=1 result=0
-markDoneBinary id=3 (0,2 1,5 1,0 6,1) t=0.633333333 [2] (2.22088885,1.62985182) tEnd=0.803214143 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-activeOp op=union miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
-markDoneBinary id=2 (5,1 0,1) t=0.268518519 [1] (3.65740752,1) tEnd=0.283328113 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=2
-activeOp op=union miFrom=0 miTo=0 suFrom=1 suTo=0 result=1
-markWinding id=3 (0,2 1,5 1,0 6,1) t=0.803214143 [3] (3.58335948,1) tEnd=0.83051493 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-markDoneBinary id=2 (5,1 0,1) t=0.283328113 [2] (3.58335948,1) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-findNextOp from:[2] to:[3] start=3 end=4
-bridgeOp current id=2 from=(0,1) to=(3.58335948,1)
-findNextOp debugShowSort contourWinding=0 oppContourWinding=0 sign=1
-debugShowSort [0] {{0,2}, {1,5}, {1,0}, {6,1}} tStart=0.83051493 tEnd=0.803214143 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [1] {{0,1}, {1,6}, {2,0}, {5,1}} tStart=0.860977989 tEnd=0.833333333 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=1
-debugShowSort [2] {{0,1}, {1,6}, {2,0}, {5,1}} tStart=0.860977989 tEnd=0.860978176 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=1
-debugShowSort [3] {{0,2}, {1,5}, {1,0}, {6,1}} tStart=0.83051493 tEnd=0.830515061 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-findNextOp firstIndex=[0] sign=1
-activeOp op=union miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=1 (0,1 1,6 2,0 5,1) t=0.833333333 [4] (3.65740752,1) tEnd=0.860977989 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=1
-activeOp op=union miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
-markDoneBinary id=1 (0,1 1,6 2,0 5,1) t=0.860977989 [5] (3.85939074,0.940439343) tEnd=0.860978176 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=1
-activeOp op=union miFrom=0 miTo=0 suFrom=1 suTo=0 result=1
-markWinding id=3 (0,2 1,5 1,0 6,1) t=0.83051493 [4] (3.85939074,0.940439343) tEnd=0.830515061 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-markDoneBinary id=3 (0,2 1,5 1,0 6,1) t=0.803214143 [3] (3.58335948,1) tEnd=0.83051493 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-findNextOp from:[3] to:[3] start=4 end=5
-bridgeOp current id=3 from=(3.58335948,1) to=(3.85939074,0.940439343)
-path.lineTo(3.58335948,1);
-path.cubicTo(3.67248249,0.97763288, 3.76445246,0.957684338, 3.85939074,0.940439343);
-findNextOp debugShowSort contourWinding=0 oppContourWinding=0 sign=1
-debugShowSort [2] {{0,2}, {1,5}, {1,0}, {6,1}} tStart=0.830515061 tEnd=0.83051493 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [3] {{0,1}, {1,6}, {2,0}, {5,1}} tStart=0.860978176 tEnd=0.860977989 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=1
-debugShowSort [0] {{0,2}, {1,5}, {1,0}, {6,1}} tStart=0.830515061 tEnd=0.867315861 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [1] {{0,1}, {1,6}, {2,0}, {5,1}} tStart=0.860978176 tEnd=0.912837717 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=1
-findNextOp firstIndex=[2] sign=1
-activeOp op=union miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-activeOp op=union miFrom=1 miTo=1 suFrom=1 suTo=0 result=0
-markDoneBinary id=3 (0,2 1,5 1,0 6,1) t=0.830515061 [5] (3.85939217,0.940439045) tEnd=0.867315861 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-activeOp op=union miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-markWinding id=1 (0,1 1,6 2,0 5,1) t=0.860978176 [6] (3.85939217,0.940439045) tEnd=0.912837717 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=1
-markDoneBinary id=3 (0,2 1,5 1,0 6,1) t=0.83051493 [4] (3.85939074,0.940439343) tEnd=0.830515061 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-findNextOp from:[3] to:[1] start=6 end=7
-bridgeOp current id=3 from=(3.85939074,0.940439343) to=(3.85939217,0.940439045)
-path.cubicTo(3.85939145,0.940439224, 3.85939169,0.940439165, 3.85939217,0.940439045);
-findNextOp debugShowSort contourWinding=0 oppContourWinding=0 sign=1
-debugShowSort [0] {{0,1}, {1,6}, {2,0}, {5,1}} tStart=0.912837717 tEnd=0.860978176 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [1] {{0,2}, {1,5}, {1,0}, {6,1}} tStart=0.867315861 tEnd=0.830515061 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=1
-debugShowSort [2] {{0,1}, {1,6}, {2,0}, {5,1}} tStart=0.912837717 tEnd=0.912837923 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [3] {{0,2}, {1,5}, {1,0}, {6,1}} tStart=0.867315861 tEnd=0.867316009 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=1
-findNextOp firstIndex=[0] sign=1
-activeOp op=union miFrom=1 miTo=1 suFrom=0 suTo=1 result=0
-activeOp op=union miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
-markDoneBinary id=1 (0,1 1,6 2,0 5,1) t=0.912837717 [7] (4.25979853,0.886136234) tEnd=0.912837923 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=1
-activeOp op=union miFrom=0 miTo=0 suFrom=1 suTo=0 result=1
-markWinding id=3 (0,2 1,5 1,0 6,1) t=0.867315861 [6] (4.25979853,0.886136234) tEnd=0.867316009 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-markDoneBinary id=1 (0,1 1,6 2,0 5,1) t=0.860978176 [6] (3.85939217,0.940439045) tEnd=0.912837717 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-findNextOp from:[1] to:[3] start=6 end=7
-bridgeOp current id=1 from=(3.85939217,0.940439045) to=(4.25979853,0.886136234)
-path.cubicTo(3.98813701,0.909405351, 4.12151289,0.890467525, 4.25980043,0.886136055);
-path.close();
-debugShowActiveSpans id=3 (0,2 1,5 1,0 6,1) t=0.867315861 (4.25979853,0.886136234) tEnd=0.867316009 other=1 otherT=0.912837717 otherIndex=7 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,1 1,6 2,0 5,1) t=0.912837923 (4.25980043,0.886136055) tEnd=1 other=3 otherT=0.867316009 otherIndex=7 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,1 0,1) t=0 (5,1) tEnd=0.268518519 other=1 otherT=1 otherIndex=9 windSum=? windValue=1 oppValue=0
-activeOp op=union miFrom=0 miTo=0 suFrom=0 suTo=1 result=1
-findNextOp debugShowSort contourWinding=-1 oppContourWinding=0 sign=-1
-debugShowSort [3] {{0,2}, {1,5}, {1,0}, {6,1}} tStart=0.867315861 tEnd=0.867316009 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [0] {{0,1}, {1,6}, {2,0}, {5,1}} tStart=0.912837717 tEnd=0.860978176 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=1
-debugShowSort [1] {{0,2}, {1,5}, {1,0}, {6,1}} tStart=0.867315861 tEnd=0.830515061 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [2] {{0,1}, {1,6}, {2,0}, {5,1}} tStart=0.912837717 tEnd=0.912837923 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=1
-findNextOp firstIndex=[3] sign=-1
-activeOp op=union miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-activeOp op=union miFrom=1 miTo=1 suFrom=0 suTo=1 result=0
-activeOp op=union miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
-markDoneBinary id=3 (0,2 1,5 1,0 6,1) t=0.867315861 [6] (4.25979853,0.886136234) tEnd=0.867316009 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-findNextOp from:[3] to:[1] start=7 end=6
-bridgeOp current id=3 from=(4.25980043,0.886136055) to=(4.25979853,0.886136234)
-path.moveTo(4.25980043,0.886136055);
-path.cubicTo(4.25979948,0.886136115, 4.25979948,0.886136174, 4.25979853,0.886136234);
-findNextOp debugShowSort contourWinding=-1 oppContourWinding=0 sign=-1
-debugShowSort [1] {{0,1}, {1,6}, {2,0}, {5,1}} tStart=0.860978176 tEnd=0.912837717 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [2] {{0,2}, {1,5}, {1,0}, {6,1}} tStart=0.830515061 tEnd=0.83051493 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=1
-debugShowSort [3] {{0,1}, {1,6}, {2,0}, {5,1}} tStart=0.860978176 tEnd=0.860977989 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [0] {{0,2}, {1,5}, {1,0}, {6,1}} tStart=0.830515061 tEnd=0.867315861 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=1
-findNextOp firstIndex=[1] sign=-1
-activeOp op=union miFrom=0 miTo=0 suFrom=0 suTo=1 result=1
-activeOp op=union miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-activeOp op=union miFrom=1 miTo=1 suFrom=1 suTo=0 result=0
-findNextOp from:[1] to:[3] start=5 end=4
-bridgeOp current id=1 from=(4.25979853,0.886136234) to=(3.85939217,0.940439045)
-path.cubicTo(4.12151289,0.890467525, 3.98813701,0.909405351, 3.85939217,0.940439045);
-debugShowActiveSpans id=1 (0,1 1,6 2,0 5,1) t=0.912837923 (4.25980043,0.886136055) tEnd=1 other=3 otherT=0.867316009 otherIndex=7 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,1 0,1) t=0 (5,1) tEnd=0.268518519 other=1 otherT=1 otherIndex=9 windSum=? windValue=1 oppValue=0
-</div>
-
-<div id="cubicOp35da">
-{{x = 0.44618727783085621, y = 2.2840286415243063}, {x = 0.51170845243761109, y = 2.4044088819954914}, {x = 0.57783675570457882, y = 2.4985733182515446}, {x = 0.64483584772311509, y = 2.5694222112973661}}
-{{x = 0.64244110111854291, y = 2.5673840215265367}, {x = 0.63479413812245555, y = 2.5620057200094775}, {x = 0.64115438240274059, y = 2.533597555954064}, {x = 0.6620248993310307, y = 2.4876932484482714}}
-</div>
-
-<div id="cubicOp38d">
- SimplifyNew_Test [cubicOp38d]
-{{0,1}, {0,6}, {3,2}, {4,1}},
-{{4,1}, {0,1}},
-op difference
-{{2,3}, {1,4}, {1,0}, {6,0}},
-{{6,0}, {2,3}},
-debugShowCubicIntersection no self intersect {{2,3}, {1,4}, {1,0}, {6,0}}
-debugShowCubicLineIntersection wtTs[0]=0 {{2,3}, {1,4}, {1,0}, {6,0}} {{2,3}} wtTs[1]=1 {{6,0}} wnTs[0]=1 {{6,0}, {2,3}} wnTs[1]=0
-debugShowCubicIntersection no intersect {{2,3}, {1,4}, {1,0}, {6,0}} {{0,1}, {0,6}, {3,2}, {4,1}}
-debugShowCubicLineIntersection wtTs[0]=0.666666667 {{2,3}, {1,4}, {1,0}, {6,0}} {{2.518518518518519,0.99999999999999967}} wnTs[0]=0.37037 {{4,1}, {0,1}}
-debugShowCubicLineIntersection no intersect {{0,1}, {0,6}, {3,2}, {4,1}} {{6,0}, {2,3}}
-debugShowLineIntersection no intersect {{6,0}, {2,3}} {{4,1}, {0,1}}
-debugShowCubicIntersection no self intersect {{0,1}, {0,6}, {3,2}, {4,1}}
-debugShowCubicLineIntersection wtTs[0]=0 {{0,1}, {0,6}, {3,2}, {4,1}} {{0,1}} wtTs[1]=1 {{4,1}} wnTs[0]=1 {{4,1}, {0,1}} wnTs[1]=0
-debugShowActiveSpans id=3 (2,3 1,4 1,0 6,0) t=0 (2,3) tEnd=0.666666667 other=4 otherT=1 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (2,3 1,4 1,0 6,0) t=0.666666667 (2.51851845,1) tEnd=1 other=2 otherT=0.37037037 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (6,0 2,3) t=0 (6,0) tEnd=1 other=3 otherT=1 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,1 0,6 3,2 4,1) t=0 (0,1) tEnd=1 other=2 otherT=1 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,1 0,1) t=0 (4,1) tEnd=0.37037037 other=1 otherT=1 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,1 0,1) t=0.37037037 (2.51851845,1) tEnd=1 other=3 otherT=0.666666667 otherIndex=1 windSum=? windValue=1 oppValue=0
-findTop debugShowSort contourWinding=0 oppContourWinding=0 sign=1
-debugShowSort [0] {{2,3}, {1,4}, {1,0}, {6,0}} tStart=1 tEnd=0.666666667 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [1] {{6,0}, {2,3}} tStart=0 tEnd=1 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-findTop xyE=(6,0) xyS=(2.51851845,1)
-findTop dxyE=(15,0) dxyS=(6.33333349,-5) cross=-75 bumpsUp=false
-markWinding id=3 (2,3 1,4 1,0 6,0) t=0.666666667 [1] (2.51851845,1) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=4 (6,0 2,3) t=0 [0] (6,0) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=3 (2,3 1,4 1,0 6,0) t=0 [0] (2,3) tEnd=0.666666667 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=3 (2,3 1,4 1,0 6,0) t=0.666666667 [1] (2.51851845,1) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-markDoneBinary id=3 (2,3 1,4 1,0 6,0) t=0.666666667 [1] (2.51851845,1) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-markDoneBinary id=4 (6,0 2,3) t=0 [0] (6,0) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-markDoneBinary id=3 (2,3 1,4 1,0 6,0) t=0 [0] (2,3) tEnd=0.666666667 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-findChaseOp debugShowSort contourWinding=-1 oppContourWinding=0 sign=-1
-debugShowSort [0] {{2,3}, {1,4}, {1,0}, {6,0}} tStart=0.666666667 tEnd=1 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [1] {{4,1}, {0,1}} tStart=0.37037037 tEnd=1 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=1
-debugShowSort [2] {{2,3}, {1,4}, {1,0}, {6,0}} tStart=0.666666667 tEnd=0 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [3] {{4,1}, {0,1}} tStart=0.37037037 tEnd=0 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=1
-findChaseOp debugShowSort contourWinding=-1 oppContourWinding=0 sign=-1
-debugShowSort [0] {{2,3}, {1,4}, {1,0}, {6,0}} tStart=0.666666667 tEnd=1 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [1] {{4,1}, {0,1}} tStart=0.37037037 tEnd=1 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=1
-debugShowSort [2] {{2,3}, {1,4}, {1,0}, {6,0}} tStart=0.666666667 tEnd=0 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [3] {{4,1}, {0,1}} tStart=0.37037037 tEnd=0 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=1
-markWinding id=2 (4,1 0,1) t=0.37037037 [1] (2.51851845,1) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=1 (0,1 0,6 3,2 4,1) t=0 [0] (0,1) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=2 (4,1 0,1) t=0 [0] (4,1) tEnd=0.37037037 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=2 (4,1 0,1) t=0 [0] (4,1) tEnd=0.37037037 newWindSum=1 newOppSum=-1 oppSum=0 windSum=1 windValue=1
-</div>
-
-<div id="cubicOp38da">
- {{0,1}, {0,6}, {3,2}, {4,1}},
- {{2,3}, {1,4}, {1,0}, {6,0}},
-computed quadratics set 2
- {{2,3}, {1.46296296,3.41666667}, {1.48148148,2.66666667}},
- {{1.48148148,2.66666667}, {1.5,1.91666667}, {2.51851852,1}},
- {{2.51851852,1}, {3.53703704,0.0833333333}, {6,0}},
-computed quadratics set 1
- {{0,1}, {0.0311951689,3.11686153}, {0.643808143,3.37716704}},
- {{0.643808143,3.37716704}, {1.25642112,3.63747255}, {2.07610987,2.9396429}},
- {{2.07610987,2.9396429}, {2.89579862,2.24181325}, {3.54822112,1.48426931}},
- {{3.54822112,1.48426931}, {3.81269436,1.19058669}, {4,1}},
-</div>
-
-<div id="cubicOp39d">
- SimplifyNew_Test [cubicOp39d]
-{{0,1}, {2,3}, {5,1}, {4,3}},
-{{4,3}, {0,1}},
-op difference
-{{1,5}, {3,4}, {1,0}, {3,2}},
-{{3,2}, {1,5}},
-debugShowCubicIntersection no self intersect {{0,1}, {2,3}, {5,1}, {4,3}}
-debugShowCubicLineIntersection wtTs[0]=0 {{0,1}, {2,3}, {5,1}, {4,3}} {{0,1}} wtTs[1]=0.285714286 {{1.8425655976676385,1.9212827988338192}} wtTs[2]=1 {{4,3}} wnTs[0]=1 {{4,3}, {0,1}} wnTs[1]=0.539358601 wnTs[2]=0
-debugShowCubicIntersection wtTs[0]=0.311007457 {{0,1}, {2,3}, {5,1}, {4,3}} {{2.005809685956442,1.9459962410665144}} wnTs[0]=0.589885 {{1,5}, {3,4}, {1,0}, {3,2}}
-debugShowCubicLineIntersection no intersect {{0,1}, {2,3}, {5,1}, {4,3}} {{3,2}, {1,5}}
-debugShowCubicLineIntersection wtTs[0]=0.576935809 {{1,5}, {3,4}, {1,0}, {3,2}} {{2.0036431374219883,2.0018215687109939}} wnTs[0]=0.499089 {{4,3}, {0,1}}
-debugShowLineIntersection wtTs[0]=0.3125 {{4,3}, {0,1}} {{2.75,2.375}} wnTs[0]=0.125 {{3,2}, {1,5}}
-debugShowCubicIntersection no self intersect {{1,5}, {3,4}, {1,0}, {3,2}}
-debugShowCubicLineIntersection wtTs[0]=0 {{1,5}, {3,4}, {1,0}, {3,2}} {{1,5}} wtTs[1]=0.285714286 {{1.9212827988338184,3.6180758017492725}} wtTs[2]=1 {{3,2}} wnTs[0]=1 {{3,2}, {1,5}} wnTs[1]=0.539358601 wnTs[2]=0
-debugShowActiveSpans id=1 (0,1 2,3 5,1 4,3) t=0 (0,1) tEnd=0.285714286 other=2 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,1 2,3 5,1 4,3) t=0.285714286 (1.84256566,1.92128277) tEnd=0.311007457 other=2 otherT=0.539358601 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,1 2,3 5,1 4,3) t=0.311007457 (2.00580978,1.94599628) tEnd=1 other=3 otherT=0.589885081 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,3 0,1) t=0 (4,3) tEnd=0.3125 other=1 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,3 0,1) t=0.3125 (2.75,2.375) tEnd=0.499089216 other=4 otherT=0.125 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,3 0,1) t=0.499089216 (2.00364304,2.00182152) tEnd=0.539358601 other=3 otherT=0.576935809 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,3 0,1) t=0.539358601 (1.84256566,1.92128277) tEnd=1 other=1 otherT=0.285714286 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,5 3,4 1,0 3,2) t=0 (1,5) tEnd=0.285714286 other=4 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,5 3,4 1,0 3,2) t=0.285714286 (1.92128277,3.61807585) tEnd=0.576935809 other=4 otherT=0.539358601 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,5 3,4 1,0 3,2) t=0.576935809 (2.00364304,2.00182152) tEnd=0.589885081 other=2 otherT=0.499089216 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,5 3,4 1,0 3,2) t=0.589885081 (2.00580978,1.94599628) tEnd=1 other=1 otherT=0.311007457 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (3,2 1,5) t=0 (3,2) tEnd=0.125 other=3 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (3,2 1,5) t=0.125 (2.75,2.375) tEnd=0.539358601 other=2 otherT=0.3125 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (3,2 1,5) t=0.539358601 (1.92128277,3.61807585) tEnd=1 other=3 otherT=0.285714286 otherIndex=1 windSum=? windValue=1 oppValue=0
-findTop debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [0] {{0,1}, {2,3}, {5,1}, {4,3}} tStart=0 tEnd=0.285714286 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] {{4,3}, {0,1}} tStart=1 tEnd=0.539358601 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=0
-findTop xyE=(0,1) xyS=(1.84256566,1.92128277)
-findTop dxyE=(6,6) dxyS=(6.48979568,1.10204077) cross=-32.3265305 bumpsUp=false
-markWinding id=1 (0,1 2,3 5,1 4,3) t=0 [0] (0,1) tEnd=0.285714286 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=2 (4,3 0,1) t=0.539358601 [3] (1.84256566,1.92128277) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=1 (0,1 2,3 5,1 4,3) t=0 [0] (0,1) tEnd=0.285714286 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-activeOp op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-findNextOp simple
-markDoneBinary id=1 (0,1 2,3 5,1 4,3) t=0 [0] (0,1) tEnd=0.285714286 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-bridgeOp current id=1 from=(1.84256566,1.92128277) to=(0,1)
-path.moveTo(1.84256566,1.92128277);
-path.cubicTo(1.22448969,1.8163265, 0.571428597,1.57142854, 0,1);
-findNextOp debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [0] {{4,3}, {0,1}} tStart=0.539358601 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] {{0,1}, {2,3}, {5,1}, {4,3}} tStart=0.285714286 tEnd=0 sign=1 windValue=1 windSum=1 1->0 (max=1) done=1 tiny=0 opp=0
-debugShowSort [2] {{4,3}, {0,1}} tStart=0.539358601 tEnd=0.499089216 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [3] {{0,1}, {2,3}, {5,1}, {4,3}} tStart=0.285714286 tEnd=0.311007457 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-findNextOp firstIndex=[0] sign=-1
-activeOp op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-activeOp op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-markWinding id=2 (4,3 0,1) t=0.499089216 [2] (2.00364304,2.00182152) tEnd=0.539358601 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=2
-activeOp op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-markWinding id=1 (0,1 2,3 5,1 4,3) t=0.285714286 [1] (1.84256566,1.92128277) tEnd=0.311007457 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=1
-markDoneBinary id=2 (4,3 0,1) t=0.539358601 [3] (1.84256566,1.92128277) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-findNextOp from:[2] to:[1] start=1 end=2
-bridgeOp current id=2 from=(0,1) to=(1.84256566,1.92128277)
-path.lineTo(1.84256566,1.92128277);
-path.close();
-debugShowActiveSpans id=1 (0,1 2,3 5,1 4,3) t=0.285714286 (1.84256566,1.92128277) tEnd=0.311007457 other=2 otherT=0.539358601 otherIndex=3 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,1 2,3 5,1 4,3) t=0.311007457 (2.00580978,1.94599628) tEnd=1 other=3 otherT=0.589885081 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,3 0,1) t=0 (4,3) tEnd=0.3125 other=1 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,3 0,1) t=0.3125 (2.75,2.375) tEnd=0.499089216 other=4 otherT=0.125 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,3 0,1) t=0.499089216 (2.00364304,2.00182152) tEnd=0.539358601 other=3 otherT=0.576935809 otherIndex=2 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,5 3,4 1,0 3,2) t=0 (1,5) tEnd=0.285714286 other=4 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,5 3,4 1,0 3,2) t=0.285714286 (1.92128277,3.61807585) tEnd=0.576935809 other=4 otherT=0.539358601 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,5 3,4 1,0 3,2) t=0.576935809 (2.00364304,2.00182152) tEnd=0.589885081 other=2 otherT=0.499089216 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,5 3,4 1,0 3,2) t=0.589885081 (2.00580978,1.94599628) tEnd=1 other=1 otherT=0.311007457 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (3,2 1,5) t=0 (3,2) tEnd=0.125 other=3 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (3,2 1,5) t=0.125 (2.75,2.375) tEnd=0.539358601 other=2 otherT=0.3125 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (3,2 1,5) t=0.539358601 (1.92128277,3.61807585) tEnd=1 other=3 otherT=0.285714286 otherIndex=1 windSum=? windValue=1 oppValue=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-findNextOp debugShowSort contourWinding=-1 oppContourWinding=0 sign=-1
-debugShowSort [3] {{0,1}, {2,3}, {5,1}, {4,3}} tStart=0.285714286 tEnd=0.311007457 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [0] {{4,3}, {0,1}} tStart=0.539358601 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=0
-debugShowSort [1] {{0,1}, {2,3}, {5,1}, {4,3}} tStart=0.285714286 tEnd=0 sign=1 windValue=1 windSum=1 1->0 (max=1) done=1 tiny=0 opp=0
-debugShowSort [2] {{4,3}, {0,1}} tStart=0.539358601 tEnd=0.499089216 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=0 tiny=0 opp=0
-findNextOp firstIndex=[3] sign=-1
-activeOp op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-activeOp op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-activeOp op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-markDoneBinary id=1 (0,1 2,3 5,1 4,3) t=0.285714286 [1] (1.84256566,1.92128277) tEnd=0.311007457 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-findNextOp from:[1] to:[2] start=3 end=2
-bridgeOp current id=1 from=(2.00580978,1.94599628) to=(1.84256566,1.92128277)
-path.moveTo(2.00580978,1.94599628);
-path.cubicTo(1.9517231,1.93876874, 1.89728141,1.93057418, 1.84256566,1.92128277);
-findNextOp debugShowSort contourWinding=-1 oppContourWinding=0 sign=-1
-debugShowSort [1] {{4,3}, {0,1}} tStart=0.499089216 tEnd=0.539358601 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [2] {{1,5}, {3,4}, {1,0}, {3,2}} tStart=0.576935809 tEnd=0.285714286 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=1
-debugShowSort [3] {{4,3}, {0,1}} tStart=0.499089216 tEnd=0.3125 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [0] {{1,5}, {3,4}, {1,0}, {3,2}} tStart=0.576935809 tEnd=0.589885081 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=1
-findNextOp firstIndex=[1] sign=-1
-activeOp op=diff miFrom=0 miTo=0 suFrom=0 suTo=1 result=0
-markDoneBinary id=3 (1,5 3,4 1,0 3,2) t=0.285714286 [1] (1.92128277,3.61807585) tEnd=0.576935809 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-activeOp op=diff miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=2 (4,3 0,1) t=0.3125 [1] (2.75,2.375) tEnd=0.499089216 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=2
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
-markWinding id=3 (1,5 3,4 1,0 3,2) t=0.576935809 [2] (2.00364304,2.00182152) tEnd=0.589885081 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-markDoneBinary id=2 (4,3 0,1) t=0.499089216 [2] (2.00364304,2.00182152) tEnd=0.539358601 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-findNextOp from:[2] to:[3] start=2 end=3
-bridgeOp current id=2 from=(1.84256566,1.92128277) to=(2.00364304,2.00182152)
-findNextOp debugShowSort contourWinding=0 oppContourWinding=-1 sign=1
-debugShowSort [2] {{1,5}, {3,4}, {1,0}, {3,2}} tStart=0.589885081 tEnd=0.576935809 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [3] {{0,1}, {2,3}, {5,1}, {4,3}} tStart=0.311007457 tEnd=1 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=1
-debugShowSort [0] {{1,5}, {3,4}, {1,0}, {3,2}} tStart=0.589885081 tEnd=1 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [1] {{0,1}, {2,3}, {5,1}, {4,3}} tStart=0.311007457 tEnd=0.285714286 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=1
-findNextOp firstIndex=[2] sign=1
-activeOp op=diff miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
-markDoneBinary id=1 (0,1 2,3 5,1 4,3) t=0.311007457 [2] (2.00580978,1.94599628) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1
-markDoneBinary id=2 (4,3 0,1) t=0 [0] (4,3) tEnd=0.3125 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=2
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-markDoneBinary id=3 (1,5 3,4 1,0 3,2) t=0.589885081 [3] (2.00580978,1.94599628) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-markDoneBinary id=4 (3,2 1,5) t=0 [0] (3,2) tEnd=0.125 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=4
-activeOp op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-markDoneBinary id=3 (1,5 3,4 1,0 3,2) t=0.576935809 [2] (2.00364304,2.00182152) tEnd=0.589885081 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1
-findNextOp from:[3] to:[1] start=2 end=1
-bridgeOp current id=3 from=(2.00364304,2.00182152) to=(2.00580978,1.94599628)
-path.lineTo(2.00364304,2.00182152);
-path.cubicTo(2.00425649,1.98283899, 2.0049727,1.96422386, 2.00580978,1.94599628);
-path.close();
-findChaseOp debugShowSort contourWinding=0 oppContourWinding=0 sign=1
-debugShowSort [0] {{3,2}, {1,5}} tStart=0.125 tEnd=0 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [1] {{4,3}, {0,1}} tStart=0.3125 tEnd=0.499089216 sign=-1 windValue=1 windSum=-1 0->1 (max=1) done=1 tiny=0 opp=1
-debugShowSort [2] {{3,2}, {1,5}} tStart=0.125 tEnd=0.539358601 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [3] {{4,3}, {0,1}} tStart=0.3125 tEnd=0 sign=1 windValue=1 windSum=-1 1->0 (max=1) done=1 tiny=0 opp=1
-findChaseOp debugShowSort contourWinding=0 oppContourWinding=0 sign=1
-debugShowSort [0] {{3,2}, {1,5}} tStart=0.125 tEnd=0 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [1] {{4,3}, {0,1}} tStart=0.3125 tEnd=0.499089216 sign=-1 windValue=1 windSum=-1 0->1 (max=1) done=1 tiny=0 opp=1
-debugShowSort [2] {{3,2}, {1,5}} tStart=0.125 tEnd=0.539358601 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [3] {{4,3}, {0,1}} tStart=0.3125 tEnd=0 sign=1 windValue=1 windSum=-1 1->0 (max=1) done=1 tiny=0 opp=1
-markWinding id=4 (3,2 1,5) t=0.125 [1] (2.75,2.375) tEnd=0.539358601 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-debugShowActiveSpans id=3 (1,5 3,4 1,0 3,2) t=0 (1,5) tEnd=0.285714286 other=4 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (3,2 1,5) t=0.125 (2.75,2.375) tEnd=0.539358601 other=2 otherT=0.3125 otherIndex=1 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (3,2 1,5) t=0.539358601 (1.92128277,3.61807585) tEnd=1 other=3 otherT=0.285714286 otherIndex=1 windSum=? windValue=1 oppValue=0
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
-findNextOp debugShowSort contourWinding=0 oppContourWinding=1 sign=1
-debugShowSort [0] {{3,2}, {1,5}} tStart=0.539358601 tEnd=0.125 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [1] {{1,5}, {3,4}, {1,0}, {3,2}} tStart=0.285714286 tEnd=0.576935809 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [2] {{3,2}, {1,5}} tStart=0.539358601 tEnd=1 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [3] {{1,5}, {3,4}, {1,0}, {3,2}} tStart=0.285714286 tEnd=0 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=0
-findNextOp firstIndex=[0] sign=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-markWinding id=4 (3,2 1,5) t=0.539358601 [2] (1.92128277,3.61807585) tEnd=1 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1
-markWinding id=3 (1,5 3,4 1,0 3,2) t=0 [0] (1,5) tEnd=0.285714286 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
-markDoneBinary id=4 (3,2 1,5) t=0.125 [1] (2.75,2.375) tEnd=0.539358601 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1
-findNextOp from:[4] to:[3] start=1 end=0
-bridgeOp current id=4 from=(2.75,2.375) to=(1.92128277,3.61807585)
-findNextOp simple
-markDoneBinary id=3 (1,5 3,4 1,0 3,2) t=0 [0] (1,5) tEnd=0.285714286 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1
-bridgeOp current id=3 from=(1.92128277,3.61807585) to=(1,5)
-path.moveTo(2.75,2.375);
-path.lineTo(1.92128277,3.61807585);
-path.cubicTo(1.8163265,4.18367338, 1.57142854,4.71428585, 1,5);
-findNextOp debugShowSort contourWinding=0 oppContourWinding=1 sign=-1
-debugShowSort [2] {{3,2}, {1,5}} tStart=0.539358601 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [3] {{1,5}, {3,4}, {1,0}, {3,2}} tStart=0.285714286 tEnd=0 sign=1 windValue=1 windSum=1 1->0 (max=1) done=1 tiny=0 opp=0
-debugShowSort [0] {{3,2}, {1,5}} tStart=0.539358601 tEnd=0.125 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [1] {{1,5}, {3,4}, {1,0}, {3,2}} tStart=0.285714286 tEnd=0.576935809 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=0
-findNextOp firstIndex=[2] sign=-1
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
-markDoneBinary id=4 (3,2 1,5) t=0.539358601 [2] (1.92128277,3.61807585) tEnd=1 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1
-findNextOp from:[4] to:[3] start=1 end=2
-bridgeOp current id=4 from=(1,5) to=(1.92128277,3.61807585)
-</div>
-
-<div id="cubicOp39da">
-computed quadratics given
- {{2.512,1.571}, {2.64,1.66}, {2.8,1.8}, {3,2}},
- {{2.41818762,1.98497726}, {2.82699049,2.00933065}, {3.20046793,1.99420472}, {3.49861995,2.00359946}},
-computed quadratics set 1
- {{2.512,1.571}, {2.702,1.70225}, {3,2}},
-computed quadratics set 2
- {{2.41818762,1.98497726}, {2.79879886,2.00375569}, {3.125,2}},
- {{3.125,2}, {3.32670858,1.99910014}, {3.49861995,2.00359946}},
-</div>
-
-<div id="cubicOp40d">
- SimplifyNew_Test [cubicOp40d]
-{{0,1}, {1,5}, {3,2}, {4,2}},
-{{4,2}, {0,1}},
-op difference
-{{2,3}, {2,4}, {1,0}, {5,1}},
-{{5,1}, {2,3}},
-debugShowCubicIntersection no self intersect {{2,3}, {2,4}, {1,0}, {5,1}}
-debugShowCubicLineIntersection wtTs[0]=0 {{2,3}, {2,4}, {1,0}, {5,1}} {{2,3}} wtTs[1]=1 {{5,1}} wnTs[0]=1 {{5,1}, {2,3}} wnTs[1]=0
-debugShowCubicIntersection wtTs[0]=0 {{2,3}, {2,4}, {1,0}, {5,1}} {{2,3}} wtTs[1]=0.226611502 {{1.915764455286163,3.0259142027140675}} wnTs[0]=0.5 {{0,1}, {1,5}, {3,2}, {4,2}} wnTs[1]=0.481278074
-debugShowCubicLineIntersection wtTs[0]=0.601219833 {{2,3}, {2,4}, {1,0}, {5,1}} {{2.2195247359544519,1.554881183988613}} wnTs[0]=0.445119 {{4,2}, {0,1}}
-debugShowCubicLineIntersection wtTs[0]=0.5 {{0,1}, {1,5}, {3,2}, {4,2}} {{2.0000000000000009,2.9999999999999996}} wnTs[0]=1 {{5,1}, {2,3}}
-debugShowLineIntersection wtTs[0]=0.454545455 {{5,1}, {2,3}} {{3.6363636363636362,1.9090909090909089}} wnTs[0]=0.0909091 {{4,2}, {0,1}}
-debugShowCubicIntersection no self intersect {{0,1}, {1,5}, {3,2}, {4,2}}
-debugShowCubicLineIntersection wtTs[0]=0 {{0,1}, {1,5}, {3,2}, {4,2}} {{0,1}} wtTs[1]=1 {{4,2}} wnTs[0]=1 {{4,2}, {0,1}} wnTs[1]=0
-debugShowActiveSpans id=3 (2,3 2,4 1,0 5,1) t=0 (2,3) tEnd=0.226611502 other=4 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (2,3 2,4 1,0 5,1) t=0.226611502 (1.91576445,3.02591419) tEnd=0.601219833 other=1 otherT=0.481278074 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (2,3 2,4 1,0 5,1) t=0.601219833 (2.21952462,1.55488122) tEnd=1 other=2 otherT=0.445118816 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (5,1 2,3) t=0 (5,1) tEnd=0.454545455 other=3 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (5,1 2,3) t=0.454545455 (3.63636374,1.90909088) tEnd=1 other=2 otherT=0.0909090909 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (5,1 2,3) t=1 (2,3) tEnd=1 other=1 otherT=0.5 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,1 1,5 3,2 4,2) t=0 (0,1) tEnd=0.481278074 other=2 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,1 1,5 3,2 4,2) t=0.481278074 (1.91576445,3.02591419) tEnd=0.5 other=3 otherT=0.226611502 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,1 1,5 3,2 4,2) t=0.5 (2,3) tEnd=1 other=3 otherT=0 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,1 1,5 3,2 4,2) t=0.5 (2,3) tEnd=1 other=4 otherT=1 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,2 0,1) t=0 (4,2) tEnd=0.0909090909 other=1 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,2 0,1) t=0.0909090909 (3.63636374,1.90909088) tEnd=0.445118816 other=4 otherT=0.454545455 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,2 0,1) t=0.445118816 (2.21952462,1.55488122) tEnd=1 other=3 otherT=0.601219833 otherIndex=3 windSum=? windValue=1 oppValue=0
-findTop debugShowSort contourWinding=0 oppContourWinding=0 sign=1
-debugShowSort [0] {{2,3}, {2,4}, {1,0}, {5,1}} tStart=1 tEnd=0.601219833 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [1] {{5,1}, {2,3}} tStart=0 tEnd=0.454545455 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-findTop xyE=(5,1) xyS=(2.21952462,1.55488122)
-findTop dxyE=(12,3) dxyS=(2.8990562,-4.19263649) cross=-59.0088043 bumpsUp=true
-markWinding id=3 (2,3 2,4 1,0 5,1) t=0.601219833 [3] (2.21952462,1.55488122) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=4 (5,1 2,3) t=0 [0] (5,1) tEnd=0.454545455 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=3 (2,3 2,4 1,0 5,1) t=0.601219833 [3] (2.21952462,1.55488122) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-markDoneBinary id=3 (2,3 2,4 1,0 5,1) t=0.601219833 [3] (2.21952462,1.55488122) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-markDoneBinary id=4 (5,1 2,3) t=0 [0] (5,1) tEnd=0.454545455 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-findChaseOp debugShowSort contourWinding=0 oppContourWinding=0 sign=1
-debugShowSort [0] {{5,1}, {2,3}} tStart=0.454545455 tEnd=0 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [1] {{4,2}, {0,1}} tStart=0.0909090909 tEnd=0.445118816 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=1
-debugShowSort [2] {{5,1}, {2,3}} tStart=0.454545455 tEnd=1 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [3] {{4,2}, {0,1}} tStart=0.0909090909 tEnd=0 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=1
-findChaseOp debugShowSort contourWinding=0 oppContourWinding=0 sign=1
-debugShowSort [0] {{5,1}, {2,3}} tStart=0.454545455 tEnd=0 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [1] {{4,2}, {0,1}} tStart=0.0909090909 tEnd=0.445118816 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=1
-debugShowSort [2] {{5,1}, {2,3}} tStart=0.454545455 tEnd=1 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [3] {{4,2}, {0,1}} tStart=0.0909090909 tEnd=0 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=1
-markWinding id=2 (4,2 0,1) t=0.0909090909 [1] (3.63636374,1.90909088) tEnd=0.445118816 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1
-markWinding id=4 (5,1 2,3) t=0.454545455 [1] (3.63636374,1.90909088) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-markWinding id=2 (4,2 0,1) t=0 [0] (4,2) tEnd=0.0909090909 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=1 (0,1 1,5 3,2 4,2) t=0.5 [2] (2,3) tEnd=0.5 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=1 (0,1 1,5 3,2 4,2) t=0.5 [3] (2,3) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-debugShowActiveSpans id=3 (2,3 2,4 1,0 5,1) t=0 (2,3) tEnd=0.226611502 other=4 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (2,3 2,4 1,0 5,1) t=0.226611502 (1.91576445,3.02591419) tEnd=0.601219833 other=1 otherT=0.481278074 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (5,1 2,3) t=0.454545455 (3.63636374,1.90909088) tEnd=1 other=2 otherT=0.0909090909 otherIndex=1 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (5,1 2,3) t=1 (2,3) tEnd=1 other=1 otherT=0.5 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,1 1,5 3,2 4,2) t=0 (0,1) tEnd=0.481278074 other=2 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,1 1,5 3,2 4,2) t=0.481278074 (1.91576445,3.02591419) tEnd=0.5 other=3 otherT=0.226611502 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,1 1,5 3,2 4,2) t=0.5 (2,3) tEnd=1 other=3 otherT=0 otherIndex=1 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,1 1,5 3,2 4,2) t=0.5 (2,3) tEnd=1 other=4 otherT=1 otherIndex=2 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,2 0,1) t=0 (4,2) tEnd=0.0909090909 other=1 otherT=1 otherIndex=4 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,2 0,1) t=0.0909090909 (3.63636374,1.90909088) tEnd=0.445118816 other=4 otherT=0.454545455 otherIndex=1 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,2 0,1) t=0.445118816 (2.21952462,1.55488122) tEnd=1 other=3 otherT=0.601219833 otherIndex=3 windSum=? windValue=1 oppValue=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=2 (4,2 0,1) t=0.0909090909 [1] (3.63636374,1.90909088) tEnd=0.445118816 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1
-findChaseOp debugShowSort contourWinding=-1 oppContourWinding=0 sign=-1
-debugShowSort [0] {{2,3}, {2,4}, {1,0}, {5,1}} tStart=0.601219833 tEnd=1 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [1] {{4,2}, {0,1}} tStart=0.445118816 tEnd=1 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=1
-debugShowSort [2] {{2,3}, {2,4}, {1,0}, {5,1}} tStart=0.601219833 tEnd=0.226611502 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [3] {{4,2}, {0,1}} tStart=0.445118816 tEnd=0.0909090909 sign=1 windValue=1 windSum=1 1->0 (max=1) done=1 tiny=0 opp=1
-findChaseOp debugShowSort contourWinding=-1 oppContourWinding=0 sign=-1
-debugShowSort [0] {{2,3}, {2,4}, {1,0}, {5,1}} tStart=0.601219833 tEnd=1 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [1] {{4,2}, {0,1}} tStart=0.445118816 tEnd=1 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=1
-debugShowSort [2] {{2,3}, {2,4}, {1,0}, {5,1}} tStart=0.601219833 tEnd=0.226611502 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [3] {{4,2}, {0,1}} tStart=0.445118816 tEnd=0.0909090909 sign=1 windValue=1 windSum=1 1->0 (max=1) done=1 tiny=0 opp=1
-markWinding id=2 (4,2 0,1) t=0.445118816 [2] (2.21952462,1.55488122) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=1 (0,1 1,5 3,2 4,2) t=0 [0] (0,1) tEnd=0.481278074 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=3 (2,3 2,4 1,0 5,1) t=0.226611502 [2] (1.91576445,3.02591419) tEnd=0.601219833 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-debugShowActiveSpans id=3 (2,3 2,4 1,0 5,1) t=0 (2,3) tEnd=0.226611502 other=4 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (2,3 2,4 1,0 5,1) t=0.226611502 (1.91576445,3.02591419) tEnd=0.601219833 other=1 otherT=0.481278074 otherIndex=1 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (5,1 2,3) t=0.454545455 (3.63636374,1.90909088) tEnd=1 other=2 otherT=0.0909090909 otherIndex=1 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (5,1 2,3) t=1 (2,3) tEnd=1 other=1 otherT=0.5 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,1 1,5 3,2 4,2) t=0 (0,1) tEnd=0.481278074 other=2 otherT=1 otherIndex=3 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,1 1,5 3,2 4,2) t=0.481278074 (1.91576445,3.02591419) tEnd=0.5 other=3 otherT=0.226611502 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,1 1,5 3,2 4,2) t=0.5 (2,3) tEnd=1 other=3 otherT=0 otherIndex=1 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,1 1,5 3,2 4,2) t=0.5 (2,3) tEnd=1 other=4 otherT=1 otherIndex=2 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,2 0,1) t=0 (4,2) tEnd=0.0909090909 other=1 otherT=1 otherIndex=4 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,2 0,1) t=0.445118816 (2.21952462,1.55488122) tEnd=1 other=3 otherT=0.601219833 otherIndex=3 windSum=1 windValue=1 oppValue=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-findNextOp simple
-markDoneBinary id=2 (4,2 0,1) t=0.445118816 [2] (2.21952462,1.55488122) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-bridgeOp current id=2 from=(2.21952462,1.55488122) to=(0,1)
-findNextOp debugShowSort contourWinding=1 oppContourWinding=0 sign=1
-debugShowSort [2] {{0,1}, {1,5}, {3,2}, {4,2}} tStart=0.481278074 tEnd=0 sign=1 windValue=1 windSum=1 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [3] {{2,3}, {2,4}, {1,0}, {5,1}} tStart=0.226611502 tEnd=0 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=1
-debugShowSort [0] {{0,1}, {1,5}, {3,2}, {4,2}} tStart=0.481278074 tEnd=0.5 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] {{2,3}, {2,4}, {1,0}, {5,1}} tStart=0.226611502 tEnd=0.601219833 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=0 tiny=0 opp=1
-findNextOp firstIndex=[2] sign=1
-activeOp op=diff miFrom=0 miTo=0 suFrom=0 suTo=1 result=0
-markDoneBinary id=3 (2,3 2,4 1,0 5,1) t=0 [0] (2,3) tEnd=0 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-markDoneBinary id=3 (2,3 2,4 1,0 5,1) t=0 [1] (2,3) tEnd=0.226611502 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-activeOp op=diff miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=1 (0,1 1,5 3,2 4,2) t=0.481278074 [1] (1.91576445,3.02591419) tEnd=0.5 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
-markDoneBinary id=1 (0,1 1,5 3,2 4,2) t=0 [0] (0,1) tEnd=0.481278074 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-findNextOp from:[1] to:[3] start=2 end=3
-bridgeOp current id=1 from=(0,1) to=(1.91576445,3.02591419)
-path.moveTo(2.21952462,1.55488122);
-path.lineTo(0,1);
-path.cubicTo(0.481278062,2.92511225, 1.19418478,3.22882462, 1.91576445,3.02591419);
-findNextOp debugShowSort contourWinding=0 oppContourWinding=1 sign=1
-debugShowSort [2] {{2,3}, {2,4}, {1,0}, {5,1}} tStart=0.601219833 tEnd=0.226611502 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [3] {{4,2}, {0,1}} tStart=0.445118816 tEnd=0.0909090909 sign=1 windValue=1 windSum=1 1->0 (max=1) done=1 tiny=0 opp=1
-debugShowSort [0] {{2,3}, {2,4}, {1,0}, {5,1}} tStart=0.601219833 tEnd=1 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [1] {{4,2}, {0,1}} tStart=0.445118816 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=1
-findNextOp firstIndex=[2] sign=1
-activeOp op=diff miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-markDoneBinary id=3 (2,3 2,4 1,0 5,1) t=0.226611502 [2] (1.91576445,3.02591419) tEnd=0.601219833 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1
-findNextOp from:[3] to:[2] start=2 end=3
-bridgeOp current id=3 from=(1.91576445,3.02591419) to=(2.21952462,1.55488122)
-path.cubicTo(1.86140633,2.74398875, 1.8575213,2.07841325, 2.21952462,1.55488122);
-path.close();
-debugShowActiveSpans id=4 (5,1 2,3) t=0.454545455 (3.63636374,1.90909088) tEnd=1 other=2 otherT=0.0909090909 otherIndex=1 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (5,1 2,3) t=1 (2,3) tEnd=1 other=1 otherT=0.5 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,1 1,5 3,2 4,2) t=0.5 (2,3) tEnd=1 other=3 otherT=0 otherIndex=1 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,1 1,5 3,2 4,2) t=0.5 (2,3) tEnd=1 other=4 otherT=1 otherIndex=2 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,2 0,1) t=0 (4,2) tEnd=0.0909090909 other=1 otherT=1 otherIndex=4 windSum=1 windValue=1 oppValue=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-findNextOp simple
-markDoneBinary id=1 (0,1 1,5 3,2 4,2) t=0.5 [2] (2,3) tEnd=0.5 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-markDoneBinary id=1 (0,1 1,5 3,2 4,2) t=0.5 [3] (2,3) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-bridgeOp current id=1 from=(2,3) to=(4,2)
-path.moveTo(2,3);
-path.cubicTo(2.75,2.75, 3.5,2, 4,2);
-findNextOp debugShowSort contourWinding=1 oppContourWinding=0 sign=1
-debugShowSort [3] {{4,2}, {0,1}} tStart=0.0909090909 tEnd=0 sign=1 windValue=1 windSum=1 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [0] {{5,1}, {2,3}} tStart=0.454545455 tEnd=0 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=1
-debugShowSort [1] {{4,2}, {0,1}} tStart=0.0909090909 tEnd=0.445118816 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=0
-debugShowSort [2] {{5,1}, {2,3}} tStart=0.454545455 tEnd=1 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=0 tiny=0 opp=1
-findNextOp firstIndex=[3] sign=1
-activeOp op=diff miFrom=0 miTo=0 suFrom=0 suTo=1 result=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
-markDoneBinary id=2 (4,2 0,1) t=0 [0] (4,2) tEnd=0.0909090909 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-findNextOp from:[2] to:[4] start=1 end=2
-bridgeOp current id=2 from=(4,2) to=(3.63636374,1.90909088)
-findNextOp debugShowSort contourWinding=0 oppContourWinding=1 sign=1
-debugShowSort [1] {{5,1}, {2,3}} tStart=1 tEnd=0.454545455 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [2] {{0,1}, {1,5}, {3,2}, {4,2}} tStart=0.5 tEnd=0.481278074 sign=1 windValue=1 windSum=1 1->0 (max=1) done=1 tiny=0 opp=1
-debugShowSort [3] {{2,3}, {2,4}, {1,0}, {5,1}} tStart=0 tEnd=0.226611502 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [0] {{0,1}, {1,5}, {3,2}, {4,2}} tStart=0.5 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=1
-findNextOp firstIndex=[1] sign=1
-activeOp op=diff miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-markDoneBinary id=4 (5,1 2,3) t=0.454545455 [1] (3.63636374,1.90909088) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1
-findNextOp from:[4] to:[1] start=3 end=4
-bridgeOp current id=4 from=(3.63636374,1.90909088) to=(2,3)
-path.lineTo(3.63636374,1.90909088);
-path.lineTo(2,3);
-path.close();
-debugShowActiveSpans id=4 (5,1 2,3) t=1 (2,3) tEnd=1 other=1 otherT=0.5 otherIndex=3 windSum=? windValue=1 oppValue=0
-findTop debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [0] {{0,1}, {1,5}, {3,2}, {4,2}} tStart=0.5 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=0
-debugShowSort [1] {{5,1}, {2,3}} tStart=1 tEnd=0.454545455 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=1
-debugShowSort [2] {{0,1}, {1,5}, {3,2}, {4,2}} tStart=0.5 tEnd=0.481278074 sign=1 windValue=1 windSum=1 1->0 (max=1) done=1 tiny=0 opp=0
-debugShowSort [3] {{2,3}, {2,4}, {1,0}, {5,1}} tStart=0 tEnd=0.226611502 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=1
-</div>
-
-<div id="cubicOp41i">
- SimplifyNew_Test [cubicOp41i]
-{{0,1}, {2,6}, {4,3}, {6,4}},
-{{6,4}, {0,1}},
-op intersect
-{{3,4}, {4,6}, {1,0}, {6,2}},
-{{6,2}, {3,4}},
-debugShowCubicIntersection no self intersect {{0,1}, {2,6}, {4,3}, {6,4}}
-debugShowCubicLineIntersection wtTs[0]=0 {{0,1}, {2,6}, {4,3}, {6,4}} {{0,1}} wtTs[1]=1 {{6,4}} wnTs[0]=1 {{6,4}, {0,1}} wnTs[1]=0
-debugShowCubicIntersection wtTs[0]=0.5 {{0,1}, {2,6}, {4,3}, {6,4}} {{2.9999999999509201,3.9999999999999996}} wtTs[1]=0.521137715 {{3.1268262924910069,3.9974325146613827}} wnTs[0]=0 {{3,4}, {4,6}, {1,0}, {6,2}} wnTs[1]=0.317571165
-debugShowCubicLineIntersection wtTs[0]=0.5 {{0,1}, {2,6}, {4,3}, {6,4}} {{3,4}} wnTs[0]=1 {{6,2}, {3,4}}
-debugShowCubicLineIntersection wtTs[0]=0.580941393 {{3,4}, {4,6}, {1,0}, {6,2}} {{3.0456725133851208,2.5228362566925604}} wnTs[0]=0.492388 {{6,4}, {0,1}}
-debugShowLineIntersection wtTs[0]=0.285714286 {{6,4}, {0,1}} {{4.2857142857142856,3.1428571428571428}} wnTs[0]=0.571429 {{6,2}, {3,4}}
-debugShowCubicIntersection no self intersect {{3,4}, {4,6}, {1,0}, {6,2}}
-debugShowCubicLineIntersection wtTs[0]=0 {{3,4}, {4,6}, {1,0}, {6,2}} {{3,4}} wtTs[1]=0.333333333 {{3.1111111111111116,3.9259259259259256}} wtTs[2]=1 {{6,2}} wnTs[0]=1 {{6,2}, {3,4}} wnTs[1]=0.962962963 wnTs[2]=0
-debugShowActiveSpans id=1 (0,1 2,6 4,3 6,4) t=0 (0,1) tEnd=0.5 other=2 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,1 2,6 4,3 6,4) t=0.5 (3,4) tEnd=0.521137715 other=4 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,1 2,6 4,3 6,4) t=0.521137715 (3.12682629,3.99743247) tEnd=1 other=3 otherT=0.317571165 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (6,4 0,1) t=0 (6,4) tEnd=0.285714286 other=1 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (6,4 0,1) t=0.285714286 (4.28571415,3.14285707) tEnd=0.492387914 other=4 otherT=0.571428571 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (6,4 0,1) t=0.492387914 (3.04567242,2.52283621) tEnd=1 other=3 otherT=0.580941393 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (3,4 4,6 1,0 6,2) t=0 (3,4) tEnd=0.317571165 other=1 otherT=0.5 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (3,4 4,6 1,0 6,2) t=0.317571165 (3.12682629,3.99743247) tEnd=0.333333333 other=1 otherT=0.521137715 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (3,4 4,6 1,0 6,2) t=0.333333333 (3.11111116,3.92592597) tEnd=0.580941393 other=4 otherT=0.962962963 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (3,4 4,6 1,0 6,2) t=0.580941393 (3.04567242,2.52283621) tEnd=1 other=2 otherT=0.492387914 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (6,2 3,4) t=0 (6,2) tEnd=0.571428571 other=3 otherT=1 otherIndex=5 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (6,2 3,4) t=0.571428571 (4.28571415,3.14285707) tEnd=0.962962963 other=2 otherT=0.285714286 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (6,2 3,4) t=0.962962963 (3.11111116,3.92592597) tEnd=1 other=3 otherT=0.333333333 otherIndex=3 windSum=? windValue=1 oppValue=0
-findTop debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [0] {{0,1}, {2,6}, {4,3}, {6,4}} tStart=0 tEnd=0.5 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] {{6,4}, {0,1}} tStart=1 tEnd=0.492387914 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=0
-findTop xyE=(0,1) xyS=(3,4)
-findTop dxyE=(6,15) dxyS=(6,9.81599801e-11) cross=-90 bumpsUp=false
-markWinding id=1 (0,1 2,6 4,3 6,4) t=0 [0] (0,1) tEnd=0.5 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=2 (6,4 0,1) t=0.492387914 [2] (3.04567242,2.52283621) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=1 (0,1 2,6 4,3 6,4) t=0 [0] (0,1) tEnd=0.5 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-activeOp op=sect miFrom=1 miTo=0 suFrom=0 suTo=0 result=0
-markDoneBinary id=1 (0,1 2,6 4,3 6,4) t=0 [0] (0,1) tEnd=0.5 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-markDoneBinary id=2 (6,4 0,1) t=0.492387914 [2] (3.04567242,2.52283621) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-findChaseOp debugShowSort contourWinding=? oppContourWinding=? sign=-1
-debugShowSort [0] {{3,4}, {4,6}, {1,0}, {6,2}} tStart=0.580941393 tEnd=1 sign=-1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=0
-debugShowSort [1] {{6,4}, {0,1}} tStart=0.492387914 tEnd=1 sign=-1 windValue=1 windSum=1 ?->? (max=?) done=1 tiny=0 opp=1
-debugShowSort [2] {{3,4}, {4,6}, {1,0}, {6,2}} tStart=0.580941393 tEnd=0.333333333 sign=1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=0
-debugShowSort [3] {{6,4}, {0,1}} tStart=0.492387914 tEnd=0.285714286 sign=1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=1
-findChaseOp debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [1] {{6,4}, {0,1}} tStart=0.492387914 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=0
-debugShowSort [2] {{3,4}, {4,6}, {1,0}, {6,2}} tStart=0.580941393 tEnd=0.333333333 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=1
-debugShowSort [3] {{6,4}, {0,1}} tStart=0.492387914 tEnd=0.285714286 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [0] {{3,4}, {4,6}, {1,0}, {6,2}} tStart=0.580941393 tEnd=1 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=1
-markWinding id=3 (3,4 4,6 1,0 6,2) t=0.333333333 [3] (3.11111116,3.92592597) tEnd=0.580941393 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-markWinding id=2 (6,4 0,1) t=0.285714286 [1] (4.28571415,3.14285707) tEnd=0.492387914 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1
-markWinding id=3 (3,4 4,6 1,0 6,2) t=0.580941393 [4] (3.04567242,2.52283621) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=4 (6,2 3,4) t=0 [0] (6,2) tEnd=0.571428571 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-debugShowActiveSpans id=1 (0,1 2,6 4,3 6,4) t=0.5 (3,4) tEnd=0.521137715 other=4 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,1 2,6 4,3 6,4) t=0.521137715 (3.12682629,3.99743247) tEnd=1 other=3 otherT=0.317571165 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (6,4 0,1) t=0 (6,4) tEnd=0.285714286 other=1 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (6,4 0,1) t=0.285714286 (4.28571415,3.14285707) tEnd=0.492387914 other=4 otherT=0.571428571 otherIndex=1 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=3 (3,4 4,6 1,0 6,2) t=0 (3,4) tEnd=0.317571165 other=1 otherT=0.5 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (3,4 4,6 1,0 6,2) t=0.317571165 (3.12682629,3.99743247) tEnd=0.333333333 other=1 otherT=0.521137715 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (3,4 4,6 1,0 6,2) t=0.333333333 (3.11111116,3.92592597) tEnd=0.580941393 other=4 otherT=0.962962963 otherIndex=2 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=3 (3,4 4,6 1,0 6,2) t=0.580941393 (3.04567242,2.52283621) tEnd=1 other=2 otherT=0.492387914 otherIndex=2 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (6,2 3,4) t=0 (6,2) tEnd=0.571428571 other=3 otherT=1 otherIndex=5 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (6,2 3,4) t=0.571428571 (4.28571415,3.14285707) tEnd=0.962962963 other=2 otherT=0.285714286 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (6,2 3,4) t=0.962962963 (3.11111116,3.92592597) tEnd=1 other=3 otherT=0.333333333 otherIndex=3 windSum=? windValue=1 oppValue=0
-activeOp op=sect miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-findNextOp debugShowSort contourWinding=-1 oppContourWinding=1 sign=-1
-debugShowSort [1] {{3,4}, {4,6}, {1,0}, {6,2}} tStart=0.333333333 tEnd=0.580941393 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [2] {{6,2}, {3,4}} tStart=0.962962963 tEnd=1 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [3] {{3,4}, {4,6}, {1,0}, {6,2}} tStart=0.333333333 tEnd=0.317571165 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [0] {{6,2}, {3,4}} tStart=0.962962963 tEnd=0.571428571 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-findNextOp firstIndex=[1] sign=-1
-activeOp op=sect miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-markWinding id=4 (6,2 3,4) t=0.962962963 [2] (3.11111116,3.92592597) tEnd=1 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=4
-activeOp op=sect miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
-markWinding id=3 (3,4 4,6 1,0 6,2) t=0.317571165 [2] (3.12682629,3.99743247) tEnd=0.333333333 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-activeOp op=sect miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-markWinding id=4 (6,2 3,4) t=0.571428571 [1] (4.28571415,3.14285707) tEnd=0.962962963 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=4
-markDoneBinary id=3 (3,4 4,6 1,0 6,2) t=0.333333333 [3] (3.11111116,3.92592597) tEnd=0.580941393 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1
-findNextOp from:[3] to:[4] start=2 end=3
-bridgeOp current id=3 from=(3.04567242,2.52283621) to=(3.11111116,3.92592597)
-path.moveTo(3.04567242,2.52283621);
-path.cubicTo(2.9460392,2.99209714, 3.02857494,3.54075789, 3.11111116,3.92592597);
-markUnsortable id=4 (6,2 3,4) t=0.962962963 [2] (3.11111116,3.92592597) tEnd=1 newWindSum=0 windSum=1 windValue=1
-markUnsortable id=1 (0,1 2,6 4,3 6,4) t=0.5 [2] (3,4) tEnd=0.521137715 newWindSum=0 windSum=? windValue=1
-markUnsortable id=1 (0,1 2,6 4,3 6,4) t=0.5 [1] (3,4) tEnd=0.5 newWindSum=0 windSum=? windValue=1
-markUnsortable id=3 (3,4 4,6 1,0 6,2) t=0 [1] (3,4) tEnd=0.317571165 newWindSum=0 windSum=? windValue=1
-findNextOp debugShowSort contourWinding=1 oppContourWinding=1 sign=1
-debugShowSort [0] {{6,2}, {3,4}} tStart=1 tEnd=0.962962963 sign=1 windValue=1 windSum=1 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] {{0,1}, {2,6}, {4,3}, {6,4}} tStart=0.5 tEnd=0.521137715 sign=-1 windValue=1 windSum=? 1->2 (max=2) done=0 tiny=0 opp=1
-debugShowSort [2] *** UNSORTABLE *** {{0,1}, {2,6}, {4,3}, {6,4}} tStart=0.5 tEnd=0.5 sign=1 windValue=1 windSum=? 2->1 (max=2) done=1 tiny=1 opp=1
-debugShowSort [3] {{3,4}, {4,6}, {1,0}, {6,2}} tStart=0 tEnd=0.317571165 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=0
-markDoneBinary id=4 (6,2 3,4) t=0.962962963 [2] (3.11111116,3.92592597) tEnd=1 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1
-path.lineTo(3,4);
-debugShowActiveSpans id=1 (0,1 2,6 4,3 6,4) t=0.5 (3,4) tEnd=0.521137715 other=4 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,1 2,6 4,3 6,4) t=0.521137715 (3.12682629,3.99743247) tEnd=1 other=3 otherT=0.317571165 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (6,4 0,1) t=0 (6,4) tEnd=0.285714286 other=1 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (6,4 0,1) t=0.285714286 (4.28571415,3.14285707) tEnd=0.492387914 other=4 otherT=0.571428571 otherIndex=1 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=3 (3,4 4,6 1,0 6,2) t=0 (3,4) tEnd=0.317571165 other=1 otherT=0.5 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (3,4 4,6 1,0 6,2) t=0.317571165 (3.12682629,3.99743247) tEnd=0.333333333 other=1 otherT=0.521137715 otherIndex=3 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=3 (3,4 4,6 1,0 6,2) t=0.580941393 (3.04567242,2.52283621) tEnd=1 other=2 otherT=0.492387914 otherIndex=2 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (6,2 3,4) t=0 (6,2) tEnd=0.571428571 other=3 otherT=1 otherIndex=5 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (6,2 3,4) t=0.571428571 (4.28571415,3.14285707) tEnd=0.962962963 other=2 otherT=0.285714286 otherIndex=1 windSum=-1 windValue=1 oppValue=0
-activeOp op=sect miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
-findNextOp debugShowSort contourWinding=0 oppContourWinding=1 sign=1
-debugShowSort [0] {{6,2}, {3,4}} tStart=0.962962963 tEnd=0.571428571 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [1] {{3,4}, {4,6}, {1,0}, {6,2}} tStart=0.333333333 tEnd=0.580941393 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [2] {{6,2}, {3,4}} tStart=0.962962963 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=0
-debugShowSort [3] {{3,4}, {4,6}, {1,0}, {6,2}} tStart=0.333333333 tEnd=0.317571165 sign=1 windValue=1 windSum=1 1->0 (max=1) done=0 tiny=0 opp=0
-findNextOp firstIndex=[0] sign=1
-activeOp op=sect miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
-activeOp op=sect miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-activeOp op=sect miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
-markDoneBinary id=4 (6,2 3,4) t=0.571428571 [1] (4.28571415,3.14285707) tEnd=0.962962963 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1
-findNextOp from:[4] to:[3] start=3 end=2
-bridgeOp current id=4 from=(4.28571415,3.14285707) to=(3.11111116,3.92592597)
-findNextOp debugShowSort contourWinding=0 oppContourWinding=1 sign=-1
-debugShowSort [1] {{3,4}, {4,6}, {1,0}, {6,2}} tStart=0.317571165 tEnd=0.333333333 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [2] {{0,1}, {2,6}, {4,3}, {6,4}} tStart=0.521137715 tEnd=0.5 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=1
-debugShowSort [3] {{3,4}, {4,6}, {1,0}, {6,2}} tStart=0.317571165 tEnd=0 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [0] {{0,1}, {2,6}, {4,3}, {6,4}} tStart=0.521137715 tEnd=1 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=1
-findNextOp firstIndex=[1] sign=-1
-activeOp op=sect miFrom=1 miTo=0 suFrom=1 suTo=1 result=1
-markWinding id=1 (0,1 2,6 4,3 6,4) t=0.5 [2] (3,4) tEnd=0.521137715 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=1
-activeOp op=sect miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-markDoneBinary id=3 (3,4 4,6 1,0 6,2) t=0 [0] (3,4) tEnd=0 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markDoneBinary id=3 (3,4 4,6 1,0 6,2) t=0 [1] (3,4) tEnd=0.317571165 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-activeOp op=sect miFrom=0 miTo=1 suFrom=0 suTo=0 result=0
-markDoneBinary id=1 (0,1 2,6 4,3 6,4) t=0.521137715 [3] (3.12682629,3.99743247) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markDoneBinary id=2 (6,4 0,1) t=0 [0] (6,4) tEnd=0.285714286 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=2
-markDoneBinary id=3 (3,4 4,6 1,0 6,2) t=0.317571165 [2] (3.12682629,3.99743247) tEnd=0.333333333 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1
-findNextOp from:[3] to:[1] start=3 end=2
-bridgeOp current id=3 from=(3.11111116,3.92592597) to=(3.12682629,3.99743247)
-path.moveTo(4.28571415,3.14285707);
-path.lineTo(3.11111116,3.92592597);
-path.cubicTo(3.11636519,3.9504447, 3.12161922,3.97430134, 3.12682629,3.99743247);
-setSpans unsortable [2] (3,4) [3] (3.12682629,3.99743247)
-setSpans unsortable [3] (3,4) [2] (3.11111116,3.92592597)
-markUnsortable id=1 (0,1 2,6 4,3 6,4) t=0.5 [2] (3,4) tEnd=0.521137715 newWindSum=0 windSum=1 windValue=1
-markUnsortable id=1 (0,1 2,6 4,3 6,4) t=0.5 [1] (3,4) tEnd=0.5 newWindSum=0 windSum=? windValue=1
-markUnsortable id=4 (6,2 3,4) t=0.962962963 [2] (3.11111116,3.92592597) tEnd=1 newWindSum=0 windSum=1 windValue=1
-findNextOp debugShowSort contourWinding=0 oppContourWinding=1 sign=-1
-debugShowSort [0] *** UNSORTABLE *** {{0,1}, {2,6}, {4,3}, {6,4}} tStart=0.5 tEnd=0.521137715 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] *** UNSORTABLE *** {{0,1}, {2,6}, {4,3}, {6,4}} tStart=0.5 tEnd=0.5 sign=1 windValue=1 windSum=? 1->0 (max=1) done=1 tiny=1 opp=0
-debugShowSort [2] *** UNSORTABLE *** {{6,2}, {3,4}} tStart=1 tEnd=0.962962963 sign=1 windValue=1 windSum=1 1->0 (max=1) done=1 tiny=0 opp=1
-path.cubicTo(3.08455086,3.99910641, 3.04227543,4, 3,4);
-markDoneBinary id=1 (0,1 2,6 4,3 6,4) t=0.5 [2] (3,4) tEnd=0.521137715 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1
-debugShowActiveSpans id=2 (6,4 0,1) t=0.285714286 (4.28571415,3.14285707) tEnd=0.492387914 other=4 otherT=0.571428571 otherIndex=1 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=3 (3,4 4,6 1,0 6,2) t=0.580941393 (3.04567242,2.52283621) tEnd=1 other=2 otherT=0.492387914 otherIndex=2 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (6,2 3,4) t=0 (6,2) tEnd=0.571428571 other=3 otherT=1 otherIndex=5 windSum=-1 windValue=1 oppValue=0
-activeOp op=sect miFrom=0 miTo=1 suFrom=1 suTo=1 result=1
-findNextOp debugShowSort contourWinding=1 oppContourWinding=-1 sign=1
-debugShowSort [3] {{6,4}, {0,1}} tStart=0.492387914 tEnd=0.285714286 sign=1 windValue=1 windSum=1 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [0] {{3,4}, {4,6}, {1,0}, {6,2}} tStart=0.580941393 tEnd=1 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=0 tiny=0 opp=1
-debugShowSort [1] {{6,4}, {0,1}} tStart=0.492387914 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=0
-debugShowSort [2] {{3,4}, {4,6}, {1,0}, {6,2}} tStart=0.580941393 tEnd=0.333333333 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=1
-findNextOp firstIndex=[3] sign=1
-activeOp op=sect miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-activeOp op=sect miFrom=0 miTo=1 suFrom=0 suTo=0 result=0
-activeOp op=sect miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-markDoneBinary id=2 (6,4 0,1) t=0.285714286 [1] (4.28571415,3.14285707) tEnd=0.492387914 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1
-findNextOp from:[2] to:[3] start=4 end=3
-bridgeOp current id=2 from=(4.28571415,3.14285707) to=(3.04567242,2.52283621)
-path.moveTo(4.28571415,3.14285707);
-path.lineTo(3.04567242,2.52283621);
-setSpans unsortable [1] (3,4) [2] (3.12682629,3.99743247)
-setSpans all tiny unsortable [1] (3,4) [0] (0,1)
-setSpans unsortable [3] (3,4) [2] (3.11111116,3.92592597)
-setSpans unsortable [2] (3,4) [3] (3.12682629,3.99743247)
-setSpans unsortable [1] (3,4) [2] (3.12682629,3.99743247)
-setSpans unsortable [3] (3,4) [2] (3.11111116,3.92592597)
-setSpans unsortable [3] (3,4) [2] (3.11111116,3.92592597)
-setSpans unsortable [2] (3,4) [3] (3.12682629,3.99743247)
-setSpans unsortable [1] (3,4) [2] (3.12682629,3.99743247)
-debugShowActiveSpans id=3 (3,4 4,6 1,0 6,2) t=0.580941393 (3.04567242,2.52283621) tEnd=1 other=2 otherT=0.492387914 otherIndex=2 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (6,2 3,4) t=0 (6,2) tEnd=0.571428571 other=3 otherT=1 otherIndex=5 windSum=-1 windValue=1 oppValue=0
-activeOp op=sect miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-markDoneBinary id=3 (3,4 4,6 1,0 6,2) t=0.580941393 [4] (3.04567242,2.52283621) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-markDoneBinary id=4 (6,2 3,4) t=0 [0] (6,2) tEnd=0.571428571 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-</div>
-
-<div id="cubicOp42d">
- SimplifyNew_Test [cubicOp42d]
-{{0,1}, {1,2}, {6,5}, {5,4}},
-{{5,4}, {0,1}},
-op difference
-{{5,6}, {4,5}, {1,0}, {2,1}},
-{{2,1}, {5,6}},
-debugShowCubicIntersection no self intersect {{5,6}, {4,5}, {1,0}, {2,1}}
-debugShowCubicLineIntersection wtTs[0]=0 {{5,6}, {4,5}, {1,0}, {2,1}} {{5,6}} wtTs[1]=1 {{2,1}} wnTs[0]=1 {{2,1}, {5,6}} wnTs[1]=0
-debugShowCubicIntersection no intersect {{5,6}, {4,5}, {1,0}, {2,1}} {{0,1}, {1,2}, {6,5}, {5,4}}
-debugShowCubicLineIntersection wtTs[0]=0.520955385 {{5,6}, {4,5}, {1,0}, {2,1}} {{2.6570733652881806,2.5942440191729084}} wnTs[0]=0.468585 {{5,4}, {0,1}}
-debugShowCubicLineIntersection wtTs[0]=0.520955385 {{0,1}, {1,2}, {6,5}, {5,4}} {{3.4057559808270916,3.3429266347118194}} wnTs[0]=0.468585 {{2,1}, {5,6}}
-debugShowLineIntersection wtTs[0]=0.375 {{2,1}, {5,6}} {{3.125,2.875}} wnTs[0]=0.375 {{5,4}, {0,1}}
-debugShowCubicIntersection no self intersect {{0,1}, {1,2}, {6,5}, {5,4}}
-debugShowCubicLineIntersection wtTs[0]=0 {{0,1}, {1,2}, {6,5}, {5,4}} {{0,1}} wtTs[1]=1 {{5,4}} wnTs[0]=1 {{5,4}, {0,1}} wnTs[1]=0
-debugShowActiveSpans id=3 (5,6 4,5 1,0 2,1) t=0 (5,6) tEnd=0.520955385 other=4 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (5,6 4,5 1,0 2,1) t=0.520955385 (2.65707326,2.594244) tEnd=1 other=2 otherT=0.468585327 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (2,1 5,6) t=0 (2,1) tEnd=0.375 other=3 otherT=1 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (2,1 5,6) t=0.375 (3.125,2.875) tEnd=0.468585327 other=2 otherT=0.375 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (2,1 5,6) t=0.468585327 (3.405756,3.34292674) tEnd=1 other=1 otherT=0.520955385 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,1 1,2 6,5 5,4) t=0 (0,1) tEnd=0.520955385 other=2 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,1 1,2 6,5 5,4) t=0.520955385 (3.405756,3.34292674) tEnd=1 other=4 otherT=0.468585327 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,4 0,1) t=0 (5,4) tEnd=0.375 other=1 otherT=1 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,4 0,1) t=0.375 (3.125,2.875) tEnd=0.468585327 other=4 otherT=0.375 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,4 0,1) t=0.468585327 (2.65707326,2.594244) tEnd=1 other=3 otherT=0.520955385 otherIndex=1 windSum=? windValue=1 oppValue=0
-findTop debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [0] {{0,1}, {1,2}, {6,5}, {5,4}} tStart=0 tEnd=0.520955385 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] {{5,4}, {0,1}} tStart=1 tEnd=0.468585327 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=0
-findTop xyE=(0,1) xyS=(3.405756,3.34292674)
-findTop dxyE=(3,3) dxyS=(7.361094,4.36636353) cross=-8.98419189 bumpsUp=false
-markWinding id=1 (0,1 1,2 6,5 5,4) t=0 [0] (0,1) tEnd=0.520955385 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=2 (5,4 0,1) t=0.468585327 [2] (2.65707326,2.594244) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=1 (0,1 1,2 6,5 5,4) t=0 [0] (0,1) tEnd=0.520955385 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-activeOp op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-findNextOp simple
-markDoneBinary id=1 (0,1 1,2 6,5 5,4) t=0 [0] (0,1) tEnd=0.520955385 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-bridgeOp current id=1 from=(3.405756,3.34292674) to=(0,1)
-path.moveTo(3.405756,3.34292674);
-path.cubicTo(2.12748885,2.58469963, 0.520955384,1.52095544, 0,1);
-findNextOp debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [1] {{5,4}, {0,1}} tStart=0.468585327 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [2] {{5,6}, {4,5}, {1,0}, {2,1}} tStart=0.520955385 tEnd=0 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=1
-debugShowSort [3] {{5,4}, {0,1}} tStart=0.468585327 tEnd=0.375 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [0] {{5,6}, {4,5}, {1,0}, {2,1}} tStart=0.520955385 tEnd=1 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=1
-findNextOp firstIndex=[1] sign=-1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-markWinding id=3 (5,6 4,5 1,0 2,1) t=0 [0] (5,6) tEnd=0.520955385 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-markWinding id=4 (2,1 5,6) t=0.468585327 [2] (3.405756,3.34292674) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=4
-activeOp op=diff miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
-markDoneBinary id=2 (5,4 0,1) t=0.375 [1] (3.125,2.875) tEnd=0.468585327 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=2
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-markDoneBinary id=3 (5,6 4,5 1,0 2,1) t=0.520955385 [1] (2.65707326,2.594244) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-markDoneBinary id=4 (2,1 5,6) t=0 [0] (2,1) tEnd=0.375 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=4
-markDoneBinary id=2 (5,4 0,1) t=0.468585327 [2] (2.65707326,2.594244) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-findNextOp from:[2] to:[3] start=1 end=0
-bridgeOp current id=2 from=(0,1) to=(2.65707326,2.594244)
-findNextOp simple
-markDoneBinary id=3 (5,6 4,5 1,0 2,1) t=0 [0] (5,6) tEnd=0.520955385 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1
-bridgeOp current id=3 from=(2.65707326,2.594244) to=(5,6)
-path.lineTo(2.65707326,2.594244);
-path.cubicTo(3.41530037,3.87251115, 4.47904444,5.47904444, 5,6);
-findNextOp debugShowSort contourWinding=-1 oppContourWinding=1 sign=-1
-debugShowSort [2] {{2,1}, {5,6}} tStart=0.468585327 tEnd=1 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [3] {{0,1}, {1,2}, {6,5}, {5,4}} tStart=0.520955385 tEnd=1 sign=-1 windValue=1 windSum=? 1->2 (max=2) done=0 tiny=0 opp=1
-debugShowSort [0] {{2,1}, {5,6}} tStart=0.468585327 tEnd=0.375 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [1] {{0,1}, {1,2}, {6,5}, {5,4}} tStart=0.520955385 tEnd=0 sign=1 windValue=1 windSum=1 2->1 (max=2) done=1 tiny=0 opp=1
-findNextOp firstIndex=[2] sign=-1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=0 result=0
-markDoneBinary id=1 (0,1 1,2 6,5 5,4) t=0.520955385 [1] (3.405756,3.34292674) tEnd=1 newWindSum=2 newOppSum=0 oppSum=? windSum=? windValue=1
-markDoneBinary id=2 (5,4 0,1) t=0 [0] (5,4) tEnd=0.375 newWindSum=2 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=2
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-markWinding id=4 (2,1 5,6) t=0.375 [1] (3.125,2.875) tEnd=0.468585327 newWindSum=-1 newOppSum=2 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=4
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=4 (2,1 5,6) t=0.468585327 [2] (3.405756,3.34292674) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1
-findNextOp from:[4] to:[4] start=2 end=1
-bridgeOp current id=4 from=(5,6) to=(3.405756,3.34292674)
-path.lineTo(3.405756,3.34292674);
-path.close();
-debugShowActiveSpans id=4 (2,1 5,6) t=0.375 (3.125,2.875) tEnd=0.468585327 other=2 otherT=0.375 otherIndex=1 windSum=-1 windValue=1 oppValue=0
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
-findNextOp debugShowSort contourWinding=0 oppContourWinding=2 sign=1
-debugShowSort [0] {{2,1}, {5,6}} tStart=0.468585327 tEnd=0.375 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [1] {{0,1}, {1,2}, {6,5}, {5,4}} tStart=0.520955385 tEnd=0 sign=1 windValue=1 windSum=1 2->1 (max=2) done=1 tiny=0 opp=1
-debugShowSort [2] {{2,1}, {5,6}} tStart=0.468585327 tEnd=1 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [3] {{0,1}, {1,2}, {6,5}, {5,4}} tStart=0.520955385 tEnd=1 sign=-1 windValue=1 windSum=2 1->2 (max=2) done=1 tiny=0 opp=1
-findNextOp firstIndex=[0] sign=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=1 result=0
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=0 result=0
-markDoneBinary id=4 (2,1 5,6) t=0.375 [1] (3.125,2.875) tEnd=0.468585327 newWindSum=-1 newOppSum=2 oppSum=2 windSum=-1 windValue=1
-findNextOp from:[4] to:[4] start=2 end=3
-bridgeOp current id=4 from=(3.125,2.875) to=(3.405756,3.34292674)
-</div>
-
-<div id="cubicOp42da">
-computed quadratics given
- {{0,1}, {1,2}, {6,5}, {5,4}},
- {{5,6}, {4,5}, {1,0}, {2,1}},
-computed quadratics set 1
- {{0,1}, {0.4140625,1.3984375}, {1.34375,2.03125}},
- {{1.34375,2.03125}, {2.2734375,2.6640625}, {3.25,3.25}},
- {{3.25,3.25}, {4.2265625,3.8359375}, {4.78125,4.09375}},
- {{4.78125,4.09375}, {5.3359375,4.3515625}, {5,4}},
-computed quadratics set 2
- {{5,6}, {4.6015625,5.5859375}, {3.96875,4.65625}},
- {{3.96875,4.65625}, {3.3359375,3.7265625}, {2.75,2.75}},
- {{2.75,2.75}, {2.1640625,1.7734375}, {1.90625,1.21875}},
- {{1.90625,1.21875}, {1.6484375,0.6640625}, {2,1}},
-</div>
-
-<div id="cubicOp42db">
- {{1.34375,2.03125}, {2.2734375,2.6640625}, {3.25,3.25}},
- {{3.96875,4.65625}, {3.3359375,3.7265625}, {2.75,2.75}},
-</div>
-
-<div id="cubicOp43d">
- SimplifyNew_Test [cubicOp43d]
-{{0,2}, {1,2}, {4,0}, {3,1}},
-{{3,1}, {0,2}},
-op difference
-{{0,4}, {1,3}, {2,0}, {2,1}},
-{{2,1}, {0,4}},
-debugShowCubicIntersection no self intersect {{0,2}, {1,2}, {4,0}, {3,1}}
-debugShowCubicLineIntersection wtTs[0]=0 {{0,2}, {1,2}, {4,0}, {3,1}} {{0,2}} wtTs[1]=0.333333333 {{1.4444444444444446,1.5185185185185186}} wtTs[2]=1 {{3,1}} wnTs[0]=1 {{3,1}, {0,2}} wnTs[1]=0.518518519 wnTs[2]=0
-debugShowCubicIntersection wtTs[0]=0.345547542 {{0,2}, {1,2}, {4,0}, {3,1}} {{1.5055045552472988,1.4898786220870244}} wnTs[0]=0.560544 {{0,4}, {1,3}, {2,0}, {2,1}}
-debugShowCubicLineIntersection wtTs[0]=0.395188999 {{0,2}, {1,2}, {4,0}, {3,1}} {{1.7523027701818603,1.3715458447272095}} wnTs[0]=0.123849 {{2,1}, {0,4}}
-debugShowCubicLineIntersection wtTs[0]=0.558102564 {{0,4}, {1,3}, {2,0}, {2,1}} {{1.5004707573680853,1.4998430808773049}} wnTs[0]=0.499843 {{3,1}, {0,2}}
-debugShowLineIntersection wtTs[0]=0.428571429 {{3,1}, {0,2}} {{1.7142857142857142,1.4285714285714284}} wnTs[0]=0.142857 {{2,1}, {0,4}}
-debugShowCubicIntersection no self intersect {{0,4}, {1,3}, {2,0}, {2,1}}
-debugShowCubicLineIntersection wtTs[0]=0 {{0,4}, {1,3}, {2,0}, {2,1}} {{0,4}} wtTs[1]=0.333333333 {{0.96296296296296258,2.5555555555555562}} wtTs[2]=1 {{2,1}} wnTs[0]=1 {{2,1}, {0,4}} wnTs[1]=0.518518519 wnTs[2]=0
-debugShowActiveSpans id=1 (0,2 1,2 4,0 3,1) t=0 (0,2) tEnd=0.333333333 other=2 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 1,2 4,0 3,1) t=0.333333333 (1.44444442,1.51851857) tEnd=0.345547542 other=2 otherT=0.518518519 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 1,2 4,0 3,1) t=0.345547542 (1.50550461,1.48987865) tEnd=0.395188999 other=3 otherT=0.560544414 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 1,2 4,0 3,1) t=0.395188999 (1.75230277,1.37154579) tEnd=1 other=4 otherT=0.123848615 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (3,1 0,2) t=0 (3,1) tEnd=0.428571429 other=1 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (3,1 0,2) t=0.428571429 (1.71428573,1.42857146) tEnd=0.499843081 other=4 otherT=0.142857143 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (3,1 0,2) t=0.499843081 (1.50047076,1.49984312) tEnd=0.518518519 other=3 otherT=0.558102564 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (3,1 0,2) t=0.518518519 (1.44444442,1.51851857) tEnd=1 other=1 otherT=0.333333333 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,4 1,3 2,0 2,1) t=0 (0,4) tEnd=0.333333333 other=4 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,4 1,3 2,0 2,1) t=0.333333333 (0.962962985,2.55555558) tEnd=0.558102564 other=4 otherT=0.518518519 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,4 1,3 2,0 2,1) t=0.558102564 (1.50047076,1.49984312) tEnd=0.560544414 other=2 otherT=0.499843081 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,4 1,3 2,0 2,1) t=0.560544414 (1.50550461,1.48987865) tEnd=1 other=1 otherT=0.345547542 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (2,1 0,4) t=0 (2,1) tEnd=0.123848615 other=3 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (2,1 0,4) t=0.123848615 (1.75230277,1.37154579) tEnd=0.142857143 other=1 otherT=0.395188999 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (2,1 0,4) t=0.142857143 (1.71428573,1.42857146) tEnd=0.518518519 other=2 otherT=0.428571429 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (2,1 0,4) t=0.518518519 (0.962962985,2.55555558) tEnd=1 other=3 otherT=0.333333333 otherIndex=1 windSum=? windValue=1 oppValue=0
-findTop debugShowSort contourWinding=0 oppContourWinding=0 sign=1
-debugShowSort [0] {{0,2}, {1,2}, {4,0}, {3,1}} tStart=1 tEnd=0.395188999 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [1] {{3,1}, {0,2}} tStart=0 tEnd=0.428571429 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-findTop xyE=(3,1) xyS=(1.75230277,1.37154579)
-findTop dxyE=(-3,3) dxyS=(4.93112993,-2.39965272) cross=-7.59443188 bumpsUp=true
-findTop cross bump disagree
-findTop swap
-markWinding id=1 (0,2 1,2 4,0 3,1) t=0.395188999 [3] (1.75230277,1.37154579) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=1 (0,2 1,2 4,0 3,1) t=0.395188999 [3] (1.75230277,1.37154579) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-markWinding id=2 (3,1 0,2) t=0 [0] (3,1) tEnd=0.428571429 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-activeOp op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-findNextOp debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [0] {{0,2}, {1,2}, {4,0}, {3,1}} tStart=0.395188999 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] {{2,1}, {0,4}} tStart=0.123848615 tEnd=0 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=1
-debugShowSort [2] {{0,2}, {1,2}, {4,0}, {3,1}} tStart=0.395188999 tEnd=0.345547542 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [3] {{2,1}, {0,4}} tStart=0.123848615 tEnd=0.142857143 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=1
-findNextOp firstIndex=[0] sign=-1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-markWinding id=4 (2,1 0,4) t=0 [0] (2,1) tEnd=0.123848615 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-markWinding id=3 (0,4 1,3 2,0 2,1) t=0.560544414 [3] (1.50550461,1.48987865) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-activeOp op=diff miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
-markDoneBinary id=1 (0,2 1,2 4,0 3,1) t=0.345547542 [2] (1.50550461,1.48987865) tEnd=0.395188999 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=1
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-markDoneBinary id=4 (2,1 0,4) t=0.123848615 [1] (1.75230277,1.37154579) tEnd=0.142857143 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=4
-markDoneBinary id=1 (0,2 1,2 4,0 3,1) t=0.395188999 [3] (1.75230277,1.37154579) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-findNextOp from:[1] to:[4] start=1 end=0
-bridgeOp current id=1 from=(3,1) to=(1.75230277,1.37154579)
-path.moveTo(3,1);
-path.cubicTo(3.60481095,0.395188987, 2.7464366,0.887767076, 1.75230277,1.37154579);
-findNextOp simple
-markDoneBinary id=4 (2,1 0,4) t=0 [0] (2,1) tEnd=0.123848615 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1
-bridgeOp current id=4 from=(1.75230277,1.37154579) to=(2,1)
-findNextOp debugShowSort contourWinding=-1 oppContourWinding=1 sign=-1
-debugShowSort [1] {{0,4}, {1,3}, {2,0}, {2,1}} tStart=0.560544414 tEnd=1 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [2] {{0,2}, {1,2}, {4,0}, {3,1}} tStart=0.345547542 tEnd=0.333333333 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=1
-debugShowSort [3] {{0,4}, {1,3}, {2,0}, {2,1}} tStart=0.560544414 tEnd=0.558102564 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [0] {{0,2}, {1,2}, {4,0}, {3,1}} tStart=0.345547542 tEnd=0.395188999 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=1
-findNextOp firstIndex=[1] sign=-1
-activeOp op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-markWinding id=1 (0,2 1,2 4,0 3,1) t=0.333333333 [1] (1.44444442,1.51851857) tEnd=0.345547542 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=1
-activeOp op=diff miFrom=0 miTo=0 suFrom=0 suTo=1 result=0
-markDoneBinary id=3 (0,4 1,3 2,0 2,1) t=0.558102564 [2] (1.50047076,1.49984312) tEnd=0.560544414 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-activeOp op=diff miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=3 (0,4 1,3 2,0 2,1) t=0.560544414 [3] (1.50550461,1.48987865) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1
-findNextOp from:[3] to:[1] start=2 end=1
-bridgeOp current id=3 from=(2,1) to=(1.50550461,1.48987865)
-path.lineTo(2,1);
-path.cubicTo(2,0.560544431, 1.80687881,0.893573642, 1.50550461,1.48987865);
-findNextOp debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [1] {{0,2}, {1,2}, {4,0}, {3,1}} tStart=0.333333333 tEnd=0.345547542 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [2] {{3,1}, {0,2}} tStart=0.518518519 tEnd=1 sign=-1 windValue=1 windSum=? 1->2 (max=2) done=0 tiny=0 opp=0
-debugShowSort [3] {{0,2}, {1,2}, {4,0}, {3,1}} tStart=0.333333333 tEnd=0 sign=1 windValue=1 windSum=? 2->1 (max=2) done=0 tiny=0 opp=0
-debugShowSort [0] {{3,1}, {0,2}} tStart=0.518518519 tEnd=0.499843081 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=0
-findNextOp firstIndex=[1] sign=-1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=0 result=0
-markDoneBinary id=2 (3,1 0,2) t=0.518518519 [3] (1.44444442,1.51851857) tEnd=1 newWindSum=2 newOppSum=0 oppSum=? windSum=? windValue=1
-markDoneBinary id=1 (0,2 1,2 4,0 3,1) t=0 [0] (0,2) tEnd=0.333333333 newWindSum=2 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=0 result=0
-activeOp op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-markWinding id=2 (3,1 0,2) t=0.499843081 [2] (1.50047076,1.49984312) tEnd=0.518518519 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=2
-markDoneBinary id=1 (0,2 1,2 4,0 3,1) t=0.333333333 [1] (1.44444442,1.51851857) tEnd=0.345547542 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-findNextOp from:[1] to:[2] start=3 end=2
-bridgeOp current id=1 from=(1.50550461,1.48987865) to=(1.44444442,1.51851857)
-path.cubicTo(1.48515844,1.49946892, 1.46480155,1.50901854, 1.44444442,1.51851857);
-findNextOp debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [2] {{3,1}, {0,2}} tStart=0.499843081 tEnd=0.518518519 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [3] {{0,4}, {1,3}, {2,0}, {2,1}} tStart=0.558102564 tEnd=0.333333333 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=1
-debugShowSort [0] {{3,1}, {0,2}} tStart=0.499843081 tEnd=0.428571429 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] {{0,4}, {1,3}, {2,0}, {2,1}} tStart=0.558102564 tEnd=0.560544414 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=1
-findNextOp firstIndex=[2] sign=-1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-markWinding id=3 (0,4 1,3 2,0 2,1) t=0.333333333 [1] (0.962962985,2.55555558) tEnd=0.558102564 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-activeOp op=diff miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
-markDoneBinary id=2 (3,1 0,2) t=0.428571429 [1] (1.71428573,1.42857146) tEnd=0.499843081 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=2
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-markDoneBinary id=2 (3,1 0,2) t=0.499843081 [2] (1.50047076,1.49984312) tEnd=0.518518519 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-findNextOp from:[2] to:[3] start=2 end=1
-bridgeOp current id=2 from=(1.44444442,1.51851857) to=(1.50047076,1.49984312)
-findNextOp debugShowSort contourWinding=-1 oppContourWinding=1 sign=-1
-debugShowSort [1] {{0,4}, {1,3}, {2,0}, {2,1}} tStart=0.333333333 tEnd=0.558102564 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [2] {{2,1}, {0,4}} tStart=0.518518519 tEnd=1 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [3] {{0,4}, {1,3}, {2,0}, {2,1}} tStart=0.333333333 tEnd=0 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [0] {{2,1}, {0,4}} tStart=0.518518519 tEnd=0.142857143 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-findNextOp firstIndex=[1] sign=-1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-markWinding id=4 (2,1 0,4) t=0.518518519 [3] (0.962962985,2.55555558) tEnd=1 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1
-markWinding id=3 (0,4 1,3 2,0 2,1) t=0 [0] (0,4) tEnd=0.333333333 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-markWinding id=4 (2,1 0,4) t=0.142857143 [2] (1.71428573,1.42857146) tEnd=0.518518519 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=4
-markDoneBinary id=3 (0,4 1,3 2,0 2,1) t=0.333333333 [1] (0.962962985,2.55555558) tEnd=0.558102564 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1
-findNextOp from:[3] to:[4] start=3 end=4
-bridgeOp current id=3 from=(1.50047076,1.49984312) to=(0.962962985,2.55555558)
-path.lineTo(1.50047076,1.49984312);
-path.cubicTo(1.3457123,1.80632472, 1.16275787,2.18094015, 0.962962985,2.55555558);
-findNextOp simple
-markDoneBinary id=4 (2,1 0,4) t=0.518518519 [3] (0.962962985,2.55555558) tEnd=1 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1
-bridgeOp current id=4 from=(0.962962985,2.55555558) to=(0,4)
-findNextOp debugShowSort contourWinding=1 oppContourWinding=1 sign=1
-debugShowSort [3] {{0,4}, {1,3}, {2,0}, {2,1}} tStart=0.333333333 tEnd=0 sign=1 windValue=1 windSum=1 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [0] {{2,1}, {0,4}} tStart=0.518518519 tEnd=0.142857143 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [1] {{0,4}, {1,3}, {2,0}, {2,1}} tStart=0.333333333 tEnd=0.558102564 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [2] {{2,1}, {0,4}} tStart=0.518518519 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=0
-findNextOp firstIndex=[3] sign=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-markDoneBinary id=3 (0,4 1,3 2,0 2,1) t=0 [0] (0,4) tEnd=0.333333333 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1
-findNextOp from:[3] to:[4] start=3 end=2
-bridgeOp current id=3 from=(0,4) to=(0.962962985,2.55555558)
-path.lineTo(0,4);
-path.cubicTo(0.333333343,3.66666675, 0.666666627,3.11111116, 0.962962985,2.55555558);
-findNextOp debugShowSort contourWinding=-1 oppContourWinding=1 sign=-1
-debugShowSort [3] {{2,1}, {0,4}} tStart=0.142857143 tEnd=0.518518519 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [0] {{3,1}, {0,2}} tStart=0.428571429 tEnd=0 sign=1 windValue=1 windSum=1 1->0 (max=1) done=0 tiny=0 opp=1
-debugShowSort [1] {{2,1}, {0,4}} tStart=0.142857143 tEnd=0.123848615 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [2] {{3,1}, {0,2}} tStart=0.428571429 tEnd=0.499843081 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=1
-findNextOp firstIndex=[3] sign=-1
-activeOp op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-activeOp op=diff miFrom=0 miTo=0 suFrom=0 suTo=1 result=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=4 (2,1 0,4) t=0.142857143 [2] (1.71428573,1.42857146) tEnd=0.518518519 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1
-findNextOp from:[4] to:[2] start=1 end=0
-bridgeOp current id=4 from=(0.962962985,2.55555558) to=(1.71428573,1.42857146)
-findNextOp simple
-markDoneBinary id=2 (3,1 0,2) t=0 [0] (3,1) tEnd=0.428571429 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-bridgeOp current id=2 from=(1.71428573,1.42857146) to=(3,1)
-path.lineTo(1.71428573,1.42857146);
-path.lineTo(3,1);
-path.close();
-assemble
-assemble contour start=(3,1) end=(3,1)
-</div>
-
-<div id="cubicOp44d">
- SimplifyNew_Test [cubicOp44d]
-{{0,2}, {3,6}, {4,0}, {3,2}},
-{{3,2}, {0,2}},
-op difference
-{{0,4}, {2,3}, {2,0}, {6,3}},
-{{6,3}, {0,4}},
-debugShowCubicIntersection no self intersect {{0,2}, {3,6}, {4,0}, {3,2}}
-debugShowCubicLineIntersection wtTs[0]=0 {{0,2}, {3,6}, {4,0}, {3,2}} {{0,2}} wtTs[1]=1 {{3,2}} wnTs[0]=1 {{3,2}, {0,2}} wnTs[1]=0
-debugShowCubicIntersection wtTs[0]=0.135342164 {{0,2}, {3,6}, {4,0}, {3,2}} {{1.1081744689414279,3.1192052729330815}} wtTs[1]=0.754165096 {{3.3748959118747366,1.708000079031383}} wtTs[2]=0.93333707 {{3.1733251116708114,1.7013446943452044}} wnTs[0]=0.223477 {{0,4}, {2,3}, {2,0}, {6,3}} wnTs[1]=0.708782366 wnTs[2]=0.67692927
-debugShowCubicLineIntersection no intersect {{0,2}, {3,6}, {4,0}, {3,2}} {{6,3}, {0,4}}
-debugShowCubicLineIntersection wtTs[0]=0.5 {{0,4}, {2,3}, {2,0}, {6,3}} {{2.25,2}} wnTs[0]=0.25 {{3,2}, {0,2}}
-debugShowCubicIntersection no self intersect {{0,4}, {2,3}, {2,0}, {6,3}}
-debugShowCubicLineIntersection wtTs[0]=0 {{0,4}, {2,3}, {2,0}, {6,3}} {{0,4}} wtTs[1]=1 {{6,3}} wnTs[0]=1 {{6,3}, {0,4}} wnTs[1]=0
-debugShowActiveSpans id=1 (0,2 3,6 4,0 3,2) t=0 (0,2) tEnd=0.135342164 other=2 otherT=1 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 3,6 4,0 3,2) t=0.135342164 (1.10817444,3.11920524) tEnd=0.754165096 other=3 otherT=0.223476766 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 3,6 4,0 3,2) t=0.754165096 (3.37489581,1.70800006) tEnd=0.93333707 other=3 otherT=0.708782366 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 3,6 4,0 3,2) t=0.93333707 (3.17332506,1.70134473) tEnd=1 other=3 otherT=0.67692927 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (3,2 0,2) t=0 (3,2) tEnd=0.25 other=1 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (3,2 0,2) t=0.25 (2.25,2) tEnd=1 other=3 otherT=0.5 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,4 2,3 2,0 6,3) t=0 (0,4) tEnd=0.223476766 other=4 otherT=1 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,4 2,3 2,0 6,3) t=0.223476766 (1.10817444,3.11920524) tEnd=0.5 other=1 otherT=0.135342164 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,4 2,3 2,0 6,3) t=0.5 (2.25,2) tEnd=0.67692927 other=2 otherT=0.25 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,4 2,3 2,0 6,3) t=0.67692927 (3.17332506,1.70134473) tEnd=0.708782366 other=1 otherT=0.93333707 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,4 2,3 2,0 6,3) t=0.708782366 (3.37489581,1.70800006) tEnd=1 other=1 otherT=0.754165096 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (6,3 0,4) t=0 (6,3) tEnd=1 other=3 otherT=1 otherIndex=5 windSum=? windValue=1 oppValue=0
-findTop debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [0] {{0,4}, {2,3}, {2,0}, {6,3}} tStart=0.67692927 tEnd=0.708782366 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] {{0,2}, {3,6}, {4,0}, {3,2}} tStart=0.93333707 tEnd=0.754165096 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=1
-debugShowSort [2] {{0,4}, {2,3}, {2,0}, {6,3}} tStart=0.67692927 tEnd=0.5 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [3] {{0,2}, {3,6}, {4,0}, {3,2}} tStart=0.93333707 tEnd=1 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=1
-findTop swap
-markWinding id=3 (0,4 2,3 2,0 6,3) t=0.67692927 [3] (3.17332506,1.70134473) tEnd=0.708782366 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=3 (0,4 2,3 2,0 6,3) t=0.67692927 [3] (3.17332506,1.70134473) tEnd=0.708782366 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-markDoneBinary id=3 (0,4 2,3 2,0 6,3) t=0.67692927 [3] (3.17332506,1.70134473) tEnd=0.708782366 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-findChaseOp debugShowSort contourWinding=? oppContourWinding=? sign=-1
-debugShowSort [0] {{0,2}, {3,6}, {4,0}, {3,2}} tStart=0.754165096 tEnd=0.93333707 sign=-1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=0
-debugShowSort [1] {{0,4}, {2,3}, {2,0}, {6,3}} tStart=0.708782366 tEnd=0.67692927 sign=1 windValue=1 windSum=-1 ?->? (max=?) done=1 tiny=0 opp=1
-debugShowSort [2] {{0,2}, {3,6}, {4,0}, {3,2}} tStart=0.754165096 tEnd=0.135342164 sign=1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=0
-debugShowSort [3] {{0,4}, {2,3}, {2,0}, {6,3}} tStart=0.708782366 tEnd=1 sign=-1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=1
-findChaseOp debugShowSort contourWinding=0 oppContourWinding=0 sign=1
-debugShowSort [1] {{0,4}, {2,3}, {2,0}, {6,3}} tStart=0.708782366 tEnd=0.67692927 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [2] {{0,2}, {3,6}, {4,0}, {3,2}} tStart=0.754165096 tEnd=0.135342164 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=1
-debugShowSort [3] {{0,4}, {2,3}, {2,0}, {6,3}} tStart=0.708782366 tEnd=1 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [0] {{0,2}, {3,6}, {4,0}, {3,2}} tStart=0.754165096 tEnd=0.93333707 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=1
-markWinding id=1 (0,2 3,6 4,0 3,2) t=0.135342164 [1] (1.10817444,3.11920524) tEnd=0.754165096 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1
-markWinding id=3 (0,4 2,3 2,0 6,3) t=0.708782366 [4] (3.37489581,1.70800006) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1
-markWinding id=4 (6,3 0,4) t=0 [0] (6,3) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1
-markWinding id=3 (0,4 2,3 2,0 6,3) t=0 [0] (0,4) tEnd=0.223476766 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1
-markWinding id=1 (0,2 3,6 4,0 3,2) t=0.754165096 [2] (3.37489581,1.70800006) tEnd=0.93333707 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-debugShowActiveSpans id=1 (0,2 3,6 4,0 3,2) t=0 (0,2) tEnd=0.135342164 other=2 otherT=1 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 3,6 4,0 3,2) t=0.135342164 (1.10817444,3.11920524) tEnd=0.754165096 other=3 otherT=0.223476766 otherIndex=1 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 3,6 4,0 3,2) t=0.754165096 (3.37489581,1.70800006) tEnd=0.93333707 other=3 otherT=0.708782366 otherIndex=4 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 3,6 4,0 3,2) t=0.93333707 (3.17332506,1.70134473) tEnd=1 other=3 otherT=0.67692927 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (3,2 0,2) t=0 (3,2) tEnd=0.25 other=1 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (3,2 0,2) t=0.25 (2.25,2) tEnd=1 other=3 otherT=0.5 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,4 2,3 2,0 6,3) t=0 (0,4) tEnd=0.223476766 other=4 otherT=1 otherIndex=1 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,4 2,3 2,0 6,3) t=0.223476766 (1.10817444,3.11920524) tEnd=0.5 other=1 otherT=0.135342164 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,4 2,3 2,0 6,3) t=0.5 (2.25,2) tEnd=0.67692927 other=2 otherT=0.25 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,4 2,3 2,0 6,3) t=0.708782366 (3.37489581,1.70800006) tEnd=1 other=1 otherT=0.754165096 otherIndex=2 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (6,3 0,4) t=0 (6,3) tEnd=1 other=3 otherT=1 otherIndex=5 windSum=-1 windValue=1 oppValue=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=1 (0,2 3,6 4,0 3,2) t=0.135342164 [1] (1.10817444,3.11920524) tEnd=0.754165096 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1
-debugShowActiveSpans id=1 (0,2 3,6 4,0 3,2) t=0 (0,2) tEnd=0.135342164 other=2 otherT=1 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 3,6 4,0 3,2) t=0.754165096 (3.37489581,1.70800006) tEnd=0.93333707 other=3 otherT=0.708782366 otherIndex=4 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 3,6 4,0 3,2) t=0.93333707 (3.17332506,1.70134473) tEnd=1 other=3 otherT=0.67692927 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (3,2 0,2) t=0 (3,2) tEnd=0.25 other=1 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (3,2 0,2) t=0.25 (2.25,2) tEnd=1 other=3 otherT=0.5 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,4 2,3 2,0 6,3) t=0 (0,4) tEnd=0.223476766 other=4 otherT=1 otherIndex=1 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,4 2,3 2,0 6,3) t=0.223476766 (1.10817444,3.11920524) tEnd=0.5 other=1 otherT=0.135342164 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,4 2,3 2,0 6,3) t=0.5 (2.25,2) tEnd=0.67692927 other=2 otherT=0.25 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,4 2,3 2,0 6,3) t=0.708782366 (3.37489581,1.70800006) tEnd=1 other=1 otherT=0.754165096 otherIndex=2 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (6,3 0,4) t=0 (6,3) tEnd=1 other=3 otherT=1 otherIndex=5 windSum=-1 windValue=1 oppValue=0
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-findNextOp simple
-markDoneBinary id=3 (0,4 2,3 2,0 6,3) t=0 [0] (0,4) tEnd=0.223476766 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1
-bridgeOp current id=3 from=(1.10817444,3.11920524) to=(0,4)
-path.moveTo(1.10817444,3.11920524);
-path.cubicTo(0.794023395,3.45316267, 0.446953505,3.77652311, 0,4);
-findNextOp simple
-markDoneBinary id=4 (6,3 0,4) t=0 [0] (6,3) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1
-bridgeOp current id=4 from=(0,4) to=(6,3)
-findNextOp debugShowSort contourWinding=-1 oppContourWinding=-1 sign=-1
-debugShowSort [3] {{0,4}, {2,3}, {2,0}, {6,3}} tStart=0.708782366 tEnd=1 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [0] {{0,2}, {3,6}, {4,0}, {3,2}} tStart=0.754165096 tEnd=0.93333707 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=0 tiny=0 opp=1
-debugShowSort [1] {{0,4}, {2,3}, {2,0}, {6,3}} tStart=0.708782366 tEnd=0.67692927 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [2] {{0,2}, {3,6}, {4,0}, {3,2}} tStart=0.754165096 tEnd=0.135342164 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=1
-findNextOp firstIndex=[3] sign=-1
-activeOp op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-activeOp op=diff miFrom=0 miTo=0 suFrom=0 suTo=1 result=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=3 (0,4 2,3 2,0 6,3) t=0.708782366 [4] (3.37489581,1.70800006) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1
-findNextOp from:[3] to:[1] start=2 end=3
-bridgeOp current id=3 from=(6,3) to=(3.37489581,1.70800006)
-path.lineTo(6,3);
-path.cubicTo(4.83512926,2.12634706, 4.00949001,1.76154041, 3.37489581,1.70800006);
-findNextOp debugShowSort contourWinding=0 oppContourWinding=0 sign=1
-debugShowSort [1] {{0,2}, {3,6}, {4,0}, {3,2}} tStart=0.93333707 tEnd=0.754165096 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [2] {{0,4}, {2,3}, {2,0}, {6,3}} tStart=0.67692927 tEnd=0.5 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=1
-debugShowSort [3] {{0,2}, {3,6}, {4,0}, {3,2}} tStart=0.93333707 tEnd=1 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [0] {{0,4}, {2,3}, {2,0}, {6,3}} tStart=0.67692927 tEnd=0.708782366 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=1
-findNextOp firstIndex=[1] sign=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-markWinding id=3 (0,4 2,3 2,0 6,3) t=0.5 [2] (2.25,2) tEnd=0.67692927 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-activeOp op=diff miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
-markDoneBinary id=1 (0,2 3,6 4,0 3,2) t=0.93333707 [3] (3.17332506,1.70134473) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1
-markDoneBinary id=2 (3,2 0,2) t=0 [0] (3,2) tEnd=0.25 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=2
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-markDoneBinary id=1 (0,2 3,6 4,0 3,2) t=0.754165096 [2] (3.37489581,1.70800006) tEnd=0.93333707 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-findNextOp from:[1] to:[3] start=3 end=2
-bridgeOp current id=1 from=(3.37489581,1.70800006) to=(3.17332506,1.70134473)
-path.cubicTo(3.37191081,1.55650449, 3.30472064,1.51977468, 3.17332506,1.70134473);
-findNextOp debugShowSort contourWinding=-1 oppContourWinding=-1 sign=-1
-debugShowSort [0] {{0,4}, {2,3}, {2,0}, {6,3}} tStart=0.5 tEnd=0.67692927 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [1] {{3,2}, {0,2}} tStart=0.25 tEnd=1 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=1
-debugShowSort [2] {{0,4}, {2,3}, {2,0}, {6,3}} tStart=0.5 tEnd=0.223476766 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [3] {{3,2}, {0,2}} tStart=0.25 tEnd=0 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=1
-findNextOp firstIndex=[0] sign=-1
-activeOp op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-markWinding id=2 (3,2 0,2) t=0.25 [1] (2.25,2) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=1 (0,2 3,6 4,0 3,2) t=0 [0] (0,2) tEnd=0.135342164 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=1
-activeOp op=diff miFrom=0 miTo=0 suFrom=0 suTo=1 result=0
-markDoneBinary id=3 (0,4 2,3 2,0 6,3) t=0.223476766 [1] (1.10817444,3.11920524) tEnd=0.5 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-activeOp op=diff miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=3 (0,4 2,3 2,0 6,3) t=0.5 [2] (2.25,2) tEnd=0.67692927 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1
-findNextOp from:[3] to:[2] start=1 end=2
-bridgeOp current id=3 from=(3.17332506,1.70134473) to=(2.25,2)
-path.cubicTo(2.81209183,1.70874941, 2.51539397,1.82307076, 2.25,2);
-findNextOp simple
-markDoneBinary id=2 (3,2 0,2) t=0.25 [1] (2.25,2) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-bridgeOp current id=2 from=(2.25,2) to=(0,2)
-findNextOp debugShowSort contourWinding=0 oppContourWinding=0 sign=1
-debugShowSort [1] {{0,2}, {3,6}, {4,0}, {3,2}} tStart=0.135342164 tEnd=0 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [2] {{0,4}, {2,3}, {2,0}, {6,3}} tStart=0.223476766 tEnd=0 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=1
-debugShowSort [3] {{0,2}, {3,6}, {4,0}, {3,2}} tStart=0.135342164 tEnd=0.754165096 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [0] {{0,4}, {2,3}, {2,0}, {6,3}} tStart=0.223476766 tEnd=0.5 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=1
-findNextOp firstIndex=[1] sign=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-activeOp op=diff miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-markDoneBinary id=1 (0,2 3,6 4,0 3,2) t=0 [0] (0,2) tEnd=0.135342164 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-findNextOp from:[1] to:[3] start=1 end=0
-bridgeOp current id=1 from=(0,2) to=(1.10817444,3.11920524)
-path.lineTo(0,2);
-path.cubicTo(0.406026483,2.54136872, 0.775417984,2.89956236, 1.10817444,3.11920524);
-path.close();
-assemble
-assemble contour start=(1.10817444,3.11920524) end=(1.10817444,3.11920524)
-</div>
-
-<div id="cubicOp45d">
- SimplifyNew_Test [cubicOp45d]
-{{0,2}, {2,4}, {4,0}, {3,2}},
-{{3,2}, {0,2}},
-op difference
-{{0,4}, {2,3}, {2,0}, {4,2}},
-{{4,2}, {0,4}},
-debugShowCubicIntersection no self intersect {{0,4}, {2,3}, {2,0}, {4,2}}
-debugShowCubicLineIntersection wtTs[0]=0 {{0,4}, {2,3}, {2,0}, {4,2}} {{0,4}} wtTs[1]=1 {{4,2}} wnTs[0]=1 {{4,2}, {0,4}} wnTs[1]=0
-debugShowCubicIntersection wtTs[0]=0.341662805 {{0,4}, {2,3}, {2,0}, {4,2}} {{1.5091099386066631,2.5537951499735922}} wtTs[1]=0.856247521 {{3.2495913270767485,1.4266624658205882}} wtTs[2]=0.859816875 {{3.2657899721435943,1.4343874043112959}} wnTs[0]=0.260341 {{0,2}, {2,4}, {4,0}, {3,2}} wnTs[1]=0.768795564 wnTs[2]=0.821660252
-debugShowCubicLineIntersection wtTs[0]=0.467845317 {{0,4}, {2,3}, {2,0}, {4,2}} {{1.9034029684653309,1.9999999999999998}} wnTs[0]=0.365532 {{3,2}, {0,2}}
-debugShowCubicLineIntersection no intersect {{0,2}, {2,4}, {4,0}, {3,2}} {{4,2}, {0,4}}
-debugShowLineIntersection no intersect {{4,2}, {0,4}} {{3,2}, {0,2}}
-debugShowCubicIntersection no self intersect {{0,2}, {2,4}, {4,0}, {3,2}}
-debugShowCubicLineIntersection wtTs[0]=0 {{0,2}, {2,4}, {4,0}, {3,2}} {{0,2}} wtTs[1]=0.5 {{2.625,2}} wtTs[2]=1 {{3,2}} wnTs[0]=1 {{3,2}, {0,2}} wnTs[1]=0.125 wnTs[2]=0
-debugShowActiveSpans id=3 (0,4 2,3 2,0 4,2) t=0 (0,4) tEnd=0.341662805 other=4 otherT=1 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,4 2,3 2,0 4,2) t=0.341662805 (1.50910997,2.5537951) tEnd=0.467845317 other=1 otherT=0.260340927 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,4 2,3 2,0 4,2) t=0.467845317 (1.90340292,2) tEnd=0.856247521 other=2 otherT=0.365532344 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,4 2,3 2,0 4,2) t=0.856247521 (3.24959135,1.42666245) tEnd=0.859816875 other=1 otherT=0.768795564 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,4 2,3 2,0 4,2) t=0.859816875 (3.26578999,1.43438745) tEnd=1 other=1 otherT=0.821660252 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (4,2 0,4) t=0 (4,2) tEnd=1 other=3 otherT=1 otherIndex=5 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 2,4 4,0 3,2) t=0 (0,2) tEnd=0.260340927 other=2 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 2,4 4,0 3,2) t=0.260340927 (1.50910997,2.5537951) tEnd=0.5 other=3 otherT=0.341662805 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 2,4 4,0 3,2) t=0.5 (2.625,2) tEnd=0.768795564 other=2 otherT=0.125 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 2,4 4,0 3,2) t=0.768795564 (3.24959135,1.42666245) tEnd=0.821660252 other=3 otherT=0.856247521 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 2,4 4,0 3,2) t=0.821660252 (3.26578999,1.43438745) tEnd=1 other=3 otherT=0.859816875 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (3,2 0,2) t=0 (3,2) tEnd=0.125 other=1 otherT=1 otherIndex=5 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (3,2 0,2) t=0.125 (2.625,2) tEnd=0.365532344 other=1 otherT=0.5 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (3,2 0,2) t=0.365532344 (1.90340292,2) tEnd=1 other=3 otherT=0.467845317 otherIndex=2 windSum=? windValue=1 oppValue=0
-findTop debugShowSort contourWinding=0 oppContourWinding=0 sign=1
-debugShowSort [1] {{0,4}, {2,3}, {2,0}, {4,2}} tStart=0.859816875 tEnd=0.856247521 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [2] {{0,2}, {2,4}, {4,0}, {3,2}} tStart=0.821660252 tEnd=1 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=1
-debugShowSort [3] {{0,4}, {2,3}, {2,0}, {4,2}} tStart=0.859816875 tEnd=1 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [0] {{0,2}, {2,4}, {4,0}, {3,2}} tStart=0.821660252 tEnd=0.768795564 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=1
-markWinding id=3 (0,4 2,3 2,0 4,2) t=0.856247521 [3] (3.24959135,1.42666245) tEnd=0.859816875 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=3 (0,4 2,3 2,0 4,2) t=0.856247521 [3] (3.24959135,1.42666245) tEnd=0.859816875 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-markDoneBinary id=3 (0,4 2,3 2,0 4,2) t=0.856247521 [3] (3.24959135,1.42666245) tEnd=0.859816875 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-findChaseOp debugShowSort contourWinding=? oppContourWinding=? sign=1
-debugShowSort [0] {{0,2}, {2,4}, {4,0}, {3,2}} tStart=0.821660252 tEnd=0.768795564 sign=1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=0
-debugShowSort [1] {{0,4}, {2,3}, {2,0}, {4,2}} tStart=0.859816875 tEnd=0.856247521 sign=1 windValue=1 windSum=-1 ?->? (max=?) done=1 tiny=0 opp=1
-debugShowSort [2] {{0,2}, {2,4}, {4,0}, {3,2}} tStart=0.821660252 tEnd=1 sign=-1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=0
-debugShowSort [3] {{0,4}, {2,3}, {2,0}, {4,2}} tStart=0.859816875 tEnd=1 sign=-1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=1
-findChaseOp debugShowSort contourWinding=0 oppContourWinding=0 sign=1
-debugShowSort [1] {{0,4}, {2,3}, {2,0}, {4,2}} tStart=0.859816875 tEnd=0.856247521 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [2] {{0,2}, {2,4}, {4,0}, {3,2}} tStart=0.821660252 tEnd=1 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=1
-debugShowSort [3] {{0,4}, {2,3}, {2,0}, {4,2}} tStart=0.859816875 tEnd=1 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [0] {{0,2}, {2,4}, {4,0}, {3,2}} tStart=0.821660252 tEnd=0.768795564 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=1
-markWinding id=1 (0,2 2,4 4,0 3,2) t=0.821660252 [4] (3.26578999,1.43438745) tEnd=1 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1
-markWinding id=2 (3,2 0,2) t=0 [0] (3,2) tEnd=0.125 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1
-markWinding id=3 (0,4 2,3 2,0 4,2) t=0.859816875 [4] (3.26578999,1.43438745) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-markWinding id=4 (4,2 0,4) t=0 [0] (4,2) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-markWinding id=3 (0,4 2,3 2,0 4,2) t=0 [0] (0,4) tEnd=0.341662805 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-markWinding id=1 (0,2 2,4 4,0 3,2) t=0.768795564 [3] (3.24959135,1.42666245) tEnd=0.821660252 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-debugShowActiveSpans id=3 (0,4 2,3 2,0 4,2) t=0 (0,4) tEnd=0.341662805 other=4 otherT=1 otherIndex=1 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,4 2,3 2,0 4,2) t=0.341662805 (1.50910997,2.5537951) tEnd=0.467845317 other=1 otherT=0.260340927 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,4 2,3 2,0 4,2) t=0.467845317 (1.90340292,2) tEnd=0.856247521 other=2 otherT=0.365532344 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,4 2,3 2,0 4,2) t=0.859816875 (3.26578999,1.43438745) tEnd=1 other=1 otherT=0.821660252 otherIndex=4 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (4,2 0,4) t=0 (4,2) tEnd=1 other=3 otherT=1 otherIndex=5 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 2,4 4,0 3,2) t=0 (0,2) tEnd=0.260340927 other=2 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 2,4 4,0 3,2) t=0.260340927 (1.50910997,2.5537951) tEnd=0.5 other=3 otherT=0.341662805 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 2,4 4,0 3,2) t=0.5 (2.625,2) tEnd=0.768795564 other=2 otherT=0.125 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 2,4 4,0 3,2) t=0.768795564 (3.24959135,1.42666245) tEnd=0.821660252 other=3 otherT=0.856247521 otherIndex=3 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 2,4 4,0 3,2) t=0.821660252 (3.26578999,1.43438745) tEnd=1 other=3 otherT=0.859816875 otherIndex=4 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (3,2 0,2) t=0 (3,2) tEnd=0.125 other=1 otherT=1 otherIndex=5 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (3,2 0,2) t=0.125 (2.625,2) tEnd=0.365532344 other=1 otherT=0.5 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (3,2 0,2) t=0.365532344 (1.90340292,2) tEnd=1 other=3 otherT=0.467845317 otherIndex=2 windSum=? windValue=1 oppValue=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=1 (0,2 2,4 4,0 3,2) t=0.821660252 [4] (3.26578999,1.43438745) tEnd=1 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1
-markDoneBinary id=2 (3,2 0,2) t=0 [0] (3,2) tEnd=0.125 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1
-findChaseOp debugShowSort contourWinding=? oppContourWinding=? sign=-1
-debugShowSort [0] {{0,2}, {2,4}, {4,0}, {3,2}} tStart=0.5 tEnd=0.768795564 sign=-1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=0
-debugShowSort [1] {{3,2}, {0,2}} tStart=0.125 tEnd=0.365532344 sign=-1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=0
-debugShowSort [2] {{0,2}, {2,4}, {4,0}, {3,2}} tStart=0.5 tEnd=0.260340927 sign=1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=0
-debugShowSort [3] {{3,2}, {0,2}} tStart=0.125 tEnd=0 sign=1 windValue=1 windSum=1 ?->? (max=?) done=1 tiny=0 opp=0
-findChaseOp debugShowSort contourWinding=1 oppContourWinding=-1 sign=1
-debugShowSort [3] {{3,2}, {0,2}} tStart=0.125 tEnd=0 sign=1 windValue=1 windSum=1 1->0 (max=1) done=1 tiny=0 opp=0
-debugShowSort [0] {{0,2}, {2,4}, {4,0}, {3,2}} tStart=0.5 tEnd=0.768795564 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] {{3,2}, {0,2}} tStart=0.125 tEnd=0.365532344 sign=-1 windValue=1 windSum=? 1->2 (max=2) done=0 tiny=0 opp=0
-debugShowSort [2] {{0,2}, {2,4}, {4,0}, {3,2}} tStart=0.5 tEnd=0.260340927 sign=1 windValue=1 windSum=? 2->1 (max=2) done=0 tiny=0 opp=0
-markWinding id=1 (0,2 2,4 4,0 3,2) t=0.5 [2] (2.625,2) tEnd=0.768795564 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1
-markWinding id=2 (3,2 0,2) t=0.125 [1] (2.625,2) tEnd=0.365532344 newWindSum=2 newOppSum=-1 oppSum=? windSum=? windValue=1
-markWinding id=1 (0,2 2,4 4,0 3,2) t=0.260340927 [1] (1.50910997,2.5537951) tEnd=0.5 newWindSum=2 newOppSum=-1 oppSum=? windSum=? windValue=1
-debugShowActiveSpans id=3 (0,4 2,3 2,0 4,2) t=0 (0,4) tEnd=0.341662805 other=4 otherT=1 otherIndex=1 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,4 2,3 2,0 4,2) t=0.341662805 (1.50910997,2.5537951) tEnd=0.467845317 other=1 otherT=0.260340927 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,4 2,3 2,0 4,2) t=0.467845317 (1.90340292,2) tEnd=0.856247521 other=2 otherT=0.365532344 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,4 2,3 2,0 4,2) t=0.859816875 (3.26578999,1.43438745) tEnd=1 other=1 otherT=0.821660252 otherIndex=4 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (4,2 0,4) t=0 (4,2) tEnd=1 other=3 otherT=1 otherIndex=5 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 2,4 4,0 3,2) t=0 (0,2) tEnd=0.260340927 other=2 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 2,4 4,0 3,2) t=0.260340927 (1.50910997,2.5537951) tEnd=0.5 other=3 otherT=0.341662805 otherIndex=1 windSum=2 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 2,4 4,0 3,2) t=0.5 (2.625,2) tEnd=0.768795564 other=2 otherT=0.125 otherIndex=1 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 2,4 4,0 3,2) t=0.768795564 (3.24959135,1.42666245) tEnd=0.821660252 other=3 otherT=0.856247521 otherIndex=3 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (3,2 0,2) t=0.125 (2.625,2) tEnd=0.365532344 other=1 otherT=0.5 otherIndex=2 windSum=2 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (3,2 0,2) t=0.365532344 (1.90340292,2) tEnd=1 other=3 otherT=0.467845317 otherIndex=2 windSum=? windValue=1 oppValue=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=1 (0,2 2,4 4,0 3,2) t=0.5 [2] (2.625,2) tEnd=0.768795564 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1
-debugShowActiveSpans id=3 (0,4 2,3 2,0 4,2) t=0 (0,4) tEnd=0.341662805 other=4 otherT=1 otherIndex=1 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,4 2,3 2,0 4,2) t=0.341662805 (1.50910997,2.5537951) tEnd=0.467845317 other=1 otherT=0.260340927 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,4 2,3 2,0 4,2) t=0.467845317 (1.90340292,2) tEnd=0.856247521 other=2 otherT=0.365532344 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,4 2,3 2,0 4,2) t=0.859816875 (3.26578999,1.43438745) tEnd=1 other=1 otherT=0.821660252 otherIndex=4 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (4,2 0,4) t=0 (4,2) tEnd=1 other=3 otherT=1 otherIndex=5 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 2,4 4,0 3,2) t=0 (0,2) tEnd=0.260340927 other=2 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 2,4 4,0 3,2) t=0.260340927 (1.50910997,2.5537951) tEnd=0.5 other=3 otherT=0.341662805 otherIndex=1 windSum=2 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 2,4 4,0 3,2) t=0.768795564 (3.24959135,1.42666245) tEnd=0.821660252 other=3 otherT=0.856247521 otherIndex=3 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (3,2 0,2) t=0.125 (2.625,2) tEnd=0.365532344 other=1 otherT=0.5 otherIndex=2 windSum=2 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (3,2 0,2) t=0.365532344 (1.90340292,2) tEnd=1 other=3 otherT=0.467845317 otherIndex=2 windSum=? windValue=1 oppValue=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-findNextOp debugShowSort contourWinding=1 oppContourWinding=0 sign=1
-debugShowSort [0] {{0,2}, {2,4}, {4,0}, {3,2}} tStart=0.821660252 tEnd=0.768795564 sign=1 windValue=1 windSum=1 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] {{0,4}, {2,3}, {2,0}, {4,2}} tStart=0.859816875 tEnd=0.856247521 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=1
-debugShowSort [2] {{0,2}, {2,4}, {4,0}, {3,2}} tStart=0.821660252 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=0
-debugShowSort [3] {{0,4}, {2,3}, {2,0}, {4,2}} tStart=0.859816875 tEnd=1 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=0 tiny=0 opp=1
-findNextOp firstIndex=[0] sign=1
-activeOp op=diff miFrom=0 miTo=0 suFrom=0 suTo=1 result=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
-markDoneBinary id=1 (0,2 2,4 4,0 3,2) t=0.768795564 [3] (3.24959135,1.42666245) tEnd=0.821660252 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-findNextOp from:[1] to:[3] start=4 end=5
-bridgeOp current id=1 from=(3.24959135,1.42666245) to=(3.26578999,1.43438745)
-path.moveTo(3.24959135,1.42666245);
-path.cubicTo(3.26158428,1.4196322, 3.26713157,1.42161608, 3.26578999,1.43438745);
-findNextOp simple
-markDoneBinary id=3 (0,4 2,3 2,0 4,2) t=0.859816875 [4] (3.26578999,1.43438745) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1
-bridgeOp current id=3 from=(3.26578999,1.43438745) to=(4,2)
-path.cubicTo(3.47857022,1.53752398, 3.71963382,1.71963382, 4,2);
-findNextOp simple
-markDoneBinary id=4 (4,2 0,4) t=0 [0] (4,2) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1
-bridgeOp current id=4 from=(4,2) to=(0,4)
-findNextOp debugShowSort contourWinding=0 oppContourWinding=1 sign=1
-debugShowSort [3] {{0,4}, {2,3}, {2,0}, {4,2}} tStart=0.341662805 tEnd=0 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [0] {{0,2}, {2,4}, {4,0}, {3,2}} tStart=0.260340927 tEnd=0.5 sign=-1 windValue=1 windSum=2 1->2 (max=2) done=0 tiny=0 opp=1
-debugShowSort [1] {{0,4}, {2,3}, {2,0}, {4,2}} tStart=0.341662805 tEnd=0.467845317 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [2] {{0,2}, {2,4}, {4,0}, {3,2}} tStart=0.260340927 tEnd=0 sign=1 windValue=1 windSum=? 2->1 (max=2) done=0 tiny=0 opp=1
-findNextOp firstIndex=[3] sign=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=1 result=0
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
-markWinding id=3 (0,4 2,3 2,0 4,2) t=0.341662805 [1] (1.50910997,2.5537951) tEnd=0.467845317 newWindSum=-1 newOppSum=2 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=0 result=0
-markDoneBinary id=1 (0,2 2,4 4,0 3,2) t=0 [0] (0,2) tEnd=0.260340927 newWindSum=2 newOppSum=0 oppSum=? windSum=? windValue=1
-markDoneBinary id=2 (3,2 0,2) t=0.365532344 [2] (1.90340292,2) tEnd=1 newWindSum=2 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=2
-markDoneBinary id=3 (0,4 2,3 2,0 4,2) t=0 [0] (0,4) tEnd=0.341662805 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1
-findNextOp from:[3] to:[3] start=1 end=2
-bridgeOp current id=3 from=(0,4) to=(1.50910997,2.5537951)
-path.lineTo(0,4);
-path.cubicTo(0.683325648,3.65833712, 1.13318419,3.08320737, 1.50910997,2.5537951);
-findNextOp debugShowSort contourWinding=0 oppContourWinding=2 sign=1
-debugShowSort [2] {{0,4}, {2,3}, {2,0}, {4,2}} tStart=0.467845317 tEnd=0.341662805 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [3] {{3,2}, {0,2}} tStart=0.365532344 tEnd=0.125 sign=1 windValue=1 windSum=2 2->1 (max=2) done=0 tiny=0 opp=1
-debugShowSort [0] {{0,4}, {2,3}, {2,0}, {4,2}} tStart=0.467845317 tEnd=0.856247521 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [1] {{3,2}, {0,2}} tStart=0.365532344 tEnd=1 sign=-1 windValue=1 windSum=2 1->2 (max=2) done=1 tiny=0 opp=1
-findNextOp firstIndex=[2] sign=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=1 result=0
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
-markWinding id=3 (0,4 2,3 2,0 4,2) t=0.467845317 [2] (1.90340292,2) tEnd=0.856247521 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=0 result=0
-markDoneBinary id=3 (0,4 2,3 2,0 4,2) t=0.341662805 [1] (1.50910997,2.5537951) tEnd=0.467845317 newWindSum=-1 newOppSum=2 oppSum=2 windSum=-1 windValue=1
-findNextOp from:[3] to:[3] start=2 end=3
-bridgeOp current id=3 from=(1.50910997,2.5537951) to=(1.90340292,2)
-path.cubicTo(1.64794636,2.35827327, 1.77669871,2.16898704, 1.90340292,2);
-findNextOp debugShowSort contourWinding=0 oppContourWinding=1 sign=1
-debugShowSort [1] {{0,4}, {2,3}, {2,0}, {4,2}} tStart=0.856247521 tEnd=0.467845317 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [2] {{0,2}, {2,4}, {4,0}, {3,2}} tStart=0.768795564 tEnd=0.5 sign=1 windValue=1 windSum=1 1->0 (max=1) done=1 tiny=0 opp=1
-debugShowSort [3] {{0,4}, {2,3}, {2,0}, {4,2}} tStart=0.856247521 tEnd=0.859816875 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [0] {{0,2}, {2,4}, {4,0}, {3,2}} tStart=0.768795564 tEnd=0.821660252 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=1
-findNextOp firstIndex=[1] sign=1
-activeOp op=diff miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-markDoneBinary id=3 (0,4 2,3 2,0 4,2) t=0.467845317 [2] (1.90340292,2) tEnd=0.856247521 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1
-findNextOp from:[3] to:[1] start=3 end=4
-bridgeOp current id=3 from=(1.90340292,2) to=(3.24959135,1.42666245)
-path.cubicTo(2.29341149,1.47984147, 2.66401696,1.15201211, 3.24959135,1.42666245);
-path.close();
-debugShowActiveSpans id=1 (0,2 2,4 4,0 3,2) t=0.260340927 (1.50910997,2.5537951) tEnd=0.5 other=3 otherT=0.341662805 otherIndex=1 windSum=2 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (3,2 0,2) t=0.125 (2.625,2) tEnd=0.365532344 other=1 otherT=0.5 otherIndex=2 windSum=2 windValue=1 oppValue=0
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=2 (3,2 0,2) t=0.125 [1] (2.625,2) tEnd=0.365532344 newWindSum=2 newOppSum=-1 oppSum=-1 windSum=2 windValue=1
-debugShowActiveSpans id=1 (0,2 2,4 4,0 3,2) t=0.260340927 (1.50910997,2.5537951) tEnd=0.5 other=3 otherT=0.341662805 otherIndex=1 windSum=2 windValue=1 oppValue=0
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=1 (0,2 2,4 4,0 3,2) t=0.260340927 [1] (1.50910997,2.5537951) tEnd=0.5 newWindSum=2 newOppSum=-1 oppSum=-1 windSum=2 windValue=1
-</div>
-
-<div id="cubicOp46d">
- SimplifyNew_Test [cubicOp46d]
-{{0,2}, {3,5}, {5,0}, {4,2}},
-{{4,2}, {0,2}},
-op difference
-{{0,5}, {2,4}, {2,0}, {5,3}},
-{{5,3}, {0,5}},
-debugShowCubicIntersection no self intersect {{0,2}, {3,5}, {5,0}, {4,2}}
-debugShowCubicLineIntersection wtTs[0]=0 {{0,2}, {3,5}, {5,0}, {4,2}} {{0,2}} wtTs[1]=0.6 {{3.887999999999999,2.0000000000000013}} wtTs[2]=1 {{4,2}} wnTs[0]=1 {{4,2}, {0,2}} wnTs[1]=0.028 wnTs[2]=0
-debugShowCubicIntersection wtTs[0]=0.215060475 {{0,2}, {3,5}, {5,0}, {4,2}} {{1.7768977226209808,2.9747215410507057}} wtTs[1]=0.578517386 {{3.8153702411617676,2.0785732044555085}} wnTs[0]=0.404694 {{0,5}, {2,4}, {2,0}, {5,3}} wnTs[1]=0.846938928
-debugShowCubicLineIntersection wtTs[0]=0.64696132 {{0,5}, {2,4}, {2,0}, {5,3}} {{2.7243714728959709,2}} wtTs[1]=0.819132784 {{3.6370281018311013,1.9999999999999996}} wnTs[0]=0.318907 {{4,2}, {0,2}} wnTs[1]=0.0907429745
-debugShowCubicIntersection no self intersect {{0,5}, {2,4}, {2,0}, {5,3}}
-debugShowCubicLineIntersection wtTs[0]=0 {{0,5}, {2,4}, {2,0}, {5,3}} {{0,5}} wtTs[1]=1 {{5,3}} wnTs[0]=1 {{5,3}, {0,5}} wnTs[1]=0
-debugShowActiveSpans id=1 (0,2 3,5 5,0 4,2) t=0 (0,2) tEnd=0.215060475 other=2 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 3,5 5,0 4,2) t=0.215060475 (1.77689767,2.97472143) tEnd=0.578517386 other=3 otherT=0.404693629 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 3,5 5,0 4,2) t=0.578517386 (3.81537032,2.07857323) tEnd=0.6 other=3 otherT=0.846938928 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 3,5 5,0 4,2) t=0.6 (3.88800001,2) tEnd=1 other=2 otherT=0.028 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,2 0,2) t=0 (4,2) tEnd=0.028 other=1 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,2 0,2) t=0.028 (3.88800001,2) tEnd=0.0907429745 other=1 otherT=0.6 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,2 0,2) t=0.0907429745 (3.63702822,2) tEnd=0.318907132 other=3 otherT=0.819132784 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,2 0,2) t=0.318907132 (2.72437143,2) tEnd=1 other=3 otherT=0.64696132 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,5 2,4 2,0 5,3) t=0 (0,5) tEnd=0.404693629 other=4 otherT=1 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,5 2,4 2,0 5,3) t=0.404693629 (1.77689767,2.97472143) tEnd=0.64696132 other=1 otherT=0.215060475 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,5 2,4 2,0 5,3) t=0.64696132 (2.72437143,2) tEnd=0.819132784 other=2 otherT=0.318907132 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,5 2,4 2,0 5,3) t=0.819132784 (3.63702822,2) tEnd=0.846938928 other=2 otherT=0.0907429745 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,5 2,4 2,0 5,3) t=0.846938928 (3.81537032,2.07857323) tEnd=1 other=1 otherT=0.578517386 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (5,3 0,5) t=0 (5,3) tEnd=1 other=3 otherT=1 otherIndex=5 windSum=? windValue=1 oppValue=0
-findTop debugShowSort contourWinding=0 oppContourWinding=0 sign=1
-debugShowSort [0] {{0,2}, {3,5}, {5,0}, {4,2}} tStart=1 tEnd=0.6 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [1] {{4,2}, {0,2}} tStart=0 tEnd=0.028 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-findTop swap
-markWinding id=1 (0,2 3,5 5,0 4,2) t=0.6 [3] (3.88800001,2) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=1 (0,2 3,5 5,0 4,2) t=0.6 [3] (3.88800001,2) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-markWinding id=2 (4,2 0,2) t=0 [0] (4,2) tEnd=0.028 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-activeOp op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-findNextOp debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [0] {{0,2}, {3,5}, {5,0}, {4,2}} tStart=0.6 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] {{4,2}, {0,2}} tStart=0.028 tEnd=0.0907429745 sign=-1 windValue=1 windSum=? 1->2 (max=2) done=0 tiny=0 opp=0
-debugShowSort [2] {{0,2}, {3,5}, {5,0}, {4,2}} tStart=0.6 tEnd=0.578517386 sign=1 windValue=1 windSum=? 2->1 (max=2) done=0 tiny=0 opp=0
-debugShowSort [3] {{4,2}, {0,2}} tStart=0.028 tEnd=0 sign=1 windValue=1 windSum=1 1->0 (max=1) done=0 tiny=0 opp=0
-findNextOp firstIndex=[0] sign=-1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=0 result=0
-markDoneBinary id=2 (4,2 0,2) t=0.028 [1] (3.88800001,2) tEnd=0.0907429745 newWindSum=2 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=2
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=0 result=0
-markDoneBinary id=1 (0,2 3,5 5,0 4,2) t=0.578517386 [2] (3.81537032,2.07857323) tEnd=0.6 newWindSum=2 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=1
-activeOp op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-markDoneBinary id=1 (0,2 3,5 5,0 4,2) t=0.6 [3] (3.88800001,2) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-findNextOp from:[1] to:[2] start=1 end=0
-bridgeOp current id=1 from=(4,2) to=(3.88800001,2)
-path.moveTo(4,2);
-path.cubicTo(4.4000001,1.20000005, 4.32000017,1.51999998, 3.88800001,2);
-findNextOp simple
-markDoneBinary id=2 (4,2 0,2) t=0 [0] (4,2) tEnd=0.028 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-bridgeOp current id=2 from=(3.88800001,2) to=(4,2)
-path.lineTo(4,2);
-path.close();
-findChaseOp debugShowSort contourWinding=1 oppContourWinding=0 sign=-1
-debugShowSort [0] {{0,2}, {3,5}, {5,0}, {4,2}} tStart=0.578517386 tEnd=0.6 sign=-1 windValue=1 windSum=2 1->2 (max=2) done=1 tiny=0 opp=0
-debugShowSort [1] {{0,5}, {2,4}, {2,0}, {5,3}} tStart=0.846938928 tEnd=0.819132784 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=1
-debugShowSort [2] {{0,2}, {3,5}, {5,0}, {4,2}} tStart=0.578517386 tEnd=0.215060475 sign=1 windValue=1 windSum=? 2->1 (max=2) done=0 tiny=0 opp=0
-debugShowSort [3] {{0,5}, {2,4}, {2,0}, {5,3}} tStart=0.846938928 tEnd=1 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=1
-findChaseOp debugShowSort contourWinding=1 oppContourWinding=0 sign=-1
-debugShowSort [0] {{0,2}, {3,5}, {5,0}, {4,2}} tStart=0.578517386 tEnd=0.6 sign=-1 windValue=1 windSum=2 1->2 (max=2) done=1 tiny=0 opp=0
-debugShowSort [1] {{0,5}, {2,4}, {2,0}, {5,3}} tStart=0.846938928 tEnd=0.819132784 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=1
-debugShowSort [2] {{0,2}, {3,5}, {5,0}, {4,2}} tStart=0.578517386 tEnd=0.215060475 sign=1 windValue=1 windSum=? 2->1 (max=2) done=0 tiny=0 opp=0
-debugShowSort [3] {{0,5}, {2,4}, {2,0}, {5,3}} tStart=0.846938928 tEnd=1 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=1
-markWinding id=3 (0,5 2,4 2,0 5,3) t=0.819132784 [3] (3.63702822,2) tEnd=0.846938928 newWindSum=-1 newOppSum=2 oppSum=? windSum=? windValue=1
-markWinding id=1 (0,2 3,5 5,0 4,2) t=0.215060475 [1] (1.77689767,2.97472143) tEnd=0.578517386 newWindSum=2 newOppSum=-1 oppSum=? windSum=? windValue=1
-markWinding id=3 (0,5 2,4 2,0 5,3) t=0.846938928 [4] (3.81537032,2.07857323) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-markWinding id=4 (5,3 0,5) t=0 [0] (5,3) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-markWinding id=3 (0,5 2,4 2,0 5,3) t=0 [0] (0,5) tEnd=0.404693629 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-debugShowActiveSpans id=1 (0,2 3,5 5,0 4,2) t=0 (0,2) tEnd=0.215060475 other=2 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 3,5 5,0 4,2) t=0.215060475 (1.77689767,2.97472143) tEnd=0.578517386 other=3 otherT=0.404693629 otherIndex=1 windSum=2 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,2 0,2) t=0.0907429745 (3.63702822,2) tEnd=0.318907132 other=3 otherT=0.819132784 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,2 0,2) t=0.318907132 (2.72437143,2) tEnd=1 other=3 otherT=0.64696132 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,5 2,4 2,0 5,3) t=0 (0,5) tEnd=0.404693629 other=4 otherT=1 otherIndex=1 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,5 2,4 2,0 5,3) t=0.404693629 (1.77689767,2.97472143) tEnd=0.64696132 other=1 otherT=0.215060475 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,5 2,4 2,0 5,3) t=0.64696132 (2.72437143,2) tEnd=0.819132784 other=2 otherT=0.318907132 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,5 2,4 2,0 5,3) t=0.819132784 (3.63702822,2) tEnd=0.846938928 other=2 otherT=0.0907429745 otherIndex=2 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,5 2,4 2,0 5,3) t=0.846938928 (3.81537032,2.07857323) tEnd=1 other=1 otherT=0.578517386 otherIndex=2 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (5,3 0,5) t=0 (5,3) tEnd=1 other=3 otherT=1 otherIndex=5 windSum=-1 windValue=1 oppValue=0
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-findNextOp debugShowSort contourWinding=-1 oppContourWinding=2 sign=-1
-debugShowSort [2] {{0,5}, {2,4}, {2,0}, {5,3}} tStart=0.819132784 tEnd=0.846938928 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [3] {{4,2}, {0,2}} tStart=0.0907429745 tEnd=0.028 sign=1 windValue=1 windSum=2 2->1 (max=2) done=1 tiny=0 opp=1
-debugShowSort [0] {{0,5}, {2,4}, {2,0}, {5,3}} tStart=0.819132784 tEnd=0.64696132 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [1] {{4,2}, {0,2}} tStart=0.0907429745 tEnd=0.318907132 sign=-1 windValue=1 windSum=? 1->2 (max=2) done=0 tiny=0 opp=1
-findNextOp firstIndex=[2] sign=-1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=0 result=0
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-markWinding id=3 (0,5 2,4 2,0 5,3) t=0.64696132 [2] (2.72437143,2) tEnd=0.819132784 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=2 (4,2 0,2) t=0.0907429745 [2] (3.63702822,2) tEnd=0.318907132 newWindSum=2 newOppSum=-1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=2
-markDoneBinary id=3 (0,5 2,4 2,0 5,3) t=0.819132784 [3] (3.63702822,2) tEnd=0.846938928 newWindSum=-1 newOppSum=2 oppSum=2 windSum=-1 windValue=1
-findNextOp from:[3] to:[3] start=3 end=2
-bridgeOp current id=3 from=(3.81537032,2.07857323) to=(3.63702822,2)
-path.moveTo(3.81537032,2.07857323);
-path.cubicTo(3.75423074,2.04822493, 3.69481921,2.02210546, 3.63702822,2);
-findNextOp debugShowSort contourWinding=-1 oppContourWinding=1 sign=-1
-debugShowSort [0] {{0,5}, {2,4}, {2,0}, {5,3}} tStart=0.64696132 tEnd=0.819132784 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [1] {{4,2}, {0,2}} tStart=0.318907132 tEnd=1 sign=-1 windValue=1 windSum=? 1->2 (max=2) done=0 tiny=0 opp=1
-debugShowSort [2] {{0,5}, {2,4}, {2,0}, {5,3}} tStart=0.64696132 tEnd=0.404693629 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [3] {{4,2}, {0,2}} tStart=0.318907132 tEnd=0.0907429745 sign=1 windValue=1 windSum=2 2->1 (max=2) done=1 tiny=0 opp=1
-findNextOp firstIndex=[0] sign=-1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=0 result=0
-markDoneBinary id=2 (4,2 0,2) t=0.318907132 [3] (2.72437143,2) tEnd=1 newWindSum=2 newOppSum=0 oppSum=? windSum=? windValue=1
-markDoneBinary id=1 (0,2 3,5 5,0 4,2) t=0 [0] (0,2) tEnd=0.215060475 newWindSum=2 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-markWinding id=3 (0,5 2,4 2,0 5,3) t=0.404693629 [1] (1.77689767,2.97472143) tEnd=0.64696132 newWindSum=-1 newOppSum=2 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=3 (0,5 2,4 2,0 5,3) t=0.64696132 [2] (2.72437143,2) tEnd=0.819132784 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1
-findNextOp from:[3] to:[3] start=2 end=1
-bridgeOp current id=3 from=(3.63702822,2) to=(2.72437143,2)
-path.cubicTo(3.2791934,1.86312568, 2.98348093,1.88013792, 2.72437143,2);
-findNextOp debugShowSort contourWinding=-1 oppContourWinding=2 sign=-1
-debugShowSort [0] {{0,5}, {2,4}, {2,0}, {5,3}} tStart=0.404693629 tEnd=0.64696132 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [1] {{0,2}, {3,5}, {5,0}, {4,2}} tStart=0.215060475 tEnd=0 sign=1 windValue=1 windSum=2 2->1 (max=2) done=1 tiny=0 opp=1
-debugShowSort [2] {{0,5}, {2,4}, {2,0}, {5,3}} tStart=0.404693629 tEnd=0 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [3] {{0,2}, {3,5}, {5,0}, {4,2}} tStart=0.215060475 tEnd=0.578517386 sign=-1 windValue=1 windSum=2 1->2 (max=2) done=0 tiny=0 opp=1
-findNextOp firstIndex=[0] sign=-1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=0 result=0
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=3 (0,5 2,4 2,0 5,3) t=0.404693629 [1] (1.77689767,2.97472143) tEnd=0.64696132 newWindSum=-1 newOppSum=2 oppSum=2 windSum=-1 windValue=1
-findNextOp from:[3] to:[3] start=1 end=0
-bridgeOp current id=3 from=(2.72437143,2) to=(1.77689767,2.97472143)
-path.cubicTo(2.35977101,2.16866159, 2.06764531,2.54096746, 1.77689767,2.97472143);
-findNextOp simple
-markDoneBinary id=3 (0,5 2,4 2,0 5,3) t=0 [0] (0,5) tEnd=0.404693629 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1
-bridgeOp current id=3 from=(1.77689767,2.97472143) to=(0,5)
-path.cubicTo(1.29122055,3.69928193, 0.809387267,4.5953064, 0,5);
-findNextOp simple
-markDoneBinary id=4 (5,3 0,5) t=0 [0] (5,3) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1
-bridgeOp current id=4 from=(0,5) to=(5,3)
-findNextOp debugShowSort contourWinding=-1 oppContourWinding=1 sign=-1
-debugShowSort [3] {{0,5}, {2,4}, {2,0}, {5,3}} tStart=0.846938928 tEnd=1 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [0] {{0,2}, {3,5}, {5,0}, {4,2}} tStart=0.578517386 tEnd=0.6 sign=-1 windValue=1 windSum=2 1->2 (max=2) done=1 tiny=0 opp=1
-debugShowSort [1] {{0,5}, {2,4}, {2,0}, {5,3}} tStart=0.846938928 tEnd=0.819132784 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [2] {{0,2}, {3,5}, {5,0}, {4,2}} tStart=0.578517386 tEnd=0.215060475 sign=1 windValue=1 windSum=2 2->1 (max=2) done=0 tiny=0 opp=1
-findNextOp firstIndex=[3] sign=-1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=0 result=0
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=3 (0,5 2,4 2,0 5,3) t=0.846938928 [4] (3.81537032,2.07857323) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1
-findNextOp from:[3] to:[3] start=4 end=3
-bridgeOp current id=3 from=(5,3) to=(3.81537032,2.07857323)
-path.lineTo(5,3);
-path.cubicTo(4.54081678,2.54081678, 4.1519165,2.2456274, 3.81537032,2.07857323);
-path.close();
-debugShowActiveSpans id=1 (0,2 3,5 5,0 4,2) t=0.215060475 (1.77689767,2.97472143) tEnd=0.578517386 other=3 otherT=0.404693629 otherIndex=1 windSum=2 windValue=1 oppValue=0
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=1 (0,2 3,5 5,0 4,2) t=0.215060475 [1] (1.77689767,2.97472143) tEnd=0.578517386 newWindSum=2 newOppSum=-1 oppSum=-1 windSum=2 windValue=1
-assemble
-assemble contour start=(4,2) end=(4,2)
-</div>
-
-<div id="cubicOp46da">
- {{0,2}, {3,5}, {5,0}, {4,2}},
-
- {{0,2}, {1.1328125,3.06640625}, {2.03125,2.984375}},
- {{2.03125,2.984375}, {2.9296875,2.90234375}, {3.5,2.375}},
- {{3.5,2.375}, {4.0703125,1.84765625}, {4.21875,1.578125}},
- {{4.21875,1.578125}, {4.3671875,1.30859375}, {4,2}},
-</div>
-
-<div id="cubicOp46db">
-{{x = 3, y = 4}, {x = 4.0000000000000009, y = 6}, {x = 0.99999999999999845, y = 7.894919286223335e-16}, {x = 6, y = 2}}
-</div>
-
-<div id="cubicOp47d">
- SimplifyNew_Test [cubicOp47d]
-{{0,1}, {1,6}, {6,2}, {5,4}},
-{{5,4}, {0,1}},
-op difference
-{{2,6}, {4,5}, {1,0}, {6,1}},
-{{6,1}, {2,6}},
-debugShowCubicIntersection no self intersect {{2,6}, {4,5}, {1,0}, {6,1}}
-debugShowCubicLineIntersection wtTs[0]=0 {{2,6}, {4,5}, {1,0}, {6,1}} {{2,6}} wtTs[1]=0.171428571 {{2.6532478134110784,5.1834402332361513}} wtTs[2]=1 {{6,1}} wnTs[0]=1 {{6,1}, {2,6}} wnTs[1]=0.836688047 wnTs[2]=0
-debugShowCubicIntersection no intersect {{2,6}, {4,5}, {1,0}, {6,1}} {{0,1}, {1,6}, {6,2}, {5,4}}
-debugShowCubicLineIntersection wtTs[0]=0.503145036 {{2,6}, {4,5}, {1,0}, {6,1}} {{2.8774036920020918,2.7264422152012551}} wnTs[0]=0.424519 {{5,4}, {0,1}}
-debugShowCubicLineIntersection wtTs[0]=0.604274731 {{0,1}, {1,6}, {6,2}, {5,4}} {{3.9881028045490883,3.5148714943136397}} wnTs[0]=0.502974 {{6,1}, {2,6}}
-debugShowLineIntersection wtTs[0]=0.486486486 {{6,1}, {2,6}} {{4.0540540540540535,3.4324324324324329}} wnTs[0]=0.189189 {{5,4}, {0,1}}
-debugShowCubicIntersection no self intersect {{0,1}, {1,6}, {6,2}, {5,4}}
-debugShowCubicLineIntersection wtTs[0]=0 {{0,1}, {1,6}, {6,2}, {5,4}} {{0,1}} wtTs[1]=0.628571429 {{4.1434402332361522,3.486064139941691}} wtTs[2]=1 {{5,4}} wnTs[0]=1 {{5,4}, {0,1}} wnTs[1]=0.171311953 wnTs[2]=0
-debugShowActiveSpans id=3 (2,6 4,5 1,0 6,1) t=0 (2,6) tEnd=0.171428571 other=4 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (2,6 4,5 1,0 6,1) t=0.171428571 (2.65324783,5.18344021) tEnd=0.503145036 other=4 otherT=0.836688047 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (2,6 4,5 1,0 6,1) t=0.503145036 (2.87740374,2.7264421) tEnd=1 other=2 otherT=0.424519262 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (6,1 2,6) t=0 (6,1) tEnd=0.486486486 other=3 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (6,1 2,6) t=0.486486486 (4.05405426,3.43243241) tEnd=0.502974299 other=2 otherT=0.189189189 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (6,1 2,6) t=0.502974299 (3.98810291,3.5148716) tEnd=0.836688047 other=1 otherT=0.604274731 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (6,1 2,6) t=0.836688047 (2.65324783,5.18344021) tEnd=1 other=3 otherT=0.171428571 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,1 1,6 6,2 5,4) t=0 (0,1) tEnd=0.604274731 other=2 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,1 1,6 6,2 5,4) t=0.604274731 (3.98810291,3.5148716) tEnd=0.628571429 other=4 otherT=0.502974299 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,1 1,6 6,2 5,4) t=0.628571429 (4.14344025,3.4860642) tEnd=1 other=2 otherT=0.171311953 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,4 0,1) t=0 (5,4) tEnd=0.171311953 other=1 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,4 0,1) t=0.171311953 (4.14344025,3.4860642) tEnd=0.189189189 other=1 otherT=0.628571429 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,4 0,1) t=0.189189189 (4.05405426,3.43243241) tEnd=0.424519262 other=4 otherT=0.486486486 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,4 0,1) t=0.424519262 (2.87740374,2.7264421) tEnd=1 other=3 otherT=0.503145036 otherIndex=2 windSum=? windValue=1 oppValue=0
-findTop debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [0] {{0,1}, {1,6}, {6,2}, {5,4}} tStart=0 tEnd=0.604274731 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] {{5,4}, {0,1}} tStart=1 tEnd=0.424519262 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=0
-markWinding id=1 (0,1 1,6 6,2 5,4) t=0 [0] (0,1) tEnd=0.604274731 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=2 (5,4 0,1) t=0.424519262 [3] (2.87740374,2.7264421) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=1 (0,1 1,6 6,2 5,4) t=0 [0] (0,1) tEnd=0.604274731 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-activeOp op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-findNextOp simple
-markDoneBinary id=1 (0,1 1,6 6,2 5,4) t=0 [0] (0,1) tEnd=0.604274731 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-bridgeOp current id=1 from=(3.98810291,3.5148716) to=(0,1)
-path.moveTo(3.98810291,3.5148716);
-path.cubicTo(2.66914129,3.75641561, 0.60427475,4.02137375, 0,1);
-findNextOp debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [1] {{5,4}, {0,1}} tStart=0.424519262 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [2] {{2,6}, {4,5}, {1,0}, {6,1}} tStart=0.503145036 tEnd=0.171428571 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=1
-debugShowSort [3] {{5,4}, {0,1}} tStart=0.424519262 tEnd=0.189189189 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [0] {{2,6}, {4,5}, {1,0}, {6,1}} tStart=0.503145036 tEnd=1 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=1
-findNextOp firstIndex=[1] sign=-1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-markWinding id=3 (2,6 4,5 1,0 6,1) t=0.171428571 [1] (2.65324783,5.18344021) tEnd=0.503145036 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-activeOp op=diff miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
-markDoneBinary id=2 (5,4 0,1) t=0.189189189 [2] (4.05405426,3.43243241) tEnd=0.424519262 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=2
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-markDoneBinary id=3 (2,6 4,5 1,0 6,1) t=0.503145036 [2] (2.87740374,2.7264421) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-markDoneBinary id=4 (6,1 2,6) t=0 [0] (6,1) tEnd=0.486486486 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=4
-markDoneBinary id=2 (5,4 0,1) t=0.424519262 [3] (2.87740374,2.7264421) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-findNextOp from:[2] to:[3] start=2 end=1
-bridgeOp current id=2 from=(0,1) to=(2.87740374,2.7264421)
-findNextOp debugShowSort contourWinding=-1 oppContourWinding=1 sign=-1
-debugShowSort [1] {{2,6}, {4,5}, {1,0}, {6,1}} tStart=0.171428571 tEnd=0.503145036 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [2] {{6,1}, {2,6}} tStart=0.836688047 tEnd=1 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [3] {{2,6}, {4,5}, {1,0}, {6,1}} tStart=0.171428571 tEnd=0 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [0] {{6,1}, {2,6}} tStart=0.836688047 tEnd=0.502974299 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-findNextOp firstIndex=[1] sign=-1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-markWinding id=4 (6,1 2,6) t=0.836688047 [3] (2.65324783,5.18344021) tEnd=1 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1
-markWinding id=3 (2,6 4,5 1,0 6,1) t=0 [0] (2,6) tEnd=0.171428571 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-markWinding id=4 (6,1 2,6) t=0.502974299 [2] (3.98810291,3.5148716) tEnd=0.836688047 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=4
-markDoneBinary id=3 (2,6 4,5 1,0 6,1) t=0.171428571 [1] (2.65324783,5.18344021) tEnd=0.503145036 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1
-findNextOp from:[3] to:[4] start=3 end=4
-bridgeOp current id=3 from=(2.87740374,2.7264421) to=(2.65324783,5.18344021)
-path.lineTo(2.87740374,2.7264421);
-path.cubicTo(2.7913022,3.55361414, 2.87475324,4.49428225, 2.65324783,5.18344021);
-findNextOp simple
-markDoneBinary id=4 (6,1 2,6) t=0.836688047 [3] (2.65324783,5.18344021) tEnd=1 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1
-bridgeOp current id=4 from=(2.65324783,5.18344021) to=(2,6)
-findNextOp debugShowSort contourWinding=1 oppContourWinding=1 sign=1
-debugShowSort [3] {{2,6}, {4,5}, {1,0}, {6,1}} tStart=0.171428571 tEnd=0 sign=1 windValue=1 windSum=1 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [0] {{6,1}, {2,6}} tStart=0.836688047 tEnd=0.502974299 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [1] {{2,6}, {4,5}, {1,0}, {6,1}} tStart=0.171428571 tEnd=0.503145036 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [2] {{6,1}, {2,6}} tStart=0.836688047 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=0
-findNextOp firstIndex=[3] sign=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-markDoneBinary id=3 (2,6 4,5 1,0 6,1) t=0 [0] (2,6) tEnd=0.171428571 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1
-findNextOp from:[3] to:[4] start=3 end=2
-bridgeOp current id=3 from=(2,6) to=(2.65324783,5.18344021)
-path.lineTo(2,6);
-path.cubicTo(2.34285712,5.82857132, 2.53877544,5.53959179, 2.65324783,5.18344021);
-findNextOp debugShowSort contourWinding=-1 oppContourWinding=1 sign=-1
-debugShowSort [3] {{6,1}, {2,6}} tStart=0.502974299 tEnd=0.836688047 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [0] {{0,1}, {1,6}, {6,2}, {5,4}} tStart=0.604274731 tEnd=0.628571429 sign=-1 windValue=1 windSum=? 1->2 (max=2) done=0 tiny=0 opp=1
-debugShowSort [1] {{6,1}, {2,6}} tStart=0.502974299 tEnd=0.486486486 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [2] {{0,1}, {1,6}, {6,2}, {5,4}} tStart=0.604274731 tEnd=0 sign=1 windValue=1 windSum=1 2->1 (max=2) done=1 tiny=0 opp=1
-findNextOp firstIndex=[3] sign=-1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=0 result=0
-markDoneBinary id=1 (0,1 1,6 6,2 5,4) t=0.604274731 [1] (3.98810291,3.5148716) tEnd=0.628571429 newWindSum=2 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-markWinding id=4 (6,1 2,6) t=0.486486486 [1] (4.05405426,3.43243241) tEnd=0.502974299 newWindSum=-1 newOppSum=2 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=4
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=4 (6,1 2,6) t=0.502974299 [2] (3.98810291,3.5148716) tEnd=0.836688047 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1
-findNextOp from:[4] to:[4] start=2 end=1
-bridgeOp current id=4 from=(2.65324783,5.18344021) to=(3.98810291,3.5148716)
-path.lineTo(3.98810291,3.5148716);
-path.close();
-debugShowActiveSpans id=4 (6,1 2,6) t=0.486486486 (4.05405426,3.43243241) tEnd=0.502974299 other=2 otherT=0.189189189 otherIndex=2 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,1 1,6 6,2 5,4) t=0.628571429 (4.14344025,3.4860642) tEnd=1 other=2 otherT=0.171311953 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,4 0,1) t=0 (5,4) tEnd=0.171311953 other=1 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,4 0,1) t=0.171311953 (4.14344025,3.4860642) tEnd=0.189189189 other=1 otherT=0.628571429 otherIndex=2 windSum=? windValue=1 oppValue=0
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
-findNextOp debugShowSort contourWinding=0 oppContourWinding=2 sign=1
-debugShowSort [1] {{6,1}, {2,6}} tStart=0.502974299 tEnd=0.486486486 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [2] {{0,1}, {1,6}, {6,2}, {5,4}} tStart=0.604274731 tEnd=0 sign=1 windValue=1 windSum=1 2->1 (max=2) done=1 tiny=0 opp=1
-debugShowSort [3] {{6,1}, {2,6}} tStart=0.502974299 tEnd=0.836688047 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [0] {{0,1}, {1,6}, {6,2}, {5,4}} tStart=0.604274731 tEnd=0.628571429 sign=-1 windValue=1 windSum=2 1->2 (max=2) done=1 tiny=0 opp=1
-findNextOp firstIndex=[1] sign=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=1 result=0
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=0 result=0
-markDoneBinary id=4 (6,1 2,6) t=0.486486486 [1] (4.05405426,3.43243241) tEnd=0.502974299 newWindSum=-1 newOppSum=2 oppSum=2 windSum=-1 windValue=1
-findNextOp from:[4] to:[4] start=2 end=3
-bridgeOp current id=4 from=(4.05405426,3.43243241) to=(3.98810291,3.5148716)
-debugShowActiveSpans id=1 (0,1 1,6 6,2 5,4) t=0.628571429 (4.14344025,3.4860642) tEnd=1 other=2 otherT=0.171311953 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,4 0,1) t=0 (5,4) tEnd=0.171311953 other=1 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,4 0,1) t=0.171311953 (4.14344025,3.4860642) tEnd=0.189189189 other=1 otherT=0.628571429 otherIndex=2 windSum=? windValue=1 oppValue=0
-</div>
-
-<div id="cubicOp47da">
-computed quadratics given
- {{2,6}, {4,5}, {1,0}, {6,1}},
- {{0,1}, {1,6}, {6,2}, {5,4}},
-computed quadratics set 1
- {{2,6}, {2.2404737,5.87759298}, {2.39345162,5.68487367}},
- {{2.39345162,5.68487367}, {2.67348969,5.31541246}, {2.74792918,4.77711896}},
- {{2.74792918,4.77711896}, {2.82236867,4.23882547}, {2.82848144,3.63729341}},
- {{2.82848144,3.63729341}, {2.83027876,3.57616472}, {2.83215462,3.51498289}},
- {{2.83215462,3.51498289}, {2.78850872,2.32758859}, {3.26769775,1.50382966}},
- {{3.26769775,1.50382966}, {3.55499101,1.08453908}, {4.20162956,0.930553195}},
- {{4.20162956,0.930553195}, {4.84826812,0.776567313}, {6,1}},
-computed quadratics set 2
- {{0,1}, {0.337189878,2.53658624}, {1.06305813,3.09524088}},
- {{1.06305813,3.09524088}, {1.78892639,3.65389552}, {2.62772567,3.64823958}},
- {{2.62772567,3.64823958}, {3.46652495,3.64258364}, {4.1425079,3.48623815}},
- {{4.1425079,3.48623815}, {4.88772835,3.3075243}, {5.09137748,3.46764237}},
- {{5.09137748,3.46764237}, {5.20611277,3.58418013}, {5,4}},
-</div>
-
-<div id="cubicOp47db">
- {{2.74792918,4.77711896}, {2.82236867,4.23882547}, {2.82848144,3.63729341}},
- {{2.62772567,3.64823958}, {3.46652495,3.64258364}, {4.1425079,3.48623815}},
-</div>
-
-<div id="cubicOp48d">
- SimplifyNew_Test [cubicOp48d]
-{{0,2}, {2,3}, {5,1}, {3,2}},
-{{3,2}, {0,2}},
-op difference
-{{1,5}, {2,3}, {2,0}, {3,2}},
-{{3,2}, {1,5}},
-debugShowCubicIntersection no self intersect {{1,5}, {2,3}, {2,0}, {3,2}}
-debugShowCubicLineIntersection wtTs[0]=0 {{1,5}, {2,3}, {2,0}, {3,2}} {{1,5}} wtTs[1]=1 {{3,2}} wnTs[0]=1 {{3,2}, {1,5}} wnTs[1]=0
-debugShowCubicIntersection wtTs[0]=0.447821962 {{1,5}, {2,3}, {2,0}, {3,2}} {{1.921448828321461,2.2502841146969206}} wtTs[1]=1 {{3,2}} wnTs[0]=0.302178 {{0,2}, {2,3}, {5,1}, {3,2}} wnTs[1]=1
-debugShowCubicLineIntersection wtTs[0]=0.5 {{1,5}, {2,3}, {2,0}, {3,2}} {{2,2}} wtTs[1]=1 {{3,2}} wnTs[0]=0.333333 {{3,2}, {0,2}} wnTs[1]=0
-debugShowCubicLineIntersection wtTs[0]=0.5 {{0,2}, {2,3}, {5,1}, {3,2}} {{3,2}} wtTs[1]=1 {{3,2}} wnTs[0]=0 {{3,2}, {1,5}} wnTs[1]=0
-debugShowLineIntersection wtTs[0]=0 {{3,2}, {1,5}} {{3,2}} wnTs[0]=0 {{3,2}, {0,2}}
-debugShowCubicIntersection wtTs[0]=0.5 {{0,2}, {2,3}, {5,1}, {3,2}} {{3,2}} wtTs[1]=1
-debugShowCubicLineIntersection wtTs[0]=0 {{0,2}, {2,3}, {5,1}, {3,2}} {{0,2}} wtTs[1]=0.5 {{3,2}} wtTs[2]=1 {{3,2}} wnTs[0]=1 {{3,2}, {0,2}} wnTs[1]=0 wnTs[2]=0
-debugShowActiveSpans id=3 (1,5 2,3 2,0 3,2) t=0 (1,5) tEnd=0.447821962 other=4 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,5 2,3 2,0 3,2) t=0.447821962 (1.92144883,2.25028419) tEnd=0.5 other=1 otherT=0.302178051 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,5 2,3 2,0 3,2) t=0.5 (2,2) tEnd=1 other=2 otherT=0.333333333 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (3,2 1,5) t=0 (3,2) tEnd=1 other=3 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 2,3 5,1 3,2) t=0 (0,2) tEnd=0.302178051 other=2 otherT=1 otherIndex=5 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 2,3 5,1 3,2) t=0.302178051 (1.92144883,2.25028419) tEnd=0.5 other=3 otherT=0.447821962 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 2,3 5,1 3,2) t=0.5 (3,2) tEnd=1 other=4 otherT=0 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (3,2 0,2) t=0 (3,2) tEnd=0.333333333 other=3 otherT=1 otherIndex=5 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (3,2 0,2) t=0.333333333 (2,2) tEnd=1 other=3 otherT=0.5 otherIndex=2 windSum=? windValue=1 oppValue=0
-findTop debugShowSort contourWinding=0 oppContourWinding=0 sign=1
-debugShowSort [1] {{1,5}, {2,3}, {2,0}, {3,2}} tStart=1 tEnd=0.5 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [2] {{3,2}, {0,2}} tStart=0 tEnd=0.333333333 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=1
-debugShowSort [3] {{3,2}, {1,5}} tStart=0 tEnd=1 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [0] {{0,2}, {2,3}, {5,1}, {3,2}} tStart=1 tEnd=0.5 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=1
-markWinding id=3 (1,5 2,3 2,0 3,2) t=0.5 [2] (2,2) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=3 (1,5 2,3 2,0 3,2) t=0.5 [2] (2,2) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-markDoneBinary id=3 (1,5 2,3 2,0 3,2) t=0.5 [2] (2,2) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-findChaseOp debugShowSort contourWinding=? oppContourWinding=? sign=1
-debugShowSort [0] {{0,2}, {2,3}, {5,1}, {3,2}} tStart=1 tEnd=0.5 sign=1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=0
-debugShowSort [1] {{1,5}, {2,3}, {2,0}, {3,2}} tStart=1 tEnd=0.5 sign=1 windValue=1 windSum=-1 ?->? (max=?) done=1 tiny=0 opp=1
-debugShowSort [2] {{3,2}, {0,2}} tStart=0 tEnd=0.333333333 sign=-1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=0
-debugShowSort [3] {{3,2}, {1,5}} tStart=0 tEnd=1 sign=-1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=1
-findChaseOp debugShowSort contourWinding=0 oppContourWinding=0 sign=1
-debugShowSort [1] {{1,5}, {2,3}, {2,0}, {3,2}} tStart=1 tEnd=0.5 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [2] {{3,2}, {0,2}} tStart=0 tEnd=0.333333333 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=1
-debugShowSort [3] {{3,2}, {1,5}} tStart=0 tEnd=1 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [0] {{0,2}, {2,3}, {5,1}, {3,2}} tStart=1 tEnd=0.5 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=1
-markWinding id=2 (3,2 0,2) t=0 [0] (3,2) tEnd=0 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1
-markWinding id=2 (3,2 0,2) t=0 [1] (3,2) tEnd=0 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1
-markWinding id=2 (3,2 0,2) t=0 [2] (3,2) tEnd=0 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1
-markWinding id=2 (3,2 0,2) t=0 [3] (3,2) tEnd=0.333333333 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1
-markWinding id=4 (3,2 1,5) t=0 [0] (3,2) tEnd=0 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-markWinding id=4 (3,2 1,5) t=0 [1] (3,2) tEnd=0 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-markWinding id=4 (3,2 1,5) t=0 [2] (3,2) tEnd=0 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-markWinding id=4 (3,2 1,5) t=0 [3] (3,2) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-markWinding id=3 (1,5 2,3 2,0 3,2) t=0 [0] (1,5) tEnd=0.447821962 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-markWinding id=1 (0,2 2,3 5,1 3,2) t=0.5 [3] (3,2) tEnd=0.5 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=1 (0,2 2,3 5,1 3,2) t=0.5 [2] (3,2) tEnd=0.5 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=1 (0,2 2,3 5,1 3,2) t=0.5 [4] (3,2) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-debugShowActiveSpans id=3 (1,5 2,3 2,0 3,2) t=0 (1,5) tEnd=0.447821962 other=4 otherT=1 otherIndex=4 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,5 2,3 2,0 3,2) t=0.447821962 (1.92144883,2.25028419) tEnd=0.5 other=1 otherT=0.302178051 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (3,2 1,5) t=0 (3,2) tEnd=1 other=3 otherT=1 otherIndex=3 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 2,3 5,1 3,2) t=0 (0,2) tEnd=0.302178051 other=2 otherT=1 otherIndex=5 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 2,3 5,1 3,2) t=0.302178051 (1.92144883,2.25028419) tEnd=0.5 other=3 otherT=0.447821962 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 2,3 5,1 3,2) t=0.5 (3,2) tEnd=1 other=4 otherT=0 otherIndex=1 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (3,2 0,2) t=0 (3,2) tEnd=0.333333333 other=3 otherT=1 otherIndex=5 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (3,2 0,2) t=0.333333333 (2,2) tEnd=1 other=3 otherT=0.5 otherIndex=2 windSum=? windValue=1 oppValue=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=2 (3,2 0,2) t=0 [0] (3,2) tEnd=0 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1
-markDoneBinary id=2 (3,2 0,2) t=0 [1] (3,2) tEnd=0 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1
-markDoneBinary id=2 (3,2 0,2) t=0 [2] (3,2) tEnd=0 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1
-markDoneBinary id=2 (3,2 0,2) t=0 [3] (3,2) tEnd=0.333333333 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1
-findChaseOp debugShowSort contourWinding=-1 oppContourWinding=0 sign=-1
-debugShowSort [0] {{1,5}, {2,3}, {2,0}, {3,2}} tStart=0.5 tEnd=1 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [1] {{3,2}, {0,2}} tStart=0.333333333 tEnd=1 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=1
-debugShowSort [2] {{1,5}, {2,3}, {2,0}, {3,2}} tStart=0.5 tEnd=0.447821962 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [3] {{3,2}, {0,2}} tStart=0.333333333 tEnd=0 sign=1 windValue=1 windSum=1 1->0 (max=1) done=1 tiny=0 opp=1
-findChaseOp debugShowSort contourWinding=-1 oppContourWinding=0 sign=-1
-debugShowSort [0] {{1,5}, {2,3}, {2,0}, {3,2}} tStart=0.5 tEnd=1 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [1] {{3,2}, {0,2}} tStart=0.333333333 tEnd=1 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=1
-debugShowSort [2] {{1,5}, {2,3}, {2,0}, {3,2}} tStart=0.5 tEnd=0.447821962 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [3] {{3,2}, {0,2}} tStart=0.333333333 tEnd=0 sign=1 windValue=1 windSum=1 1->0 (max=1) done=1 tiny=0 opp=1
-markWinding id=2 (3,2 0,2) t=0.333333333 [4] (2,2) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=1 (0,2 2,3 5,1 3,2) t=0 [0] (0,2) tEnd=0.302178051 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=3 (1,5 2,3 2,0 3,2) t=0.447821962 [1] (1.92144883,2.25028419) tEnd=0.5 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-debugShowActiveSpans id=3 (1,5 2,3 2,0 3,2) t=0 (1,5) tEnd=0.447821962 other=4 otherT=1 otherIndex=4 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,5 2,3 2,0 3,2) t=0.447821962 (1.92144883,2.25028419) tEnd=0.5 other=1 otherT=0.302178051 otherIndex=1 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (3,2 1,5) t=0 (3,2) tEnd=1 other=3 otherT=1 otherIndex=3 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 2,3 5,1 3,2) t=0 (0,2) tEnd=0.302178051 other=2 otherT=1 otherIndex=5 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 2,3 5,1 3,2) t=0.302178051 (1.92144883,2.25028419) tEnd=0.5 other=3 otherT=0.447821962 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 2,3 5,1 3,2) t=0.5 (3,2) tEnd=1 other=4 otherT=0 otherIndex=1 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (3,2 0,2) t=0.333333333 (2,2) tEnd=1 other=3 otherT=0.5 otherIndex=2 windSum=1 windValue=1 oppValue=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-findNextOp simple
-markDoneBinary id=2 (3,2 0,2) t=0.333333333 [4] (2,2) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-bridgeOp current id=2 from=(2,2) to=(0,2)
-findNextOp debugShowSort contourWinding=1 oppContourWinding=0 sign=1
-debugShowSort [2] {{0,2}, {2,3}, {5,1}, {3,2}} tStart=0.302178051 tEnd=0 sign=1 windValue=1 windSum=1 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [3] {{1,5}, {2,3}, {2,0}, {3,2}} tStart=0.447821962 tEnd=0 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=0 tiny=0 opp=1
-debugShowSort [0] {{0,2}, {2,3}, {5,1}, {3,2}} tStart=0.302178051 tEnd=0.5 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] {{1,5}, {2,3}, {2,0}, {3,2}} tStart=0.447821962 tEnd=0.5 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=0 tiny=0 opp=1
-findNextOp firstIndex=[2] sign=1
-activeOp op=diff miFrom=0 miTo=0 suFrom=0 suTo=1 result=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=1 (0,2 2,3 5,1 3,2) t=0.302178051 [1] (1.92144883,2.25028419) tEnd=0.5 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
-markDoneBinary id=1 (0,2 2,3 5,1 3,2) t=0 [0] (0,2) tEnd=0.302178051 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-findNextOp from:[1] to:[3] start=1 end=2
-bridgeOp current id=1 from=(0,2) to=(1.92144883,2.25028419)
-path.moveTo(2,2);
-path.lineTo(0,2);
-path.cubicTo(0.60435605,2.30217814, 1.30002379,2.33042121, 1.92144883,2.25028419);
-findNextOp debugShowSort contourWinding=0 oppContourWinding=1 sign=1
-debugShowSort [2] {{1,5}, {2,3}, {2,0}, {3,2}} tStart=0.5 tEnd=0.447821962 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [3] {{3,2}, {0,2}} tStart=0.333333333 tEnd=0 sign=1 windValue=1 windSum=1 1->0 (max=1) done=1 tiny=0 opp=1
-debugShowSort [0] {{1,5}, {2,3}, {2,0}, {3,2}} tStart=0.5 tEnd=1 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [1] {{3,2}, {0,2}} tStart=0.333333333 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=1
-findNextOp firstIndex=[2] sign=1
-activeOp op=diff miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-markDoneBinary id=3 (1,5 2,3 2,0 3,2) t=0.447821962 [1] (1.92144883,2.25028419) tEnd=0.5 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1
-findNextOp from:[3] to:[2] start=4 end=5
-bridgeOp current id=3 from=(1.92144883,2.25028419) to=(2,2)
-path.cubicTo(1.94782197,2.1619792, 1.97391093,2.0782671, 2,2);
-path.close();
-debugShowActiveSpans id=3 (1,5 2,3 2,0 3,2) t=0 (1,5) tEnd=0.447821962 other=4 otherT=1 otherIndex=4 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (3,2 1,5) t=0 (3,2) tEnd=1 other=3 otherT=1 otherIndex=3 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 2,3 5,1 3,2) t=0.5 (3,2) tEnd=1 other=4 otherT=0 otherIndex=1 windSum=1 windValue=1 oppValue=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-findNextOp debugShowSort contourWinding=1 oppContourWinding=0 sign=1
-debugShowSort [1] {{0,2}, {2,3}, {5,1}, {3,2}} tStart=1 tEnd=0.5 sign=1 windValue=1 windSum=1 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [2] {{1,5}, {2,3}, {2,0}, {3,2}} tStart=1 tEnd=0.5 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=1
-debugShowSort [3] {{3,2}, {0,2}} tStart=0 tEnd=0.333333333 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=0
-debugShowSort [4] {{0,2}, {2,3}, {5,1}, {3,2}} tStart=0.5 tEnd=0.302178051 sign=1 windValue=1 windSum=1 1->0 (max=1) done=1 tiny=0 opp=0
-debugShowSort [5] {{3,2}, {1,5}} tStart=0 tEnd=1 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=0 tiny=0 opp=1
-debugShowSort [0] {{0,2}, {2,3}, {5,1}, {3,2}} tStart=0.5 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=0 tiny=0 opp=0
-findNextOp firstIndex=[1] sign=1
-activeOp op=diff miFrom=0 miTo=0 suFrom=0 suTo=1 result=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-activeOp op=diff miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-markDoneBinary id=1 (0,2 2,3 5,1 3,2) t=0.5 [2] (3,2) tEnd=0.5 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-markDoneBinary id=1 (0,2 2,3 5,1 3,2) t=0.5 [3] (3,2) tEnd=0.5 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-markDoneBinary id=1 (0,2 2,3 5,1 3,2) t=0.5 [4] (3,2) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-findNextOp from:[1] to:[1] start=3 end=5
-bridgeOp current id=1 from=(3,2) to=(3,2)
-path.moveTo(3,2);
-path.cubicTo(3.75,1.75, 4,1.5, 3,2);
-path.close();
-debugShowActiveSpans id=3 (1,5 2,3 2,0 3,2) t=0 (1,5) tEnd=0.447821962 other=4 otherT=1 otherIndex=4 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (3,2 1,5) t=0 (3,2) tEnd=1 other=3 otherT=1 otherIndex=3 windSum=-1 windValue=1 oppValue=0
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
-findNextOp simple
-markDoneBinary id=4 (3,2 1,5) t=0 [0] (3,2) tEnd=0 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1
-markDoneBinary id=4 (3,2 1,5) t=0 [1] (3,2) tEnd=0 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1
-markDoneBinary id=4 (3,2 1,5) t=0 [2] (3,2) tEnd=0 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1
-markDoneBinary id=4 (3,2 1,5) t=0 [3] (3,2) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1
-bridgeOp current id=4 from=(3,2) to=(1,5)
-findNextOp debugShowSort contourWinding=0 oppContourWinding=1 sign=1
-debugShowSort [3] {{1,5}, {2,3}, {2,0}, {3,2}} tStart=0.447821962 tEnd=0 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [0] {{0,2}, {2,3}, {5,1}, {3,2}} tStart=0.302178051 tEnd=0.5 sign=-1 windValue=1 windSum=1 1->2 (max=2) done=1 tiny=0 opp=1
-debugShowSort [1] {{1,5}, {2,3}, {2,0}, {3,2}} tStart=0.447821962 tEnd=0.5 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [2] {{0,2}, {2,3}, {5,1}, {3,2}} tStart=0.302178051 tEnd=0 sign=1 windValue=1 windSum=1 2->1 (max=2) done=1 tiny=0 opp=1
-findNextOp firstIndex=[3] sign=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=1 result=0
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=0 result=0
-markDoneBinary id=3 (1,5 2,3 2,0 3,2) t=0 [0] (1,5) tEnd=0.447821962 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1
-findNextOp from:[3] to:[3] start=1 end=2
-bridgeOp current id=3 from=(1,5) to=(1.92144883,2.25028419)
-path.moveTo(3,2);
-path.lineTo(1,5);
-path.cubicTo(1.44782197,4.10435629, 1.69509947,3.00816751, 1.92144883,2.25028419);
-</div>
-
-<div id="cubicOp48da">
- {{0,2}, {2,3}, {5,1}, {3,2}},
-
- {{0,2}, {0.796711951,2.36012932}, {1.63878124,2.27837338}},
- {{1.63878124,2.27837338}, {2.48085053,2.19661745}, {3.06246392,1.97878949}},
- {{3.06246392,1.97878949}, {3.64407731,1.76096154}, {3.65942155,1.71287481}},
- {{3.65942155,1.71287481}, {3.66835761,1.67480112}, {3,2}},
-</div>
-
-<div id="cubicOp32d">
- SimplifyNew_Test [cubicOp32d]
-{{0,1}, {1,2}, {6,0}, {3,1}},
-{{3,1}, {0,1}},
-op difference
-{{0,6}, {1,3}, {1,0}, {2,1}},
-{{2,1}, {0,6}},
-insert t=0.5 pts roughly equal
-insert t=0.5 pts roughly equal
-insert t=0.5 pts roughly equal
-debugShowCubicIntersection wtTs[0]=1 {{0,1}, {1,2}, {6,0}, {3,1}} {{3,1}} wtTs[1]=0.5
-insert t=0.5 pts roughly equal
-debugShowCubicLineIntersection wtTs[0]=0 {{0,1}, {1,2}, {6,0}, {3,1}} {{0,1}} wtTs[1]=0.5 {{3,1}} wtTs[2]=1 {{3,1}} wnTs[0]=1 {{3,1}, {0,1}} wnTs[1]=0 wnTs[2]=0
-debugShowCubicIntersection wtTs[0]=0.235702334 {{0,1}, {1,2}, {6,0}, {3,1}} {{1.2166390977965289,1.2856741834504377}} wnTs[0]=0.640711 {{0,6}, {1,3}, {1,0}, {2,1}}
-debugShowCubicLineIntersection wtTs[0]=0.336702456 {{0,1}, {1,2}, {6,0}, {3,1}} {{1.9124722896380537,1.2188192759048657}} wnTs[0]=0.0437639 {{2,1}, {0,6}}
-debugShowCubicLineIntersection wtTs[0]=0.724744871 {{0,6}, {1,3}, {1,0}, {2,1}} {{1.359821149611685,1.0000000000000004}} wtTs[1]=1 {{2,1}} wnTs[0]=0.546726 {{3,1}, {0,1}} wnTs[1]=0.333333333
-debugShowLineIntersection wtTs[0]=0 {{3,1}, {0,1}} {{2,1}} wnTs[0]=0.333333 {{2,1}, {0,6}}
-debugShowCubicIntersection no self intersect {{0,6}, {1,3}, {1,0}, {2,1}}
-debugShowCubicLineIntersection wtTs[0]=0 {{0,6}, {1,3}, {1,0}, {2,1}} {{0,6}} wtTs[1]=1 {{2,1}} wnTs[0]=1 {{2,1}, {0,6}} wnTs[1]=0
-debugShowActiveSpans id=1 (0,1 1,2 6,0 3,1) t=0 (0,1) tEnd=0.235702334 other=2 otherT=1 otherIndex=5 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,1 1,2 6,0 3,1) t=0.235702334 (1.21663904,1.28567421) tEnd=0.336702456 other=3 otherT=0.640711351 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,1 1,2 6,0 3,1) t=0.336702456 (1.91247225,1.21881926) tEnd=0.5 other=4 otherT=0.0437638552 otherIndex=2 windSum=? windValue=1 oppValue=0
-</div>
-
-<div id="cubicOp48db">
-computed quadratics given
- {{0,2}, {2,3}, {5,1}, {3,2}},
- {{1,5}, {2,3}, {2,0}, {3,2}},
-computed quadratics set 1
- {{0,2}, {0.796711951,2.36012932}, {1.63878124,2.27837338}},
- {{1.63878124,2.27837338}, {2.48085053,2.19661745}, {3.06246392,1.97878949}},
- {{3.06246392,1.97878949}, {3.64407731,1.76096154}, {3.65942155,1.71287481}},
- {{3.65942155,1.71287481}, {3.66835761,1.67480112}, {3,2}},
-computed quadratics set 2
- {{1,5}, {1.50173477,3.89061296}, {1.76597918,2.79793753}},
- {{1.76597918,2.79793753}, {2.0153684,1.78464605}, {2.27205088,1.42969352}},
- {{2.27205088,1.42969352}, {2.52873337,1.07474099}, {3,2}},
-</div>
-
-<div id="cubicOp48dc">
- {{1.63878124,2.27837338}, {2.48085053,2.19661745}, {3.06246392,1.97878949}},
- {{2.27205088,1.42969352}, {2.52873337,1.07474099}, {3,2}},
-</div>
-
-<div id="cubicOp49d">
- SimplifyNew_Test [cubicOp49d]
-{{0,2}, {1,5}, {3,2}, {4,1}},
-{{4,1}, {0,2}},
-op difference
-{{2,3}, {1,4}, {2,0}, {5,1}},
-{{5,1}, {2,3}},
-debugShowCubicIntersection no self intersect {{2,3}, {1,4}, {2,0}, {5,1}}
-debugShowCubicLineIntersection wtTs[0]=0 {{2,3}, {1,4}, {2,0}, {5,1}} {{2,3}} wtTs[1]=1 {{5,1}} wnTs[0]=1 {{5,1}, {2,3}} wnTs[1]=0
-debugShowCubicIntersection wtTs[0]=1.74609417e-09 {{2,3}, {1,4}, {2,0}, {5,1}} {{1.9999999947617175,3.0000000052382827}} wtTs[1]=0.122781788 {{1.7221068406383582,3.1607246577308117}} wnTs[0]=0.5 {{0,2}, {1,5}, {3,2}, {4,1}} wnTs[1]=0.438140761
-debugShowCubicLineIntersection wtTs[0]=0.651913155 {{2,3}, {1,4}, {2,0}, {5,1}} {{2.5942051033446676,1.3514487241638331}} wnTs[0]=0.351449 {{4,1}, {0,2}}
-debugShowCubicLineIntersection wtTs[0]=0.5 {{0,2}, {1,5}, {3,2}, {4,1}} {{2,3}} wnTs[0]=1 {{5,1}, {2,3}}
-debugShowLineIntersection no intersect {{5,1}, {2,3}} {{4,1}, {0,2}}
-debugShowCubicIntersection no self intersect {{0,2}, {1,5}, {3,2}, {4,1}}
-debugShowCubicLineIntersection wtTs[0]=0 {{0,2}, {1,5}, {3,2}, {4,1}} {{0,2}} wtTs[1]=1 {{4,1}} wnTs[0]=1 {{4,1}, {0,2}} wnTs[1]=0
-debugShowActiveSpans id=3 (2,3 1,4 2,0 5,1) t=1.74609417e-09 (2,3) tEnd=0.122781788 other=1 otherT=0.499999999 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (2,3 1,4 2,0 5,1) t=0.122781788 (1.72210681,3.16072464) tEnd=0.651913155 other=1 otherT=0.438140761 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (2,3 1,4 2,0 5,1) t=0.651913155 (2.59420514,1.35144877) tEnd=1 other=2 otherT=0.351448724 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (5,1 2,3) t=0 (5,1) tEnd=1 other=3 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 1,5 3,2 4,1) t=0 (0,2) tEnd=0.438140761 other=2 otherT=1 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 1,5 3,2 4,1) t=0.438140761 (1.72210681,3.16072464) tEnd=0.499999999 other=3 otherT=0.122781788 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 1,5 3,2 4,1) t=0.5 (2,3) tEnd=1 other=4 otherT=1 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,1 0,2) t=0 (4,1) tEnd=0.351448724 other=1 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,1 0,2) t=0.351448724 (2.59420514,1.35144877) tEnd=1 other=3 otherT=0.651913155 otherIndex=3 windSum=? windValue=1 oppValue=0
-findTop debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [1] {{2,3}, {1,4}, {2,0}, {5,1}} tStart=0.122781788 tEnd=0.651913155 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [2] {{0,2}, {1,5}, {3,2}, {4,1}} tStart=0.438140761 tEnd=0 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=1
-debugShowSort [3] {{2,3}, {1,4}, {2,0}, {5,1}} tStart=0.122781788 tEnd=1.74609417e-09 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [0] {{0,2}, {1,5}, {3,2}, {4,1}} tStart=0.438140761 tEnd=0.499999999 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=1
-findTop swap
-markWinding id=3 (2,3 1,4 2,0 5,1) t=0.122781788 [2] (1.72210681,3.16072464) tEnd=0.651913155 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=3 (2,3 1,4 2,0 5,1) t=0.122781788 [2] (1.72210681,3.16072464) tEnd=0.651913155 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-markDoneBinary id=3 (2,3 1,4 2,0 5,1) t=0.122781788 [2] (1.72210681,3.16072464) tEnd=0.651913155 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-findChaseOp debugShowSort contourWinding=? oppContourWinding=? sign=1
-debugShowSort [0] {{4,1}, {0,2}} tStart=0.351448724 tEnd=0 sign=1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=0
-debugShowSort [1] {{2,3}, {1,4}, {2,0}, {5,1}} tStart=0.651913155 tEnd=1 sign=-1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=1
-debugShowSort [2] {{4,1}, {0,2}} tStart=0.351448724 tEnd=1 sign=-1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=0
-debugShowSort [3] {{2,3}, {1,4}, {2,0}, {5,1}} tStart=0.651913155 tEnd=0.122781788 sign=1 windValue=1 windSum=-1 ?->? (max=?) done=1 tiny=0 opp=1
-findChaseOp debugShowSort contourWinding=0 oppContourWinding=0 sign=1
-debugShowSort [3] {{2,3}, {1,4}, {2,0}, {5,1}} tStart=0.651913155 tEnd=0.122781788 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [0] {{4,1}, {0,2}} tStart=0.351448724 tEnd=0 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=1
-debugShowSort [1] {{2,3}, {1,4}, {2,0}, {5,1}} tStart=0.651913155 tEnd=1 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [2] {{4,1}, {0,2}} tStart=0.351448724 tEnd=1 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=1
-markWinding id=2 (4,1 0,2) t=0 [0] (4,1) tEnd=0.351448724 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1
-markWinding id=1 (0,2 1,5 3,2 4,1) t=0.5 [3] (2,3) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1
-markWinding id=3 (2,3 1,4 2,0 5,1) t=0.651913155 [3] (2.59420514,1.35144877) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1
-markWinding id=4 (5,1 2,3) t=0 [0] (5,1) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1
-markWinding id=2 (4,1 0,2) t=0.351448724 [1] (2.59420514,1.35144877) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=1 (0,2 1,5 3,2 4,1) t=0 [0] (0,2) tEnd=0.438140761 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-debugShowActiveSpans id=3 (2,3 1,4 2,0 5,1) t=1.74609417e-09 (2,3) tEnd=0.122781788 other=1 otherT=0.499999999 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (2,3 1,4 2,0 5,1) t=0.651913155 (2.59420514,1.35144877) tEnd=1 other=2 otherT=0.351448724 otherIndex=1 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (5,1 2,3) t=0 (5,1) tEnd=1 other=3 otherT=1 otherIndex=4 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 1,5 3,2 4,1) t=0 (0,2) tEnd=0.438140761 other=2 otherT=1 otherIndex=2 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 1,5 3,2 4,1) t=0.438140761 (1.72210681,3.16072464) tEnd=0.499999999 other=3 otherT=0.122781788 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 1,5 3,2 4,1) t=0.5 (2,3) tEnd=1 other=4 otherT=1 otherIndex=2 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,1 0,2) t=0 (4,1) tEnd=0.351448724 other=1 otherT=1 otherIndex=4 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,1 0,2) t=0.351448724 (2.59420514,1.35144877) tEnd=1 other=3 otherT=0.651913155 otherIndex=3 windSum=-1 windValue=1 oppValue=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=2 (4,1 0,2) t=0 [0] (4,1) tEnd=0.351448724 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1
-markDoneBinary id=1 (0,2 1,5 3,2 4,1) t=0.5 [3] (2,3) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1
-setSpans unsortable [1] (2,3) [2] (1.72210681,3.16072464)
-debugShowActiveSpans id=3 (2,3 1,4 2,0 5,1) t=1.74609417e-09 (2,3) tEnd=0.122781788 other=1 otherT=0.499999999 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (2,3 1,4 2,0 5,1) t=0.651913155 (2.59420514,1.35144877) tEnd=1 other=2 otherT=0.351448724 otherIndex=1 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (5,1 2,3) t=0 (5,1) tEnd=1 other=3 otherT=1 otherIndex=4 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 1,5 3,2 4,1) t=0 (0,2) tEnd=0.438140761 other=2 otherT=1 otherIndex=2 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,2 1,5 3,2 4,1) t=0.438140761 (1.72210681,3.16072464) tEnd=0.499999999 other=3 otherT=0.122781788 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,1 0,2) t=0.351448724 (2.59420514,1.35144877) tEnd=1 other=3 otherT=0.651913155 otherIndex=3 windSum=-1 windValue=1 oppValue=0
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-findNextOp simple
-markDoneBinary id=4 (5,1 2,3) t=0 [0] (5,1) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1
-bridgeOp current id=4 from=(2,3) to=(5,1)
-findNextOp debugShowSort contourWinding=-1 oppContourWinding=-1 sign=-1
-debugShowSort [1] {{2,3}, {1,4}, {2,0}, {5,1}} tStart=0.651913155 tEnd=1 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [2] {{4,1}, {0,2}} tStart=0.351448724 tEnd=1 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=0 tiny=0 opp=1
-debugShowSort [3] {{2,3}, {1,4}, {2,0}, {5,1}} tStart=0.651913155 tEnd=0.122781788 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [0] {{4,1}, {0,2}} tStart=0.351448724 tEnd=0 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=1
-findNextOp firstIndex=[1] sign=-1
-activeOp op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-activeOp op=diff miFrom=0 miTo=0 suFrom=0 suTo=1 result=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=3 (2,3 1,4 2,0 5,1) t=0.651913155 [3] (2.59420514,1.35144877) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1
-findNextOp from:[3] to:[2] start=1 end=2
-bridgeOp current id=3 from=(5,1) to=(2.59420514,1.35144877)
-path.moveTo(2,3);
-path.lineTo(5,1);
-path.cubicTo(3.9557395,0.651913166, 3.15380788,0.909648538, 2.59420514,1.35144877);
-findNextOp simple
-markDoneBinary id=2 (4,1 0,2) t=0.351448724 [1] (2.59420514,1.35144877) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-bridgeOp current id=2 from=(2.59420514,1.35144877) to=(0,2)
-findNextOp debugShowSort contourWinding=0 oppContourWinding=0 sign=1
-debugShowSort [2] {{0,2}, {1,5}, {3,2}, {4,1}} tStart=0.438140761 tEnd=0 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [3] {{2,3}, {1,4}, {2,0}, {5,1}} tStart=0.122781788 tEnd=1.74609417e-09 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=1
-debugShowSort [0] {{0,2}, {1,5}, {3,2}, {4,1}} tStart=0.438140761 tEnd=0.499999999 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [1] {{2,3}, {1,4}, {2,0}, {5,1}} tStart=0.122781788 tEnd=0.651913155 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=1
-findNextOp firstIndex=[2] sign=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-markWinding id=3 (2,3 1,4 2,0 5,1) t=1.74609417e-09 [1] (2,3) tEnd=0.122781788 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-activeOp op=diff miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
-markDoneBinary id=1 (0,2 1,5 3,2 4,1) t=0.438140761 [1] (1.72210681,3.16072464) tEnd=0.499999999 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=1
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-markDoneBinary id=1 (0,2 1,5 3,2 4,1) t=0 [0] (0,2) tEnd=0.438140761 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-findNextOp from:[1] to:[3] start=2 end=1
-bridgeOp current id=1 from=(0,2) to=(1.72210681,3.16072464)
-path.lineTo(0,2);
-path.cubicTo(0.43814075,3.31442237, 1.06824887,3.47704053, 1.72210681,3.16072464);
-setSpans unsortable [1] (2,3) [2] (1.72210681,3.16072464)
-setSpans all tiny unsortable [2] (2,3) [1] (1.72210681,3.16072464)
-markUnsortable id=3 (2,3 1,4 2,0 5,1) t=1.74609417e-09 [1] (2,3) tEnd=0.122781788 newWindSum=0 windSum=-1 windValue=1
-markUnsortable id=3 (2,3 1,4 2,0 5,1) t=0 [0] (2,3) tEnd=1.74609417e-09 newWindSum=0 windSum=? windValue=1
-markUnsortable id=1 (0,2 1,5 3,2 4,1) t=0.499999999 [2] (2,3) tEnd=0.5 newWindSum=0 windSum=? windValue=1
-markUnsortable id=1 (0,2 1,5 3,2 4,1) t=0.438140761 [1] (1.72210681,3.16072464) tEnd=0.499999999 newWindSum=0 windSum=-1 windValue=1
-findNextOp debugShowSort contourWinding=-1 oppContourWinding=-1 sign=-1
-debugShowSort [0] *** UNSORTABLE *** {{2,3}, {1,4}, {2,0}, {5,1}} tStart=1.74609417e-09 tEnd=0.122781788 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [1] *** UNSORTABLE *** {{2,3}, {1,4}, {2,0}, {5,1}} tStart=1.74609417e-09 tEnd=0 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=1 tiny=1 opp=0
-debugShowSort [2] *** UNSORTABLE *** {{0,2}, {1,5}, {3,2}, {4,1}} tStart=0.499999999 tEnd=0.5 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=1 tiny=1 opp=1
-debugShowSort [3] *** UNSORTABLE *** {{0,2}, {1,5}, {3,2}, {4,1}} tStart=0.499999999 tEnd=0.438140761 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=1
-path.cubicTo(1.78458714,3.17018676, 1.87721825,3.12278175, 2,3);
-markDoneBinary id=3 (2,3 1,4 2,0 5,1) t=1.74609417e-09 [1] (2,3) tEnd=0.122781788 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1
-path.close();
-setSpans all tiny unsortable [2] (2,3) [1] (1.72210681,3.16072464)
-setSpans unsortable [1] (2,3) [2] (1.72210681,3.16072464)
-setSpans unsortable [1] (2,3) [2] (1.72210681,3.16072464)
-setSpans all tiny unsortable [2] (2,3) [1] (1.72210681,3.16072464)
-setSpans unsortable [1] (2,3) [2] (1.72210681,3.16072464)
-assemble
-assemble contour start=(2,3) end=(2,3)
-</div>
-
-<div id="cubicOp50d">
- SimplifyNew_Test [cubicOp50d]
-{{0,3}, {1,6}, {5,0}, {5,1}},
-{{5,1}, {0,3}},
-op difference
-{{0,5}, {1,5}, {3,0}, {6,1}},
-{{6,1}, {0,5}},
-debugShowCubicIntersection no self intersect {{0,5}, {1,5}, {3,0}, {6,1}}
-debugShowCubicLineIntersection wtTs[0]=0 {{0,5}, {1,5}, {3,0}, {6,1}} {{0,5}} wtTs[1]=0.181818182 {{0.64462809917355357,4.5702479338842981}} wtTs[2]=1 {{6,1}} wnTs[0]=1 {{6,1}, {0,5}} wnTs[1]=0.892561983 wnTs[2]=0
-debugShowCubicIntersection wtTs[0]=0.326064989 {{0,5}, {1,5}, {3,0}, {6,1}} {{1.2971500960309803,3.7865580517965118}} wnTs[0]=0.265062 {{0,3}, {1,6}, {5,0}, {5,1}}
-debugShowCubicLineIntersection wtTs[0]=0.639696212 {{0,5}, {1,5}, {3,0}, {6,1}} {{3.1467223651509295,1.7413110539396279}} wnTs[0]=0.370656 {{5,1}, {0,3}}
-debugShowCubicLineIntersection no intersect {{0,3}, {1,6}, {5,0}, {5,1}} {{6,1}, {0,5}}
-debugShowLineIntersection no intersect {{6,1}, {0,5}} {{5,1}, {0,3}}
-debugShowCubicIntersection no self intersect {{0,3}, {1,6}, {5,0}, {5,1}}
-debugShowCubicLineIntersection wtTs[0]=0 {{0,3}, {1,6}, {5,0}, {5,1}} {{0,3}} wtTs[1]=0.772727273 {{4.4623403456048081,1.2150638617580767}} wtTs[2]=1 {{5,1}} wnTs[0]=1 {{5,1}, {0,3}} wnTs[1]=0.107531931 wnTs[2]=0
-debugShowActiveSpans id=3 (0,5 1,5 3,0 6,1) t=0 (0,5) tEnd=0.181818182 other=4 otherT=1 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,5 1,5 3,0 6,1) t=0.181818182 (0.644628108,4.57024813) tEnd=0.326064989 other=4 otherT=0.892561983 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,5 1,5 3,0 6,1) t=0.326064989 (1.29715014,3.78655815) tEnd=0.639696212 other=1 otherT=0.26506234 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,5 1,5 3,0 6,1) t=0.639696212 (3.14672232,1.74131107) tEnd=1 other=2 otherT=0.370655527 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (6,1 0,5) t=0 (6,1) tEnd=0.892561983 other=3 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (6,1 0,5) t=0.892561983 (0.644628108,4.57024813) tEnd=1 other=3 otherT=0.181818182 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,3 1,6 5,0 5,1) t=0 (0,3) tEnd=0.26506234 other=2 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,3 1,6 5,0 5,1) t=0.26506234 (1.29715014,3.78655815) tEnd=0.772727273 other=3 otherT=0.326064989 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,3 1,6 5,0 5,1) t=0.772727273 (4.46234035,1.21506381) tEnd=1 other=2 otherT=0.107531931 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,1 0,3) t=0 (5,1) tEnd=0.107531931 other=1 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,1 0,3) t=0.107531931 (4.46234035,1.21506381) tEnd=0.370655527 other=1 otherT=0.772727273 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,1 0,3) t=0.370655527 (3.14672232,1.74131107) tEnd=1 other=3 otherT=0.639696212 otherIndex=3 windSum=? windValue=1 oppValue=0
-findTop debugShowSort contourWinding=0 oppContourWinding=0 sign=1
-debugShowSort [0] {{0,3}, {1,6}, {5,0}, {5,1}} tStart=1 tEnd=0.772727273 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [1] {{5,1}, {0,3}} tStart=0 tEnd=0.107531931 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-markWinding id=1 (0,3 1,6 5,0 5,1) t=0.772727273 [2] (4.46234035,1.21506381) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=2 (5,1 0,3) t=0 [0] (5,1) tEnd=0.107531931 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=1 (0,3 1,6 5,0 5,1) t=0.772727273 [2] (4.46234035,1.21506381) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-activeOp op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-findNextOp simple
-markDoneBinary id=1 (0,3 1,6 5,0 5,1) t=0.772727273 [2] (4.46234035,1.21506381) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-bridgeOp current id=1 from=(4.46234035,1.21506381) to=(5,1)
-path.moveTo(4.46234035,1.21506381);
-path.cubicTo(4.79338837,0.90702486, 5,0.772727251, 5,1);
-findNextOp debugShowSort contourWinding=0 oppContourWinding=0 sign=1
-debugShowSort [0] {{5,1}, {0,3}} tStart=0.107531931 tEnd=0 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [1] {{0,3}, {1,6}, {5,0}, {5,1}} tStart=0.772727273 tEnd=1 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [2] {{5,1}, {0,3}} tStart=0.107531931 tEnd=0.370655527 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [3] {{0,3}, {1,6}, {5,0}, {5,1}} tStart=0.772727273 tEnd=0.26506234 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=0
-findNextOp firstIndex=[0] sign=1
-activeOp op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-activeOp op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-markWinding id=2 (5,1 0,3) t=0.107531931 [1] (4.46234035,1.21506381) tEnd=0.370655527 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=2
-activeOp op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-markWinding id=1 (0,3 1,6 5,0 5,1) t=0.26506234 [1] (1.29715014,3.78655815) tEnd=0.772727273 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=1
-markDoneBinary id=2 (5,1 0,3) t=0 [0] (5,1) tEnd=0.107531931 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-findNextOp from:[2] to:[1] start=2 end=1
-bridgeOp current id=2 from=(5,1) to=(4.46234035,1.21506381)
-path.lineTo(4.46234035,1.21506381);
-path.close();
-debugShowActiveSpans id=3 (0,5 1,5 3,0 6,1) t=0 (0,5) tEnd=0.181818182 other=4 otherT=1 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,5 1,5 3,0 6,1) t=0.181818182 (0.644628108,4.57024813) tEnd=0.326064989 other=4 otherT=0.892561983 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,5 1,5 3,0 6,1) t=0.326064989 (1.29715014,3.78655815) tEnd=0.639696212 other=1 otherT=0.26506234 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (0,5 1,5 3,0 6,1) t=0.639696212 (3.14672232,1.74131107) tEnd=1 other=2 otherT=0.370655527 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (6,1 0,5) t=0 (6,1) tEnd=0.892561983 other=3 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (6,1 0,5) t=0.892561983 (0.644628108,4.57024813) tEnd=1 other=3 otherT=0.181818182 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,3 1,6 5,0 5,1) t=0 (0,3) tEnd=0.26506234 other=2 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,3 1,6 5,0 5,1) t=0.26506234 (1.29715014,3.78655815) tEnd=0.772727273 other=3 otherT=0.326064989 otherIndex=2 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,1 0,3) t=0.107531931 (4.46234035,1.21506381) tEnd=0.370655527 other=1 otherT=0.772727273 otherIndex=2 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,1 0,3) t=0.370655527 (3.14672232,1.74131107) tEnd=1 other=3 otherT=0.639696212 otherIndex=3 windSum=? windValue=1 oppValue=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-findNextOp debugShowSort contourWinding=1 oppContourWinding=0 sign=1
-debugShowSort [3] {{0,3}, {1,6}, {5,0}, {5,1}} tStart=0.772727273 tEnd=0.26506234 sign=1 windValue=1 windSum=1 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [0] {{5,1}, {0,3}} tStart=0.107531931 tEnd=0 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [1] {{0,3}, {1,6}, {5,0}, {5,1}} tStart=0.772727273 tEnd=1 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [2] {{5,1}, {0,3}} tStart=0.107531931 tEnd=0.370655527 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=0 tiny=0 opp=0
-findNextOp firstIndex=[3] sign=1
-activeOp op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-activeOp op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-activeOp op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-markDoneBinary id=1 (0,3 1,6 5,0 5,1) t=0.26506234 [1] (1.29715014,3.78655815) tEnd=0.772727273 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-findNextOp from:[1] to:[2] start=1 end=2
-bridgeOp current id=1 from=(1.29715014,3.78655815) to=(4.46234035,1.21506381)
-path.moveTo(1.29715014,3.78655815);
-path.cubicTo(2.36251926,3.45810199, 3.72286963,1.90313876, 4.46234035,1.21506381);
-findNextOp debugShowSort contourWinding=1 oppContourWinding=0 sign=1
-debugShowSort [0] {{5,1}, {0,3}} tStart=0.370655527 tEnd=0.107531931 sign=1 windValue=1 windSum=1 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] {{0,5}, {1,5}, {3,0}, {6,1}} tStart=0.639696212 tEnd=1 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=1
-debugShowSort [2] {{5,1}, {0,3}} tStart=0.370655527 tEnd=1 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [3] {{0,5}, {1,5}, {3,0}, {6,1}} tStart=0.639696212 tEnd=0.326064989 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=1
-findNextOp firstIndex=[0] sign=1
-activeOp op=diff miFrom=0 miTo=0 suFrom=0 suTo=1 result=0
-markDoneBinary id=3 (0,5 1,5 3,0 6,1) t=0.639696212 [3] (3.14672232,1.74131107) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markDoneBinary id=4 (6,1 0,5) t=0 [0] (6,1) tEnd=0.892561983 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=4
-activeOp op=diff miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=2 (5,1 0,3) t=0.370655527 [2] (3.14672232,1.74131107) tEnd=1 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1
-markDoneBinary id=1 (0,3 1,6 5,0 5,1) t=0 [0] (0,3) tEnd=0.26506234 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
-markWinding id=3 (0,5 1,5 3,0 6,1) t=0.326064989 [2] (1.29715014,3.78655815) tEnd=0.639696212 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-markDoneBinary id=2 (5,1 0,3) t=0.107531931 [1] (4.46234035,1.21506381) tEnd=0.370655527 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-findNextOp from:[2] to:[3] start=3 end=2
-bridgeOp current id=2 from=(4.46234035,1.21506381) to=(3.14672232,1.74131107)
-findNextOp debugShowSort contourWinding=0 oppContourWinding=1 sign=-1
-debugShowSort [1] {{0,5}, {1,5}, {3,0}, {6,1}} tStart=0.326064989 tEnd=0.639696212 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [2] {{0,3}, {1,6}, {5,0}, {5,1}} tStart=0.26506234 tEnd=0 sign=1 windValue=1 windSum=1 1->0 (max=1) done=1 tiny=0 opp=1
-debugShowSort [3] {{0,5}, {1,5}, {3,0}, {6,1}} tStart=0.326064989 tEnd=0.181818182 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [0] {{0,3}, {1,6}, {5,0}, {5,1}} tStart=0.26506234 tEnd=0.772727273 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=1
-findNextOp firstIndex=[1] sign=-1
-activeOp op=diff miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-markDoneBinary id=3 (0,5 1,5 3,0 6,1) t=0.181818182 [1] (0.644628108,4.57024813) tEnd=0.326064989 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-activeOp op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-markDoneBinary id=3 (0,5 1,5 3,0 6,1) t=0.326064989 [2] (1.29715014,3.78655815) tEnd=0.639696212 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1
-findNextOp from:[3] to:[1] start=1 end=2
-bridgeOp current id=3 from=(3.14672232,1.74131107) to=(1.29715014,3.78655815)
-path.lineTo(3.14672232,1.74131107);
-path.cubicTo(2.43183374,2.33584237, 1.81530964,3.13070869, 1.29715014,3.78655815);
-path.close();
-findChaseOp debugShowSort contourWinding=1 oppContourWinding=0 sign=1
-debugShowSort [0] {{6,1}, {0,5}} tStart=0.892561983 tEnd=0 sign=1 windValue=1 windSum=1 1->0 (max=1) done=1 tiny=0 opp=0
-debugShowSort [1] {{0,5}, {1,5}, {3,0}, {6,1}} tStart=0.181818182 tEnd=0.326064989 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=0
-debugShowSort [2] {{6,1}, {0,5}} tStart=0.892561983 tEnd=1 sign=-1 windValue=1 windSum=? 1->2 (max=2) done=0 tiny=0 opp=0
-debugShowSort [3] {{0,5}, {1,5}, {3,0}, {6,1}} tStart=0.181818182 tEnd=0 sign=1 windValue=1 windSum=? 2->1 (max=2) done=0 tiny=0 opp=0
-findChaseOp debugShowSort contourWinding=1 oppContourWinding=0 sign=1
-debugShowSort [0] {{6,1}, {0,5}} tStart=0.892561983 tEnd=0 sign=1 windValue=1 windSum=1 1->0 (max=1) done=1 tiny=0 opp=0
-debugShowSort [1] {{0,5}, {1,5}, {3,0}, {6,1}} tStart=0.181818182 tEnd=0.326064989 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=0
-debugShowSort [2] {{6,1}, {0,5}} tStart=0.892561983 tEnd=1 sign=-1 windValue=1 windSum=? 1->2 (max=2) done=0 tiny=0 opp=0
-debugShowSort [3] {{0,5}, {1,5}, {3,0}, {6,1}} tStart=0.181818182 tEnd=0 sign=1 windValue=1 windSum=? 2->1 (max=2) done=0 tiny=0 opp=0
-markWinding id=4 (6,1 0,5) t=0.892561983 [1] (0.644628108,4.57024813) tEnd=1 newWindSum=2 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=3 (0,5 1,5 3,0 6,1) t=0 [0] (0,5) tEnd=0.181818182 newWindSum=2 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=3 (0,5 1,5 3,0 6,1) t=0 [0] (0,5) tEnd=0.181818182 newWindSum=2 newOppSum=0 oppSum=0 windSum=2 windValue=1
-debugShowActiveSpans id=3 (0,5 1,5 3,0 6,1) t=0 (0,5) tEnd=0.181818182 other=4 otherT=1 otherIndex=2 windSum=2 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (6,1 0,5) t=0.892561983 (0.644628108,4.57024813) tEnd=1 other=3 otherT=0.181818182 otherIndex=1 windSum=2 windValue=1 oppValue=0
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=1 result=0
-markDoneBinary id=4 (6,1 0,5) t=0.892561983 [1] (0.644628108,4.57024813) tEnd=1 newWindSum=2 newOppSum=0 oppSum=0 windSum=2 windValue=1
-markDoneBinary id=3 (0,5 1,5 3,0 6,1) t=0 [0] (0,5) tEnd=0.181818182 newWindSum=2 newOppSum=0 oppSum=0 windSum=2 windValue=1
-assemble
-assemble contour start=(4.46234035,1.21506381) end=(4.46234035,1.21506381)
-path.moveTo(4.46234035,1.21506381);
-path.cubicTo(4.79338837,0.90702486, 5,0.772727251, 5,1);
-path.lineTo(4.46234035,1.21506381);
-path.close();
-assemble contour start=(1.29715014,3.78655815) end=(1.29715014,3.78655815)
-</div>
-
-<div id="cubicOp51d">
- SimplifyNew_Test [cubicOp51d]
-{{0,3}, {1,2}, {4,1}, {6,0}},
-{{6,0}, {0,3}},
-op difference
-{{1,4}, {0,6}, {3,0}, {2,1}},
-{{2,1}, {1,4}},
-debugShowCubicIntersection no self intersect {{0,3}, {1,2}, {4,1}, {6,0}}
-debugShowCubicLineIntersection wtTs[0]=0 {{0,3}, {1,2}, {4,1}, {6,0}} {{0,3}} wtTs[1]=1 {{6,0}} wnTs[0]=1 {{6,0}, {0,3}} wnTs[1]=0
-debugShowCubicIntersection wtTs[0]=0.397354824 {{0,3}, {1,2}, {4,1}, {6,0}} {{1.9511935265302276,1.8079355291007386}} wnTs[0]=0.661665 {{1,4}, {0,6}, {3,0}, {2,1}}
-debugShowCubicLineIntersection wtTs[0]=0.355273081 {{0,3}, {1,2}, {4,1}, {6,0}} {{1.6886064138367243,1.9341807584898274}} wnTs[0]=0.311394 {{2,1}, {1,4}}
-debugShowCubicLineIntersection wtTs[0]=0.6185225 {{1,4}, {0,6}, {3,0}, {2,1}} {{1.8422478636338226,2.0788760681830887}} wnTs[0]=0.692959 {{6,0}, {0,3}}
-debugShowLineIntersection wtTs[0]=0.733333333 {{6,0}, {0,3}} {{1.6000000000000003,2.1999999999999997}} wnTs[0]=0.4 {{2,1}, {1,4}}
-debugShowCubicIntersection no self intersect {{1,4}, {0,6}, {3,0}, {2,1}}
-debugShowCubicLineIntersection wtTs[0]=0 {{1,4}, {0,6}, {3,0}, {2,1}} {{1,4}} wtTs[1]=0.333333333 {{1.0370370370370368,3.8888888888888897}} wtTs[2]=1 {{2,1}} wnTs[0]=1 {{2,1}, {1,4}} wnTs[1]=0.962962963 wnTs[2]=0
-debugShowActiveSpans id=1 (0,3 1,2 4,1 6,0) t=0 (0,3) tEnd=0.355273081 other=2 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,3 1,2 4,1 6,0) t=0.355273081 (1.68860638,1.93418074) tEnd=0.397354824 other=4 otherT=0.311393586 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,3 1,2 4,1 6,0) t=0.397354824 (1.95119357,1.80793548) tEnd=1 other=3 otherT=0.66166507 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (6,0 0,3) t=0 (6,0) tEnd=0.692958689 other=1 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (6,0 0,3) t=0.692958689 (1.84224784,2.07887602) tEnd=0.733333333 other=3 otherT=0.6185225 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (6,0 0,3) t=0.733333333 (1.60000002,2.20000005) tEnd=1 other=4 otherT=0.4 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,4 0,6 3,0 2,1) t=0 (1,4) tEnd=0.333333333 other=4 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,4 0,6 3,0 2,1) t=0.333333333 (1.03703701,3.88888884) tEnd=0.6185225 other=4 otherT=0.962962963 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,4 0,6 3,0 2,1) t=0.6185225 (1.84224784,2.07887602) tEnd=0.66166507 other=2 otherT=0.692958689 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,4 0,6 3,0 2,1) t=0.66166507 (1.95119357,1.80793548) tEnd=1 other=1 otherT=0.397354824 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (2,1 1,4) t=0 (2,1) tEnd=0.311393586 other=3 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (2,1 1,4) t=0.311393586 (1.68860638,1.93418074) tEnd=0.4 other=1 otherT=0.355273081 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (2,1 1,4) t=0.4 (1.60000002,2.20000005) tEnd=0.962962963 other=2 otherT=0.733333333 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (2,1 1,4) t=0.962962963 (1.03703701,3.88888884) tEnd=1 other=3 otherT=0.333333333 otherIndex=1 windSum=? windValue=1 oppValue=0
-findTop debugShowSort contourWinding=0 oppContourWinding=0 sign=1
-debugShowSort [0] {{0,3}, {1,2}, {4,1}, {6,0}} tStart=1 tEnd=0.397354824 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [1] {{6,0}, {0,3}} tStart=0 tEnd=0.692958689 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-findTop swap
-markWinding id=1 (0,3 1,2 4,1 6,0) t=0.397354824 [2] (1.95119357,1.80793548) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=1 (0,3 1,2 4,1 6,0) t=0.397354824 [2] (1.95119357,1.80793548) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-markWinding id=2 (6,0 0,3) t=0 [0] (6,0) tEnd=0.692958689 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-activeOp op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-findNextOp debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [0] {{0,3}, {1,2}, {4,1}, {6,0}} tStart=0.397354824 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] {{1,4}, {0,6}, {3,0}, {2,1}} tStart=0.66166507 tEnd=1 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=1
-debugShowSort [2] {{0,3}, {1,2}, {4,1}, {6,0}} tStart=0.397354824 tEnd=0.355273081 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [3] {{1,4}, {0,6}, {3,0}, {2,1}} tStart=0.66166507 tEnd=0.6185225 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=1
-findNextOp firstIndex=[0] sign=-1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-markWinding id=3 (1,4 0,6 3,0 2,1) t=0.66166507 [3] (1.95119357,1.80793548) tEnd=1 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1
-markWinding id=4 (2,1 1,4) t=0 [0] (2,1) tEnd=0.311393586 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=4
-activeOp op=diff miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
-markDoneBinary id=1 (0,3 1,2 4,1 6,0) t=0.355273081 [1] (1.68860638,1.93418074) tEnd=0.397354824 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=1
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-markDoneBinary id=3 (1,4 0,6 3,0 2,1) t=0.6185225 [2] (1.84224784,2.07887602) tEnd=0.66166507 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-markDoneBinary id=1 (0,3 1,2 4,1 6,0) t=0.397354824 [2] (1.95119357,1.80793548) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-findNextOp from:[1] to:[3] start=3 end=4
-bridgeOp current id=1 from=(6,0) to=(1.95119357,1.80793548)
-path.moveTo(6,0);
-path.cubicTo(4.79470968,0.602645159, 3.22623801,1.20529044, 1.95119357,1.80793548);
-findNextOp simple
-markDoneBinary id=3 (1,4 0,6 3,0 2,1) t=0.66166507 [3] (1.95119357,1.80793548) tEnd=1 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1
-bridgeOp current id=3 from=(1.95119357,1.80793548) to=(2,1)
-path.cubicTo(2.21878767,1.12462389, 2.33833504,0.661665022, 2,1);
-findNextOp debugShowSort contourWinding=1 oppContourWinding=1 sign=1
-debugShowSort [1] {{2,1}, {1,4}} tStart=0.311393586 tEnd=0 sign=1 windValue=1 windSum=1 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [2] {{0,3}, {1,2}, {4,1}, {6,0}} tStart=0.355273081 tEnd=0 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=1
-debugShowSort [3] {{2,1}, {1,4}} tStart=0.311393586 tEnd=0.4 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [0] {{0,3}, {1,2}, {4,1}, {6,0}} tStart=0.355273081 tEnd=0.397354824 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=1
-findNextOp firstIndex=[1] sign=1
-activeOp op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-markWinding id=1 (0,3 1,2 4,1 6,0) t=0 [0] (0,3) tEnd=0.355273081 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=2 (6,0 0,3) t=0.733333333 [2] (1.60000002,2.20000005) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=2
-activeOp op=diff miFrom=0 miTo=0 suFrom=0 suTo=1 result=0
-markDoneBinary id=4 (2,1 1,4) t=0.311393586 [1] (1.68860638,1.93418074) tEnd=0.4 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=4
-activeOp op=diff miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=4 (2,1 1,4) t=0 [0] (2,1) tEnd=0.311393586 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1
-findNextOp from:[4] to:[1] start=1 end=0
-bridgeOp current id=4 from=(2,1) to=(1.68860638,1.93418074)
-findNextOp simple
-markDoneBinary id=1 (0,3 1,2 4,1 6,0) t=0 [0] (0,3) tEnd=0.355273081 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-bridgeOp current id=1 from=(1.68860638,1.93418074) to=(0,3)
-path.lineTo(1.68860638,1.93418074);
-path.cubicTo(0.962984085,2.28945374, 0.355273068,2.64472699, 0,3);
-findNextOp debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [2] {{6,0}, {0,3}} tStart=0.733333333 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [3] {{2,1}, {1,4}} tStart=0.4 tEnd=0.962962963 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=1
-debugShowSort [0] {{6,0}, {0,3}} tStart=0.733333333 tEnd=0.692958689 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] {{2,1}, {1,4}} tStart=0.4 tEnd=0.311393586 sign=1 windValue=1 windSum=1 1->0 (max=1) done=1 tiny=0 opp=1
-findNextOp firstIndex=[2] sign=-1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-markWinding id=4 (2,1 1,4) t=0.4 [2] (1.60000002,2.20000005) tEnd=0.962962963 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=4
-activeOp op=diff miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
-markDoneBinary id=2 (6,0 0,3) t=0.692958689 [1] (1.84224784,2.07887602) tEnd=0.733333333 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=2
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-markDoneBinary id=2 (6,0 0,3) t=0.733333333 [2] (1.60000002,2.20000005) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-findNextOp from:[2] to:[4] start=2 end=3
-bridgeOp current id=2 from=(0,3) to=(1.60000002,2.20000005)
-findNextOp debugShowSort contourWinding=1 oppContourWinding=1 sign=1
-debugShowSort [1] {{2,1}, {1,4}} tStart=0.962962963 tEnd=0.4 sign=1 windValue=1 windSum=1 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [2] {{1,4}, {0,6}, {3,0}, {2,1}} tStart=0.333333333 tEnd=0 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [3] {{2,1}, {1,4}} tStart=0.962962963 tEnd=1 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [0] {{1,4}, {0,6}, {3,0}, {2,1}} tStart=0.333333333 tEnd=0.6185225 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=0
-findNextOp firstIndex=[1] sign=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-markWinding id=3 (1,4 0,6 3,0 2,1) t=0 [0] (1,4) tEnd=0.333333333 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-markWinding id=4 (2,1 1,4) t=0.962962963 [3] (1.03703701,3.88888884) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=4
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-markWinding id=3 (1,4 0,6 3,0 2,1) t=0.333333333 [1] (1.03703701,3.88888884) tEnd=0.6185225 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-markDoneBinary id=4 (2,1 1,4) t=0.4 [2] (1.60000002,2.20000005) tEnd=0.962962963 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1
-findNextOp from:[4] to:[3] start=1 end=0
-bridgeOp current id=4 from=(1.60000002,2.20000005) to=(1.03703701,3.88888884)
-path.lineTo(1.60000002,2.20000005);
-findNextOp simple
-markDoneBinary id=3 (1,4 0,6 3,0 2,1) t=0 [0] (1,4) tEnd=0.333333333 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1
-bridgeOp current id=3 from=(1.03703701,3.88888884) to=(1,4)
-path.lineTo(1.03703701,3.88888884);
-path.cubicTo(0.777777791,4.44444466, 0.666666687,4.66666651, 1,4);
-findNextOp debugShowSort contourWinding=-1 oppContourWinding=1 sign=-1
-debugShowSort [3] {{2,1}, {1,4}} tStart=0.962962963 tEnd=1 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [0] {{1,4}, {0,6}, {3,0}, {2,1}} tStart=0.333333333 tEnd=0.6185225 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] {{2,1}, {1,4}} tStart=0.962962963 tEnd=0.4 sign=1 windValue=1 windSum=1 1->0 (max=1) done=1 tiny=0 opp=0
-debugShowSort [2] {{1,4}, {0,6}, {3,0}, {2,1}} tStart=0.333333333 tEnd=0 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=0
-findNextOp firstIndex=[3] sign=-1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-markDoneBinary id=4 (2,1 1,4) t=0.962962963 [3] (1.03703701,3.88888884) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1
-findNextOp from:[4] to:[3] start=1 end=2
-bridgeOp current id=4 from=(1,4) to=(1.03703701,3.88888884)
-findNextOp debugShowSort contourWinding=1 oppContourWinding=1 sign=1
-debugShowSort [3] {{1,4}, {0,6}, {3,0}, {2,1}} tStart=0.6185225 tEnd=0.333333333 sign=1 windValue=1 windSum=1 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [0] {{6,0}, {0,3}} tStart=0.692958689 tEnd=0 sign=1 windValue=1 windSum=1 1->0 (max=1) done=0 tiny=0 opp=1
-debugShowSort [1] {{1,4}, {0,6}, {3,0}, {2,1}} tStart=0.6185225 tEnd=0.66166507 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=0
-debugShowSort [2] {{6,0}, {0,3}} tStart=0.692958689 tEnd=0.733333333 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=1
-findNextOp firstIndex=[3] sign=1
-activeOp op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-activeOp op=diff miFrom=0 miTo=0 suFrom=0 suTo=1 result=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=3 (1,4 0,6 3,0 2,1) t=0.333333333 [1] (1.03703701,3.88888884) tEnd=0.6185225 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1
-findNextOp from:[3] to:[2] start=1 end=0
-bridgeOp current id=3 from=(1.03703701,3.88888884) to=(1.84224784,2.07887602)
-path.lineTo(1.03703701,3.88888884);
-path.cubicTo(1.25885081,3.41357374, 1.58910847,2.69425988, 1.84224784,2.07887602);
-findNextOp simple
-markDoneBinary id=2 (6,0 0,3) t=0 [0] (6,0) tEnd=0.692958689 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-bridgeOp current id=2 from=(1.84224784,2.07887602) to=(6,0)
-path.lineTo(6,0);
-path.close();
-assemble
-assemble contour start=(6,0) end=(6,0)
-</div>
-
-<div id="cubicOp51da">
-$1 = {{x = 1.9511935265302274, y = 1.8079355291007388}, {x = 3.2262380859340407, y = 1.2052903527338259}, {x = 4.794709647266175, y = 0.60264517636691295}, {x = 6, y = 0}}
-(gdb) p startEdge
-$2 = {{x = 1.9511935265302274, y = 1.8079355291007388}, {x = 2.5538387028971403, y = 3.0829800885045522}}
-(gdb) p endEdge
-$3 = {{x = 6, y = 0}, {x = 5.3973548236330871, y = -1.205290352733825}}
-</div>
-
-<div id="cubicOp52da">
-$3 = {{fX = 2.625, fY = 2.25}, {fX = 2.25, fY = 1.25}, {fX = 2, fY = 0.5}, {fX = 2, fY = 1}}
-</div>
-
-<div id="cubicOp52db">
-$3 = {{x = 1.9511935265302274, y = 1.8079355291007388}, {x = 3.2262380859340407, y = 1.2052903527338259}, {x = 4.794709647266175, y = 0.60264517636691295}, {x = 6, y = 0}}
-(gdb) p startEdge
-$4 = {{x = 1.9511935265302274, y = 1.8079355291007388}, {x = 3.7591290556309662, y = 5.8567420025705115}}
-(gdb) p endEdge
-$5 = {{x = 6, y = 0}, {x = 7.8079355291007388, y = 4.0488064734697726}}
-</div>
-
-<div id="cubicOp53d">
- SimplifyNew_Test [cubicOp53d]
-{{0,3}, {1,2}, {5,3}, {2,1}},
-{{2,1}, {0,3}},
-op difference
-{{3,5}, {1,2}, {3,0}, {2,1}},
-{{2,1}, {3,5}},
-debugShowCubicIntersection no self intersect {{3,5}, {1,2}, {3,0}, {2,1}}
-debugShowCubicLineIntersection wtTs[0]=0 {{3,5}, {1,2}, {3,0}, {2,1}} {{3,5}} wtTs[1]=0.5 {{2.125,1.5}} wtTs[2]=1 {{2,1}} wnTs[0]=1 {{2,1}, {3,5}} wnTs[1]=0.125 wnTs[2]=0
-debugShowCubicIntersection wtTs[0]=0.32953467 {{3,5}, {1,2}, {3,0}, {2,1}} {{2.0754128281547217,2.4315376490509659}} wtTs[1]=0.59235675 {{2.2015477442470841,1.1371488033015213}} wtTs[2]=1 {{2,1}} wnTs[0]=0.414081 {{0,3}, {1,2}, {5,3}, {2,1}} wnTs[1]=0.976311205 wnTs[2]=1
-debugShowCubicLineIntersection wtTs[0]=1 {{3,5}, {1,2}, {3,0}, {2,1}} {{2,1}} wnTs[0]=0 {{2,1}, {0,3}}
-debugShowCubicLineIntersection wtTs[0]=0.467845317 {{0,3}, {1,2}, {5,3}, {2,1}} {{2.3494328385891112,2.3977313543564462}} wtTs[1]=1 {{2,1}} wnTs[0]=0.349433 {{2,1}, {3,5}} wnTs[1]=0
-debugShowLineIntersection wtTs[0]=-0 {{2,1}, {3,5}} {{2,1}} wnTs[0]=0 {{2,1}, {0,3}}
-debugShowCubicIntersection no self intersect {{0,3}, {1,2}, {5,3}, {2,1}}
-debugShowCubicLineIntersection wtTs[0]=0 {{0,3}, {1,2}, {5,3}, {2,1}} {{0,3}} wtTs[1]=1 {{2,1}} wnTs[0]=1 {{2,1}, {0,3}} wnTs[1]=0
-debugShowActiveSpans id=3 (3,5 1,2 3,0 2,1) t=0 (3,5) tEnd=0.32953467 other=4 otherT=1 otherIndex=5 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (3,5 1,2 3,0 2,1) t=0.32953467 (2.07541275,2.43153763) tEnd=0.5 other=1 otherT=0.414080655 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (3,5 1,2 3,0 2,1) t=0.5 (2.125,1.5) tEnd=0.59235675 other=4 otherT=0.125 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (3,5 1,2 3,0 2,1) t=0.59235675 (2.20154786,1.13714886) tEnd=1 other=1 otherT=0.976311205 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (2,1 3,5) t=0 (2,1) tEnd=0.125 other=3 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (2,1 3,5) t=0 (2,1) tEnd=0.125 other=1 otherT=1 otherIndex=5 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (2,1 3,5) t=-0 (2,1) tEnd=0.125 other=2 otherT=0 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (2,1 3,5) t=0.125 (2.125,1.5) tEnd=0.349432839 other=3 otherT=0.5 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (2,1 3,5) t=0.349432839 (2.34943295,2.3977313) tEnd=1 other=1 otherT=0.467845317 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,3 1,2 5,3 2,1) t=0 (0,3) tEnd=0.414080655 other=2 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,3 1,2 5,3 2,1) t=0.414080655 (2.07541275,2.43153763) tEnd=0.467845317 other=3 otherT=0.32953467 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,3 1,2 5,3 2,1) t=0.467845317 (2.34943295,2.3977313) tEnd=0.976311205 other=4 otherT=0.349432839 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,3 1,2 5,3 2,1) t=0.976311205 (2.20154786,1.13714886) tEnd=1 other=3 otherT=0.59235675 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (2,1 0,3) t=0 (2,1) tEnd=1 other=3 otherT=1 otherIndex=6 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (2,1 0,3) t=0 (2,1) tEnd=1 other=4 otherT=-0 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (2,1 0,3) t=0 (2,1) tEnd=1 other=1 otherT=1 otherIndex=6 windSum=? windValue=1 oppValue=0
-findTop debugShowSort contourWinding=0 oppContourWinding=0 sign=1
-debugShowSort [0] {{3,5}, {1,2}, {3,0}, {2,1}} tStart=1 tEnd=0.59235675 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [1] {{2,1}, {0,3}} tStart=0 tEnd=1 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=1
-debugShowSort [2] {{2,1}, {3,5}} tStart=0 tEnd=0.125 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [3] {{0,3}, {1,2}, {5,3}, {2,1}} tStart=1 tEnd=0.976311205 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=1
-markWinding id=3 (3,5 1,2 3,0 2,1) t=0.59235675 [3] (2.20154786,1.13714886) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=3 (3,5 1,2 3,0 2,1) t=0.59235675 [3] (2.20154786,1.13714886) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-markDoneBinary id=3 (3,5 1,2 3,0 2,1) t=0.59235675 [3] (2.20154786,1.13714886) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-findChaseOp debugShowSort contourWinding=0 oppContourWinding=0 sign=1
-debugShowSort [0] {{3,5}, {1,2}, {3,0}, {2,1}} tStart=1 tEnd=0.59235675 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [1] {{2,1}, {0,3}} tStart=0 tEnd=1 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=1
-debugShowSort [2] {{2,1}, {3,5}} tStart=0 tEnd=0.125 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [3] {{0,3}, {1,2}, {5,3}, {2,1}} tStart=1 tEnd=0.976311205 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=1
-findChaseOp debugShowSort contourWinding=0 oppContourWinding=0 sign=1
-debugShowSort [0] {{3,5}, {1,2}, {3,0}, {2,1}} tStart=1 tEnd=0.59235675 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [1] {{2,1}, {0,3}} tStart=0 tEnd=1 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=1
-debugShowSort [2] {{2,1}, {3,5}} tStart=0 tEnd=0.125 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [3] {{0,3}, {1,2}, {5,3}, {2,1}} tStart=1 tEnd=0.976311205 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=1
-markWinding id=2 (2,1 0,3) t=0 [0] (2,1) tEnd=0 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1
-markWinding id=2 (2,1 0,3) t=0 [1] (2,1) tEnd=0 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1
-markWinding id=2 (2,1 0,3) t=0 [2] (2,1) tEnd=1 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1
-markWinding id=1 (0,3 1,2 5,3 2,1) t=0 [0] (0,3) tEnd=0.414080655 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1
-markWinding id=4 (2,1 3,5) t=0 [0] (2,1) tEnd=0 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-markWinding id=4 (2,1 3,5) t=0 [1] (2,1) tEnd=-0 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-markWinding id=4 (2,1 3,5) t=-0 [2] (2,1) tEnd=0.125 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-markWinding id=1 (0,3 1,2 5,3 2,1) t=0.976311205 [3] (2.20154786,1.13714886) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-debugShowActiveSpans id=3 (3,5 1,2 3,0 2,1) t=0 (3,5) tEnd=0.32953467 other=4 otherT=1 otherIndex=5 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (3,5 1,2 3,0 2,1) t=0.32953467 (2.07541275,2.43153763) tEnd=0.5 other=1 otherT=0.414080655 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (3,5 1,2 3,0 2,1) t=0.5 (2.125,1.5) tEnd=0.59235675 other=4 otherT=0.125 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (2,1 3,5) t=0 (2,1) tEnd=0.125 other=3 otherT=1 otherIndex=4 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (2,1 3,5) t=0 (2,1) tEnd=0.125 other=1 otherT=1 otherIndex=5 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (2,1 3,5) t=-0 (2,1) tEnd=0.125 other=2 otherT=0 otherIndex=1 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (2,1 3,5) t=0.125 (2.125,1.5) tEnd=0.349432839 other=3 otherT=0.5 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (2,1 3,5) t=0.349432839 (2.34943295,2.3977313) tEnd=1 other=1 otherT=0.467845317 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,3 1,2 5,3 2,1) t=0 (0,3) tEnd=0.414080655 other=2 otherT=1 otherIndex=3 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,3 1,2 5,3 2,1) t=0.414080655 (2.07541275,2.43153763) tEnd=0.467845317 other=3 otherT=0.32953467 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,3 1,2 5,3 2,1) t=0.467845317 (2.34943295,2.3977313) tEnd=0.976311205 other=4 otherT=0.349432839 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,3 1,2 5,3 2,1) t=0.976311205 (2.20154786,1.13714886) tEnd=1 other=3 otherT=0.59235675 otherIndex=3 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (2,1 0,3) t=0 (2,1) tEnd=1 other=3 otherT=1 otherIndex=6 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (2,1 0,3) t=0 (2,1) tEnd=1 other=4 otherT=-0 otherIndex=2 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (2,1 0,3) t=0 (2,1) tEnd=1 other=1 otherT=1 otherIndex=6 windSum=1 windValue=1 oppValue=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=2 (2,1 0,3) t=0 [0] (2,1) tEnd=0 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1
-markDoneBinary id=2 (2,1 0,3) t=0 [1] (2,1) tEnd=0 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1
-markDoneBinary id=2 (2,1 0,3) t=0 [2] (2,1) tEnd=1 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1
-markDoneBinary id=1 (0,3 1,2 5,3 2,1) t=0 [0] (0,3) tEnd=0.414080655 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1
-findChaseOp debugShowSort contourWinding=? oppContourWinding=? sign=-1
-debugShowSort [0] {{0,3}, {1,2}, {5,3}, {2,1}} tStart=0.414080655 tEnd=0.467845317 sign=-1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=0
-debugShowSort [1] {{3,5}, {1,2}, {3,0}, {2,1}} tStart=0.32953467 tEnd=0.5 sign=-1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=1
-debugShowSort [2] {{0,3}, {1,2}, {5,3}, {2,1}} tStart=0.414080655 tEnd=0 sign=1 windValue=1 windSum=1 ?->? (max=?) done=1 tiny=0 opp=0
-debugShowSort [3] {{3,5}, {1,2}, {3,0}, {2,1}} tStart=0.32953467 tEnd=0 sign=1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=1
-findChaseOp debugShowSort contourWinding=1 oppContourWinding=-1 sign=1
-debugShowSort [2] {{0,3}, {1,2}, {5,3}, {2,1}} tStart=0.414080655 tEnd=0 sign=1 windValue=1 windSum=1 1->0 (max=1) done=1 tiny=0 opp=0
-debugShowSort [3] {{3,5}, {1,2}, {3,0}, {2,1}} tStart=0.32953467 tEnd=0 sign=1 windValue=1 windSum=? -1->-2 (max=-2) done=0 tiny=0 opp=1
-debugShowSort [0] {{0,3}, {1,2}, {5,3}, {2,1}} tStart=0.414080655 tEnd=0.467845317 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] {{3,5}, {1,2}, {3,0}, {2,1}} tStart=0.32953467 tEnd=0.5 sign=-1 windValue=1 windSum=? -2->-1 (max=-2) done=0 tiny=0 opp=1
-markWinding id=3 (3,5 1,2 3,0 2,1) t=0 [0] (3,5) tEnd=0.32953467 newWindSum=-2 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=4 (2,1 3,5) t=0.349432839 [4] (2.34943295,2.3977313) tEnd=1 newWindSum=-2 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=1 (0,3 1,2 5,3 2,1) t=0.414080655 [1] (2.07541275,2.43153763) tEnd=0.467845317 newWindSum=1 newOppSum=-2 oppSum=? windSum=? windValue=1
-markWinding id=3 (3,5 1,2 3,0 2,1) t=0.32953467 [1] (2.07541275,2.43153763) tEnd=0.5 newWindSum=-2 newOppSum=1 oppSum=? windSum=? windValue=1
-debugShowActiveSpans id=3 (3,5 1,2 3,0 2,1) t=0 (3,5) tEnd=0.32953467 other=4 otherT=1 otherIndex=5 windSum=-2 windValue=1 oppValue=0
-debugShowActiveSpans id=3 (3,5 1,2 3,0 2,1) t=0.32953467 (2.07541275,2.43153763) tEnd=0.5 other=1 otherT=0.414080655 otherIndex=1 windSum=-2 windValue=1 oppValue=0
-debugShowActiveSpans id=3 (3,5 1,2 3,0 2,1) t=0.5 (2.125,1.5) tEnd=0.59235675 other=4 otherT=0.125 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (2,1 3,5) t=0 (2,1) tEnd=0.125 other=3 otherT=1 otherIndex=4 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (2,1 3,5) t=0 (2,1) tEnd=0.125 other=1 otherT=1 otherIndex=5 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (2,1 3,5) t=-0 (2,1) tEnd=0.125 other=2 otherT=0 otherIndex=1 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (2,1 3,5) t=0.125 (2.125,1.5) tEnd=0.349432839 other=3 otherT=0.5 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (2,1 3,5) t=0.349432839 (2.34943295,2.3977313) tEnd=1 other=1 otherT=0.467845317 otherIndex=2 windSum=-2 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,3 1,2 5,3 2,1) t=0.414080655 (2.07541275,2.43153763) tEnd=0.467845317 other=3 otherT=0.32953467 otherIndex=1 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,3 1,2 5,3 2,1) t=0.467845317 (2.34943295,2.3977313) tEnd=0.976311205 other=4 otherT=0.349432839 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,3 1,2 5,3 2,1) t=0.976311205 (2.20154786,1.13714886) tEnd=1 other=3 otherT=0.59235675 otherIndex=3 windSum=1 windValue=1 oppValue=0
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=1 result=0
-markDoneBinary id=3 (3,5 1,2 3,0 2,1) t=0 [0] (3,5) tEnd=0.32953467 newWindSum=-2 newOppSum=0 oppSum=0 windSum=-2 windValue=1
-markDoneBinary id=4 (2,1 3,5) t=0.349432839 [4] (2.34943295,2.3977313) tEnd=1 newWindSum=-2 newOppSum=0 oppSum=0 windSum=-2 windValue=1
-debugShowActiveSpans id=3 (3,5 1,2 3,0 2,1) t=0.32953467 (2.07541275,2.43153763) tEnd=0.5 other=1 otherT=0.414080655 otherIndex=1 windSum=-2 windValue=1 oppValue=0
-debugShowActiveSpans id=3 (3,5 1,2 3,0 2,1) t=0.5 (2.125,1.5) tEnd=0.59235675 other=4 otherT=0.125 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (2,1 3,5) t=0 (2,1) tEnd=0.125 other=3 otherT=1 otherIndex=4 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (2,1 3,5) t=0 (2,1) tEnd=0.125 other=1 otherT=1 otherIndex=5 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (2,1 3,5) t=-0 (2,1) tEnd=0.125 other=2 otherT=0 otherIndex=1 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (2,1 3,5) t=0.125 (2.125,1.5) tEnd=0.349432839 other=3 otherT=0.5 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,3 1,2 5,3 2,1) t=0.414080655 (2.07541275,2.43153763) tEnd=0.467845317 other=3 otherT=0.32953467 otherIndex=1 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,3 1,2 5,3 2,1) t=0.467845317 (2.34943295,2.3977313) tEnd=0.976311205 other=4 otherT=0.349432839 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,3 1,2 5,3 2,1) t=0.976311205 (2.20154786,1.13714886) tEnd=1 other=3 otherT=0.59235675 otherIndex=3 windSum=1 windValue=1 oppValue=0
-activeOp op=diff miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
-markDoneBinary id=1 (0,3 1,2 5,3 2,1) t=0.414080655 [1] (2.07541275,2.43153763) tEnd=0.467845317 newWindSum=1 newOppSum=-2 oppSum=-2 windSum=1 windValue=1
-debugShowActiveSpans id=3 (3,5 1,2 3,0 2,1) t=0.32953467 (2.07541275,2.43153763) tEnd=0.5 other=1 otherT=0.414080655 otherIndex=1 windSum=-2 windValue=1 oppValue=0
-debugShowActiveSpans id=3 (3,5 1,2 3,0 2,1) t=0.5 (2.125,1.5) tEnd=0.59235675 other=4 otherT=0.125 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (2,1 3,5) t=0 (2,1) tEnd=0.125 other=3 otherT=1 otherIndex=4 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (2,1 3,5) t=0 (2,1) tEnd=0.125 other=1 otherT=1 otherIndex=5 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (2,1 3,5) t=-0 (2,1) tEnd=0.125 other=2 otherT=0 otherIndex=1 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (2,1 3,5) t=0.125 (2.125,1.5) tEnd=0.349432839 other=3 otherT=0.5 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,3 1,2 5,3 2,1) t=0.467845317 (2.34943295,2.3977313) tEnd=0.976311205 other=4 otherT=0.349432839 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,3 1,2 5,3 2,1) t=0.976311205 (2.20154786,1.13714886) tEnd=1 other=3 otherT=0.59235675 otherIndex=3 windSum=1 windValue=1 oppValue=0
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=3 (3,5 1,2 3,0 2,1) t=0.32953467 [1] (2.07541275,2.43153763) tEnd=0.5 newWindSum=-2 newOppSum=1 oppSum=1 windSum=-2 windValue=1
-debugShowActiveSpans id=3 (3,5 1,2 3,0 2,1) t=0.5 (2.125,1.5) tEnd=0.59235675 other=4 otherT=0.125 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (2,1 3,5) t=0 (2,1) tEnd=0.125 other=3 otherT=1 otherIndex=4 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (2,1 3,5) t=0 (2,1) tEnd=0.125 other=1 otherT=1 otherIndex=5 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (2,1 3,5) t=-0 (2,1) tEnd=0.125 other=2 otherT=0 otherIndex=1 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (2,1 3,5) t=0.125 (2.125,1.5) tEnd=0.349432839 other=3 otherT=0.5 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,3 1,2 5,3 2,1) t=0.467845317 (2.34943295,2.3977313) tEnd=0.976311205 other=4 otherT=0.349432839 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,3 1,2 5,3 2,1) t=0.976311205 (2.20154786,1.13714886) tEnd=1 other=3 otherT=0.59235675 otherIndex=3 windSum=1 windValue=1 oppValue=0
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-findNextOp debugShowSort contourWinding=-1 oppContourWinding=1 sign=-1
-debugShowSort [2] {{2,1}, {3,5}} tStart=-0 tEnd=0.125 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [3] {{0,3}, {1,2}, {5,3}, {2,1}} tStart=1 tEnd=0.976311205 sign=1 windValue=1 windSum=1 1->0 (max=1) done=0 tiny=0 opp=1
-debugShowSort [0] {{3,5}, {1,2}, {3,0}, {2,1}} tStart=1 tEnd=0.59235675 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [1] {{2,1}, {0,3}} tStart=0 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=1
-findNextOp firstIndex=[2] sign=-1
-activeOp op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-activeOp op=diff miFrom=0 miTo=0 suFrom=0 suTo=1 result=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=4 (2,1 3,5) t=0 [1] (2,1) tEnd=-0 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1
-markDoneBinary id=4 (2,1 3,5) t=0 [0] (2,1) tEnd=0 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1
-markDoneBinary id=4 (2,1 3,5) t=-0 [2] (2,1) tEnd=0.125 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1
-findNextOp from:[4] to:[1] start=5 end=3
-bridgeOp current id=4 from=(2.125,1.5) to=(2,1)
-findNextOp debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [1] {{0,3}, {1,2}, {5,3}, {2,1}} tStart=0.976311205 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [2] {{3,5}, {1,2}, {3,0}, {2,1}} tStart=0.59235675 tEnd=0.5 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=1
-debugShowSort [3] {{0,3}, {1,2}, {5,3}, {2,1}} tStart=0.976311205 tEnd=0.467845317 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [0] {{3,5}, {1,2}, {3,0}, {2,1}} tStart=0.59235675 tEnd=1 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=1
-findNextOp firstIndex=[1] sign=-1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-markWinding id=3 (3,5 1,2 3,0 2,1) t=0.5 [2] (2.125,1.5) tEnd=0.59235675 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-activeOp op=diff miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
-markDoneBinary id=1 (0,3 1,2 5,3 2,1) t=0.467845317 [2] (2.34943295,2.3977313) tEnd=0.976311205 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=1
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-markDoneBinary id=1 (0,3 1,2 5,3 2,1) t=0.976311205 [3] (2.20154786,1.13714886) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-findNextOp from:[1] to:[3] start=3 end=2
-bridgeOp current id=1 from=(2,1) to=(2.20154786,1.13714886)
-path.moveTo(2.125,1.5);
-path.lineTo(2,1);
-path.cubicTo(2.07106638,1.04737759, 2.13820457,1.0930717, 2.20154786,1.13714886);
-findNextOp debugShowSort contourWinding=-1 oppContourWinding=1 sign=-1
-debugShowSort [0] {{3,5}, {1,2}, {3,0}, {2,1}} tStart=0.5 tEnd=0.59235675 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [1] {{2,1}, {3,5}} tStart=0.125 tEnd=-0 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [2] {{3,5}, {1,2}, {3,0}, {2,1}} tStart=0.5 tEnd=0.32953467 sign=1 windValue=1 windSum=-2 -1->-2 (max=-2) done=1 tiny=0 opp=0
-debugShowSort [3] {{2,1}, {3,5}} tStart=0.125 tEnd=0.349432839 sign=-1 windValue=1 windSum=? -2->-1 (max=-2) done=0 tiny=0 opp=0
-findNextOp firstIndex=[0] sign=-1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=1 result=0
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=4 (2,1 3,5) t=0.125 [3] (2.125,1.5) tEnd=0.349432839 newWindSum=-2 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=4
-markDoneBinary id=3 (3,5 1,2 3,0 2,1) t=0.5 [2] (2.125,1.5) tEnd=0.59235675 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1
-findNextOp from:[3] to:[4] start=3 end=2
-bridgeOp current id=3 from=(2.20154786,1.13714886) to=(2.125,1.5)
-path.cubicTo(2.17544317,1.23998928, 2.14808917,1.36146486, 2.125,1.5);
-path.close();
-assemble
-assemble contour start=(2.125,1.5) end=(2.125,1.5)
-</div>
-
-<div id="cubicOp53da">
-$1 = {{fX = 2.20154786, fY = 1.13714886}, {fX = 2.31676745, fY = 0.683232486}, {fX = 2.40764332, fY = 0.592356741}, {fX = 2, fY = 1}}
-</div>
-
-<div id="cubicOp53db">
-$5 = {{x = 2.2015477442470841, y = 1.1371488033015216}, {x = 2.3167674423028313, y = 0.68323255769716895}, {x = 2.4076432497431508, y = 0.59235675025684875}, {x = 2, y = 1}}
-(gdb) p startEdge
-$2 = {{x = 2.2015477442470841, y = 1.1371488033015216}, {x = 2.6554639898514365, y = 1.2523685013572687}}
-(gdb) p endEdge
-$3 = {{x = 2, y = 1}, {x = 2.4076432497431512, y = 1.4076432497431508}}
-</div>
-
-<div id="cubicOp54d">
- SimplifyNew_Test [cubicOp54d]
-{{0,4}, {1,3}, {5,4}, {4,2}},
-{{4,2}, {0,4}},
-op difference
-{{4,5}, {2,4}, {4,0}, {3,1}},
-{{3,1}, {4,5}},
-debugShowCubicIntersection no self intersect {{4,5}, {2,4}, {4,0}, {3,1}}
-debugShowCubicLineIntersection wtTs[0]=0 {{4,5}, {2,4}, {4,0}, {3,1}} {{4,5}} wtTs[1]=0.583333333 {{3.1938657407407405,1.7754629629629624}} wtTs[2]=1 {{3,1}} wnTs[0]=1 {{3,1}, {4,5}} wnTs[1]=0.193865741 wnTs[2]=0
-debugShowCubicIntersection no intersect {{4,5}, {2,4}, {4,0}, {3,1}} {{0,4}, {1,3}, {5,4}, {4,2}}
-debugShowCubicLineIntersection wtTs[0]=0.467349523 {{4,5}, {2,4}, {4,0}, {3,1}} {{3.1023548730676489,2.4488225634661758}} wnTs[0]=0.224411 {{4,2}, {0,4}}
-debugShowCubicLineIntersection wtTs[0]=0.649488354 {{0,4}, {1,3}, {5,4}, {4,2}} {{3.5531651685912107,3.2126606743648427}} wnTs[0]=0.553165 {{3,1}, {4,5}}
-debugShowLineIntersection wtTs[0]=0.333333333 {{3,1}, {4,5}} {{3.333333333333333,2.333333333333333}} wnTs[0]=0.166667 {{4,2}, {0,4}}
-debugShowCubicIntersection no self intersect {{0,4}, {1,3}, {5,4}, {4,2}}
-debugShowCubicLineIntersection wtTs[0]=0 {{0,4}, {1,3}, {5,4}, {4,2}} {{0,4}} wtTs[1]=0.166666667 {{0.7129629629629628,3.6435185185185186}} wtTs[2]=1 {{4,2}} wnTs[0]=1 {{4,2}, {0,4}} wnTs[1]=0.821759259 wnTs[2]=0
-debugShowActiveSpans id=3 (4,5 2,4 4,0 3,1) t=0 (4,5) tEnd=0.467349523 other=4 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (4,5 2,4 4,0 3,1) t=0.467349523 (3.10235476,2.4488225) tEnd=0.583333333 other=2 otherT=0.224411282 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (4,5 2,4 4,0 3,1) t=0.583333333 (3.19386578,1.77546299) tEnd=1 other=4 otherT=0.193865741 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (3,1 4,5) t=0 (3,1) tEnd=0.193865741 other=3 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (3,1 4,5) t=0.193865741 (3.19386578,1.77546299) tEnd=0.333333333 other=3 otherT=0.583333333 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (3,1 4,5) t=0.333333333 (3.33333325,2.33333325) tEnd=0.553165169 other=2 otherT=0.166666667 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (3,1 4,5) t=0.553165169 (3.5531652,3.21266079) tEnd=1 other=1 otherT=0.649488354 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,4 1,3 5,4 4,2) t=0 (0,4) tEnd=0.166666667 other=2 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,4 1,3 5,4 4,2) t=0.166666667 (0.712962985,3.64351845) tEnd=0.649488354 other=2 otherT=0.821759259 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,4 1,3 5,4 4,2) t=0.649488354 (3.5531652,3.21266079) tEnd=1 other=4 otherT=0.553165169 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,2 0,4) t=0 (4,2) tEnd=0.166666667 other=1 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,2 0,4) t=0.166666667 (3.33333325,2.33333325) tEnd=0.224411282 other=4 otherT=0.333333333 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,2 0,4) t=0.224411282 (3.10235476,2.4488225) tEnd=0.821759259 other=3 otherT=0.467349523 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,2 0,4) t=0.821759259 (0.712962985,3.64351845) tEnd=1 other=1 otherT=0.166666667 otherIndex=1 windSum=? windValue=1 oppValue=0
-findTop debugShowSort contourWinding=0 oppContourWinding=0 sign=1
-debugShowSort [0] {{4,5}, {2,4}, {4,0}, {3,1}} tStart=1 tEnd=0.583333333 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [1] {{3,1}, {4,5}} tStart=0 tEnd=0.193865741 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-findTop swap serpentine=0
-markWinding id=3 (4,5 2,4 4,0 3,1) t=0.583333333 [2] (3.19386578,1.77546299) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=3 (4,5 2,4 4,0 3,1) t=0.583333333 [2] (3.19386578,1.77546299) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-markWinding id=4 (3,1 4,5) t=0 [0] (3,1) tEnd=0.193865741 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-markDoneBinary id=3 (4,5 2,4 4,0 3,1) t=0.583333333 [2] (3.19386578,1.77546299) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-debugShowActiveSpans id=3 (4,5 2,4 4,0 3,1) t=0 (4,5) tEnd=0.467349523 other=4 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (4,5 2,4 4,0 3,1) t=0.467349523 (3.10235476,2.4488225) tEnd=0.583333333 other=2 otherT=0.224411282 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (3,1 4,5) t=0 (3,1) tEnd=0.193865741 other=3 otherT=1 otherIndex=3 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (3,1 4,5) t=0.193865741 (3.19386578,1.77546299) tEnd=0.333333333 other=3 otherT=0.583333333 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (3,1 4,5) t=0.333333333 (3.33333325,2.33333325) tEnd=0.553165169 other=2 otherT=0.166666667 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (3,1 4,5) t=0.553165169 (3.5531652,3.21266079) tEnd=1 other=1 otherT=0.649488354 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,4 1,3 5,4 4,2) t=0 (0,4) tEnd=0.166666667 other=2 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,4 1,3 5,4 4,2) t=0.166666667 (0.712962985,3.64351845) tEnd=0.649488354 other=2 otherT=0.821759259 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,4 1,3 5,4 4,2) t=0.649488354 (3.5531652,3.21266079) tEnd=1 other=4 otherT=0.553165169 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,2 0,4) t=0 (4,2) tEnd=0.166666667 other=1 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,2 0,4) t=0.166666667 (3.33333325,2.33333325) tEnd=0.224411282 other=4 otherT=0.333333333 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,2 0,4) t=0.224411282 (3.10235476,2.4488225) tEnd=0.821759259 other=3 otherT=0.467349523 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,2 0,4) t=0.821759259 (0.712962985,3.64351845) tEnd=1 other=1 otherT=0.166666667 otherIndex=1 windSum=? windValue=1 oppValue=0
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-markDoneBinary id=4 (3,1 4,5) t=0 [0] (3,1) tEnd=0.193865741 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-findChaseOp debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [0] {{4,5}, {2,4}, {4,0}, {3,1}} tStart=0.583333333 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=0
-debugShowSort [1] {{3,1}, {4,5}} tStart=0.193865741 tEnd=0 sign=1 windValue=1 windSum=1 1->0 (max=1) done=1 tiny=0 opp=0
-debugShowSort [2] {{4,5}, {2,4}, {4,0}, {3,1}} tStart=0.583333333 tEnd=0.467349523 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [3] {{3,1}, {4,5}} tStart=0.193865741 tEnd=0.333333333 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-findChaseOp debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [0] {{4,5}, {2,4}, {4,0}, {3,1}} tStart=0.583333333 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=0
-debugShowSort [1] {{3,1}, {4,5}} tStart=0.193865741 tEnd=0 sign=1 windValue=1 windSum=1 1->0 (max=1) done=1 tiny=0 opp=0
-debugShowSort [2] {{4,5}, {2,4}, {4,0}, {3,1}} tStart=0.583333333 tEnd=0.467349523 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [3] {{3,1}, {4,5}} tStart=0.193865741 tEnd=0.333333333 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-markWinding id=3 (4,5 2,4 4,0 3,1) t=0.467349523 [1] (3.10235476,2.4488225) tEnd=0.583333333 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=4 (3,1 4,5) t=0.193865741 [1] (3.19386578,1.77546299) tEnd=0.333333333 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-debugShowActiveSpans id=3 (4,5 2,4 4,0 3,1) t=0 (4,5) tEnd=0.467349523 other=4 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (4,5 2,4 4,0 3,1) t=0.467349523 (3.10235476,2.4488225) tEnd=0.583333333 other=2 otherT=0.224411282 otherIndex=2 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (3,1 4,5) t=0.193865741 (3.19386578,1.77546299) tEnd=0.333333333 other=3 otherT=0.583333333 otherIndex=2 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (3,1 4,5) t=0.333333333 (3.33333325,2.33333325) tEnd=0.553165169 other=2 otherT=0.166666667 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (3,1 4,5) t=0.553165169 (3.5531652,3.21266079) tEnd=1 other=1 otherT=0.649488354 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,4 1,3 5,4 4,2) t=0 (0,4) tEnd=0.166666667 other=2 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,4 1,3 5,4 4,2) t=0.166666667 (0.712962985,3.64351845) tEnd=0.649488354 other=2 otherT=0.821759259 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,4 1,3 5,4 4,2) t=0.649488354 (3.5531652,3.21266079) tEnd=1 other=4 otherT=0.553165169 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,2 0,4) t=0 (4,2) tEnd=0.166666667 other=1 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,2 0,4) t=0.166666667 (3.33333325,2.33333325) tEnd=0.224411282 other=4 otherT=0.333333333 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,2 0,4) t=0.224411282 (3.10235476,2.4488225) tEnd=0.821759259 other=3 otherT=0.467349523 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,2 0,4) t=0.821759259 (0.712962985,3.64351845) tEnd=1 other=1 otherT=0.166666667 otherIndex=1 windSum=? windValue=1 oppValue=0
-activeOp op=diff miFrom=0 miTo=0 suFrom=0 suTo=1 result=0
-markDoneBinary id=3 (4,5 2,4 4,0 3,1) t=0.467349523 [1] (3.10235476,2.4488225) tEnd=0.583333333 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-findChaseOp debugShowSort contourWinding=? oppContourWinding=? sign=1
-debugShowSort [0] {{4,2}, {0,4}} tStart=0.224411282 tEnd=0.166666667 sign=1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=0
-debugShowSort [1] {{4,5}, {2,4}, {4,0}, {3,1}} tStart=0.467349523 tEnd=0.583333333 sign=-1 windValue=1 windSum=-1 ?->? (max=?) done=1 tiny=0 opp=1
-debugShowSort [2] {{4,2}, {0,4}} tStart=0.224411282 tEnd=0.821759259 sign=-1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=0
-debugShowSort [3] {{4,5}, {2,4}, {4,0}, {3,1}} tStart=0.467349523 tEnd=0 sign=1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=1
-findChaseOp debugShowSort contourWinding=-1 oppContourWinding=0 sign=-1
-debugShowSort [1] {{4,5}, {2,4}, {4,0}, {3,1}} tStart=0.467349523 tEnd=0.583333333 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [2] {{4,2}, {0,4}} tStart=0.224411282 tEnd=0.821759259 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=1
-debugShowSort [3] {{4,5}, {2,4}, {4,0}, {3,1}} tStart=0.467349523 tEnd=0 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [0] {{4,2}, {0,4}} tStart=0.224411282 tEnd=0.166666667 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=1
-markWinding id=2 (4,2 0,4) t=0.224411282 [2] (3.10235476,2.4488225) tEnd=0.821759259 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=3 (4,5 2,4 4,0 3,1) t=0 [0] (4,5) tEnd=0.467349523 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-markWinding id=4 (3,1 4,5) t=0.553165169 [3] (3.5531652,3.21266079) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-markWinding id=2 (4,2 0,4) t=0.166666667 [1] (3.33333325,2.33333325) tEnd=0.224411282 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1
-debugShowActiveSpans id=3 (4,5 2,4 4,0 3,1) t=0 (4,5) tEnd=0.467349523 other=4 otherT=1 otherIndex=4 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (3,1 4,5) t=0.193865741 (3.19386578,1.77546299) tEnd=0.333333333 other=3 otherT=0.583333333 otherIndex=2 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (3,1 4,5) t=0.333333333 (3.33333325,2.33333325) tEnd=0.553165169 other=2 otherT=0.166666667 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (3,1 4,5) t=0.553165169 (3.5531652,3.21266079) tEnd=1 other=1 otherT=0.649488354 otherIndex=2 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,4 1,3 5,4 4,2) t=0 (0,4) tEnd=0.166666667 other=2 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,4 1,3 5,4 4,2) t=0.166666667 (0.712962985,3.64351845) tEnd=0.649488354 other=2 otherT=0.821759259 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,4 1,3 5,4 4,2) t=0.649488354 (3.5531652,3.21266079) tEnd=1 other=4 otherT=0.553165169 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,2 0,4) t=0 (4,2) tEnd=0.166666667 other=1 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,2 0,4) t=0.166666667 (3.33333325,2.33333325) tEnd=0.224411282 other=4 otherT=0.333333333 otherIndex=2 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,2 0,4) t=0.224411282 (3.10235476,2.4488225) tEnd=0.821759259 other=3 otherT=0.467349523 otherIndex=1 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (4,2 0,4) t=0.821759259 (0.712962985,3.64351845) tEnd=1 other=1 otherT=0.166666667 otherIndex=1 windSum=? windValue=1 oppValue=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-findNextOp debugShowSort contourWinding=1 oppContourWinding=0 sign=1
-debugShowSort [1] {{4,2}, {0,4}} tStart=0.821759259 tEnd=0.224411282 sign=1 windValue=1 windSum=1 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [2] {{0,4}, {1,3}, {5,4}, {4,2}} tStart=0.166666667 tEnd=0 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [3] {{4,2}, {0,4}} tStart=0.821759259 tEnd=1 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [0] {{0,4}, {1,3}, {5,4}, {4,2}} tStart=0.166666667 tEnd=0.649488354 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=0
-findNextOp firstIndex=[1] sign=1
-activeOp op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-markWinding id=1 (0,4 1,3 5,4 4,2) t=0 [0] (0,4) tEnd=0.166666667 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=2 (4,2 0,4) t=0.821759259 [3] (0.712962985,3.64351845) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=2
-activeOp op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-activeOp op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-markWinding id=1 (0,4 1,3 5,4 4,2) t=0.166666667 [1] (0.712962985,3.64351845) tEnd=0.649488354 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=1
-markDoneBinary id=2 (4,2 0,4) t=0.224411282 [2] (3.10235476,2.4488225) tEnd=0.821759259 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-findNextOp from:[2] to:[1] start=1 end=0
-bridgeOp current id=2 from=(3.10235476,2.4488225) to=(0.712962985,3.64351845)
-findNextOp simple
-markDoneBinary id=1 (0,4 1,3 5,4 4,2) t=0 [0] (0,4) tEnd=0.166666667 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-bridgeOp current id=1 from=(0.712962985,3.64351845) to=(0,4)
-path.moveTo(3.10235476,2.4488225);
-path.lineTo(0.712962985,3.64351845);
-path.cubicTo(0.416666657,3.72222233, 0.166666672,3.83333325, 0,4);
-findNextOp debugShowSort contourWinding=-1 oppContourWinding=0 sign=-1
-debugShowSort [3] {{4,2}, {0,4}} tStart=0.821759259 tEnd=1 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [0] {{0,4}, {1,3}, {5,4}, {4,2}} tStart=0.166666667 tEnd=0.649488354 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] {{4,2}, {0,4}} tStart=0.821759259 tEnd=0.224411282 sign=1 windValue=1 windSum=1 1->0 (max=1) done=1 tiny=0 opp=0
-debugShowSort [2] {{0,4}, {1,3}, {5,4}, {4,2}} tStart=0.166666667 tEnd=0 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=0
-findNextOp firstIndex=[3] sign=-1
-activeOp op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-activeOp op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-activeOp op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-markDoneBinary id=2 (4,2 0,4) t=0.821759259 [3] (0.712962985,3.64351845) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-findNextOp from:[2] to:[1] start=1 end=2
-bridgeOp current id=2 from=(0,4) to=(0.712962985,3.64351845)
-findNextOp debugShowSort contourWinding=1 oppContourWinding=0 sign=1
-debugShowSort [2] {{0,4}, {1,3}, {5,4}, {4,2}} tStart=0.649488354 tEnd=0.166666667 sign=1 windValue=1 windSum=1 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [3] {{3,1}, {4,5}} tStart=0.553165169 tEnd=1 sign=-1 windValue=1 windSum=-1 0->1 (max=1) done=0 tiny=0 opp=1
-debugShowSort [0] {{0,4}, {1,3}, {5,4}, {4,2}} tStart=0.649488354 tEnd=1 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] {{3,1}, {4,5}} tStart=0.553165169 tEnd=0.333333333 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=1
-findNextOp firstIndex=[2] sign=1
-activeOp op=diff miFrom=0 miTo=0 suFrom=0 suTo=1 result=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=1 (0,4 1,3 5,4 4,2) t=0.649488354 [2] (3.5531652,3.21266079) tEnd=1 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1
-markDoneBinary id=2 (4,2 0,4) t=0 [0] (4,2) tEnd=0.166666667 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=2
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
-markWinding id=4 (3,1 4,5) t=0.333333333 [2] (3.33333325,2.33333325) tEnd=0.553165169 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=4
-markDoneBinary id=1 (0,4 1,3 5,4 4,2) t=0.166666667 [1] (0.712962985,3.64351845) tEnd=0.649488354 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-findNextOp from:[1] to:[4] start=3 end=2
-bridgeOp current id=1 from=(0.712962985,3.64351845) to=(3.5531652,3.21266079)
-path.lineTo(0.712962985,3.64351845);
-path.cubicTo(1.57131267,3.41551948, 2.81819034,3.45948982, 3.5531652,3.21266079);
-findNextOp debugShowSort contourWinding=0 oppContourWinding=1 sign=-1
-debugShowSort [3] {{3,1}, {4,5}} tStart=0.333333333 tEnd=0.553165169 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [0] {{4,2}, {0,4}} tStart=0.166666667 tEnd=0 sign=1 windValue=1 windSum=1 1->0 (max=1) done=1 tiny=0 opp=1
-debugShowSort [1] {{3,1}, {4,5}} tStart=0.333333333 tEnd=0.193865741 sign=1 windValue=1 windSum=-1 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [2] {{4,2}, {0,4}} tStart=0.166666667 tEnd=0.224411282 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=0 tiny=0 opp=1
-findNextOp firstIndex=[3] sign=-1
-activeOp op=diff miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-markDoneBinary id=4 (3,1 4,5) t=0.333333333 [2] (3.33333325,2.33333325) tEnd=0.553165169 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1
-findNextOp from:[4] to:[2] start=1 end=2
-bridgeOp current id=4 from=(3.5531652,3.21266079) to=(3.33333325,2.33333325)
-findNextOp debugShowSort contourWinding=1 oppContourWinding=-1 sign=1
-debugShowSort [0] {{4,2}, {0,4}} tStart=0.224411282 tEnd=0.166666667 sign=1 windValue=1 windSum=1 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] {{4,5}, {2,4}, {4,0}, {3,1}} tStart=0.467349523 tEnd=0.583333333 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=1
-debugShowSort [2] {{4,2}, {0,4}} tStart=0.224411282 tEnd=0.821759259 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=0
-debugShowSort [3] {{4,5}, {2,4}, {4,0}, {3,1}} tStart=0.467349523 tEnd=0 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=0 tiny=0 opp=1
-findNextOp firstIndex=[0] sign=1
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-markDoneBinary id=2 (4,2 0,4) t=0.166666667 [1] (3.33333325,2.33333325) tEnd=0.224411282 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1
-findNextOp from:[2] to:[2] start=2 end=3
-sharedlibrary apply-load-rules all
-bridgeOp current id=2 from=(3.33333325,2.33333325) to=(3.10235476,2.4488225)
-path.lineTo(3.33333325,2.33333325);
-path.lineTo(3.10235476,2.4488225);
-path.close();
-debugShowActiveSpans id=3 (4,5 2,4 4,0 3,1) t=0 (4,5) tEnd=0.467349523 other=4 otherT=1 otherIndex=4 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (3,1 4,5) t=0.193865741 (3.19386578,1.77546299) tEnd=0.333333333 other=3 otherT=0.583333333 otherIndex=2 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (3,1 4,5) t=0.553165169 (3.5531652,3.21266079) tEnd=1 other=1 otherT=0.649488354 otherIndex=2 windSum=-1 windValue=1 oppValue=0
-activeOp op=diff miFrom=0 miTo=0 suFrom=0 suTo=1 result=0
-markDoneBinary id=4 (3,1 4,5) t=0.193865741 [1] (3.19386578,1.77546299) tEnd=0.333333333 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-debugShowActiveSpans id=3 (4,5 2,4 4,0 3,1) t=0 (4,5) tEnd=0.467349523 other=4 otherT=1 otherIndex=4 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (3,1 4,5) t=0.553165169 (3.5531652,3.21266079) tEnd=1 other=1 otherT=0.649488354 otherIndex=2 windSum=-1 windValue=1 oppValue=0
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
-findNextOp simple
-markDoneBinary id=4 (3,1 4,5) t=0.553165169 [3] (3.5531652,3.21266079) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1
-bridgeOp current id=4 from=(3.5531652,3.21266079) to=(4,5)
-findNextOp debugShowSort contourWinding=0 oppContourWinding=1 sign=1
-debugShowSort [3] {{4,5}, {2,4}, {4,0}, {3,1}} tStart=0.467349523 tEnd=0 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [0] {{4,2}, {0,4}} tStart=0.224411282 tEnd=0.166666667 sign=1 windValue=1 windSum=1 1->0 (max=1) done=1 tiny=0 opp=1
-debugShowSort [1] {{4,5}, {2,4}, {4,0}, {3,1}} tStart=0.467349523 tEnd=0.583333333 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [2] {{4,2}, {0,4}} tStart=0.224411282 tEnd=0.821759259 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=1
-findNextOp firstIndex=[3] sign=1
-activeOp op=diff miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-markDoneBinary id=3 (4,5 2,4 4,0 3,1) t=0 [0] (4,5) tEnd=0.467349523 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1
-findNextOp from:[3] to:[2] start=2 end=3
-bridgeOp current id=3 from=(4,5) to=(3.10235476,2.4488225)
-path.moveTo(3.5531652,3.21266079);
-path.lineTo(4,5);
-path.cubicTo(3.06530094,4.53265047, 3.00426435,3.41005421, 3.10235476,2.4488225);
-</div>
-
-<div id="cubicOp54da">
-computed quadratics given
- {{0,4}, {1,3}, {5,4}, {4,2}},
- {{4,5}, {2,4}, {4,0}, {3,1}},
-computed quadratics set 1
- {{0,4}, {0.313151522,3.71221453}, {0.886767898,3.60197476}},
- {{0.886767898,3.60197476}, {1.46038427,3.491735}, {2.10714698,3.44196686}},
- {{2.10714698,3.44196686}, {3.12180288,3.38575704}, {3.75968569,3.1281838}},
- {{3.75968569,3.1281838}, {4.3975685,2.87061055}, {4,2}},
-computed quadratics set 2
- {{4,5}, {3.59856947,4.79217123}, {3.39068129,4.44939202}},
- {{3.39068129,4.44939202}, {3.03659239,3.81843234}, {3.06844529,3.02100922}},
- {{3.06844529,3.02100922}, {3.09985637,2.22825976}, {3.22177695,1.60368348}},
- {{3.22177695,1.60368348}, {3.35239933,0.944897345}, {3.25461667,0.846601983}},
- {{3.25461667,0.846601983}, {3.19302952,0.807536747}, {3,1}},
-</div>
-
-<div id="cubicOp54db">
- {{3.39068129,4.44939202}, {3.03659239,3.81843234}, {3.06844529,3.02100922}},
- {{2.10714698,3.44196686}, {3.12180288,3.38575704}, {3.75968569,3.1281838}},
-</div>
-
-<div id="cubicOp54dc">
-(gdb) p cSub1
-$2 = {{x = 3.0774019473063863, y = 3.35198509346713}, {x = 3.0763003260366699, y = 3.3355427495692078}, {x = 3.0753041923884408, y = 3.3190757607779853}, {x = 3.0744102085015879, y = 3.3025879417907196}}
-(gdb) p cSub2
-$3 = {{x = 3.053913680774329, y = 3.3310471586283938}, {x = 3.0685526504546785, y = 3.3285797268698434}, {x = 3.0831050944309708, y = 3.3260658459407866}, {x = 3.0975671980059394, y = 3.3235031316554351}}
-(gdb) p s1
-$4 = {{x = 3.0774019473063863, y = 3.35198509346713}, {x = 3.0757503498668397, y = 3.327320623945933}, {x = 3.0744102085015879, y = 3.3025879417907196}}
-(gdb) p s2
-$5 = {{x = 3.053913680774329, y = 3.3310471586283938}, {x = 3.0758730889691694, y = 3.3273466070370152}, {x = 3.0975671980059394, y = 3.3235031316554351}}
-</div>
-
-<div id="cubicOp54dd">
-{{x = 3.053913680774329, y = 3.3310471586283938}, {x = 3.0758730889691694, y = 3.3273466070370152}, {x = 3.0975671980059394, y = 3.3235031316554351}}
-{{x = 3.0744102085015879, y = 3.3025879417907196}, {x = 3.0774019473063863, y = 3.35198509346713}}
-</div>
-
-<div id="cubicOp55d">
- SimplifyNew_Test [cubicOp55d]
-{{0,5}, {1,3}, {3,2}, {5,0}},
-{{5,0}, {0,5}},
-op difference
-{{2,3}, {0,5}, {5,0}, {3,1}},
-{{3,1}, {2,3}},
-debugShowCubicIntersection no self intersect {{0,5}, {1,3}, {3,2}, {5,0}}
-debugShowCubicLineIntersection wtTs[0]=0 {{0,5}, {1,3}, {3,2}, {5,0}} {{0,5}} wtTs[1]=1 {{5,0}} wnTs[0]=1 {{5,0}, {0,5}} wnTs[1]=0
-debugShowCubicIntersection wtTs[0]=0.658239823 {{0,5}, {1,3}, {3,2}, {5,0}} {{2.9893565350663849,1.7799961946192431}} wnTs[0]=0.613267 {{2,3}, {0,5}, {5,0}, {3,1}}
-debugShowCubicLineIntersection wtTs[0]=0.540876747 {{0,5}, {1,3}, {3,2}, {5,0}} {{2.3420409812806477,2.3159180374387045}} wnTs[0]=0.657959 {{3,1}, {2,3}}
-debugShowCubicLineIntersection wtTs[0]=0 {{2,3}, {0,5}, {5,0}, {3,1}} {{2,3}} wnTs[0]=0.6 {{5,0}, {0,5}}
-debugShowLineIntersection wtTs[0]=0.6 {{5,0}, {0,5}} {{2,3}} wnTs[0]=1 {{3,1}, {2,3}}
-debugShowCubicIntersection no self intersect {{2,3}, {0,5}, {5,0}, {3,1}}
-debugShowCubicLineIntersection wtTs[0]=0 {{2,3}, {0,5}, {5,0}, {3,1}} {{2,3}} wtTs[1]=0.4 {{2.0640000000000005,2.871999999999999}} wtTs[2]=1 {{3,1}} wnTs[0]=1 {{3,1}, {2,3}} wnTs[1]=0.936 wnTs[2]=0
-debugShowActiveSpans id=1 (0,5 1,3 3,2 5,0) t=0 (0,5) tEnd=0.540876747 other=2 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,5 1,3 3,2 5,0) t=0.540876747 (2.34204102,2.31591797) tEnd=0.658239823 other=4 otherT=0.657959019 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,5 1,3 3,2 5,0) t=0.658239823 (2.98935652,1.77999616) tEnd=1 other=3 otherT=0.613266786 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,0 0,5) t=0 (5,0) tEnd=0.6 other=1 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,0 0,5) t=0.6 (2,3) tEnd=1 other=3 otherT=0 otherIndex=0 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,0 0,5) t=0.6 (2,3) tEnd=1 other=4 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (2,3 0,5 5,0 3,1) t=0 (2,3) tEnd=0.4 other=2 otherT=0.6 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (2,3 0,5 5,0 3,1) t=0 (2,3) tEnd=0.4 other=4 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (2,3 0,5 5,0 3,1) t=0.4 (2.06399989,2.87199998) tEnd=0.613266786 other=4 otherT=0.936 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (2,3 0,5 5,0 3,1) t=0.613266786 (2.98935652,1.77999616) tEnd=1 other=1 otherT=0.658239823 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (3,1 2,3) t=0 (3,1) tEnd=0.657959019 other=3 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (3,1 2,3) t=0.657959019 (2.34204102,2.31591797) tEnd=0.936 other=1 otherT=0.540876747 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (3,1 2,3) t=0.936 (2.06399989,2.87199998) tEnd=1 other=3 otherT=0.4 otherIndex=2 windSum=? windValue=1 oppValue=0
-findTop debugShowSort contourWinding=0 oppContourWinding=0 sign=1
-debugShowSort [0] {{0,5}, {1,3}, {3,2}, {5,0}} tStart=1 tEnd=0.658239823 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [1] {{5,0}, {0,5}} tStart=0 tEnd=0.6 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-findTop swap serpentine=0
-markWinding id=1 (0,5 1,3 3,2 5,0) t=0.658239823 [2] (2.98935652,1.77999616) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=1 (0,5 1,3 3,2 5,0) t=0.658239823 [2] (2.98935652,1.77999616) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-markWinding id=2 (5,0 0,5) t=0 [0] (5,0) tEnd=0.6 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-activeOp op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-findNextOp debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [0] {{0,5}, {1,3}, {3,2}, {5,0}} tStart=0.658239823 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] {{2,3}, {0,5}, {5,0}, {3,1}} tStart=0.613266786 tEnd=1 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=1
-debugShowSort [2] {{0,5}, {1,3}, {3,2}, {5,0}} tStart=0.658239823 tEnd=0.540876747 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [3] {{2,3}, {0,5}, {5,0}, {3,1}} tStart=0.613266786 tEnd=0.4 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=1
-findNextOp firstIndex=[0] sign=-1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-markWinding id=3 (2,3 0,5 5,0 3,1) t=0.613266786 [3] (2.98935652,1.77999616) tEnd=1 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1
-markWinding id=4 (3,1 2,3) t=0 [0] (3,1) tEnd=0.657959019 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=4
-activeOp op=diff miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
-markDoneBinary id=1 (0,5 1,3 3,2 5,0) t=0.540876747 [1] (2.34204102,2.31591797) tEnd=0.658239823 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=1
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-markDoneBinary id=3 (2,3 0,5 5,0 3,1) t=0.4 [2] (2.06399989,2.87199998) tEnd=0.613266786 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-markDoneBinary id=1 (0,5 1,3 3,2 5,0) t=0.658239823 [2] (2.98935652,1.77999616) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-findNextOp from:[1] to:[3] start=3 end=4
-bridgeOp current id=1 from=(5,0) to=(2.98935652,1.77999616)
-path.moveTo(5,0);
-path.cubicTo(4.31647968,0.683520317, 3.63295937,1.25024068, 2.98935652,1.77999616);
-findNextOp simple
-markDoneBinary id=3 (2,3 0,5 5,0 3,1) t=0.613266786 [3] (2.98935652,1.77999616) tEnd=1 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1
-bridgeOp current id=3 from=(2.98935652,1.77999616) to=(3,1)
-path.cubicTo(3.49999475,1.123909, 3.77346635,0.613266766, 3,1);
-findNextOp debugShowSort contourWinding=1 oppContourWinding=1 sign=1
-debugShowSort [1] {{3,1}, {2,3}} tStart=0.657959019 tEnd=0 sign=1 windValue=1 windSum=1 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [2] {{0,5}, {1,3}, {3,2}, {5,0}} tStart=0.540876747 tEnd=0 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=1
-debugShowSort [3] {{3,1}, {2,3}} tStart=0.657959019 tEnd=0.936 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [0] {{0,5}, {1,3}, {3,2}, {5,0}} tStart=0.540876747 tEnd=0.658239823 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=1
-findNextOp firstIndex=[1] sign=1
-activeOp op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-markWinding id=1 (0,5 1,3 3,2 5,0) t=0 [0] (0,5) tEnd=0.540876747 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=2 (5,0 0,5) t=0.6 [1] (2,3) tEnd=0.6 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=2 (5,0 0,5) t=0.6 [2] (2,3) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=2
-activeOp op=diff miFrom=0 miTo=0 suFrom=0 suTo=1 result=0
-markDoneBinary id=4 (3,1 2,3) t=0.657959019 [1] (2.34204102,2.31591797) tEnd=0.936 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=4
-activeOp op=diff miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=4 (3,1 2,3) t=0 [0] (3,1) tEnd=0.657959019 newWindSum=1 newOppSum=1 oppSum=1 windSum=1 windValue=1
-findNextOp from:[4] to:[1] start=1 end=0
-bridgeOp current id=4 from=(3,1) to=(2.34204102,2.31591797)
-findNextOp simple
-markDoneBinary id=1 (0,5 1,3 3,2 5,0) t=0 [0] (0,5) tEnd=0.540876747 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-bridgeOp current id=1 from=(2.34204102,2.31591797) to=(0,5)
-path.lineTo(2.34204102,2.31591797);
-path.cubicTo(1.37430108,3.12904072, 0.540876746,3.91824651, 0,5);
-findNextOp debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [3] {{5,0}, {0,5}} tStart=0.6 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [0] {{5,0}, {0,5}} tStart=0.6 tEnd=0 sign=1 windValue=1 windSum=1 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] {{3,1}, {2,3}} tStart=1 tEnd=0.936 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=1
-debugShowSort [2] {{2,3}, {0,5}, {5,0}, {3,1}} tStart=0 tEnd=0.4 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=1
-findNextOp firstIndex=[3] sign=-1
-activeOp op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-activeOp op=diff miFrom=0 miTo=0 suFrom=0 suTo=1 result=0
-markDoneBinary id=4 (3,1 2,3) t=0.936 [2] (2.06399989,2.87199998) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=4
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-markDoneBinary id=3 (2,3 0,5 5,0 3,1) t=0 [0] (2,3) tEnd=0 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-markDoneBinary id=3 (2,3 0,5 5,0 3,1) t=0 [1] (2,3) tEnd=0.4 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-markDoneBinary id=2 (5,0 0,5) t=0.6 [1] (2,3) tEnd=0.6 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-markDoneBinary id=2 (5,0 0,5) t=0.6 [2] (2,3) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-findNextOp from:[2] to:[2] start=2 end=0
-bridgeOp current id=2 from=(0,5) to=(2,3)
-findNextOp simple
-markDoneBinary id=2 (5,0 0,5) t=0 [0] (5,0) tEnd=0.6 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-bridgeOp current id=2 from=(2,3) to=(5,0)
-path.lineTo(5,0);
-path.close();
-assemble
-assemble contour start=(5,0) end=(5,0)
-</div>
-
-<div id="cubicOp55da">
-$1 = {{x = 2.9893565350663844, y = 1.7799961946192431}, {x = 3.6329592934456443, y = 1.250240688218315}, {x = 4.3164796467228257, y = 0.68352035327717708}, {x = 5, y = 0}}
-</div>
-
-<div id="cubicOp56da">
-$3 = {{x = 3.2077595567431376, y = 1.2121007383531144}, {x = 3.0712003892698903, y = 0.91360430885366861}, {x = 2.6980028578011237, y = 0.76733238073295829}, {x = 2, y = 1}}
-</div>
-
-<div id="cubicOp57da">
-computed quadratics given
- {{0,5}, {0,5}, {5,4}, {6,4}},
- {{4,5}, {4,6}, {5,0}, {5,0}},
-computed quadratics set 1
- {{0,5}, {0.0833333333,4.98148148}, {1.33333333,4.74074074}},
- {{1.33333333,4.74074074}, {2.58333333,4.5}, {4,4.25925926}},
- {{4,4.25925926}, {5.41666667,4.01851852}, {6,4}},
-computed quadratics set 2
- {{4,5}, {4.0078125,5.32421875}, {4.15625,4.640625}},
- {{4.15625,4.640625}, {4.3046875,3.95703125}, {4.5,2.875}},
- {{4.5,2.875}, {4.6953125,1.79296875}, {4.84375,0.921875}},
- {{4.84375,0.921875}, {4.9921875,0.05078125}, {5,0}},
-</div>
-
-<div id="cubicOp58d">
- SimplifyNew_Test [cubicOp58d]
-{{0,5}, {3,4}, {6,5}, {5,3}},
-{{5,3}, {0,5}},
-op difference
-{{5,6}, {3,5}, {5,0}, {4,3}},
-{{4,3}, {5,6}},
-debugShowCubicIntersection no self intersect {{5,6}, {3,5}, {5,0}, {4,3}}
-debugShowCubicLineIntersection wtTs[0]=0 {{5,6}, {3,5}, {5,0}, {4,3}} {{5,6}} wtTs[1]=0.454545455 {{4.0946656649135988,3.2839969947407956}} wtTs[2]=1 {{4,3}} wnTs[0]=1 {{4,3}, {5,6}} wnTs[1]=0.0946656649 wnTs[2]=0
-debugShowCubicIntersection wtTs[0]=0.297296392 {{5,6}, {3,5}, {5,0}, {4,3}} {{4.0929072920341625,4.362808103638363}} wnTs[0]=0.515735 {{0,5}, {3,4}, {6,5}, {5,3}}
-debugShowCubicLineIntersection wtTs[0]=0.442158094 {{5,6}, {3,5}, {5,0}, {4,3}} {{4.0879917456946373,3.3648033017221453}} wnTs[0]=0.182402 {{5,3}, {0,5}}
-debugShowCubicLineIntersection wtTs[0]=0.579011103 {{0,5}, {3,4}, {6,5}, {5,3}} {{4.4346371023199076,4.3039113069597246}} wnTs[0]=0.434637 {{4,3}, {5,6}}
-debugShowLineIntersection wtTs[0]=0.117647059 {{4,3}, {5,6}} {{4.117647058823529,3.3529411764705879}} wnTs[0]=0.176471 {{5,3}, {0,5}}
-debugShowCubicIntersection no self intersect {{0,5}, {3,4}, {6,5}, {5,3}}
-debugShowCubicLineIntersection wtTs[0]=0 {{0,5}, {3,4}, {6,5}, {5,3}} {{0,5}} wtTs[1]=1 {{5,3}} wnTs[0]=1 {{5,3}, {0,5}} wnTs[1]=0
-debugShowActiveSpans id=3 (5,6 3,5 5,0 4,3) t=0 (5,6) tEnd=0.297296392 other=4 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (5,6 3,5 5,0 4,3) t=0.297296392 (4.09290743,4.36280823) tEnd=0.442158094 other=1 otherT=0.515734731 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (5,6 3,5 5,0 4,3) t=0.442158094 (4.08799171,3.36480331) tEnd=0.454545455 other=2 otherT=0.182401651 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (5,6 3,5 5,0 4,3) t=0.454545455 (4.09466553,3.28399706) tEnd=1 other=4 otherT=0.0946656649 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (4,3 5,6) t=0 (4,3) tEnd=0.0946656649 other=3 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (4,3 5,6) t=0.0946656649 (4.09466553,3.28399706) tEnd=0.117647059 other=3 otherT=0.454545455 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (4,3 5,6) t=0.117647059 (4.11764717,3.35294127) tEnd=0.434637102 other=2 otherT=0.176470588 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (4,3 5,6) t=0.434637102 (4.43463707,4.30391121) tEnd=1 other=1 otherT=0.579011103 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,5 3,4 6,5 5,3) t=0 (0,5) tEnd=0.515734731 other=2 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,5 3,4 6,5 5,3) t=0.515734731 (4.09290743,4.36280823) tEnd=0.579011103 other=3 otherT=0.297296392 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,5 3,4 6,5 5,3) t=0.579011103 (4.43463707,4.30391121) tEnd=1 other=4 otherT=0.434637102 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,3 0,5) t=0 (5,3) tEnd=0.176470588 other=1 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,3 0,5) t=0.176470588 (4.11764717,3.35294127) tEnd=0.182401651 other=4 otherT=0.117647059 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,3 0,5) t=0.182401651 (4.08799171,3.36480331) tEnd=1 other=3 otherT=0.442158094 otherIndex=2 windSum=? windValue=1 oppValue=0
-findTop debugShowSort contourWinding=0 oppContourWinding=0 sign=1
-debugShowSort [0] {{5,6}, {3,5}, {5,0}, {4,3}} tStart=1 tEnd=0.454545455 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [1] {{4,3}, {5,6}} tStart=0 tEnd=0.0946656649 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-markWinding id=3 (5,6 3,5 5,0 4,3) t=0.454545455 [3] (4.09466553,3.28399706) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=4 (4,3 5,6) t=0 [0] (4,3) tEnd=0.0946656649 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=3 (5,6 3,5 5,0 4,3) t=0.454545455 [3] (4.09466553,3.28399706) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-markDoneBinary id=3 (5,6 3,5 5,0 4,3) t=0.454545455 [3] (4.09466553,3.28399706) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-markDoneBinary id=4 (4,3 5,6) t=0 [0] (4,3) tEnd=0.0946656649 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-findChaseOp debugShowSort contourWinding=-1 oppContourWinding=0 sign=-1
-debugShowSort [0] {{5,6}, {3,5}, {5,0}, {4,3}} tStart=0.454545455 tEnd=1 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [1] {{4,3}, {5,6}} tStart=0.0946656649 tEnd=0 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [2] {{5,6}, {3,5}, {5,0}, {4,3}} tStart=0.454545455 tEnd=0.442158094 sign=1 windValue=1 windSum=? -1->-2 (max=-2) done=0 tiny=0 opp=0
-debugShowSort [3] {{4,3}, {5,6}} tStart=0.0946656649 tEnd=0.117647059 sign=-1 windValue=1 windSum=? -2->-1 (max=-2) done=0 tiny=0 opp=0
-findChaseOp debugShowSort contourWinding=-1 oppContourWinding=0 sign=-1
-debugShowSort [0] {{5,6}, {3,5}, {5,0}, {4,3}} tStart=0.454545455 tEnd=1 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [1] {{4,3}, {5,6}} tStart=0.0946656649 tEnd=0 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [2] {{5,6}, {3,5}, {5,0}, {4,3}} tStart=0.454545455 tEnd=0.442158094 sign=1 windValue=1 windSum=? -1->-2 (max=-2) done=0 tiny=0 opp=0
-debugShowSort [3] {{4,3}, {5,6}} tStart=0.0946656649 tEnd=0.117647059 sign=-1 windValue=1 windSum=? -2->-1 (max=-2) done=0 tiny=0 opp=0
-markWinding id=3 (5,6 3,5 5,0 4,3) t=0.442158094 [2] (4.08799171,3.36480331) tEnd=0.454545455 newWindSum=-2 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=4 (4,3 5,6) t=0.0946656649 [1] (4.09466553,3.28399706) tEnd=0.117647059 newWindSum=-2 newOppSum=0 oppSum=? windSum=? windValue=1
-debugShowActiveSpans id=3 (5,6 3,5 5,0 4,3) t=0 (5,6) tEnd=0.297296392 other=4 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (5,6 3,5 5,0 4,3) t=0.297296392 (4.09290743,4.36280823) tEnd=0.442158094 other=1 otherT=0.515734731 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (5,6 3,5 5,0 4,3) t=0.442158094 (4.08799171,3.36480331) tEnd=0.454545455 other=2 otherT=0.182401651 otherIndex=2 windSum=-2 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (4,3 5,6) t=0.0946656649 (4.09466553,3.28399706) tEnd=0.117647059 other=3 otherT=0.454545455 otherIndex=3 windSum=-2 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (4,3 5,6) t=0.117647059 (4.11764717,3.35294127) tEnd=0.434637102 other=2 otherT=0.176470588 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (4,3 5,6) t=0.434637102 (4.43463707,4.30391121) tEnd=1 other=1 otherT=0.579011103 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,5 3,4 6,5 5,3) t=0 (0,5) tEnd=0.515734731 other=2 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,5 3,4 6,5 5,3) t=0.515734731 (4.09290743,4.36280823) tEnd=0.579011103 other=3 otherT=0.297296392 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,5 3,4 6,5 5,3) t=0.579011103 (4.43463707,4.30391121) tEnd=1 other=4 otherT=0.434637102 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,3 0,5) t=0 (5,3) tEnd=0.176470588 other=1 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,3 0,5) t=0.176470588 (4.11764717,3.35294127) tEnd=0.182401651 other=4 otherT=0.117647059 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,3 0,5) t=0.182401651 (4.08799171,3.36480331) tEnd=1 other=3 otherT=0.442158094 otherIndex=2 windSum=? windValue=1 oppValue=0
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=1 result=0
-markDoneBinary id=3 (5,6 3,5 5,0 4,3) t=0.442158094 [2] (4.08799171,3.36480331) tEnd=0.454545455 newWindSum=-2 newOppSum=0 oppSum=0 windSum=-2 windValue=1
-findChaseOp debugShowSort contourWinding=? oppContourWinding=? sign=1
-debugShowSort [0] {{5,3}, {0,5}} tStart=0.182401651 tEnd=0.176470588 sign=1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=0
-debugShowSort [1] {{5,6}, {3,5}, {5,0}, {4,3}} tStart=0.442158094 tEnd=0.454545455 sign=-1 windValue=1 windSum=-2 ?->? (max=?) done=1 tiny=0 opp=1
-debugShowSort [2] {{5,3}, {0,5}} tStart=0.182401651 tEnd=1 sign=-1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=0
-debugShowSort [3] {{5,6}, {3,5}, {5,0}, {4,3}} tStart=0.442158094 tEnd=0.297296392 sign=1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=1
-findChaseOp debugShowSort contourWinding=-2 oppContourWinding=0 sign=-1
-debugShowSort [1] {{5,6}, {3,5}, {5,0}, {4,3}} tStart=0.442158094 tEnd=0.454545455 sign=-1 windValue=1 windSum=-2 -2->-1 (max=-2) done=1 tiny=0 opp=0
-debugShowSort [2] {{5,3}, {0,5}} tStart=0.182401651 tEnd=1 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=1
-debugShowSort [3] {{5,6}, {3,5}, {5,0}, {4,3}} tStart=0.442158094 tEnd=0.297296392 sign=1 windValue=1 windSum=? -1->-2 (max=-2) done=0 tiny=0 opp=0
-debugShowSort [0] {{5,3}, {0,5}} tStart=0.182401651 tEnd=0.176470588 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=1
-markWinding id=2 (5,3 0,5) t=0.182401651 [2] (4.08799171,3.36480331) tEnd=1 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1
-markWinding id=1 (0,5 3,4 6,5 5,3) t=0 [0] (0,5) tEnd=0.515734731 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1
-markWinding id=3 (5,6 3,5 5,0 4,3) t=0.297296392 [1] (4.09290743,4.36280823) tEnd=0.442158094 newWindSum=-2 newOppSum=1 oppSum=? windSum=? windValue=1
-markWinding id=2 (5,3 0,5) t=0.176470588 [1] (4.11764717,3.35294127) tEnd=0.182401651 newWindSum=1 newOppSum=-2 oppSum=? windSum=? windValue=1
-debugShowActiveSpans id=3 (5,6 3,5 5,0 4,3) t=0 (5,6) tEnd=0.297296392 other=4 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (5,6 3,5 5,0 4,3) t=0.297296392 (4.09290743,4.36280823) tEnd=0.442158094 other=1 otherT=0.515734731 otherIndex=1 windSum=-2 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (4,3 5,6) t=0.0946656649 (4.09466553,3.28399706) tEnd=0.117647059 other=3 otherT=0.454545455 otherIndex=3 windSum=-2 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (4,3 5,6) t=0.117647059 (4.11764717,3.35294127) tEnd=0.434637102 other=2 otherT=0.176470588 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (4,3 5,6) t=0.434637102 (4.43463707,4.30391121) tEnd=1 other=1 otherT=0.579011103 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,5 3,4 6,5 5,3) t=0 (0,5) tEnd=0.515734731 other=2 otherT=1 otherIndex=3 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,5 3,4 6,5 5,3) t=0.515734731 (4.09290743,4.36280823) tEnd=0.579011103 other=3 otherT=0.297296392 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,5 3,4 6,5 5,3) t=0.579011103 (4.43463707,4.30391121) tEnd=1 other=4 otherT=0.434637102 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,3 0,5) t=0 (5,3) tEnd=0.176470588 other=1 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,3 0,5) t=0.176470588 (4.11764717,3.35294127) tEnd=0.182401651 other=4 otherT=0.117647059 otherIndex=2 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,3 0,5) t=0.182401651 (4.08799171,3.36480331) tEnd=1 other=3 otherT=0.442158094 otherIndex=2 windSum=1 windValue=1 oppValue=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=2 (5,3 0,5) t=0.182401651 [2] (4.08799171,3.36480331) tEnd=1 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1
-markDoneBinary id=1 (0,5 3,4 6,5 5,3) t=0 [0] (0,5) tEnd=0.515734731 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1
-debugShowActiveSpans id=3 (5,6 3,5 5,0 4,3) t=0 (5,6) tEnd=0.297296392 other=4 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (5,6 3,5 5,0 4,3) t=0.297296392 (4.09290743,4.36280823) tEnd=0.442158094 other=1 otherT=0.515734731 otherIndex=1 windSum=-2 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (4,3 5,6) t=0.0946656649 (4.09466553,3.28399706) tEnd=0.117647059 other=3 otherT=0.454545455 otherIndex=3 windSum=-2 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (4,3 5,6) t=0.117647059 (4.11764717,3.35294127) tEnd=0.434637102 other=2 otherT=0.176470588 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (4,3 5,6) t=0.434637102 (4.43463707,4.30391121) tEnd=1 other=1 otherT=0.579011103 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,5 3,4 6,5 5,3) t=0.515734731 (4.09290743,4.36280823) tEnd=0.579011103 other=3 otherT=0.297296392 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,5 3,4 6,5 5,3) t=0.579011103 (4.43463707,4.30391121) tEnd=1 other=4 otherT=0.434637102 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,3 0,5) t=0 (5,3) tEnd=0.176470588 other=1 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,3 0,5) t=0.176470588 (4.11764717,3.35294127) tEnd=0.182401651 other=4 otherT=0.117647059 otherIndex=2 windSum=1 windValue=1 oppValue=0
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=3 (5,6 3,5 5,0 4,3) t=0.297296392 [1] (4.09290743,4.36280823) tEnd=0.442158094 newWindSum=-2 newOppSum=1 oppSum=1 windSum=-2 windValue=1
-debugShowActiveSpans id=3 (5,6 3,5 5,0 4,3) t=0 (5,6) tEnd=0.297296392 other=4 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (4,3 5,6) t=0.0946656649 (4.09466553,3.28399706) tEnd=0.117647059 other=3 otherT=0.454545455 otherIndex=3 windSum=-2 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (4,3 5,6) t=0.117647059 (4.11764717,3.35294127) tEnd=0.434637102 other=2 otherT=0.176470588 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (4,3 5,6) t=0.434637102 (4.43463707,4.30391121) tEnd=1 other=1 otherT=0.579011103 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,5 3,4 6,5 5,3) t=0.515734731 (4.09290743,4.36280823) tEnd=0.579011103 other=3 otherT=0.297296392 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,5 3,4 6,5 5,3) t=0.579011103 (4.43463707,4.30391121) tEnd=1 other=4 otherT=0.434637102 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,3 0,5) t=0 (5,3) tEnd=0.176470588 other=1 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,3 0,5) t=0.176470588 (4.11764717,3.35294127) tEnd=0.182401651 other=4 otherT=0.117647059 otherIndex=2 windSum=1 windValue=1 oppValue=0
-activeOp op=diff miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
-markDoneBinary id=2 (5,3 0,5) t=0.176470588 [1] (4.11764717,3.35294127) tEnd=0.182401651 newWindSum=1 newOppSum=-2 oppSum=-2 windSum=1 windValue=1
-debugShowActiveSpans id=3 (5,6 3,5 5,0 4,3) t=0 (5,6) tEnd=0.297296392 other=4 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (4,3 5,6) t=0.0946656649 (4.09466553,3.28399706) tEnd=0.117647059 other=3 otherT=0.454545455 otherIndex=3 windSum=-2 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (4,3 5,6) t=0.117647059 (4.11764717,3.35294127) tEnd=0.434637102 other=2 otherT=0.176470588 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (4,3 5,6) t=0.434637102 (4.43463707,4.30391121) tEnd=1 other=1 otherT=0.579011103 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,5 3,4 6,5 5,3) t=0.515734731 (4.09290743,4.36280823) tEnd=0.579011103 other=3 otherT=0.297296392 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,5 3,4 6,5 5,3) t=0.579011103 (4.43463707,4.30391121) tEnd=1 other=4 otherT=0.434637102 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,3 0,5) t=0 (5,3) tEnd=0.176470588 other=1 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=1 result=0
-markDoneBinary id=4 (4,3 5,6) t=0.0946656649 [1] (4.09466553,3.28399706) tEnd=0.117647059 newWindSum=-2 newOppSum=0 oppSum=0 windSum=-2 windValue=1
-findChaseOp debugShowSort contourWinding=? oppContourWinding=? sign=-1
-debugShowSort [0] {{0,5}, {3,4}, {6,5}, {5,3}} tStart=0.515734731 tEnd=0.579011103 sign=-1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=0
-debugShowSort [1] {{5,6}, {3,5}, {5,0}, {4,3}} tStart=0.297296392 tEnd=0.442158094 sign=-1 windValue=1 windSum=-2 ?->? (max=?) done=1 tiny=0 opp=1
-debugShowSort [2] {{0,5}, {3,4}, {6,5}, {5,3}} tStart=0.515734731 tEnd=0 sign=1 windValue=1 windSum=1 ?->? (max=?) done=1 tiny=0 opp=0
-debugShowSort [3] {{5,6}, {3,5}, {5,0}, {4,3}} tStart=0.297296392 tEnd=0 sign=1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=1
-findChaseOp debugShowSort contourWinding=-2 oppContourWinding=1 sign=-1
-debugShowSort [1] {{5,6}, {3,5}, {5,0}, {4,3}} tStart=0.297296392 tEnd=0.442158094 sign=-1 windValue=1 windSum=-2 -2->-1 (max=-2) done=1 tiny=0 opp=0
-debugShowSort [2] {{0,5}, {3,4}, {6,5}, {5,3}} tStart=0.515734731 tEnd=0 sign=1 windValue=1 windSum=1 1->0 (max=1) done=1 tiny=0 opp=1
-debugShowSort [3] {{5,6}, {3,5}, {5,0}, {4,3}} tStart=0.297296392 tEnd=0 sign=1 windValue=1 windSum=? -1->-2 (max=-2) done=0 tiny=0 opp=0
-debugShowSort [0] {{0,5}, {3,4}, {6,5}, {5,3}} tStart=0.515734731 tEnd=0.579011103 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=1
-markWinding id=3 (5,6 3,5 5,0 4,3) t=0 [0] (5,6) tEnd=0.297296392 newWindSum=-2 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=4 (4,3 5,6) t=0.434637102 [3] (4.43463707,4.30391121) tEnd=1 newWindSum=-2 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=1 (0,5 3,4 6,5 5,3) t=0.515734731 [1] (4.09290743,4.36280823) tEnd=0.579011103 newWindSum=1 newOppSum=-2 oppSum=? windSum=? windValue=1
-debugShowActiveSpans id=3 (5,6 3,5 5,0 4,3) t=0 (5,6) tEnd=0.297296392 other=4 otherT=1 otherIndex=4 windSum=-2 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (4,3 5,6) t=0.117647059 (4.11764717,3.35294127) tEnd=0.434637102 other=2 otherT=0.176470588 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (4,3 5,6) t=0.434637102 (4.43463707,4.30391121) tEnd=1 other=1 otherT=0.579011103 otherIndex=2 windSum=-2 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,5 3,4 6,5 5,3) t=0.515734731 (4.09290743,4.36280823) tEnd=0.579011103 other=3 otherT=0.297296392 otherIndex=1 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,5 3,4 6,5 5,3) t=0.579011103 (4.43463707,4.30391121) tEnd=1 other=4 otherT=0.434637102 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,3 0,5) t=0 (5,3) tEnd=0.176470588 other=1 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=1 result=0
-markDoneBinary id=3 (5,6 3,5 5,0 4,3) t=0 [0] (5,6) tEnd=0.297296392 newWindSum=-2 newOppSum=0 oppSum=0 windSum=-2 windValue=1
-markDoneBinary id=4 (4,3 5,6) t=0.434637102 [3] (4.43463707,4.30391121) tEnd=1 newWindSum=-2 newOppSum=0 oppSum=0 windSum=-2 windValue=1
-debugShowActiveSpans id=4 (4,3 5,6) t=0.117647059 (4.11764717,3.35294127) tEnd=0.434637102 other=2 otherT=0.176470588 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,5 3,4 6,5 5,3) t=0.515734731 (4.09290743,4.36280823) tEnd=0.579011103 other=3 otherT=0.297296392 otherIndex=1 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,5 3,4 6,5 5,3) t=0.579011103 (4.43463707,4.30391121) tEnd=1 other=4 otherT=0.434637102 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,3 0,5) t=0 (5,3) tEnd=0.176470588 other=1 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-activeOp op=diff miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
-markDoneBinary id=1 (0,5 3,4 6,5 5,3) t=0.515734731 [1] (4.09290743,4.36280823) tEnd=0.579011103 newWindSum=1 newOppSum=-2 oppSum=-2 windSum=1 windValue=1
-findChaseOp debugShowSort contourWinding=? oppContourWinding=? sign=1
-debugShowSort [0] {{5,3}, {0,5}} tStart=0.176470588 tEnd=0 sign=1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=0
-debugShowSort [1] {{4,3}, {5,6}} tStart=0.117647059 tEnd=0.0946656649 sign=1 windValue=1 windSum=-2 ?->? (max=?) done=1 tiny=0 opp=1
-debugShowSort [2] {{5,3}, {0,5}} tStart=0.176470588 tEnd=0.182401651 sign=-1 windValue=1 windSum=1 ?->? (max=?) done=1 tiny=0 opp=0
-debugShowSort [3] {{4,3}, {5,6}} tStart=0.117647059 tEnd=0.434637102 sign=-1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=1
-findChaseOp debugShowSort contourWinding=-1 oppContourWinding=0 sign=1
-debugShowSort [1] {{4,3}, {5,6}} tStart=0.117647059 tEnd=0.0946656649 sign=1 windValue=1 windSum=-2 -1->-2 (max=-2) done=1 tiny=0 opp=0
-debugShowSort [2] {{5,3}, {0,5}} tStart=0.176470588 tEnd=0.182401651 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=1
-debugShowSort [3] {{4,3}, {5,6}} tStart=0.117647059 tEnd=0.434637102 sign=-1 windValue=1 windSum=? -2->-1 (max=-2) done=0 tiny=0 opp=0
-debugShowSort [0] {{5,3}, {0,5}} tStart=0.176470588 tEnd=0 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=1
-markWinding id=4 (4,3 5,6) t=0.117647059 [2] (4.11764717,3.35294127) tEnd=0.434637102 newWindSum=-2 newOppSum=1 oppSum=? windSum=? windValue=1
-markWinding id=2 (5,3 0,5) t=0 [0] (5,3) tEnd=0.176470588 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1
-markWinding id=1 (0,5 3,4 6,5 5,3) t=0.579011103 [2] (4.43463707,4.30391121) tEnd=1 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1
-debugShowActiveSpans id=4 (4,3 5,6) t=0.117647059 (4.11764717,3.35294127) tEnd=0.434637102 other=2 otherT=0.176470588 otherIndex=1 windSum=-2 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,5 3,4 6,5 5,3) t=0.579011103 (4.43463707,4.30391121) tEnd=1 other=4 otherT=0.434637102 otherIndex=3 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,3 0,5) t=0 (5,3) tEnd=0.176470588 other=1 otherT=1 otherIndex=3 windSum=1 windValue=1 oppValue=0
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=4 (4,3 5,6) t=0.117647059 [2] (4.11764717,3.35294127) tEnd=0.434637102 newWindSum=-2 newOppSum=1 oppSum=1 windSum=-2 windValue=1
-debugShowActiveSpans id=1 (0,5 3,4 6,5 5,3) t=0.579011103 (4.43463707,4.30391121) tEnd=1 other=4 otherT=0.434637102 otherIndex=3 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,3 0,5) t=0 (5,3) tEnd=0.176470588 other=1 otherT=1 otherIndex=3 windSum=1 windValue=1 oppValue=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=1 (0,5 3,4 6,5 5,3) t=0.579011103 [2] (4.43463707,4.30391121) tEnd=1 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1
-markDoneBinary id=2 (5,3 0,5) t=0 [0] (5,3) tEnd=0.176470588 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1
-assemble
-</div>
-
-<div id="cubicOp58da">
-$1 = {{fX = 4.09466553, fY = 3.28399706}, {fX = 4.19834709, fY = 2.10743785}, {fX = 4.5454545, fY = 1.36363637}, {fX = 4, fY = 3}}
-</div>
-
-<div id="cubicOp61d">
- SimplifyNew_Test [cubicOp61d]
-{{1,2}, {0,5}, {3,2}, {6,1}},
-{{6,1}, {1,2}},
-op difference
-{{2,3}, {1,6}, {2,1}, {5,0}},
-{{5,0}, {2,3}},
-debugShowCubicIntersection wtTs[0]=0 {{2,3}, {1,6}, {2,1}, {5,0}} {{2,3}} wtTs[1]=0.5
-debugShowCubicLineIntersection wtTs[0]=0 {{2,3}, {1,6}, {2,1}, {5,0}} {{2,3}} wtTs[1]=0.5 {{2,3}} wtTs[2]=1 {{5,0}} wnTs[0]=1 {{5,0}, {2,3}} wnTs[1]=1 wnTs[2]=0
-debugShowCubicIntersection wtTs[0]=0 {{2,3}, {1,6}, {2,1}, {5,0}} {{2,3}} wtTs[1]=0.5 {{2.0000000000728706,2.9999999998542584}} wnTs[0]=0.5 {{1,2}, {0,5}, {3,2}, {6,1}} wnTs[1]=0.500000029
-debugShowCubicLineIntersection wtTs[0]=0.704088595 {{2,3}, {1,6}, {2,1}, {5,0}} {{2.8621787139852466,1.6275642572029505}} wnTs[0]=0.627564 {{6,1}, {1,2}}
-debugShowCubicLineIntersection wtTs[0]=0.5 {{1,2}, {0,5}, {3,2}, {6,1}} {{2,3}} wnTs[0]=1 {{5,0}, {2,3}}
-debugShowLineIntersection wtTs[0]=0.5 {{5,0}, {2,3}} {{3.5,1.5}} wnTs[0]=0.5 {{6,1}, {1,2}}
-debugShowCubicIntersection no self intersect {{1,2}, {0,5}, {3,2}, {6,1}}
-debugShowCubicLineIntersection wtTs[0]=0 {{1,2}, {0,5}, {3,2}, {6,1}} {{1,2}} wtTs[1]=1 {{6,1}} wnTs[0]=1 {{6,1}, {1,2}} wnTs[1]=0
-debugShowActiveSpans id=3 (2,3 1,6 2,1 5,0) t=0 (2,3) tEnd=0.5 other=3 otherT=0.5 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (2,3 1,6 2,1 5,0) t=0 (2,3) tEnd=0.5 other=4 otherT=1 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (2,3 1,6 2,1 5,0) t=0 (2,3) tEnd=0.5 other=1 otherT=0.5 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (2,3 1,6 2,1 5,0) t=0.5 (2,3) tEnd=0.704088595 other=1 otherT=0.500000029 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (2,3 1,6 2,1 5,0) t=0.704088595 (2.8621788,1.62756431) tEnd=1 other=2 otherT=0.627564257 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (5,0 2,3) t=0 (5,0) tEnd=0.5 other=3 otherT=1 otherIndex=7 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (5,0 2,3) t=0.5 (3.5,1.5) tEnd=1 other=2 otherT=0.5 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,2 0,5 3,2 6,1) t=0 (1,2) tEnd=0.5 other=2 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,2 0,5 3,2 6,1) t=0.500000029 (2,3) tEnd=1 other=3 otherT=0.5 otherIndex=5 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (6,1 1,2) t=0 (6,1) tEnd=0.5 other=1 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (6,1 1,2) t=0.5 (3.5,1.5) tEnd=0.627564257 other=4 otherT=0.5 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (6,1 1,2) t=0.627564257 (2.8621788,1.62756431) tEnd=1 other=3 otherT=0.704088595 otherIndex=6 windSum=? windValue=1 oppValue=0
-(gdb) continue
-findTop debugShowSort contourWinding=0 oppContourWinding=0 sign=1
-debugShowSort [0] {{2,3}, {1,6}, {2,1}, {5,0}} tStart=1 tEnd=0.704088595 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [1] {{5,0}, {2,3}} tStart=0 tEnd=0.5 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-markWinding id=3 (2,3 1,6 2,1 5,0) t=0.704088595 [6] (2.8621788,1.62756431) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=4 (5,0 2,3) t=0 [0] (5,0) tEnd=0.5 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=3 (2,3 1,6 2,1 5,0) t=0.704088595 [6] (2.8621788,1.62756431) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-markDoneBinary id=3 (2,3 1,6 2,1 5,0) t=0.704088595 [6] (2.8621788,1.62756431) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-markDoneBinary id=4 (5,0 2,3) t=0 [0] (5,0) tEnd=0.5 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-findChaseOp debugShowSort contourWinding=? oppContourWinding=? sign=1
-debugShowSort [0] {{6,1}, {1,2}} tStart=0.5 tEnd=0 sign=1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=0
-debugShowSort [1] {{5,0}, {2,3}} tStart=0.5 tEnd=0 sign=1 windValue=1 windSum=-1 ?->? (max=?) done=1 tiny=0 opp=1
-debugShowSort [2] {{6,1}, {1,2}} tStart=0.5 tEnd=0.627564257 sign=-1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=0
-debugShowSort [3] {{5,0}, {2,3}} tStart=0.5 tEnd=1 sign=-1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=1
-findChaseOp debugShowSort contourWinding=0 oppContourWinding=0 sign=1
-debugShowSort [1] {{5,0}, {2,3}} tStart=0.5 tEnd=0 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [2] {{6,1}, {1,2}} tStart=0.5 tEnd=0.627564257 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=1
-debugShowSort [3] {{5,0}, {2,3}} tStart=0.5 tEnd=1 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [0] {{6,1}, {1,2}} tStart=0.5 tEnd=0 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=1
-markWinding id=2 (6,1 1,2) t=0.5 [1] (3.5,1.5) tEnd=0.627564257 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1
-markWinding id=4 (5,0 2,3) t=0.5 [1] (3.5,1.5) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-markWinding id=2 (6,1 1,2) t=0 [0] (6,1) tEnd=0.5 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=1 (1,2 0,5 3,2 6,1) t=0.500000029 [3] (2,3) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-debugShowActiveSpans id=3 (2,3 1,6 2,1 5,0) t=0 (2,3) tEnd=0.5 other=3 otherT=0.5 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (2,3 1,6 2,1 5,0) t=0 (2,3) tEnd=0.5 other=4 otherT=1 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (2,3 1,6 2,1 5,0) t=0 (2,3) tEnd=0.5 other=1 otherT=0.5 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (2,3 1,6 2,1 5,0) t=0.5 (2,3) tEnd=0.704088595 other=1 otherT=0.500000029 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (5,0 2,3) t=0.5 (3.5,1.5) tEnd=1 other=2 otherT=0.5 otherIndex=1 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,2 0,5 3,2 6,1) t=0 (1,2) tEnd=0.5 other=2 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,2 0,5 3,2 6,1) t=0.500000029 (2,3) tEnd=1 other=3 otherT=0.5 otherIndex=5 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (6,1 1,2) t=0 (6,1) tEnd=0.5 other=1 otherT=1 otherIndex=4 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (6,1 1,2) t=0.5 (3.5,1.5) tEnd=0.627564257 other=4 otherT=0.5 otherIndex=1 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (6,1 1,2) t=0.627564257 (2.8621788,1.62756431) tEnd=1 other=3 otherT=0.704088595 otherIndex=6 windSum=? windValue=1 oppValue=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=2 (6,1 1,2) t=0.5 [1] (3.5,1.5) tEnd=0.627564257 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1
-findChaseOp debugShowSort contourWinding=1 oppContourWinding=-1 sign=1
-debugShowSort [0] {{6,1}, {1,2}} tStart=0.627564257 tEnd=0.5 sign=1 windValue=1 windSum=1 1->0 (max=1) done=1 tiny=0 opp=0
-debugShowSort [1] {{2,3}, {1,6}, {2,1}, {5,0}} tStart=0.704088595 tEnd=1 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=1
-debugShowSort [2] {{6,1}, {1,2}} tStart=0.627564257 tEnd=1 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [3] {{2,3}, {1,6}, {2,1}, {5,0}} tStart=0.704088595 tEnd=0.5 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=1
-findChaseOp debugShowSort contourWinding=1 oppContourWinding=-1 sign=1
-debugShowSort [0] {{6,1}, {1,2}} tStart=0.627564257 tEnd=0.5 sign=1 windValue=1 windSum=1 1->0 (max=1) done=1 tiny=0 opp=0
-debugShowSort [1] {{2,3}, {1,6}, {2,1}, {5,0}} tStart=0.704088595 tEnd=1 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=1
-debugShowSort [2] {{6,1}, {1,2}} tStart=0.627564257 tEnd=1 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [3] {{2,3}, {1,6}, {2,1}, {5,0}} tStart=0.704088595 tEnd=0.5 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=1
-markWinding id=2 (6,1 1,2) t=0.627564257 [2] (2.8621788,1.62756431) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=1 (1,2 0,5 3,2 6,1) t=0 [0] (1,2) tEnd=0.5 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=3 (2,3 1,6 2,1 5,0) t=0.5 [5] (2,3) tEnd=0.704088595 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-debugShowActiveSpans id=3 (2,3 1,6 2,1 5,0) t=0 (2,3) tEnd=0.5 other=3 otherT=0.5 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (2,3 1,6 2,1 5,0) t=0 (2,3) tEnd=0.5 other=4 otherT=1 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (2,3 1,6 2,1 5,0) t=0 (2,3) tEnd=0.5 other=1 otherT=0.5 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (2,3 1,6 2,1 5,0) t=0.5 (2,3) tEnd=0.704088595 other=1 otherT=0.500000029 otherIndex=3 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (5,0 2,3) t=0.5 (3.5,1.5) tEnd=1 other=2 otherT=0.5 otherIndex=1 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,2 0,5 3,2 6,1) t=0 (1,2) tEnd=0.5 other=2 otherT=1 otherIndex=3 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,2 0,5 3,2 6,1) t=0.500000029 (2,3) tEnd=1 other=3 otherT=0.5 otherIndex=5 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (6,1 1,2) t=0 (6,1) tEnd=0.5 other=1 otherT=1 otherIndex=4 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (6,1 1,2) t=0.627564257 (2.8621788,1.62756431) tEnd=1 other=3 otherT=0.704088595 otherIndex=6 windSum=1 windValue=1 oppValue=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-findNextOp simple
-markDoneBinary id=2 (6,1 1,2) t=0.627564257 [2] (2.8621788,1.62756431) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-bridgeOp current id=2 from=(2.8621788,1.62756431) to=(1,2)
-setSpans all tiny unsortable [1] (2,3) [0] (1,2)
-setSpans all tiny unsortable [1] (2,3) [3] (2.00000024,3)
-markUnsortable id=1 (1,2 0,5 3,2 6,1) t=0 [0] (1,2) tEnd=0.5 newWindSum=0 windSum=1 windValue=1
-markUnsortable id=1 (1,2 0,5 3,2 6,1) t=0.5 [1] (2,3) tEnd=0.5 newWindSum=0 windSum=? windValue=1
-markUnsortable id=3 (2,3 1,6 2,1 5,0) t=0 [2] (2,3) tEnd=0.5 newWindSum=0 windSum=? windValue=1
-markUnsortable id=4 (5,0 2,3) t=1 [3] (2,3) tEnd=1 newWindSum=0 windSum=? windValue=1
-findNextOp debugShowSort contourWinding=1 oppContourWinding=0 sign=1
-debugShowSort [0] *** UNSORTABLE *** {{1,2}, {0,5}, {3,2}, {6,1}} tStart=0.5 tEnd=0 sign=1 windValue=1 windSum=1 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] *** UNSORTABLE *** {{1,2}, {0,5}, {3,2}, {6,1}} tStart=0.5 tEnd=0.500000029 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=1 tiny=1 opp=0
-debugShowSort [2] {{2,3}, {1,6}, {2,1}, {5,0}} tStart=0 tEnd=0.5 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=1
-debugShowSort [3] {{5,0}, {2,3}} tStart=1 tEnd=0.5 sign=1 windValue=1 windSum=-1 1->0 (max=1) done=0 tiny=0 opp=1
-path.moveTo(2.8621788,1.62756431);
-path.lineTo(1,2);
-path.cubicTo(0.5,3.5, 1,3.5, 2,3);
-markDoneBinary id=1 (1,2 0,5 3,2 6,1) t=0 [0] (1,2) tEnd=0.5 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-debugShowActiveSpans id=3 (2,3 1,6 2,1 5,0) t=0 (2,3) tEnd=0.5 other=3 otherT=0.5 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (2,3 1,6 2,1 5,0) t=0 (2,3) tEnd=0.5 other=4 otherT=1 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (2,3 1,6 2,1 5,0) t=0 (2,3) tEnd=0.5 other=1 otherT=0.5 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (2,3 1,6 2,1 5,0) t=0.5 (2,3) tEnd=0.704088595 other=1 otherT=0.500000029 otherIndex=3 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (5,0 2,3) t=0.5 (3.5,1.5) tEnd=1 other=2 otherT=0.5 otherIndex=1 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,2 0,5 3,2 6,1) t=0.500000029 (2,3) tEnd=1 other=3 otherT=0.5 otherIndex=5 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (6,1 1,2) t=0 (6,1) tEnd=0.5 other=1 otherT=1 otherIndex=4 windSum=1 windValue=1 oppValue=0
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
-setSpans unsortable [2] (2,3) [3] (2,3)
-setSpans all tiny unsortable [4] (2,3) [2] (2,3)
-setSpans all tiny unsortable [2] (2,3) [3] (2.00000024,3)
-setSpans all tiny unsortable [2] (2,3) [0] (1,2)
-markUnsortable id=4 (5,0 2,3) t=0.5 [1] (3.5,1.5) tEnd=1 newWindSum=0 windSum=-1 windValue=1
-markUnsortable id=3 (2,3 1,6 2,1 5,0) t=0 [1] (2,3) tEnd=0 newWindSum=0 windSum=? windValue=1
-markUnsortable id=3 (2,3 1,6 2,1 5,0) t=0.5 [4] (2,3) tEnd=0.5 newWindSum=0 windSum=? windValue=1
-markUnsortable id=3 (2,3 1,6 2,1 5,0) t=0.5 [3] (2,3) tEnd=0.5 newWindSum=0 windSum=? windValue=1
-markUnsortable id=1 (1,2 0,5 3,2 6,1) t=0.5 [2] (2,3) tEnd=0.500000029 newWindSum=0 windSum=? windValue=1
-markUnsortable id=1 (1,2 0,5 3,2 6,1) t=0.5 [1] (2,3) tEnd=0.5 newWindSum=0 windSum=? windValue=1
-findNextOp debugShowSort contourWinding=0 oppContourWinding=1 sign=1
-debugShowSort [0] {{5,0}, {2,3}} tStart=1 tEnd=0.5 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [1] *** UNSORTABLE *** {{2,3}, {1,6}, {2,1}, {5,0}} tStart=0 tEnd=0.5 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [2] *** UNSORTABLE *** {{2,3}, {1,6}, {2,1}, {5,0}} tStart=0.5 tEnd=0.5 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=1 tiny=1 opp=0
-debugShowSort [3] *** UNSORTABLE *** {{2,3}, {1,6}, {2,1}, {5,0}} tStart=0.5 tEnd=0 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [4] *** UNSORTABLE *** {{1,2}, {0,5}, {3,2}, {6,1}} tStart=0.5 tEnd=0.500000029 sign=-1 windValue=1 windSum=? 1->2 (max=2) done=1 tiny=1 opp=1
-debugShowSort [5] *** UNSORTABLE *** {{1,2}, {0,5}, {3,2}, {6,1}} tStart=0.5 tEnd=0 sign=1 windValue=1 windSum=1 2->1 (max=2) done=1 tiny=0 opp=1
-markDoneBinary id=4 (5,0 2,3) t=0.5 [1] (3.5,1.5) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1
-path.moveTo(3.5,1.5);
-path.lineTo(2,3);
-debugShowActiveSpans id=3 (2,3 1,6 2,1 5,0) t=0 (2,3) tEnd=0.5 other=3 otherT=0.5 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (2,3 1,6 2,1 5,0) t=0 (2,3) tEnd=0.5 other=4 otherT=1 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (2,3 1,6 2,1 5,0) t=0 (2,3) tEnd=0.5 other=1 otherT=0.5 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (2,3 1,6 2,1 5,0) t=0.5 (2,3) tEnd=0.704088595 other=1 otherT=0.500000029 otherIndex=3 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,2 0,5 3,2 6,1) t=0.500000029 (2,3) tEnd=1 other=3 otherT=0.5 otherIndex=5 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (6,1 1,2) t=0 (6,1) tEnd=0.5 other=1 otherT=1 otherIndex=4 windSum=1 windValue=1 oppValue=0
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-markUnsortable id=3 (2,3 1,6 2,1 5,0) t=0.5 [5] (2,3) tEnd=0.704088595 newWindSum=0 windSum=-1 windValue=1
-markUnsortable id=3 (2,3 1,6 2,1 5,0) t=0.5 [4] (2,3) tEnd=0.5 newWindSum=0 windSum=? windValue=1
-markUnsortable id=1 (1,2 0,5 3,2 6,1) t=0.500000029 [3] (2,3) tEnd=1 newWindSum=0 windSum=1 windValue=1
-markUnsortable id=1 (1,2 0,5 3,2 6,1) t=0.5 [2] (2,3) tEnd=0.500000029 newWindSum=0 windSum=? windValue=1
-findNextOp debugShowSort contourWinding=-1 oppContourWinding=1 sign=-1
-debugShowSort [0] {{2,3}, {1,6}, {2,1}, {5,0}} tStart=0.5 tEnd=0.704088595 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [1] *** UNSORTABLE *** {{2,3}, {1,6}, {2,1}, {5,0}} tStart=0.5 tEnd=0.5 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=1 tiny=1 opp=0
-debugShowSort [2] {{1,2}, {0,5}, {3,2}, {6,1}} tStart=0.500000029 tEnd=1 sign=-1 windValue=1 windSum=1 1->2 (max=2) done=0 tiny=0 opp=1
-debugShowSort [3] {{1,2}, {0,5}, {3,2}, {6,1}} tStart=0.500000029 tEnd=0.5 sign=1 windValue=1 windSum=? 2->1 (max=2) done=1 tiny=1 opp=1
-path.moveTo(2.8621788,1.62756431);
-path.cubicTo(2.49148154,2.10034132, 2.20408869,2.59182286, 2,3);
-markDoneBinary id=3 (2,3 1,6 2,1 5,0) t=0.5 [5] (2,3) tEnd=0.704088595 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1
-debugShowActiveSpans id=3 (2,3 1,6 2,1 5,0) t=0 (2,3) tEnd=0.5 other=3 otherT=0.5 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (2,3 1,6 2,1 5,0) t=0 (2,3) tEnd=0.5 other=4 otherT=1 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (2,3 1,6 2,1 5,0) t=0 (2,3) tEnd=0.5 other=1 otherT=0.5 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,2 0,5 3,2 6,1) t=0.500000029 (2,3) tEnd=1 other=3 otherT=0.5 otherIndex=5 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (6,1 1,2) t=0 (6,1) tEnd=0.5 other=1 otherT=1 otherIndex=4 windSum=1 windValue=1 oppValue=0
-activeOp op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-findNextOp simple
-markDoneBinary id=2 (6,1 1,2) t=0 [0] (6,1) tEnd=0.5 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-bridgeOp current id=2 from=(3.5,1.5) to=(6,1)
-setSpans unsortable [3] (2.00000024,3) [4] (6,1)
-setSpans unsortable [3] (2.00000024,3) [2] (2,3)
-setSpans unsortable [5] (2,3) [6] (2.8621788,1.62756431)
-markUnsortable id=1 (1,2 0,5 3,2 6,1) t=0.500000029 [3] (2,3) tEnd=1 newWindSum=0 windSum=1 windValue=1
-markUnsortable id=1 (1,2 0,5 3,2 6,1) t=0.5 [2] (2,3) tEnd=0.500000029 newWindSum=0 windSum=? windValue=1
-markUnsortable id=3 (2,3 1,6 2,1 5,0) t=0.5 [5] (2,3) tEnd=0.704088595 newWindSum=0 windSum=-1 windValue=1
-markUnsortable id=3 (2,3 1,6 2,1 5,0) t=0.5 [4] (2,3) tEnd=0.5 newWindSum=0 windSum=? windValue=1
-findNextOp debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [0] *** UNSORTABLE *** {{1,2}, {0,5}, {3,2}, {6,1}} tStart=0.500000029 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] *** UNSORTABLE *** {{1,2}, {0,5}, {3,2}, {6,1}} tStart=0.500000029 tEnd=0.5 sign=1 windValue=1 windSum=? 1->0 (max=1) done=1 tiny=1 opp=0
-debugShowSort [2] *** UNSORTABLE *** {{2,3}, {1,6}, {2,1}, {5,0}} tStart=0.5 tEnd=0.704088595 sign=-1 windValue=1 windSum=-1 0->1 (max=1) done=1 tiny=0 opp=1
-debugShowSort [3] *** UNSORTABLE *** {{2,3}, {1,6}, {2,1}, {5,0}} tStart=0.5 tEnd=0.5 sign=1 windValue=1 windSum=? 1->0 (max=1) done=1 tiny=1 opp=1
-path.moveTo(3.5,1.5);
-path.lineTo(6,1);
-path.cubicTo(4.5,1.5, 3.00000024,2.49999976, 2,3);
-markDoneBinary id=1 (1,2 0,5 3,2 6,1) t=0.500000029 [3] (2,3) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-debugShowActiveSpans id=3 (2,3 1,6 2,1 5,0) t=0 (2,3) tEnd=0.5 other=3 otherT=0.5 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (2,3 1,6 2,1 5,0) t=0 (2,3) tEnd=0.5 other=4 otherT=1 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (2,3 1,6 2,1 5,0) t=0 (2,3) tEnd=0.5 other=1 otherT=0.5 otherIndex=1 windSum=? windValue=1 oppValue=0
-</div>
-
-<div id="cubicOp62d">
- SimplifyNew_Test [cubicOp62d]
-{{1,3}, {5,6}, {5,3}, {5,4}},
-{{5,4}, {1,3}},
-op difference
-{{3,5}, {4,5}, {3,1}, {6,5}},
-{{6,5}, {3,5}},
-debugShowCubicIntersection no self intersect {{1,3}, {5,6}, {5,3}, {5,4}}
-debugShowCubicLineIntersection wtTs[0]=0 {{1,3}, {5,6}, {5,3}, {5,4}} {{1,3}} wtTs[1]=0.666666667 {{4.8518518518518512,3.9629629629629628}} wtTs[2]=1 {{5,4}} wnTs[0]=1 {{5,4}, {1,3}} wnTs[1]=0.037037037 wnTs[2]=0
-debugShowCubicIntersection wtTs[0]=0.278899971 {{1,3}, {5,6}, {5,3}, {5,4}} {{3.5001544800676263,4.3269091333431628}} wtTs[1]=0.855895664 {{4.9880300830066844,3.7869549154423883}} wtTs[2]=0.865207906 {{4.9902038991416013,3.7891603690182212}} wtTs[3]=0.865213351 {{4.9902050861407137,3.789162057358868}} wnTs[0]=0.2789 {{3,5}, {4,5}, {3,1}, {6,5}} wnTs[1]=0.864850875 wnTs[2]=0.865207887 wnTs[3]=0.865208087
-debugShowCubicLineIntersection wtTs[0]=0.448187637 {{3,5}, {4,5}, {3,1}, {6,5}} {{3.6795004703683416,3.6698751175920856}} wnTs[0]=0.330125 {{5,4}, {1,3}}
-debugShowCubicIntersection no self intersect {{3,5}, {4,5}, {3,1}, {6,5}}
-debugShowCubicLineIntersection wtTs[0]=0 {{3,5}, {4,5}, {3,1}, {6,5}} {{3,5}} wtTs[1]=1 {{6,5}} wnTs[0]=1 {{6,5}, {3,5}} wnTs[1]=0
-debugShowActiveSpans id=1 (1,3 5,6 5,3 5,4) t=0 (1,3) tEnd=0.278899971 other=2 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 5,6 5,3 5,4) t=0.278899971 (3.5001545,4.32690907) tEnd=0.666666667 other=3 otherT=0.278899971 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 5,6 5,3 5,4) t=0.666666667 (4.85185194,3.96296287) tEnd=0.855895664 other=2 otherT=0.037037037 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 5,6 5,3 5,4) t=0.855895664 (4.98802996,3.78695488) tEnd=0.865207906 other=3 otherT=0.864850875 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 5,6 5,3 5,4) t=0.865207906 (4.99020386,3.78916025) tEnd=0.865213351 other=3 otherT=0.865207887 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 5,6 5,3 5,4) t=0.865213351 (4.99020529,3.78916216) tEnd=1 other=3 otherT=0.865208087 otherIndex=5 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,4 1,3) t=0 (5,4) tEnd=0.037037037 other=1 otherT=1 otherIndex=6 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,4 1,3) t=0.037037037 (4.85185194,3.96296287) tEnd=0.330124882 other=1 otherT=0.666666667 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,4 1,3) t=0.330124882 (3.67950058,3.66987514) tEnd=1 other=3 otherT=0.448187637 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (3,5 4,5 3,1 6,5) t=0 (3,5) tEnd=0.278899971 other=4 otherT=1 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (3,5 4,5 3,1 6,5) t=0.278899971 (3.5001545,4.32690907) tEnd=0.448187637 other=1 otherT=0.278899971 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (3,5 4,5 3,1 6,5) t=0.448187637 (3.67950058,3.66987514) tEnd=0.864850875 other=2 otherT=0.330124882 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (3,5 4,5 3,1 6,5) t=0.864850875 (4.98802996,3.78695488) tEnd=0.865207887 other=1 otherT=0.855895664 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (3,5 4,5 3,1 6,5) t=0.865207887 (4.99020386,3.78916025) tEnd=0.865208087 other=1 otherT=0.865207906 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (3,5 4,5 3,1 6,5) t=0.865208087 (4.99020529,3.78916216) tEnd=1 other=1 otherT=0.865213351 otherIndex=5 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (6,5 3,5) t=0 (6,5) tEnd=1 other=3 otherT=1 otherIndex=6 windSum=? windValue=1 oppValue=0
-findTop debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [0] {{1,3}, {5,6}, {5,3}, {5,4}} tStart=0 tEnd=0.278899971 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] {{5,4}, {1,3}} tStart=1 tEnd=0.330124882 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=0
-markWinding id=1 (1,3 5,6 5,3 5,4) t=0 [0] (1,3) tEnd=0.278899971 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=2 (5,4 1,3) t=0.330124882 [2] (3.67950058,3.66987514) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=1 (1,3 5,6 5,3 5,4) t=0 [0] (1,3) tEnd=0.278899971 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-activeOp op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-findNextOp simple
-markDoneBinary id=1 (1,3 5,6 5,3 5,4) t=0 [0] (1,3) tEnd=0.278899971 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-bridgeOp current id=1 from=(3.5001545,4.32690907) to=(1,3)
-path.moveTo(3.5001545,4.32690907);
-path.cubicTo(2.92005897,4.20668888, 2.11559987,3.83669996, 1,3);
-findNextOp debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [1] {{5,4}, {1,3}} tStart=0.330124882 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [2] {{3,5}, {4,5}, {3,1}, {6,5}} tStart=0.448187637 tEnd=0.278899971 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=1
-debugShowSort [3] {{5,4}, {1,3}} tStart=0.330124882 tEnd=0.037037037 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [0] {{3,5}, {4,5}, {3,1}, {6,5}} tStart=0.448187637 tEnd=0.864850875 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=1
-findNextOp firstIndex=[1] sign=-1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-markWinding id=3 (3,5 4,5 3,1 6,5) t=0.278899971 [1] (3.5001545,4.32690907) tEnd=0.448187637 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-activeOp op=diff miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
-markDoneBinary id=2 (5,4 1,3) t=0.037037037 [1] (4.85185194,3.96296287) tEnd=0.330124882 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=2
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-markDoneBinary id=3 (3,5 4,5 3,1 6,5) t=0.448187637 [2] (3.67950058,3.66987514) tEnd=0.864850875 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-markDoneBinary id=2 (5,4 1,3) t=0.330124882 [2] (3.67950058,3.66987514) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-findNextOp from:[2] to:[3] start=2 end=1
-bridgeOp current id=2 from=(1,3) to=(3.67950058,3.66987514)
-findNextOp debugShowSort contourWinding=-1 oppContourWinding=1 sign=-1
-debugShowSort [0] {{3,5}, {4,5}, {3,1}, {6,5}} tStart=0.278899971 tEnd=0.448187637 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [1] {{1,3}, {5,6}, {5,3}, {5,4}} tStart=0.278899971 tEnd=0 sign=1 windValue=1 windSum=1 1->0 (max=1) done=1 tiny=0 opp=1
-debugShowSort [2] {{3,5}, {4,5}, {3,1}, {6,5}} tStart=0.278899971 tEnd=0 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [3] {{1,3}, {5,6}, {5,3}, {5,4}} tStart=0.278899971 tEnd=0.666666667 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=1
-findNextOp firstIndex=[0] sign=-1
-activeOp op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-activeOp op=diff miFrom=0 miTo=0 suFrom=0 suTo=1 result=0
-markDoneBinary id=3 (3,5 4,5 3,1 6,5) t=0 [0] (3,5) tEnd=0.278899971 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-markDoneBinary id=4 (6,5 3,5) t=0 [0] (6,5) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-markDoneBinary id=3 (3,5 4,5 3,1 6,5) t=0.865208087 [5] (4.99020529,3.78916216) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-activeOp op=diff miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=1 (1,3 5,6 5,3 5,4) t=0.278899971 [1] (3.5001545,4.32690907) tEnd=0.666666667 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=1
-markDoneBinary id=3 (3,5 4,5 3,1 6,5) t=0.278899971 [1] (3.5001545,4.32690907) tEnd=0.448187637 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1
-findNextOp from:[3] to:[1] start=1 end=0
-bridgeOp current id=3 from=(3.67950058,3.66987514) to=(3.5001545,4.32690907)
-path.lineTo(3.67950058,3.66987514);
-path.cubicTo(3.60967231,3.86879396, 3.5595932,4.10721159, 3.5001545,4.32690907);
-path.close();
-findChaseOp debugShowSort contourWinding=? oppContourWinding=? sign=-1
-debugShowSort [0] {{1,3}, {5,6}, {5,3}, {5,4}} tStart=0.666666667 tEnd=0.855895664 sign=-1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=0
-debugShowSort [1] {{5,4}, {1,3}} tStart=0.037037037 tEnd=0.330124882 sign=-1 windValue=1 windSum=1 ?->? (max=?) done=1 tiny=0 opp=0
-debugShowSort [2] {{1,3}, {5,6}, {5,3}, {5,4}} tStart=0.666666667 tEnd=0.278899971 sign=1 windValue=1 windSum=1 ?->? (max=?) done=1 tiny=0 opp=0
-debugShowSort [3] {{5,4}, {1,3}} tStart=0.037037037 tEnd=0 sign=1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=0
-findChaseOp debugShowSort contourWinding=0 oppContourWinding=-1 sign=-1
-debugShowSort [1] {{5,4}, {1,3}} tStart=0.037037037 tEnd=0.330124882 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=0
-debugShowSort [2] {{1,3}, {5,6}, {5,3}, {5,4}} tStart=0.666666667 tEnd=0.278899971 sign=1 windValue=1 windSum=1 1->0 (max=1) done=1 tiny=0 opp=0
-debugShowSort [3] {{5,4}, {1,3}} tStart=0.037037037 tEnd=0 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [0] {{1,3}, {5,6}, {5,3}, {5,4}} tStart=0.666666667 tEnd=0.855895664 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-markWinding id=2 (5,4 1,3) t=0 [0] (5,4) tEnd=0.037037037 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1
-markWinding id=1 (1,3 5,6 5,3 5,4) t=0.865213351 [5] (4.99020529,3.78916216) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1
-markWinding id=1 (1,3 5,6 5,3 5,4) t=0.666666667 [2] (4.85185194,3.96296287) tEnd=0.855895664 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1
-debugShowActiveSpans id=1 (1,3 5,6 5,3 5,4) t=0.666666667 (4.85185194,3.96296287) tEnd=0.855895664 other=2 otherT=0.037037037 otherIndex=1 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 5,6 5,3 5,4) t=0.855895664 (4.98802996,3.78695488) tEnd=0.865207906 other=3 otherT=0.864850875 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 5,6 5,3 5,4) t=0.865207906 (4.99020386,3.78916025) tEnd=0.865213351 other=3 otherT=0.865207887 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 5,6 5,3 5,4) t=0.865213351 (4.99020529,3.78916216) tEnd=1 other=3 otherT=0.865208087 otherIndex=5 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,4 1,3) t=0 (5,4) tEnd=0.037037037 other=1 otherT=1 otherIndex=6 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=3 (3,5 4,5 3,1 6,5) t=0.864850875 (4.98802996,3.78695488) tEnd=0.865207887 other=1 otherT=0.855895664 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (3,5 4,5 3,1 6,5) t=0.865207887 (4.99020386,3.78916025) tEnd=0.865208087 other=1 otherT=0.865207906 otherIndex=4 windSum=? windValue=1 oppValue=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=2 (5,4 1,3) t=0 [0] (5,4) tEnd=0.037037037 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1
-markDoneBinary id=1 (1,3 5,6 5,3 5,4) t=0.865213351 [5] (4.99020529,3.78916216) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1
-findChaseOp debugShowSort contourWinding=? oppContourWinding=? sign=1
-debugShowSort [0] {{1,3}, {5,6}, {5,3}, {5,4}} tStart=0.865213351 tEnd=0.865207906 sign=1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=0
-debugShowSort [1] {{3,5}, {4,5}, {3,1}, {6,5}} tStart=0.865208087 tEnd=0.865207887 sign=1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=1
-debugShowSort [2] {{1,3}, {5,6}, {5,3}, {5,4}} tStart=0.865213351 tEnd=1 sign=-1 windValue=1 windSum=-1 ?->? (max=?) done=1 tiny=0 opp=0
-debugShowSort [3] {{3,5}, {4,5}, {3,1}, {6,5}} tStart=0.865208087 tEnd=1 sign=-1 windValue=1 windSum=-1 ?->? (max=?) done=1 tiny=0 opp=1
-findChaseOp debugShowSort contourWinding=-1 oppContourWinding=-1 sign=-1
-debugShowSort [2] {{1,3}, {5,6}, {5,3}, {5,4}} tStart=0.865213351 tEnd=1 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [3] {{3,5}, {4,5}, {3,1}, {6,5}} tStart=0.865208087 tEnd=1 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=1
-debugShowSort [0] {{1,3}, {5,6}, {5,3}, {5,4}} tStart=0.865213351 tEnd=0.865207906 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [1] {{3,5}, {4,5}, {3,1}, {6,5}} tStart=0.865208087 tEnd=0.865207887 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=1
-markWinding id=1 (1,3 5,6 5,3 5,4) t=0.865207906 [4] (4.99020386,3.78916025) tEnd=0.865213351 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=3 (3,5 4,5 3,1 6,5) t=0.865207887 [4] (4.99020386,3.78916025) tEnd=0.865208087 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1
-debugShowActiveSpans id=1 (1,3 5,6 5,3 5,4) t=0.666666667 (4.85185194,3.96296287) tEnd=0.855895664 other=2 otherT=0.037037037 otherIndex=1 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 5,6 5,3 5,4) t=0.855895664 (4.98802996,3.78695488) tEnd=0.865207906 other=3 otherT=0.864850875 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 5,6 5,3 5,4) t=0.865207906 (4.99020386,3.78916025) tEnd=0.865213351 other=3 otherT=0.865207887 otherIndex=4 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=3 (3,5 4,5 3,1 6,5) t=0.864850875 (4.98802996,3.78695488) tEnd=0.865207887 other=1 otherT=0.855895664 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (3,5 4,5 3,1 6,5) t=0.865207887 (4.99020386,3.78916025) tEnd=0.865208087 other=1 otherT=0.865207906 otherIndex=4 windSum=-1 windValue=1 oppValue=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-findNextOp debugShowSort contourWinding=-1 oppContourWinding=0 sign=-1
-debugShowSort [2] {{1,3}, {5,6}, {5,3}, {5,4}} tStart=0.865207906 tEnd=0.865213351 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [3] {{3,5}, {4,5}, {3,1}, {6,5}} tStart=0.865207887 tEnd=0.865208087 sign=-1 windValue=1 windSum=-1 0->1 (max=1) done=0 tiny=0 opp=1
-debugShowSort [0] {{1,3}, {5,6}, {5,3}, {5,4}} tStart=0.865207906 tEnd=0.855895664 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [1] {{3,5}, {4,5}, {3,1}, {6,5}} tStart=0.865207887 tEnd=0.864850875 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=1
-findNextOp firstIndex=[2] sign=-1
-activeOp op=diff miFrom=0 miTo=0 suFrom=0 suTo=1 result=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=1 (1,3 5,6 5,3 5,4) t=0.855895664 [3] (4.98802996,3.78695488) tEnd=0.865207906 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
-markWinding id=3 (3,5 4,5 3,1 6,5) t=0.864850875 [3] (4.98802996,3.78695488) tEnd=0.865207887 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-markDoneBinary id=1 (1,3 5,6 5,3 5,4) t=0.865207906 [4] (4.99020386,3.78916025) tEnd=0.865213351 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-findNextOp from:[1] to:[3] start=4 end=3
-bridgeOp current id=1 from=(4.99020529,3.78916216) to=(4.99020386,3.78916025)
-path.moveTo(4.99020529,3.78916216);
-path.cubicTo(4.99020433,3.78916144, 4.99020433,3.78916097, 4.99020386,3.78916025);
-findNextOp debugShowSort contourWinding=0 oppContourWinding=-1 sign=-1
-debugShowSort [2] {{3,5}, {4,5}, {3,1}, {6,5}} tStart=0.864850875 tEnd=0.865207887 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [3] {{1,3}, {5,6}, {5,3}, {5,4}} tStart=0.855895664 tEnd=0.865207906 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=1
-debugShowSort [0] {{3,5}, {4,5}, {3,1}, {6,5}} tStart=0.864850875 tEnd=0.448187637 sign=1 windValue=1 windSum=-1 1->0 (max=1) done=1 tiny=0 opp=0
-debugShowSort [1] {{1,3}, {5,6}, {5,3}, {5,4}} tStart=0.855895664 tEnd=0.666666667 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=0 tiny=0 opp=1
-findNextOp firstIndex=[2] sign=-1
-activeOp op=diff miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-markDoneBinary id=3 (3,5 4,5 3,1 6,5) t=0.864850875 [3] (4.98802996,3.78695488) tEnd=0.865207887 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1
-findNextOp from:[3] to:[1] start=3 end=2
-bridgeOp current id=3 from=(4.99020386,3.78916025) to=(4.98802996,3.78695488)
-path.cubicTo(4.98947859,3.78842425, 4.98875427,3.78768921, 4.98802996,3.78695488);
-findNextOp debugShowSort contourWinding=-1 oppContourWinding=-1 sign=-1
-debugShowSort [0] {{1,3}, {5,6}, {5,3}, {5,4}} tStart=0.666666667 tEnd=0.855895664 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [1] {{5,4}, {1,3}} tStart=0.037037037 tEnd=0.330124882 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=0
-debugShowSort [2] {{1,3}, {5,6}, {5,3}, {5,4}} tStart=0.666666667 tEnd=0.278899971 sign=1 windValue=1 windSum=1 1->0 (max=1) done=1 tiny=0 opp=0
-debugShowSort [3] {{5,4}, {1,3}} tStart=0.037037037 tEnd=0 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=0
-findNextOp firstIndex=[0] sign=-1
-activeOp op=diff miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-activeOp op=diff miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=1 (1,3 5,6 5,3 5,4) t=0.666666667 [2] (4.85185194,3.96296287) tEnd=0.855895664 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1
-path.cubicTo(4.97231197,3.77658033, 4.93595362,3.85783577, 4.85185194,3.96296287);
-</div>
-
-<div id="testQuad1">
- RunTestSet [testQuad1]
-{{0,0}, {0,0}, {0,1}},
-{{0,1}, {1,1}},
-{{1,1}, {0,0}},
-{{0,0}, {1,1}, {0,2}},
-{{0,2}, {0,0}},
-debugShowLineIntersection wtTs[0]=0 {{0,0}, {0,1}} {{0,1}} wnTs[0]=1 {{0,1}, {1,1}}
-debugShowLineIntersection wtTs[0]=1 {{0,0}, {0,1}} {{0,0}} wnTs[0]=0 {{1,1}, {0,0}}
-debugShowLineIntersection wtTs[0]=-0 {{0,1}, {1,1}} {{1,1}} wnTs[0]=1 {{1,1}, {0,0}}
-debugShowQuadLineIntersection wtTs[0]=0 {{0,0}, {1,1}, {0,2}} {{0,0}} wnTs[0]=0 {{0,0}, {0,1}}
-debugShowLineIntersection wtTs[0]=1 {{0,0}, {0,1}} {{0,0}} wtTs[1]=0.5 {{0,1}} wnTs[0]=-0 {{0,2}, {0,0}} wnTs[1]=1
-debugShowQuadLineIntersection wtTs[0]=0.5 {{0,0}, {1,1}, {0,2}} {{0.5,1}} wnTs[0]=0.5 {{0,1}, {1,1}}
-debugShowLineIntersection wtTs[0]=0.5 {{0,1}, {1,1}} {{0,1}} wnTs[0]=0 {{0,2}, {0,0}}
-debugShowQuadLineIntersection wtTs[0]=0 {{0,0}, {1,1}, {0,2}} {{0,0}} wnTs[0]=1 {{1,1}, {0,0}}
-debugShowLineIntersection wtTs[0]=1 {{1,1}, {0,0}} {{0,0}} wnTs[0]=1 {{0,2}, {0,0}}
-debugShowQuadLineIntersection wtTs[0]=0 {{0,0}, {1,1}, {0,2}} {{0,0}} wtTs[1]=1 {{0,2}} wnTs[0]=1 {{0,2}, {0,0}} wnTs[1]=0
-debugShowTs id=1 [o=3,4 t=0 0,0 w=1 o=0] [o=2 t=1 0,1 w=1 o=0]
-debugShowTs id=5 [o=4 t=0 0,2 w=1 o=0] [o=2 t=0.5 0,1 w=1 o=0] [o=3,4 t=1 0,0 w=1 o=0]
-addTPair addTPair this=5 0.5 other=1 1
-debugShowTs id=1 [o=3,4 t=0 0,0 w=1 o=0] [o=2,5 t=1 0,1 w=1 o=0]
-debugShowTs id=5 [o=4 t=0 0,2 w=1 o=0] [o=2,1 t=0.5 0,1 w=1 o=0] [o=3,4 t=1 0,0 w=1 o=0]
-debugShowTs id=1 [o=3,4 t=0 0,0 w=0 o=0] [o=2,5 t=1 0,1 w=1 o=0] done
-debugShowTs id=5 [o=4 t=0 0,2 w=1 o=0] [o=2,1 t=0.5 0,1 w=0 o=0] [o=3,4 t=1 0,0 w=1 o=0]
-debugShowActiveSpans id=2 (0,1 1,1) t=0 (0,1) tEnd=0.5 other=1 otherT=1 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (0,1 1,1) t=0 (0,1) tEnd=0.5 other=5 otherT=0.5 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (0,1 1,1) t=0.5 (0.5,1) tEnd=1 other=4 otherT=0.5 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,1 0,0) t=-0 (1,1) tEnd=1 other=2 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (0,0 1,1 0,2) t=0 (0,0) tEnd=0.5 other=1 otherT=0 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (0,0 1,1 0,2) t=0 (0,0) tEnd=0.5 other=3 otherT=1 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (0,0 1,1 0,2) t=0 (0,0) tEnd=0.5 other=5 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (0,0 1,1 0,2) t=0.5 (0.5,1) tEnd=1 other=2 otherT=0.5 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=5 (0,2 0,0) t=0 (0,2) tEnd=0.5 other=4 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-findTop debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [0] {{0,0}, {1,1}, {0,2}} tStart=0 tEnd=0.5 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] {{1,1}, {0,0}} tStart=1 tEnd=-0 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=0
-findTop swap=1 serpentine=0 controls_contained_by_ends=0
-markWinding id=4 (0,0 1,1 0,2) t=0 [0] (0,0) tEnd=0 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=4 (0,0 1,1 0,2) t=0 [1] (0,0) tEnd=0 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=4 (0,0 1,1 0,2) t=0 [2] (0,0) tEnd=0.5 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=4 (0,0 1,1 0,2) t=0 [0] (0,0) tEnd=0 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-markWinding id=4 (0,0 1,1 0,2) t=0 [1] (0,0) tEnd=0 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-markWinding id=4 (0,0 1,1 0,2) t=0 [2] (0,0) tEnd=0.5 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-findNextWinding debugShowSort contourWinding=0 oppContourWinding=0 sign=1
-debugShowSort [0] {{0,0}, {1,1}, {0,2}} tStart=0.5 tEnd=0 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [1] {{0,1}, {1,1}} tStart=0.5 tEnd=0 sign=1 windValue=1 windSum=? -1->-2 (max=-2) done=0 tiny=0 opp=0
-debugShowSort [2] {{0,0}, {1,1}, {0,2}} tStart=0.5 tEnd=1 sign=-1 windValue=1 windSum=? -2->-1 (max=-2) done=0 tiny=0 opp=0
-debugShowSort [3] {{0,1}, {1,1}} tStart=0.5 tEnd=1 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-findNextWinding firstIndex=[0] sign=1
-markDone id=2 (0,1 1,1) t=0 [0] (0,1) tEnd=0 newWindSum=-2 windSum=? windValue=1
-markDone id=2 (0,1 1,1) t=0 [1] (0,1) tEnd=0.5 newWindSum=-2 windSum=? windValue=1
-findNextWinding chase.append id=2
-markDone id=4 (0,0 1,1 0,2) t=0.5 [3] (0.5,1) tEnd=1 newWindSum=-2 windSum=? windValue=1
-markDone id=5 (0,2 0,0) t=0 [0] (0,2) tEnd=0.5 newWindSum=-2 windSum=? windValue=1
-findNextWinding chase.append id=5
-markWinding id=2 (0,1 1,1) t=0.5 [2] (0.5,1) tEnd=1 newWindSum=-1 windSum=? windValue=1
-markWinding id=3 (1,1 0,0) t=-0 [0] (1,1) tEnd=1 newWindSum=-1 windSum=? windValue=1
-findNextWinding chase.append id=3
-markDoneUnary id=4 (0,0 1,1 0,2) t=0 [0] (0,0) tEnd=0 newWindSum=-1 windSum=-1 windValue=1
-markDoneUnary id=4 (0,0 1,1 0,2) t=0 [1] (0,0) tEnd=0 newWindSum=-1 windSum=-1 windValue=1
-markDoneUnary id=4 (0,0 1,1 0,2) t=0 [2] (0,0) tEnd=0.5 newWindSum=-1 windSum=-1 windValue=1
-findNextWinding from:[4] to:[2] start=2 end=3
-bridgeWinding current id=4 from=(0,0) to=(0.5,1)
-path.moveTo(0,0);
-path.quadTo(0.5,0.5, 0.5,1);
-findNextWinding simple
-markDoneUnary id=2 (0,1 1,1) t=0.5 [2] (0.5,1) tEnd=1 newWindSum=-1 windSum=-1 windValue=1
-bridgeWinding current id=2 from=(0.5,1) to=(1,1)
-findNextWinding debugShowSort contourWinding=0 oppContourWinding=? sign=1
-debugShowSort [1] {{1,1}, {0,0}} tStart=1 tEnd=-0 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [0] {{0,0}, {1,1}, {0,2}} tStart=0 tEnd=0.5 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=0
-findNextWinding firstIndex=[1] sign=1
-markDoneUnary id=3 (1,1 0,0) t=-0 [0] (1,1) tEnd=1 newWindSum=-1 windSum=-1 windValue=1
-findNextWinding from:[3] to:[4] start=1 end=3
-bridgeWinding current id=3 from=(1,1) to=(0,0)
-path.lineTo(1,1);
-path.lineTo(0,0);
-path.close();
-</div>
-
-<div id="cubicOp67u">
- RunTestSet [cubicOp67u]
-{{3,5}, {1,6}, {5,0}, {3,1}},
-{{3,1}, {3,5}},
-op union
-{{0,5}, {1,3}, {5,3}, {6,1}},
-{{6,1}, {0,5}},
-debugShowCubicIntersection no self intersect {{3,5}, {1,6}, {5,0}, {3,1}}
-debugShowCubicLineIntersection wtTs[0]=0 {{3,5}, {1,6}, {5,0}, {3,1}} {{3,5}} wtTs[1]=0.5 {{3,3}} wtTs[2]=1 {{3,1}} wnTs[0]=1 {{3,1}, {3,5}} wnTs[1]=0.5 wnTs[2]=0
-debugShowCubicIntersection no intersect {{3,5}, {1,6}, {5,0}, {3,1}} {{0,5}, {1,3}, {5,3}, {6,1}}
-debugShowCubicLineIntersection wtTs[0]=0.5 {{3,5}, {1,6}, {5,0}, {3,1}} {{2.9999999999999991,3.0000000000000004}} wnTs[0]=0.5 {{6,1}, {0,5}}
-debugShowCubicLineIntersection wtTs[0]=0.5 {{0,5}, {1,3}, {5,3}, {6,1}} {{2.9999999999999991,2.9999999999999991}} wnTs[0]=0.5 {{3,1}, {3,5}}
-debugShowLineIntersection wtTs[0]=0.5 {{3,1}, {3,5}} {{3,3}} wnTs[0]=0.5 {{6,1}, {0,5}}
-debugShowCubicIntersection no self intersect {{0,5}, {1,3}, {5,3}, {6,1}}
-debugShowCubicLineIntersection wtTs[0]=0 {{0,5}, {1,3}, {5,3}, {6,1}} {{0,5}} wtTs[1]=0.5 {{3,3}} wtTs[2]=1 {{6,1}} wnTs[0]=1 {{6,1}, {0,5}} wnTs[1]=0.5 wnTs[2]=0
-SkOpSegment::debugShowActiveSpans id=1 (3,5 1,6 5,0 3,1) t=0 (3,5) tEnd=0.5 other=2 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-SkOpSegment::debugShowActiveSpans id=1 (3,5 1,6 5,0 3,1) t=0.5 (3,3) tEnd=1 other=4 otherT=0.5 otherIndex=3 windSum=? windValue=1 oppValue=0
-SkOpSegment::debugShowActiveSpans id=1 (3,5 1,6 5,0 3,1) t=0.5 (3,3) tEnd=1 other=2 otherT=0.5 otherIndex=2 windSum=? windValue=1 oppValue=0
-SkOpSegment::debugShowActiveSpans id=2 (3,1 3,5) t=0 (3,1) tEnd=0.5 other=1 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-SkOpSegment::debugShowActiveSpans id=2 (3,1 3,5) t=0.5 (3,3) tEnd=1 other=3 otherT=0.5 otherIndex=1 windSum=? windValue=1 oppValue=0
-SkOpSegment::debugShowActiveSpans id=2 (3,1 3,5) t=0.5 (3,3) tEnd=1 other=1 otherT=0.5 otherIndex=2 windSum=? windValue=1 oppValue=0
-SkOpSegment::debugShowActiveSpans id=2 (3,1 3,5) t=0.5 (3,3) tEnd=1 other=4 otherT=0.5 otherIndex=1 windSum=? windValue=1 oppValue=0
-SkOpSegment::debugShowActiveSpans id=3 (0,5 1,3 5,3 6,1) t=0 (0,5) tEnd=0.5 other=4 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-SkOpSegment::debugShowActiveSpans id=3 (0,5 1,3 5,3 6,1) t=0.5 (3,3) tEnd=1 other=2 otherT=0.5 otherIndex=1 windSum=? windValue=1 oppValue=0
-SkOpSegment::debugShowActiveSpans id=3 (0,5 1,3 5,3 6,1) t=0.5 (3,3) tEnd=1 other=4 otherT=0.5 otherIndex=2 windSum=? windValue=1 oppValue=0
-SkOpSegment::debugShowActiveSpans id=4 (6,1 0,5) t=0 (6,1) tEnd=0.5 other=3 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-SkOpSegment::debugShowActiveSpans id=4 (6,1 0,5) t=0.5 (3,3) tEnd=1 other=2 otherT=0.5 otherIndex=3 windSum=? windValue=1 oppValue=0
-SkOpSegment::debugShowActiveSpans id=4 (6,1 0,5) t=0.5 (3,3) tEnd=1 other=3 otherT=0.5 otherIndex=2 windSum=? windValue=1 oppValue=0
-SkOpSegment::debugShowActiveSpans id=4 (6,1 0,5) t=0.5 (3,3) tEnd=1 other=1 otherT=0.5 otherIndex=1 windSum=? windValue=1 oppValue=0
-SkOpSegment::findTop SkOpSegment::debugShowSort contourWinding=0 oppContourWinding=0 sign=1
-SkOpSegment::debugShowSort [0] {{3,5}, {1,6}, {5,0}, {3,1}} tStart=1 tEnd=0.5 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-SkOpSegment::debugShowSort [1] {{3,1}, {3,5}} tStart=0 tEnd=0.5 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-SkOpSegment::findTop swap=1 serpentine=0 containedByEnds=0 monotonic=0
-SkOpSegment::markWinding id=1 (3,5 1,6 5,0 3,1) t=0.5 [1] (3,3) tEnd=0.5 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-SkOpSegment::markWinding id=1 (3,5 1,6 5,0 3,1) t=0.5 [2] (3,3) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-SkOpSegment::markWinding id=1 (3,5 1,6 5,0 3,1) t=0.5 [1] (3,3) tEnd=0.5 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-SkOpSegment::markWinding id=1 (3,5 1,6 5,0 3,1) t=0.5 [2] (3,3) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-SkOpSegment::markWinding id=2 (3,1 3,5) t=0 [0] (3,1) tEnd=0.5 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-SkOpSegment::activeOp op=union miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-SkOpSegment::findNextOp SkOpSegment::debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-SkOpSegment::debugShowSort [1] {{3,5}, {1,6}, {5,0}, {3,1}} tStart=0.5 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=0 tiny=0 opp=0
-SkOpSegment::debugShowSort [2] {{3,1}, {3,5}} tStart=0.5 tEnd=0 sign=1 windValue=1 windSum=1 1->0 (max=1) done=0 tiny=0 opp=0
-SkOpSegment::debugShowSort [3] {{6,1}, {0,5}} tStart=0.5 tEnd=1 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=1
-SkOpSegment::debugShowSort [4] {{3,5}, {1,6}, {5,0}, {3,1}} tStart=0.5 tEnd=0 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-SkOpSegment::debugShowSort [5] {{3,1}, {3,5}} tStart=0.5 tEnd=1 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-SkOpSegment::debugShowSort [0] {{6,1}, {0,5}} tStart=0.5 tEnd=0 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=1
-SkOpSegment::findNextOp firstIndex=[1] sign=-1
-SkOpSegment::activeOp op=union miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-SkOpSegment::activeOp op=union miFrom=0 miTo=0 suFrom=0 suTo=1 result=1
-SkOpSegment::markWinding id=4 (6,1 0,5) t=0.5 [2] (3,3) tEnd=0.5 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-SkOpSegment::markWinding id=4 (6,1 0,5) t=0.5 [1] (3,3) tEnd=0.5 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-SkOpSegment::markWinding id=4 (6,1 0,5) t=0.5 [3] (3,3) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-SkOpSegment::markWinding id=3 (0,5 1,3 5,3 6,1) t=0 [0] (0,5) tEnd=0.5 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-SkOpSegment::findNextOp chase.append id=3
-SkOpSegment::activeOp op=union miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-SkOpSegment::markDoneBinary id=1 (3,5 1,6 5,0 3,1) t=0 [0] (3,5) tEnd=0.5 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-SkOpSegment::markDoneBinary id=2 (3,1 3,5) t=0.5 [2] (3,3) tEnd=0.5 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-SkOpSegment::markDoneBinary id=2 (3,1 3,5) t=0.5 [1] (3,3) tEnd=0.5 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-SkOpSegment::markDoneBinary id=2 (3,1 3,5) t=0.5 [3] (3,3) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-SkOpSegment::findNextOp chase.append id=2
-SkOpSegment::activeOp op=union miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
-SkOpSegment::activeOp op=union miFrom=0 miTo=0 suFrom=1 suTo=0 result=1
-SkOpSegment::markWinding id=4 (6,1 0,5) t=0 [0] (6,1) tEnd=0.5 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-SkOpSegment::markWinding id=3 (0,5 1,3 5,3 6,1) t=0.5 [1] (3,3) tEnd=0.5 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-SkOpSegment::markWinding id=3 (0,5 1,3 5,3 6,1) t=0.5 [2] (3,3) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-SkOpSegment::findNextOp chase.append id=3
-SkOpSegment::markDoneBinary id=1 (3,5 1,6 5,0 3,1) t=0.5 [1] (3,3) tEnd=0.5 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-SkOpSegment::markDoneBinary id=1 (3,5 1,6 5,0 3,1) t=0.5 [2] (3,3) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-SkOpSegment::findNextOp from:[1] to:[2] start=2 end=0
-bridgeOp current id=1 from=(3,1) to=(3,3)
-path.moveTo(3,1);
-path.cubicTo(4,0.5, 3.5,1.75, 3,3);
-SkOpSegment::findNextOp simple
-SkOpSegment::markDoneBinary id=2 (3,1 3,5) t=0 [0] (3,1) tEnd=0.5 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-bridgeOp current id=2 from=(3,3) to=(3,1)
-path.lineTo(3,1);
-path.close();
-SkOpSegment::debugShowActiveSpans id=3 (0,5 1,3 5,3 6,1) t=0 (0,5) tEnd=0.5 other=4 otherT=1 otherIndex=4 windSum=1 windValue=1 oppValue=0
-SkOpSegment::debugShowActiveSpans id=3 (0,5 1,3 5,3 6,1) t=0.5 (3,3) tEnd=1 other=2 otherT=0.5 otherIndex=1 windSum=1 windValue=1 oppValue=0
-SkOpSegment::debugShowActiveSpans id=3 (0,5 1,3 5,3 6,1) t=0.5 (3,3) tEnd=1 other=4 otherT=0.5 otherIndex=2 windSum=1 windValue=1 oppValue=0
-SkOpSegment::debugShowActiveSpans id=4 (6,1 0,5) t=0 (6,1) tEnd=0.5 other=3 otherT=1 otherIndex=3 windSum=1 windValue=1 oppValue=0
-SkOpSegment::debugShowActiveSpans id=4 (6,1 0,5) t=0.5 (3,3) tEnd=1 other=2 otherT=0.5 otherIndex=3 windSum=1 windValue=1 oppValue=0
-SkOpSegment::debugShowActiveSpans id=4 (6,1 0,5) t=0.5 (3,3) tEnd=1 other=3 otherT=0.5 otherIndex=2 windSum=1 windValue=1 oppValue=0
-SkOpSegment::debugShowActiveSpans id=4 (6,1 0,5) t=0.5 (3,3) tEnd=1 other=1 otherT=0.5 otherIndex=1 windSum=1 windValue=1 oppValue=0
-SkOpSegment::activeOp op=union miFrom=0 miTo=0 suFrom=0 suTo=1 result=1
-SkOpSegment::findNextOp simple
-SkOpSegment::markDoneBinary id=3 (0,5 1,3 5,3 6,1) t=0.5 [1] (3,3) tEnd=0.5 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-SkOpSegment::markDoneBinary id=3 (0,5 1,3 5,3 6,1) t=0.5 [2] (3,3) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-bridgeOp current id=3 from=(3,3) to=(6,1)
-path.moveTo(3,3);
-path.cubicTo(4.25,2.5, 5.5,2, 6,1);
-SkOpSegment::findNextOp SkOpSegment::debugShowSort contourWinding=1 oppContourWinding=0 sign=1
-SkOpSegment::debugShowSort [1] {{6,1}, {0,5}} tStart=0.5 tEnd=0 sign=1 windValue=1 windSum=1 1->0 (max=1) done=0 tiny=0 opp=0
-SkOpSegment::debugShowSort [2] {{3,5}, {1,6}, {5,0}, {3,1}} tStart=0.5 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=1
-SkOpSegment::debugShowSort [3] {{3,1}, {3,5}} tStart=0.5 tEnd=0 sign=1 windValue=1 windSum=1 1->0 (max=1) done=1 tiny=0 opp=1
-SkOpSegment::debugShowSort [4] {{0,5}, {1,3}, {5,3}, {6,1}} tStart=0.5 tEnd=0 sign=1 windValue=1 windSum=1 0->-1 (max=-1) done=0 tiny=0 opp=0
-SkOpSegment::debugShowSort [5] {{6,1}, {0,5}} tStart=0.5 tEnd=1 sign=-1 windValue=1 windSum=1 -1->0 (max=-1) done=0 tiny=0 opp=0
-SkOpSegment::debugShowSort [6] {{3,5}, {1,6}, {5,0}, {3,1}} tStart=0.5 tEnd=0 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=1
-SkOpSegment::debugShowSort [7] {{3,1}, {3,5}} tStart=0.5 tEnd=1 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=1
-SkOpSegment::debugShowSort [0] {{0,5}, {1,3}, {5,3}, {6,1}} tStart=0.5 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=0
-SkOpSegment::findNextOp firstIndex=[1] sign=1
-SkOpSegment::activeOp op=union miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-SkOpSegment::activeOp op=union miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-SkOpSegment::activeOp op=union miFrom=0 miTo=0 suFrom=0 suTo=1 result=1
-SkOpSegment::activeOp op=union miFrom=0 miTo=0 suFrom=1 suTo=0 result=1
-SkOpSegment::activeOp op=union miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-SkOpSegment::activeOp op=union miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-SkOpSegment::activeOp op=union miFrom=0 miTo=0 suFrom=0 suTo=1 result=1
-SkOpSegment::markDoneBinary id=4 (6,1 0,5) t=0 [0] (6,1) tEnd=0.5 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-SkOpSegment::findNextOp from:[4] to:[3] start=2 end=0
-bridgeOp current id=4 from=(6,1) to=(3,3)
-path.lineTo(3,3);
-path.close();
-SkOpSegment::debugShowActiveSpans id=3 (0,5 1,3 5,3 6,1) t=0 (0,5) tEnd=0.5 other=4 otherT=1 otherIndex=4 windSum=1 windValue=1 oppValue=0
-SkOpSegment::debugShowActiveSpans id=4 (6,1 0,5) t=0.5 (3,3) tEnd=1 other=2 otherT=0.5 otherIndex=3 windSum=1 windValue=1 oppValue=0
-SkOpSegment::debugShowActiveSpans id=4 (6,1 0,5) t=0.5 (3,3) tEnd=1 other=3 otherT=0.5 otherIndex=2 windSum=1 windValue=1 oppValue=0
-SkOpSegment::debugShowActiveSpans id=4 (6,1 0,5) t=0.5 (3,3) tEnd=1 other=1 otherT=0.5 otherIndex=1 windSum=1 windValue=1 oppValue=0
-SkOpSegment::activeOp op=union miFrom=0 miTo=0 suFrom=1 suTo=0 result=1
-SkOpSegment::findNextOp simple
-SkOpSegment::markDoneBinary id=3 (0,5 1,3 5,3 6,1) t=0 [0] (0,5) tEnd=0.5 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-bridgeOp current id=3 from=(3,3) to=(0,5)
-path.moveTo(3,3);
-path.cubicTo(1.75,3.5, 0.5,4, 0,5);
-SkOpSegment::findNextOp SkOpSegment::debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-SkOpSegment::debugShowSort [5] {{6,1}, {0,5}} tStart=0.5 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=0 tiny=0 opp=0
-SkOpSegment::debugShowSort [6] {{3,5}, {1,6}, {5,0}, {3,1}} tStart=0.5 tEnd=0 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=1
-SkOpSegment::debugShowSort [7] {{3,1}, {3,5}} tStart=0.5 tEnd=1 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=1
-SkOpSegment::debugShowSort [0] {{0,5}, {1,3}, {5,3}, {6,1}} tStart=0.5 tEnd=1 sign=-1 windValue=1 windSum=1 1->2 (max=2) done=1 tiny=0 opp=0
-SkOpSegment::debugShowSort [1] {{6,1}, {0,5}} tStart=0.5 tEnd=0 sign=1 windValue=1 windSum=1 2->1 (max=2) done=1 tiny=0 opp=0
-SkOpSegment::debugShowSort [2] {{3,5}, {1,6}, {5,0}, {3,1}} tStart=0.5 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=1
-SkOpSegment::debugShowSort [3] {{3,1}, {3,5}} tStart=0.5 tEnd=0 sign=1 windValue=1 windSum=1 1->0 (max=1) done=1 tiny=0 opp=1
-SkOpSegment::debugShowSort [4] {{0,5}, {1,3}, {5,3}, {6,1}} tStart=0.5 tEnd=0 sign=1 windValue=1 windSum=1 1->0 (max=1) done=1 tiny=0 opp=0
-SkOpSegment::findNextOp firstIndex=[5] sign=-1
-SkOpSegment::activeOp op=union miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-SkOpSegment::activeOp op=union miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
-SkOpSegment::activeOp op=union miFrom=0 miTo=0 suFrom=1 suTo=1 result=0
-SkOpSegment::activeOp op=union miFrom=0 miTo=0 suFrom=1 suTo=1 result=0
-SkOpSegment::activeOp op=union miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-SkOpSegment::activeOp op=union miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
-SkOpSegment::activeOp op=union miFrom=0 miTo=0 suFrom=1 suTo=0 result=1
-SkOpSegment::markDoneBinary id=4 (6,1 0,5) t=0.5 [2] (3,3) tEnd=0.5 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-SkOpSegment::markDoneBinary id=4 (6,1 0,5) t=0.5 [1] (3,3) tEnd=0.5 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-SkOpSegment::markDoneBinary id=4 (6,1 0,5) t=0.5 [3] (3,3) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-SkOpSegment::findNextOp from:[4] to:[3] start=2 end=0
-bridgeOp current id=4 from=(0,5) to=(3,3)
-path.lineTo(3,3);
-path.close();
-</div>
-
-<div id="cubicOp68u">
- RunTestSet [cubicOp68u]
-{{0,5}, {4,5}, {4,1}, {5,0}},
-{{5,0}, {0,5}},
-op union
-{{1,4}, {0,5}, {5,0}, {5,4}},
-{{5,4}, {1,4}},
-debugShowCubicIntersection no self intersect {{0,5}, {4,5}, {4,1}, {5,0}}
-debugShowCubicLineIntersection wtTs[0]=0 {{0,5}, {4,5}, {4,1}, {5,0}} {{0,5}} wtTs[1]=1 {{5,0}} wnTs[0]=1 {{5,0}, {0,5}} wnTs[1]=0
-debugShowCubicIntersection wtTs[0]=0.565184359 {{0,5}, {4,5}, {4,1}, {5,0}} {{3.8517056846571536,2.4305708556260548}} wnTs[0]=0.684396 {{1,4}, {0,5}, {5,0}, {5,4}}
-debugShowCubicLineIntersection wtTs[0]=0.320104156 {{0,5}, {4,5}, {4,1}, {5,0}} {{2.7756498612431599,4.0000000000000018}} wnTs[0]=0.556088 {{5,4}, {1,4}}
-debugShowCubicLineIntersection wtTs[0]=0 {{1,4}, {0,5}, {5,0}, {5,4}} {{0.99999999999999978,4}} wnTs[0]=0.8 {{5,0}, {0,5}}
-debugShowLineIntersection no intersect {{5,0}, {0,5}} {{5,4}, {1,4}}
-debugShowCubicIntersection no self intersect {{1,4}, {0,5}, {5,0}, {5,4}}
-debugShowCubicLineIntersection wtTs[0]=0 {{1,4}, {0,5}, {5,0}, {5,4}} {{1,4}} wtTs[1]=0.2 {{1.0320000000000003,4.0000000000000009}} wtTs[2]=1 {{5,4}} wnTs[0]=1 {{5,4}, {1,4}} wnTs[1]=0.992 wnTs[2]=0
-debugShowActiveSpans id=1 (0,5 4,5 4,1 5,0) t=0 (0,5) tEnd=0.320104156 other=2 otherT=1 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,5 4,5 4,1 5,0) t=0.320104156 (2.77564979,4) tEnd=0.565184359 other=4 otherT=0.556087535 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,5 4,5 4,1 5,0) t=0.565184359 (3.85170579,2.43057084) tEnd=1 other=3 otherT=0.684395636 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,0 0,5) t=0 (5,0) tEnd=0.8 other=1 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,0 0,5) t=0.8 (1,4) tEnd=1 other=3 otherT=0 otherIndex=0 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,4 0,5 5,0 5,4) t=0 (1,4) tEnd=0.2 other=2 otherT=0.8 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,4 0,5 5,0 5,4) t=0 (1,4) tEnd=0.2 other=4 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,4 0,5 5,0 5,4) t=0.2 (1.03199995,4) tEnd=0.684395636 other=4 otherT=0.992 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,4 0,5 5,0 5,4) t=0.684395636 (3.85170579,2.43057084) tEnd=1 other=1 otherT=0.565184359 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (5,4 1,4) t=0 (5,4) tEnd=0.556087535 other=3 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (5,4 1,4) t=0.556087535 (2.77564979,4) tEnd=0.992 other=1 otherT=0.320104156 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (5,4 1,4) t=0.992 (1.03199995,4) tEnd=1 other=3 otherT=0.2 otherIndex=2 windSum=? windValue=1 oppValue=0
-findTop debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [0] {{5,0}, {0,5}} tStart=0 tEnd=0.8 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] {{0,5}, {4,5}, {4,1}, {5,0}} tStart=1 tEnd=0.565184359 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=0
-markWinding id=2 (5,0 0,5) t=0 [0] (5,0) tEnd=0.8 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=1 (0,5 4,5 4,1 5,0) t=0.565184359 [2] (3.85170579,2.43057084) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=2 (5,0 0,5) t=0 [0] (5,0) tEnd=0.8 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-activeOp op=union miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-findNextOp simple
-markDoneBinary id=2 (5,0 0,5) t=0 [0] (5,0) tEnd=0.8 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-bridgeOp current id=2 from=(1,4) to=(5,0)
-findNextOp debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [1] {{0,5}, {4,5}, {4,1}, {5,0}} tStart=0.565184359 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [2] {{1,4}, {0,5}, {5,0}, {5,4}} tStart=0.684395636 tEnd=0.2 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=1
-debugShowSort [3] {{0,5}, {4,5}, {4,1}, {5,0}} tStart=0.565184359 tEnd=0.320104156 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [0] {{1,4}, {0,5}, {5,0}, {5,4}} tStart=0.684395636 tEnd=1 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=1
-findNextOp firstIndex=[1] sign=-1
-activeOp op=union miFrom=1 miTo=1 suFrom=0 suTo=1 result=0
-markDoneBinary id=3 (1,4 0,5 5,0 5,4) t=0.2 [2] (1.03199995,4) tEnd=0.684395636 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-activeOp op=union miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
-markDoneBinary id=1 (0,5 4,5 4,1 5,0) t=0.320104156 [1] (2.77564979,4) tEnd=0.565184359 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=1
-activeOp op=union miFrom=0 miTo=0 suFrom=1 suTo=0 result=1
-markWinding id=3 (1,4 0,5 5,0 5,4) t=0.684395636 [3] (3.85170579,2.43057084) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=4 (5,4 1,4) t=0 [0] (5,4) tEnd=0.556087535 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=4
-markDoneBinary id=1 (0,5 4,5 4,1 5,0) t=0.565184359 [2] (3.85170579,2.43057084) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-findNextOp from:[1] to:[3] start=3 end=4
-bridgeOp current id=1 from=(5,0) to=(3.85170579,2.43057084)
-path.moveTo(1,4);
-path.lineTo(5,0);
-path.cubicTo(4.56518459,0.434815645, 4.31943321,1.43682528, 3.85170579,2.43057084);
-findNextOp simple
-markDoneBinary id=3 (1,4 0,5 5,0 5,4) t=0.684395636 [3] (3.85170579,2.43057084) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-bridgeOp current id=3 from=(3.85170579,2.43057084) to=(5,4)
-path.cubicTo(4.50196934,2.37162018, 5,2.73758245, 5,4);
-findNextOp debugShowSort contourWinding=0 oppContourWinding=0 sign=1
-debugShowSort [3] {{5,4}, {1,4}} tStart=0.556087535 tEnd=0 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [0] {{0,5}, {4,5}, {4,1}, {5,0}} tStart=0.320104156 tEnd=0.565184359 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=1
-debugShowSort [1] {{5,4}, {1,4}} tStart=0.556087535 tEnd=0.992 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [2] {{0,5}, {4,5}, {4,1}, {5,0}} tStart=0.320104156 tEnd=0 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=1
-findNextOp firstIndex=[3] sign=1
-activeOp op=union miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-activeOp op=union miFrom=1 miTo=1 suFrom=1 suTo=0 result=0
-markDoneBinary id=4 (5,4 1,4) t=0.556087535 [1] (2.77564979,4) tEnd=0.992 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=4
-activeOp op=union miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-markWinding id=1 (0,5 4,5 4,1 5,0) t=0 [0] (0,5) tEnd=0.320104156 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=2 (5,0 0,5) t=0.8 [1] (1,4) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=2
-markDoneBinary id=4 (5,4 1,4) t=0 [0] (5,4) tEnd=0.556087535 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-findNextOp from:[4] to:[1] start=1 end=0
-bridgeOp current id=4 from=(5,4) to=(2.77564979,4)
-findNextOp simple
-markDoneBinary id=1 (0,5 4,5 4,1 5,0) t=0 [0] (0,5) tEnd=0.320104156 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-bridgeOp current id=1 from=(2.77564979,4) to=(0,5)
-path.lineTo(2.77564979,4);
-path.cubicTo(2.15096664,4.59013319, 1.28041661,5, 0,5);
-findNextOp debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [1] {{5,0}, {0,5}} tStart=0.8 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [2] {{1,4}, {0,5}, {5,0}, {5,4}} tStart=0 tEnd=0.2 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=1
-debugShowSort [0] {{5,0}, {0,5}} tStart=0.8 tEnd=0 sign=1 windValue=1 windSum=1 1->0 (max=1) done=1 tiny=0 opp=0
-findNextOp firstIndex=[1] sign=-1
-activeOp op=union miFrom=1 miTo=1 suFrom=0 suTo=1 result=0
-markDoneBinary id=3 (1,4 0,5 5,0 5,4) t=0 [0] (1,4) tEnd=0 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1
-markDoneBinary id=3 (1,4 0,5 5,0 5,4) t=0 [1] (1,4) tEnd=0.2 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-activeOp op=union miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
-markDoneBinary id=2 (5,0 0,5) t=0.8 [1] (1,4) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-../../src/pathops/SkPathOpsOp.cpp:183: failed assertion "unsortable"
-</div>
-
-<div id="cubicOp68ua">
- RunTestSet [cubicOp68u]
-{{0,5}, {4,5}, {4,1}, {5,0}},
-{{5,0}, {0,5}},
-op union
-{{1,4}, {0,5}, {5,0}, {5,4}},
-{{5,4}, {1,4}},
-debugShowCubicIntersection no self intersect {{0,5}, {4,5}, {4,1}, {5,0}}
-debugShowCubicLineIntersection wtTs[0]=0 {{0,5}, {4,5}, {4,1}, {5,0}} {{0,5}} wtTs[1]=1 {{5,0}} wnTs[0]=1 {{5,0}, {0,5}} wnTs[1]=0
-debugShowCubicIntersection wtTs[0]=0.565184359 {{0,5}, {4,5}, {4,1}, {5,0}} {{3.851705684657154,2.4305708556260521}} wnTs[0]=0.684396 {{1,4}, {0,5}, {5,0}, {5,4}}
-debugShowCubicLineIntersection wtTs[0]=0.320104156 {{0,5}, {4,5}, {4,1}, {5,0}} {{2.7756498612431599,4.0000000000000018}} wnTs[0]=0.556088 {{5,4}, {1,4}}
-debugShowCubicLineIntersection wtTs[0]=0 {{1,4}, {0,5}, {5,0}, {5,4}} {{0.99999999999999978,4}} wnTs[0]=0.8 {{5,0}, {0,5}}
-debugShowLineIntersection wtTs[0]=0.8 {{5,0}, {0,5}} {{0.99999999999999978,4}} wnTs[0]=1 {{5,4}, {1,4}}
-debugShowCubicIntersection no self intersect {{1,4}, {0,5}, {5,0}, {5,4}}
-debugShowCubicLineIntersection wtTs[0]=0 {{1,4}, {0,5}, {5,0}, {5,4}} {{1,4}} wtTs[1]=0.2 {{1.0320000000000003,4.0000000000000009}} wtTs[2]=1 {{5,4}} wnTs[0]=1 {{5,4}, {1,4}} wnTs[1]=0.992 wnTs[2]=0
-debugShowActiveSpans id=1 (0,5 4,5 4,1 5,0) t=0 (0,5) tEnd=0.320104156 other=2 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,5 4,5 4,1 5,0) t=0.320104156 (2.77564979,4) tEnd=0.565184359 other=4 otherT=0.556087535 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,5 4,5 4,1 5,0) t=0.565184359 (3.85170579,2.43057084) tEnd=1 other=3 otherT=0.684395636 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,0 0,5) t=0 (5,0) tEnd=0.8 other=1 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,0 0,5) t=0.8 (1,4) tEnd=1 other=3 otherT=0 otherIndex=0 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (5,0 0,5) t=0.8 (1,4) tEnd=1 other=4 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,4 0,5 5,0 5,4) t=0 (1,4) tEnd=0.2 other=2 otherT=0.8 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,4 0,5 5,0 5,4) t=0 (1,4) tEnd=0.2 other=4 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,4 0,5 5,0 5,4) t=0.2 (1.03199995,4) tEnd=0.684395636 other=4 otherT=0.992 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,4 0,5 5,0 5,4) t=0.684395636 (3.85170579,2.43057084) tEnd=1 other=1 otherT=0.565184359 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (5,4 1,4) t=0 (5,4) tEnd=0.556087535 other=3 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (5,4 1,4) t=0.556087535 (2.77564979,4) tEnd=0.992 other=1 otherT=0.320104156 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (5,4 1,4) t=0.992 (1.03199995,4) tEnd=1 other=3 otherT=0.2 otherIndex=2 windSum=? windValue=1 oppValue=0
-findTop debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [0] {{5,0}, {0,5}} tStart=0 tEnd=0.8 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] {{0,5}, {4,5}, {4,1}, {5,0}} tStart=1 tEnd=0.565184359 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=0
-markWinding id=2 (5,0 0,5) t=0 [0] (5,0) tEnd=0.8 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=1 (0,5 4,5 4,1 5,0) t=0.565184359 [2] (3.85170579,2.43057084) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=2 (5,0 0,5) t=0 [0] (5,0) tEnd=0.8 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-activeOp op=union miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-findNextOp simple
-markDoneBinary id=2 (5,0 0,5) t=0 [0] (5,0) tEnd=0.8 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-bridgeOp current id=2 from=(1,4) to=(5,0)
-findNextOp debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [1] {{0,5}, {4,5}, {4,1}, {5,0}} tStart=0.565184359 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [2] {{1,4}, {0,5}, {5,0}, {5,4}} tStart=0.684395636 tEnd=0.2 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=1
-debugShowSort [3] {{0,5}, {4,5}, {4,1}, {5,0}} tStart=0.565184359 tEnd=0.320104156 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [0] {{1,4}, {0,5}, {5,0}, {5,4}} tStart=0.684395636 tEnd=1 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=1
-findNextOp firstIndex=[1] sign=-1
-activeOp op=union miFrom=1 miTo=1 suFrom=0 suTo=1 result=0
-markDoneBinary id=3 (1,4 0,5 5,0 5,4) t=0.2 [2] (1.03199995,4) tEnd=0.684395636 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-activeOp op=union miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
-markDoneBinary id=1 (0,5 4,5 4,1 5,0) t=0.320104156 [1] (2.77564979,4) tEnd=0.565184359 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=1
-activeOp op=union miFrom=0 miTo=0 suFrom=1 suTo=0 result=1
-markWinding id=3 (1,4 0,5 5,0 5,4) t=0.684395636 [3] (3.85170579,2.43057084) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=4 (5,4 1,4) t=0 [0] (5,4) tEnd=0.556087535 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=4
-markDoneBinary id=1 (0,5 4,5 4,1 5,0) t=0.565184359 [2] (3.85170579,2.43057084) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-findNextOp from:[1] to:[3] start=3 end=4
-bridgeOp current id=1 from=(5,0) to=(3.85170579,2.43057084)
-path.moveTo(1,4);
-path.lineTo(5,0);
-path.cubicTo(4.56518459,0.434815645, 4.31943321,1.43682528, 3.85170579,2.43057084);
-findNextOp simple
-markDoneBinary id=3 (1,4 0,5 5,0 5,4) t=0.684395636 [3] (3.85170579,2.43057084) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-bridgeOp current id=3 from=(3.85170579,2.43057084) to=(5,4)
-path.cubicTo(4.50196934,2.37162018, 5,2.73758245, 5,4);
-findNextOp debugShowSort contourWinding=0 oppContourWinding=0 sign=1
-debugShowSort [3] {{5,4}, {1,4}} tStart=0.556087535 tEnd=0 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [0] {{0,5}, {4,5}, {4,1}, {5,0}} tStart=0.320104156 tEnd=0.565184359 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=1
-debugShowSort [1] {{5,4}, {1,4}} tStart=0.556087535 tEnd=0.992 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [2] {{0,5}, {4,5}, {4,1}, {5,0}} tStart=0.320104156 tEnd=0 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=1
-findNextOp firstIndex=[3] sign=1
-activeOp op=union miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-activeOp op=union miFrom=1 miTo=1 suFrom=1 suTo=0 result=0
-markDoneBinary id=4 (5,4 1,4) t=0.556087535 [1] (2.77564979,4) tEnd=0.992 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=4
-activeOp op=union miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-markWinding id=1 (0,5 4,5 4,1 5,0) t=0 [0] (0,5) tEnd=0.320104156 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=2 (5,0 0,5) t=0.8 [1] (1,4) tEnd=0.8 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=2 (5,0 0,5) t=0.8 [2] (1,4) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=2
-markDoneBinary id=4 (5,4 1,4) t=0 [0] (5,4) tEnd=0.556087535 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-findNextOp from:[4] to:[1] start=1 end=0
-bridgeOp current id=4 from=(5,4) to=(2.77564979,4)
-findNextOp simple
-markDoneBinary id=1 (0,5 4,5 4,1 5,0) t=0 [0] (0,5) tEnd=0.320104156 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-bridgeOp current id=1 from=(2.77564979,4) to=(0,5)
-path.lineTo(2.77564979,4);
-path.cubicTo(2.15096664,4.59013319, 1.28041661,5, 0,5);
-findNextOp debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [1] {{5,0}, {0,5}} tStart=0.8 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [2] {{1,4}, {0,5}, {5,0}, {5,4}} tStart=0 tEnd=0.2 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=1
-debugShowSort [3] {{5,4}, {1,4}} tStart=1 tEnd=0.992 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=1
-debugShowSort [0] {{5,0}, {0,5}} tStart=0.8 tEnd=0 sign=1 windValue=1 windSum=1 1->0 (max=1) done=1 tiny=0 opp=0
-findNextOp firstIndex=[1] sign=-1
-activeOp op=union miFrom=1 miTo=1 suFrom=0 suTo=1 result=0
-markDoneBinary id=3 (1,4 0,5 5,0 5,4) t=0 [0] (1,4) tEnd=0 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1
-markDoneBinary id=3 (1,4 0,5 5,0 5,4) t=0 [1] (1,4) tEnd=0.2 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-activeOp op=union miFrom=1 miTo=1 suFrom=1 suTo=0 result=0
-markDoneBinary id=4 (5,4 1,4) t=0.992 [2] (1.03199995,4) tEnd=1 newWindSum=1 newOppSum=1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=4
-activeOp op=union miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-markDoneBinary id=2 (5,0 0,5) t=0.8 [1] (1,4) tEnd=0.8 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-markDoneBinary id=2 (5,0 0,5) t=0.8 [2] (1,4) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-findNextOp from:[2] to:[2] start=2 end=0
-bridgeOp current id=2 from=(0,5) to=(1,4)
-path.lineTo(1,4);
-path.close();
-</div>
-
-<div id="cubicOp69d">
- RunTestSet [cubicOp69d]
-{{1,3}, {0,1}, {3,1}, {2,0}},
-{{2,0}, {1,3}},
-op difference
-{{1,3}, {0,2}, {3,1}, {1,0}},
-{{1,0}, {1,3}},
-debugShowCubicIntersection no self intersect {{1,3}, {0,2}, {3,1}, {1,0}}
-debugShowCubicLineIntersection wtTs[0]=0 {{1,3}, {0,2}, {3,1}, {1,0}} {{1,3}} wtTs[1]=0.333333333 {{1.0000000000000002,2.0000000000000004}} wtTs[2]=1 {{1,0}} wnTs[0]=1 {{1,0}, {1,3}} wnTs[1]=0.666666667 wnTs[2]=0
-debugShowCubicIntersection wtTs[0]=0 {{1,3}, {0,2}, {3,1}, {1,0}} {{1,3}} wtTs[1]=0.195806707 {{0.80509754536484868,2.412579877819526}} wtTs[2]=0.665291365 {{1.6652800396786596,1.0041259050152926}} wnTs[0]=0 {{1,3}, {0,1}, {3,1}, {2,0}} wnTs[1]=0.109171117 wnTs[2]=0.555550487
-debugShowCubicLineIntersection wtTs[0]=0 {{1,3}, {0,2}, {3,1}, {1,0}} {{1,3}} wtTs[1]=0.666666667 {{1.6666666666666665,1.0000000000000002}} wnTs[0]=1 {{2,0}, {1,3}} wnTs[1]=0.333333333
-debugShowCubicLineIntersection wtTs[0]=0 {{1,3}, {0,1}, {3,1}, {2,0}} {{1,3}} wtTs[1]=0.316987298 {{1,1.6054083424670758}} wnTs[0]=1 {{1,0}, {1,3}} wnTs[1]=0.535136114
-debugShowLineIntersection wtTs[0]=1 {{1,0}, {1,3}} {{1,3}} wnTs[0]=1 {{2,0}, {1,3}}
-debugShowCubicIntersection no self intersect {{1,3}, {0,1}, {3,1}, {2,0}}
-debugShowCubicLineIntersection wtTs[0]=0 {{1,3}, {0,1}, {3,1}, {2,0}} {{1,3}} wtTs[1]=0.555555556 {{1.6652949245541837,1.0041152263374487}} wtTs[2]=1 {{2,0}} wnTs[0]=1 {{2,0}, {1,3}} wnTs[1]=0.334705075 wnTs[2]=0
-debugShowActiveSpans id=3 (1,3 0,2 3,1 1,0) t=0 (1,3) tEnd=0.195806707 other=4 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,3 0,2 3,1 1,0) t=0 (1,3) tEnd=0.195806707 other=1 otherT=0 otherIndex=0 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,3 0,2 3,1 1,0) t=0 (1,3) tEnd=0.195806707 other=2 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,3 0,2 3,1 1,0) t=0.195806707 (0.80509752,2.41257977) tEnd=0.333333333 other=1 otherT=0.109171117 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,3 0,2 3,1 1,0) t=0.333333333 (1,2) tEnd=0.665291365 other=4 otherT=0.666666667 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,3 0,2 3,1 1,0) t=0.665291365 (1.66527998,1.00412595) tEnd=0.666666667 other=1 otherT=0.555550487 otherIndex=5 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,3 0,2 3,1 1,0) t=0.666666667 (1.66666663,1) tEnd=1 other=2 otherT=0.333333333 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (1,0 1,3) t=0 (1,0) tEnd=0.535136114 other=3 otherT=1 otherIndex=7 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (1,0 1,3) t=0.535136114 (1,1.60540831) tEnd=0.666666667 other=1 otherT=0.316987298 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (1,0 1,3) t=0.666666667 (1,2) tEnd=1 other=3 otherT=0.333333333 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 0,1 3,1 2,0) t=0 (1,3) tEnd=0.109171117 other=3 otherT=0 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 0,1 3,1 2,0) t=0 (1,3) tEnd=0.109171117 other=4 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 0,1 3,1 2,0) t=0 (1,3) tEnd=0.109171117 other=2 otherT=1 otherIndex=5 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 0,1 3,1 2,0) t=0.109171117 (0.80509752,2.41257977) tEnd=0.316987298 other=3 otherT=0.195806707 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 0,1 3,1 2,0) t=0.316987298 (1,1.60540831) tEnd=0.555550487 other=4 otherT=0.535136114 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 0,1 3,1 2,0) t=0.555550487 (1.66527998,1.00412595) tEnd=0.555555556 other=3 otherT=0.665291365 otherIndex=5 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 0,1 3,1 2,0) t=0.555555556 (1.66529489,1.00411522) tEnd=1 other=2 otherT=0.334705075 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (2,0 1,3) t=0 (2,0) tEnd=0.333333333 other=1 otherT=1 otherIndex=7 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (2,0 1,3) t=0.333333333 (1.66666663,1) tEnd=0.334705075 other=3 otherT=0.666666667 otherIndex=6 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (2,0 1,3) t=0.334705075 (1.66529489,1.00411522) tEnd=1 other=1 otherT=0.555555556 otherIndex=6 windSum=? windValue=1 oppValue=0
-findTop debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [0] {{1,0}, {1,3}} tStart=0 tEnd=0.535136114 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] {{1,3}, {0,2}, {3,1}, {1,0}} tStart=1 tEnd=0.666666667 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=0
-markWinding id=4 (1,0 1,3) t=0 [0] (1,0) tEnd=0.535136114 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=3 (1,3 0,2 3,1 1,0) t=0.666666667 [6] (1.66666663,1) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=4 (1,0 1,3) t=0 [0] (1,0) tEnd=0.535136114 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-markDoneBinary id=4 (1,0 1,3) t=0 [0] (1,0) tEnd=0.535136114 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-markDoneBinary id=3 (1,3 0,2 3,1 1,0) t=0.666666667 [6] (1.66666663,1) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-</div>
-
-<div id="cubicOp69da">
- RunTestSet [cubicOp69da]
-{{1,3}, {0,1}, {3,1}, {2,0}},
-{{2,0}, {1,3}},
-op difference
-{{1,3}, {0,2}, {3,1}, {1,0}},
-{{1,0}, {1,3}},
-debugShowCubicIntersection no self intersect {{1,3}, {0,2}, {3,1}, {1,0}}
-debugShowCubicLineIntersection wtTs[0]=0 {{1,3}, {0,2}, {3,1}, {1,0}} {{1,3}} wtTs[1]=0.333333333 {{1,2.0000000000000004}} wtTs[2]=1 {{1,0}} wnTs[0]=1 {{1,0}, {1,3}} wnTs[1]=0.666666667 wnTs[2]=0
-debugShowCubicIntersection wtTs[0]=0 {{1,3}, {0,2}, {3,1}, {1,0}} {{1,3}} wtTs[1]=0.195806707 {{0.80509754536484845,2.4125798778195251}} wtTs[2]=0.665291365 {{1.6652800396786593,1.0041259050152929}} wnTs[0]=0 {{1,3}, {0,1}, {3,1}, {2,0}} wnTs[1]=0.109171117 wnTs[2]=0.555550487
-debugShowCubicLineIntersection wtTs[0]=0 {{1,3}, {0,2}, {3,1}, {1,0}} {{1,3}} wtTs[1]=0.666666667 {{1.6666666666666667,1}} wnTs[0]=1 {{2,0}, {1,3}} wnTs[1]=0.333333333
-debugShowCubicLineIntersection wtTs[0]=0 {{1,3}, {0,1}, {3,1}, {2,0}} {{1,3}} wtTs[1]=0.316987298 {{1,1.6054083424670758}} wnTs[0]=1 {{1,0}, {1,3}} wnTs[1]=0.535136114
-debugShowLineIntersection wtTs[0]=1 {{1,0}, {1,3}} {{1,3}} wnTs[0]=1 {{2,0}, {1,3}}
-debugShowCubicIntersection no self intersect {{1,3}, {0,1}, {3,1}, {2,0}}
-debugShowCubicLineIntersection wtTs[0]=0 {{1,3}, {0,1}, {3,1}, {2,0}} {{1,3}} wtTs[1]=0.555555556 {{1.6652949245541839,1.0041152263374484}} wtTs[2]=1 {{2,0}} wnTs[0]=1 {{2,0}, {1,3}} wnTs[1]=0.334705075 wnTs[2]=0
-debugShowActiveSpans id=3 (1,3 0,2 3,1 1,0) t=0 (1,3) tEnd=0.195806707 other=4 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,3 0,2 3,1 1,0) t=0 (1,3) tEnd=0.195806707 other=1 otherT=0 otherIndex=0 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,3 0,2 3,1 1,0) t=0 (1,3) tEnd=0.195806707 other=2 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,3 0,2 3,1 1,0) t=0.195806707 (0.80509752,2.41257977) tEnd=0.333333333 other=1 otherT=0.109171117 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,3 0,2 3,1 1,0) t=0.333333333 (1,2) tEnd=0.665291365 other=4 otherT=0.666666667 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,3 0,2 3,1 1,0) t=0.665291365 (1.66527998,1.00412595) tEnd=0.666666667 other=1 otherT=0.555550487 otherIndex=5 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,3 0,2 3,1 1,0) t=0.666666667 (1.66666663,1) tEnd=1 other=2 otherT=0.333333333 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (1,0 1,3) t=0 (1,0) tEnd=0.535136114 other=3 otherT=1 otherIndex=7 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (1,0 1,3) t=0.535136114 (1,1.60540831) tEnd=0.666666667 other=1 otherT=0.316987298 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (1,0 1,3) t=0.666666667 (1,2) tEnd=1 other=3 otherT=0.333333333 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 0,1 3,1 2,0) t=0 (1,3) tEnd=0.109171117 other=3 otherT=0 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 0,1 3,1 2,0) t=0 (1,3) tEnd=0.109171117 other=4 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 0,1 3,1 2,0) t=0 (1,3) tEnd=0.109171117 other=2 otherT=1 otherIndex=5 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 0,1 3,1 2,0) t=0.109171117 (0.80509752,2.41257977) tEnd=0.316987298 other=3 otherT=0.195806707 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 0,1 3,1 2,0) t=0.316987298 (1,1.60540831) tEnd=0.555550487 other=4 otherT=0.535136114 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 0,1 3,1 2,0) t=0.555550487 (1.66527998,1.00412595) tEnd=0.555555556 other=3 otherT=0.665291365 otherIndex=5 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 0,1 3,1 2,0) t=0.555555556 (1.66529489,1.00411522) tEnd=1 other=2 otherT=0.334705075 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (2,0 1,3) t=0 (2,0) tEnd=0.333333333 other=1 otherT=1 otherIndex=7 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (2,0 1,3) t=0.333333333 (1.66666663,1) tEnd=0.334705075 other=3 otherT=0.666666667 otherIndex=6 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (2,0 1,3) t=0.334705075 (1.66529489,1.00411522) tEnd=1 other=1 otherT=0.555555556 otherIndex=6 windSum=? windValue=1 oppValue=0
-findTop debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [0] {{1,0}, {1,3}} tStart=0 tEnd=0.535136114 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] {{1,3}, {0,2}, {3,1}, {1,0}} tStart=1 tEnd=0.666666667 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=0
-markWinding id=4 (1,0 1,3) t=0 [0] (1,0) tEnd=0.535136114 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=3 (1,3 0,2 3,1 1,0) t=0.666666667 [6] (1.66666663,1) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=4 (1,0 1,3) t=0 [0] (1,0) tEnd=0.535136114 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-markDoneBinary id=4 (1,0 1,3) t=0 [0] (1,0) tEnd=0.535136114 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-markDoneBinary id=3 (1,3 0,2 3,1 1,0) t=0.666666667 [6] (1.66666663,1) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-findChaseOp debugShowSort contourWinding=? oppContourWinding=? sign=1
-debugShowSort [0] {{2,0}, {1,3}} tStart=0.333333333 tEnd=0 sign=1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=0
-debugShowSort [1] {{1,3}, {0,2}, {3,1}, {1,0}} tStart=0.666666667 tEnd=1 sign=-1 windValue=1 windSum=1 ?->? (max=?) done=1 tiny=0 opp=1
-debugShowSort [2] {{1,3}, {0,2}, {3,1}, {1,0}} tStart=0.666666667 tEnd=0.665291365 sign=1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=1
-debugShowSort [3] {{2,0}, {1,3}} tStart=0.333333333 tEnd=0.334705075 sign=-1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=0
-findChaseOp debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [1] {{1,3}, {0,2}, {3,1}, {1,0}} tStart=0.666666667 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=0
-debugShowSort [2] {{1,3}, {0,2}, {3,1}, {1,0}} tStart=0.666666667 tEnd=0.665291365 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [3] {{2,0}, {1,3}} tStart=0.333333333 tEnd=0.334705075 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=1
-debugShowSort [0] {{2,0}, {1,3}} tStart=0.333333333 tEnd=0 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=1
-markWinding id=3 (1,3 0,2 3,1 1,0) t=0.665291365 [5] (1.66527998,1.00412595) tEnd=0.666666667 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=2 (2,0 1,3) t=0.333333333 [1] (1.66666663,1) tEnd=0.334705075 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=2 (2,0 1,3) t=0 [0] (2,0) tEnd=0.333333333 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=1 (1,3 0,1 3,1 2,0) t=0.555555556 [6] (1.66529489,1.00411522) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-debugShowActiveSpans id=3 (1,3 0,2 3,1 1,0) t=0 (1,3) tEnd=0.195806707 other=4 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,3 0,2 3,1 1,0) t=0 (1,3) tEnd=0.195806707 other=1 otherT=0 otherIndex=0 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,3 0,2 3,1 1,0) t=0 (1,3) tEnd=0.195806707 other=2 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,3 0,2 3,1 1,0) t=0.195806707 (0.80509752,2.41257977) tEnd=0.333333333 other=1 otherT=0.109171117 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,3 0,2 3,1 1,0) t=0.333333333 (1,2) tEnd=0.665291365 other=4 otherT=0.666666667 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,3 0,2 3,1 1,0) t=0.665291365 (1.66527998,1.00412595) tEnd=0.666666667 other=1 otherT=0.555550487 otherIndex=5 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (1,0 1,3) t=0.535136114 (1,1.60540831) tEnd=0.666666667 other=1 otherT=0.316987298 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (1,0 1,3) t=0.666666667 (1,2) tEnd=1 other=3 otherT=0.333333333 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 0,1 3,1 2,0) t=0 (1,3) tEnd=0.109171117 other=3 otherT=0 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 0,1 3,1 2,0) t=0 (1,3) tEnd=0.109171117 other=4 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 0,1 3,1 2,0) t=0 (1,3) tEnd=0.109171117 other=2 otherT=1 otherIndex=5 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 0,1 3,1 2,0) t=0.109171117 (0.80509752,2.41257977) tEnd=0.316987298 other=3 otherT=0.195806707 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 0,1 3,1 2,0) t=0.316987298 (1,1.60540831) tEnd=0.555550487 other=4 otherT=0.535136114 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 0,1 3,1 2,0) t=0.555550487 (1.66527998,1.00412595) tEnd=0.555555556 other=3 otherT=0.665291365 otherIndex=5 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 0,1 3,1 2,0) t=0.555555556 (1.66529489,1.00411522) tEnd=1 other=2 otherT=0.334705075 otherIndex=2 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (2,0 1,3) t=0 (2,0) tEnd=0.333333333 other=1 otherT=1 otherIndex=7 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (2,0 1,3) t=0.333333333 (1.66666663,1) tEnd=0.334705075 other=3 otherT=0.666666667 otherIndex=6 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (2,0 1,3) t=0.334705075 (1.66529489,1.00411522) tEnd=1 other=1 otherT=0.555555556 otherIndex=6 windSum=? windValue=1 oppValue=0
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-markDoneBinary id=3 (1,3 0,2 3,1 1,0) t=0.665291365 [5] (1.66527998,1.00412595) tEnd=0.666666667 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-findChaseOp debugShowSort contourWinding=? oppContourWinding=? sign=-1
-debugShowSort [0] {{1,3}, {0,1}, {3,1}, {2,0}} tStart=0.555550487 tEnd=0.555555556 sign=-1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=0
-debugShowSort [1] {{1,3}, {0,2}, {3,1}, {1,0}} tStart=0.665291365 tEnd=0.666666667 sign=-1 windValue=1 windSum=1 ?->? (max=?) done=1 tiny=0 opp=1
-debugShowSort [2] {{1,3}, {0,1}, {3,1}, {2,0}} tStart=0.555550487 tEnd=0.316987298 sign=1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=0
-debugShowSort [3] {{1,3}, {0,2}, {3,1}, {1,0}} tStart=0.665291365 tEnd=0.333333333 sign=1 windValue=1 windSum=? ?->? (max=?) done=0 tiny=0 opp=1
-findChaseOp debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [1] {{1,3}, {0,2}, {3,1}, {1,0}} tStart=0.665291365 tEnd=0.666666667 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=0
-debugShowSort [2] {{1,3}, {0,1}, {3,1}, {2,0}} tStart=0.555550487 tEnd=0.316987298 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=1
-debugShowSort [3] {{1,3}, {0,2}, {3,1}, {1,0}} tStart=0.665291365 tEnd=0.333333333 sign=1 windValue=1 windSum=? 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [0] {{1,3}, {0,1}, {3,1}, {2,0}} tStart=0.555550487 tEnd=0.555555556 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=1
-markWinding id=1 (1,3 0,1 3,1 2,0) t=0.316987298 [4] (1,1.60540831) tEnd=0.555550487 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1
-markWinding id=3 (1,3 0,2 3,1 1,0) t=0.333333333 [4] (1,2) tEnd=0.665291365 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1
-markWinding id=1 (1,3 0,1 3,1 2,0) t=0.555550487 [5] (1.66527998,1.00412595) tEnd=0.555555556 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-debugShowActiveSpans id=3 (1,3 0,2 3,1 1,0) t=0 (1,3) tEnd=0.195806707 other=4 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,3 0,2 3,1 1,0) t=0 (1,3) tEnd=0.195806707 other=1 otherT=0 otherIndex=0 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,3 0,2 3,1 1,0) t=0 (1,3) tEnd=0.195806707 other=2 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,3 0,2 3,1 1,0) t=0.195806707 (0.80509752,2.41257977) tEnd=0.333333333 other=1 otherT=0.109171117 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,3 0,2 3,1 1,0) t=0.333333333 (1,2) tEnd=0.665291365 other=4 otherT=0.666666667 otherIndex=2 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (1,0 1,3) t=0.535136114 (1,1.60540831) tEnd=0.666666667 other=1 otherT=0.316987298 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (1,0 1,3) t=0.666666667 (1,2) tEnd=1 other=3 otherT=0.333333333 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 0,1 3,1 2,0) t=0 (1,3) tEnd=0.109171117 other=3 otherT=0 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 0,1 3,1 2,0) t=0 (1,3) tEnd=0.109171117 other=4 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 0,1 3,1 2,0) t=0 (1,3) tEnd=0.109171117 other=2 otherT=1 otherIndex=5 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 0,1 3,1 2,0) t=0.109171117 (0.80509752,2.41257977) tEnd=0.316987298 other=3 otherT=0.195806707 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 0,1 3,1 2,0) t=0.316987298 (1,1.60540831) tEnd=0.555550487 other=4 otherT=0.535136114 otherIndex=1 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 0,1 3,1 2,0) t=0.555550487 (1.66527998,1.00412595) tEnd=0.555555556 other=3 otherT=0.665291365 otherIndex=5 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 0,1 3,1 2,0) t=0.555555556 (1.66529489,1.00411522) tEnd=1 other=2 otherT=0.334705075 otherIndex=2 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (2,0 1,3) t=0 (2,0) tEnd=0.333333333 other=1 otherT=1 otherIndex=7 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (2,0 1,3) t=0.333333333 (1.66666663,1) tEnd=0.334705075 other=3 otherT=0.666666667 otherIndex=6 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (2,0 1,3) t=0.334705075 (1.66529489,1.00411522) tEnd=1 other=1 otherT=0.555555556 otherIndex=6 windSum=? windValue=1 oppValue=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=1 (1,3 0,1 3,1 2,0) t=0.316987298 [4] (1,1.60540831) tEnd=0.555550487 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1
-findChaseOp debugShowSort contourWinding=-1 oppContourWinding=1 sign=-1
-debugShowSort [0] {{1,3}, {0,1}, {3,1}, {2,0}} tStart=0.316987298 tEnd=0.555550487 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [1] {{1,0}, {1,3}} tStart=0.535136114 tEnd=0 sign=1 windValue=1 windSum=1 1->0 (max=1) done=1 tiny=0 opp=1
-debugShowSort [2] {{1,3}, {0,1}, {3,1}, {2,0}} tStart=0.316987298 tEnd=0.109171117 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [3] {{1,0}, {1,3}} tStart=0.535136114 tEnd=0.666666667 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=1
-findChaseOp debugShowSort contourWinding=-1 oppContourWinding=1 sign=-1
-debugShowSort [0] {{1,3}, {0,1}, {3,1}, {2,0}} tStart=0.316987298 tEnd=0.555550487 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [1] {{1,0}, {1,3}} tStart=0.535136114 tEnd=0 sign=1 windValue=1 windSum=1 1->0 (max=1) done=1 tiny=0 opp=1
-debugShowSort [2] {{1,3}, {0,1}, {3,1}, {2,0}} tStart=0.316987298 tEnd=0.109171117 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [3] {{1,0}, {1,3}} tStart=0.535136114 tEnd=0.666666667 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=1
-markWinding id=1 (1,3 0,1 3,1 2,0) t=0.109171117 [3] (0.80509752,2.41257977) tEnd=0.316987298 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=4 (1,0 1,3) t=0.535136114 [1] (1,1.60540831) tEnd=0.666666667 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1
-debugShowActiveSpans id=3 (1,3 0,2 3,1 1,0) t=0 (1,3) tEnd=0.195806707 other=4 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,3 0,2 3,1 1,0) t=0 (1,3) tEnd=0.195806707 other=1 otherT=0 otherIndex=0 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,3 0,2 3,1 1,0) t=0 (1,3) tEnd=0.195806707 other=2 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,3 0,2 3,1 1,0) t=0.195806707 (0.80509752,2.41257977) tEnd=0.333333333 other=1 otherT=0.109171117 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (1,3 0,2 3,1 1,0) t=0.333333333 (1,2) tEnd=0.665291365 other=4 otherT=0.666666667 otherIndex=2 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (1,0 1,3) t=0.535136114 (1,1.60540831) tEnd=0.666666667 other=1 otherT=0.316987298 otherIndex=4 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=4 (1,0 1,3) t=0.666666667 (1,2) tEnd=1 other=3 otherT=0.333333333 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 0,1 3,1 2,0) t=0 (1,3) tEnd=0.109171117 other=3 otherT=0 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 0,1 3,1 2,0) t=0 (1,3) tEnd=0.109171117 other=4 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 0,1 3,1 2,0) t=0 (1,3) tEnd=0.109171117 other=2 otherT=1 otherIndex=5 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 0,1 3,1 2,0) t=0.109171117 (0.80509752,2.41257977) tEnd=0.316987298 other=3 otherT=0.195806707 otherIndex=3 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 0,1 3,1 2,0) t=0.555550487 (1.66527998,1.00412595) tEnd=0.555555556 other=3 otherT=0.665291365 otherIndex=5 windSum=-1 windValue=1 oppValue=0
-debugShowActiveSpans id=1 (1,3 0,1 3,1 2,0) t=0.555555556 (1.66529489,1.00411522) tEnd=1 other=2 otherT=0.334705075 otherIndex=2 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (2,0 1,3) t=0 (2,0) tEnd=0.333333333 other=1 otherT=1 otherIndex=7 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (2,0 1,3) t=0.333333333 (1.66666663,1) tEnd=0.334705075 other=3 otherT=0.666666667 otherIndex=6 windSum=1 windValue=1 oppValue=0
-debugShowActiveSpans id=2 (2,0 1,3) t=0.334705075 (1.66529489,1.00411522) tEnd=1 other=1 otherT=0.555555556 otherIndex=6 windSum=? windValue=1 oppValue=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-findNextOp debugShowSort contourWinding=-1 oppContourWinding=0 sign=-1
-debugShowSort [1] {{1,3}, {0,1}, {3,1}, {2,0}} tStart=0.109171117 tEnd=0.316987298 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [2] {{1,3}, {0,2}, {3,1}, {1,0}} tStart=0.195806707 tEnd=0 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=1
-debugShowSort [3] {{1,3}, {0,1}, {3,1}, {2,0}} tStart=0.109171117 tEnd=0 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [0] {{1,3}, {0,2}, {3,1}, {1,0}} tStart=0.195806707 tEnd=0.333333333 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=1
-findNextOp firstIndex=[1] sign=-1
-activeOp op=diff miFrom=0 miTo=0 suFrom=0 suTo=1 result=0
-markDoneBinary id=3 (1,3 0,2 3,1 1,0) t=0 [1] (1,3) tEnd=0 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-markDoneBinary id=3 (1,3 0,2 3,1 1,0) t=0 [0] (1,3) tEnd=0 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-markDoneBinary id=3 (1,3 0,2 3,1 1,0) t=0 [2] (1,3) tEnd=0.195806707 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-activeOp op=diff miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-markDoneBinary id=1 (1,3 0,1 3,1 2,0) t=0 [1] (1,3) tEnd=0 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1
-markDoneBinary id=1 (1,3 0,1 3,1 2,0) t=0 [0] (1,3) tEnd=0 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1
-markDoneBinary id=1 (1,3 0,1 3,1 2,0) t=0 [2] (1,3) tEnd=0.109171117 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
-markWinding id=3 (1,3 0,2 3,1 1,0) t=0.195806707 [3] (0.80509752,2.41257977) tEnd=0.333333333 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=3
-markDoneBinary id=1 (1,3 0,1 3,1 2,0) t=0.109171117 [3] (0.80509752,2.41257977) tEnd=0.316987298 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-findNextOp from:[1] to:[3] start=3 end=4
-bridgeOp current id=1 from=(1,1.60540831) to=(0.80509752,2.41257977)
-path.moveTo(1,1.60540831);
-path.cubicTo(0.847867966,1.82018507, 0.758966982,2.08026719, 0.80509752,2.41257977);
-findNextOp debugShowSort contourWinding=0 oppContourWinding=-1 sign=1
-debugShowSort [2] {{1,3}, {0,2}, {3,1}, {1,0}} tStart=0.333333333 tEnd=0.195806707 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [3] {{1,0}, {1,3}} tStart=0.666666667 tEnd=1 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [0] {{1,3}, {0,2}, {3,1}, {1,0}} tStart=0.333333333 tEnd=0.665291365 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] {{1,0}, {1,3}} tStart=0.666666667 tEnd=0.535136114 sign=1 windValue=1 windSum=1 1->0 (max=1) done=0 tiny=0 opp=0
-findNextOp firstIndex=[2] sign=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
-markWinding id=4 (1,0 1,3) t=0.666666667 [2] (1,2) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=4
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
-markDoneBinary id=3 (1,3 0,2 3,1 1,0) t=0.195806707 [3] (0.80509752,2.41257977) tEnd=0.333333333 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1
-findNextOp from:[3] to:[4] start=2 end=3
-bridgeOp current id=3 from=(0.80509752,2.41257977) to=(1,2)
-path.cubicTo(0.835544765,2.27505326, 0.908315599,2.13752651, 1,2);
-findNextOp debugShowSort contourWinding=0 oppContourWinding=-1 sign=1
-debugShowSort [1] {{1,0}, {1,3}} tStart=1 tEnd=0.666666667 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [2] {{1,3}, {0,1}, {3,1}, {2,0}} tStart=0 tEnd=0.109171117 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=1
-debugShowSort [3] {{1,3}, {0,2}, {3,1}, {1,0}} tStart=0 tEnd=0.195806707 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [0] {{2,0}, {1,3}} tStart=1 tEnd=0.334705075 sign=1 windValue=1 windSum=? 0->-1 (max=-1) done=0 tiny=0 opp=1
-findNextOp firstIndex=[1] sign=1
-activeOp op=diff miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-markWinding id=2 (2,0 1,3) t=0.334705075 [2] (1.66529489,1.00411522) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextOp chase.append id=2
-markDoneBinary id=4 (1,0 1,3) t=0.666666667 [2] (1,2) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1
-findNextOp from:[4] to:[2] start=4 end=2
-bridgeOp current id=4 from=(1,2) to=(1,3)
-findNextOp debugShowSort contourWinding=-1 oppContourWinding=0 sign=-1
-debugShowSort [3] {{2,0}, {1,3}} tStart=0.334705075 tEnd=1 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [0] {{1,3}, {0,1}, {3,1}, {2,0}} tStart=0.555555556 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] {{2,0}, {1,3}} tStart=0.334705075 tEnd=0.333333333 sign=1 windValue=1 windSum=1 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [2] {{1,3}, {0,1}, {3,1}, {2,0}} tStart=0.555555556 tEnd=0.555550487 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=0 tiny=0 opp=0
-findNextOp firstIndex=[3] sign=-1
-activeOp op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-activeOp op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-activeOp op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-markDoneBinary id=2 (2,0 1,3) t=0.334705075 [2] (1.66529489,1.00411522) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-findNextOp from:[2] to:[1] start=6 end=7
-bridgeOp current id=2 from=(1,3) to=(1.66529489,1.00411522)
-path.lineTo(1,3);
-findNextOp simple
-markDoneBinary id=1 (1,3 0,1 3,1 2,0) t=0.555555556 [6] (1.66529489,1.00411522) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-bridgeOp current id=1 from=(1.66529489,1.00411522) to=(2,0)
-path.lineTo(1.66529489,1.00411522);
-path.cubicTo(2.09876537,0.69135803, 2.44444442,0.444444448, 2,0);
-findNextOp debugShowSort contourWinding=1 oppContourWinding=0 sign=1
-debugShowSort [0] {{2,0}, {1,3}} tStart=0.333333333 tEnd=0 sign=1 windValue=1 windSum=1 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] {{1,3}, {0,2}, {3,1}, {1,0}} tStart=0.666666667 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=1
-debugShowSort [2] {{1,3}, {0,2}, {3,1}, {1,0}} tStart=0.666666667 tEnd=0.665291365 sign=1 windValue=1 windSum=1 1->0 (max=1) done=1 tiny=0 opp=1
-debugShowSort [3] {{2,0}, {1,3}} tStart=0.333333333 tEnd=0.334705075 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=0 tiny=0 opp=0
-findNextOp firstIndex=[0] sign=1
-activeOp op=diff miFrom=0 miTo=0 suFrom=0 suTo=1 result=0
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-markDoneBinary id=2 (2,0 1,3) t=0 [0] (2,0) tEnd=0.333333333 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-findNextOp from:[2] to:[2] start=1 end=2
-bridgeOp current id=2 from=(2,0) to=(1.66666663,1)
-findNextOp debugShowSort contourWinding=1 oppContourWinding=0 sign=1
-debugShowSort [1] {{2,0}, {1,3}} tStart=0.334705075 tEnd=0.333333333 sign=1 windValue=1 windSum=1 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [2] {{1,3}, {0,1}, {3,1}, {2,0}} tStart=0.555555556 tEnd=0.555550487 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [3] {{2,0}, {1,3}} tStart=0.334705075 tEnd=1 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [0] {{1,3}, {0,1}, {3,1}, {2,0}} tStart=0.555555556 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=0
-findNextOp firstIndex=[1] sign=1
-activeOp op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-activeOp op=diff miFrom=1 miTo=0 suFrom=0 suTo=0 result=1
-activeOp op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-markDoneBinary id=2 (2,0 1,3) t=0.333333333 [1] (1.66666663,1) tEnd=0.334705075 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-findNextOp from:[2] to:[1] start=6 end=5
-bridgeOp current id=2 from=(1.66666663,1) to=(1.66529489,1.00411522)
-path.lineTo(1.66666663,1);
-findNextOp debugShowSort contourWinding=-1 oppContourWinding=0 sign=-1
-debugShowSort [0] {{1,3}, {0,1}, {3,1}, {2,0}} tStart=0.555550487 tEnd=0.555555556 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [1] {{1,3}, {0,2}, {3,1}, {1,0}} tStart=0.665291365 tEnd=0.666666667 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=1 tiny=0 opp=1
-debugShowSort [2] {{1,3}, {0,1}, {3,1}, {2,0}} tStart=0.555550487 tEnd=0.316987298 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [3] {{1,3}, {0,2}, {3,1}, {1,0}} tStart=0.665291365 tEnd=0.333333333 sign=1 windValue=1 windSum=1 1->0 (max=1) done=0 tiny=0 opp=1
-findNextOp firstIndex=[0] sign=-1
-activeOp op=diff miFrom=0 miTo=0 suFrom=0 suTo=1 result=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=1 suTo=1 result=0
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
-markDoneBinary id=1 (1,3 0,1 3,1 2,0) t=0.555550487 [5] (1.66527998,1.00412595) tEnd=0.555555556 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1
-findNextOp from:[1] to:[3] start=5 end=4
-bridgeOp current id=1 from=(1.66529489,1.00411522) to=(1.66527998,1.00412595)
-path.lineTo(1.66529489,1.00411522);
-path.cubicTo(1.66529,1.0041188, 1.66528511,1.00412238, 1.66527998,1.00412595);
-findNextOp debugShowSort contourWinding=0 oppContourWinding=-1 sign=-1
-debugShowSort [0] {{1,3}, {0,2}, {3,1}, {1,0}} tStart=0.333333333 tEnd=0.665291365 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] {{1,0}, {1,3}} tStart=0.666666667 tEnd=0.535136114 sign=1 windValue=1 windSum=1 1->0 (max=1) done=0 tiny=0 opp=0
-debugShowSort [2] {{1,3}, {0,2}, {3,1}, {1,0}} tStart=0.333333333 tEnd=0.195806707 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=0
-debugShowSort [3] {{1,0}, {1,3}} tStart=0.666666667 tEnd=1 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=0
-findNextOp firstIndex=[0] sign=-1
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=0 suTo=1 result=1
-activeOp op=diff miFrom=1 miTo=1 suFrom=1 suTo=0 result=1
-markDoneBinary id=3 (1,3 0,2 3,1 1,0) t=0.333333333 [4] (1,2) tEnd=0.665291365 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1
-findNextOp from:[3] to:[4] start=2 end=1
-bridgeOp current id=3 from=(1.66527998,1.00412595) to=(1,2)
-path.cubicTo(1.55280685,1.33608389, 1.22130537,1.66804194, 1,2);
-findNextOp debugShowSort contourWinding=0 oppContourWinding=-1 sign=-1
-debugShowSort [3] {{1,0}, {1,3}} tStart=0.535136114 tEnd=0.666666667 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [0] {{1,3}, {0,1}, {3,1}, {2,0}} tStart=0.316987298 tEnd=0.555550487 sign=-1 windValue=1 windSum=-1 -1->0 (max=-1) done=1 tiny=0 opp=1
-debugShowSort [1] {{1,0}, {1,3}} tStart=0.535136114 tEnd=0 sign=1 windValue=1 windSum=1 1->0 (max=1) done=1 tiny=0 opp=0
-debugShowSort [2] {{1,3}, {0,1}, {3,1}, {2,0}} tStart=0.316987298 tEnd=0.109171117 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=1 tiny=0 opp=1
-findNextOp firstIndex=[3] sign=-1
-activeOp op=diff miFrom=1 miTo=0 suFrom=1 suTo=1 result=0
-activeOp op=diff miFrom=0 miTo=0 suFrom=1 suTo=0 result=0
-activeOp op=diff miFrom=0 miTo=1 suFrom=0 suTo=0 result=1
-markDoneBinary id=4 (1,0 1,3) t=0.535136114 [1] (1,1.60540831) tEnd=0.666666667 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1
-findNextOp from:[4] to:[1] start=4 end=3
-bridgeOp current id=4 from=(1,2) to=(1,1.60540831)
-path.lineTo(1,1.60540831);
-path.close();
-</div>
-
-<div id="testTriangles1">
- RunTestSet [testTriangles1]
-{{0,0}, {1,0}},
-{{1,0}, {3,3}},
-{{3,3}, {0,0}},
-{{0,0}, {1,2}},
-{{1,2}, {1,1}},
-{{1,1}, {0,0}},
-debugShowLineIntersection wtTs[0]=0 {{0,0}, {1,0}} {{1,0}} wnTs[0]=1 {{1,0}, {3,3}}
-debugShowLineIntersection wtTs[0]=1 {{0,0}, {1,0}} {{0,0}} wnTs[0]=0 {{3,3}, {0,0}}
-debugShowLineIntersection wtTs[0]=1 {{1,0}, {3,3}} {{3,3}} wnTs[0]=0 {{3,3}, {0,0}}
-debugShowLineIntersection wtTs[0]=0 {{0,0}, {1,0}} {{0,0}} wnTs[0]=0 {{0,0}, {1,2}}
-debugShowLineIntersection wtTs[0]=1 {{0,0}, {1,0}} {{0,0}} wnTs[0]=0 {{1,1}, {0,0}}
-debugShowLineIntersection no intersect {{1,0}, {3,3}} {{0,0}, {1,2}}
-debugShowLineIntersection no intersect {{1,0}, {3,3}} {{1,2}, {1,1}}
-debugShowLineIntersection no intersect {{1,0}, {3,3}} {{1,1}, {0,0}}
-debugShowLineIntersection wtTs[0]=1 {{3,3}, {0,0}} {{0,0}} wnTs[0]=-0 {{0,0}, {1,2}}
-debugShowLineIntersection wtTs[0]=0.666666667 {{3,3}, {0,0}} {{1,1}} wnTs[0]=1 {{1,2}, {1,1}}
-debugShowLineIntersection wtTs[0]=0.666666667 {{3,3}, {0,0}} {{1,1}} wtTs[1]=1 {{0,0}} wnTs[0]=0 {{1,1}, {0,0}} wnTs[1]=1
-debugShowLineIntersection wtTs[0]=1 {{0,0}, {1,2}} {{1,2}} wnTs[0]=0 {{1,2}, {1,1}}
-debugShowLineIntersection wtTs[0]=0 {{0,0}, {1,2}} {{0,0}} wnTs[0]=1 {{1,1}, {0,0}}
-debugShowLineIntersection wtTs[0]=-0 {{1,2}, {1,1}} {{1,1}} wnTs[0]=1 {{1,1}, {0,0}}
-debugShowTs id=3 [o=2 t=0 3,3 w=1 o=0] [o=5 t=0.667 1,1 w=1 o=0] [o=1,4 t=1 0,0 w=1 o=0]
-debugShowTs id=6 [o=5 t=-0 1,1 w=1 o=0] [o=1,4 t=1 0,0 w=1 o=0]
-addTPair addTPair this=3 0.666666667 other=6 0
-debugShowTs id=3 [o=2 t=0 3,3 w=1 o=0] [o=5,6 t=0.667 1,1 w=1 o=0] [o=1,4 t=1 0,0 w=1 o=0]
-debugShowTs id=6 [o=5,3 t=-0 1,1 w=1 o=0] [o=1,4 t=1 0,0 w=1 o=0]
-debugShowTs id=3 [o=2 t=0 3,3 w=1 o=0] [o=5,6 t=0.667 1,1 w=2 o=0] [o=1,4 t=1 0,0 w=1 o=0]
-debugShowTs id=6 [o=5,3 t=-0 1,1 w=0 o=0] [o=1,4 t=1 0,0 w=1 o=0] done
-debugShowActiveSpans id=1 (0,0 1,0) t=0 (0,0) tEnd=1 other=3 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,0 1,0) t=0 (0,0) tEnd=1 other=4 otherT=0 otherIndex=0 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,0 1,0) t=0 (0,0) tEnd=1 other=6 otherT=1 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (1,0 3,3) t=0 (1,0) tEnd=1 other=1 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (3,3 0,0) t=0 (3,3) tEnd=0.666666667 other=2 otherT=1 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (3,3 0,0) t=0.666666667 (1,1) tEnd=1 other=5 otherT=1 otherIndex=1 windSum=? windValue=2 oppValue=0
-debugShowActiveSpans id=3 (3,3 0,0) t=0.666666667 (1,1) tEnd=1 other=6 otherT=0 otherIndex=1 windSum=? windValue=2 oppValue=0
-debugShowActiveSpans id=4 (0,0 1,2) t=0 (0,0) tEnd=1 other=1 otherT=0 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (0,0 1,2) t=-0 (0,0) tEnd=1 other=3 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (0,0 1,2) t=0 (0,0) tEnd=1 other=6 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=5 (1,2 1,1) t=0 (1,2) tEnd=1 other=4 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=5 (1,2 1,1) t=1 (1,1) tEnd=1 other=3 otherT=0.666666667 otherIndex=1 windSum=? windValue=1 oppValue=0
-findTop debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [0] {{0,0}, {1,2}} tStart=0 tEnd=1 sign=-1 windValue=1 windSum=? 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] {{3,3}, {0,0}} tStart=1 tEnd=0.666666667 sign=1 windValue=2 windSum=? 1->-1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [2] {{0,0}, {1,0}} tStart=0 tEnd=1 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-markWinding id=4 (0,0 1,2) t=0 [0] (0,0) tEnd=-0 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=4 (0,0 1,2) t=-0 [1] (0,0) tEnd=0 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=4 (0,0 1,2) t=0 [2] (0,0) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=4 (0,0 1,2) t=0 [0] (0,0) tEnd=-0 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-markWinding id=4 (0,0 1,2) t=-0 [1] (0,0) tEnd=0 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-markWinding id=4 (0,0 1,2) t=0 [2] (0,0) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-markWinding id=5 (1,2 1,1) t=0 [0] (1,2) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextWinding debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [0] {{0,0}, {1,2}} tStart=0 tEnd=1 sign=-1 windValue=1 windSum=1 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] {{3,3}, {0,0}} tStart=1 tEnd=0.666666667 sign=1 windValue=2 windSum=? 1->-1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [2] {{0,0}, {1,0}} tStart=0 tEnd=1 sign=-1 windValue=1 windSum=? -1->0 (max=-1) done=0 tiny=0 opp=0
-findNextWinding firstIndex=[0] sign=-1
-markDone id=3 (3,3 0,0) t=0.666666667 [1] (1,1) tEnd=0.666666667 newWindSum=1 windSum=? windValue=2
-markDone id=3 (3,3 0,0) t=0.666666667 [2] (1,1) tEnd=1 newWindSum=1 windSum=? windValue=2
-findNextWinding chase.append id=3
-markWinding id=1 (0,0 1,0) t=0 [0] (0,0) tEnd=0 newWindSum=-1 windSum=? windValue=1
-markWinding id=1 (0,0 1,0) t=0 [1] (0,0) tEnd=0 newWindSum=-1 windSum=? windValue=1
-markWinding id=1 (0,0 1,0) t=0 [2] (0,0) tEnd=1 newWindSum=-1 windSum=? windValue=1
-markWinding id=2 (1,0 3,3) t=0 [0] (1,0) tEnd=1 newWindSum=-1 windSum=? windValue=1
-markWinding id=3 (3,3 0,0) t=0 [0] (3,3) tEnd=0.666666667 newWindSum=-1 windSum=? windValue=1
-findNextWinding chase.append id=3
-markDoneUnary id=4 (0,0 1,2) t=0 [0] (0,0) tEnd=-0 newWindSum=1 windSum=1 windValue=1
-markDoneUnary id=4 (0,0 1,2) t=-0 [1] (0,0) tEnd=0 newWindSum=1 windSum=1 windValue=1
-markDoneUnary id=4 (0,0 1,2) t=0 [2] (0,0) tEnd=1 newWindSum=1 windSum=1 windValue=1
-findNextWinding from:[4] to:[1] start=1 end=3
-bridgeWinding current id=4 from=(1,2) to=(0,0)
-findNextWinding simple
-markDoneUnary id=1 (0,0 1,0) t=0 [0] (0,0) tEnd=0 newWindSum=-1 windSum=-1 windValue=1
-markDoneUnary id=1 (0,0 1,0) t=0 [1] (0,0) tEnd=0 newWindSum=-1 windSum=-1 windValue=1
-markDoneUnary id=1 (0,0 1,0) t=0 [2] (0,0) tEnd=1 newWindSum=-1 windSum=-1 windValue=1
-bridgeWinding current id=1 from=(0,0) to=(1,0)
-path.moveTo(1,2);
-path.lineTo(0,0);
-findNextWinding simple
-markDoneUnary id=2 (1,0 3,3) t=0 [0] (1,0) tEnd=1 newWindSum=-1 windSum=-1 windValue=1
-bridgeWinding current id=2 from=(1,0) to=(3,3)
-path.lineTo(1,0);
-findNextWinding debugShowSort contourWinding=0 oppContourWinding=? sign=1
-debugShowSort [2] {{3,3}, {0,0}} tStart=0.666666667 tEnd=0 sign=1 windValue=1 windSum=-1 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [0] {{3,3}, {0,0}} tStart=0.666666667 tEnd=1 sign=-1 windValue=2 windSum=1 -1->1 (max=1) done=1 tiny=0 opp=0
-debugShowSort [1] {{1,2}, {1,1}} tStart=1 tEnd=0 sign=1 windValue=1 windSum=1 1->0 (max=1) done=0 tiny=0 opp=0
-findNextWinding firstIndex=[2] sign=1
-markDoneUnary id=3 (3,3 0,0) t=0 [0] (3,3) tEnd=0.666666667 newWindSum=-1 windSum=-1 windValue=1
-findNextWinding from:[3] to:[5] start=1 end=0
-bridgeWinding current id=3 from=(3,3) to=(1,1)
-path.lineTo(3,3);
-findNextWinding simple
-markDoneUnary id=5 (1,2 1,1) t=0 [0] (1,2) tEnd=1 newWindSum=1 windSum=1 windValue=1
-bridgeWinding current id=5 from=(1,1) to=(1,2)
-path.lineTo(1,1);
-path.lineTo(1,2);
-path.close();
-debugShowActiveSpans id=5 (1,2 1,1) t=1 (1,1) tEnd=1 other=3 otherT=0.666666667 otherIndex=1 windSum=? windValue=1 oppValue=0
-findTop debugShowSort contourWinding=0 oppContourWinding=0 sign=-2
-debugShowSort [0] {{3,3}, {0,0}} tStart=0.666666667 tEnd=1 sign=-1 windValue=2 windSum=1 0->2 (max=2) done=1 tiny=0 opp=0
-debugShowSort [1] {{1,2}, {1,1}} tStart=1 tEnd=0 sign=1 windValue=1 windSum=1 2->1 (max=2) done=1 tiny=0 opp=0
-debugShowSort [2] {{3,3}, {0,0}} tStart=0.666666667 tEnd=0 sign=1 windValue=1 windSum=-1 1->0 (max=1) done=1 tiny=0 opp=0
-</div>
-
-<div id="testTriangles1a">
- RunTestSet [testTriangles1a]
-debugShowLineIntersection wtTs[0]=0 {{0,0}, {1,0}} {{1,0}} wnTs[0]=1 {{1,0}, {3,3}}
-debugShowLineIntersection wtTs[0]=1 {{0,0}, {1,0}} {{0,0}} wnTs[0]=0 {{3,3}, {0,0}}
-debugShowLineIntersection wtTs[0]=1 {{1,0}, {3,3}} {{3,3}} wnTs[0]=0 {{3,3}, {0,0}}
-debugShowLineIntersection wtTs[0]=0 {{0,0}, {1,0}} {{0,0}} wnTs[0]=0 {{0,0}, {1,2}}
-debugShowLineIntersection wtTs[0]=1 {{0,0}, {1,0}} {{0,0}} wnTs[0]=0 {{1,1}, {0,0}}
-debugShowLineIntersection no intersect {{1,0}, {3,3}} {{0,0}, {1,2}}
-debugShowLineIntersection no intersect {{1,0}, {3,3}} {{1,2}, {1,1}}
-debugShowLineIntersection no intersect {{1,0}, {3,3}} {{1,1}, {0,0}}
-debugShowLineIntersection wtTs[0]=1 {{3,3}, {0,0}} {{0,0}} wnTs[0]=-0 {{0,0}, {1,2}}
-debugShowLineIntersection wtTs[0]=0.666666667 {{3,3}, {0,0}} {{1,1}} wnTs[0]=1 {{1,2}, {1,1}}
-debugShowLineIntersection wtTs[0]=0.666666667 {{3,3}, {0,0}} {{1,1}} wtTs[1]=1 {{0,0}} wnTs[0]=0 {{1,1}, {0,0}} wnTs[1]=1
-debugShowLineIntersection wtTs[0]=1 {{0,0}, {1,2}} {{1,2}} wnTs[0]=0 {{1,2}, {1,1}}
-debugShowLineIntersection wtTs[0]=0 {{0,0}, {1,2}} {{0,0}} wnTs[0]=1 {{1,1}, {0,0}}
-debugShowLineIntersection wtTs[0]=-0 {{1,2}, {1,1}} {{1,1}} wnTs[0]=1 {{1,1}, {0,0}}
-debugShowTs id=3 [o=2 t=0 3,3 w=1 o=0] [o=5 t=0.667 1,1 w=1 o=0] [o=1,4 t=1 0,0 w=1 o=0]
-debugShowTs id=6 [o=5 t=-0 1,1 w=1 o=0] [o=1,4 t=1 0,0 w=1 o=0]
-addTPair addTPair this=3 0.666666667 other=6 0
-debugShowTs id=3 [o=2 t=0 3,3 w=1 o=0] [o=5,6 t=0.667 1,1 w=1 o=0] [o=1,4 t=1 0,0 w=1 o=0]
-debugShowTs id=6 [o=5,3 t=-0 1,1 w=1 o=0] [o=1,4 t=1 0,0 w=1 o=0]
-debugShowTs id=3 [o=2 t=0 3,3 w=1 o=0] [o=5,6 t=0.667 1,1 w=2 o=0] [o=1,4 t=1 0,0 w=1 o=0]
-debugShowTs id=6 [o=5,3 t=-0 1,1 w=0 o=0] [o=1,4 t=1 0,0 w=1 o=0] done
-debugShowActiveSpans id=1 (0,0 1,0) t=0 (0,0) tEnd=1 other=3 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,0 1,0) t=0 (0,0) tEnd=1 other=4 otherT=0 otherIndex=0 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=1 (0,0 1,0) t=0 (0,0) tEnd=1 other=6 otherT=1 otherIndex=2 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=2 (1,0 3,3) t=0 (1,0) tEnd=1 other=1 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (3,3 0,0) t=0 (3,3) tEnd=0.666666667 other=2 otherT=1 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=3 (3,3 0,0) t=0.666666667 (1,1) tEnd=1 other=5 otherT=1 otherIndex=1 windSum=? windValue=2 oppValue=0
-debugShowActiveSpans id=3 (3,3 0,0) t=0.666666667 (1,1) tEnd=1 other=6 otherT=0 otherIndex=1 windSum=? windValue=2 oppValue=0
-debugShowActiveSpans id=4 (0,0 1,2) t=0 (0,0) tEnd=1 other=1 otherT=0 otherIndex=1 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (0,0 1,2) t=-0 (0,0) tEnd=1 other=3 otherT=1 otherIndex=4 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=4 (0,0 1,2) t=0 (0,0) tEnd=1 other=6 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-debugShowActiveSpans id=5 (1,2 1,1) t=0 (1,2) tEnd=1 other=4 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0
-findTop debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [0] {{0,0}, {1,2}} tStart=0 tEnd=1 sign=-1 windValue=1 windSum= 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] {{3,3}, {0,0}} tStart=1 tEnd=0.666666667 sign=1 windValue=2 windSum= 1->-1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [2] {{0,0}, {1,0}} tStart=0 tEnd=1 sign=-1 windValue=1 windSum= -1->0 (max=-1) done=0 tiny=0 opp=0
-markWinding id=4 (0,0 1,2) t=0 [0] (0,0) tEnd=-0 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=4 (0,0 1,2) t=-0 [1] (0,0) tEnd=0 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=4 (0,0 1,2) t=0 [2] (0,0) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-markWinding id=4 (0,0 1,2) t=0 [0] (0,0) tEnd=-0 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-markWinding id=4 (0,0 1,2) t=-0 [1] (0,0) tEnd=0 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-markWinding id=4 (0,0 1,2) t=0 [2] (0,0) tEnd=1 newWindSum=1 newOppSum=0 oppSum=0 windSum=1 windValue=1
-markWinding id=5 (1,2 1,1) t=0 [0] (1,2) tEnd=1 newWindSum=1 newOppSum=0 oppSum=? windSum=? windValue=1
-findNextWinding debugShowSort contourWinding=0 oppContourWinding=0 sign=-1
-debugShowSort [0] {{0,0}, {1,2}} tStart=0 tEnd=1 sign=-1 windValue=1 windSum= 0->1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [1] {{3,3}, {0,0}} tStart=1 tEnd=0.666666667 sign=1 windValue=2 windSum= 1->-1 (max=1) done=0 tiny=0 opp=0
-debugShowSort [2] {{0,0}, {1,0}} tStart=0 tEnd=1 sign=-1 windValue=1 windSum= -1->0 (max=-1) done=0 tiny=0 opp=0
-findNextWinding firstIndex=[0] sign=-1
-markDone id=3 (3,3 0,0) t=0.666666667 [1] (1,1) tEnd=0.666666667 newWindSum=1 windSum=? windValue=2
-markDone id=3 (3,3 0,0) t=0.666666667 [2] (1,1) tEnd=1 newWindSum=1 windSum=? windValue=2
-findNextWinding chase.append id=3
-markWinding id=1 (0,0 1,0) t=0 [0] (0,0) tEnd=0 newWindSum=-1 windSum=? windValue=1
-markWinding id=1 (0,0 1,0) t=0 [1] (0,0) tEnd=0 newWindSum=-1 windSum=? windValue=1
-markWinding id=1 (0,0 1,0) t=0 [2] (0,0) tEnd=1 newWindSum=-1 windSum=? windValue=1
-markWinding id=2 (1,0 3,3) t=0 [0] (1,0) tEnd=1 newWindSum=-1 windSum=? windValue=1
-markWinding id=3 (3,3 0,0) t=0 [0] (3,3) tEnd=0.666666667 newWindSum=-1 windSum=? windValue=1
-findNextWinding chase.append id=3
-markDoneUnary id=4 (0,0 1,2) t=0 [0] (0,0) tEnd=-0 newWindSum=1 windSum=1 windValue=1
-markDoneUnary id=4 (0,0 1,2) t=-0 [1] (0,0) tEnd=0 newWindSum=1 windSum=1 windValue=1
-markDoneUnary id=4 (0,0 1,2) t=0 [2] (0,0) tEnd=1 newWindSum=1 windSum=1 windValue=1
-findNextWinding from:[4] to:[1] start=1 end=3
-bridgeWinding current id=4 from=(1,2) to=(0,0)
-findNextWinding simple
-markDoneUnary id=1 (0,0 1,0) t=0 [0] (0,0) tEnd=0 newWindSum=-1 windSum=-1 windValue=1
-markDoneUnary id=1 (0,0 1,0) t=0 [1] (0,0) tEnd=0 newWindSum=-1 windSum=-1 windValue=1
-markDoneUnary id=1 (0,0 1,0) t=0 [2] (0,0) tEnd=1 newWindSum=-1 windSum=-1 windValue=1
-bridgeWinding current id=1 from=(0,0) to=(1,0)
-path.moveTo(1,2);
-path.lineTo(0,0);
-findNextWinding simple
-markDoneUnary id=2 (1,0 3,3) t=0 [0] (1,0) tEnd=1 newWindSum=-1 windSum=-1 windValue=1
-bridgeWinding current id=2 from=(1,0) to=(3,3)
-path.lineTo(1,0);
-findNextWinding debugShowSort contourWinding=0 oppContourWinding=? sign=1
-debugShowSort [2] {{3,3}, {0,0}} tStart=0.666666667 tEnd=0 sign=1 windValue=1 windSum= 0->-1 (max=-1) done=0 tiny=0 opp=0
-debugShowSort [0] {{3,3}, {0,0}} tStart=0.666666667 tEnd=1 sign=-1 windValue=2 windSum= -1->1 (max=1) done=1 tiny=0 opp=0
-debugShowSort [1] {{1,2}, {1,1}} tStart=1 tEnd=0 sign=1 windValue=1 windSum= 1->0 (max=1) done=0 tiny=0 opp=0
-findNextWinding firstIndex=[2] sign=1
-markDoneUnary id=3 (3,3 0,0) t=0 [0] (3,3) tEnd=0.666666667 newWindSum=-1 windSum=-1 windValue=1
-findNextWinding from:[3] to:[5] start=1 end=0
-bridgeWinding current id=3 from=(3,3) to=(1,1)
-path.lineTo(3,3);
-findNextWinding simple
-markDoneUnary id=5 (1,2 1,1) t=0 [0] (1,2) tEnd=1 newWindSum=1 windSum=1 windValue=1
-bridgeWinding current id=5 from=(1,1) to=(1,2)
-path.lineTo(1,1);
-path.lineTo(1,2);
-path.close();
-</div>
-
-</div>
-
-<script type="text/javascript">
-
-var testDivs = [
- testTriangles1a,
- testTriangles1,
- cubicOp69da,
- cubicOp69d,
- cubicOp68ua,
- cubicOp68u,
- cubicOp67u,
- testQuad1,
- cubicOp62d,
- cubicOp61d,
- cubicOp58da,
- cubicOp58d,
- cubicOp57da,
- cubicOp56da,
- cubicOp55da,
- cubicOp55d,
- cubicOp54dd,
- cubicOp54dc,
- cubicOp54db,
- cubicOp54da,
- cubicOp54d,
- cubicOp53db,
- cubicOp53da,
- cubicOp53d,
- cubicOp52db,
- cubicOp52da,
- cubicOp51da,
- cubicOp51d,
- cubicOp50d,
- cubicOp49d,
- cubicOp48dc,
- cubicOp48db,
- cubicOp48da,
- cubicOp48d,
- cubicOp47db,
- cubicOp47da,
- cubicOp47d,
- cubicOp46db,
- cubicOp46da,
- cubicOp46d,
- cubicOp45d,
- cubicOp44d,
- cubicOp43d,
- cubicOp42d,
- cubicOp42da,
- cubicOp42db,
- cubicOp41i,
- cubicOp40d,
- cubicOp39da,
- cubicOp39d,
- cubicOp38d,
- cubicOp38da,
- cubicOp36u,
- cubicOp35da,
- cubicOp32d,
-];
-
-var decimal_places = 3; // make this 3 to show more precision
-
-var tests = [];
-var testLines = [];
-var testTitles = [];
-var testIndex = 0;
-var ctx;
-
-var xmin, xmax;
-var ymin, ymax;
-var scale;
-var mouseX, mouseY;
-var srcLeft, srcTop;
-var screenWidth, screenHeight;
-var drawnPts, drawnLines, drawnQuads, drawnCubics;
-var curveT = 0;
-
-var pt_labels = 2;
-var control_lines = 0;
-var curve_t = false;
-var debug_xy = false;
-var step_limit = 0;
-var draw_active = false;
-var draw_add = false;
-var draw_deriviatives = 0;
-var draw_hints = false;
-var draw_hodo = 0;
-var draw_intersection = 0;
-var draw_intersectT = false;
-var draw_legend = true;
-var draw_log = false;
-var draw_mark = false;
-var draw_midpoint = false;
-var draw_sequence = false;
-var draw_sort = false;
-var draw_path = 3;
-var draw_computed = 0;
-
-var activeCount = 0;
-var addCount = 0;
-var sectCount = 0;
-var sortCount = 0;
-var markCount = 0;
-var activeMax = 0;
-var addMax = 0;
-var sectMax = 0;
-var sectMax2 = 0;
-var sortMax = 0;
-var markMax = 0;
-var stepMax = 0;
-var lastIndex = 0;
-var hasPath = false;
-var hasComputedPath = false;
-
-var SPAN_ID = 0;
-var SPAN_X1 = SPAN_ID + 1;
-var SPAN_Y1 = SPAN_X1 + 1;
-var SPAN_X2 = SPAN_Y1 + 1;
-var SPAN_Y2 = SPAN_X2 + 1;
-var SPAN_L_T = SPAN_Y2 + 1;
-var SPAN_L_TX = SPAN_L_T + 1;
-var SPAN_L_TY = SPAN_L_TX + 1;
-var SPAN_L_TEND = SPAN_L_TY + 1;
-var SPAN_L_OTHER = SPAN_L_TEND + 1;
-var SPAN_L_OTHERT = SPAN_L_OTHER + 1;
-var SPAN_L_OTHERI = SPAN_L_OTHERT + 1;
-var SPAN_L_SUM = SPAN_L_OTHERI + 1;
-var SPAN_L_VAL = SPAN_L_SUM + 1;
-var SPAN_L_OPP = SPAN_L_VAL + 1;
-
-var SPAN_X3 = SPAN_Y2 + 1;
-var SPAN_Y3 = SPAN_X3 + 1;
-var SPAN_Q_T = SPAN_Y3 + 1;
-var SPAN_Q_TX = SPAN_Q_T + 1;
-var SPAN_Q_TY = SPAN_Q_TX + 1;
-var SPAN_Q_TEND = SPAN_Q_TY + 1;
-var SPAN_Q_OTHER = SPAN_Q_TEND + 1;
-var SPAN_Q_OTHERT = SPAN_Q_OTHER + 1;
-var SPAN_Q_OTHERI = SPAN_Q_OTHERT + 1;
-var SPAN_Q_SUM = SPAN_Q_OTHERI + 1;
-var SPAN_Q_VAL = SPAN_Q_SUM + 1;
-var SPAN_Q_OPP = SPAN_Q_VAL + 1;
-
-var SPAN_X4 = SPAN_Y3 + 1;
-var SPAN_Y4 = SPAN_X4 + 1;
-var SPAN_C_T = SPAN_Y4 + 1;
-var SPAN_C_TX = SPAN_C_T + 1;
-var SPAN_C_TY = SPAN_C_TX + 1;
-var SPAN_C_TEND = SPAN_C_TY + 1;
-var SPAN_C_OTHER = SPAN_C_TEND + 1;
-var SPAN_C_OTHERT = SPAN_C_OTHER + 1;
-var SPAN_C_OTHERI = SPAN_C_OTHERT + 1;
-var SPAN_C_SUM = SPAN_C_OTHERI + 1;
-var SPAN_C_VAL = SPAN_C_SUM + 1;
-var SPAN_C_OPP = SPAN_C_VAL + 1;
-
-var ACTIVE_LINE_SPAN = 1;
-var ACTIVE_QUAD_SPAN = ACTIVE_LINE_SPAN + 1;
-var ACTIVE_CUBIC_SPAN = ACTIVE_QUAD_SPAN + 1;
-
-var ADD_MOVETO = ACTIVE_CUBIC_SPAN + 1;
-var ADD_LINETO = ADD_MOVETO + 1;
-var ADD_QUADTO = ADD_LINETO + 1;
-var ADD_CUBICTO = ADD_QUADTO + 1;
-var ADD_CLOSE = ADD_CUBICTO + 1;
-
-var PATH_LINE = ADD_CLOSE + 1;
-var PATH_QUAD = PATH_LINE + 1;
-var PATH_CUBIC = PATH_QUAD + 1;
-
-var INTERSECT_LINE = PATH_CUBIC + 1;
-var INTERSECT_LINE_2 = INTERSECT_LINE + 1;
-var INTERSECT_LINE_NO = INTERSECT_LINE_2 + 1;
-var INTERSECT_QUAD_LINE = INTERSECT_LINE_NO + 1;
-var INTERSECT_QUAD_LINE_2 = INTERSECT_QUAD_LINE + 1;
-var INTERSECT_QUAD_LINE_NO = INTERSECT_QUAD_LINE_2 + 1;
-var INTERSECT_QUAD = INTERSECT_QUAD_LINE_NO + 1;
-var INTERSECT_QUAD_2 = INTERSECT_QUAD + 1;
-var INTERSECT_QUAD_NO = INTERSECT_QUAD_2 + 1;
-var INTERSECT_SELF_CUBIC = INTERSECT_QUAD_NO + 1;
-var INTERSECT_SELF_CUBIC_NO = INTERSECT_SELF_CUBIC + 1;
-var INTERSECT_CUBIC_LINE = INTERSECT_SELF_CUBIC_NO + 1;
-var INTERSECT_CUBIC_LINE_2 = INTERSECT_CUBIC_LINE + 1;
-var INTERSECT_CUBIC_LINE_3 = INTERSECT_CUBIC_LINE_2 + 1;
-var INTERSECT_CUBIC_LINE_NO = INTERSECT_CUBIC_LINE_3 + 1;
-// FIXME: add cubic/quad
-var INTERSECT_CUBIC = INTERSECT_CUBIC_LINE_NO + 1;
-var INTERSECT_CUBIC_2 = INTERSECT_CUBIC + 1;
-var INTERSECT_CUBIC_3 = INTERSECT_CUBIC_2 + 1;
-var INTERSECT_CUBIC_4 = INTERSECT_CUBIC_3 + 1;
-// FIXME: add cubic 5- 9
-var INTERSECT_CUBIC_NO = INTERSECT_CUBIC_4 + 1;
-
-var SORT_LINE = INTERSECT_CUBIC_NO + 1;
-var SORT_QUAD = SORT_LINE + 1;
-var SORT_CUBIC = SORT_QUAD + 1;
-
-var SORT_LINE_UNSORTABLE = SORT_CUBIC + 1;
-var SORT_QUAD_UNSORTABLE = SORT_LINE_UNSORTABLE + 1;
-var SORT_CUBIC_UNSORTABLE = SORT_QUAD_UNSORTABLE + 1;
-
-var SORT_LINE_COMPACT = SORT_CUBIC_UNSORTABLE + 1;
-var SORT_QUAD_COMPACT = SORT_LINE_COMPACT + 1;
-var SORT_CUBIC_COMPACT = SORT_QUAD_COMPACT + 1;
-
-var OP_DIFFERENCE = SORT_CUBIC_COMPACT + 1;
-var OP_INTERSECT = OP_DIFFERENCE + 1;
-var OP_UNION = OP_INTERSECT + 1;
-var OP_XOR = OP_UNION + 1;
-
-var MARK_LINE = OP_XOR + 1;
-var MARK_QUAD = MARK_LINE + 1;
-var MARK_CUBIC = MARK_QUAD + 1;
-var MARK_DONE_LINE = MARK_CUBIC + 1;
-var MARK_DONE_QUAD = MARK_DONE_LINE + 1;
-var MARK_DONE_CUBIC = MARK_DONE_QUAD + 1;
-var MARK_UNSORTABLE_LINE = MARK_DONE_CUBIC + 1;
-var MARK_UNSORTABLE_QUAD = MARK_UNSORTABLE_LINE + 1;
-var MARK_UNSORTABLE_CUBIC = MARK_UNSORTABLE_QUAD + 1;
-var MARK_SIMPLE_LINE = MARK_UNSORTABLE_CUBIC + 1;
-var MARK_SIMPLE_QUAD = MARK_SIMPLE_LINE + 1;
-var MARK_SIMPLE_CUBIC = MARK_SIMPLE_QUAD + 1;
-var MARK_SIMPLE_DONE_LINE = MARK_SIMPLE_CUBIC + 1;
-var MARK_SIMPLE_DONE_QUAD = MARK_SIMPLE_DONE_LINE + 1;
-var MARK_SIMPLE_DONE_CUBIC = MARK_SIMPLE_DONE_QUAD + 1;
-var MARK_DONE_UNARY_LINE = MARK_SIMPLE_DONE_CUBIC + 1;
-var MARK_DONE_UNARY_QUAD = MARK_DONE_UNARY_LINE + 1;
-var MARK_DONE_UNARY_CUBIC = MARK_DONE_UNARY_QUAD + 1;
-
-var COMPUTED_SET_1 = MARK_DONE_UNARY_CUBIC + 1;
-var COMPUTED_SET_2 = COMPUTED_SET_1 + 1;
-var FRAG_TYPE_LAST = COMPUTED_SET_2;
-
-var REC_TYPE_UNKNOWN = -1;
-var REC_TYPE_PATH = 0;
-var REC_TYPE_SECT = 1;
-var REC_TYPE_ACTIVE = 2;
-var REC_TYPE_ADD = 3;
-var REC_TYPE_SORT = 4;
-var REC_TYPE_OP = 5;
-var REC_TYPE_MARK = 6;
-var REC_TYPE_COMPUTED = 7;
-var REC_TYPE_COIN = 8;
-var REC_TYPE_LAST = REC_TYPE_COIN;
-
-function strs_to_nums(strs) {
- var result = [];
- for (var idx = 1; idx < strs.length; ++idx) {
- var str = strs[idx];
- var num = parseFloat(str);
- if (isNaN(num)) {
- result.push(str);
- } else {
- result.push(num);
- }
- }
- return result;
-}
-
-function filter_str_by(id, str, regex, array) {
- if (regex.test(str)) {
- var strs = regex.exec(str);
- var result = strs_to_nums(strs);
- array.push(id);
- array.push(result);
- return true;
- }
- return false;
-}
-
-function construct_regexp2(pattern) {
- var escape = pattern.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
- escape = escape.replace(/UNSORTABLE/g, "\\*\\*\\* UNSORTABLE \\*\\*\\*");
- escape = escape.replace(/CUBIC_VAL/g, "\\(P_VAL P_VAL P_VAL P_VAL\\)");
- escape = escape.replace(/QUAD_VAL/g, "\\(P_VAL P_VAL P_VAL\\)");
- escape = escape.replace(/LINE_VAL/g, "\\(P_VAL P_VAL\\)");
- escape = escape.replace(/PT_VAL/g, "\\(P_VAL\\)");
- escape = escape.replace(/P_VAL/g, "(-?\\d+\\.?\\d*(?:e-?\\d+)?),(-?\\d+\\.?\\d*(?:e-?\\d+)?)");
- escape = escape.replace(/T_VAL/g, "(-?\\d+\\.?\\d*(?:e-?\\d+)?)");
- escape = escape.replace(/IDX/g, "(\\d+)");
- escape = escape.replace(/NUM/g, "(-?\\d+)");
- escape = escape.replace(/OPT/g, "(\\?|-?\\d+)");
- return new RegExp(escape, 'i');
-}
-
-function construct_regexp2c(pattern) {
- var escape = pattern.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
- escape = escape.replace(/UNSORTABLE/g, "\\*\\*\\* UNSORTABLE \\*\\*\\*");
- escape = escape.replace(/CUBIC_VAL/g, "(?:\\$\\d = )?\\{\\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}\\}");
- escape = escape.replace(/QUAD_VAL/g, "(?:\\$\\d = )?\\{\\{P_VAL\\}, \\{P_VAL\\}, \\{P_VAL\\}\\}");
- escape = escape.replace(/LINE_VAL/g, "(?:\\$\\d = )?\\{\\{P_VAL\\}, \\{P_VAL\\}\\}");
- escape = escape.replace(/PT_VAL/g, "\\{\\{P_VAL\\}\\}");
- escape = escape.replace(/P_VAL/g, "(?:f?[xX] = )?(-?\\d+\\.?\\d*(?:e-?\\d+)?),(?: f?[yY] = )?(-?\\d+\\.?\\d*(?:e-?\\d+)?)");
- escape = escape.replace(/T_VAL/g, "(-?\\d+\\.?\\d*(?:e-?\\d+)?)");
- escape = escape.replace(/IDX/g, "(\\d+)");
- escape = escape.replace(/NUM/g, "(-?\\d+)");
- escape = escape.replace(/OPT/g, "(\\?|-?\\d+)");
- return new RegExp(escape, 'i');
-}
-
-function match_regexp(str, lineNo, array, id, pattern) {
- var regex = construct_regexp2(pattern);
- if (filter_str_by(id, str, regex, array)) {
- return true;
- }
- regex = construct_regexp2c(pattern);
- return filter_str_by(id, str, regex, array);
-}
-
-function parse_all(test) {
- var lines = test.match(/[^\r\n]+/g);
- var records = []; // a rec can be the original paths, a set of intersections, a set of active spans, a sort, or a path add
- var record = [];
- var recType = REC_TYPE_UNKNOWN;
- var lastLineNo;
- var moveX, moveY;
- for (var lineNo = 0; lineNo < lines.length; ++lineNo) {
- var line = lines[lineNo];
- if (line.length == 0) {
- continue;
- }
- var opStart = "SkOpSegment::";
- if (line.lastIndexOf(opStart, 0) === 0) {
- line = line.substr(opStart.length);
- }
- var type = line.lastIndexOf("debugShowSort", 0) === 0 ? REC_TYPE_SORT
- : line.lastIndexOf("debugShowActiveSpans", 0) === 0 ? REC_TYPE_ACTIVE
- : line.lastIndexOf("debugShowTs", 0) === 0 ? REC_TYPE_COIN
- : line.lastIndexOf("debugShow", 0) === 0 ? REC_TYPE_SECT
- : line.lastIndexOf("computed", 0) === 0 ? REC_TYPE_COMPUTED
- : line.lastIndexOf("path.", 0) === 0 ? REC_TYPE_ADD
- : line.lastIndexOf("mark", 0) === 0 ? REC_TYPE_MARK
- : line.lastIndexOf(" {{", 0) === 0 ? REC_TYPE_COMPUTED
- : line.lastIndexOf("{{", 0) === 0 ? REC_TYPE_PATH
- : line.lastIndexOf("op", 0) === 0 ? REC_TYPE_OP
- : line.lastIndexOf("$", 0) === 0 ? REC_TYPE_PATH
- : REC_TYPE_UNKNOWN;
- if (recType != type || recType == REC_TYPE_ADD || recType == REC_TYPE_SECT) {
- if (recType != REC_TYPE_UNKNOWN) {
- records.push(recType);
- records.push(lastLineNo);
- records.push(record);
- }
- record = [];
- recType = type;
- lastLineNo = lineNo;
- }
- var found = false;
- switch (recType) {
- case REC_TYPE_ACTIVE:
- found = match_regexp(line, lineNo, record, ACTIVE_LINE_SPAN, "debugShowActiveSpans" +
-" id=IDX LINE_VAL t=T_VAL PT_VAL tEnd=T_VAL other=IDX otherT=T_VAL otherIndex=IDX windSum=OPT windValue=IDX oppValue=IDX"
- ) || match_regexp(line, lineNo, record, ACTIVE_QUAD_SPAN, "debugShowActiveSpans" +
-" id=IDX QUAD_VAL t=T_VAL PT_VAL tEnd=T_VAL other=IDX otherT=T_VAL otherIndex=IDX windSum=OPT windValue=IDX oppValue=IDX"
- ) || match_regexp(line, lineNo, record, ACTIVE_CUBIC_SPAN, "debugShowActiveSpans" +
-" id=IDX CUBIC_VAL t=T_VAL PT_VAL tEnd=T_VAL other=IDX otherT=T_VAL otherIndex=IDX windSum=OPT windValue=IDX oppValue=IDX"
- );
- break;
- case REC_TYPE_ADD:
- if (match_regexp(line, lineNo, record, ADD_MOVETO, "path.moveTo(P_VAL);")) {
- moveX = record[1][0];
- moveY = record[1][1];
- found = true;
- } else if (match_regexp(line, lineNo, record, ADD_LINETO, "path.lineTo(P_VAL);")) {
- record[1].unshift(moveY);
- record[1].unshift(moveX);
- moveX = record[1][2];
- moveY = record[1][3];
- found = true;
- } else if (match_regexp(line, lineNo, record, ADD_QUADTO, "path.quadTo(P_VAL, P_VAL);")) {
- record[1].unshift(moveY);
- record[1].unshift(moveX);
- moveX = record[1][4];
- moveY = record[1][5];
- found = true;
- } else if (match_regexp(line, lineNo, record, ADD_CUBICTO, "path.cubicTo(P_VAL, P_VAL, P_VAL);")) {
- record[1].unshift(moveY);
- record[1].unshift(moveX);
- moveX = record[1][6];
- moveY = record[1][7];
- found = true;
- } else {
- found = match_regexp(line, lineNo, record, ADD_CLOSE, "path.close();");
- }
- break;
- case REC_TYPE_COIN:
- found = true;
- break;
- case REC_TYPE_COMPUTED:
- found = line == "computed quadratics given"
- || match_regexp(line, lineNo, record, COMPUTED_SET_1, "computed quadratics set 1"
- ) || match_regexp(line, lineNo, record, COMPUTED_SET_2, "computed quadratics set 2"
- ) || match_regexp(line, lineNo, record, PATH_QUAD, " QUAD_VAL,"
- ) || match_regexp(line, lineNo, record, PATH_CUBIC, " CUBIC_VAL,"
- );
- break;
- case REC_TYPE_PATH:
- found = match_regexp(line, lineNo, record, PATH_LINE, "LINE_VAL"
- ) || match_regexp(line, lineNo, record, PATH_QUAD, "QUAD_VAL"
- ) || match_regexp(line, lineNo, record, PATH_CUBIC, "CUBIC_VAL"
- );
- break;
- case REC_TYPE_SECT:
- found = match_regexp(line, lineNo, record, INTERSECT_LINE, "debugShowLineIntersection" +
-" wtTs[0]=T_VAL LINE_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL"
- ) || match_regexp(line, lineNo, record, INTERSECT_LINE_2, "debugShowLineIntersection" +
-" wtTs[0]=T_VAL LINE_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL"
- ) || match_regexp(line, lineNo, record, INTERSECT_LINE_NO, "debugShowLineIntersection" +
-" no intersect LINE_VAL LINE_VAL"
- ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_LINE, "debugShowQuadLineIntersection" +
-" wtTs[0]=T_VAL QUAD_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL"
- ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_LINE_2, "debugShowQuadLineIntersection" +
-" wtTs[0]=T_VAL QUAD_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL"
- ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_LINE_NO, "debugShowQuadLineIntersection" +
-" no intersect QUAD_VAL LINE_VAL"
- ) || match_regexp(line, lineNo, record, INTERSECT_QUAD, "debugShowQuadIntersection" +
-" wtTs[0]=T_VAL QUAD_VAL PT_VAL wnTs[0]=T_VAL QUAD_VAL"
- ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_2, "debugShowQuadIntersection" +
-" wtTs[0]=T_VAL QUAD_VAL PT_VAL wtTs[1]=T_VAL wnTs[0]=T_VAL QUAD_VAL wnTs[1]=T_VAL"
- ) || match_regexp(line, lineNo, record, INTERSECT_QUAD_NO, "debugShowQuadIntersection" +
-" no intersect QUAD_VAL QUAD_VAL"
- ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE, "debugShowCubicLineIntersection" +
-" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL"
- ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE_2, "debugShowCubicLineIntersection" +
-" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL"
- ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE_3, "debugShowCubicLineIntersection" +
-" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wtTs[2]=T_VAL PT_VAL wnTs[0]=T_VAL LINE_VAL wnTs[1]=T_VAL wnTs[2]=T_VAL"
- ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_LINE_NO, "debugShowCubicLineIntersection" +
-" no intersect CUBIC_VAL LINE_VAL"
- ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC, "debugShowCubicIntersection" +
-" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wnTs[0]=T_VAL CUBIC_VAL"
- ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_2, "debugShowCubicIntersection" +
-" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wnTs[0]=T_VAL CUBIC_VAL wnTs[1]=T_VAL"
- ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_3, "debugShowCubicIntersection" +
-" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wtTs[2]=T_VAL PT_VAL wnTs[0]=T_VAL CUBIC_VAL wnTs[1]=T_VAL wnTs[2]=T_VAL"
- ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_4, "debugShowCubicIntersection" +
-" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL PT_VAL wtTs[2]=T_VAL PT_VAL wtTs[3]=T_VAL PT_VAL wnTs[0]=T_VAL CUBIC_VAL wnTs[1]=T_VAL wnTs[2]=T_VAL wnTs[3]=T_VAL"
- ) || match_regexp(line, lineNo, record, INTERSECT_CUBIC_NO, "debugShowCubicIntersection" +
-" no intersect CUBIC_VAL CUBIC_VAL"
- ) || match_regexp(line, lineNo, record, INTERSECT_SELF_CUBIC, "debugShowCubicIntersection" +
-" wtTs[0]=T_VAL CUBIC_VAL PT_VAL wtTs[1]=T_VAL"
- ) || match_regexp(line, lineNo, record, INTERSECT_SELF_CUBIC_NO, "debugShowCubicIntersection" +
-" no self intersect CUBIC_VAL"
- );
- break;
- case REC_TYPE_SORT:
- found = match_regexp(line, lineNo, record, SORT_LINE, "debugShowSort" +
-" [IDX] LINE_VAL tStart=T_VAL tEnd=T_VAL sign=NUM windValue=IDX windSum=OPT OPT->OPT (max=OPT) done=IDX tiny=IDX opp=IDX"
- ) || match_regexp(line, lineNo, record, SORT_QUAD, "debugShowSort" +
-" [IDX] QUAD_VAL tStart=T_VAL tEnd=T_VAL sign=NUM windValue=IDX windSum=OPT OPT->OPT (max=OPT) done=IDX tiny=IDX opp=IDX"
- ) || match_regexp(line, lineNo, record, SORT_CUBIC, "debugShowSort" +
-" [IDX] CUBIC_VAL tStart=T_VAL tEnd=T_VAL sign=NUM windValue=IDX windSum=OPT OPT->OPT (max=OPT) done=IDX tiny=IDX opp=IDX"
- ) || match_regexp(line, lineNo, record, SORT_LINE_UNSORTABLE, "debugShowSort" +
-" [IDX] UNSORTABLE LINE_VAL tStart=T_VAL tEnd=T_VAL sign=NUM windValue=IDX windSum=OPT OPT->OPT (max=OPT) done=IDX tiny=IDX opp=IDX"
- ) || match_regexp(line, lineNo, record, SORT_QUAD_UNSORTABLE, "debugShowSort" +
-" [IDX] UNSORTABLE QUAD_VAL tStart=T_VAL tEnd=T_VAL sign=NUM windValue=IDX windSum=OPT OPT->OPT (max=OPT) done=IDX tiny=IDX opp=IDX"
- ) || match_regexp(line, lineNo, record, SORT_CUBIC_UNSORTABLE, "debugShowSort" +
-" [IDX] UNSORTABLE CUBIC_VAL tStart=T_VAL tEnd=T_VAL sign=NUM windValue=IDX windSum=OPT OPT->OPT (max=OPT) done=IDX tiny=IDX opp=IDX"
- ) || match_regexp(line, lineNo, record, SORT_LINE_COMPACT, "debugShowSort" +
-" [IDX] id=IDX line start=IDX PT_VAL end=IDX PT_VAL sign=NUM windValue=IDX windSum=OPT OPT->OPT (max=OPT) done=IDX tiny=IDX opp=IDX"
- ) || match_regexp(line, lineNo, record, SORT_QUAD_COMPACT, "debugShowSort" +
-" [IDX] id=IDX quad start=IDX PT_VAL end=IDX PT_VAL sign=NUM windValue=IDX windSum=OPT OPT->OPT (max=OPT) done=IDX tiny=IDX opp=IDX"
- ) || match_regexp(line, lineNo, record, SORT_CUBIC_COMPACT, "debugShowSort" +
-" [IDX] id=IDX cubic start=IDX PT_VAL end=IDX PT_VAL sign=NUM windValue=IDX windSum=OPT OPT->OPT (max=OPT) done=IDX tiny=IDX opp=IDX"
- );
- break;
- case REC_TYPE_MARK:
- found = match_regexp(line, lineNo, record, MARK_LINE, "markWinding" +
-" id=IDX LINE_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM newOppSum=NUM oppSum=OPT windSum=OPT windValue=IDX"
- ) || match_regexp(line, lineNo, record, MARK_QUAD, "markWinding" +
-" id=IDX QUAD_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM newOppSum=NUM oppSum=OPT windSum=OPT windValue=IDX"
- ) || match_regexp(line, lineNo, record, MARK_CUBIC, "markWinding" +
-" id=IDX CUBIC_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM newOppSum=NUM oppSum=OPT windSum=OPT windValue=IDX"
- ) || match_regexp(line, lineNo, record, MARK_DONE_LINE, "markDoneBinary" +
-" id=IDX LINE_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM newOppSum=NUM oppSum=OPT windSum=OPT windValue=IDX"
- ) || match_regexp(line, lineNo, record, MARK_DONE_QUAD, "markDoneBinary" +
-" id=IDX QUAD_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM newOppSum=NUM oppSum=OPT windSum=OPT windValue=IDX"
- ) || match_regexp(line, lineNo, record, MARK_DONE_CUBIC, "markDoneBinary" +
-" id=IDX CUBIC_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM newOppSum=NUM oppSum=OPT windSum=OPT windValue=IDX"
- ) || match_regexp(line, lineNo, record, MARK_UNSORTABLE_LINE, "markUnsortable" +
-" id=IDX LINE_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
- ) || match_regexp(line, lineNo, record, MARK_UNSORTABLE_QUAD, "markUnsortable" +
-" id=IDX QUAD_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
- ) || match_regexp(line, lineNo, record, MARK_UNSORTABLE_CUBIC, "markUnsortable" +
-" id=IDX CUBIC_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
- ) || match_regexp(line, lineNo, record, MARK_SIMPLE_LINE, "markWinding" +
-" id=IDX LINE_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
- ) || match_regexp(line, lineNo, record, MARK_SIMPLE_QUAD, "markWinding" +
-" id=IDX QUAD_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
- ) || match_regexp(line, lineNo, record, MARK_SIMPLE_CUBIC, "markWinding" +
-" id=IDX CUBIC_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
- ) || match_regexp(line, lineNo, record, MARK_SIMPLE_DONE_LINE, "markDone" +
-" id=IDX LINE_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
- ) || match_regexp(line, lineNo, record, MARK_SIMPLE_DONE_QUAD, "markDone" +
-" id=IDX QUAD_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
- ) || match_regexp(line, lineNo, record, MARK_SIMPLE_DONE_CUBIC, "markDone" +
-" id=IDX CUBIC_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
- ) || match_regexp(line, lineNo, record, MARK_DONE_UNARY_LINE, "markDoneUnary" +
-" id=IDX LINE_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
- ) || match_regexp(line, lineNo, record, MARK_DONE_UNARY_QUAD, "markDoneUnary" +
-" id=IDX QUAD_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
- ) || match_regexp(line, lineNo, record, MARK_DONE_UNARY_CUBIC, "markDoneUnary" +
-" id=IDX CUBIC_VAL t=T_VAL [IDX] PT_VAL tEnd=T_VAL newWindSum=NUM windSum=OPT windValue=IDX"
- );
- break;
- case REC_TYPE_OP:
- found = match_regexp(line, lineNo, record, OP_DIFFERENCE, "op difference"
- ) || match_regexp(line, lineNo, record, OP_INTERSECT, "op intersect"
- ) || match_regexp(line, lineNo, record, OP_UNION, "op union"
- ) || match_regexp(line, lineNo, record, OP_XOR, "op xor"
- );
- break;
- case REC_TYPE_UNKNOWN:
- found = true;
- break;
- }
- if (!found) {
- console.log(line + " [" + lineNo + "] of type " + type + " not found");
- }
- }
- if (recType != REC_TYPE_UNKNOWN) {
- records.push(recType);
- records.push(lastLineNo);
- records.push(record);
- }
- if (records.length >= 1) {
- tests[testIndex] = records;
- testLines[testIndex] = lines;
- }
-}
-
-function init(test) {
- var canvas = document.getElementById('canvas');
- if (!canvas.getContext) return;
- screenWidth = canvas.width = window.innerWidth - 20;
- screenHeight = canvas.height = window.innerHeight - 20;
- ctx = canvas.getContext('2d');
- xmin = Infinity;
- xmax = -Infinity;
- ymin = Infinity;
- ymax = -Infinity;
- hasPath = hasComputedPath = false;
- for (var testIndex = 0; testIndex < test.length; testIndex += 3) {
- var recType = test[testIndex];
- if (!typeof recType == 'number' || recType < REC_TYPE_UNKNOWN || recType > REC_TYPE_LAST) {
- console.log("unknown rec type: " + recType);
- throw "stop execution";
- }
- var records = test[testIndex + 2];
- for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
- var fragType = records[recordIndex];
- if (!typeof fragType == 'number' || fragType < 1 || fragType > FRAG_TYPE_LAST) {
- console.log("unknown in range frag type: " + fragType);
- throw "stop execution";
- }
- var frags = records[recordIndex + 1];
- var first = 0;
- var last = -1;
- var first2 = 0;
- var last2 = 0;
- switch (recType) {
- case REC_TYPE_COMPUTED:
- if (fragType == COMPUTED_SET_1 || fragType == COMPUTED_SET_2) {
- break;
- }
- hasComputedPath = true;
- case REC_TYPE_PATH:
- switch (fragType) {
- case PATH_LINE:
- last = 4;
- break;
- case PATH_QUAD:
- last = 6;
- break;
- case PATH_CUBIC:
- last = 8;
- break;
- default:
- console.log("unknown " + (recType == REC_TYPE_PATH ? "REC_TYPE_PATH"
- : "REC_TYPE_COMPUTED") + " frag type:" + fragType);
- throw "stop execution";
- }
- if (recType == REC_TYPE_PATH) {
- hasPath = true;
- }
- break;
- case REC_TYPE_ACTIVE:
- first = 1;
- switch (fragType) {
- case ACTIVE_LINE_SPAN:
- last = 5;
- break;
- case ACTIVE_QUAD_SPAN:
- last = 7;
- break;
- case ACTIVE_CUBIC_SPAN:
- last = 9;
- break;
- default:
- console.log("unknown REC_TYPE_ACTIVE frag type: " + fragType);
- throw "stop execution";
- }
- break;
- case REC_TYPE_ADD:
- switch (fragType) {
- case ADD_MOVETO:
- break;
- case ADD_LINETO:
- last = 4;
- break;
- case ADD_QUADTO:
- last = 6;
- break;
- case ADD_CUBICTO:
- last = 8;
- break;
- case ADD_CLOSE:
- break;
- default:
- console.log("unknown REC_TYPE_ADD frag type: " + fragType);
- throw "stop execution";
- }
- break;
- case REC_TYPE_SECT:
- switch (fragType) {
- case INTERSECT_LINE:
- first = 1; last = 5; first2 = 8; last2 = 12;
- break;
- case INTERSECT_LINE_2:
- first = 1; last = 5; first2 = 11; last2 = 15;
- break;
- case INTERSECT_LINE_NO:
- first = 0; last = 4; first2 = 4; last2 = 8;
- break;
- case INTERSECT_QUAD_LINE:
- first = 1; last = 7; first2 = 10; last2 = 14;
- break;
- case INTERSECT_QUAD_LINE_2:
- first = 1; last = 7; first2 = 13; last2 = 17;
- break;
- case INTERSECT_QUAD_LINE_NO:
- first = 0; last = 6; first2 = 6; last2 = 10;
- break;
- case INTERSECT_QUAD:
- first = 1; last = 7; first2 = 10; last2 = 16;
- break;
- case INTERSECT_QUAD_2:
- first = 1; last = 7; first2 = 13; last2 = 19;
- break;
- case INTERSECT_QUAD_NO:
- first = 0; last = 6; first2 = 6; last2 = 12;
- break;
- case INTERSECT_SELF_CUBIC:
- first = 1; last = 9;
- break;
- case INTERSECT_SELF_CUBIC_NO:
- first = 0; last = 8;
- break;
- case INTERSECT_CUBIC_LINE:
- first = 1; last = 9; first2 = 12; last2 = 16;
- break;
- case INTERSECT_CUBIC_LINE_2:
- first = 1; last = 9; first2 = 15; last2 = 19;
- break;
- case INTERSECT_CUBIC_LINE_3:
- first = 1; last = 9; first2 = 18; last2 = 22;
- break;
- case INTERSECT_CUBIC_LINE_NO:
- first = 0; last = 8; first2 = 8; last2 = 12;
- break;
- case INTERSECT_CUBIC:
- first = 1; last = 9; first2 = 12; last2 = 20;
- break;
- case INTERSECT_CUBIC_2:
- first = 1; last = 9; first2 = 15; last2 = 23;
- break;
- case INTERSECT_CUBIC_3:
- first = 1; last = 9; first2 = 18; last2 = 26;
- break;
- case INTERSECT_CUBIC_4:
- first = 1; last = 9; first2 = 21; last2 = 29;
- break;
- case INTERSECT_CUBIC_NO:
- first = 0; last = 8; first2 = 8; last2 = 16;
- break;
- default:
- console.log("unknown REC_TYPE_SECT frag type: " + fragType);
- throw "stop execution";
- }
- break;
- default:
- continue;
- }
- for (var idx = first; idx < last; idx += 2) {
- xmin = Math.min(xmin, frags[idx]);
- xmax = Math.max(xmax, frags[idx]);
- ymin = Math.min(ymin, frags[idx + 1]);
- ymax = Math.max(ymax, frags[idx + 1]);
- }
- for (var idx = first2; idx < last2; idx += 2) {
- xmin = Math.min(xmin, frags[idx]);
- xmax = Math.max(xmax, frags[idx]);
- ymin = Math.min(ymin, frags[idx + 1]);
- ymax = Math.max(ymax, frags[idx + 1]);
- }
- }
- }
- setScale();
- if (hasPath == false && hasComputedPath == true && !draw_computed) {
- draw_computed = 3; // show both quadratics and cubics
- }
- if (hasPath == true && hasComputedPath == false && draw_computed) {
- draw_computed = 0;
- }
-}
-
-function setScale() {
- var srcWidth = xmax - xmin;
- var srcHeight = ymax - ymin;
- var hscale = ctx.canvas.width / srcWidth;
- var vscale = ctx.canvas.height / srcHeight;
- scale = Math.min(hscale, vscale);
- var invScale = 1 / scale;
- var sxmin = xmin - invScale * 5;
- var symin = ymin - invScale * 10;
- var sxmax = xmax + invScale * (6 * decimal_places + 10);
- var symax = ymax + invScale * 10;
- srcWidth = sxmax - sxmin;
- srcHeight = symax - symin;
- hscale = ctx.canvas.width / srcWidth;
- vscale = ctx.canvas.height / srcHeight;
- scale = Math.min(hscale, vscale);
- srcLeft = sxmin;
- srcTop = symin;
-}
-
-function drawPoint(px, py, end) {
- for (var pts = 0; pts < drawnPts.length; pts += 2) {
- var x = drawnPts[pts];
- var y = drawnPts[pts + 1];
- if (px == x && py == y) {
- return;
- }
- }
- drawnPts.push(px);
- drawnPts.push(py);
- var label = px.toFixed(decimal_places) + ", " + py.toFixed(decimal_places);
- var _px = (px - srcLeft) * scale;
- var _py = (py - srcTop) * scale;
- ctx.beginPath();
- ctx.arc(_px, _py, 3, 0, Math.PI*2, true);
- ctx.closePath();
- if (end) {
- ctx.fill();
- } else {
- ctx.stroke();
- }
- ctx.textAlign = "left";
- ctx.fillText(label, _px + 5, _py);
-}
-
-function drawPoints(ptArray, curveType, drawControls) {
- var count = (curveType - PATH_LINE + 2) * 2;
- for (var idx = 0; idx < count; idx += 2) {
- if (!drawControls && idx != 0 && idx != count - 2) {
- continue;
- }
- drawPoint(ptArray[idx], ptArray[idx + 1], idx == 0 || idx == count - 2);
- }
-}
-
-function drawControlLines(curve, curveType, drawEnd) {
- if (curveType == PATH_LINE) {
- return;
- }
- ctx.strokeStyle = "rgba(0,0,0, 0.3)";
- drawLine(curve[0], curve[1], curve[2], curve[3]);
- drawLine(curve[2], curve[3], curve[4], curve[5]);
- if (curveType == PATH_CUBIC) {
- drawLine(curve[4], curve[5], curve[6], curve[7]);
- if (drawEnd > 1) {
- drawLine(curve[6], curve[7], curve[0], curve[1]);
- if (drawEnd > 2) {
- drawLine(curve[0], curve[1], curve[4], curve[5]);
- drawLine(curve[6], curve[7], curve[2], curve[3]);
- }
- }
- } else if (drawEnd > 1) {
- drawLine(curve[4], curve[5], curve[0], curve[1]);
- }
-}
-
-function pointAtT(curve, curveType, t) {
- var xy = {};
- switch (curveType) {
- case PATH_LINE:
- var a = 1 - t;
- var b = t;
- xy.x = a * curve[0] + b * curve[2];
- xy.y = a * curve[1] + b * curve[3];
- break;
- case PATH_QUAD:
- var one_t = 1 - t;
- var a = one_t * one_t;
- var b = 2 * one_t * t;
- var c = t * t;
- xy.x = a * curve[0] + b * curve[2] + c * curve[4];
- xy.y = a * curve[1] + b * curve[3] + c * curve[5];
- break;
- case PATH_CUBIC:
- var one_t = 1 - t;
- var one_t2 = one_t * one_t;
- var a = one_t2 * one_t;
- var b = 3 * one_t2 * t;
- var t2 = t * t;
- var c = 3 * one_t * t2;
- var d = t2 * t;
- xy.x = a * curve[0] + b * curve[2] + c * curve[4] + d * curve[6];
- xy.y = a * curve[1] + b * curve[3] + c * curve[5] + d * curve[7];
- break;
- }
- return xy;
-}
-
-function drawPointAtT(curve, curveType) {
- var x, y;
- var xy = pointAtT(curve, curveType, curveT);
- drawPoint(xy.x, xy.y, true);
- if (!draw_intersectT) {
- return;
- }
- ctx.fillStyle = "red";
- drawTAtPointUp(xy.x, xy.y, curveT);
-}
-
-function drawTAtPointUp(px, py, t) {
- var label = t.toFixed(decimal_places);
- var _px = (px - srcLeft)* scale;
- var _py = (py - srcTop) * scale;
- ctx.fillText(label, _px + 5, _py - 10);
-}
-
-function drawTAtPointDown(px, py, t) {
- var label = t.toFixed(decimal_places);
- var _px = (px - srcLeft)* scale;
- var _py = (py - srcTop) * scale;
- ctx.fillText(label, _px + 5, _py + 10);
-}
-
-function alreadyDrawnLine(x1, y1, x2, y2) {
- for (var pts = 0; pts < drawnLines.length; pts += 4) {
- if (x1 == drawnLines[pts] && y1 == drawnLines[pts + 1]
- && x2 == drawnLines[pts + 2] && y2 == drawnLines[pts + 3]) {
- return true;
- }
- }
- drawnLines.push(x1);
- drawnLines.push(y1);
- drawnLines.push(x2);
- drawnLines.push(y2);
- return false;
-}
-
-function drawLine(x1, y1, x2, y2) {
- if (alreadyDrawnLine(x1, y1, x2, y2)) {
- return;
- }
- ctx.beginPath();
- ctx.moveTo((x1 - srcLeft) * scale,
- (y1 - srcTop) * scale);
- ctx.lineTo((x2 - srcLeft) * scale,
- (y2 - srcTop) * scale);
- ctx.stroke();
-}
-
-function linePartial(x1, y1, x2, y2, t1, t2) {
- var dx = x1 - x2;
- var dy = y1 - y2;
- var array = [
- x1 - t1 * dx,
- y1 - t1 * dy,
- x1 - t2 * dx,
- y1 - t2 * dy
- ];
- return array;
-}
-
-function drawLinePartial(x1, y1, x2, y2, t1, t2) {
- var a = linePartial(x1, y1, x2, y2, t1, t2);
- var ax = a[0];
- var ay = a[1];
- var bx = a[2];
- var by = a[3];
- if (alreadyDrawnLine(ax, ay, bx, by)) {
- return;
- }
- ctx.beginPath();
- ctx.moveTo((ax - srcLeft) * scale,
- (ay - srcTop) * scale);
- ctx.lineTo((bx - srcLeft) * scale,
- (by - srcTop) * scale);
- ctx.stroke();
-}
-
-function alreadyDrawnQuad(x1, y1, x2, y2, x3, y3) {
- for (var pts = 0; pts < drawnQuads.length; pts += 6) {
- if (x1 == drawnQuads[pts] && y1 == drawnQuads[pts + 1]
- && x2 == drawnQuads[pts + 2] && y2 == drawnQuads[pts + 3]
- && x3 == drawnQuads[pts + 4] && x3 == drawnQuads[pts + 5]) {
- return true;
- }
- }
- drawnQuads.push(x1);
- drawnQuads.push(y1);
- drawnQuads.push(x2);
- drawnQuads.push(y2);
- drawnQuads.push(x3);
- drawnQuads.push(y3);
- return false;
-}
-
-function drawQuad(x1, y1, x2, y2, x3, y3) {
- if (alreadyDrawnQuad(x1, y1, x2, y2, x3, y3)) {
- return;
- }
- ctx.beginPath();
- ctx.moveTo((x1 - srcLeft) * scale,
- (y1 - srcTop) * scale);
- ctx.quadraticCurveTo((x2 - srcLeft) * scale,
- (y2 - srcTop) * scale,
- (x3 - srcLeft) * scale,
- (y3 - srcTop) * scale);
- ctx.stroke();
-}
-
-function interp(A, B, t) {
- return A + (B - A) * t;
-}
-
-function interp_quad_coords(x1, x2, x3, t)
-{
- var ab = interp(x1, x2, t);
- var bc = interp(x2, x3, t);
- var abc = interp(ab, bc, t);
- return abc;
-}
-
-function quadPartial(x1, y1, x2, y2, x3, y3, t1, t2) {
- var ax = interp_quad_coords(x1, x2, x3, t1);
- var ay = interp_quad_coords(y1, y2, y3, t1);
- var dx = interp_quad_coords(x1, x2, x3, (t1 + t2) / 2);
- var dy = interp_quad_coords(y1, y2, y3, (t1 + t2) / 2);
- var cx = interp_quad_coords(x1, x2, x3, t2);
- var cy = interp_quad_coords(y1, y2, y3, t2);
- var bx = 2*dx - (ax + cx)/2;
- var by = 2*dy - (ay + cy)/2;
- var array = [
- ax, ay, bx, by, cx, cy
- ];
- return array;
-}
-
-function drawQuadPartial(x1, y1, x2, y2, x3, y3, t1, t2) {
- var a = quadPartial(x1, y1, x2, y2, x3, y3, t1, t2);
- var ax = a[0];
- var ay = a[1];
- var bx = a[2];
- var by = a[3];
- var cx = a[4];
- var cy = a[5];
- if (alreadyDrawnQuad(ax, ay, bx, by, cx, cy)) {
- return;
- }
- ctx.beginPath();
- ctx.moveTo((ax - srcLeft) * scale,
- (ay - srcTop) * scale);
- ctx.quadraticCurveTo((bx - srcLeft) * scale,
- (by - srcTop) * scale,
- (cx - srcLeft) * scale,
- (cy - srcTop) * scale);
- ctx.stroke();
-}
-
-function alreadyDrawnCubic(x1, y1, x2, y2, x3, y3, x4, y4) {
- for (var pts = 0; pts < drawnCubics.length; pts += 8) {
- if (x1 == drawnCubics[pts] && y1 == drawnCubics[pts + 1]
- && x2 == drawnCubics[pts + 2] && y2 == drawnCubics[pts + 3]
- && x3 == drawnCubics[pts + 4] && y3 == drawnCubics[pts + 5]
- && x4 == drawnCubics[pts + 6] && y4 == drawnCubics[pts + 7]) {
- return true;
- }
- }
- drawnCubics.push(x1);
- drawnCubics.push(y1);
- drawnCubics.push(x2);
- drawnCubics.push(y2);
- drawnCubics.push(x3);
- drawnCubics.push(y3);
- drawnCubics.push(x4);
- drawnCubics.push(y4);
- return false;
-}
-
-function drawCubic(x1, y1, x2, y2, x3, y3, x4, y4) {
- if (alreadyDrawnCubic(x1, y1, x2, y2, x3, y3, x4, y4)) {
- return;
- }
- ctx.beginPath();
- ctx.moveTo((x1 - srcLeft) * scale,
- (y1 - srcTop) * scale);
- ctx.bezierCurveTo((x2 - srcLeft) * scale,
- (y2 - srcTop) * scale,
- (x3 - srcLeft) * scale,
- (y3 - srcTop) * scale,
- (x4 - srcLeft) * scale,
- (y4 - srcTop) * scale);
- ctx.stroke();
-}
-
-function interp_cubic_coords(x1, x2, x3, x4, t)
-{
- var ab = interp(x1, x2, t);
- var bc = interp(x2, x3, t);
- var cd = interp(x3, x4, t);
- var abc = interp(ab, bc, t);
- var bcd = interp(bc, cd, t);
- var abcd = interp(abc, bcd, t);
- return abcd;
-}
-
-function cubicPartial(x1, y1, x2, y2, x3, y3, x4, y4, t1, t2) {
- var ax = interp_cubic_coords(x1, x2, x3, x4, t1);
- var ay = interp_cubic_coords(y1, y2, y3, y4, t1);
- var ex = interp_cubic_coords(x1, x2, x3, x4, (t1*2+t2)/3);
- var ey = interp_cubic_coords(y1, y2, y3, y4, (t1*2+t2)/3);
- var fx = interp_cubic_coords(x1, x2, x3, x4, (t1+t2*2)/3);
- var fy = interp_cubic_coords(y1, y2, y3, y4, (t1+t2*2)/3);
- var dx = interp_cubic_coords(x1, x2, x3, x4, t2);
- var dy = interp_cubic_coords(y1, y2, y3, y4, t2);
- var mx = ex * 27 - ax * 8 - dx;
- var my = ey * 27 - ay * 8 - dy;
- var nx = fx * 27 - ax - dx * 8;
- var ny = fy * 27 - ay - dy * 8;
- var bx = (mx * 2 - nx) / 18;
- var by = (my * 2 - ny) / 18;
- var cx = (nx * 2 - mx) / 18;
- var cy = (ny * 2 - my) / 18;
- var array = [
- ax, ay, bx, by, cx, cy, dx, dy
- ];
- return array;
-}
-
-function drawCubicPartial(x1, y1, x2, y2, x3, y3, x4, y4, t1, t2) {
- var a = cubicPartial(x1, y1, x2, y2, x3, y3, x4, y4, t1, t2);
- var ax = a[0];
- var ay = a[1];
- var bx = a[2];
- var by = a[3];
- var cx = a[4];
- var cy = a[5];
- var dx = a[6];
- var dy = a[7];
- if (alreadyDrawnCubic(ax, ay, bx, by, cx, cy, dx, dy)) {
- return;
- }
- ctx.beginPath();
- ctx.moveTo((ax - srcLeft) * scale,
- (ay - srcTop) * scale);
- ctx.bezierCurveTo((bx - srcLeft) * scale,
- (by - srcTop) * scale,
- (cx - srcLeft) * scale,
- (cy - srcTop) * scale,
- (dx - srcLeft) * scale,
- (dy - srcTop) * scale);
- ctx.stroke();
-}
-
-function boundsWidth(pts) {
- var min = pts[0];
- var max = pts[0];
- for (var idx = 2; idx < pts.length; idx += 2) {
- min = Math.min(min, pts[idx]);
- max = Math.max(max, pts[idx]);
- }
- return max - min;
-}
-
-function boundsHeight(pts) {
- var min = pts[1];
- var max = pts[1];
- for (var idx = 3; idx < pts.length; idx += 2) {
- min = Math.min(min, pts[idx]);
- max = Math.max(max, pts[idx]);
- }
- return max - min;
-}
-
-function tangent(pts) {
- var dx = pts[2] - pts[0];
- var dy = pts[3] - pts[1];
- if (dx == 0 && dy == 0 && pts.length > 4) {
- dx = pts[4] - pts[0];
- dy = pts[5] - pts[1];
- if (dx == 0 && dy == 0 && pts.length > 6) {
- dx = pts[6] - pts[0];
- dy = pts[7] - pts[1];
- }
- }
- return Math.atan2(-dy, dx);
-}
-
-function hodograph(cubic) {
- var hodo = [];
- hodo[0] = 3 * (cubic[2] - cubic[0]);
- hodo[1] = 3 * (cubic[3] - cubic[1]);
- hodo[2] = 3 * (cubic[4] - cubic[2]);
- hodo[3] = 3 * (cubic[5] - cubic[3]);
- hodo[4] = 3 * (cubic[6] - cubic[4]);
- hodo[5] = 3 * (cubic[7] - cubic[5]);
- return hodo;
-}
-
-function hodograph2(cubic) {
- var quad = hodograph(cubic);
- var hodo = [];
- hodo[0] = 2 * (quad[2] - quad[0]);
- hodo[1] = 2 * (quad[3] - quad[1]);
- hodo[2] = 2 * (quad[4] - quad[2]);
- hodo[3] = 2 * (quad[5] - quad[3]);
- return hodo;
-}
-
-function quadraticRootsReal(A, B, C, s) {
- if (A == 0) {
- if (B == 0) {
- s[0] = 0;
- return C == 0;
- }
- s[0] = -C / B;
- return 1;
- }
- /* normal form: x^2 + px + q = 0 */
- var p = B / (2 * A);
- var q = C / A;
- var p2 = p * p;
- if (p2 < q) {
- return 0;
- }
- var sqrt_D = 0;
- if (p2 > q) {
- sqrt_D = sqrt(p2 - q);
- }
- s[0] = sqrt_D - p;
- s[1] = -sqrt_D - p;
- return 1 + s[0] != s[1];
-}
-
-function add_valid_ts(s, realRoots, t) {
- var foundRoots = 0;
- for (var index = 0; index < realRoots; ++index) {
- var tValue = s[index];
- if (tValue >= 0 && tValue <= 1) {
- for (var idx2 = 0; idx2 < foundRoots; ++idx2) {
- if (t[idx2] != tValue) {
- t[foundRoots++] = tValue;
- }
- }
- }
- }
- return foundRoots;
-}
-
-function quadraticRootsValidT(a, b, c, t) {
- var s = [];
- var realRoots = quadraticRootsReal(A, B, C, s);
- var foundRoots = add_valid_ts(s, realRoots, t);
- return foundRoots != 0;
-}
-
-function find_cubic_inflections(cubic, tValues) {
- var Ax = src[2] - src[0];
- var Ay = src[3] - src[1];
- var Bx = src[4] - 2 * src[2] + src[0];
- var By = src[5] - 2 * src[3] + src[1];
- var Cx = src[6] + 3 * (src[2] - src[4]) - src[0];
- var Cy = src[7] + 3 * (src[3] - src[5]) - src[1];
- return quadraticRootsValidT(Bx * Cy - By * Cx, (Ax * Cy - Ay * Cx),
- Ax * By - Ay * Bx, tValues);
-}
-
-function dxy_at_t(curve, type, t) {
- var dxy = {};
- if (type == PATH_QUAD) {
- var a = t - 1;
- var b = 1 - 2 * t;
- var c = t;
- dxy.x = a * curve[0] + b * curve[2] + c * curve[4];
- dxy.y = a * curve[1] + b * curve[3] + c * curve[5];
- } else if (type == PATH_CUBIC) {
- var one_t = 1 - t;
- var a = curve[0];
- var b = curve[2];
- var c = curve[4];
- var d = curve[6];
- dxy.x = 3 * ((b - a) * one_t * one_t + 2 * (c - b) * t * one_t + (d - c) * t * t);
- a = curve[1];
- b = curve[3];
- c = curve[5];
- d = curve[7];
- dxy.y = 3 * ((b - a) * one_t * one_t + 2 * (c - b) * t * one_t + (d - c) * t * t);
- }
- return dxy;
-}
-
-function drawLabel(num, px, py) {
- ctx.beginPath();
- ctx.arc(px, py, 8, 0, Math.PI*2, true);
- ctx.closePath();
- ctx.strokeStyle = "rgba(0,0,0, 0.4)";
- ctx.lineWidth = num == 0 || num == 3 ? 2 : 1;
- ctx.stroke();
- ctx.fillStyle = "black";
- ctx.font = "normal 10px Arial";
- // ctx.rotate(0.001);
- ctx.fillText(num, px - 2, py + 3);
- // ctx.rotate(-0.001);
-}
-
-function drawLabelX(ymin, num, loc) {
- var px = (loc - srcLeft) * scale;
- var py = (ymin - srcTop) * scale - 20;
- drawLabel(num, px, py);
-}
-
-function drawLabelY(xmin, num, loc) {
- var px = (xmin - srcLeft) * scale - 20;
- var py = (loc - srcTop) * scale;
- drawLabel(num, px, py);
-}
-
-function drawHodoOrigin(hx, hy, hMinX, hMinY, hMaxX, hMaxY) {
- ctx.beginPath();
- ctx.moveTo(hx, hy - 100);
- ctx.lineTo(hx, hy);
- ctx.strokeStyle = hMinY < 0 ? "green" : "blue";
- ctx.stroke();
- ctx.beginPath();
- ctx.moveTo(hx, hy);
- ctx.lineTo(hx, hy + 100);
- ctx.strokeStyle = hMaxY > 0 ? "green" : "blue";
- ctx.stroke();
- ctx.beginPath();
- ctx.moveTo(hx - 100, hy);
- ctx.lineTo(hx, hy);
- ctx.strokeStyle = hMinX < 0 ? "green" : "blue";
- ctx.stroke();
- ctx.beginPath();
- ctx.moveTo(hx, hy);
- ctx.lineTo(hx + 100, hy);
- ctx.strokeStyle = hMaxX > 0 ? "green" : "blue";
- ctx.stroke();
-}
-
-function scalexy(x, y, mag) {
- var length = Math.sqrt(x * x + y * y);
- return mag / length;
-}
-
-function drawArrow(x, y, dx, dy) {
- var dscale = scalexy(dx, dy, 1 / scale * 100);
- dx *= dscale;
- dy *= dscale;
- ctx.beginPath();
- ctx.moveTo((x - srcLeft) * scale, (y - srcTop) * scale);
- x += dx;
- y += dy;
- ctx.lineTo((x - srcLeft) * scale, (y - srcTop) * scale);
- dx /= 10;
- dy /= 10;
- ctx.lineTo((x - dy - srcLeft) * scale, (y + dx - srcTop) * scale);
- ctx.lineTo((x + dx * 2 - srcLeft) * scale, (y + dy * 2 - srcTop) * scale);
- ctx.lineTo((x + dy - srcLeft) * scale, (y - dx - srcTop) * scale);
- ctx.lineTo((x - srcLeft) * scale, (y - srcTop) * scale);
- ctx.strokeStyle = "rgba(0,75,0, 0.4)";
- ctx.stroke();
-}
-
-function drawCurveSpecials(curve, type) {
- if (pt_labels) {
- drawPoints(curve, type, pt_labels == 2);
- }
- if (control_lines != 0) {
- drawControlLines(curve, type, control_lines);
- }
- if (curve_t) {
- drawPointAtT(curve, type);
- }
- if (draw_midpoint) {
- var mid = pointAtT(curve, type, 0.5);
- drawPoint(mid.x, mid.y, true);
- }
- if (type == PATH_LINE) {
- return;
- }
- if (draw_deriviatives > 0) {
- var d = dxy_at_t(curve, type, 0);
- drawArrow(curve[0], curve[1], d.x, d.y);
- if (draw_deriviatives == 2) {
- d = dxy_at_t(curve, type, 1);
- if (type == PATH_CUBIC) {
- drawArrow(curve[6], curve[7], d.x, d.y);
- } else {
- drawArrow(curve[4], curve[5], d.x, d.y);
- }
- }
- if (draw_midpoint) {
- var mid = pointAtT(curve, 0.5);
- d = dxy_at_t(curve, type, 0.5);
- drawArrow(mid.x, mid.y, d.x, d.y);
- }
- }
- if (type != PATH_CUBIC) {
- return;
- }
- if (draw_hodo == 1 || draw_hodo == 2) {
- var hodo = hodograph(curve);
- var hMinX = Math.min(0, hodo[0], hodo[2], hodo[4]);
- var hMinY = Math.min(0, hodo[1], hodo[3], hodo[5]);
- var hMaxX = Math.max(0, hodo[0], hodo[2], hodo[4]);
- var hMaxY = Math.max(0, hodo[1], hodo[3], hodo[5]);
- var hScaleX = hMaxX - hMinX > 0 ? ctx.canvas.width / (hMaxX - hMinX) : 1;
- var hScaleY = hMaxY - hMinY > 0 ? ctx.canvas.height / (hMaxY - hMinY) : 1;
- var hUnit = Math.min(hScaleX, hScaleY);
- hUnit /= 2;
- var hx = xoffset - hMinX * hUnit;
- var hy = yoffset - hMinY * hUnit;
- ctx.moveTo(hx + hodo[0] * hUnit, hy + hodo[1] * hUnit);
- ctx.quadraticCurveTo(
- hx + hodo[2] * hUnit, hy + hodo[3] * hUnit,
- hx + hodo[4] * hUnit, hy + hodo[5] * hUnit);
- ctx.strokeStyle = "red";
- ctx.stroke();
- if (draw_hodo == 1) {
- drawHodoOrigin(hx, hy, hMinX, hMinY, hMaxX, hMaxY);
- }
- }
- if (draw_hodo == 3) {
- var hodo = hodograph2(curve);
- var hMinX = Math.min(0, hodo[0], hodo[2]);
- var hMinY = Math.min(0, hodo[1], hodo[3]);
- var hMaxX = Math.max(0, hodo[0], hodo[2]);
- var hMaxY = Math.max(0, hodo[1], hodo[3]);
- var hScaleX = hMaxX - hMinX > 0 ? ctx.canvas.width / (hMaxX - hMinX) : 1;
- var hScaleY = hMaxY - hMinY > 0 ? ctx.canvas.height / (hMaxY - hMinY) : 1;
- var hUnit = Math.min(hScaleX, hScaleY);
- hUnit /= 2;
- var hx = xoffset - hMinX * hUnit;
- var hy = yoffset - hMinY * hUnit;
- ctx.moveTo(hx + hodo[0] * hUnit, hy + hodo[1] * hUnit);
- ctx.lineTo(hx + hodo[2] * hUnit, hy + hodo[3] * hUnit);
- ctx.strokeStyle = "red";
- ctx.stroke();
- drawHodoOrigin(hx, hy, hMinX, hMinY, hMaxX, hMaxY);
- }
- if (draw_sequence) {
- var ymin = Math.min(curve[1], curve[3], curve[5], curve[7]);
- for (var i = 0; i < 8; i+= 2) {
- drawLabelX(ymin, i >> 1, curve[i]);
- }
- var xmin = Math.min(curve[0], curve[2], curve[4], curve[6]);
- for (var i = 1; i < 8; i+= 2) {
- drawLabelY(xmin, i >> 1, curve[i]);
- }
- }
-}
-
-function logCurves(test) {
- for (curves in test) {
- var curve = test[curves];
- if (curve.length != 8) {
- continue;
- }
- var str = "{{";
- for (i = 0; i < 8; i += 2) {
- str += curve[i].toFixed(decimal_places) + "," + curve[i + 1].toFixed(decimal_places);
- if (i < 6) {
- str += "}, {";
- }
- }
- str += "}}";
- console.log(str);
- }
-}
-
-function draw(test, lines, title) {
- ctx.fillStyle = "rgba(0,0,0, 0.1)";
- ctx.font = "normal 50px Arial";
- ctx.textAlign = "left";
- ctx.fillText(title, 50, 50);
- ctx.font = "normal 10px Arial";
- ctx.lineWidth = "1.001"; "0.999";
- var secondPath = test.length;
- var closeCount = 0;
- var logStart = -1;
- var logRange = 0;
- // find last active rec type at this step
- var curType = test[0];
- var curStep = 0;
- var hasOp = false;
- var lastActive = 0;
- var lastAdd = 0;
- var lastSect = 0;
- var lastSort = 0;
- var lastMark = 0;
- activeCount = 0;
- addCount = 0;
- sectCount = 0;
- sortCount = 0;
- markCount = 0;
- activeMax = 0;
- addMax = 0;
- sectMax = 0;
- sectMax2 = 0;
- sortMax = 0;
- markMax = 0;
- lastIndex = test.length - 3;
- for (var testIndex = 0; testIndex < test.length; testIndex += 3) {
- var recType = test[testIndex];
- if (!typeof recType == 'number' || recType < REC_TYPE_UNKNOWN || recType > REC_TYPE_LAST) {
- console.log("unknown rec type: " + recType);
- throw "stop execution";
- }
- // if (curType == recType && curType != REC_TYPE_ADD) {
- // continue;
- // }
- var inStepRange = step_limit == 0 || curStep < step_limit;
- curType = recType;
- if (recType == REC_TYPE_OP) {
- hasOp = true;
- continue;
- }
- if (recType == REC_TYPE_UNKNOWN) {
- // these types do not advance step
- continue;
- }
- var bumpStep = false;
- var records = test[testIndex + 2];
- var fragType = records[0];
- if (recType == REC_TYPE_ADD) {
- if (records.length != 2) {
- console.log("expect only two elements: " + records.length);
- throw "stop execution";
- }
- if (fragType == ADD_MOVETO || fragType == ADD_CLOSE) {
- continue;
- }
- ++addMax;
- if (!draw_add || !inStepRange) {
- continue;
- }
- lastAdd = testIndex;
- ++addCount;
- bumpStep = true;
- }
- if (recType == REC_TYPE_PATH && hasOp) {
- secondPath = testIndex;
- }
- if (recType == REC_TYPE_ACTIVE) {
- ++activeMax;
- if (!draw_active || !inStepRange) {
- continue;
- }
- lastActive = testIndex;
- ++activeCount;
- bumpStep = true;
- }
- if (recType == REC_TYPE_SECT) {
- if (records.length != 2) {
- console.log("expect only two elements: " + records.length);
- throw "stop execution";
- }
- ++sectMax;
- var sectBump = 1;
- switch (fragType) {
- case INTERSECT_LINE:
- case INTERSECT_QUAD_LINE:
- case INTERSECT_QUAD:
- case INTERSECT_SELF_CUBIC:
- case INTERSECT_CUBIC_LINE:
- case INTERSECT_CUBIC:
- sectBump = 1;
- break;
- case INTERSECT_LINE_2:
- case INTERSECT_QUAD_LINE_2:
- case INTERSECT_QUAD_2:
- case INTERSECT_CUBIC_LINE_2:
- case INTERSECT_CUBIC_2:
- sectBump = 2;
- break;
- case INTERSECT_LINE_NO:
- case INTERSECT_QUAD_LINE_NO:
- case INTERSECT_QUAD_NO:
- case INTERSECT_SELF_CUBIC_NO:
- case INTERSECT_CUBIC_LINE_NO:
- case INTERSECT_CUBIC_NO:
- sectBump = 0;
- break;
- case INTERSECT_CUBIC_LINE_3:
- case INTERSECT_CUBIC_3:
- sectBump = 3;
- break;
- case INTERSECT_CUBIC_4:
- sectBump = 4;
- break;
- default:
- console.log("missing case " + records.length);
- throw "stop execution";
- }
- sectMax2 += sectBump;
- if (draw_intersection <= 1 || !inStepRange) {
- continue;
- }
- lastSect = testIndex;
- sectCount += sectBump;
- bumpStep = true;
- }
- if (recType == REC_TYPE_SORT) {
- ++sortMax;
- if (!draw_sort || !inStepRange) {
- continue;
- }
- lastSort = testIndex;
- ++sortCount;
- bumpStep = true;
- }
- if (recType == REC_TYPE_MARK) {
- ++markMax;
- if (!draw_mark || !inStepRange) {
- continue;
- }
- lastMark = testIndex;
- ++markCount;
- bumpStep = true;
- }
- if (bumpStep) {
- lastIndex = testIndex;
- logStart = test[testIndex + 1];
- logRange = records.length / 2;
- ++curStep;
- }
- }
- stepMax = (draw_add ? addMax : 0) + (draw_active ? activeMax : 0)
- + (draw_sort ? sortMax : 0) + (draw_mark ? markMax : 0)
- + (draw_intersection == 2 ? sectMax : draw_intersection == 3 ? sectMax2 : 0);
- if (stepMax == 0) {
- stepMax = addMax + activeMax + sortMax + markMax;
- }
- drawnPts = [];
- drawnLines = [];
- drawnQuads = [];
- drawnCubics = [];
- var pathIndex = 0;
- var opLetter = 'S';
- for (var testIndex = lastIndex; testIndex >= 0; testIndex -= 3) {
- var recType = test[testIndex];
- var records = test[testIndex + 2];
- for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
- var fragType = records[recordIndex];
- if (!typeof fragType == 'number' || fragType < 1 || fragType > FRAG_TYPE_LAST) {
- console.log("unknown in range frag type: " + fragType);
- throw "stop execution";
- }
- var frags = records[recordIndex + 1];
- switch (recType) {
- case REC_TYPE_COMPUTED:
- if (draw_computed == 0) {
- continue;
- }
- ctx.lineWidth = 1;
- ctx.strokeStyle = pathIndex == 0 ? "black" : "red";
- ctx.fillStyle = "blue";
- var drawThis = false;
- switch (fragType) {
- case PATH_QUAD:
- if ((draw_computed & 5) == 1 || ((draw_computed & 4) != 0
- && (draw_computed & 1) == pathIndex)) {
- drawQuad(frags[0], frags[1], frags[2], frags[3],
- frags[4], frags[5]);
- drawThis = true;
- }
- break;
- case PATH_CUBIC:
- if ((draw_computed & 6) == 2 || ((draw_computed & 4) != 0
- && (draw_computed & 1) != pathIndex)) {
- drawCubic(frags[0], frags[1], frags[2], frags[3],
- frags[4], frags[5], frags[6], frags[7]);
- drawThis = true;
- }
- ++pathIndex;
- break;
- case COMPUTED_SET_1:
- pathIndex = 0;
- break;
- case COMPUTED_SET_2:
- pathIndex = 1;
- break;
- default:
- console.log("unknown REC_TYPE_COMPUTED frag type: " + fragType);
- throw "stop execution";
- }
- if (!drawThis) {
- break;
- }
- drawCurveSpecials(frags, fragType);
- break;
- case REC_TYPE_PATH:
- if (!draw_path) {
- continue;
- }
- var firstPath = testIndex < secondPath;
- if ((draw_path & (firstPath ? 1 : 2)) == 0) {
- continue;
- }
- ctx.lineWidth = 1;
- ctx.strokeStyle = firstPath ? "black" : "red";
- ctx.fillStyle = "blue";
- switch (fragType) {
- case PATH_LINE:
- drawLine(frags[0], frags[1], frags[2], frags[3]);
- break;
- case PATH_QUAD:
- drawQuad(frags[0], frags[1], frags[2], frags[3],
- frags[4], frags[5]);
- break;
- case PATH_CUBIC:
- drawCubic(frags[0], frags[1], frags[2], frags[3],
- frags[4], frags[5], frags[6], frags[7]);
- break;
- default:
- console.log("unknown REC_TYPE_PATH frag type: " + fragType);
- throw "stop execution";
- }
- drawCurveSpecials(frags, fragType);
- break;
- case REC_TYPE_OP:
- switch (fragType) {
- case OP_INTERSECT: opLetter = 'I'; break;
- case OP_DIFFERENCE: opLetter = 'D'; break;
- case OP_UNION: opLetter = 'U'; break;
- case OP_XOR: opLetter = 'X'; break;
- default:
- console.log("unknown REC_TYPE_OP frag type: " + fragType);
- throw "stop execution";
- }
- break;
- case REC_TYPE_ACTIVE:
- if (!draw_active || (step_limit > 0 && testIndex < lastActive)) {
- continue;
- }
- var x1 = frags[SPAN_X1];
- var y1 = frags[SPAN_Y1];
- var x2 = frags[SPAN_X2];
- var y2 = frags[SPAN_Y2];
- var x3, y3, x3, y4, t1, t2;
- ctx.lineWidth = 3;
- ctx.strokeStyle = "rgba(0,0,255, 0.3)";
- switch (fragType) {
- case ACTIVE_LINE_SPAN:
- t1 = frags[SPAN_L_T];
- t2 = frags[SPAN_L_TEND];
- drawLinePartial(x1, y1, x2, y2, t1, t2);
- break;
- case ACTIVE_QUAD_SPAN:
- x3 = frags[SPAN_X3];
- y3 = frags[SPAN_Y3];
- t1 = frags[SPAN_Q_T];
- t2 = frags[SPAN_Q_TEND];
- drawQuadPartial(x1, y1, x2, y2, x3, y3, t1, t2);
- break;
- case ACTIVE_CUBIC_SPAN:
- x3 = frags[SPAN_X3];
- y3 = frags[SPAN_Y3];
- x4 = frags[SPAN_X4];
- y4 = frags[SPAN_Y4];
- t1 = frags[SPAN_C_T];
- t2 = frags[SPAN_C_TEND];
- drawCubicPartial(x1, y1, x2, y2, x3, y3, x4, y4, t1, t2);
- break;
- default:
- console.log("unknown REC_TYPE_ACTIVE frag type: " + fragType);
- throw "stop execution";
- }
- break;
- case REC_TYPE_ADD:
- if (!draw_add) {
- continue;
- }
- ctx.lineWidth = 3;
- ctx.strokeStyle = closeCount == 0 ? "rgba(0,0,255, 0.3)"
- : closeCount == 1 ? "rgba(0,127,0, 0.3)"
- : closeCount == 2 ? "rgba(0,127,127, 0.3)"
- : closeCount == 3 ? "rgba(127,127,0, 0.3)"
- : "rgba(127,0,127, 0.3)";
- switch (fragType) {
- case ADD_MOVETO:
- break;
- case ADD_LINETO:
- if (step_limit == 0 || testIndex >= lastAdd) {
- drawLine(frags[0], frags[1], frags[2], frags[3]);
- }
- break;
- case ADD_QUADTO:
- if (step_limit == 0 || testIndex >= lastAdd) {
- drawQuad(frags[0], frags[1], frags[2], frags[3], frags[4], frags[5]);
- }
- break;
- case ADD_CUBICTO:
- if (step_limit == 0 || testIndex >= lastAdd) {
- drawCubic(frags[0], frags[1], frags[2], frags[3],
- frags[4], frags[5], frags[6], frags[7]);
- }
- break;
- case ADD_CLOSE:
- ++closeCount;
- break;
- default:
- console.log("unknown REC_TYPE_ADD frag type: " + fragType);
- throw "stop execution";
- }
- break;
- case REC_TYPE_SECT:
- if (!draw_intersection) {
- continue;
- }
- if (draw_intersection != 1 && (step_limit > 0 && testIndex < lastSect)) {
- continue;
- }
- // draw_intersection == 1 : show all
- // draw_intersection == 2 : step == 0 ? show all : show intersection line #step
- // draw_intersection == 3 : step == 0 ? show all : show intersection #step
- ctx.lineWidth = 1;
- ctx.strokeStyle = "rgba(0,0,255, 0.3)";
- ctx.fillStyle = "blue";
- var f = [];
- var c1s;
- var c1l;
- var c2s;
- var c2l;
- switch (fragType) {
- case INTERSECT_LINE:
- f.push(5, 6, 0, 7);
- c1s = 1; c1l = 4; c2s = 8; c2l = 4;
- break;
- case INTERSECT_LINE_2:
- f.push(5, 6, 0, 10);
- f.push(8, 9, 7, 15);
- c1s = 1; c1l = 4; c2s = 11; c2l = 4;
- break;
- case INTERSECT_LINE_NO:
- c1s = 0; c1l = 4; c2s = 4; c2l = 4;
- break;
- case INTERSECT_QUAD_LINE:
- f.push(7, 8, 0, 9);
- c1s = 1; c1l = 6; c2s = 10; c2l = 4;
- break;
- case INTERSECT_QUAD_LINE_2:
- f.push(7, 8, 0, 12);
- f.push(10, 11, 9, 17);
- c1s = 1; c1l = 6; c2s = 13; c2l = 4;
- break;
- case INTERSECT_QUAD_LINE_NO:
- c1s = 0; c1l = 6; c2s = 6; c2l = 4;
- break;
- case INTERSECT_QUAD:
- f.push(7, 8, 0, 9);
- c1s = 1; c1l = 6; c2s = 10; c2l = 6;
- break;
- case INTERSECT_QUAD_2:
- f.push(7, 8, 0, 12);
- f.push(10, 11, 9, 19);
- c1s = 1; c1l = 6; c2s = 13; c2l = 6;
- break;
- case INTERSECT_QUAD_NO:
- c1s = 0; c1l = 6; c2s = 6; c2l = 6;
- break;
- case INTERSECT_SELF_CUBIC:
- f.push(9, 10, 0, 11);
- c1s = 1; c1l = 8; c2s = 0; c2l = 0;
- break;
- case INTERSECT_SELF_CUBIC_NO:
- c1s = 0; c1l = 8; c2s = 0; c2l = 0;
- break;
- case INTERSECT_CUBIC_LINE:
- f.push(9, 10, 0, 11);
- c1s = 1; c1l = 8; c2s = 12; c2l = 4;
- break;
- case INTERSECT_CUBIC_LINE_2:
- f.push(9, 10, 0, 14);
- f.push(12, 13, 11, 19);
- c1s = 1; c1l = 8; c2s = 15; c2l = 4;
- break;
- case INTERSECT_CUBIC_LINE_3:
- f.push(9, 10, 0, 17);
- f.push(12, 13, 11, 22);
- f.push(15, 16, 14, 23);
- c1s = 1; c1l = 8; c2s = 18; c2l = 4;
- break;
- case INTERSECT_CUBIC_LINE_NO:
- c1s = 0; c1l = 8; c2s = 8; c2l = 4;
- break;
- case INTERSECT_CUBIC:
- f.push(9, 10, 0, 11);
- c1s = 1; c1l = 8; c2s = 12; c2l = 8;
- break;
- case INTERSECT_CUBIC_2:
- f.push(9, 10, 0, 14);
- f.push(12, 13, 11, 23);
- c1s = 1; c1l = 8; c2s = 15; c2l = 8;
- break;
- case INTERSECT_CUBIC_3:
- f.push(9, 10, 0, 17);
- f.push(12, 13, 11, 26);
- f.push(15, 16, 14, 27);
- c1s = 1; c1l = 8; c2s = 18; c2l = 8;
- break;
- case INTERSECT_CUBIC_4:
- f.push(9, 10, 0, 20);
- f.push(12, 13, 11, 29);
- f.push(15, 16, 14, 30);
- f.push(18, 19, 17, 31);
- c1s = 1; c1l = 8; c2s = 21; c2l = 8;
- break;
- case INTERSECT_CUBIC_NO:
- c1s = 0; c1l = 8; c2s = 8; c2l = 8;
- break;
- default:
- console.log("unknown REC_TYPE_SECT frag type: " + fragType);
- throw "stop execution";
- }
- if (draw_intersection != 1) {
- switch (c1l) {
- case 4:
- drawLine(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3]);
- break;
- case 6:
- drawQuad(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
- frags[c1s + 4], frags[c1s + 5]);
- break;
- case 8:
- drawCubic(frags[c1s], frags[c1s + 1], frags[c1s + 2], frags[c1s + 3],
- frags[c1s + 4], frags[c1s + 5], frags[c1s + 6], frags[c1s + 7]);
- break;
- }
- switch (c2l) {
- case 0:
- break;
- case 4:
- drawLine(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3]);
- break;
- case 6:
- drawQuad(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
- frags[c2s + 4], frags[c2s + 5]);
- break;
- case 8:
- drawCubic(frags[c2s], frags[c2s + 1], frags[c2s + 2], frags[c2s + 3],
- frags[c2s + 4], frags[c2s + 5], frags[c2s + 6], frags[c2s + 7]);
- break;
- }
- }
- for (var idx = 0; idx < f.length; idx += 4) {
- if (draw_intersection != 3 || idx == lastSect - testIndex) {
- drawPoint(frags[f[idx]], frags[f[idx + 1]], true);
- }
- }
- if (!draw_intersectT) {
- break;
- }
- ctx.fillStyle = "red";
- for (var idx = 0; idx < f.length; idx += 4) {
- if (draw_intersection != 3 || idx == lastSect - testIndex) {
- drawTAtPointUp(frags[f[idx]], frags[f[idx + 1]], frags[f[idx + 2]]);
- drawTAtPointDown(frags[f[idx]], frags[f[idx + 1]], frags[f[idx + 3]]);
- }
- }
- break;
- case REC_TYPE_SORT:
- if (!draw_sort || (step_limit > 0 && testIndex < lastSort)) {
- continue;
- }
- ctx.lineWidth = 3;
- ctx.strokeStyle = "rgba(127,127,0, 0.5)";
- switch (fragType) {
- case SORT_LINE:
- case SORT_LINE_UNSORTABLE:
- drawLinePartial(frags[1], frags[2], frags[3], frags[4],
- frags[5], frags[6]);
- break;
- case SORT_QUAD:
- case SORT_QUAD_UNSORTABLE:
- drawQuadPartial(frags[1], frags[2], frags[3], frags[4],
- frags[5], frags[6], frags[7], frags[8]);
- break;
- case SORT_CUBIC:
- case SORT_CUBIC_UNSORTABLE:
- drawCubicPartial(frags[1], frags[2], frags[3], frags[4],
- frags[5], frags[6], frags[7], frags[8], frags[9], frags[10]);
- break;
- case SORT_LINE_COMPACT:
- case SORT_QUAD_COMPACT:
- case SORT_CUBIC_COMPACT:
- // unsupported
- break;
- default:
- console.log("unknown REC_TYPE_SORT frag type: " + fragType);
- throw "stop execution";
- }
- break;
- case REC_TYPE_MARK:
- if (!draw_mark || (step_limit > 0 && testIndex < lastMark)) {
- continue;
- }
- ctx.lineWidth = 3;
- ctx.strokeStyle = fragType >= MARK_DONE_LINE ?
- "rgba(127,0,127, 0.5)" : "rgba(127,127,0, 0.5)";
- switch (fragType) {
- case MARK_LINE:
- case MARK_DONE_LINE:
- case MARK_UNSORTABLE_LINE:
- case MARK_SIMPLE_LINE:
- case MARK_SIMPLE_DONE_LINE:
- case MARK_DONE_UNARY_LINE:
- drawLinePartial(frags[1], frags[2], frags[3], frags[4],
- frags[5], frags[9]);
- break;
- case MARK_QUAD:
- case MARK_DONE_QUAD:
- case MARK_UNSORTABLE_QUAD:
- case MARK_SIMPLE_QUAD:
- case MARK_SIMPLE_DONE_QUAD:
- case MARK_DONE_UNARY_QUAD:
- drawQuadPartial(frags[1], frags[2], frags[3], frags[4],
- frags[5], frags[6], frags[7], frags[11]);
- break;
- case MARK_CUBIC:
- case MARK_DONE_CUBIC:
- case MARK_UNSORTABLE_CUBIC:
- case MARK_SIMPLE_CUBIC:
- case MARK_SIMPLE_DONE_CUBIC:
- case MARK_DONE_UNARY_CUBIC:
- drawCubicPartial(frags[1], frags[2], frags[3], frags[4],
- frags[5], frags[6], frags[7], frags[8], frags[9], frags[13]);
- break;
- default:
- console.log("unknown REC_TYPE_MARK frag type: " + fragType);
- throw "stop execution";
- }
- break;
- default:
- continue;
- }
- }
- switch (recType) {
- case REC_TYPE_SORT:
- if (!draw_sort || (step_limit > 0 && testIndex < lastSort)) {
- break;
- }
- var angles = []; // use tangent lines to describe arcs
- var windFrom = [];
- var windTo = [];
- var opp = [];
- var minXY = Number.MAX_VALUE;
- var partial;
- for (var recordIndex = 0; recordIndex < records.length; recordIndex += 2) {
- var fragType = records[recordIndex];
- var frags = records[recordIndex + 1];
- var idx = 10;
- switch (fragType) {
- case SORT_LINE:
- case SORT_LINE_UNSORTABLE:
- partial = linePartial(frags[1], frags[2], frags[3], frags[4],
- frags[5], frags[6]);
- break;
- case SORT_QUAD:
- case SORT_QUAD_UNSORTABLE:
- partial = quadPartial(frags[1], frags[2], frags[3], frags[4],
- frags[5], frags[6], frags[7], frags[8]);
- idx += 2;
- break;
- case SORT_CUBIC:
- case SORT_CUBIC_UNSORTABLE:
- partial = cubicPartial(frags[1], frags[2], frags[3], frags[4],
- frags[5], frags[6], frags[7], frags[8], frags[9], frags[10]);
- idx += 4;
- break;
- case SORT_LINE_COMPACT:
- case SORT_QUAD_COMPACT:
- case SORT_CUBIC_COMPACT:
- // unsupported
- continue;
- default:
- console.log("unknown REC_TYPE_SORT frag type: " + fragType);
- throw "stop execution";
- }
- var dx = boundsWidth(partial);
- var dy = boundsHeight(partial);
- minXY = Math.min(minXY, dx * dx + dy * dy);
- angles.push(tangent(partial));
- windFrom.push(frags[idx]);
- windTo.push(frags[idx + 1]);
- opp.push(frags[idx + 5]);
- }
- var radius = Math.sqrt(minXY) / 2 * scale;
- radius = Math.min(50, radius);
- var centerX = (partial[0] - srcLeft) * scale;
- var centerY = (partial[1] - srcTop) * scale;
- ctx.lineWidth = 1;
- ctx.strokeStyle = "rgba(127,0,171, 0.5)";
- ctx.fillStyle = "rgba(0,0,0, 0.5)";
- ctx.font = "normal 10px Arial";
- ctx.textAlign = "center";
- for (var angleIndex = 0; angleIndex < angles.length; ++angleIndex) {
- var angleParts = [
- angles[(angleIndex + angles.length - 1) % angles.length],
- angles[angleIndex],
- angles[(angleIndex + 1) % angles.length]
- ];
- var angleStart = (angleParts[0] + angleParts[1]) / 2;
- if (angleParts[0] > angleParts[1]) {
- angleStart -= Math.PI;
- }
- var angleEnd = (angleParts[1] + angleParts[2]) / 2;
- if (angleParts[1] > angleParts[2]) {
- angleEnd -= Math.PI;
- }
- ctx.beginPath();
- ctx.arc(centerX, centerY, radius + (opp[angleIndex] ? 10 : 0),
- Math.PI * 2 - angleStart - Math.PI / 18, Math.PI * 2 - angleEnd + Math.PI / 18, true);
- ctx.stroke();
- var tx = centerX + Math.cos(angleStart) * (radius + (opp[angleIndex] ? 10 : 0));
- var ty = centerY - Math.sin(angleStart) * (radius + (opp[angleIndex] ? 10 : 0));
- ctx.fillText(windFrom[angleIndex], tx, ty + 5);
- tx = centerX + Math.cos(angleEnd) * (radius + (opp[angleIndex] ? 10 : 0));
- ty = centerY - Math.sin(angleEnd) * (radius + (opp[angleIndex] ? 10 : 0));
- ctx.fillText(windTo[angleIndex], tx, ty + 5);
- }
- break;
- default:
- break;
- }
- }
- if (draw_log && logStart >= 0) {
- ctx.font = "normal 10px Arial";
- ctx.textAlign = "left";
- ctx.beginPath();
- var top = ctx.canvas.height - 20 - (logRange + 2) * 10;
- ctx.rect(50, top, ctx.canvas.width-100, (logRange + 2) * 10);
- ctx.fillStyle = "white";
- ctx.fill();
- ctx.fillStyle = "rgba(0,0,0, 0.5)";
- if (logStart > 0) {
- ctx.fillText(lines[logStart - 1], 50, top + 8);
- }
- ctx.fillStyle = "black";
- for (var idx = 0; idx < logRange; ++idx) {
- ctx.fillText(lines[logStart + idx], 50, top + 18 + 10 * idx);
- }
- ctx.fillStyle = "rgba(0,0,0, 0.5)";
- if (logStart + logRange < lines.length) {
- ctx.fillText(lines[logStart + logRange], 50, top + 18 + 10 * logRange);
- }
- }
- if (draw_legend) {
- var pos = 0;
- var drawSomething = draw_add | draw_active | draw_sort | draw_mark;
- // drawBox(pos++, "yellow", "black", opLetter, true, '');
- drawBox(pos++, "rgba(0,0,255, 0.3)", "black", draw_intersection > 1 ? sectCount : sectMax2, draw_intersection, intersectionKey);
- drawBox(pos++, "rgba(0,0,255, 0.3)", "black", draw_add ? addCount : addMax, draw_add, addKey);
- drawBox(pos++, "rgba(0,0,255, 0.3)", "black", draw_active ? activeCount : activeMax, draw_active, activeKey);
- drawBox(pos++, "rgba(127,127,0, 0.3)", "black", draw_sort ? sortCount : sortMax, draw_sort, sortKey);
- drawBox(pos++, "rgba(127,0,127, 0.3)", "black", draw_mark ? markCount : markMax, draw_mark, markKey);
- drawBox(pos++, "black", "white",
- (new Array('P', 'P1', 'P2', 'P'))[draw_path], draw_path != 0, pathKey);
- drawBox(pos++, "rgba(0,63,0, 0.7)", "white",
- (new Array('Q', 'Q', 'C', 'QC', 'Qc', 'Cq'))[draw_computed],
- draw_computed != 0, computedKey);
- drawBox(pos++, "green", "black", step_limit, drawSomething, '');
- drawBox(pos++, "green", "black", stepMax, drawSomething, '');
- drawBox(pos++, "red", "black", lastIndex, drawSomething & draw_log, '');
- drawBox(pos++, "red", "black", test.length - 1, drawSomething & draw_log, '');
- if (curve_t) {
- drawCurveTControl();
- }
- ctx.font = "normal 20px Arial";
- ctx.fillStyle = "rgba(0,0,0, 0.3)";
- ctx.textAlign = "right";
- ctx.fillText(scale.toFixed(decimal_places) + 'x' , ctx.canvas.width - 10, ctx.canvas.height - 5);
- }
- if (draw_hints) {
- ctx.font = "normal 10px Arial";
- ctx.fillStyle = "rgba(0,0,0, 0.5)";
- ctx.textAlign = "right";
- var y = 4;
- ctx.fillText("control lines : " + controlLinesKey, ctx.canvas.width - 10, pos * 50 + y++ * 10);
- ctx.fillText("curve t : " + curveTKey, ctx.canvas.width - 10, pos * 50 + y++ * 10);
- ctx.fillText("deriviatives : " + deriviativesKey, ctx.canvas.width - 10, pos * 50 + y++ * 10);
- ctx.fillText("intersect t : " + intersectTKey, ctx.canvas.width - 10, pos * 50 + y++ * 10);
- ctx.fillText("hodo : " + hodoKey, ctx.canvas.width - 10, pos * 50 + y++ * 10);
- ctx.fillText("log : " + logKey, ctx.canvas.width - 10, pos * 50 + y++ * 10);
- ctx.fillText("log curve : " + logCurvesKey, ctx.canvas.width - 10, pos * 50 + y++ * 10);
- ctx.fillText("mid point : " + midpointKey, ctx.canvas.width - 10, pos * 50 + y++ * 10);
- ctx.fillText("points : " + ptsKey, ctx.canvas.width - 10, pos * 50 + y++ * 10);
- ctx.fillText("sequence : " + sequenceKey, ctx.canvas.width - 10, pos * 50 + y++ * 10);
- ctx.fillText("xy : " + xyKey, ctx.canvas.width - 10, pos * 50 + y++ * 10);
- }
-}
-
-function drawBox(y, backC, foreC, str, enable, label) {
- ctx.beginPath();
- ctx.fillStyle = backC;
- ctx.rect(ctx.canvas.width - 40, y * 50 + 10, 40, 30);
- ctx.fill();
- ctx.font = "normal 16px Arial";
- ctx.fillStyle = foreC;
- ctx.textAlign = "center";
- ctx.fillText(str, ctx.canvas.width - 20, y * 50 + 32);
- if (!enable) {
- ctx.fillStyle = "rgba(255,255,255, 0.5)";
- ctx.fill();
- }
- if (label != '') {
- ctx.font = "normal 9px Arial";
- ctx.fillStyle = "black";
- ctx.fillText(label, ctx.canvas.width - 47, y * 50 + 40);
- }
-}
-
-function drawCurveTControl() {
- ctx.lineWidth = 2;
- ctx.strokeStyle = "rgba(0,0,0, 0.3)";
- ctx.beginPath();
- ctx.rect(ctx.canvas.width - 80, 40, 28, ctx.canvas.height - 80);
- ctx.stroke();
- var ty = 40 + curveT * (ctx.canvas.height - 80);
- ctx.beginPath();
- ctx.moveTo(ctx.canvas.width - 80, ty);
- ctx.lineTo(ctx.canvas.width - 85, ty - 5);
- ctx.lineTo(ctx.canvas.width - 85, ty + 5);
- ctx.lineTo(ctx.canvas.width - 80, ty);
- ctx.fillStyle = "rgba(0,0,0, 0.6)";
- ctx.fill();
- var num = curveT.toFixed(decimal_places);
- ctx.font = "normal 10px Arial";
- ctx.textAlign = "left";
- ctx.fillText(num, ctx.canvas.width - 78, ty);
-}
-
-function ptInTControl() {
- var e = window.event;
- var tgt = e.target || e.srcElement;
- var left = tgt.offsetLeft;
- var top = tgt.offsetTop;
- var x = (e.clientX - left);
- var y = (e.clientY - top);
- if (x < ctx.canvas.width - 80 || x > ctx.canvas.width - 50) {
- return false;
- }
- if (y < 40 || y > ctx.canvas.height - 80) {
- return false;
- }
- curveT = (y - 40) / (ctx.canvas.height - 120);
- if (curveT < 0 || curveT > 1) {
- throw "stop execution";
- }
- return true;
-}
-
-function drawTop() {
- if (tests[testIndex] == null) {
- var str = testDivs[testIndex].firstChild.data;
- parse_all(str);
- var title = testDivs[testIndex].id.toString();
- testTitles[testIndex] = title;
- }
- init(tests[testIndex]);
- redraw();
-}
-
-function redraw() {
- ctx.beginPath();
- ctx.fillStyle = "white";
- ctx.rect(0, 0, ctx.canvas.width, ctx.canvas.height);
- ctx.fill();
- draw(tests[testIndex], testLines[testIndex], testTitles[testIndex]);
-}
-
-var activeKey = 'a';
-var addKey = 'd';
-var centerKey = 'c';
-var computedKey = 'q';
-var computedBackKey = 'Q';
-var controlLinesBackKey = 'V';
-var controlLinesKey = 'v';
-var curveTKey = 'u';
-var deriviativesKey = 'f';
-var hodoKey = 'h';
-var intersectTKey = 't';
-var intersectionBackKey = 'I';
-var intersectionKey = 'i';
-var logKey = 'l';
-var logCurvesKey = 'z';
-var markKey = 'm';
-var midpointKey = 'k';
-var pathKey = 'b';
-var pathBackKey = 'B';
-var ptsKey = 'x';
-var sequenceKey = 'j';
-var sortKey = 'o';
-var stepBackKey = 'S';
-var stepKey = 's';
-var xyKey = 'y';
-
-function doKeyPress(evt) {
- var char = String.fromCharCode(evt.charCode);
- switch (char) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- decimal_places = char - '0';
- redraw();
- break;
- case activeKey:
- draw_active ^= true;
- redraw();
- break;
- case addKey:
- draw_add ^= true;
- redraw();
- break;
- case centerKey:
- setScale();
- redraw();
- break;
- case controlLinesBackKey:
- control_lines = (control_lines + 3) % 4;
- redraw();
- break;
- case controlLinesKey:
- control_lines = (control_lines + 1) % 4;
- redraw();
- break;
- case computedBackKey:
- draw_computed = (draw_computed + 5) % 6;
- redraw();
- break;
- case computedKey:
- draw_computed = (draw_computed + 1) % 6;
- redraw();
- break;
- case curveTKey:
- curve_t ^= true;
- if (curve_t) {
- draw_legend = true;
- }
- redraw();
- break;
- case deriviativesKey:
- draw_deriviatives = (draw_deriviatives + 1) % 3;
- redraw();
- break;
- case hodoKey:
- draw_hodo = (draw_hodo + 1) % 4;
- redraw();
- break;
- case intersectionBackKey:
- draw_intersection = (draw_intersection + 3) % 4;
- redraw();
- break;
- case intersectionKey:
- draw_intersection = (draw_intersection + 1) % 4;
- redraw();
- break;
- case intersectTKey:
- draw_intersectT ^= true;
- redraw();
- break;
- case logCurvesKey:
- logCurves(tests[testIndex]);
- break;
- case logKey:
- draw_log ^= true;
- redraw();
- break;
- case markKey:
- draw_mark ^= true;
- redraw();
- break;
- case midpointKey:
- draw_midpoint ^= true;
- redraw();
- break;
- case pathKey:
- draw_path = (draw_path + 1) % 4;
- redraw();
- break;
- case pathBackKey:
- draw_path = (draw_path + 3) % 4;
- redraw();
- break;
- case ptsKey:
- pt_labels = (pt_labels + 1) % 3;
- redraw();
- break;
- case sequenceKey:
- draw_sequence ^= true;
- redraw();
- break;
- case sortKey:
- draw_sort ^= true;
- redraw();
- break;
- case stepKey:
- step_limit++;
- if (step_limit > stepMax) {
- step_limit = stepMax;
- }
- redraw();
- break;
- case stepBackKey:
- step_limit--;
- if (step_limit < 0) {
- step_limit = 0;
- }
- redraw();
- break;
- case xyKey:
- debug_xy ^= true;
- redraw();
- break;
- case '-':
- scale /= 2;
- calcLeftTop();
- redraw();
- break;
- case '=':
- case '+':
- scale *= 2;
- calcLeftTop();
- redraw();
- break;
- case '?':
- draw_hints ^= true;
- if (draw_hints && !draw_legend) {
- draw_legend = true;
- }
- redraw();
- break;
- case '/':
- draw_legend ^= true;
- redraw();
- break;
- }
-}
-
-function doKeyDown(evt) {
- var char = evt.keyCode;
- switch (char) {
- case 37: // left arrow
- if (evt.shiftKey) {
- testIndex -= 9;
- }
- if (--testIndex < 0)
- testIndex = tests.length - 1;
- drawTop();
- break;
- case 39: // right arrow
- if (evt.shiftKey) {
- testIndex += 9;
- }
- if (++testIndex >= tests.length)
- testIndex = 0;
- drawTop();
- break;
- }
-}
-
-function calcXY() {
- var e = window.event;
- var tgt = e.target || e.srcElement;
- var left = tgt.offsetLeft;
- var top = tgt.offsetTop;
- mouseX = (e.clientX - left) / scale + srcLeft;
- mouseY = (e.clientY - top) / scale + srcTop;
-}
-
-function calcLeftTop() {
- srcLeft = mouseX - screenWidth / 2 / scale;
- srcTop = mouseY - screenHeight / 2 / scale;
-}
-
-function handleMouseClick() {
- if (!curve_t || !ptInTControl()) {
- calcXY();
- calcLeftTop();
- }
- redraw();
-}
-
-function handleMouseOver() {
- calcXY();
- if (!debug_xy) {
- return;
- }
- var num = mouseX.toFixed(decimal_places) + ", " + mouseY.toFixed(decimal_places);
- ctx.beginPath();
- ctx.rect(300,100,num.length * 6,10);
- ctx.fillStyle="white";
- ctx.fill();
- ctx.font = "normal 10px Arial";
- ctx.fillStyle="black";
- ctx.textAlign = "left";
- ctx.fillText(num, 300, 108);
-}
-
-function start() {
- for (var i = 0; i < testDivs.length; ++i) {
- tests[i] = null;
- }
- testIndex = 0;
- drawTop();
- window.addEventListener('keypress', doKeyPress, true);
- window.addEventListener('keydown', doKeyDown, true);
- window.onresize = function() {
- drawTop();
- }
-}
-
-</script>
-</head>
-
-<body onLoad="start();">
-<canvas id="canvas" width="750" height="500"
- onmousemove="handleMouseOver()"
- onclick="handleMouseClick()"
- ></canvas >
-</body>
-</html>
diff --git a/experimental/Intersection/bc.htm b/experimental/Intersection/bc.htm
deleted file mode 100644
index fc9191a694..0000000000
--- a/experimental/Intersection/bc.htm
+++ /dev/null
@@ -1,455 +0,0 @@
-<!-- bezier clip visualizer -->
-<html>
-<head>
-<div style="height:0">
-
-<div id="clip1">
-(gdb) p smaller
-$2 = {{
- x = 0.91292418204644155,
- y = 0.41931201426549197
- }, {
- x = 0.70491388044579517,
- y = 0.64754305977710236
- }, {
- x = 0,
- y = 1
- }}
-(gdb) p larger
-$3 = {{
- x = 0.21875,
- y = 0.765625
- }, {
- x = 0.125,
- y = 0.875
- }, {
- x = 0,
- y = 1
- }}
-(gdb) p distance2y
-$1 = {{
- x = 0,
- y = 0.080355482722450078
- }, {
- x = 0.5,
- y = 0.038383741101172597
- }, {
- x = 1,
- y = 0
- }}
-</div>
-
-<div id="quad21a">
-bezier_clip q1=(0,0 1,0 0,2) q2=(0.5,0.25 0.5,0.5 0,1) minT=0 maxT=1
-</div>
-<div id="quad21b">
-bezier_clip q1=(0.5,0.25 0.5,0.375 0.375,0.5625) q2=(0,0 1,0 0,2) minT=0.3 maxT=0.78125
-</div>
-<div id="quad21c">
-bezier_clip q1=(0.42,0.18 0.6125,0.46875 0.341796875,1.22070312) q2=(0.5,0.25 0.5,0.375 0.375,0.5625) minT=0 maxT=0.926710098
-</div>
-<div id="quad21d">
-bezier_clip q1=(0.5,0.25 0.5,0.307919381 0.473162762,0.379257381) q2=(0.42,0.18 0.6125,0.46875 0.341796875,1.22070312) minT=0.187231244 maxT=0.729263299
-</div>
-<div id="quad21e">
-bezier_clip q1=(0.475846194,0.304363878 0.53317904,0.507883959 0.454423387,0.847492538) q2=(0.5,0.25 0.5,0.307919381 0.473162762,0.379257381) minT=0 maxT=1
-</div>
-<div id="quad21f">
-bezier_clip q1=(0.493290691,0.311274036 0.486581381,0.343588381 0.473162762,0.379257381) q2=(0.475846194,0.304363878 0.53317904,0.507883959 0.454423387,0.847492538) minT=0.0828748517 maxT=0.150086861
-</div>
-
-<div id="quad21g">
-(gdb) p smaller
-$1 = {{
- x = 0.48441440743366754,
- y = 0.33903196011243797
- }, {
- x = 0.48750982503868118,
- y = 0.35346899178071778
- }, {
- x = 0.48999046908865357,
- y = 0.368520797004039
- }}
-(gdb) p larger
-$2 = {{
- x = 0.49329069058425024,
- y = 0.31127403581536672
- }, {
- x = 0.48658138116850047,
- y = 0.34358838107698753
- }, {
- x = 0.47316276233700094,
- y = 0.37925738104648321
- }}
-</div>
-
-<div id="quad36">
-(gdb) p fQ
-$2 = {{
- x = 1.8883839294261275,
- y = 2.1108590606904345
- }, {
- x = 1.888463903363252,
- y = 2.1111576060205435
- }, {
- x = 1.8885438199983176,
- y = 2.1114561800016824
- }}
-(gdb) p rh.fQ
-$3 = {{
- x = 1.8883839294260976,
- y = 2.1108590606903377
- }, {
- x = 1.8886366953645748,
- y = 2.1109850143489544
- }, {
- x = 1.8888888888888888,
- y = 2.1111111111111112
- }}
-(gdb)
-</div>
-
-<div id="quad37">
- {{x = 360.048828125, y = 229.2578125}, {x = 360.048828125, y = 224.4140625}, {x = 362.607421875, y = 221.3671875}}
- {{x = 362.607421875, y = 221.3671875}, {x = 365.166015625, y = 218.3203125}, {x = 369.228515625, y = 218.3203125}}
-</div>
-
-<div id="quad38">
-$2 = {{fX = 369.969421, fY = 137.94809}, {fX = 383.982849, fY = 121.260353}, {fX = 406.233154, fY = 121.260353}}
-$4 = {{fX = 406.232788, fY = 121.260353}, {fX = 409.441956, fY = 121.260353}, {fX = 412.972046, fY = 121.795212}}
-</div>
-
-<div id="quad39">
-{{x = 406.233154296875, y = 121.26035308837891}, {x = 406.23153587045397, y = 121.26035308837891}, {x = 406.22991748761177, y = 121.26035317666889}},
-{{x = 406.23295158013377, y = 121.26035308872596}, {x = 406.2328698329315, y = 121.26035308837889}, {x = 406.2327880859375, y = 121.26035308837891}},
-</div>
-
-</div>
-
-<script type="text/javascript">
-
-var testDivs = [
- quad56,
- quad39,
- quad38,
- quad37,
- quad36,
- quad21g,
- quad21a,
- quad21b,
- quad21c,
- quad21d,
- quad21e,
- quad21f,
- clip1,
-];
-
-var scale, columns, rows, xStart, yStart;
-
-var ticks = 10;
-var at_x = 13 + 0.5;
-var at_y = 13 + 0.5;
-var init_decimal_places = 1; // make this 3 to show more precision
-var decimal_places;
-var tests = [];
-var testTitles = [];
-var testIndex = 0;
-var ctx;
-var fat1 = true;
-var fat2 = false;
-var ctl1 = true;
-var ctl2 = false;
-var ctlPts1 = true;
-var ctlPts2 = false;
-var minScale = 1;
-var subscale = 1;
-
-function parse(test, title) {
- var curveStrs = test.split("{{");
- if (curveStrs.length == 1)
- curveStrs = test.split("=(");
- var pattern = /[a-z$=]?-?\d+\.*\d*/g;
- var curves = [];
- for (var c in curveStrs) {
- var curveStr = curveStrs[c];
- var points = curveStr.match(pattern);
- var pts = [];
- for (var wd in points) {
- var num = parseFloat(points[wd]);
- if (isNaN(num)) continue;
- pts.push(num);
- }
- if (pts.length > 0)
- curves.push(pts);
- }
- if (curves.length >= 2) {
- tests.push(curves);
- testTitles.push(title);
- }
-}
-
-function init(test) {
- var canvas = document.getElementById('canvas');
- if (!canvas.getContext) return;
- canvas.width = window.innerWidth - at_x;
- canvas.height = window.innerHeight - at_y;
- ctx = canvas.getContext('2d');
- var xmin = Infinity;
- var xmax = -Infinity;
- var ymin = Infinity;
- var ymax = -Infinity;
- for (var curves in test) {
- var curve = test[curves];
- var last = curve.length;
- for (var idx = 0; idx < last; idx += 2) {
- xmin = Math.min(xmin, curve[idx]);
- xmax = Math.max(xmax, curve[idx]);
- ymin = Math.min(ymin, curve[idx + 1]);
- ymax = Math.max(ymax, curve[idx + 1]);
- }
- }
- subscale = 1;
- decimal_places = init_decimal_places;
- if (xmax != xmin && ymax != ymin) {
- while ((xmax - xmin) * subscale < 0.1 && (ymax - ymin) * subscale < 0.1) {
- subscale *= 10;
- decimal_places += 1;
- // if (subscale > 100000) {
- // break;
- // }
- }
- }
- columns = Math.ceil(xmax * subscale) - Math.floor(xmin * subscale) + 1;
- rows = Math.ceil(ymax * subscale) - Math.floor(ymin * subscale) + 1;
-
- xStart = Math.floor(xmin * subscale) / subscale;
- yStart = Math.floor(ymin * subscale) / subscale;
- var hscale = ctx.canvas.width / columns / ticks;
- var vscale = ctx.canvas.height / rows / ticks;
- minScale = Math.floor(Math.min(hscale, vscale));
- scale = minScale * subscale;
- // while (columns < 1000 && rows < 1000) {
- // columns *= 2;
- // rows *= 2;
- // }
-}
-
-function drawPoint(px, py, xoffset, yoffset, unit) {
- var label = px.toFixed(decimal_places) + ", " + py.toFixed(decimal_places);
- var _px = px * unit + xoffset;
- var _py = py * unit + yoffset;
- ctx.beginPath();
- ctx.arc(_px, _py, 3, 0, Math.PI*2, true);
- ctx.closePath();
- ctx.fill();
- ctx.fillText(label, _px + 5, _py);
-}
-
-function draw(test, title, _at_x, _at_y, scale) {
- ctx.fillStyle = "rgba(0,0,0, 0.1)";
- ctx.font = "normal 50px Arial";
- ctx.fillText(title, 50, 50);
- ctx.font = "normal 10px Arial";
-
- var unit = scale * ticks;
- ctx.lineWidth = 1;
- var i;
- for (i = 0; i <= rows * ticks; ++i) {
- ctx.strokeStyle = (i % ticks) != 0 ? "rgb(160,160,160)" : "black";
- ctx.beginPath();
- ctx.moveTo(_at_x + 0, _at_y + i * minScale);
- ctx.lineTo(_at_x + unit * columns, _at_y + i * minScale);
- ctx.stroke();
- }
- for (i = 0; i <= columns * ticks; ++i) {
- ctx.strokeStyle = (i % ticks) != 0 ? "rgb(160,160,160)" : "black";
- ctx.beginPath();
- ctx.moveTo(_at_x + i * minScale, _at_y + 0);
- ctx.lineTo(_at_x + i * minScale, _at_y + unit * rows);
- ctx.stroke();
- }
-
- var xoffset = xStart * -unit + _at_x;
- var yoffset = yStart * -unit + _at_y;
-
- ctx.fillStyle = "rgb(40,80,60)"
- for (i = 0; i <= columns; i += (1 / ticks))
- {
- num = xStart + i / subscale;
- ctx.fillText(num.toFixed(decimal_places), xoffset + num * unit - 5, 10);
- }
- for (i = 0; i <= rows; i += (1 / ticks))
- {
- num = yStart + i / subscale;
- ctx.fillText(num.toFixed(decimal_places), 0, yoffset + num * unit + 0);
- }
-
- // draw curve 1 and 2
- var curves, pts;
- for (curves in test) {
- var curve = test[curves];
- ctx.beginPath();
- ctx.moveTo(xoffset + curve[0] * unit, yoffset + curve[1] * unit);
- switch (curve.length) {
- case 6:
- ctx.quadraticCurveTo(
- xoffset + curve[2] * unit, yoffset + curve[3] * unit,
- xoffset + curve[4] * unit, yoffset + curve[5] * unit);
- break;
- case 8:
- ctx.bezierCurveTo(
- xoffset + curve[2] * unit, yoffset + curve[3] * unit,
- xoffset + curve[4] * unit, yoffset + curve[5] * unit,
- xoffset + curve[6] * unit, yoffset + curve[7] * unit);
- break;
- }
- if (curves == 2) ctx.strokeStyle = curves ? "red" : "blue";
- ctx.stroke();
- ctx.strokeStyle = "rgba(0,0,0, 0.3)";
- ctx.beginPath();
- ctx.moveTo(xoffset + curve[0] * unit, yoffset + curve[1] * unit);
- ctx.lineTo(xoffset + curve[2] * unit, yoffset + curve[3] * unit);
- ctx.lineTo(xoffset + curve[4] * unit, yoffset + curve[5] * unit);
- if (curve.length == 8)
- ctx.lineTo(xoffset + curve[6] * unit, yoffset + curve[7] * unit);
- ctx.stroke();
- }
- // optionally draw fat lines for curve
- if (fat1)
- drawFat(test[0], xoffset, yoffset, unit);
- if (fat2)
- drawFat(test[1], xoffset, yoffset, unit);
- if (ctl1)
- drawCtl(test[0], xoffset, yoffset, unit);
- if (ctl2)
- drawCtl(test[1], xoffset, yoffset, unit);
- if (ctlPts1)
- drawCtlPts(test[0], xoffset, yoffset, unit);
- if (ctlPts2)
- drawCtlPts(test[1], xoffset, yoffset, unit);
-}
-
-function drawCtl(curve, xoffset, yoffset, unit) {
- var last = curve.length - 2;
- ctx.strokeStyle = "rgba(0,0,0, 0.5)";
- ctx.beginPath();
- ctx.moveTo(xoffset + curve[0] * unit, yoffset + curve[1] * unit);
- ctx.lineTo(xoffset + curve[2] * unit, yoffset + curve[3] * unit);
- ctx.lineTo(xoffset + curve[4] * unit, yoffset + curve[5] * unit);
- ctx.stroke();
-}
-
-function drawCtlPts(curve, xoffset, yoffset, unit) {
- drawPoint(curve[0], curve[1], xoffset, yoffset, unit);
- drawPoint(curve[2], curve[3], xoffset, yoffset, unit);
- drawPoint(curve[4], curve[5], xoffset, yoffset, unit);
-}
-
-function drawFat(curve, xoffset, yoffset, unit) {
- var last = curve.length - 2;
- ctx.strokeStyle = "rgba(0,0,0, 0.5)";
- ctx.beginPath();
- ctx.moveTo(xoffset + curve[0] * unit, yoffset + curve[1] * unit);
- ctx.lineTo(xoffset + curve[last] * unit, yoffset + curve[last + 1] * unit);
- ctx.stroke();
- // draw line parallel to end points through control points
- var dx = curve[last] - curve[0];
- var dy = curve[last + 1] - curve[1];
- drawParallelLine(curve[2], curve[3], dx, dy, xoffset, yoffset, unit);
- if (curve.length == 8)
- drawParallelLine(curve[4], curve[5], dx, dy, xoffset, yoffset, unit);
-}
-
-function drawParallelLine(x, y, dx, dy, xoffset, yoffset, unit) {
- var x1 = x - dx;
- var y1 = y - dy;
- var x2 = x + dx;
- var y2 = y + dy;
- ctx.beginPath();
- ctx.moveTo(xoffset + x1 * unit, yoffset + y1 * unit);
- ctx.lineTo(xoffset + x2 * unit, yoffset + y2 * unit);
- ctx.stroke();
-}
-
-function drawTop() {
- init(tests[testIndex]);
- redraw();
-}
-
-function redraw() {
- ctx.beginPath();
- ctx.rect(0, 0, ctx.canvas.width, ctx.canvas.height);
- ctx.fillStyle="white";
- ctx.fill();
- draw(tests[testIndex], testTitles[testIndex], at_x, at_y, scale);
-}
-
-function doKeyPress(evt) {
- var char = String.fromCharCode(evt.charCode);
- switch (char) {
- case 'c':
- ctl2 ^= true;
- if (ctl2 == false)
- ctl1 ^= true;
- drawTop();
- break;
- case 'd':
- ctlPts2 ^= true;
- if (ctlPts2 == false)
- ctlPts1 ^= true;
- drawTop();
- break;
- case 'f':
- fat2 ^= true;
- if (fat2 == false)
- fat1 ^= true;
- drawTop();
- break;
- case 'N':
- testIndex += 9;
- case 'n':
- if (++testIndex >= tests.length)
- testIndex = 0;
- mouseX = Infinity;
- drawTop();
- break;
- case 'P':
- testIndex -= 9;
- case 'p':
- if (--testIndex < 0)
- testIndex = tests.length - 1;
- mouseX = Infinity;
- drawTop();
- break;
- }
-}
-
-function handleMouseClick() {
-}
-
-function handleMouseOver() {
-}
-
-function start() {
- for (i = 0; i < testDivs.length; ++i) {
- var title = testDivs[i].id.toString();
- var str = testDivs[i].firstChild.data;
- parse(str, title);
- }
- drawTop();
- window.addEventListener('keypress', doKeyPress, true);
- window.onresize = function() {
- drawTop();
- }
-}
-
-</script>
-</head>
-
-<body onLoad="start();">
-<canvas id="canvas" width="750" height="500"
- onmousemove="handleMouseOver()"
- onclick="handleMouseClick()"
- ></canvas >
-</body>
-</html>
diff --git a/experimental/Intersection/cd.htm b/experimental/Intersection/cd.htm
deleted file mode 100644
index 2e43022d7e..0000000000
--- a/experimental/Intersection/cd.htm
+++ /dev/null
@@ -1,517 +0,0 @@
-<html>
-<head>
-<div style="height:0">
-
-<div id="test1">
-computeDelta c1=(0,1 1,6 1,0 2,0) t1=0.0166500365 scale1=1 c2=(0,1 0,2 1,0 6,1) t2=0.126935168 scale2=1
-cubicTangent t=0.0166500365 tangent=(-2.85263545,-12.6745554 2.95089079,15.1559166) pt=(0.0491276698 1.24068063) dxy=(2.90176312 13.915236)
-cubicTangent t=0.126935168 tangent=(-0.852150487,0.242871519 0.961097194,2.2532568) pt=(0.0544733534 1.24806416) dxy=(0.90662384 1.00519264)
-cubicDelta tangent=(-0.00039510851,-0.00189471984 0.0495227783,1.24257535) intersectLen=0.00193547772 tangentLen=14.2145708 scale=0.00390625 result=0.00404241153
-cubicDelta tangent=(0.00495057512,0.00548880522 0.0495227783,1.24257535) intersectLen=0.00739156118 tangentLen=1.35365395 scale=0.00390625 result=0.00936670107
-</div>
-
-<div id="test2">
-computeDelta c1=(0,1 0,2 1,0 6,1) t1=0.121215914 scale1=0.0187334021 c2=(0,1 1,6 1,0 2,0) t2=0.0167515231 scale2=0.00808482306
-cubicTangent t=0.121215914 tangent=(-0.810112087,0.159501524 0.908958243,2.32468734) pt=(0.0494230781 1.24209443) dxy=(0.859535165 1.08259291)
-cubicTangent t=0.0167515231 tangent=(-2.85175241,-12.6666182 2.95059667,15.1508033) pt=(0.0494221303 1.24209251) dxy=(2.90117454 13.9087108)
-cubicDelta tangent=(7.4284882e-07,9.35625319e-07 0.0494223352,1.2420935) intersectLen=1.19466276e-06 tangentLen=1.38231983 scale=7.31773521e-05 result=7.40415969e-05
-cubicDelta tangent=(-2.04951629e-07,-9.82572016e-07 0.0494223352,1.2420935) intersectLen=1.00371955e-06 tangentLen=14.2080628 scale=3.15813401e-05 result=3.16519844e-05
-</div>
-
-<div id="test3">
-computeDelta c1=(0,1 1,6 1,0 2,0) t1=0.0167458976 scale1=6.33039689e-05 c2=(0,1 0,2 1,0 6,1) t2=0.121141872 scale2=0.000148083194
-cubicTangent t=0.0167458976 tangent=(-2.85180136,-12.6670582 2.95061297,15.1510867) pt=(0.0494058095 1.24201427) dxy=(2.90120716 13.9090724)
-cubicTangent t=0.121141872 tangent=(-0.809569955,0.158411583 0.908288874,2.32561689) pt=(0.0493594591 1.24201424) dxy=(0.858929414 1.08360265)
-cubicDelta tangent=(-1.65436799e-05,-7.93143093e-05 0.0494223532,1.24209358) intersectLen=8.1021312e-05 tangentLen=14.2084235 scale=2.47281129e-07 result=5.94962466e-06
-cubicDelta tangent=(-6.28940702e-05,-7.93454971e-05 0.0494223532,1.24209358) intersectLen=0.000101249059 tangentLen=1.38273441 scale=5.78449976e-07 result=7.38022436e-05
-</div>
-
-</div>
-
-<script type="text/javascript">
-
-var testDivs = [
- test3,
- test2,
- test1,
-];
-
-var scale, columns, rows, xStart, yStart;
-
-var ticks = 10;
-var at_x = 13 + 0.5;
-var at_y = 23 + 0.5;
-var decimal_places = 3;
-var tests = [];
-var testTitles = [];
-var testIndex = 0;
-var ctx;
-var minScale = 1;
-var subscale = 1;
-var curveT = -1;
-var drawCubics = true;
-var drawQuads = true;
-var drawControlLines = true;
-var drawT = true;
-
-var xmin, xmax, ymin, ymax;
-
-function strs_to_nums(strs) {
- var result = [];
- for (var idx in strs) {
- var str = strs[idx];
- var num = parseFloat(str);
- if (isNaN(num)) {
- result.push(str);
- } else {
- result.push(num);
- }
- }
- return result;
-}
-
-function construct_regexp(pattern) {
- var escape = pattern.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
- escape = escape.replace(/PT_VAL/g, "(-?\\d+\\.?\\d*e?-?\\d*),(-?\\d+\\.?\\d*e?-?\\d*)");
- escape = escape.replace(/T_VAL/g, "(-?\\d+\\.?\\d*e?-?\\d*)");
- escape = escape.replace(/IDX/g, "(\\d+)");
- escape = escape.replace(/OPT/g, "(\\?|-?\\d+)");
- return new RegExp(escape, 'i');
-}
-
-var COMPUTE_DELTA = 1;
-var CUBIC_TANGENT = 2;
-var CUBIC_DATA = 3;
-
-var DELTA_C1_X1 = 1;
-var DELTA_C1_Y1 = 2;
-var DELTA_C1_X2 = 3;
-var DELTA_C1_Y2 = 4;
-var DELTA_C1_X3 = 5;
-var DELTA_C1_Y3 = 6;
-var DELTA_C1_X4 = 7;
-var DELTA_C1_Y4 = 8;
-var DELTA_T1 = 9;
-var DELTA_SCALE1 = 10;
-var DELTA_C2_X1 = 11;
-var DELTA_C2_Y1 = 12;
-var DELTA_C2_X2 = 13;
-var DELTA_C2_Y2 = 14;
-var DELTA_C2_X3 = 15;
-var DELTA_C2_Y3 = 16;
-var DELTA_C2_X4 = 17;
-var DELTA_C2_Y4 = 18;
-var DELTA_T2 = 19;
-var DELTA_SCALE2 = 20;
-
-var TANGENT_T = 1;
-var TANGENT_TANGENT_X1 = 2;
-var TANGENT_TANGENT_Y1 = 3;
-var TANGENT_TANGENT_X2 = 4;
-var TANGENT_TANGENT_Y2 = 5;
-var TANGENT_PT_X = 6;
-var TANGENT_PT_Y = 7;
-var TANGENT_DXY_X = 8;
-var TANGENT_DXY_Y = 9;
-
-var CUBIC_TANGENT_X1 = 1;
-var CUBIC_TANGENT_Y1 = 2;
-var CUBIC_TANGENT_X2 = 3;
-var CUBIC_TANGENT_Y2 = 4;
-var CUBIC_INTERSECTION_LEN = 5;
-var CUBIC_TANGENT_LEN = 6;
-var CUBIC_SCALE = 7;
-var CUBIC_RESULT = 8;
-
-function parse(test, title) {
- var compute_delta = construct_regexp(" c1=(PT_VAL PT_VAL PT_VAL PT_VAL)"
- + " t1=T_VAL scale1=T_VAL c2=(PT_VAL PT_VAL PT_VAL PT_VAL) t2=T_VAL scale2=T_VAL");
- var cubic_tangent = construct_regexp(" t=T_VAL tangent=(PT_VAL PT_VAL)"
- + " pt=(T_VAL T_VAL) dxy=(T_VAL T_VAL)");
- var cubic_data = construct_regexp(" tangent=(PT_VAL PT_VAL)"
- + " intersectLen=T_VAL tangentLen=T_VAL scale=T_VAL result=T_VAL");
-
- var cStrs = test.split("computeDelta");
- var data = [];
- for (var cs in cStrs) {
- var str = cStrs[cs];
- if (str == "\n") {
- continue;
- }
- var tStrs = str.split("cubicTangent");
- for (var ts in tStrs) {
- str = tStrs[ts];
- if (str == "\n") {
- continue;
- }
- var dStrs = str.split("cubicDelta");
- var dataStrs;
- for (var ds in dStrs) {
- str = dStrs[ds];
- if (str == "\n") {
- continue;
- }
- var lineMatch, lineStrs;
- if (compute_delta.test(str)) {
- lineMatch = COMPUTE_DELTA;
- lineStrs = compute_delta.exec(str);
- } else if (cubic_tangent.test(str)) {
- lineMatch = CUBIC_TANGENT;
- lineStrs = cubic_tangent.exec(str);
- } else if (cubic_data.test(str)) {
- lineMatch = CUBIC_DATA;
- lineStrs = cubic_data.exec(str);
- } else {
- continue;
- }
- var line = strs_to_nums(lineStrs);
- data.push(lineMatch);
- data.push(line);
- }
- }
- }
- if (data.length >= 1) {
- tests.push(data);
- testTitles.push(title);
- }
-}
-
-function init(test) {
- var canvas = document.getElementById('canvas');
- if (!canvas.getContext) return;
- canvas.width = window.innerWidth - at_x;
- canvas.height = window.innerHeight - at_y;
- ctx = canvas.getContext('2d');
- xmin = Infinity;
- xmax = -Infinity;
- ymin = Infinity;
- ymax = -Infinity;
- var scanType = -1;
- for (var scansStr in test) {
- var scans = parseInt(scansStr);
- var scan = test[scans];
- if (scanType == -1) {
- scanType = scan;
- continue;
- }
- if (scanType == CUBIC_TANGENT) {
- for (var idx = TANGENT_TANGENT_X1; idx < TANGENT_PT_X; idx += 2) {
- xmin = Math.min(xmin, scan[idx]);
- xmax = Math.max(xmax, scan[idx]);
- ymin = Math.min(ymin, scan[idx + 1]);
- ymax = Math.max(ymax, scan[idx + 1]);
- }
- }
- scanType = -1;
- }
- var testW = xmax - xmin;
- var testH = ymax - ymin;
- subscale = 1;
- if (testW > 1e10 || testH > 1e10) {
- return;
- }
- while (testW * subscale < 0.1 && testH * subscale < 0.1) {
- subscale *= 10;
- }
- while (testW * subscale > 10 && testH * subscale > 10) {
- subscale /= 10;
- }
- calcFromScale();
-}
-
-function calcFromScale() {
- xStart = Math.floor(xmin * subscale) / subscale;
- yStart = Math.floor(ymin * subscale) / subscale;
- var xEnd = Math.ceil(xmin * subscale) / subscale;
- var yEnd = Math.ceil(ymin * subscale) / subscale;
- var cCelsW = Math.floor(ctx.canvas.width / 10);
- var cCelsH = Math.floor(ctx.canvas.height / 10);
- var testW = xEnd - xStart;
- var testH = yEnd - yStart;
- var scaleWH = 1;
- while (cCelsW > testW * scaleWH * 10 && cCelsH > testH * scaleWH * 10) {
- scaleWH *= 10;
- }
- while (cCelsW * 10 < testW * scaleWH && cCelsH * 10 < testH * scaleWH) {
- scaleWH /= 10;
- }
-
- columns = Math.ceil(xmax * subscale) - Math.floor(xmin * subscale) + 1;
- rows = Math.ceil(ymax * subscale) - Math.floor(ymin * subscale) + 1;
-
- var hscale = ctx.canvas.width / columns / ticks;
- var vscale = ctx.canvas.height / rows / ticks;
- minScale = Math.floor(Math.min(hscale, vscale));
- scale = minScale * subscale;
-}
-
-function drawPoint(px, py, xoffset, yoffset, unit) {
- var label = px.toFixed(decimal_places) + ", " + py.toFixed(decimal_places);
- var _px = px * unit + xoffset;
- var _py = py * unit + yoffset;
- ctx.beginPath();
- ctx.arc(_px, _py, 3, 0, Math.PI*2, true);
- ctx.closePath();
- ctx.fill();
- ctx.fillText(label, _px + 5, _py);
-}
-
-function drawTPt(scan, cIdx, tIdx, xoffset, yoffset, unit) {
- var t = scan[tIdx];
- var one_t = 1 - t;
- var one_t2 = one_t * one_t;
- var a = one_t2 * one_t;
- var b = 3 * one_t2 * t;
- var t2 = t * t;
- var c = 3 * one_t * t2;
- var d = t2 * t;
- var x = a * scan[cIdx + 0] + b * scan[cIdx + 2] + c * scan[cIdx + 4] + d * scan[cIdx + 6];
- var y = a * scan[cIdx + 1] + b * scan[cIdx + 3] + c * scan[cIdx + 5] + d * scan[cIdx + 7];
- drawPoint(x, y, xoffset, yoffset, unit);
-}
-
-function draw(test, title, scale) {
- ctx.fillStyle = "rgba(0,0,0, 0.1)";
- ctx.font = "normal 50px Arial";
- ctx.fillText(title, 50, 50);
- ctx.font = "normal 10px Arial";
-
- var unit = scale * ticks;
- ctx.lineWidth = 1;
- var i;
- for (i = 0; i <= rows * ticks; ++i) {
- ctx.strokeStyle = (i % ticks) != 0 ? "rgb(200,200,200)" : "black";
- ctx.beginPath();
- ctx.moveTo(at_x + 0, at_y + i * minScale);
- ctx.lineTo(at_x + ticks * columns * minScale, at_y + i * minScale);
- ctx.stroke();
- }
- for (i = 0; i <= columns * ticks; ++i) {
- ctx.strokeStyle = (i % ticks) != 0 ? "rgb(200,200,200)" : "black";
- ctx.beginPath();
- ctx.moveTo(at_x + i * minScale, at_y + 0);
- ctx.lineTo(at_x + i * minScale, at_y + ticks * rows * minScale);
- ctx.stroke();
- }
-
- var xoffset = xStart * -unit + at_x;
- var yoffset = yStart * -unit + at_y;
-
- ctx.fillStyle = "rgb(40,80,60)"
- for (i = 0; i <= columns; i += 1)
- {
- num = xStart + i / subscale;
- ctx.fillText(num.toFixed(decimal_places), xoffset + num * unit - 5, 10);
- }
- for (i = 0; i <= rows; i += 1)
- {
- num = yStart + i / subscale;
- ctx.fillText(num.toFixed(decimal_places), 0, yoffset + num * unit + 0);
- }
- var scanType = -1;
- var partIndex = 0;
- for (var scans in test) {
- var scan = test[scans];
- if (scanType == -1) {
- scanType = scan;
- continue;
- }
- partIndex++;
- if (scanType == COMPUTE_DELTA) {
- ctx.beginPath();
- ctx.moveTo(xoffset + scan[DELTA_C1_X1] * unit, yoffset + scan[DELTA_C1_Y1] * unit);
- ctx.bezierCurveTo(
- xoffset + scan[DELTA_C1_X2] * unit, yoffset + scan[DELTA_C1_Y2] * unit,
- xoffset + scan[DELTA_C1_X3] * unit, yoffset + scan[DELTA_C1_Y3] * unit,
- xoffset + scan[DELTA_C1_X4] * unit, yoffset + scan[DELTA_C1_Y4] * unit);
- ctx.strokeStyle = "red"; // "rgba(0,0,0, 1.0)";
- ctx.stroke();
- ctx.beginPath();
- ctx.moveTo(xoffset + scan[DELTA_C2_X1] * unit, yoffset + scan[DELTA_C2_Y1] * unit);
- ctx.bezierCurveTo(
- xoffset + scan[DELTA_C2_X2] * unit, yoffset + scan[DELTA_C2_Y2] * unit,
- xoffset + scan[DELTA_C2_X3] * unit, yoffset + scan[DELTA_C2_Y3] * unit,
- xoffset + scan[DELTA_C2_X4] * unit, yoffset + scan[DELTA_C2_Y4] * unit);
- ctx.strokeStyle = "blue"; // "rgba(0,0,0, 1.0)";
- ctx.stroke();
- }
- if (scanType == COMPUTE_DELTA && drawControlLines) {
- ctx.beginPath();
- ctx.moveTo(xoffset + scan[DELTA_C1_X1] * unit, yoffset + scan[DELTA_C1_Y1] * unit);
- ctx.lineTo(xoffset + scan[DELTA_C1_X2] * unit, yoffset + scan[DELTA_C1_Y2] * unit);
- ctx.lineTo(xoffset + scan[DELTA_C1_X3] * unit, yoffset + scan[DELTA_C1_Y3] * unit);
- ctx.lineTo(xoffset + scan[DELTA_C1_X4] * unit, yoffset + scan[DELTA_C1_Y4] * unit);
- ctx.strokeStyle = "rgba(0,0,0, 0.3)";
- ctx.stroke();
- ctx.beginPath();
- ctx.moveTo(xoffset + scan[DELTA_C2_X1] * unit, yoffset + scan[DELTA_C2_Y1] * unit);
- ctx.lineTo(xoffset + scan[DELTA_C2_X2] * unit, yoffset + scan[DELTA_C2_Y2] * unit);
- ctx.lineTo(xoffset + scan[DELTA_C2_X3] * unit, yoffset + scan[DELTA_C2_Y3] * unit);
- ctx.lineTo(xoffset + scan[DELTA_C2_X4] * unit, yoffset + scan[DELTA_C2_Y4] * unit);
- ctx.strokeStyle = "rgba(0,0,0, 0.3)";
- ctx.stroke();
- }
- if (scanType == COMPUTE_DELTA && drawT) {
- drawTPt(scan, DELTA_C1_X1, DELTA_T1, xoffset, yoffset, unit);
- drawTPt(scan, DELTA_C2_X1, DELTA_T2, xoffset, yoffset, unit);
- var num = "c1=" + scan[DELTA_T1].toFixed(decimal_places)
- + " c2=" + scan[DELTA_T2].toFixed(decimal_places);
- ctx.beginPath();
- ctx.rect(200,10,200,10);
- ctx.fillStyle="white";
- ctx.fill();
- ctx.fillStyle="black";
- ctx.fillText(num, 230, 18);
- }
- if (scanType == CUBIC_TANGENT) {
- ctx.beginPath();
- ctx.moveTo(xoffset + scan[TANGENT_TANGENT_X1] * unit, yoffset + scan[TANGENT_TANGENT_Y1] * unit);
- ctx.lineTo(xoffset + scan[TANGENT_TANGENT_X2] * unit, yoffset + scan[TANGENT_TANGENT_Y2] * unit);
- ctx.strokeStyle = partIndex > 2 ? "rgba(0,0,255, 0.7)" : "rgba(255,0,0, 0.7)";
- ctx.stroke();
- }
- scanType = -1;
- }
-}
-
-function drawTop() {
- init(tests[testIndex]);
- redraw();
-}
-
-function redraw() {
- ctx.beginPath();
- ctx.rect(0, 0, ctx.canvas.width, ctx.canvas.height);
- ctx.fillStyle="white";
- ctx.fill();
- draw(tests[testIndex], testTitles[testIndex], scale);
-}
-
-function doKeyPress(evt) {
- var char = String.fromCharCode(evt.charCode);
- switch (char) {
- case 'c':
- drawCubics ^= true;
- redraw();
- break;
- case 'd':
- decimal_places++;
- redraw();
- break;
- case 'D':
- decimal_places--;
- if (decimal_places < 1) {
- decimal_places = 1;
- }
- redraw();
- break;
- case 'l':
- drawControlLines ^= true;
- redraw();
- break;
- case 'N':
- testIndex += 9;
- case 'n':
- if (++testIndex >= tests.length)
- testIndex = 0;
- mouseX = Infinity;
- drawTop();
- break;
- case 'P':
- testIndex -= 9;
- case 'p':
- if (--testIndex < 0)
- testIndex = tests.length - 1;
- mouseX = Infinity;
- drawTop();
- break;
- case 'q':
- drawQuads ^= true;
- redraw();
- break;
- case 't':
- drawT ^= true;
- redraw();
- break;
- case 'x':
- drawCubics ^= true;
- drawQuads ^= true;
- redraw();
- break;
- case '-':
- case '_':
- subscale /= 2;
- calcFromScale();
- redraw();
- break;
- case '+':
- case '=':
- subscale *= 2;
- calcFromScale();
- redraw();
- break;
- }
-}
-
-/*
- var e = window.event;
- var tgt = e.target || e.srcElement;
- var min = tgt.offsetTop + Math.ceil(at_y);
- var max = min + ticks * rows * minScale;
- curveT = (e.clientY - min) / (max - min);
- redraw();
-}
-*/
-
-function calcXY() {
- var e = window.event;
- var tgt = e.target || e.srcElement;
- var left = tgt.offsetLeft;
- var top = tgt.offsetTop;
- var unit = scale * ticks;
- mouseX = (e.clientX - left - Math.ceil(at_x) + 1) / unit + xStart;
- mouseY = (e.clientY - top - Math.ceil(at_y)) / unit + yStart;
-}
-
-function handleMouseOver() {
- /* calcXY();
- var num = mouseX.toFixed(decimal_places) + ", " + mouseY.toFixed(decimal_places);
- ctx.beginPath();
- ctx.rect(30,10,200,10);
- ctx.fillStyle="white";
- ctx.fill();
- ctx.fillStyle="black";
- ctx.fillText(num, 30, 18);
-*/
-}
-
-function start() {
- for (i = 0; i < testDivs.length; ++i) {
- var title = testDivs[i].id.toString();
- var str = testDivs[i].firstChild.data;
- parse(str, title);
- }
- drawTop();
- window.addEventListener('keypress', doKeyPress, true);
- window.onresize = function() {
- drawTop();
- }
-}
-
-function handleMouseClick() {
- start();
-}
-
-function startx() {
-}
-
-</script>
-</head>
-
-<body onLoad="startx();">
-<canvas id="canvas" width="750" height="500"
- onmousemove="handleMouseOver()"
- onclick="handleMouseClick()"
- ></canvas >
-</body>
-</html>
diff --git a/experimental/Intersection/edge_Prefix.pch b/experimental/Intersection/edge_Prefix.pch
deleted file mode 100644
index dd26d56794..0000000000
--- a/experimental/Intersection/edge_Prefix.pch
+++ /dev/null
@@ -1,5 +0,0 @@
-//
-// Prefix header for all source files of the 'edge' target in the 'edge' project
-//
-
-#include <Carbon/Carbon.h>
diff --git a/experimental/Intersection/hg.htm b/experimental/Intersection/hg.htm
deleted file mode 100644
index 32f49a7446..0000000000
--- a/experimental/Intersection/hg.htm
+++ /dev/null
@@ -1,649 +0,0 @@
-<html>
-<head>
-<div style="height:0">
-
-<div id="cubic1">
-{{3.13,2.74}, {1.08,4.62}, {3.71,0.94}, {2.01,3.81}}
-{{6.71,3.14}, {7.99,2.75}, {8.27,1.96}, {6.35,3.57}}
-{{9.45,10.67}, {10.05,5.78}, {13.95,7.46}, {14.72,5.29}}
-{{3.34,8.98}, {1.95,10.27}, {3.76,7.65}, {4.96,10.64}}
-</div>
-
-</div>
-
-<script type="text/javascript">
-
-var testDivs = [
- cubic1,
-];
-
-var scale, columns, rows, xStart, yStart;
-
-var ticks = 10;
-var at_x = 13 + 0.5;
-var at_y = 23 + 0.5;
-var decimal_places = 3;
-var tests = [];
-var testTitles = [];
-var testIndex = 0;
-var ctx;
-var minScale = 1;
-var subscale = 1;
-var curveT = -1;
-var xmin, xmax, ymin, ymax;
-
-var mouseX, mouseY;
-var mouseDown = false;
-
-var draw_deriviatives = false;
-var draw_endpoints = true;
-var draw_hodo = false;
-var draw_hodo2 = false;
-var draw_hodo_origin = true;
-var draw_midpoint = false;
-var draw_tangents = true;
-var draw_sequence = true;
-
-function parse(test, title) {
- var curveStrs = test.split("{{");
- if (curveStrs.length == 1)
- curveStrs = test.split("=(");
- var pattern = /[a-z$=]?-?\d+\.*\d*e?-?\d*/g;
- var curves = [];
- for (var c in curveStrs) {
- var curveStr = curveStrs[c];
- var points = curveStr.match(pattern);
- var pts = [];
- for (var wd in points) {
- var num = parseFloat(points[wd]);
- if (isNaN(num)) continue;
- pts.push(num);
- }
- if (pts.length > 2)
- curves.push(pts);
- }
- if (curves.length >= 1) {
- tests.push(curves);
- testTitles.push(title);
- }
-}
-
-function init(test) {
- var canvas = document.getElementById('canvas');
- if (!canvas.getContext) return;
- canvas.width = window.innerWidth - 20;
- canvas.height = window.innerHeight - 20;
- ctx = canvas.getContext('2d');
- xmin = Infinity;
- xmax = -Infinity;
- ymin = Infinity;
- ymax = -Infinity;
- for (var curves in test) {
- var curve = test[curves];
- var last = curve.length;
- for (var idx = 0; idx < last; idx += 2) {
- xmin = Math.min(xmin, curve[idx]);
- xmax = Math.max(xmax, curve[idx]);
- ymin = Math.min(ymin, curve[idx + 1]);
- ymax = Math.max(ymax, curve[idx + 1]);
- }
- }
- xmin -= 1;
- var testW = xmax - xmin;
- var testH = ymax - ymin;
- subscale = 1;
- while (testW * subscale < 0.1 && testH * subscale < 0.1) {
- subscale *= 10;
- }
- while (testW * subscale > 10 && testH * subscale > 10) {
- subscale /= 10;
- }
- calcFromScale();
-}
-
-function hodograph(cubic) {
- var hodo = [];
- hodo[0] = 3 * (cubic[2] - cubic[0]);
- hodo[1] = 3 * (cubic[3] - cubic[1]);
- hodo[2] = 3 * (cubic[4] - cubic[2]);
- hodo[3] = 3 * (cubic[5] - cubic[3]);
- hodo[4] = 3 * (cubic[6] - cubic[4]);
- hodo[5] = 3 * (cubic[7] - cubic[5]);
- return hodo;
-}
-
-function hodograph2(cubic) {
- var quad = hodograph(cubic);
- var hodo = [];
- hodo[0] = 2 * (quad[2] - quad[0]);
- hodo[1] = 2 * (quad[3] - quad[1]);
- hodo[2] = 2 * (quad[4] - quad[2]);
- hodo[3] = 2 * (quad[5] - quad[3]);
- return hodo;
-}
-
-function quadraticRootsReal(A, B, C, s) {
- if (A == 0) {
- if (B == 0) {
- s[0] = 0;
- return C == 0;
- }
- s[0] = -C / B;
- return 1;
- }
- /* normal form: x^2 + px + q = 0 */
- var p = B / (2 * A);
- var q = C / A;
- var p2 = p * p;
- if (p2 < q) {
- return 0;
- }
- var sqrt_D = 0;
- if (p2 > q) {
- sqrt_D = sqrt(p2 - q);
- }
- s[0] = sqrt_D - p;
- s[1] = -sqrt_D - p;
- return 1 + s[0] != s[1];
-}
-
-function add_valid_ts(s, realRoots, t) {
- var foundRoots = 0;
- for (var index = 0; index < realRoots; ++index) {
- var tValue = s[index];
- if (tValue >= 0 && tValue <= 1) {
- for (var idx2 = 0; idx2 < foundRoots; ++idx2) {
- if (t[idx2] != tValue) {
- t[foundRoots++] = tValue;
- }
- }
- }
- }
- return foundRoots;
-}
-
-function quadraticRootsValidT(a, b, c, t) {
- var s = [];
- var realRoots = quadraticRootsReal(A, B, C, s);
- var foundRoots = add_valid_ts(s, realRoots, t);
- return foundRoots != 0;
-}
-
-function find_cubic_inflections(cubic, tValues)
-{
- var Ax = src[2] - src[0];
- var Ay = src[3] - src[1];
- var Bx = src[4] - 2 * src[2] + src[0];
- var By = src[5] - 2 * src[3] + src[1];
- var Cx = src[6] + 3 * (src[2] - src[4]) - src[0];
- var Cy = src[7] + 3 * (src[3] - src[5]) - src[1];
- return quadraticRootsValidT(Bx * Cy - By * Cx, (Ax * Cy - Ay * Cx),
- Ax * By - Ay * Bx, tValues);
-}
-
-function dx_at_t(cubic, t) {
- var one_t = 1 - t;
- var a = cubic[0];
- var b = cubic[2];
- var c = cubic[4];
- var d = cubic[6];
- return 3 * ((b - a) * one_t * one_t + 2 * (c - b) * t * one_t + (d - c) * t * t);
-}
-
-function dy_at_t(cubic, t) {
- var one_t = 1 - t;
- var a = cubic[1];
- var b = cubic[3];
- var c = cubic[5];
- var d = cubic[7];
- return 3 * ((b - a) * one_t * one_t + 2 * (c - b) * t * one_t + (d - c) * t * t);
-}
-
-function x_at_t(cubic, t) {
- var one_t = 1 - t;
- var one_t2 = one_t * one_t;
- var a = one_t2 * one_t;
- var b = 3 * one_t2 * t;
- var t2 = t * t;
- var c = 3 * one_t * t2;
- var d = t2 * t;
- return a * cubic[0] + b * cubic[2] + c * cubic[4] + d * cubic[6];
-}
-
-function y_at_t(cubic, t) {
- var one_t = 1 - t;
- var one_t2 = one_t * one_t;
- var a = one_t2 * one_t;
- var b = 3 * one_t2 * t;
- var t2 = t * t;
- var c = 3 * one_t * t2;
- var d = t2 * t;
- return a * cubic[1] + b * cubic[3] + c * cubic[5] + d * cubic[7];
-}
-
-function calcFromScale() {
- xStart = Math.floor(xmin * subscale) / subscale;
- yStart = Math.floor(ymin * subscale) / subscale;
- var xEnd = Math.ceil(xmin * subscale) / subscale;
- var yEnd = Math.ceil(ymin * subscale) / subscale;
- var cCelsW = Math.floor(ctx.canvas.width / 10);
- var cCelsH = Math.floor(ctx.canvas.height / 10);
- var testW = xEnd - xStart;
- var testH = yEnd - yStart;
- var scaleWH = 1;
- while (cCelsW > testW * scaleWH * 10 && cCelsH > testH * scaleWH * 10) {
- scaleWH *= 10;
- }
- while (cCelsW * 10 < testW * scaleWH && cCelsH * 10 < testH * scaleWH) {
- scaleWH /= 10;
- }
-
- columns = Math.ceil(xmax * subscale) - Math.floor(xmin * subscale) + 1;
- rows = Math.ceil(ymax * subscale) - Math.floor(ymin * subscale) + 1;
-
- var hscale = ctx.canvas.width / columns / ticks;
- var vscale = ctx.canvas.height / rows / ticks;
- minScale = Math.floor(Math.min(hscale, vscale));
- scale = minScale * subscale;
-}
-
-function drawLine(x1, y1, x2, y2) {
- var unit = scale * ticks;
- var xoffset = xStart * -unit + at_x;
- var yoffset = yStart * -unit + at_y;
- ctx.beginPath();
- ctx.moveTo(xoffset + x1 * unit, yoffset + y1 * unit);
- ctx.lineTo(xoffset + x2 * unit, yoffset + y2 * unit);
- ctx.stroke();
-}
-
-function drawPoint(px, py) {
- var unit = scale * ticks;
- var xoffset = xStart * -unit + at_x;
- var yoffset = yStart * -unit + at_y;
- var _px = px * unit + xoffset;
- var _py = py * unit + yoffset;
- ctx.beginPath();
- ctx.arc(_px, _py, 3, 0, Math.PI*2, true);
- ctx.closePath();
- ctx.stroke();
-}
-
-function drawPointSolid(px, py) {
- drawPoint(px, py);
- ctx.fillStyle = "rgba(0,0,0, 0.4)";
- ctx.fill();
-}
-
-function drawLabel(num, px, py) {
- ctx.beginPath();
- ctx.arc(px, py, 8, 0, Math.PI*2, true);
- ctx.closePath();
- ctx.strokeStyle = "rgba(0,0,0, 0.4)";
- ctx.lineWidth = num == 0 || num == 3 ? 2 : 1;
- ctx.stroke();
- ctx.fillStyle = "black";
- ctx.font = "normal 10px Arial";
- // ctx.rotate(0.001);
- ctx.fillText(num, px - 2, py + 3);
- // ctx.rotate(-0.001);
-}
-
-function drawLabelX(ymin, num, loc) {
- var unit = scale * ticks;
- var xoffset = xStart * -unit + at_x;
- var yoffset = yStart * -unit + at_y;
- var px = loc * unit + xoffset;
- var py = ymin * unit + yoffset - 20;
- drawLabel(num, px, py);
-}
-
-function drawLabelY(xmin, num, loc) {
- var unit = scale * ticks;
- var xoffset = xStart * -unit + at_x;
- var yoffset = yStart * -unit + at_y;
- var px = xmin * unit + xoffset - 20;
- var py = loc * unit + yoffset;
- drawLabel(num, px, py);
-}
-
-function drawHodoOrigin(hx, hy, hMinX, hMinY, hMaxX, hMaxY) {
- ctx.beginPath();
- ctx.moveTo(hx, hy - 100);
- ctx.lineTo(hx, hy);
- ctx.strokeStyle = hMinY < 0 ? "green" : "blue";
- ctx.stroke();
- ctx.beginPath();
- ctx.moveTo(hx, hy);
- ctx.lineTo(hx, hy + 100);
- ctx.strokeStyle = hMaxY > 0 ? "green" : "blue";
- ctx.stroke();
- ctx.beginPath();
- ctx.moveTo(hx - 100, hy);
- ctx.lineTo(hx, hy);
- ctx.strokeStyle = hMinX < 0 ? "green" : "blue";
- ctx.stroke();
- ctx.beginPath();
- ctx.moveTo(hx, hy);
- ctx.lineTo(hx + 100, hy);
- ctx.strokeStyle = hMaxX > 0 ? "green" : "blue";
- ctx.stroke();
-}
-
-function logCurves(test) {
- for (curves in test) {
- var curve = test[curves];
- if (curve.length != 8) {
- continue;
- }
- var str = "{{";
- for (i = 0; i < 8; i += 2) {
- str += curve[i].toFixed(2) + "," + curve[i + 1].toFixed(2);
- if (i < 6) {
- str += "}, {";
- }
- }
- str += "}}";
- console.log(str);
- }
-}
-
-function scalexy(x, y, mag) {
- var length = Math.sqrt(x * x + y * y);
- return mag / length;
-}
-
-function drawArrow(x, y, dx, dy) {
- var unit = scale * ticks;
- var xoffset = xStart * -unit + at_x;
- var yoffset = yStart * -unit + at_y;
- var dscale = scalexy(dx, dy, 1);
- dx *= dscale;
- dy *= dscale;
- ctx.beginPath();
- ctx.moveTo(xoffset + x * unit, yoffset + y * unit);
- x += dx;
- y += dy;
- ctx.lineTo(xoffset + x * unit, yoffset + y * unit);
- dx /= 10;
- dy /= 10;
- ctx.lineTo(xoffset + (x - dy) * unit, yoffset + (y + dx) * unit);
- ctx.lineTo(xoffset + (x + dx * 2) * unit, yoffset + (y + dy * 2) * unit);
- ctx.lineTo(xoffset + (x + dy) * unit, yoffset + (y - dx) * unit);
- ctx.lineTo(xoffset + x * unit, yoffset + y * unit);
- ctx.strokeStyle = "rgba(0,75,0, 0.4)";
- ctx.stroke();
-}
-
-function draw(test, title) {
- ctx.fillStyle = "rgba(0,0,0, 0.1)";
- ctx.font = "normal 50px Arial";
- ctx.fillText(title, 50, 50);
- ctx.font = "normal 10px Arial";
- var unit = scale * ticks;
- // ctx.lineWidth = "1.001"; "0.999";
- var xoffset = xStart * -unit + at_x;
- var yoffset = yStart * -unit + at_y;
-
- for (curves in test) {
- var curve = test[curves];
- if (curve.length != 8) {
- continue;
- }
- ctx.lineWidth = 1;
- if (draw_tangents) {
- ctx.strokeStyle = "rgba(0,0,255, 0.3)";
- drawLine(curve[0], curve[1], curve[2], curve[3]);
- drawLine(curve[2], curve[3], curve[4], curve[5]);
- drawLine(curve[4], curve[5], curve[6], curve[7]);
- }
- if (draw_deriviatives) {
- var dx = dx_at_t(curve, 0);
- var dy = dy_at_t(curve, 0);
- drawArrow(curve[0], curve[1], dx, dy);
- dx = dx_at_t(curve, 1);
- dy = dy_at_t(curve, 1);
- drawArrow(curve[6], curve[7], dx, dy);
- if (draw_midpoint) {
- var midX = x_at_t(curve, 0.5);
- var midY = y_at_t(curve, 0.5);
- dx = dx_at_t(curve, 0.5);
- dy = dy_at_t(curve, 0.5);
- drawArrow(midX, midY, dx, dy);
- }
- }
- ctx.beginPath();
- ctx.moveTo(xoffset + curve[0] * unit, yoffset + curve[1] * unit);
- ctx.bezierCurveTo(
- xoffset + curve[2] * unit, yoffset + curve[3] * unit,
- xoffset + curve[4] * unit, yoffset + curve[5] * unit,
- xoffset + curve[6] * unit, yoffset + curve[7] * unit);
- ctx.strokeStyle = "black";
- ctx.stroke();
- if (draw_endpoints) {
- drawPoint(curve[0], curve[1]);
- drawPoint(curve[2], curve[3]);
- drawPoint(curve[4], curve[5]);
- drawPoint(curve[6], curve[7]);
- }
- if (draw_midpoint) {
- var midX = x_at_t(curve, 0.5);
- var midY = y_at_t(curve, 0.5);
- drawPointSolid(midX, midY);
- }
- if (draw_hodo) {
- var hodo = hodograph(curve);
- var hMinX = Math.min(0, hodo[0], hodo[2], hodo[4]);
- var hMinY = Math.min(0, hodo[1], hodo[3], hodo[5]);
- var hMaxX = Math.max(0, hodo[0], hodo[2], hodo[4]);
- var hMaxY = Math.max(0, hodo[1], hodo[3], hodo[5]);
- var hScaleX = hMaxX - hMinX > 0 ? ctx.canvas.width / (hMaxX - hMinX) : 1;
- var hScaleY = hMaxY - hMinY > 0 ? ctx.canvas.height / (hMaxY - hMinY) : 1;
- var hUnit = Math.min(hScaleX, hScaleY);
- hUnit /= 2;
- var hx = xoffset - hMinX * hUnit;
- var hy = yoffset - hMinY * hUnit;
- ctx.moveTo(hx + hodo[0] * hUnit, hy + hodo[1] * hUnit);
- ctx.quadraticCurveTo(
- hx + hodo[2] * hUnit, hy + hodo[3] * hUnit,
- hx + hodo[4] * hUnit, hy + hodo[5] * hUnit);
- ctx.strokeStyle = "red";
- ctx.stroke();
- if (draw_hodo_origin) {
- drawHodoOrigin(hx, hy, hMinX, hMinY, hMaxX, hMaxY);
- }
- }
- if (draw_hodo2) {
- var hodo = hodograph2(curve);
- var hMinX = Math.min(0, hodo[0], hodo[2]);
- var hMinY = Math.min(0, hodo[1], hodo[3]);
- var hMaxX = Math.max(0, hodo[0], hodo[2]);
- var hMaxY = Math.max(0, hodo[1], hodo[3]);
- var hScaleX = hMaxX - hMinX > 0 ? ctx.canvas.width / (hMaxX - hMinX) : 1;
- var hScaleY = hMaxY - hMinY > 0 ? ctx.canvas.height / (hMaxY - hMinY) : 1;
- var hUnit = Math.min(hScaleX, hScaleY);
- hUnit /= 2;
- var hx = xoffset - hMinX * hUnit;
- var hy = yoffset - hMinY * hUnit;
- ctx.moveTo(hx + hodo[0] * hUnit, hy + hodo[1] * hUnit);
- ctx.lineTo(hx + hodo[2] * hUnit, hy + hodo[3] * hUnit);
- ctx.strokeStyle = "red";
- ctx.stroke();
- drawHodoOrigin(hx, hy, hMinX, hMinY, hMaxX, hMaxY);
- }
- if (draw_sequence) {
- var ymin = Math.min(curve[1], curve[3], curve[5], curve[7]);
- for (var i = 0; i < 8; i+= 2) {
- drawLabelX(ymin, i >> 1, curve[i]);
- }
- var xmin = Math.min(curve[0], curve[2], curve[4], curve[6]);
- for (var i = 1; i < 8; i+= 2) {
- drawLabelY(xmin, i >> 1, curve[i]);
- }
- }
- }
-}
-
-function drawTop() {
- init(tests[testIndex]);
- redraw();
-}
-
-function redraw() {
- ctx.beginPath();
- ctx.rect(0, 0, ctx.canvas.width, ctx.canvas.height);
- ctx.fillStyle="white";
- ctx.fill();
- draw(tests[testIndex], testTitles[testIndex]);
-}
-
-function doKeyPress(evt) {
- var char = String.fromCharCode(evt.charCode);
- switch (char) {
- case '2':
- draw_hodo2 ^= true;
- redraw();
- break;
- case 'd':
- draw_deriviatives ^= true;
- redraw();
- break;
- case 'e':
- draw_endpoints ^= true;
- redraw();
- break;
- case 'h':
- draw_hodo ^= true;
- redraw();
- break;
- case 'N':
- testIndex += 9;
- case 'n':
- if (++testIndex >= tests.length)
- testIndex = 0;
- drawTop();
- break;
- case 'l':
- logCurves(tests[testIndex]);
- break;
- case 'm':
- draw_midpoint ^= true;
- redraw();
- break;
- case 'o':
- draw_hodo_origin ^= true;
- redraw();
- break;
- case 'P':
- testIndex -= 9;
- case 'p':
- if (--testIndex < 0)
- testIndex = tests.length - 1;
- drawTop();
- break;
- case 's':
- draw_sequence ^= true;
- redraw();
- break;
- case 't':
- draw_tangents ^= true;
- redraw();
- break;
- }
-}
-
-function calcXY() {
- var e = window.event;
- var tgt = e.target || e.srcElement;
- var left = tgt.offsetLeft;
- var top = tgt.offsetTop;
- var unit = scale * ticks;
- mouseX = (e.clientX - left - Math.ceil(at_x) + 1) / unit + xStart;
- mouseY = (e.clientY - top - Math.ceil(at_y)) / unit + yStart;
-}
-
-var lastX, lastY;
-var activeCurve = [];
-var activePt;
-
-function handleMouseClick() {
- calcXY();
-}
-
-function initDown() {
- var unit = scale * ticks;
- var xoffset = xStart * -unit + at_x;
- var yoffset = yStart * -unit + at_y;
- var test = tests[testIndex];
- var bestDistance = 1000000;
- activePt = -1;
- for (curves in test) {
- var testCurve = test[curves];
- if (testCurve.length != 8) {
- continue;
- }
- for (var i = 0; i < 8; i += 2) {
- var testX = testCurve[i];
- var testY = testCurve[i + 1];
- var dx = testX - mouseX;
- var dy = testY - mouseY;
- var dist = dx * dx + dy * dy;
- if (dist > bestDistance) {
- continue;
- }
- activeCurve = testCurve;
- activePt = i;
- bestDistance = dist;
- }
- }
- if (activePt >= 0) {
- lastX = mouseX;
- lastY = mouseY;
- }
-}
-
-function handleMouseOver() {
- if (!mouseDown) {
- activePt = -1;
- return;
- }
- calcXY();
- if (activePt < 0) {
- initDown();
- return;
- }
- var unit = scale * ticks;
- var deltaX = (mouseX - lastX) /* / unit */;
- var deltaY = (mouseY - lastY) /*/ unit */;
- lastX = mouseX;
- lastY = mouseY;
- activeCurve[activePt] += deltaX;
- activeCurve[activePt + 1] += deltaY;
- redraw();
-}
-
-function start() {
- for (i = 0; i < testDivs.length; ++i) {
- var title = testDivs[i].id.toString();
- var str = testDivs[i].firstChild.data;
- parse(str, title);
- }
- drawTop();
- window.addEventListener('keypress', doKeyPress, true);
- window.onresize = function() {
- drawTop();
- }
-}
-
-</script>
-</head>
-
-<body onLoad="start();">
-<canvas id="canvas" width="750" height="500"
- onmousedown="mouseDown = true"
- onmouseup="mouseDown = false"
- onmousemove="handleMouseOver()"
- onclick="handleMouseClick()"
- ></canvas >
-</body>
-</html>
diff --git a/experimental/Intersection/op.htm b/experimental/Intersection/op.htm
deleted file mode 100644
index 2fc5577f83..0000000000
--- a/experimental/Intersection/op.htm
+++ /dev/null
@@ -1,4806 +0,0 @@
-<!-- path visualizer -->
-<html>
-<head>
-<div style="height:0">
-
-<div id="testSimplifyQuadratic1">
- SkPath path, out;
- path.moveTo(0, 0);
- path.quadTo(1, 0, 1, 1);
- path.close();
- path.moveTo(1, 0);
- path.quadTo(0, 0, 0, 1);
- path.close();
- testSimplify(path, true, out, bitmap);
-}
-</div>
-
-<div id="testSimplifyQuadratic2">
- SkPath path, out;
- path.moveTo(0, 0);
- path.quadTo(20, 0, 20, 20);
- path.close();
- path.moveTo(20, 0);
- path.quadTo(0, 0, 0, 20);
- path.close();
- testSimplify(path, true, out, bitmap);
-}
-</div>
-
-<div id="testSimplifyQuadratic3">
- SkPath path, out;
- path.moveTo(0, 0);
- path.quadTo(20, 0, 20, 20);
- path.close();
- path.moveTo(0, 20);
- path.quadTo(0, 0, 20, 0);
- path.close();
- testSimplify(path, true, out, bitmap);
-}
-</div>
-
-<div id="testSimplifyQuadratic4">
- SkPath path, out;
- path.moveTo(0, 20);
- path.quadTo(20, 0, 40, 20);
- path.close();
- path.moveTo(40, 10);
- path.quadTo(20, 30, 0, 10);
- path.close();
- testSimplify(path, true, out, bitmap);
- drawAsciiPaths(path, out, true);
-}
-</div>
-
-<div id="testSimplifyQuadratic5">
- SkPath path, out;
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.lineTo(0, 0);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(0, 0, 0, 1);
- path.close();
- testSimplify(path, true, out, bitmap);
- drawAsciiPaths(path, out, true);
-}
-</div>
-
-<div id="testSimplifyQuadratic6">
- SkPath path, out;
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.lineTo(1, 0);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(1, 0, 0, 1);
- path.close();
- testSimplify(path, true, out, bitmap);
- drawAsciiPaths(path, out, true);
-}
-</div>
-
-<div id="testSimplifyQuadratic7">
- SkPath path, out;
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.lineTo(0, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(1, 0, 0, 2);
- path.close();
- testSimplify(path, true, out, bitmap);
- drawAsciiPaths(path, out, true);
-}
-</div>
-
-<div id="testSimplifyQuadratic8">
- SkPath path, out;
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.lineTo(0, 0);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(1, 0, 0, 2);
- path.close();
- testSimplify(path, true, out, bitmap);
- drawAsciiPaths(path, out, true);
-}
-</div>
-
-<div id="testSimplifyQuadratic9">
- SkPath path, out;
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.lineTo(1, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(1, 0, 2, 2);
- path.close();
- testSimplify(path, true, out, bitmap);
- drawAsciiPaths(path, out, true);
-}
-</div>
-
-<div id="testSimplifyQuadratic10">
- SkPath path, out;
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.lineTo(0, 0);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 1);
- path.quadTo(1, 1, 1, 2);
- path.close();
- testSimplify(path, true, out, bitmap);
- drawAsciiPaths(path, out, true);
-}
-</div>
-
-<div id="testSimplifyQuadratic11">
- SkPath path, out;
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.lineTo(0, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(2, 1);
- path.quadTo(2, 2, 3, 3);
- path.close();
- testSimplify(path, true, out, bitmap);
- drawAsciiPaths(path, out, true);
-}
-</div>
-
-<div id="testSimplifyQuadratic12">
- SkPath path, out;
- path.moveTo(0, 0);
- path.lineTo(0, 2);
- path.lineTo(0, 0);
- path.close();
- path.moveTo(3, 0);
- path.quadTo(1, 1, 0, 2);
- path.lineTo(3, 0);
- path.close();
- testSimplify(path, true, out, bitmap);
- drawAsciiPaths(path, out, true);
-}
-</div>
-
-<div id="testSimplifyQuadratic13">
- SkPath path, out;
-path.moveTo(0, 0);
-path.quadTo(0, 0, 1, 0);
-path.lineTo(1, 1);
-path.lineTo(0, 0);
-path.close();
-path.moveTo(0, 0);
-path.quadTo(3, 0, 1, 1);
-path.lineTo(0, 0);
-path.close();
- testSimplify(path, true, out, bitmap);
- drawAsciiPaths(path, out, true);
-}
-</div>
-
-<div id="testSimplifyQuadratic14">
- SkPath path, out;
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.lineTo(1, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(0, 1, 2, 1);
- path.close();
- testSimplify(path, true, out, bitmap);
- drawAsciiPaths(path, out, true);
-}
-</div>
-
-<div id="testSimplifyQuadratic15">
- SkPath path, out;
- path.moveTo(0, 0);
- path.quadTo(0, 0, 1, 3);
- path.lineTo(3, 3);
- path.close();
- path.moveTo(0, 1);
- path.lineTo(1, 1);
- path.quadTo(0, 3, 3, 3);
- path.close();
- testSimplify(path, true, out, bitmap);
- drawAsciiPaths(path, out, true);
-}
-</div>
-
-<div id="testSimplifyQuadratic16">
- SkPath path, out;
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.lineTo(0, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(1, 0, 0, 1);
- path.close();
- testSimplify(path, true, out, bitmap);
- drawAsciiPaths(path, out, true);
-}
-</div>
-
-<div id="testSimplifyQuadratic17">
- SkPath path, out;
- path.moveTo(8, 8);
- path.quadTo(10, 10, 8, -10);
- path.close();
- path.moveTo(8, 8);
- path.quadTo(12, 12, 14, 4);
- path.close();
- path.moveTo(8, 8);
- path.quadTo(9, 9, 10, 8);
- path.close();
- testSimplify(path, true, out, bitmap);
- drawAsciiPaths(path, out, true);
-}
-</div>
-
-<div id="testSimplifyQuadratic18">
- SkPath path, out;
- path.moveTo(8.0000000000000071, 8.0000000000000071);
- path.quadTo(8.7289570079366854, 8.7289570079366889, 9.3914917259458743, 9.0593802763083691);
- path.close();
- path.moveTo(8.0000000000000142, 8.0000000000000142);
- path.quadTo(8.1250000000000107, 8.1250000000000071, 8.2500000000000071, 8.2187500000000053);
- path.close();
- testSimplify(path, true, out, bitmap);
- drawAsciiPaths(path, out, true);
-</div>
-
-<div id="testSimplifyQuadratic19">
- SkPath path, simple;
- path.moveTo(0,4);
- path.lineTo(6,4);
- path.lineTo(3,1);
- path.close();
- path.moveTo(2,3);
- path.lineTo(3,2);
- path.lineTo(4,3);
- path.close();
- testSimplifyx(path);
-</div>
-
-<div id="testSimplifyQuadratic20">
- SkPath path, simple;
- path.moveTo(0,4);
- path.lineTo(6,4);
- path.lineTo(3,1);
- path.close();
- path.moveTo(2,3);
- path.lineTo(4,3);
- path.lineTo(3,2);
- path.close();
- testSimplifyx(path);
-</div>
-
-<div id="testSimplifyQuadratic21">
- SkPath path, simple;
- path.moveTo(0,4);
- path.lineTo(8,4);
- path.lineTo(4,0);
- path.close();
- path.moveTo(2,2);
- path.lineTo(3,3);
- path.lineTo(4,2);
- path.close();
- testSimplifyx(path);
-</div>
-
-<div id="testLine5">
- path.moveTo(3,0);
- path.lineTo(6,2);
- path.lineTo(0,2);
- path.close();
- path.moveTo(3,0);
- path.lineTo(6,2);
- path.lineTo(0,2);
- path.close();
-</div>
-
-<div id="testLine6">
- SkPath path, simple;
- path.moveTo(0,0);
- path.lineTo(4,0);
- path.lineTo(2,2);
- path.close();
- path.moveTo(2,0);
- path.lineTo(6,0);
- path.lineTo(4,2);
- path.close();
- testSimplifyx(path);
-</div>
-
-<div id="testLine7">
- SkPath path, simple;
- path.moveTo(0,0);
- path.lineTo(4,0);
- path.lineTo(2,2);
- path.close();
- path.moveTo(6,0);
- path.lineTo(2,0);
- path.lineTo(4,2);
- path.close();
- testSimplifyx(path);
-</div>
-
-<div id="testLine7b">
- path.moveTo(0,0);
- path.lineTo(4,0);
- path.close();
- path.moveTo(6,0);
- path.lineTo(2,0);
- path.lineTo(4,2);
- path.close();
-</div>
-
-<div id="testLine9">
- SkPath path, simple;
- path.moveTo(0,4);
- path.lineTo(4,4);
- path.lineTo(2,2);
- path.close();
- path.moveTo(6,4);
- path.lineTo(2,4);
- path.lineTo(4,2);
- path.close();
- testSimplifyx(path);
-</div>
-
-<div id="testLine12">
- path.moveTo(0,4);
- path.lineTo(6,4);
- path.lineTo(3,1);
- path.close();
- path.moveTo(2,3);
- path.lineTo(3,2);
- path.lineTo(4,3);
- path.close();
-</div>
-
-<div id="testLine13">
- path.moveTo(6,4);
- path.lineTo(0,4);
- path.lineTo(3,1);
- path.close();
- path.moveTo(3,2);
- path.lineTo(2,3);
- path.lineTo(4,3);
- path.close();
-</div>
-
-<div id="testLine16">
- path.addRect(0, 0, 12, 12, SkPath::kCW_Direction);
- path.addRect(0, 4, 9, 9, SkPath::kCW_Direction);
-</div>
-
-<div id="testLine17">
- SkPath path, simple;
- path.addRect(0, 0, 12, 12, SkPath::kCW_Direction);
- path.addRect(4, 12, 13, 13, SkPath::kCW_Direction);
- testSimplifyx(path);
-</div>
-
-<div id="testLine19">
- SkPath path, simple;
- path.addRect(0, 0, 12, 12, SkPath::kCW_Direction);
- path.addRect(12, 16, 21, 21, SkPath::kCW_Direction);
- testSimplifyx(path);
-</div>
-
-<div id="testLine22">
- path.addRect(0, 12, 12, 12, SkPath::kCW_Direction);
- path.addRect(4, 12, 13, 13, SkPath::kCW_Direction);
-</div>
-
-<div id="testLine24">
- path.addRect(0, 18, 12, 12, SkPath::kCW_Direction);
- path.addRect(4, 12, 13, 13, SkPath::kCW_Direction);
-</div>
-
-<div id="testLine28">
- SkPath path, simple;
- path.addRect(0, 6, 12, 12, SkPath::kCW_Direction);
- path.addRect(0, 0, 9, 9, SkPath::kCW_Direction);
- testSimplifyx(path);
-</div>
-
-<div id="testLine29">
- SkPath path, simple;
- path.addRect(0, 18, 12, 12, SkPath::kCW_Direction);
- path.addRect(12, 12, 21, 21, SkPath::kCW_Direction);
- testSimplifyx(path);
-</div>
-
-<div id="testLine30">
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 0, 12, 12, SkPath::kCW_Direction);
- path.addRect(4, 4, 13, 13, SkPath::kCW_Direction);
-</div>
-
-<div id="testLine31">
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 0, 12, 12, SkPath::kCW_Direction);
- path.addRect(0, 4, 9, 9, SkPath::kCW_Direction);
-</div>
-
-<div id="testLine32">
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 0, 12, 12, SkPath::kCW_Direction);
- path.addRect(4, 12, 13, 13, SkPath::kCW_Direction);
-</div>
-
-<div id="testLine33">
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 0, 12, 12, SkPath::kCW_Direction);
- path.addRect(4, 16, 13, 13, SkPath::kCW_Direction);
-</div>
-
-<div id="testLine34">
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 6, 12, 12, SkPath::kCW_Direction);
- path.addRect(4, 12, 13, 13, SkPath::kCW_Direction);
-</div>
-
-<div id="testLine35">
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(6, 0, 18, 18, SkPath::kCW_Direction);
- path.addRect(4, 16, 13, 13, SkPath::kCW_Direction);
-</div>
-
-<div id="testLine36">
- path.addRect(0, 10, 20, 20, SkPath::kCW_Direction);
- path.addRect(6, 12, 18, 18, SkPath::kCW_Direction);
- path.addRect(4, 16, 13, 13, SkPath::kCW_Direction);
-</div>
-
-<div id="testLine37">
- path.addRect(0, 20, 20, 20, SkPath::kCW_Direction);
- path.addRect(18, 24, 30, 30, SkPath::kCW_Direction);
- path.addRect(0, 0, 9, 9, SkPath::kCW_Direction);
-</div>
-
-<div id="testLine38">
- path.addRect(10, 0, 30, 30, SkPath::kCW_Direction);
- path.addRect(6, 12, 18, 18, SkPath::kCW_Direction);
- path.addRect(12, 12, 21, 21, SkPath::kCW_Direction);
-</div>
-
-<div id="testLine39">
- path.addRect(10, 0, 30, 30, SkPath::kCW_Direction);
- path.addRect(12, 6, 24, 24, SkPath::kCW_Direction);
- path.addRect(12, 4, 21, 21, SkPath::kCW_Direction);
-</div>
-
-<div id="testLine40">
- path.addRect(10, 0, 30, 30, SkPath::kCW_Direction);
- path.addRect(12, 18, 24, 24, SkPath::kCW_Direction);
- path.addRect(4, 16, 13, 13, SkPath::kCW_Direction);
-</div>
-
-<div id="testLine41">
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(18, 24, 30, 30, SkPath::kCW_Direction);
- path.addRect(12, 0, 21, 21, SkPath::kCW_Direction);
-</div>
-
-<div id="testLine42">
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 0, 12, 12, SkPath::kCW_Direction);
- path.addRect(8, 16, 17, 17, SkPath::kCW_Direction);
-</div>
-
-<div id="testLine43">
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(6, 24, 18, 18, SkPath::kCW_Direction);
- path.addRect(0, 32, 9, 36, SkPath::kCCW_Direction);
-</div>
-
-<div id="testLine44">
- path.addRect(10, 40, 30, 30, SkPath::kCW_Direction);
- path.addRect(18, 0, 30, 30, SkPath::kCW_Direction);
- path.addRect(18, 32, 27, 36, SkPath::kCCW_Direction);
-</div>
-
-<div id="testLine45">
- path.addRect(10, 0, 30, 30, SkPath::kCW_Direction);
- path.addRect(18, 0, 30, 30, SkPath::kCW_Direction);
- path.addRect(24, 32, 33, 36, SkPath::kCW_Direction);
-</div>
-
-<div id="testLine46">
- path.addRect(10, 40, 30, 30, SkPath::kCW_Direction);
- path.addRect(24, 0, 36, 36, SkPath::kCW_Direction);
- path.addRect(24, 32, 33, 36, SkPath::kCW_Direction);
-</div>
-
-<div id="testLine47">
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 0, 12, 12, SkPath::kCW_Direction);
- path.addRect(0, 0, 9, 9, SkPath::kCCW_Direction);
-</div>
-
-<div id="testLine48">
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 6, 12, 12, SkPath::kCW_Direction);
- path.addRect(0, 0, 9, 9, SkPath::kCCW_Direction);
-</div>
-
-<div id="testLine49">
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 0, 12, 12, SkPath::kCW_Direction);
- path.addRect(0, 0, 9, 9, SkPath::kCW_Direction);
-</div>
-
-<div id="testLine50">
- path.addRect(10, 30, 30, 30, SkPath::kCW_Direction);
- path.addRect(24, 20, 36, 30, SkPath::kCW_Direction);
-</div>
-
-<div id="testLine51">
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 12, 12, 12, SkPath::kCW_Direction);
- path.addRect(4, 12, 13, 13, SkPath::kCCW_Direction);
-</div>
-
-<div id="testLine52">
- path.addRect(0, 30, 20, 20, SkPath::kCW_Direction);
- path.addRect(6, 20, 18, 30, SkPath::kCW_Direction);
- path.addRect(32, 0, 36, 41, SkPath::kCW_Direction);
-</div>
-
-<div id="testLine53">
- path.addRect(10, 30, 30, 30, SkPath::kCW_Direction);
- path.addRect(12, 20, 24, 30, SkPath::kCW_Direction);
- path.addRect(12, 32, 21, 36, SkPath::kCCW_Direction);
-</div>
-
-<div id="testLine54">
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(6, 0, 18, 18, SkPath::kCW_Direction);
- path.addRect(8, 4, 17, 17, SkPath::kCCW_Direction);
-</div>
-
-<div id="testLine55">
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(6, 6, 18, 18, SkPath::kCW_Direction);
- path.addRect(4, 4, 13, 13, SkPath::kCCW_Direction);
-</div>
-
-<div id="testLine56">
- path.addRect(0, 20, 20, 20, SkPath::kCW_Direction);
- path.addRect(18, 20, 30, 30, SkPath::kCW_Direction);
- path.addRect(12, 0, 21, 21, SkPath::kCCW_Direction);
-</div>
-
-<div id="testLine57">
- path.addRect(20, 0, 40, 40, SkPath::kCW_Direction);
- path.addRect(20, 0, 30, 40, SkPath::kCW_Direction);
- path.addRect(12, 0, 21, 21, SkPath::kCCW_Direction);
-</div>
-
-<div id="testLine58">
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 0, 12, 12, SkPath::kCCW_Direction);
- path.addRect(0, 12, 9, 9, SkPath::kCCW_Direction);
-</div>
-
-<div id="testLine59">
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(6, 6, 18, 18, SkPath::kCCW_Direction);
- path.addRect(4, 4, 13, 13, SkPath::kCCW_Direction);
-</div>
-
-<div id="testLine60">
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(6, 12, 18, 18, SkPath::kCCW_Direction);
- path.addRect(4, 12, 13, 13, SkPath::kCCW_Direction);
-</div>
-
-<div id="testLine61">
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(12, 0, 24, 24, SkPath::kCCW_Direction);
- path.addRect(12, 0, 21, 21, SkPath::kCCW_Direction);
-</div>
-
-<div id="testLine62">
- path.addRect(0, 0, 60, 60, SkPath::kCW_Direction);
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 12, 12, 12, SkPath::kCW_Direction);
- path.addRect(4, 12, 13, 13, SkPath::kCCW_Direction);
-</div>
-
-<div id="testLine63">
- path.addRect(0, 0, 60, 60, SkPath::kCW_Direction);
- path.addRect(0, 10, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 6, 12, 12, SkPath::kCCW_Direction);
- path.addRect(0, 32, 9, 36, SkPath::kCCW_Direction);
-</div>
-
-<div id="testLine64">
- path.addRect(0, 0, 60, 60, SkPath::kCW_Direction);
- path.addRect(10, 40, 30, 30, SkPath::kCW_Direction);
- path.addRect(18, 6, 30, 30, SkPath::kCW_Direction);
-</div>
-
-<div id="testLine65">
- path.addRect(0, 0, 60, 60, SkPath::kCW_Direction);
- path.addRect(10, 0, 30, 30, SkPath::kCW_Direction);
- path.addRect(24, 0, 36, 36, SkPath::kCW_Direction);
- path.addRect(32, 6, 36, 41, SkPath::kCCW_Direction);
-</div>
-
-<div id="testLine66">
- path.addRect(0, 0, 60, 60, SkPath::kCW_Direction);
- path.addRect(0, 30, 20, 20, SkPath::kCW_Direction);
- path.addRect(12, 20, 24, 30, SkPath::kCW_Direction);
-</div>
-
-<div id="testLine67">
- path.addRect(0, 0, 60, 60, SkPath::kCW_Direction);
- path.addRect(10, 40, 30, 30, SkPath::kCW_Direction);
- path.addRect(24, 20, 36, 30, SkPath::kCW_Direction);
- path.addRect(32, 0, 36, 41, SkPath::kCW_Direction);
-</div>
-
-<div id="testLine68a">
- path.addRect(0, 0, 8, 8, SkPath::kCW_Direction);
- path.addRect(2, 2, 6, 6, SkPath::kCW_Direction);
- path.addRect(1, 2, 4, 2, SkPath::kCW_Direction);
-</div>
-
-<div id="testLine68b">
- path.addRect(0, 0, 8, 8, SkPath::kCW_Direction);
- path.addRect(2, 2, 6, 6, SkPath::kCCW_Direction);
- path.addRect(1, 2, 4, 2, SkPath::kCW_Direction);
-</div>
-
-<div id="testLine68c">
- path.addRect(0, 0, 8, 8, SkPath::kCCW_Direction);
- path.addRect(2, 2, 6, 6, SkPath::kCW_Direction);
- path.addRect(1, 2, 4, 2, SkPath::kCW_Direction);
-</div>
-
-<div id="testLine68d">
- path.addRect(0, 0, 8, 8, SkPath::kCCW_Direction);
- path.addRect(2, 2, 6, 6, SkPath::kCCW_Direction);
- path.addRect(1, 2, 4, 2, SkPath::kCW_Direction);
-</div>
-
-<div id="testLine68e">
- path.addRect(0, 0, 8, 8, SkPath::kCW_Direction);
- path.addRect(0, 0, 8, 8, SkPath::kCW_Direction);
- path.addRect(2, 2, 6, 6, SkPath::kCCW_Direction);
- path.addRect(1, 2, 2, 2, SkPath::kCW_Direction);
-</div>
-
-<div id="testLine68f">
- path.addRect(0, 0, 8, 8, SkPath::kCW_Direction);
- path.addRect(2, 2, 6, 6, SkPath::kCCW_Direction);
- path.addRect(2, 2, 6, 6, SkPath::kCCW_Direction);
- path.addRect(1, 2, 2, 2, SkPath::kCW_Direction);
-</div>
-
-<div id="testLine69">
- path.addRect(0, 20, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 20, 12, 30, SkPath::kCW_Direction);
- path.addRect(12, 32, 21, 36, SkPath::kCW_Direction);
-</div>
-
-<div id="testLine70">
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 24, 12, 12, SkPath::kCW_Direction);
- path.addRect(12, 32, 21, 36, SkPath::kCCW_Direction);
-</div>
-
-<div id="testLine71">
- path.addRect(0, 0, 20, 20, SkPath::kCW_Direction);
- path.addRect(12, 0, 24, 24, SkPath::kCW_Direction);
- path.addRect(12, 32, 21, 36, SkPath::kCW_Direction);
-</div>
-
-<div id="testLine72">
- path.addRect(0, 0, 60, 60, SkPath::kCW_Direction);
- path.addRect(10, 40, 30, 30, SkPath::kCW_Direction);
- path.addRect(6, 20, 18, 30, SkPath::kCW_Direction);
-</div>
-
-<div id="testLine73">
- path.addRect(0, 0, 60, 60, SkPath::kCW_Direction);
- path.addRect(0, 40, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 20, 12, 30, SkPath::kCW_Direction);
- path.addRect(0, 0, 9, 9, SkPath::kCCW_Direction);
-</div>
-
-<div id="testLine74">
- path.addRect(20, 30, 40, 40, SkPath::kCW_Direction);
- path.addRect(24, 20, 36, 30, SkPath::kCCW_Direction);
- path.addRect(32, 24, 36, 41, SkPath::kCCW_Direction);
-</div>
-
-<div id="testLine75">
- path.addRect(0, 0, 60, 60, SkPath::kCW_Direction);
- path.addRect(10, 0, 30, 30, SkPath::kCCW_Direction);
- path.addRect(18, 0, 30, 30, SkPath::kCCW_Direction);
- path.addRect(12, 0, 21, 21, SkPath::kCCW_Direction);
-</div>
-
-<div id="testLine76">
- path.addRect(36, 0, 66, 60, SkPath::kCW_Direction);
- path.addRect(10, 20, 40, 30, SkPath::kCW_Direction);
- path.addRect(24, 20, 36, 30, SkPath::kCCW_Direction);
- path.addRect(32, 6, 36, 41, SkPath::kCCW_Direction);
-</div>
-
-<div id="testLine77">
- path.addRect(20, 0, 40, 40, SkPath::kCW_Direction);
- path.addRect(24, 6, 36, 36, SkPath::kCCW_Direction);
- path.addRect(24, 32, 33, 36, SkPath::kCCW_Direction);
-</div>
-
-<div id="testLine78">
- path.addRect(0, 0, 30, 60, SkPath::kCW_Direction);
- path.addRect(10, 20, 30, 30, SkPath::kCCW_Direction);
- path.addRect(18, 20, 30, 30, SkPath::kCCW_Direction);
- path.addRect(32, 0, 36, 41, SkPath::kCCW_Direction);
-</div>
-
-<div id="testLine79">
- path.addRect(0, 36, 60, 30, SkPath::kCW_Direction);
- path.addRect(10, 30, 40, 30, SkPath::kCW_Direction);
- path.addRect(0, 20, 12, 30, SkPath::kCCW_Direction);
- path.addRect(0, 32, 9, 36, SkPath::kCCW_Direction);
-</div>
-
-<div id="testLine81">
- path.addRect(-1, -1, 3, 3, SkPath::kCW_Direction);
- path.addRect(0, 0, 1, 1, SkPath::kCW_Direction);
- path.addRect(1, 1, 2, 2, SkPath::kCCW_Direction);
-</div>
-
-<div id="testDegenerate1">
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.lineTo(2, 0);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(2, 0);
- path.close();
-</div>
-
-<div id="testDegenerate2">
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.lineTo(0, 0);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(0, 1);
- path.close();
-</div>
-
-<div id="testDegenerate3">
- path.moveTo(0, 0);
- path.lineTo(2, 0);
- path.lineTo(1, 0);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.lineTo(3, 0);
- path.close();
-</div>
-
-<div id="testDegenerate4">
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(1, 3);
- path.close();
- path.moveTo(1, 0);
- path.lineTo(1, 1);
- path.lineTo(1, 2);
- path.close();
-</div>
-
-<div id="testNondegenerate1">
- path.moveTo(0, 0);
- path.lineTo(3, 0);
- path.lineTo(1, 3);
- path.close();
- path.moveTo(1, 1);
- path.lineTo(2, 1);
- path.lineTo(1, 2);
- path.close();
-</div>
-
-<div id="testNondegenerate2">
- path.moveTo(1, 0);
- path.lineTo(0, 1);
- path.lineTo(1, 1);
- path.close();
- path.moveTo(0, 2);
- path.lineTo(0, 3);
- path.lineTo(1, 2);
- path.close();
-</div>
-
-<div id="testNondegenerate3">
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(2, 1);
- path.close();
- path.moveTo(0, 1);
- path.lineTo(1, 1);
- path.lineTo(0, 2);
- path.close();
-</div>
-
-<div id="testNondegenerate4">
- path.moveTo(1, 0);
- path.lineTo(0, 1);
- path.lineTo(1, 2);
- path.close();
- path.moveTo(0, 2);
- path.lineTo(0, 3);
- path.lineTo(1, 3);
- path.close();
-</div>
-
-<div id="testQuadralateral5">
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(1, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(2, 2);
- path.lineTo(3, 2);
- path.lineTo(3, 3);
- path.close();
-</div>
-
-<div id="testQuadralateral6">
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(1, 1);
- path.close();
- path.moveTo(1, 0);
- path.lineTo(2, 0);
- path.lineTo(0, 2);
- path.lineTo(2, 2);
- path.close();
-</div>
-
-<div id="testFauxQuadralateral6">
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(1, 1);
- path.close();
- path.moveTo(1, 0);
- path.lineTo(2, 0);
- path.lineTo(1.333, 0.667);
- path.close();
- path.moveTo(1.333, 0.667);
- path.lineTo(0, 2);
- path.lineTo(2, 2);
- path.close();
-</div>
-
-<div id="testFauxQuadralateral6a">
- path.moveTo(0, 0);
- path.lineTo(3, 0);
- path.lineTo(3, 3);
- path.close();
- path.moveTo(3, 0);
- path.lineTo(6, 0);
- path.lineTo(4, 2);
- path.close();
- path.moveTo(4, 2);
- path.lineTo(0, 6);
- path.lineTo(6, 6);
- path.close();
-</div>
-
-<div id="testFauxQuadralateral6b">
- path.moveTo(0, 0);
- path.lineTo(3, 0);
- path.lineTo(3, 3);
- path.close();
- path.moveTo(3, 0);
- path.lineTo(6, 0);
- path.lineTo(4, 2);
- path.close();
- path.moveTo(4, 2);
- path.lineTo(6, 6);
- path.lineTo(0, 6);
- path.close();
-</div>
-
-<div id="testFauxQuadralateral6c">
- path.moveTo(0, 0);
- path.lineTo(3, 3);
- path.lineTo(3, 0);
- path.close();
- path.moveTo(3, 0);
- path.lineTo(6, 0);
- path.lineTo(4, 2);
- path.close();
- path.moveTo(4, 2);
- path.lineTo(0, 6);
- path.lineTo(6, 6);
- path.close();
-</div>
-
-<div id="testFauxQuadralateral6d">
- path.moveTo(0, 0);
- path.lineTo(3, 3);
- path.lineTo(3, 0);
- path.close();
- path.moveTo(3, 0);
- path.lineTo(6, 0);
- path.lineTo(4, 2);
- path.close();
- path.moveTo(4, 2);
- path.lineTo(6, 6);
- path.lineTo(0, 6);
-</div>
-
-<div id="testQuadralateral6a">
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.lineTo(3, 0);
- path.lineTo(3, 3);
- path.close();
- path.moveTo(3, 0);
- path.lineTo(6, 0);
- path.lineTo(0, 6);
- path.lineTo(6, 6);
-</div>
-
-<div id="testQuadralateral7">
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(2, 1);
- path.close();
- path.moveTo(1, 0);
- path.lineTo(1, 1);
- path.lineTo(2, 2);
- path.lineTo(1, 3);
- path.close();
-</div>
-
-<div id="testQuadralateral8">
- path.moveTo(0, 0);
- path.lineTo(3, 1);
- path.lineTo(1, 3);
- path.lineTo(3, 3);
- path.close();
- path.moveTo(2, 1);
- path.lineTo(0, 2);
- path.lineTo(3, 2);
- path.lineTo(2, 3);
- path.close();
-</div>
-
-<div id="testQuadralateral9">
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(1, 2);
- path.lineTo(2, 2);
- path.close();
- path.moveTo(1, 1);
- path.lineTo(2, 1);
- path.lineTo(1, 3);
- path.lineTo(2, 3);
- path.close();
-</div>
-
-<div id="testLine1x">
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 0, 12, 12, SkPath::kCW_Direction);
- path.addRect(4, 0, 13, 13, SkPath::kCW_Direction);
-</div>
-
-<div id="testLine2x">
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 20, 20, 20, SkPath::kCW_Direction);
- path.addRect(0, 20, 12, 30, SkPath::kCW_Direction);
- path.addRect(12, 0, 21, 21, SkPath::kCCW_Direction);
-</div>
-
-<div id="testLine3x">
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(10, 30, 30, 30, SkPath::kCW_Direction);
- path.addRect(18, 20, 30, 30, SkPath::kCCW_Direction);
- path.addRect(0, 32, 9, 36, SkPath::kCCW_Direction);
-</div>
-
-<div id="testLine4x">
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(10, 30, 30, 30, SkPath::kCW_Direction);
- path.addRect(24, 20, 36, 30, SkPath::kCCW_Direction);
- path.addRect(0, 32, 9, 36, SkPath::kCCW_Direction);
-</div>
-
-<div id="testQuadratic1">
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.lineTo(1, 0);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.close();
-</div>
-
-<div id="testQuadratic2">
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.lineTo(3, 0);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(1, 0, 0, 1);
- path.close();
-</div>
-
-<div id="testQuadratic3">
- path.moveTo(0, 0);
- path.quadTo(0, 0, 1, 0);
- path.lineTo(0, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(1, 0, 0, 1);
- path.close();
-</div>
-
-<div id="testQuadratic4x">
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0, 0);
- path.quadTo(0, 0, 1, 0);
- path.lineTo(0, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(1, 0, 0, 2);
- path.close();
-</div>
-
-<div id="testQuadratic5">
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.lineTo(0, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.quadTo(0, 1, 0, 2);
- path.close();
-</div>
-
-<div id="testQuadratic6">
- path.moveTo(0, 0);
- path.quadTo(0, 0, 1, 0);
- path.lineTo(2, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(2, 0, 0, 1);
- path.close();
-</div>
-
-<div id="testQuadratic7">
- path.moveTo(0, 0);
- path.quadTo(0, 0, 1, 0);
- path.lineTo(3, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(3, 0, 1, 2);
- path.close();
-</div>
-
-<div id="testQuadratic8">
- path.moveTo(0, 0);
- path.quadTo(0, 0, 1, 0);
- path.lineTo(0, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.quadTo(0, 1, 1, 2);
- path.close();
-</div>
-
-<div id="testQuadratic9">
- path.moveTo(0, 0);
- path.quadTo(0, 0, 1, 0);
- path.lineTo(3, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.quadTo(1, 2, 3, 2);
- path.close();
-</div>
-
-<div id="testQuadratic9a">
- path.moveTo(1.08000004, 0.720000029);
- path.lineTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(3, 1);
- path.lineTo(1.01568651, 0.338562161);
- path.quadTo(1.03542483, 0.541699469, 1.08000004, 0.720000029);
- path.close();
- path.moveTo(1.08000004, 0.720000029);
- path.lineTo(3, 2);
- path.quadTo(1.39999998, 2, 1.08000004, 0.720000029);
- path.close();
-
-</div>
-
-<div id="testQuadratic10a">
-path.moveTo(15.5, 15.5);
-path.lineTo(46.5, 15.5);
-path.quadTo(0, 31, 0, 46.5);
-path.lineTo(15.5, 15.5);
-path.close();
-</div>
-
-<div id="testQuadratic10b">
-path.moveTo(5.16666698, 36.1666641);
-path.lineTo(15.5, 15.5);
-path.lineTo(46.5, 15.5);
-path.quadTo(15.5, 25.8333321, 5.16666698, 36.1666641);
-path.close();
-path.moveTo(5.16666698, 36.1666641);
-path.lineTo(0, 46.5);
-path.quadTo(0, 41.3333359, 5.16666698, 36.1666641);
-path.close();
-</div>
-
-<div id="testQuadratic11a">
-path.moveTo(0, 0);
-path.lineTo(15.5, 31);
-path.lineTo(0, 0);
-path.close();
-path.moveTo(0, 15.5);
-path.lineTo(15.5, 15.5);
-path.quadTo(15.5, 15.5, 46.5, 31);
-path.lineTo(0, 15.5);
-path.close();
-</div>
-
-<div id="testQuadratic11b">
-path.moveTo(9.30000019, 18.6000004);
-path.lineTo(0, 15.5);
-path.lineTo(7.75, 15.5);
-path.lineTo(15.5, 15.5);
-path.lineTo(46.5, 31);
-path.lineTo(9.30000019, 18.6000004);
-path.close();
-</div>
-
-<div id="testQuadratic12">
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.lineTo(1, 3);
- path.close();
- path.moveTo(1, 0);
- path.lineTo(0, 1);
- path.quadTo(1, 1, 0, 3);
- path.close();
-</div>
-
-<div id="testQuadratic13a">
-path.moveTo(0, 0);
-path.quadTo(0, 0, 15.5, 0);
-path.lineTo(15.5, 31);
-path.lineTo(0, 0);
-path.close();
-path.moveTo(0, 0);
-path.quadTo(15.5, 46.5, 46.5, 46.5);
-path.lineTo(0, 0);
-path.close();
-</div>
-
-<div id="testQuadratic13b">
-path.moveTo(14.8800001, 29.7600002);
-path.quadTo(6.20000029, 18.6000004, 0, 0);
-path.lineTo(14.8800001, 29.7600002);
-path.close();
-path.moveTo(15.5, 30.5437222);
-path.lineTo(15.5, 31);
-path.lineTo(14.8800001, 29.7600002);
-path.quadTo(15.1884346, 30.156559, 15.5, 30.5437222);
-path.close();
-path.moveTo(15.5, 15.5);
-path.lineTo(0, 0);
-path.lineTo(15.5, 0);
-path.lineTo(15.5, 15.5);
-path.close();
-path.moveTo(15.5, 30.5437222);
-path.lineTo(15.5, 15.5);
-path.lineTo(46.5, 46.5);
-path.quadTo(28.34062, 46.5, 15.5, 30.5437222);
-path.close();
-</div>
-
-<div id="testQuadratic14">
- path.moveTo(0, 0);
- path.quadTo(0, 0, 1, 0);
- path.lineTo(3, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.quadTo(3, 2, 3, 3);
- path.close();
-</div>
-
-<div id="testQuadratic15">
- path.moveTo(0, 0);
- path.quadTo(0, 0, 1, 0);
- path.lineTo(1, 3);
- path.close();
- path.moveTo(1, 0);
- path.lineTo(0, 1);
- path.quadTo(1, 1, 0, 3);
- path.close();
-</div>
-
-<div id="testQuadratic16a">
-path.moveTo(0, 0);
-path.quadTo(0, 0, 31, 0);
-path.lineTo(46.5, 31);
-path.lineTo(0, 0);
-path.close();
-path.moveTo(46.5, 15.5);
-path.lineTo(0, 31);
-path.quadTo(0, 31, 15.5, 31);
-path.lineTo(46.5, 15.5);
-path.close();
-</div>
-
-<div id="testQuadratic16b">
-path.moveTo(31, 20.6666679);
-path.lineTo(0, 0);
-path.lineTo(31, 0);
-path.lineTo(39.8571434, 17.7142868);
-path.lineTo(31, 20.6666679);
-path.close();
-path.moveTo(33.214283, 22.1428585);
-path.lineTo(15.5, 31);
-path.lineTo(0, 31);
-path.lineTo(31, 20.6666679);
-path.lineTo(33.214283, 22.1428585);
-path.close();
-path.moveTo(40.2999992, 18.6000004);
-path.lineTo(46.5, 31);
-path.lineTo(33.214283, 22.1428585);
-path.lineTo(40.2999992, 18.6000004);
-path.close();
-path.moveTo(39.8571434, 17.7142868);
-path.lineTo(46.5, 15.5);
-path.lineTo(40.2999992, 18.6000004);
-path.lineTo(39.8571434, 17.7142868);
-path.close();
-</div>
-
-<div id="testQuadratic17x">
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0, 0);
- path.quadTo(0, 0, 3, 1);
- path.lineTo(0, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.quadTo(3, 1, 0, 2);
- path.close();
-</div>
-
-<div id="testQuadratic18">
- path.moveTo(0, 0);
- path.quadTo(1, 0, 0, 1);
- path.lineTo(0, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(1, 0, 1, 1);
- path.close();
-</div>
-
-<div id="testQuadratic19">
- path.moveTo(0, 0);
- path.quadTo(1, 0, 0, 1);
- path.lineTo(0, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(2, 0, 0, 1);
- path.close();
-</div>
-
-<div id="testQuadratic20">
- path.moveTo(0, 0);
- path.quadTo(1, 0, 0, 1);
- path.lineTo(0, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(1, 0, 0, 1);
- path.close();
-</div>
-
-<div id="testQuadratic21">
- path.moveTo(0, 0);
- path.quadTo(1, 0, 0, 1);
- path.lineTo(0, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(1, 0, 0, 2);
- path.close();
-</div>
-
-<div id="testQuadratic22">
- path.moveTo(0, 0);
- path.quadTo(1, 0, 0, 1);
- path.lineTo(0, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(0, 1, 2, 1);
- path.close();
-</div>
-
-<div id="testQuadratic23">
- path.moveTo(0, 0);
- path.quadTo(1, 0, 0, 1);
- path.lineTo(0, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(0, 2, 1, 2);
- path.close();
-</div>
-
-<div id="testQuadratic24">
- path.moveTo(0, 0);
- path.quadTo(1, 0, 0, 1);
- path.lineTo(0, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.quadTo(2, 0, 0, 1);
- path.close();
-</div>
-
-<div id="testQuadratic25">
- path.moveTo(0, 0);
- path.quadTo(1, 0, 1, 1);
- path.lineTo(1, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(2, 1, 0, 2);
- path.close();
-</div>
-
-<div id="testQuadratic26">
- path.moveTo(0, 0);
- path.quadTo(1, 0, 1, 1);
- path.lineTo(0, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(1, 0, 0, 1);
- path.close();
-</div>
-
-<div id="testQuadratic27">
- path.moveTo(0, 0);
- path.quadTo(1, 0, 1, 1);
- path.lineTo(2, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(2, 1, 0, 2);
- path.close();
-</div>
-
-<div id="testQuadratic28">
- path.moveTo(0, 0);
- path.quadTo(1, 0, 0, 1);
- path.lineTo(0, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 2);
- path.quadTo(1, 2, 0, 3);
- path.close();
-</div>
-
-<div id="testQuadratic29">
- path.moveTo(0, 0);
- path.quadTo(1, 0, 2, 1);
- path.lineTo(0, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(1, 0, 0, 1);
- path.close();
-</div>
-
-<div id="testQuadratic30">
- path.moveTo(0, 0);
- path.quadTo(1, 0, 1, 2);
- path.lineTo(1, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.quadTo(0, 1, 1, 2);
- path.close();
-</div>
-
-<div id="testQuadratic31">
- path.moveTo(0, 0);
- path.quadTo(1, 0, 1, 2);
- path.lineTo(1, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.quadTo(0, 1, 1, 3);
- path.close();
-</div>
-
-<div id="testQuadratic32">
- path.moveTo(0, 0);
- path.quadTo(1, 0, 2, 3);
- path.lineTo(2, 3);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(3, 1, 0, 2);
- path.close();
-</div>
-
-<div id="testQuadratic33">
- path.moveTo(0, 0);
- path.quadTo(2, 0, 0, 1);
- path.lineTo(0, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 1);
- path.quadTo(2, 1, 2, 2);
- path.close();
-</div>
-
-<div id="testQuadratic34">
- path.moveTo(0, 0);
- path.quadTo(2, 0, 0, 1);
- path.lineTo(0, 1);
- path.close();
- path.moveTo(1, 0);
- path.lineTo(1, 1);
- path.quadTo(2, 1, 1, 2);
- path.close();
-</div>
-
-<div id="testQuadratic35">
- path.moveTo(0, 0);
- path.quadTo(0, 1, 1, 1);
- path.lineTo(1, 3);
- path.close();
- path.moveTo(2, 0);
- path.lineTo(3, 0);
- path.quadTo(0, 1, 1, 1);
- path.close();
-</div>
-
-<div id="testQuadratic36">
- path.moveTo(0, 0);
- path.quadTo(2, 1, 2, 3);
- path.lineTo(2, 3);
- path.close();
- path.moveTo(3, 1);
- path.lineTo(1, 2);
- path.quadTo(3, 2, 1, 3);
- path.close();
-</div>
-
-<div id="testQuadratic37">
- path.moveTo(0, 0);
- path.quadTo(0, 2, 1, 2);
- path.lineTo(1, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(3, 1);
- path.quadTo(0, 2, 1, 2);
- path.close();
-</div>
-
-<div id="testQuadratic38">
- path.moveTo(1, 0);
- path.quadTo(0, 1, 1, 1);
- path.lineTo(1, 1);
- path.close();
- path.moveTo(1, 0);
- path.lineTo(1, 2);
- path.quadTo(2, 2, 1, 3);
- path.close();
-</div>
-
-<div id="testQuadratic39">
-path.moveTo(15.5, 0);
-path.quadTo(46.5, 15.5, 46.5, 31);
-path.lineTo(15.5, 0);
-path.close();
-path.moveTo(46.5, 15.5);
-path.lineTo(0, 31);
-path.quadTo(0, 31, 15.5, 31);
-path.lineTo(46.5, 15.5);
- path.close();
-</div>
-
-<div id="testQuadratic39a">
-path.moveTo(34.875, 19.375);
-path.lineTo(15.5, 0);
-path.quadTo(32.9687576, 8.73437881, 40.5937271, 17.4687576);
-path.lineTo(34.875, 19.375);
-path.close();
-path.moveTo(36.1666641, 20.6666679);
-path.lineTo(15.5, 31);
-path.lineTo(0, 31);
-path.lineTo(34.875, 19.375);
-path.lineTo(36.1666641, 20.6666679);
-path.close();
-path.moveTo(41.1812401, 18.15938);
-path.quadTo(46.5, 24.5796909, 46.5, 31);
-path.lineTo(36.1666641, 20.6666679);
-path.lineTo(41.1812401, 18.15938);
-path.close();
-path.moveTo(40.5937271, 17.4687576);
-path.lineTo(46.5, 15.5);
-path.lineTo(41.1812401, 18.15938);
-path.quadTo(40.8951759, 17.8140678, 40.5937271, 17.4687576);
- path.close();
-</div>
-
-<div id="testQuadratic40x">
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(2, 0);
- path.quadTo(3, 0, 2, 2);
- path.lineTo(3, 2);
- path.close();
- path.moveTo(3, 1);
- path.lineTo(0, 2);
- path.quadTo(0, 2, 1, 2);
- path.close();
-</div>
-
-<div id="testQuadratic40xa">
-path.moveTo(31, 0);
-path.quadTo(41.3333359, 0, 37.8888893, 13.7777777);
-path.lineTo(31, 0);
-path.close();
-path.moveTo(37.8888893, 13.7777777);
-path.quadTo(37.2993202, 16.1360455, 36.3061028, 18.8979664);
-path.lineTo(0, 31);
-path.lineTo(15.5, 31);
-path.lineTo(35.5182915, 20.9908543);
-path.quadTo(33.7454262, 25.5091457, 31, 31);
-path.lineTo(46.5, 31);
-path.lineTo(40.2999992, 18.6000004);
-path.lineTo(46.5, 15.5);
-path.lineTo(39.8571434, 17.7142868);
-path.lineTo(37.8888893, 13.7777777);
-path.close();
-path.moveTo(36.3061028, 18.8979664);
-path.quadTo(35.9396667, 19.9169388, 35.5182915, 20.9908543);
-path.lineTo(40.2999992, 18.6000004);
-path.lineTo(39.8571434, 17.7142868);
-path.lineTo(36.3061028, 18.8979664);
-</div>
-
-<div id="testQuadratic40xb">
-path.moveTo(31, 0);
-path.quadTo(46.5, 0, 31, 31);
-path.lineTo(46.5, 31);
-path.lineTo(31, 0);
-path.close();
-path.moveTo(46.5, 15.5);
-path.lineTo(0, 31);
-path.quadTo(0, 31, 15.5, 31);
-path.lineTo(46.5, 15.5);
-path.close();
-</div>
-
-<div id="testQuadratic41o">
-path.moveTo(419.33905, 236.377808);
-path.quadTo(398.847778, 242.58728, 384.255524, 242.58728);
-path.quadTo(359.417633, 242.58728, 343.738708, 226.080429);
-path.quadTo(328.059784, 209.573578, 328.059784, 183.286819);
-path.quadTo(328.059784, 157.724487, 341.875854, 141.372879);
-path.quadTo(355.691956, 125.021263, 377.218109, 125.021263);
-path.quadTo(397.605896, 125.021263, 408.731201, 139.51004);
-path.quadTo(419.856506, 153.99881, 419.856506, 180.699539);
-path.lineTo(419.752991, 187.012497);
-path.lineTo(348.861511, 187.012497);
-path.quadTo(353.311646, 227.063599, 388.084686, 227.063599);
-path.quadTo(400.814117, 227.063599, 419.33905, 220.233185);
-path.lineTo(419.33905, 236.377808);
-path.close();
-path.moveTo(349.792938, 171.695801);
-path.lineTo(399.365234, 171.695801);
-path.quadTo(399.365234, 140.337967, 375.976227, 140.337967);
-path.quadTo(352.483704, 140.337967, 349.792938, 171.695801);
-path.close();
-path.moveTo(378.682587, 277.360321);
-path.lineTo(381.062897, 259.66333);
-path.quadTo(398.759888, 268.046112, 415.939423, 268.046112);
-path.quadTo(450.402008, 268.046112, 450.402008, 231.513718);
-path.lineTo(450.402008, 213.816727);
-path.quadTo(439.12146, 237.41272, 413.352142, 237.41272);
-path.quadTo(393.171356, 237.41272, 381.269867, 222.716965);
-path.quadTo(369.368378, 208.02121, 369.368378, 183.079834);
-path.quadTo(369.368378, 157.414017, 382.92572, 141.269379);
-path.quadTo(396.483093, 125.124756, 418.009247, 125.124756);
-path.quadTo(436.844666, 125.124756, 450.402008, 140.441467);
-path.lineTo(450.402008, 127.608543);
-path.lineTo(470.89325, 127.608543);
-path.lineTo(470.89325, 209.366608);
-path.quadTo(470.89325, 235.756866, 468.150757, 248.43454);
-path.quadTo(465.408234, 261.112213, 457.853363, 269.184509);
-path.quadTo(444.502991, 283.362823, 416.353394, 283.362823);
-path.quadTo(396.690063, 283.362823, 378.682587, 277.360321);
-path.close();
-path.moveTo(450.402008, 201.087311);
-path.lineTo(450.402008, 154.412781);
-path.quadTo(436.948151, 140.441467, 421.113983, 140.441467);
-path.quadTo(407.039185, 140.441467, 399.070374, 151.722);
-path.quadTo(391.101532, 163.002533, 391.101532, 182.665863);
-path.quadTo(391.101532, 219.612228, 417.07782, 219.612228);
-path.quadTo(434.774841, 219.612228, 450.402008, 201.087311);
-path.close();
-path.moveTo(482.9328, 236.377808);
-path.quadTo(462.441528, 242.58728, 447.849274, 242.58728);
-path.quadTo(423.011383, 242.58728, 407.332458, 226.080429);
-path.quadTo(391.653534, 209.573578, 391.653534, 183.286819);
-path.quadTo(391.653534, 157.724487, 405.469604, 141.372879);
-path.quadTo(419.285706, 125.021263, 440.811859, 125.021263);
-path.quadTo(461.199646, 125.021263, 472.324951, 139.51004);
-path.quadTo(483.450256, 153.99881, 483.450256, 180.699539);
-path.lineTo(483.346741, 187.012497);
-path.lineTo(412.455261, 187.012497);
-path.quadTo(416.905396, 227.063599, 451.678436, 227.063599);
-path.quadTo(464.407867, 227.063599, 482.9328, 220.233185);
-path.lineTo(482.9328, 236.377808);
-path.close();
-path.moveTo(413.386688, 171.695801);
-path.lineTo(462.958984, 171.695801);
-path.quadTo(462.958984, 140.337967, 439.569977, 140.337967);
-path.quadTo(416.077454, 140.337967, 413.386688, 171.695801);
-path.close();
-</div>
-
-<div id="testQuadratic41s">
-path.moveTo(341.875854, 141.372879);
-path.quadTo(355.691956,125.021263, 377.218109,125.021263);
-path.quadTo(388.787811,125.021263, 397.374664,129.687164);
-path.quadTo(406.565979,125.124756, 418.009247,125.124756);
-path.quadTo(423.583374,125.124756, 428.695251,126.466187);
-path.quadTo(434.412903,125.021263, 440.811859,125.021263);
-path.quadTo(449.427277,125.021263, 456.388672,127.608543);
-path.lineTo(470.89325,127.608543);
-path.lineTo(470.89325,137.749908);
-path.quadTo(471.627319,138.601486, 472.324951,139.51004);
-path.quadTo(483.450256,153.99881, 483.450256,180.699539);
-path.lineTo(483.346741,187.012497);
-path.lineTo(470.89325,187.012497);
-path.lineTo(470.89325,209.366608);
-path.quadTo(470.89325,217.414856, 470.638184,224.187729);
-path.quadTo(476.428223,222.631516, 482.9328,220.233185);
-path.lineTo(482.9328,236.377808);
-path.quadTo(475.87207,238.517426, 469.511749,239.919785);
-path.quadTo(468.946777,244.754791, 468.150757,248.43454);
-path.quadTo(465.408234,261.112213, 457.853363,269.184509);
-path.quadTo(444.502991,283.362823, 416.353394,283.362823);
-path.quadTo(396.690063,283.362823, 378.682587,277.360321);
-path.lineTo(381.062897,259.66333);
-path.quadTo(398.759888,268.046112, 415.939423,268.046112);
-path.quadTo(444.719147,268.046112, 449.464905,242.568665);
-path.quadTo(448.648254,242.58728, 447.849274,242.58728);
-path.quadTo(433.084625,242.58728, 421.556366,236.754425);
-path.quadTo(418.89566,237.203537, 416.046783,237.346252);
-path.quadTo(397.661652,242.58728, 384.255524,242.58728);
-path.quadTo(359.417633,242.58728, 343.738708,226.080429);
-path.quadTo(328.059784,209.573578, 328.059784,183.286819);
-path.quadTo(328.059784,157.724487, 341.875854,141.372879);
-path.close();
-path.moveTo(442.014923, 226.179474);
-path.quadTo(445.951935,226.953491, 450.402008,227.049881);
-path.lineTo(450.402008,213.816727);
-path.quadTo(446.904755,221.132065, 442.014923,226.179474);
-path.close();
-path.moveTo(395.347717, 206.501785);
-path.quadTo(392.200165,197.593536, 391.734406,187.012497);
-path.lineTo(391.197113,187.012497);
-path.quadTo(391.738647,198.938644, 395.347717,206.501785);
-path.close();
-path.moveTo(391.808533, 171.695801);
-path.lineTo(392.428436,171.695801);
-path.quadTo(393.693451,162.656265, 397.02359,154.9935);
-path.quadTo(397.023804,154.992996, 397.024048,154.992493);
-path.quadTo(393.175995,143.845093, 383.003235,141.177292);
-path.quadTo(382.964447,141.223267, 382.92572,141.269379);
-</div>
-
-<div id="testQuadratic42o">
-path.moveTo(421.962158, 236.285355);
-path.quadTo(400.947845, 242.65332, 385.983124, 242.65332);
-path.quadTo(360.511261, 242.65332, 344.432129, 225.725143);
-path.quadTo(328.352997, 208.796951, 328.352997, 181.839218);
-path.quadTo(328.352997, 155.62442, 342.521729, 138.855438);
-path.quadTo(356.69046, 122.086449, 378.766083, 122.086449);
-path.quadTo(399.674255, 122.086449, 411.083527, 136.945038);
-path.quadTo(422.492798, 151.803635, 422.492798, 179.185898);
-path.lineTo(422.386688, 185.660004);
-path.lineTo(349.685699, 185.660004);
-path.quadTo(354.24942, 226.733398, 389.910034, 226.733398);
-path.quadTo(402.964386, 226.733398, 421.962158, 219.728638);
-path.lineTo(421.962158, 236.285355);
-path.close();
-path.moveTo(350.6409, 169.952347);
-path.lineTo(401.478516, 169.952347);
-path.quadTo(401.478516, 137.794098, 377.492493, 137.794098);
-path.quadTo(353.40036, 137.794098, 350.6409, 169.952347);
-path.close();
-path.moveTo(379.213562, 278.313934);
-path.lineTo(381.654602, 260.165222);
-path.quadTo(399.803314, 268.761993, 417.421356, 268.761993);
-path.quadTo(452.763611, 268.761993, 452.763611, 231.297104);
-path.lineTo(452.763611, 213.148392);
-path.quadTo(441.195129, 237.34668, 414.768036, 237.34668);
-path.quadTo(394.072144, 237.34668, 381.866882, 222.275818);
-path.quadTo(369.661591, 207.204956, 369.661591, 181.626953);
-path.quadTo(369.661591, 155.306015, 383.565002, 138.749298);
-path.quadTo(397.468384, 122.192581, 419.544037, 122.192581);
-path.quadTo(438.860199, 122.192581, 452.763611, 137.900238);
-path.lineTo(452.763611, 124.739769);
-path.lineTo(473.777893, 124.739769);
-path.lineTo(473.777893, 208.584686);
-path.quadTo(473.777893, 235.64856, 470.965363, 248.649826);
-path.quadTo(468.152863, 261.651093, 460.405151, 269.929443);
-path.quadTo(446.71402, 284.469666, 417.845886, 284.469666);
-path.quadTo(397.680664, 284.469666, 379.213562, 278.313934);
-path.close();
-path.moveTo(452.763611, 200.094055);
-path.lineTo(452.763611, 152.228165);
-path.quadTo(438.966339, 137.900238, 422.727997, 137.900238);
-path.quadTo(408.293945, 137.900238, 400.121704, 149.468719);
-path.quadTo(391.949493, 161.037186, 391.949493, 181.202423);
-path.quadTo(391.949493, 219.091827, 418.588837, 219.091827);
-path.quadTo(436.737549, 219.091827, 452.763611, 200.094055);
-path.close();
-path.moveTo(485.555908, 236.285355);
-path.quadTo(464.541595, 242.65332, 449.576874, 242.65332);
-path.quadTo(424.105011, 242.65332, 408.025879, 225.725143);
-path.quadTo(391.946747, 208.796951, 391.946747, 181.839218);
-path.quadTo(391.946747, 155.62442, 406.115479, 138.855438);
-path.quadTo(420.28421, 122.086449, 442.359833, 122.086449);
-path.quadTo(463.268005, 122.086449, 474.677277, 136.945038);
-path.quadTo(486.086548, 151.803635, 486.086548, 179.185898);
-path.lineTo(485.980438, 185.660004);
-path.lineTo(413.279449, 185.660004);
-path.quadTo(417.84317, 226.733398, 453.503784, 226.733398);
-path.quadTo(466.558136, 226.733398, 485.555908, 219.728638);
-path.lineTo(485.555908, 236.285355);
-path.close();
-path.moveTo(414.23465, 169.952347);
-path.lineTo(465.072266, 169.952347);
-path.quadTo(465.072266, 137.794098, 441.086243, 137.794098);
-path.quadTo(416.99411, 137.794098, 414.23465, 169.952347);
-path.close();
-</div>
-
-<div id="testQuadratic42s">
-path.moveTo(342.521729, 138.855438);
-path.quadTo(356.69046,122.086449, 378.766083,122.086449);
-path.quadTo(390.293488,122.086449, 398.933502,126.603004);
-path.quadTo(408.150299,122.192581, 419.544037,122.192581);
-path.quadTo(425.108429,122.192581, 430.223633,123.496056);
-path.quadTo(435.959412,122.086449, 442.359833,122.086449);
-path.quadTo(451.19516,122.086449, 458.334229,124.739769);
-path.lineTo(473.777893,124.739769);
-path.lineTo(473.777893,135.814713);
-path.quadTo(474.234741,136.368698, 474.677277,136.945038);
-path.quadTo(486.086548,151.803635, 486.086548,179.185898);
-path.lineTo(485.980438,185.660004);
-path.lineTo(473.777893,185.660004);
-path.lineTo(473.777893,208.584686);
-path.quadTo(473.777893,216.745773, 473.522156,223.628113);
-path.quadTo(479.207153,222.069519, 485.555908,219.728638);
-path.lineTo(485.555908,236.285355);
-path.quadTo(478.638306,238.381592, 472.376221,239.787796);
-path.quadTo(471.792389,244.826782, 470.965363,248.649826);
-path.quadTo(468.152863,261.651093, 460.405151,269.929443);
-path.quadTo(446.71402,284.469666, 417.845886,284.469666);
-path.quadTo(397.680664,284.469666, 379.213562,278.313934);
-path.lineTo(381.654602,260.165222);
-path.quadTo(399.803314,268.761993, 417.421356,268.761993);
-path.quadTo(446.944275,268.761993, 451.80542,242.619034);
-path.quadTo(450.674866,242.65332, 449.576874,242.65332);
-path.quadTo(434.524628,242.65332, 422.75238,236.741913);
-path.quadTo(420.864227,237.041901, 418.884674,237.193085);
-path.quadTo(399.840271,242.65332, 385.983124,242.65332);
-path.quadTo(360.511261,242.65332, 344.432129,225.725143);
-path.quadTo(328.352997,208.796951, 328.352997,181.839218);
-path.quadTo(328.352997,155.62442, 342.521729,138.855438);
-path.close();
-path.moveTo(383.823944, 138.443222);
-path.quadTo(380.900299,137.794098, 377.492493,137.794098);
-path.quadTo(353.40036,137.794098, 350.6409,169.952347);
-path.lineTo(370.408203,169.952347);
-path.quadTo(372.883484,151.469254, 383.565002,138.749298);
-path.quadTo(383.694122,138.595551, 383.823944,138.443222);
-path.close();
-path.moveTo(369.740021, 185.660004);
-path.lineTo(349.685699,185.660004);
-path.quadTo(353.983734,224.342361, 385.863525,226.594208);
-path.quadTo(383.762756,224.616837, 381.866882,222.275818);
-path.quadTo(370.639954,208.41301, 369.740021,185.660004);
-path.close();
-path.moveTo(413.279449, 185.660004);
-path.quadTo(415.737305,207.780716, 427.214905,217.987976);
-path.quadTo(440.600586,214.512451, 452.763611,200.094055);
-path.lineTo(452.763611,185.660004);
-</div>
-
-<div id="testQuadratic43o">
-path.moveTo(288.755981, 240);
-path.lineTo(288.755981, 102.232819);
-path.lineTo(315.843994, 102.232819);
-path.lineTo(354.009216, 208.816208);
-path.lineTo(393.291473, 102.232819);
-path.lineTo(417.493835, 102.232819);
-path.lineTo(417.493835, 240);
-path.lineTo(399.248962, 240);
-path.lineTo(399.248962, 127.92453);
-path.lineTo(361.269928, 230.784485);
-path.lineTo(342.373474, 230.784485);
-path.lineTo(305.511444, 127.645271);
-path.lineTo(305.511444, 240);
-path.lineTo(288.755981, 240);
-path.close();
-path.moveTo(397.864014, 236.741989);
-path.quadTo(379.433014, 242.327148, 366.307892, 242.327148);
-path.quadTo(343.967255, 242.327148, 329.864746, 227.479935);
-path.quadTo(315.762238, 212.632736, 315.762238, 188.988907);
-path.quadTo(315.762238, 165.996674, 328.189209, 151.289093);
-path.quadTo(340.61618, 136.581512, 359.978058, 136.581512);
-path.quadTo(378.315979, 136.581512, 388.322723, 149.613556);
-path.quadTo(398.329468, 162.645584, 398.329468, 186.661758);
-path.lineTo(398.236359, 192.339996);
-path.lineTo(334.472504, 192.339996);
-path.quadTo(338.475189, 228.364258, 369.752075, 228.364258);
-path.quadTo(381.20163, 228.364258, 397.864014, 222.220581);
-path.lineTo(397.864014, 236.741989);
-path.close();
-path.moveTo(335.310272, 178.563278);
-path.lineTo(379.898438, 178.563278);
-path.quadTo(379.898438, 150.358246, 358.861023, 150.358246);
-path.quadTo(337.730499, 150.358246, 335.310272, 178.563278);
-path.close();
-path.moveTo(346.052765, 240);
-path.lineTo(346.052765, 138.908661);
-path.lineTo(364.390686, 138.908661);
-path.lineTo(364.390686, 157.898193);
-path.quadTo(375.281769, 136.674606, 396.039917, 136.674606);
-path.quadTo(398.832489, 136.674606, 401.904327, 137.140045);
-path.lineTo(401.904327, 154.267853);
-path.quadTo(397.156952, 152.685394, 393.526611, 152.685394);
-path.quadTo(376.119537, 152.685394, 364.390686, 173.350464);
-path.lineTo(364.390686, 240);
-path.lineTo(346.052765, 240);
-path.close();
-path.moveTo(362.792297, 273.604034);
-path.lineTo(364.933289, 257.68634);
-path.quadTo(380.850983, 265.226288, 396.303253, 265.226288);
-path.quadTo(427.300842, 265.226288, 427.300842, 232.366959);
-path.lineTo(427.300842, 216.449265);
-path.quadTo(417.15448, 237.672852, 393.976105, 237.672852);
-path.quadTo(375.824341, 237.672852, 365.119446, 224.454651);
-path.quadTo(354.414581, 211.23645, 354.414581, 188.802734);
-path.quadTo(354.414581, 165.717422, 366.608826, 151.196014);
-path.quadTo(378.803101, 136.674606, 398.164948, 136.674606);
-path.quadTo(415.106598, 136.674606, 427.300842, 150.451324);
-path.lineTo(427.300842, 138.908661);
-path.lineTo(445.731873, 138.908661);
-path.lineTo(445.731873, 212.446564);
-path.quadTo(445.731873, 236.183472, 443.265106, 247.586502);
-path.quadTo(440.798309, 258.989532, 434.003052, 266.250244);
-path.quadTo(421.994965, 279.002991, 396.675598, 279.002991);
-path.quadTo(378.989258, 279.002991, 362.792297, 273.604034);
-path.close();
-path.moveTo(427.300842, 204.999695);
-path.lineTo(427.300842, 163.017929);
-path.quadTo(415.199677, 150.451324, 400.95755, 150.451324);
-path.quadTo(388.297852, 150.451324, 381.130249, 160.597687);
-path.quadTo(373.962616, 170.744064, 373.962616, 188.430389);
-path.quadTo(373.962616, 221.662079, 397.327179, 221.662079);
-path.quadTo(413.244873, 221.662079, 427.300842, 204.999695);
-path.close();
-path.moveTo(461.457764, 236.741989);
-path.quadTo(443.026764, 242.327148, 429.901642, 242.327148);
-path.quadTo(407.561005, 242.327148, 393.458496, 227.479935);
-path.quadTo(379.355988, 212.632736, 379.355988, 188.988907);
-path.quadTo(379.355988, 165.996674, 391.782959, 151.289093);
-path.quadTo(404.20993, 136.581512, 423.571808, 136.581512);
-path.quadTo(441.909729, 136.581512, 451.916473, 149.613556);
-path.quadTo(461.923218, 162.645584, 461.923218, 186.661758);
-path.lineTo(461.830109, 192.339996);
-path.lineTo(398.066254, 192.339996);
-path.quadTo(402.068939, 228.364258, 433.345825, 228.364258);
-path.quadTo(444.79538, 228.364258, 461.457764, 222.220581);
-path.lineTo(461.457764, 236.741989);
-path.close();
-path.moveTo(398.904022, 178.563278);
-path.lineTo(443.492188, 178.563278);
-path.quadTo(443.492188, 150.358246, 422.454773, 150.358246);
-path.quadTo(401.324249, 150.358246, 398.904022, 178.563278);
-path.close();
-</div>
-
-<div id="testQuadratic43s">
-path.moveTo(288.755981, 240);
-path.lineTo(288.755981,102.232819);
-path.lineTo(315.843994,102.232819);
-path.lineTo(331.979736,147.294876);
-path.quadTo(343.453125,136.581512, 359.978058,136.581512);
-path.quadTo(370.869446,136.581512, 378.822021,141.178574);
-path.quadTo(378.893585,141.140915, 378.965302,141.103577);
-path.lineTo(393.291473,102.232819);
-path.lineTo(417.493835,102.232819);
-path.lineTo(417.493835,136.965759);
-path.quadTo(420.44223,136.581512, 423.571808,136.581512);
-path.quadTo(431.320984,136.581512, 437.582458,138.908661);
-path.lineTo(445.731873,138.908661);
-path.lineTo(445.731873,143.392502);
-path.quadTo(449.143951,146.002823, 451.916473,149.613556);
-path.quadTo(461.923218,162.645584, 461.923218,186.661758);
-path.lineTo(461.830109,192.339996);
-path.lineTo(445.731873,192.339996);
-path.lineTo(445.731873,212.446564);
-path.quadTo(445.731873,220.39856, 445.455017,226.966339);
-path.quadTo(452.7435,225.43367, 461.457764,222.220581);
-path.lineTo(461.457764,236.741989);
-path.quadTo(452.250824,239.531982, 444.367889,240.928268);
-path.quadTo(443.897583,244.662796, 443.265106,247.586502);
-path.quadTo(440.798309,258.989532, 434.003052,266.250244);
-path.quadTo(421.994965,279.002991, 396.675598,279.002991);
-path.quadTo(378.989258,279.002991, 362.792297,273.604034);
-path.lineTo(364.933289,257.68634);
-path.quadTo(380.850983,265.226288, 396.303253,265.226288);
-path.quadTo(422.230743,265.226288, 426.471558,242.237076);
-path.quadTo(419.570892,241.869324, 413.503387,240);
-path.lineTo(399.248962,240);
-path.lineTo(399.248962,237.37915);
-path.quadTo(397.047638,237.633072, 394.711517,237.667465);
-path.quadTo(378.296356,242.327148, 366.307892,242.327148);
-path.quadTo(357.463165,242.327148, 349.909637,240);
-path.lineTo(346.052765,240);
-path.lineTo(346.052765,238.625916);
-path.quadTo(336.926056,234.914124, 329.864746,227.479935);
-path.quadTo(315.762238,212.632736, 315.762238,188.988907);
-path.quadTo(315.762238,176.540054, 319.405273,166.519882);
-path.lineTo(305.511444,127.645271);
-path.lineTo(305.511444,240);
-path.lineTo(288.755981,240);
-path.close();
-path.moveTo(375.464813, 192.339996);
-path.lineTo(374.267029,195.583939);
-path.quadTo(375.987579,214.575378, 387.432068,219.736267);
-path.quadTo(380.122528,208.101486, 379.428741,192.339996);
-path.lineTo(375.464813,192.339996);
-path.close();
-path.moveTo(427.300842, 178.563278);
-path.lineTo(427.300842,163.017929);
-path.quadTo(422.561523,158.096329, 417.493835,155.102234);
-path.lineTo(417.493835,178.563278);
-path.lineTo(427.300842,178.563278);
-path.close();
-path.moveTo(427.300842, 192.339996);
-path.lineTo(417.493835,192.339996);
-path.lineTo(417.493835,214.429169);
-path.quadTo(422.505676,210.684036, 427.300842,204.999695);
-path.lineTo(427.300842,192.339996);
-path.close();
-path.moveTo(420.700134, 226.556015);
-path.quadTo(423.794342,227.54834, 427.300842,227.996094);
-path.lineTo(427.300842,216.449265);
-path.quadTo(424.497772,222.312531, 420.700134,226.556015);
-path.close();
-path.moveTo(368.744965, 228.354782);
-path.quadTo(366.836426,226.574738, 365.119446,224.454651);
-path.quadTo(364.748657,223.996796, 364.390686,223.527878);
-path.lineTo(364.390686,228.077774);
-path.quadTo(366.495239,228.312164, 368.744965,228.354782);
-path.close();
-path.moveTo(399.248962, 199.701065);
-path.lineTo(399.248962,192.339996);
-path.lineTo(398.236359,192.339996);
-path.lineTo(398.066254,192.339996);
-path.quadTo(398.498535,196.230621, 399.248962,199.701065);
-path.close();
-path.moveTo(399.248962, 178.563278);
-path.lineTo(399.248962,175.376892);
-path.quadTo(399.04483,176.922348, 398.904022,178.563278);
-path.lineTo(399.248962,178.563278);
-path.close();
-path.moveTo(399.248962, 136.688828);
-path.lineTo(399.248962,127.92453);
-path.lineTo(396.018158,136.674606);
-path.quadTo(396.029053,136.674606, 396.039917,136.674606);
-path.quadTo(396.513672,136.674606, 396.995453,136.688004);
-path.quadTo(397.576904,136.674606, 398.164948,136.674606);
-path.quadTo(398.709412,136.674606, 399.248962,136.688828);
-path.close();
-path.moveTo(346.052765, 178.563278);
-path.lineTo(346.052765,154.02713);
-path.quadTo(340.97113,157.621338, 338.22525,164.736588);
-path.lineTo(343.1763,178.563278);
-path.lineTo(346.052765,178.563278);
-path.close();
-path.moveTo(364.390686, 150.922379);
-path.lineTo(364.390686,154.048065);
-path.quadTo(365.340851,152.726639, 366.38147,151.468765);
-path.quadTo(365.420258,151.14975, 364.390686,150.922379);
-path.close();
-path.moveTo(367.863586, 152.032623);
-path.quadTo(367.144043,151.721848, 366.38147,151.468765);
-</div>
-
-<div id="testQuadratic44o">
-path.moveTo(354.009216, 208.816208);
-path.lineTo(393.291473, 102.232819);
-path.lineTo(399.248962, 127.92453);
-path.lineTo(361.269928, 230.784485);
-path.lineTo(354.009216, 208.816208);
-path.close();
-path.moveTo(328.189209, 151.289093);
-path.quadTo(340.61618, 136.581512, 359.978058, 136.581512);
-path.quadTo(378.315979, 136.581512, 388.322723, 149.613556);
-path.lineTo(328.189209, 151.289093);
-path.close();
-path.moveTo(346.052765, 138.908661);
-path.lineTo(364.390686, 138.908661);
-path.lineTo(364.390686, 157.898193);
-path.quadTo(375.281769, 136.674606, 396.039917, 136.674606);
-path.lineTo(346.052765, 138.908661);
-path.close();
-</div>
-
-<div id="testQuadratic44s">
-path.moveTo(380.33902, 137.376312);
-path.lineTo(393.291473,102.232819);
-path.lineTo(399.248962,127.92453);
-path.lineTo(396.018158,136.674606);
-path.quadTo(396.029053,136.674606, 396.039917,136.674606);
-path.lineTo(396.017792,136.675598);
-path.lineTo(361.269928,230.784485);
-path.lineTo(354.009216,208.816208);
-path.lineTo(375.699249,149.965286);
-path.lineTo(369.22699,150.14563);
-path.quadTo(373.524384,144.511566, 378.917297,141.233871);
-path.lineTo(380.33902,137.376312);
-path.close();
-path.moveTo(380.33902, 137.376312);
-path.lineTo(378.917297,141.233856);
-path.quadTo(375.048248,138.978912, 370.480499,137.816925);
-path.lineTo(380.33902,137.376312);
-path.close();
-path.moveTo(392.55661, 136.830276);
-path.lineTo(380.33902,137.376312);
-</div>
-
-<div id="testQuadratic45o">
-path.moveTo(315.843994, 102.232819);
-path.lineTo(354.009216, 208.816208);
-path.lineTo(393.291473, 102.232819);
-path.lineTo(399.248962, 127.92453);
-path.lineTo(361.269928, 230.784485);
-path.lineTo(342.373474, 230.784485);
-path.lineTo(305.511444, 127.645271);
-path.lineTo(315.843994, 102.232819);
-path.close();
-path.moveTo(366.307892, 242.327148);
-path.quadTo(343.967255, 242.327148, 329.864746, 227.479935);
-path.quadTo(315.762238, 212.632736, 315.762238, 188.988907);
-path.quadTo(315.762238, 165.996674, 328.189209, 151.289093);
-path.quadTo(340.61618, 136.581512, 359.978058, 136.581512);
-path.quadTo(378.315979, 136.581512, 388.322723, 149.613556);
-path.quadTo(398.329468, 162.645584, 398.329468, 186.661758);
-path.lineTo(398.236359, 192.339996);
-path.lineTo(334.472504, 192.339996);
-path.quadTo(338.475189, 228.364258, 369.752075, 228.364258);
-path.quadTo(381.20163, 228.364258, 397.864014, 222.220581);
-path.lineTo(366.307892, 242.327148);
-path.close();
-path.moveTo(335.310272, 178.563278);
-path.lineTo(379.898438, 178.563278);
-path.quadTo(379.898438, 150.358246, 358.861023, 150.358246);
-path.quadTo(337.730499, 150.358246, 335.310272, 178.563278);
-path.close();
-path.moveTo(346.052765, 240);
-path.lineTo(346.052765, 138.908661);
-path.lineTo(364.390686, 138.908661);
-path.lineTo(364.390686, 157.898193);
-path.quadTo(375.281769, 136.674606, 396.039917, 136.674606);
-path.lineTo(401.904327, 154.267853);
-path.quadTo(397.156952, 152.685394, 393.526611, 152.685394);
-path.quadTo(376.119537, 152.685394, 364.390686, 173.350464);
-path.lineTo(364.390686, 240);
-path.lineTo(346.052765, 240);
-path.close();
-path.moveTo(396.303253, 265.226288);
-path.quadTo(427.300842, 265.226288, 427.300842, 232.366959);
-path.lineTo(427.300842, 216.449265);
-path.quadTo(417.15448, 237.672852, 393.976105, 237.672852);
-path.quadTo(375.824341, 237.672852, 365.119446, 224.454651);
-path.quadTo(354.414581, 211.23645, 354.414581, 188.802734);
-path.quadTo(354.414581, 165.717422, 366.608826, 151.196014);
-path.quadTo(378.803101, 136.674606, 398.164948, 136.674606);
-path.lineTo(396.303253, 265.226288);
-path.close();
-path.moveTo(400.95755, 150.451324);
-path.quadTo(388.297852, 150.451324, 381.130249, 160.597687);
-path.quadTo(373.962616, 170.744064, 373.962616, 188.430389);
-path.quadTo(373.962616, 221.662079, 397.327179, 221.662079);
-path.lineTo(400.95755, 150.451324);
-path.close();
-path.moveTo(429.901642, 242.327148);
-path.quadTo(407.561005, 242.327148, 393.458496, 227.479935);
-path.quadTo(379.355988, 212.632736, 379.355988, 188.988907);
-path.quadTo(379.355988, 165.996674, 391.782959, 151.289093);
-path.quadTo(404.20993, 136.581512, 423.571808, 136.581512);
-path.lineTo(429.901642, 242.327148);
-path.close();
-</div>
-
-<div id="testQuadratic45s">
-path.moveTo(305.511444, 127.645271);
-path.lineTo(315.843994,102.232819);
-path.lineTo(331.979736,147.294876);
-path.quadTo(343.453125,136.581512, 359.978058,136.581512);
-path.quadTo(370.869446,136.581512, 378.822021,141.178574);
-path.quadTo(378.893585,141.140915, 378.965302,141.103577);
-path.lineTo(393.291473,102.232819);
-path.lineTo(399.248962,127.92453);
-path.lineTo(396.018158,136.674606);
-path.quadTo(396.029053,136.674606, 396.039917,136.674606);
-path.lineTo(396.054596,136.718628);
-path.quadTo(397.098907,136.674606, 398.164948,136.674606);
-path.lineTo(398.076477,142.784256);
-path.lineTo(398.697632,144.647751);
-path.quadTo(409.233032,136.581512, 423.571808,136.581512);
-path.lineTo(429.901642,242.327148);
-path.quadTo(428.161621,242.327148, 426.471558,242.237076);
-path.quadTo(427.300842,237.741562, 427.300842,232.366959);
-path.lineTo(427.300842,216.449265);
-path.quadTo(419.710114,232.327133, 404.8255,236.326401);
-path.quadTo(400.557983,233.971252, 396.803375,230.691772);
-path.lineTo(396.7034,237.596863);
-path.quadTo(395.363068,237.672852, 393.976105,237.672852);
-path.quadTo(385.309937,237.672852, 378.341187,234.659912);
-path.lineTo(366.307892,242.327148);
-path.quadTo(357.463165,242.327148, 349.909637,240);
-path.lineTo(346.052765,240);
-path.lineTo(346.052765,238.625916);
-path.quadTo(336.926056,234.914124, 329.864746,227.479935);
-path.quadTo(315.762238,212.632736, 315.762238,188.988907);
-path.quadTo(315.762238,176.540054, 319.405273,166.519882);
-path.lineTo(305.511444,127.645271);
-path.close();
-path.moveTo(375.464813, 192.339996);
-path.lineTo(374.267029,195.583939);
-path.quadTo(375.987579,214.575378, 387.432068,219.736267);
-path.quadTo(380.122528,208.101486, 379.428741,192.339996);
-path.lineTo(375.464813,192.339996);
-path.close();
-path.moveTo(397.925934, 153.178131);
-path.lineTo(397.615479,174.615356);
-path.quadTo(398.329468,180.246704, 398.329468,186.661758);
-path.lineTo(398.236359,192.339996);
-path.lineTo(397.358795,192.339996);
-path.lineTo(396.934174,221.659714);
-path.quadTo(397.129852,221.662079, 397.327179,221.662079);
-path.lineTo(400.781189,153.910889);
-path.quadTo(399.295654,153.462463, 397.925934,153.178131);
-path.close();
-path.moveTo(400.914398, 151.298019);
-path.lineTo(400.632721,150.453003);
-path.quadTo(400.794678,150.451324, 400.95755,150.451324);
-path.lineTo(400.914398,151.298019);
-path.close();
-path.moveTo(368.744965, 228.354782);
-path.quadTo(366.836426,226.574738, 365.119446,224.454651);
-path.quadTo(364.748657,223.996796, 364.390686,223.527878);
-path.lineTo(364.390686,228.077774);
-path.quadTo(366.495239,228.312164, 368.744965,228.354782);
-path.close();
-path.moveTo(346.052765, 178.563278);
-path.lineTo(346.052765,154.02713);
-path.quadTo(340.97113,157.621338, 338.22525,164.736588);
-path.lineTo(343.1763,178.563278);
-path.lineTo(346.052765,178.563278);
-path.close();
-path.moveTo(364.390686, 150.922379);
-path.lineTo(364.390686,154.048065);
-path.quadTo(365.340851,152.726639, 366.38147,151.468765);
-path.quadTo(365.420258,151.14975, 364.390686,150.922379);
-path.close();
-path.moveTo(367.863586, 152.032623);
-path.quadTo(367.144043,151.721848, 366.38147,151.468765);
-</div>
-
-<div id="testQuadratic46o">
-path.moveTo(366.608826, 151.196014);
-path.quadTo(378.803101, 136.674606, 398.164948, 136.674606);
-path.lineTo(354.009216, 208.816208);
-path.lineTo(393.291473, 102.232819);
-path.lineTo(359.978058, 136.581512);
-path.quadTo(378.315979, 136.581512, 388.322723, 149.613556);
-path.lineTo(364.390686, 157.898193);
-path.quadTo(375.281769, 136.674606, 396.039917, 136.674606);
-path.lineTo(350, 120);
-path.lineTo(366.608826, 151.196014);
-path.close();
-</div>
-
-<div id="testQuadratic46s">
-path.moveTo(369.285553, 126.984779);
-path.lineTo(393.291473,102.232819);
-path.lineTo(382.416199,131.740402);
-path.lineTo(396.039917,136.674606);
-path.quadTo(387.290802,136.674606, 380.294495,140.44487);
-path.quadTo(379.623352,140.760971, 378.965302,141.103577);
-path.lineTo(378.917297,141.233856);
-path.quadTo(378.86972,141.206131, 378.822021,141.178574);
-path.quadTo(372.011871,144.761871, 366.608826,151.196014);
-path.lineTo(350,120);
-path.lineTo(369.285553,126.984779);
-path.close();
-path.moveTo(374.00174, 154.571106);
-path.lineTo(378.917297,141.233871);
-path.quadTo(378.917297,141.233871, 378.917297,141.233856);
-path.quadTo(384.294891,144.368011, 388.322723,149.613556);
-path.lineTo(374.00174,154.571106);
-path.close();
-path.moveTo(378.917297, 141.233871);
-path.quadTo(370.233887,146.511475, 364.390686,157.898193);
-path.lineTo(374.00174,154.571106);
-path.lineTo(354.009216,208.816208);
-path.lineTo(398.164948,136.674606);
-path.quadTo(388.299255,136.674606, 380.294495,140.44487);
-</div>
-
-<div id="testQuadratic47o">
-path.moveTo(343.939362, 212.598053);
-path.lineTo(378.457642, 118.940636);
-path.lineTo(383.692657, 141.516571);
-path.lineTo(350.319519, 231.902115);
-path.lineTo(343.939362, 212.598053);
-path.close();
-path.moveTo(325.429016, 162.047577);
-path.quadTo(336.348907, 149.123688, 353.36264, 149.123688);
-path.quadTo(369.476624, 149.123688, 378.269806, 160.575241);
-path.lineTo(325.429016, 162.047577);
-path.close();
-path.moveTo(370.867188, 186.014069);
-path.quadTo(370.867188, 161.229614, 352.381104, 161.229614);
-path.quadTo(333.813202, 161.229614, 331.686493, 186.014069);
-path.lineTo(370.867188, 186.014069);
-path.close();
-path.moveTo(353.161499, 195.011719);
-path.quadTo(353.161499, 174.726105, 363.876862, 161.96579);
-path.lineTo(353.161499, 195.011719);
-path.close();
-</div>
-
-<div id="testQuadratic47s">
-path.moveTo(366.466309, 151.476364);
-path.lineTo(378.457642,118.940636);
-path.lineTo(383.692657,141.516571);
-path.lineTo(377.159943,159.209305);
-path.quadTo(377.728729,159.87059, 378.269806,160.575241);
-path.lineTo(376.638824,160.620682);
-path.lineTo(370.26593,177.8806);
-path.quadTo(368.708496,168.390671, 363.116943,164.309357);
-path.lineTo(356.079041,186.014069);
-path.lineTo(367.262817,186.014069);
-path.lineTo(350.319519,231.902115);
-path.lineTo(343.939362,212.598053);
-path.lineTo(353.736816,186.014923);
-path.lineTo(353.737122,186.014069);
-path.lineTo(353.736938,186.014069);
-path.quadTo(353.736877,186.014496, 353.736816,186.014923);
-path.quadTo(353.161499,190.31131, 353.161499,195.011719);
-</div>
-
-<div id="testQuadratic48o">
-path.moveTo(366.608826, 151.196014);
-path.quadTo(378.803101, 136.674606, 398.164948, 136.674606);
-path.lineTo(354.009216, 208.816208);
-path.lineTo(393.291473, 102.232819);
-path.lineTo(359.978058, 136.581512);
-path.quadTo(378.315979, 136.581512, 388.322723, 149.613556);
-path.lineTo(364.390686, 157.898193);
-path.quadTo(375.281769, 136.674606, 396.039917, 136.674606);
-path.lineTo(350, 120);
-path.lineTo(366.608826, 151.196014);
-path.close();
-</div>
-
-<div id="testQuadratic48s">
-path.moveTo(369.285553, 126.984779);
-path.lineTo(393.291473,102.232819);
-path.lineTo(382.416199,131.740402);
-path.lineTo(396.039917,136.674606);
-path.quadTo(387.290802,136.674606, 380.294495,140.44487);
-path.quadTo(379.623352,140.760971, 378.965302,141.103577);
-path.lineTo(378.917297,141.233856);
-path.quadTo(378.86972,141.206131, 378.822021,141.178574);
-path.quadTo(372.011871,144.761871, 366.608826,151.196014);
-path.lineTo(350,120);
-path.lineTo(369.285553,126.984779);
-path.close();
-</div>
-
-<div id="testQuadratic49s">
-path.moveTo(366.400513, 204.162521);
-path.lineTo(411.545044, 81.6732483);
-path.lineTo(366.400513, 204.162521);
-path.close();
-path.moveTo(331.585693, 138.050415);
-path.quadTo(345.867188, 121.147957, 368.11853, 121.147957);
-path.quadTo(389.193115, 121.147957, 400.693176, 136.124817);
-path.lineTo(331.585693, 138.050415);
-path.close();
-path.moveTo(369.863983, 145.645813);
-path.quadTo(382.380371, 121.254936, 406.236359, 121.254936);
-path.lineTo(369.863983, 145.645813);
-path.close();
-path.moveTo(369.970581, 137.94342);
-path.quadTo(383.98465, 121.254936, 406.235992, 121.254936);
-path.lineTo(369.970581, 137.94342);
-path.close();
-</div>
-
-<div id="testQuadratic50o">
-path.moveTo(366.400513, 204.162521);
-path.lineTo(411.545044, 81.6732483);
-path.lineTo(366.400513, 204.162521);
-path.close();
-path.moveTo(331.585693, 138.050415);
-path.quadTo(345.867188, 121.147957, 368.11853, 121.147957);
-path.quadTo(389.193115, 121.147957, 400.693176, 136.124817);
-path.lineTo(331.585693, 138.050415);
-path.close();
-path.moveTo(369.863983, 145.645813);
-path.quadTo(382.380371, 121.254936, 406.236359, 121.254936);
-path.lineTo(369.863983, 145.645813);
-path.close();
-path.moveTo(369.970581, 137.94342);
-path.quadTo(383.98465, 121.254936, 406.235992, 121.254936);
-path.lineTo(369.970581, 137.94342);
-path.close();
-</div>
-
-<div id="testQuadratic50s">
-path.moveTo(331.585693, 138.050415);
-path.quadTo(345.867188,121.147957, 368.11853,121.147957);
-path.quadTo(378.797424,121.147957, 387.017914,124.993469);
-path.quadTo(391.577667,123.030998, 396.645874,122.098694);
-path.quadTo(401.232697,121.254936, 406.235992,121.254936);
-path.lineTo(395.061676,126.397095);
-path.lineTo(391.979187,127.81559);
-path.quadTo(393.010406,128.517273, 393.994415,129.292801);
-path.quadTo(394.053131,129.339066, 394.111664,129.385605);
-path.lineTo(393.910492,129.520508);
-path.lineTo(383.340973,136.608322);
-path.lineTo(375.350006,136.830978);
-path.quadTo(376.20224,135.708145, 377.092102,134.66626);
-path.lineTo(372.197113,136.918823);
-</div>
-
-<div id="testQuadratic51">
-path.moveTo(369.863983, 145.645813);
-path.quadTo(382.380371, 121.254936, 406.236359, 121.254936);
-path.lineTo(369.863983, 145.645813);
-path.close();
-path.moveTo(369.970581, 137.94342);
-path.quadTo(383.98465, 121.254936, 406.235992, 121.254936);
-path.lineTo(369.970581, 137.94342);
-path.close();
-</div>
-
-<div id="testQuadratic52o">
-path.moveTo(366.400513, 204.162521);
-path.lineTo(411.545044, 81.6732483);
-path.lineTo(366.400513, 204.162521);
-path.close();
-path.moveTo(331.585693, 138.050415);
-path.quadTo(345.867188, 121.147957, 368.11853, 121.147957);
-path.quadTo(389.193115, 121.147957, 400.693176, 136.124817);
-path.lineTo(331.585693, 138.050415);
-path.close();
-path.moveTo(369.863983, 145.645813);
-path.quadTo(382.380371, 121.254936, 406.236359, 121.254936);
-path.lineTo(369.863983, 145.645813);
-path.close();
-path.moveTo(369.970581, 137.94342);
-path.quadTo(383.98465, 121.254936, 406.235992, 121.254936);
-path.lineTo(369.970581, 137.94342);
-path.close();
-</div>
-
-<div id="testQuadratic52s">
-path.moveTo(331.585693, 138.050415);
-path.quadTo(345.867188,121.147957, 368.11853,121.147957);
-path.quadTo(378.797424,121.147957, 387.017914,124.993469);
-path.quadTo(391.577667,123.030998, 396.645874,122.098694);
-path.quadTo(401.232697,121.254936, 406.235992,121.254936);
-path.close();
-path.moveTo(383.340973, 136.608322);
-path.lineTo(369.863983,145.645813);
-path.quadTo(372.378204,140.746292, 375.350006,136.830978);
-path.lineTo(372.197113,136.918823);
-path.lineTo(369.970581,137.94342);
-path.quadTo(370.390961,137.442825, 370.818756,136.95723);
-path.lineTo(331.585693,138.050415);
-path.quadTo(345.867188,121.147957, 368.11853,121.147957);
-path.quadTo(378.797424,121.147957, 387.017914,124.993469);
-path.quadTo(391.577667,123.030998, 396.645874,122.098694);
-path.quadTo(401.232697,121.254936, 406.235992,121.254936);
-path.close();
-path.moveTo(383.340973, 136.608322);
-path.lineTo(391.380798,136.384293);
-path.lineTo(400.693176,136.124817);
-path.quadTo(397.721985,132.255341, 394.111664,129.385605);
-path.lineTo(406.236359,121.254936);
-path.quadTo(406.236176,121.254936, 406.235992,121.254936);
-path.lineTo(406.235992,121.254936);
-path.quadTo(401.232697,121.254936, 396.645874,122.098694);
-path.quadTo(391.577667,123.030998, 387.017914,124.993469);
-path.quadTo(378.797424,121.147957, 368.11853,121.147957);
-path.quadTo(345.867188,121.147957, 331.585693,138.050415);
-path.lineTo(370.818756,136.95723);
-path.quadTo(370.390961,137.442825, 369.970581,137.94342);
-path.lineTo(372.197113,136.918823);
-path.lineTo(375.350006,136.830978);
-path.quadTo(372.378204,140.746292, 369.863983,145.645813);
-path.lineTo(383.340973,136.608322);
-path.close();
-</div>
-
-<div id="testQuadratic52sa">
-path.moveTo(331.585693, 138.050415);
-path.quadTo(345.867188,121.147957, 368.11853,121.147957);
-path.quadTo(378.797424,121.147957, 387.017914,124.993469);
-path.quadTo(391.577667,123.030998, 396.645874,122.098694);
-path.quadTo(401.232697,121.254936, 406.235992,121.254936);
-path.close();
-</div>
-
-<div id="testQuadratic52sb">
-path.moveTo(383.340973, 136.608322);
-path.lineTo(369.863983,145.645813);
-path.quadTo(372.378204,140.746292, 375.350006,136.830978);
-path.lineTo(372.197113,136.918823);
-path.lineTo(369.970581,137.94342);
-path.quadTo(370.390961,137.442825, 370.818756,136.95723);
-path.lineTo(331.585693,138.050415);
-path.quadTo(345.867188,121.147957, 368.11853,121.147957);
-path.quadTo(378.797424,121.147957, 387.017914,124.993469);
-path.quadTo(391.577667,123.030998, 396.645874,122.098694);
-path.quadTo(401.232697,121.254936, 406.235992,121.254936);
-path.close();
-</div>
-
-<div id="testQuadratic52sc">
-path.moveTo(383.340973, 136.608322);
-path.lineTo(391.380798,136.384293);
-path.lineTo(400.693176,136.124817);
-path.quadTo(397.721985,132.255341, 394.111664,129.385605);
-path.lineTo(406.236359,121.254936);
-path.quadTo(406.236176,121.254936, 406.235992,121.254936);
-path.lineTo(406.235992,121.254936);
-path.quadTo(401.232697,121.254936, 396.645874,122.098694);
-path.quadTo(391.577667,123.030998, 387.017914,124.993469);
-path.quadTo(378.797424,121.147957, 368.11853,121.147957);
-path.quadTo(345.867188,121.147957, 331.585693,138.050415);
-path.lineTo(370.818756,136.95723);
-path.quadTo(370.390961,137.442825, 369.970581,137.94342);
-path.lineTo(372.197113,136.918823);
-path.lineTo(375.350006,136.830978);
-path.quadTo(372.378204,140.746292, 369.863983,145.645813);
-path.lineTo(383.340973,136.608322);
-path.close();
-</div>
-
-<div id="testQuadratic53o">
-path.moveTo(303.12088, 141.299606);
-path.lineTo(330.463562, 217.659027);
-path.lineTo(303.12088, 141.299606);
-path.close();
-path.moveTo(371.919067, 205.854996);
-path.lineTo(326.236786, 205.854996);
-path.quadTo(329.104431, 231.663818, 351.512085, 231.663818);
-path.lineTo(371.919067, 205.854996);
-path.close();
-</div>
-
-<div id="testQuadratic53s">
-path.moveTo(326.236786,205.854996);
-path.lineTo(326.236786,205.854996);
-path.close();
-path.moveTo(371.919067,205.854996);
-path.lineTo(326.236786,205.854996);
-</div>
-
-<div id="testQuadratic54">
-path.moveTo(303.12088, 141.299606);
-path.lineTo(330.463562, 217.659027);
-path.lineTo(358.606506, 141.299606);
-path.lineTo(303.12088, 141.299606);
-path.close();
-path.moveTo(371.919067, 205.854996);
-path.lineTo(326.236786, 205.854996);
-path.quadTo(329.104431, 231.663818, 351.512085, 231.663818);
-path.lineTo(371.919067, 205.854996);
-path.close();
-</div>
-
-<div id="testQuadratic55o">
-path.moveTo(303.12088, 141.299606);
-path.lineTo(330.463562, 217.659027);
-path.lineTo(358.606506, 141.299606);
-path.lineTo(303.12088, 141.299606);
-path.close();
-path.moveTo(326.236786, 205.854996);
-path.quadTo(329.104431, 231.663818, 351.512085, 231.663818);
-path.lineTo(326.236786, 205.854996);
-path.close();
-</div>
-
-<div id="testQuadratic55s">
-path.moveTo(326.236786,205.854996);
-path.lineTo(303.12088,141.299606);
-path.lineTo(358.606506,141.299606);
-path.lineTo(332.468719,212.218475);
-path.lineTo(351.512085,231.663818);
-path.quadTo(329.104431,231.663818, 326.236786,205.854996);
-path.close();
-</div>
-
-<div id="testQuadratic56o">
-path.moveTo(366.608826, 151.196014);
-path.quadTo(378.803101, 136.674606, 398.164948, 136.674606);
-path.lineTo(354.009216, 208.816208);
-path.lineTo(393.291473, 102.232819);
-path.lineTo(359.978058, 136.581512);
-path.quadTo(378.315979, 136.581512, 388.322723, 149.613556);
-path.lineTo(364.390686, 157.898193);
-path.quadTo(375.281769, 136.674606, 396.039917, 136.674606);
-path.lineTo(350, 120);
-path.lineTo(366.608826, 151.196014);
-path.close();
-</div>
-
-<div id="testQuadratic56s">
-path.moveTo(369.285553,126.984779);
-path.lineTo(393.291473,102.232819);
-path.lineTo(382.416199,131.740402);
-path.lineTo(396.039917,136.674606);
-path.quadTo(387.290802,136.674606, 380.294495,140.44487);
-path.quadTo(379.623352,140.760971, 378.965302,141.103577);
-path.lineTo(378.917297,141.233856);
-path.quadTo(378.86972,141.206131, 378.822021,141.178574);
-path.quadTo(372.011871,144.761871, 366.608826,151.196014);
-path.lineTo(350,120);
-path.lineTo(369.285553,126.984779);
-path.close();
-path.moveTo(378.917297,141.233871);
-path.lineTo(378.917297,141.233856);
-path.quadTo(378.86972,141.206131, 378.822021,141.178574);
-path.quadTo(372.011871,144.761871, 366.608826,151.196014);
-</div>
-
-<div id="testQuadratic57o">
-path.moveTo(303.12088, 141.299606);
-path.lineTo(330.463562, 217.659027);
-path.lineTo(358.606506, 141.299606);
-path.lineTo(362.874634, 159.705902);
-path.lineTo(335.665344, 233.397751);
-path.lineTo(322.12738, 233.397751);
-path.lineTo(295.718353, 159.505829);
-path.lineTo(295.718353, 240);
-path.lineTo(303.12088, 141.299606);
-path.close();
-path.moveTo(322.935669, 231.030273);
-path.quadTo(312.832214, 220.393295, 312.832214, 203.454178);
-path.quadTo(312.832214, 186.981888, 321.73526, 176.444946);
-path.quadTo(330.638306, 165.90802, 344.509705, 165.90802);
-path.lineTo(371.919067, 205.854996);
-path.lineTo(326.236786, 205.854996);
-path.quadTo(329.104431, 231.663818, 351.512085, 231.663818);
-path.lineTo(322.935669, 231.030273);
-path.close();
-path.moveTo(326.837006, 195.984955);
-path.lineTo(358.78125, 195.984955);
-path.lineTo(343.709442, 175.778046);
-path.quadTo(328.570923, 175.778046, 326.837006, 195.984955);
-path.close();
-</div>
-
-<div id="testQuadratic57s">
-path.moveTo(300.708282,173.46756);
-path.lineTo(303.12088,141.299606);
-path.lineTo(317.770294,182.210785);
-path.quadTo(319.462738,179.134506, 321.73526,176.444946);
-path.quadTo(330.638306,165.90802, 344.509705,165.90802);
-path.lineTo(347.780151,170.674438);
-path.lineTo(358.606506,141.299606);
-path.lineTo(362.874634,159.705902);
-path.lineTo(354.960693,181.139511);
-path.lineTo(371.919067,205.854996);
-path.lineTo(345.834961,205.854996);
-path.lineTo(337.609253,228.13298);
-path.quadTo(342.649323,231.302383, 349.843323,231.626816);
-path.lineTo(336.429047,231.329422);
-path.lineTo(335.665344,233.397751);
-path.lineTo(322.12738,233.397751);
-path.lineTo(320.050781,227.587433);
-path.quadTo(313.982483,219.336182, 313.015503,207.902908);
-path.lineTo(300.708282,173.46756);
-path.close();
-path.moveTo(300.708282,173.46756);
-path.lineTo(295.718353,240);
-path.lineTo(295.718353,159.505829);
-path.lineTo(300.708282,173.46756);
-path.close();
-path.moveTo(349.843323,231.626816);
-path.lineTo(351.512085,231.663818);
-path.quadTo(350.663696,231.663818, 349.843323,231.626816);
-path.close();
-path.moveTo(326.236786,205.854996);
-path.lineTo(330.463562,217.659027);
-path.lineTo(334.814056,205.854996);
-path.lineTo(326.236786,205.854996);
-path.close();
-path.moveTo(334.814056,205.854996);
-path.lineTo(338.451721,195.984955);
-path.lineTo(349.479309,195.984955);
-path.lineTo(352.559326,187.643173);
-path.lineTo(358.78125,195.984955);
-</div>
-
-<div id="testQuadratic58o">
-path.moveTo(283.714233, 240);
-path.lineTo(283.714233, 141.299606);
-path.lineTo(303.12088, 141.299606);
-path.lineTo(330.463562, 217.659027);
-path.lineTo(358.606506, 141.299606);
-path.lineTo(362.874634, 159.705902);
-path.lineTo(335.665344, 233.397751);
-path.lineTo(322.12738, 233.397751);
-path.lineTo(295.718353, 159.505829);
-path.lineTo(295.718353, 240);
-path.lineTo(283.714233, 240);
-path.close();
-path.moveTo(322.935669, 231.030273);
-path.quadTo(312.832214, 220.393295, 312.832214, 203.454178);
-path.quadTo(312.832214, 186.981888, 321.73526, 176.444946);
-path.quadTo(330.638306, 165.90802, 344.509705, 165.90802);
-path.quadTo(357.647522, 165.90802, 364.81665, 175.244537);
-path.lineTo(371.919067, 205.854996);
-path.lineTo(326.236786, 205.854996);
-path.quadTo(329.104431, 231.663818, 351.512085, 231.663818);
-path.lineTo(322.935669, 231.030273);
-path.close();
-path.moveTo(326.837006, 195.984955);
-path.lineTo(358.78125, 195.984955);
-path.quadTo(358.78125, 175.778046, 343.709442, 175.778046);
-path.quadTo(328.570923, 175.778046, 326.837006, 195.984955);
-path.close();
-</div>
-
-<div id="testQuadratic58s">
-path.moveTo(283.714233,240);
-path.lineTo(283.714233,141.299606);
-path.lineTo(303.12088,141.299606);
-path.lineTo(317.770294,182.210785);
-path.quadTo(319.462738,179.134506, 321.73526,176.444946);
-path.quadTo(330.638306,165.90802, 344.509705,165.90802);
-path.quadTo(347.07132,165.90802, 349.406036,166.26297);
-path.lineTo(358.606506,141.299606);
-path.lineTo(362.874634,159.705902);
-path.lineTo(359.116211,169.884979);
-path.quadTo(362.326477,172.001541, 364.81665,175.244537);
-path.lineTo(371.919067,205.854996);
-path.lineTo(345.834961,205.854996);
-path.lineTo(337.609253,228.13298);
-path.quadTo(342.649323,231.302383, 349.843323,231.626816);
-path.lineTo(336.429047,231.329422);
-path.lineTo(335.665344,233.397751);
-path.lineTo(322.12738,233.397751);
-path.lineTo(320.050781,227.587433);
-path.quadTo(313.982483,219.336182, 313.015503,207.902908);
-path.lineTo(295.718353,159.505829);
-path.lineTo(295.718353,240);
-path.lineTo(283.714233,240);
-path.close();
-path.moveTo(349.843323,231.626816);
-path.lineTo(351.512085,231.663818);
-path.quadTo(350.663696,231.663818, 349.843323,231.626816);
-path.close();
-path.moveTo(326.236786,205.854996);
-path.lineTo(330.463562,217.659027);
-path.lineTo(334.814056,205.854996);
-path.lineTo(326.236786,205.854996);
-path.close();
-path.moveTo(334.814056,205.854996);
-path.lineTo(338.451721,195.984955);
-path.lineTo(349.479309,195.984955);
-path.lineTo(355.054535,180.885361);
-path.quadTo(358.78125,185.936935, 358.78125,195.984955);
-</div>
-
-<div id="testQuadratic58a">
-path.moveTo(283.714233,240);
-path.lineTo(283.714233,141.299606);
-path.lineTo(303.12088,141.299606);
-path.lineTo(317.770294,182.210785);
-path.quadTo(319.462738,179.134506, 321.73526,176.444946);
-path.quadTo(330.638306,165.90802, 344.509705,165.90802);
-path.quadTo(347.07132,165.90802, 349.406036,166.26297);
-path.lineTo(358.606506,141.299606);
-path.lineTo(362.874634,159.705902);
-path.lineTo(359.116211,169.884979);
-path.quadTo(362.326477,172.001541, 364.81665,175.244537);
-path.lineTo(371.919067,205.854996);
-path.lineTo(345.834961,205.854996);
-path.lineTo(337.609253,228.13298);
-path.quadTo(342.649323,231.302383, 349.843323,231.626816);
-path.lineTo(336.429047,231.329422);
-path.lineTo(335.665344,233.397751);
-path.lineTo(322.12738,233.397751);
-path.lineTo(320.050781,227.587433);
-path.quadTo(313.982483,219.336182, 313.015503,207.902908);
-path.lineTo(295.718353,159.505829);
-path.lineTo(295.718353,240);
-path.lineTo(283.714233,240);
-path.close();
-path.moveTo(349.843323,231.626816);
-path.lineTo(351.512085,231.663818);
-path.quadTo(350.663696,231.663818, 349.843323,231.626816);
-path.close();
-path.moveTo(349.479309,195.984955);
-path.lineTo(358.78125,195.984955);
-path.quadTo(358.78125,185.936935, 355.054535,180.885361);
-path.lineTo(349.479309,195.984955);
-path.close();
-path.moveTo(345.858368,175.888794);
-path.lineTo(338.451721,195.984955);
-path.lineTo(326.837006,195.984955);
-path.quadTo(328.570923,175.778046, 343.709442,175.778046);
-path.quadTo(344.825195,175.778046, 345.858368,175.888794);
-path.close();
-</div>
-
-<div id="testQuadratic59">
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.lineTo(2, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(2, 0);
- path.quadTo(3, 1, 1, 2);
-</div>
-
-<div id="testQuadratic59o">
-path.moveTo(369.863983, 145.645813);
-path.quadTo(382.380371, 121.254936, 406.236359, 121.254936);
-path.quadTo(409.445679, 121.254936, 412.975952, 121.789818);
-path.lineTo(369.863983, 145.645813);
-path.close();
-path.moveTo(369.970581, 137.94342);
-path.quadTo(383.98465, 121.254936, 406.235992, 121.254936);
-path.quadTo(425.705902, 121.254936, 439.71994, 137.087616);
-path.lineTo(369.970581, 137.94342);
-path.close();
-</div>
-
-<div id="testQuadratic59s">
-path.moveTo(369.970581,137.94342);
-path.quadTo(383.98465,121.254936, 406.235992,121.254936);
-path.quadTo(406.237854,121.254936, 406.239746,121.254936);
-path.lineTo(406.239532,121.254936);
-path.quadTo(409.447418,121.255203, 412.975952,121.789818);
-</div>
-
-<div id="testQuadratic60">
-path.moveTo(360.416077, 166.795715);
-path.quadTo(370.126831, 147.872162, 388.635406, 147.872162);
-path.lineTo(360.416077, 166.795715);
-path.close();
-path.moveTo(353.2948, 194.351074);
-path.quadTo(353.2948, 173.767563, 364.167572, 160.819855);
-path.quadTo(375.040314, 147.872162, 392.303894, 147.872162);
-path.lineTo(353.2948, 194.351074);
-path.close();
-</div>
-
-<div id="testQuadratic61">
-path.moveTo(348.781738, 123.864815);
-path.lineTo(369.848602, 123.864815);
-path.lineTo(369.848602, 145.680267);
-path.quadTo(382.360413, 121.298294, 406.207703, 121.298294);
-path.lineTo(348.781738, 123.864815);
-path.close();
-path.moveTo(369.961151, 137.980698);
-path.quadTo(383.970093, 121.298294, 406.213287, 121.298294);
-path.lineTo(369.961151, 137.980698);
-path.close();
-</div>
-
-<div id="testQuadratic62x">
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.lineTo(2, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(2, 0);
- path.quadTo(3, 1, 1, 2);
- path.close();
-</div>
-
-<div id="testLine1a">
- path.addRect(0, 0, 12, 12, SkPath::kCW_Direction);
- path.addRect(4, 0, 13, 13, SkPath::kCCW_Direction);
- path.close();
-</div>
-
-<div id="testQuadratic63">
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.lineTo(3, 2);
- path.close();
- path.moveTo(1, 0);
- path.lineTo(2, 1);
- path.quadTo(2, 1, 2, 2);
- path.close();
-</div>
-
-<div id="testQuadratic64">
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.lineTo(2, 3);
- path.close();
- path.moveTo(1, 2);
- path.lineTo(2, 2);
- path.quadTo(0, 3, 3, 3);
- path.close();
-</div>
-
-<div id="testQuadratic65">
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.lineTo(3, 2);
- path.close();
- path.moveTo(2, 1);
- path.lineTo(2, 2);
- path.quadTo(0, 3, 1, 3);
- path.close();
-</div>
-
-<div id="testQuadratic66">
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 1);
- path.lineTo(3, 2);
- path.close();
- path.moveTo(2, 0);
- path.lineTo(1, 1);
- path.quadTo(3, 2, 2, 3);
- path.close();
-</div>
-
-<div id="testQuadratic67x">
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0, 0);
- path.quadTo(0, 0, 2, 1);
- path.lineTo(2, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(2, 0);
- path.quadTo(1, 1, 3, 2);
- path.close();
-</div>
-
-<div id="testQuadratic68">
- path.moveTo(0, 0);
- path.quadTo(1, 0, 0, 1);
- path.lineTo(1, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(0, 1, 2, 1);
- path.close();
-</div>
-
-<div id="testQuadratic69">
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 1);
- path.lineTo(3, 2);
- path.close();
- path.moveTo(2, 0);
- path.lineTo(1, 1);
- path.quadTo(3, 2, 2, 3);
- path.close();
-</div>
-
-<div id="testQuadratic70x">
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0, 0);
- path.quadTo(1, 0, 0, 1);
- path.lineTo(1, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(0, 1, 2, 1);
- path.close();
-</div>
-
-<div id="testQuadratic71">
- path.moveTo(0, 0);
- path.quadTo(1, 0, 1, 1);
- path.lineTo(3, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(1, 1, 3, 1);
- path.close();
-</div>
-
-<div id="testQuadratic72">
- path.moveTo(0, 0);
- path.quadTo(1, 0, 1, 2);
- path.lineTo(1, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.quadTo(0, 1, 3, 2);
- path.close();
-</div>
-
-<div id="testQuadratic73">
- path.moveTo(0, 0);
- path.quadTo(1, 0, 0, 3);
- path.lineTo(0, 3);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.quadTo(0, 1, 1, 1);
- path.close();
-</div>
-
-<div id="testQuadratic74">
- path.moveTo(0, 0);
- path.quadTo(1, 0, 1, 3);
- path.lineTo(1, 3);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 1);
- path.quadTo(3, 2, 2, 3);
- path.close();
-</div>
-
-<div id="testQuadratic75">
- path.moveTo(0, 0);
- path.quadTo(1, 0, 1, 3);
- path.lineTo(2, 3);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 1);
- path.quadTo(3, 2, 2, 3);
- path.close();
-</div>
-
-<div id="testQuadratic76">
- path.moveTo(0, 0);
- path.quadTo(0, 0, 0, 0);
- path.lineTo(2, 3);
- path.close();
- path.moveTo(1, 0);
- path.lineTo(1, 2);
- path.quadTo(1, 2, 2, 2);
- path.close();
-</div>
-
-<div id="testQuadratic77">
- path.moveTo(0, 0);
- path.quadTo(1, 0, 1, 1);
- path.lineTo(3, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.quadTo(0, 1, 3, 2);
- path.close();
-</div>
-
-<div id="testQuadratic78">
- path.moveTo(0, 0);
- path.quadTo(1, 0, 1, 2);
- path.lineTo(3, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(2, 1, 0, 2);
- path.close();
-</div>
-
-<div id="testQuadratic79">
- path.moveTo(0, 0);
- path.quadTo(1, 0, 1, 2);
- path.lineTo(3, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.quadTo(0, 1, 3, 2);
- path.close();
-</div>
-
-<div id="testQuadratic80">
- path.moveTo(0, 0);
- path.quadTo(1, 0, 2, 3);
- path.lineTo(2, 3);
- path.close();
- path.moveTo(1, 0);
- path.lineTo(3, 0);
- path.quadTo(0, 1, 1, 1);
- path.close();
-</div>
-
-<div id="testQuadratic81">
- path.moveTo(0, 0);
- path.quadTo(2, 0, 1, 1);
- path.lineTo(1, 1);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(2, 1, 0, 2);
- path.close();
-</div>
-
-<div id="testQuadratic82">
- path.moveTo(0, 0);
- path.quadTo(2, 0, 1, 1);
- path.lineTo(0, 3);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(2, 1, 0, 2);
- path.close();
-</div>
-
-<div id="testQuadratic83">
- path.moveTo(0, 0);
- path.quadTo(0, 0, 2, 0);
- path.lineTo(2, 2);
- path.close();
- path.moveTo(0, 1);
- path.lineTo(0, 2);
- path.quadTo(2, 2, 1, 3);
- path.close();
-</div>
-
-<div id="testQuadratic84">
- path.moveTo(0, 0);
- path.quadTo(2, 0, 1, 1);
- path.lineTo(2, 1);
- path.close();
- path.moveTo(1, 0);
- path.lineTo(2, 0);
- path.quadTo(0, 1, 2, 2);
- path.close();
-</div>
-
-<div id="testQuadratic85">
- path.moveTo(0, 0);
- path.quadTo(3, 0, 1, 1);
- path.lineTo(1, 1);
- path.close();
- path.moveTo(1, 0);
- path.lineTo(3, 0);
- path.quadTo(0, 1, 1, 2);
- path.close();
-</div>
-
-<div id="testQuadratic86">
- path.moveTo(0, 0);
- path.quadTo(0, 1, 1, 1);
- path.lineTo(2, 3);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.quadTo(1, 1, 1, 3);
- path.close();
-</div>
-
-<div id="testQuadratic87">
- path.moveTo(0, 0);
- path.quadTo(2, 1, 0, 2);
- path.lineTo(2, 3);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 1);
- path.quadTo(0, 2, 3, 2);
- path.close();
-</div>
-
-<div id="testQuadratic88">
- path.moveTo(0, 0);
- path.quadTo(2, 1, 0, 2);
- path.lineTo(2, 2);
- path.close();
- path.moveTo(1, 0);
- path.lineTo(1, 1);
- path.quadTo(0, 2, 2, 2);
- path.close();
-</div>
-
-<div id="testQuadratic89x">
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0, 0);
- path.quadTo(3, 1, 2, 2);
- path.lineTo(0, 3);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(2, 1);
- path.quadTo(3, 1, 3, 3);
- path.close();
-</div>
-
-<div id="testQuadratic90x">
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(0, 0);
- path.quadTo(3, 0, 2, 2);
- path.lineTo(1, 3);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(0, 1);
- path.quadTo(3, 2, 2, 3);
- path.close();
-</div>
-
-<div id="testQuadratic91">
- path.moveTo(0, 0);
- path.quadTo(3, 2, 2, 3);
- path.lineTo(2, 3);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(1, 1);
- path.quadTo(2, 1, 2, 3);
- path.close();
-</div>
-
-<div id="testQuadratic92x">
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(1, 0);
- path.quadTo(3, 0, 2, 2);
- path.lineTo(2, 2);
- path.close();
- path.moveTo(2, 0);
- path.lineTo(0, 1);
- path.quadTo(3, 2, 2, 3);
- path.close();
-</div>
-
-<div id="testLine82">
- path.addRect(20, 0, 40, 40, SkPath::kCCWDirection);
- path.addRect(24, 20, 36, 30, SkPath::kCCWDirection);
- path.addRect(24, 32, 33, 36, SkPath::kCCWDirection);
-</div>
-
-<div id="testLine82a">
- SkPath path;
- path.addRect(0, 0, 6, 10, SkPath::kCW_Direction);
- path.addRect(2, 2, 4, 4, SkPath::kCW_Direction);
- path.addRect(2, 6, 4, 8, SkPath::kCW_Direction);
- testSimplifyx(path);
-</div>
-
-<div id="testLine82b">
- SkPath path;
- path.addRect(0, 0, 6, 10, SkPath::kCW_Direction);
- path.addRect(2, 2, 4, 4, SkPath::kCW_Direction);
- path.addRect(2, 6, 4, 8, SkPath::kCCW_Direction);
- testSimplifyx(path);
-</div>
-
-<div id="testLine82c">
- SkPath path;
- path.addRect(0, 0, 6, 10, SkPath::kCW_Direction);
- path.addRect(2, 2, 4, 4, SkPath::kCCW_Direction);
- path.addRect(2, 6, 4, 8, SkPath::kCW_Direction);
- testSimplifyx(path);
-</div>
-
-
-<div id="testLine82d">
- SkPath path;
- path.addRect(0, 0, 6, 10, SkPath::kCW_Direction);
- path.addRect(2, 2, 4, 4, SkPath::kCCW_Direction);
- path.addRect(2, 6, 4, 8, SkPath::kCCW_Direction);
- testSimplifyx(path);
-</div>
-
-<div id="testLine82e">
- SkPath path;
- path.addRect(0, 0, 6, 10, SkPath::kCCW_Direction);
- path.addRect(2, 2, 4, 4, SkPath::kCW_Direction);
- path.addRect(2, 6, 4, 8, SkPath::kCW_Direction);
- testSimplifyx(path);
-</div>
-
-<div id="testLine82f">
- SkPath path;
- path.addRect(0, 0, 6, 10, SkPath::kCCW_Direction);
- path.addRect(2, 2, 4, 4, SkPath::kCW_Direction);
- path.addRect(2, 6, 4, 8, SkPath::kCCW_Direction);
- testSimplifyx(path);
-</div>
-
-<div id="testLine82g">
- SkPath path;
- path.addRect(0, 0, 6, 10, SkPath::kCCW_Direction);
- path.addRect(2, 2, 4, 4, SkPath::kCCW_Direction);
- path.addRect(2, 6, 4, 8, SkPath::kCW_Direction);
- testSimplifyx(path);
-</div>
-
-<div id="testLine82h">
- SkPath path;
- path.addRect(0, 0, 6, 10, SkPath::kCCW_Direction);
- path.addRect(2, 2, 4, 4, SkPath::kCCW_Direction);
- path.addRect(2, 6, 4, 8, SkPath::kCCW_Direction);
- testSimplifyx(path);
-</div>
-
-<div id="testLine83">
-path.addRect(10, 30, 30, 40, SkPath::kCCW_Direction);
-path.addRect(0, 12, 12, 18, SkPath::kCCW_Direction);
-path.addRect(4, 13, 13, 16, SkPath::kCCW_Direction);
-</div>
-
-<div id="testLine84x">
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.addRect(0, 12, 60, 30, SkPath::kCCW_Direction);
- path.addRect(10, 20, 40, 30, SkPath::kCCW_Direction);
- path.addRect(0, 12, 12, 12, SkPath::kCCW_Direction);
- path.addRect(4, 12, 13, 13, SkPath::kCCW_Direction);
-</div>
-
-<div id="testLine85">
- path.addRect(36, 0, 66, 60, SkPath::kCCW_Direction);
- path.addRect(20, 0, 40, 40, SkPath::kCCW_Direction);
- path.addRect(12, 0, 24, 24, SkPath::kCCW_Direction);
- path.addRect(32, 0, 36, 41, SkPath::kCCW_Direction);
-</div>
-
-<div id="testQuadralateral1">
- path.moveTo(0, 0);
- path.lineTo(0, 0);
- path.lineTo(0, 0);
- path.lineTo(3, 2);
- path.close();
- path.moveTo(0, 0);
- path.lineTo(2, 1);
- path.lineTo(2, 2);
- path.lineTo(2, 3);
- path.close();
-</div>
-
-<div id="testCubic1">
- path.moveTo(0, 0);
- path.cubicTo(0, 1, 1, 1, 1, 0);
- path.close();
- path.moveTo(1, 0);
- path.cubicTo(0, 0, 0, 1, 1, 1);
- path.close();
-</div>
-
-<div id="testQuadratic93">
- path.moveTo(3, 0);
- path.quadTo(0, 1, 3, 2);
- path.lineTo(0, 3);
- path.close();
- path.moveTo(1, 0);
- path.lineTo(2, 0);
- path.quadTo(1, 1, 2, 2);
- path.close();
-</div>
-
-<div id="cubicOp1d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(0,2, 1,0, 1,0);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,1);
- pathB.cubicTo(0,1, 1,0, 2,0);
- pathB.close();
-</div>
-
-<div id="cubicOp2d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,2);
- path.cubicTo(0,1, 1,0, 1,0);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,1);
- pathB.cubicTo(0,1, 2,0, 1,0);
- pathB.close();
-</div>
-
-<div id="cubicOp3d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(2,3, 1,0, 1,0);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,1);
- pathB.cubicTo(0,1, 1,0, 3,2);
- pathB.close();
-</div>
-
-<div id="cubicOp4d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(0,2, 1,0, 2,0);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,1);
- pathB.cubicTo(0,2, 1,0, 2,0);
- pathB.close();
-</div>
-
-<div id="cubicOp5d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(0,2, 1,0, 2,0);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,1);
- pathB.cubicTo(0,2, 1,0, 2,0);
- pathB.close();
-</div>
-
-<div id="cubicOp6d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(0,6, 1,0, 3,0);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,1);
- pathB.cubicTo(0,3, 1,0, 6,0);
- pathB.close();
-</div>
-
-<div id="cubicOp7d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(3,4, 1,0, 3,0);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,1);
- pathB.cubicTo(0,3, 1,0, 4,3);
- pathB.close();
-</div>
-
-<div id="cubicOp8d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(0,5, 1,0, 4,0);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,1);
- pathB.cubicTo(0,4, 1,0, 5,0);
- pathB.close();
-</div>
-
-<div id="cubicOp9d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(1,6, 1,0, 2,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,1);
- pathB.cubicTo(1,2, 1,0, 6,1);
- pathB.close();
-</div>
-
-<div id="quadOp9d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.quadTo(1,6, 1.5f,1);
- path.quadTo(1.5f,0.8f, 2,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,1);
- pathB.quadTo(1,2, 1.4f,1);
- pathB.quadTo(3,0.4f, 6,1);
- pathB.close();
-</div>
-
-<div id="lineOp9d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.lineTo(1,6);
- path.lineTo(1.5f,1);
- path.lineTo(1.8f,0.8f);
- path.lineTo(2,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,1);
- pathB.lineTo(1,2);
- pathB.lineTo(1.4f,1);
- pathB.lineTo(3,0.4f);
- pathB.lineTo(6,1);
- pathB.close();
-</div>
-
-<div id="cubicOp1i">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(1,2, 1,0, 2,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,1);
- pathB.cubicTo(1,2, 1,0, 2,1);
- pathB.close();
-</div>
-
-<div id="cubicOp10d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(1,3, 1,0, 4,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,1);
- pathB.cubicTo(1,4, 1,0, 3,1);
- pathB.close();
-</div>
-
-<div id="cubicOp11d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(3,4, 1,0, 5,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,1);
- pathB.cubicTo(1,5, 1,0, 4,3);
- pathB.close();
-</div>
-
-<div id="cubicOp12d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(1,6, 1,0, 1,0);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,1);
- pathB.cubicTo(0,1, 1,0, 6,1);
- pathB.close();
-</div>
-
-<div id="cubicOp13d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(4,5, 1,0, 5,3);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,1);
- pathB.cubicTo(3,5, 1,0, 5,4);
- pathB.close();
-</div>
-
-<div id="cubicOp14d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(0,2, 2,0, 2,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,2);
- pathB.cubicTo(1,2, 1,0, 2,0);
- pathB.close();
-</div>
-
-<div id="cubicOp15d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(3,6, 2,0, 2,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,2);
- pathB.cubicTo(1,2, 1,0, 6,3);
- pathB.close();
-</div>
-
-<div id="cubicOp16d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,2);
- path.cubicTo(0,1, 3,0, 1,0);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,3);
- pathB.cubicTo(0,1, 2,0, 1,0);
- pathB.close();
-</div>
-
-<div id="cubicOp17d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,2);
- path.cubicTo(0,2, 4,0, 2,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,4);
- pathB.cubicTo(1,2, 2,0, 2,0);
- pathB.close();
-</div>
-
-<div id="cubicOp18d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(3,5, 2,0, 2,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,2);
- pathB.cubicTo(1,2, 1,0, 5,3);
- pathB.close();
-</div>
-
-<div id="cubicOp19i">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,2);
- path.cubicTo(0,1, 2,1, 6,2);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(1,2);
- pathB.cubicTo(2,6, 2,0, 1,0);
- pathB.close();
-</div>
-
-<div id="cubicOp20d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(0,1, 6,0, 2,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,6);
- pathB.cubicTo(1,2, 1,0, 1,0);
- pathB.close();
-</div>
-
-<div id="cubicOp21d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(0,1, 2,1, 6,5);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(1,2);
- pathB.cubicTo(5,6, 1,0, 1,0);
- pathB.close();
-</div>
-
-<div id="cubicOp22d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(2,3, 3,0, 2,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,3);
- pathB.cubicTo(1,2, 1,0, 3,2);
- pathB.close();
-</div>
-
-<div id="cubicOp23d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(1,2, 4,0, 2,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,4);
- pathB.cubicTo(1,2, 1,0, 2,1);
- pathB.close();
-</div>
-
-<div id="cubicOp24d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(1,2, 2,0, 3,2);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,2);
- pathB.cubicTo(2,3, 1,0, 2,1);
- pathB.close();
-</div>
-
-<div id="cubicOp25i">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(2,4, 5,0, 3,2);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,5);
- pathB.cubicTo(2,3, 1,0, 4,2);
- pathB.close();
-</div>
-
-<div id="cubicOp26d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(3,4, 4,0, 3,2);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,4);
- pathB.cubicTo(2,3, 1,0, 4,3);
- pathB.close();
-</div>
-
-<div id="cubicOp27d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(3,6, 1,0, 5,2);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,1);
- pathB.cubicTo(2,5, 1,0, 6,3);
- pathB.close();
-</div>
-
-<div id="cubicOp28u">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(1,4, 6,0, 3,2);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,6);
- pathB.cubicTo(2,3, 1,0, 4,1);
- pathB.close();
-</div>
-
-<div id="cubicOp29d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(2,5, 6,0, 4,2);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,6);
- pathB.cubicTo(2,4, 1,0, 5,2);
- pathB.close();
-</div>
-
-<div id="cubicOp30d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(2,5, 6,0, 5,3);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,6);
- pathB.cubicTo(3,5, 1,0, 5,2);
- pathB.close();
-</div>
-
-<div id="cubicOp31d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,2);
- path.cubicTo(0,3, 2,1, 4,0);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(1,2);
- pathB.cubicTo(0,4, 2,0, 3,0);
- pathB.close();
-</div>
-
-<div id="cubicOp32d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(1,2, 6,0, 3,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,6);
- pathB.cubicTo(1,3, 1,0, 2,1);
- pathB.close();
-</div>
-
-<div id="cubicOp33i">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(1,2, 6,0, 3,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,6);
- pathB.cubicTo(1,3, 1,0, 2,1);
- pathB.close();
-</div>
-
-<div id="cubicOp34d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(3,5, 2,1, 3,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(1,2);
- pathB.cubicTo(1,3, 1,0, 5,3);
- pathB.close();
-</div>
-
-<div id="cubicOp35d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(1,5, 2,1, 4,0);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(1,2);
- pathB.cubicTo(0,4, 1,0, 5,1);
- pathB.close();
-</div>
-
-<div id="cubicOp36u">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(1,6, 2,0, 5,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,2);
- pathB.cubicTo(1,5, 1,0, 6,1);
- pathB.close();
-</div>
-
-<div id="cubicOp37d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(2,6, 6,1, 4,3);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(1,6);
- pathB.cubicTo(3,4, 1,0, 6,2);
- pathB.close();
-</div>
-
-<div id="cubicOp38d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(0,6, 3,2, 4,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(2,3);
- pathB.cubicTo(1,4, 1,0, 6,0);
- pathB.close();
-</div>
-
-<div id="cubicOp39d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(2,3, 5,1, 4,3);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(1,5);
- pathB.cubicTo(3,4, 1,0, 3,2);
- pathB.close();
-</div>
-
-<div id="cubicOp40d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(1,5, 3,2, 4,2);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(2,3);
- pathB.cubicTo(2,4, 1,0, 5,1);
- pathB.close();
-</div>
-
-<div id="cubicOp41i">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(2,6, 4,3, 6,4);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(3,4);
- pathB.cubicTo(4,6, 1,0, 6,2);
- pathB.close();
-</div>
-
-<div id="cubicOp42d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(1,2, 6,5, 5,4);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(5,6);
- pathB.cubicTo(4,5, 1,0, 2,1);
- pathB.close();
-</div>
-
-<div id="cubicOp43d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,2);
- path.cubicTo(1,2, 4,0, 3,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,4);
- pathB.cubicTo(1,3, 2,0, 2,1);
- pathB.close();
-</div>
-
-<div id="cubicOp44d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,2);
- path.cubicTo(3,6, 4,0, 3,2);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,4);
- pathB.cubicTo(2,3, 2,0, 6,3);
- pathB.close();
-</div>
-
-<div id="cubicOp45d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,2);
- path.cubicTo(2,4, 4,0, 3,2);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,4);
- pathB.cubicTo(2,3, 2,0, 4,2);
- pathB.close();
-</div>
-
-<div id="cubicOp46d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,2);
- path.cubicTo(3,5, 5,0, 4,2);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,5);
- pathB.cubicTo(2,4, 2,0, 5,3);
- pathB.close();
-</div>
-
-<div id="cubicOp47d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(1,6, 6,2, 5,4);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(2,6);
- pathB.cubicTo(4,5, 1,0, 6,1);
- pathB.close();
-</div>
-
-<div id="cubicOp48d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,2);
- path.cubicTo(2,3, 5,1, 3,2);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(1,5);
- pathB.cubicTo(2,3, 2,0, 3,2);
- pathB.close();
-</div>
-
-<div id="cubicOp49d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,2);
- path.cubicTo(1,5, 3,2, 4,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(2,3);
- pathB.cubicTo(1,4, 2,0, 5,1);
- pathB.close();
-</div>
-
-<div id="cubicOp50d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,3);
- path.cubicTo(1,6, 5,0, 5,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,5);
- pathB.cubicTo(1,5, 3,0, 6,1);
- pathB.close();
-</div>
-
-<div id="cubicOp51d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,3);
- path.cubicTo(1,2, 4,1, 6,0);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(1,4);
- pathB.cubicTo(0,6, 3,0, 2,1);
- pathB.close();
-</div>
-
-<div id="cubicOp52d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,2);
- path.cubicTo(1,2, 5,4, 4,3);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(4,5);
- pathB.cubicTo(3,4, 2,0, 2,1);
- pathB.close();
-</div>
-
-<div id="cubicOp53d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,3);
- path.cubicTo(1,2, 5,3, 2,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(3,5);
- pathB.cubicTo(1,2, 3,0, 2,1);
- pathB.close();
-</div>
-
-<div id="cubicOp54d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,4);
- path.cubicTo(1,3, 5,4, 4,2);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(4,5);
- pathB.cubicTo(2,4, 4,0, 3,1);
- pathB.close();
-</div>
-
-<div id="cubicOp55d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,5);
- path.cubicTo(1,3, 3,2, 5,0);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(2,3);
- pathB.cubicTo(0,5, 5,0, 3,1);
- pathB.close();
-</div>
-
-<div id="cubicOp56d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(2,6, 5,0, 2,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,5);
- pathB.cubicTo(1,2, 1,0, 6,2);
- pathB.close();
-</div>
-
-<div id="cubicOp57d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,5);
- path.cubicTo(0,5, 5,4, 6,4);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(4,5);
- pathB.cubicTo(4,6, 5,0, 5,0);
- pathB.close();
-</div>
-
-<div id="cubicOp58d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,5);
- path.cubicTo(3,4, 6,5, 5,3);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(5,6);
- pathB.cubicTo(3,5, 5,0, 4,3);
- pathB.close();
-</div>
-
-<div id="cubicOp59d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(5,6, 4,0, 4,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,4);
- pathB.cubicTo(1,4, 1,0, 6,5);
- pathB.close();
-</div>
-
-<div id="cubicOp60d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,2);
- path.cubicTo(4,6, 6,0, 5,2);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,6);
- pathB.cubicTo(2,5, 2,0, 6,4);
- pathB.close();
-</div>
-
-<div id="cubicOp61d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(1,2);
- path.cubicTo(0,5, 3,2, 6,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(2,3);
- pathB.cubicTo(1,6, 2,1, 5,0);
- pathB.close();
-</div>
-
-<div id="cubicOp62d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(1,3);
- path.cubicTo(5,6, 5,3, 5,4);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(3,5);
- pathB.cubicTo(4,5, 3,1, 6,5);
- pathB.close();
-</div>
-
-<div id="cubicOp63d">
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(2,3);
- path.cubicTo(0,4, 3,2, 5,3);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(2,3);
- pathB.cubicTo(3,5, 3,2, 4,0);
- pathB.close();
-</div>
-
-<div id="testQuadratic94">
- SkPath path;
- path.moveTo(0, 0);
- path.lineTo(8, 8);
- path.quadTo(8, 4, 4, 4);
- path.quadTo(4, 0, 0, 0);
- path.close();
- testSimplify(reporter, path);
-</div>
-
-<div id="testQuadratic95">
- SkPath path;
- path.moveTo(8, 8);
- path.lineTo(0, 0);
- path.quadTo(4, 0, 4, 4);
- path.quadTo(8, 4, 8, 8);
- path.close();
- testSimplify(reporter, path);
-</div>
-
-<div id="testQuadratic96">
- SkPath path;
- path.moveTo(8, 0);
- path.lineTo(0, 8);
- path.quadTo(0, 4, 4, 4);
- path.quadTo(4, 0, 8, 0);
- path.close();
- testSimplify(reporter, path);
-</div>
-
-<div id="testQuadratic97">
- SkPath path;
- path.moveTo(0, 8);
- path.lineTo(8, 0);
- path.quadTo(4, 0, 4, 4);
- path.quadTo(0, 4, 0, 8);
- path.close();
- testSimplify(reporter, path);
-</div>
-
-<div id="testTriangle2">
- path.moveTo(0, 0);
- path.lineTo(1, 0);
- path.lineTo(3, 3);
- path.close();
- path.moveTo(1, 1);
- path.lineTo(2, 3);
- path.lineTo(1, 2);
- path.close();
-</div>
-
-</div>
-
-<script type="text/javascript">
-
-var testDivs = [
- testTriangle2,
- testQuadratic97,
- testQuadratic96,
- testQuadratic95,
- testQuadratic94,
- testLine16,
- cubicOp63d,
- cubicOp62d,
- cubicOp61d,
- cubicOp60d,
- cubicOp59d,
- cubicOp58d,
- cubicOp57d,
- cubicOp56d,
- cubicOp55d,
- cubicOp54d,
- cubicOp53d,
- cubicOp52d,
- cubicOp51d,
- cubicOp50d,
- cubicOp49d,
- cubicOp48d,
- cubicOp47d,
- cubicOp46d,
- cubicOp45d,
- cubicOp44d,
- cubicOp43d,
- cubicOp42d,
- cubicOp41i,
- cubicOp40d,
- cubicOp39d,
- cubicOp38d,
- cubicOp37d,
- cubicOp36u,
- cubicOp35d,
- cubicOp34d,
- cubicOp33i,
- cubicOp32d,
- cubicOp31d,
- cubicOp30d,
- cubicOp29d,
- cubicOp28u,
- cubicOp27d,
- cubicOp26d,
- cubicOp25i,
- cubicOp24d,
- cubicOp23d,
- cubicOp18d,
- cubicOp15d,
- cubicOp14d,
- cubicOp13d,
- cubicOp11d,
- cubicOp9d,
- cubicOp8d,
- cubicOp7d,
- cubicOp6d,
- cubicOp5d,
- cubicOp10d,
- cubicOp22d,
- cubicOp21d,
- cubicOp20d,
- cubicOp19i,
- cubicOp17d,
- cubicOp16d,
- cubicOp12d,
- cubicOp1i,
- lineOp9d,
- quadOp9d,
- cubicOp4d,
- cubicOp3d,
- cubicOp2d,
- cubicOp1d,
- testQuadratic93,
- testCubic1,
- testQuadralateral1,
- testLine85,
- testLine84x,
- testLine83,
- testLine82h,
- testLine82g,
- testLine82f,
- testLine82e,
- testLine82d,
- testLine82c,
- testLine82b,
- testLine82a,
- testLine82,
- testQuadratic92x,
- testQuadratic91,
- testQuadratic90x,
- testQuadratic89x,
- testQuadratic88,
- testQuadratic87,
- testQuadratic86,
- testQuadratic85,
- testQuadratic84,
- testQuadratic83,
- testQuadratic82,
- testQuadratic81,
- testQuadratic80,
- testQuadratic79,
- testQuadratic78,
- testQuadratic77,
- testQuadratic76,
- testQuadratic75,
- testQuadratic74,
- testQuadratic73,
- testQuadratic72,
- testQuadratic71,
- testQuadratic70x,
- testQuadratic69,
- testQuadratic68,
- testQuadratic67x,
- testQuadratic66,
- testQuadratic65,
- testQuadratic64,
- testQuadratic63,
- testLine1a,
- testQuadratic62x,
- testLine81,
- testQuadratic61,
- testQuadratic60,
- testQuadratic59,
- testQuadratic59o,
- testQuadratic59s,
- testQuadratic58o,
- testQuadratic58a,
- testQuadratic58s,
- testQuadratic57o,
- testQuadratic57s,
- testQuadratic56o,
- testQuadratic56s,
- testQuadratic55o,
- testQuadratic55s,
- testQuadratic54,
- testQuadratic53o,
- testQuadratic53s,
- testQuadratic52sa,
- testQuadratic52sb,
- testQuadratic52sc,
- testQuadratic52o,
- testQuadratic52s,
- testQuadratic51,
- testQuadratic50o,
- testQuadratic50s,
- testQuadratic49s,
- testQuadratic48o,
- testQuadratic48s,
- testQuadratic47o,
- testQuadratic47s,
- testQuadratic46o,
- testQuadratic46s,
- testQuadratic45o,
- testQuadratic45s,
- testQuadratic44o,
- testQuadratic44s,
- testQuadratic43o,
- testQuadratic43s,
- testQuadratic42o,
- testQuadratic42s,
- testQuadratic41o,
- testQuadratic41s,
- testQuadratic40xb,
- testQuadratic40xa,
- testQuadratic40x,
- testQuadratic39,
- testQuadratic39a,
- testQuadratic38,
- testQuadratic37,
- testQuadratic36,
- testQuadratic35,
- testQuadratic34,
- testQuadratic33,
- testQuadratic32,
- testQuadratic31,
- testQuadratic30,
- testQuadratic29,
- testQuadratic28,
- testQuadratic27,
- testQuadratic26,
- testQuadratic25,
- testQuadratic24,
- testQuadratic23,
- testQuadratic22,
- testQuadratic21,
- testQuadratic20,
- testQuadratic19,
- testQuadratic18,
- testQuadratic17x,
- testQuadratic16b,
- testQuadratic16a,
- testQuadratic15,
- testQuadratic14,
- testQuadratic13b,
- testQuadratic13a,
- testQuadratic12,
- testQuadratic11b,
- testQuadratic11a,
- testQuadratic10b,
- testQuadratic10a,
- testQuadratic9a,
- testQuadratic9,
- testQuadratic8,
- testQuadratic7,
- testQuadratic6,
- testQuadratic5,
- testQuadratic4x,
- testQuadratic3,
- testQuadratic2,
- testQuadratic1,
- testLine4x,
- testLine3x,
- testLine2x,
- testLine1x,
- testQuadralateral9,
- testQuadralateral8,
- testQuadralateral7,
- testFauxQuadralateral6d,
- testFauxQuadralateral6c,
- testFauxQuadralateral6b,
- testFauxQuadralateral6a,
- testFauxQuadralateral6,
- testQuadralateral6a,
- testQuadralateral6,
- testQuadralateral5,
- testNondegenerate4,
- testNondegenerate3,
- testNondegenerate2,
- testNondegenerate1,
- testDegenerate4,
- testDegenerate3,
- testDegenerate2,
- testDegenerate1,
- testLine79,
- testLine78,
- testLine77,
- testLine76,
- testLine75,
- testLine74,
- testLine73,
- testLine72,
- testLine71,
- testLine70,
- testLine69,
- testLine68f,
- testLine68e,
- testLine68d,
- testLine68c,
- testLine68b,
- testLine68a,
- testLine67,
- testLine66,
- testLine65,
- testLine64,
- testLine63,
- testLine62,
- testLine61,
- testLine60,
- testLine59,
- testLine58,
- testLine57,
- testLine56,
- testLine55,
- testLine54,
- testLine53,
- testLine52,
- testLine51,
- testLine50,
- testLine49,
- testLine48,
- testLine47,
- testLine46,
- testLine45,
- testLine44,
- testLine43,
- testLine42,
- testLine41,
- testLine40,
- testLine39,
- testLine38,
- testLine37,
- testLine36,
- testLine35,
- testLine34,
- testLine33,
- testLine32,
- testLine31,
- testLine30,
- testLine29,
- testLine28,
- testLine24,
- testLine22,
- testLine19,
- testLine17,
- testLine16,
- testLine13,
- testLine12,
- testLine9,
- testLine7b,
- testLine7,
- testLine6,
- testLine5,
- testSimplifyQuadratic21,
- testSimplifyQuadratic20,
- testSimplifyQuadratic19,
- testSimplifyQuadratic18,
- testSimplifyQuadratic17,
- testSimplifyQuadratic16,
- testSimplifyQuadratic15,
- testSimplifyQuadratic14,
- testSimplifyQuadratic13,
- testSimplifyQuadratic12,
- testSimplifyQuadratic11,
- testSimplifyQuadratic10,
- testSimplifyQuadratic9,
- testSimplifyQuadratic8,
- testSimplifyQuadratic7,
- testSimplifyQuadratic6,
- testSimplifyQuadratic5,
- testSimplifyQuadratic4,
- testSimplifyQuadratic3,
- testSimplifyQuadratic2,
- testSimplifyQuadratic1,
-];
-
-var scale, columns, rows, xStart, yStart;
-
-var ticks = 0.1;
-var at_x = 13 + 0.5;
-var at_y = 13 + 0.5;
-var decimal_places = 0; // make this 3 to show more precision
-
-var tests = [];
-var testTitles = [];
-var testIndex = 0;
-var hasXor = false;
-var draw_labels = true;
-
-var ctx;
-
-function parse(test, title) {
- var contours = [];
- var contourStrs = test.split("path.close();");
- var pattern = /-?\d+\.*\d*/g;
- hasXor = test.split("kEvenOdd_FillType").length > 1;
- for (var c in contourStrs) {
- var contour = contourStrs[c];
- var verbStrs = contour.split("path");
- var verbs = [];
- for (var v in verbStrs) {
- var verbStr = verbStrs[v];
- var points = verbStr.match(pattern);
- var pts = [];
- for (var wd in points) {
- var num = parseFloat(points[wd]);
- if (isNaN(num)) continue;
- pts.push(num);
- }
- if (pts.length > 0)
- verbs.push(pts);
- }
- if (verbs.length > 0) {
- var lastIndex = verbs.length - 1;
- var lastVerb = verbs[lastIndex];
- var lastLen = lastVerb.length;
- if (verbs[0][0] != lastVerb[lastLen - 2] && verbs[0][1] != lastVerb[lastLen - 1]) {
- var lastPts = [];
- lastPts.push(verbs[0][0]);
- lastPts.push(verbs[0][1]);
- verbs.push(lastPts);
- }
- contours.push(verbs);
- }
- }
- if (contours.length > 0) {
- tests.push(contours);
- testTitles.push(title);
- }
-}
-
-function parseRect(test, title) {
- var contours = [];
- var rectStrs = test.split("path.addRect");
- var pattern = /-?\d+\.*\d*/g;
- hasXor = test.split("kEvenOdd_FillType").length > 1;
- for (var r in rectStrs) {
- var rect = rectStrs[r];
- var sideStrs = rect.match(pattern);
- var ccw = rect.split("kCCW_Direction").length > 1;
- var sides = [];
- for (var wd in sideStrs) {
- var num = parseFloat(sideStrs[wd]);
- if (isNaN(num)) continue;
- sides.push(num);
- }
- if (sides.length == 0)
- continue;
- var verbs = [];
- var topLeft = [];
- topLeft.push(sides[0]); topLeft.push(sides[1]);
- var topRight = [];
- topRight.push(sides[2]); topRight.push(sides[1]);
- var botLeft = [];
- botLeft.push(sides[0]); botLeft.push(sides[3]);
- var botRight = [];
- botRight.push(sides[2]); botRight.push(sides[3]);
- verbs.push(topLeft);
- if (!ccw) {
- verbs.push(topRight);
- verbs.push(botRight);
- verbs.push(botLeft);
- } else {
- verbs.push(botLeft);
- verbs.push(botRight);
- verbs.push(topRight);
- }
- verbs.push(topLeft);
- contours.push(verbs);
- }
- if (contours.length > 0) {
- tests.push(contours);
- testTitles.push(title);
- }
-}
-
-function init(test) {
- var canvas = document.getElementById('canvas');
- if (!canvas.getContext) return;
- canvas.width = window.innerWidth - at_x;
- canvas.height = window.innerHeight - at_y;
- ctx = canvas.getContext('2d');
- var xmin = Infinity;
- var xmax = -Infinity;
- var ymin = Infinity;
- var ymax = -Infinity;
- for (var contours in test) {
- var contour = test[contours];
- for (var verbs in contour) {
- var verb = contour[verbs];
- var last = verb.length;
- for (var idx = 0; idx < last; idx += 2) {
- xmin = Math.min(xmin, verb[idx]);
- xmax = Math.max(xmax, verb[idx]);
- ymin = Math.min(ymin, verb[idx + 1]);
- ymax = Math.max(ymax, verb[idx + 1]);
- }
- }
- }
- var subscale = 1;
- while ((xmax - xmin) * subscale < 0.1 && (ymax - ymin) * subscale < 0.1) {
- subscale *= 10;
- }
- columns = Math.ceil(xmax) - Math.floor(xmin) + 1;
- rows = Math.ceil(ymax) - Math.floor(ymin) + 1;
- xStart = Math.floor(xmin);
- yStart = Math.floor(ymin);
- var hscale = ctx.canvas.width / columns / ticks;
- var vscale = ctx.canvas.height / rows / ticks;
- scale = Math.floor(Math.min(hscale, vscale)) * subscale;
-}
-
-function drawPoint(px, py, xoffset, yoffset, unit) {
- var label = px.toFixed(decimal_places) + ", " + py.toFixed(decimal_places);
- var _px = px * unit + xoffset;
- var _py = py * unit + yoffset;
- ctx.beginPath();
- ctx.arc(_px, _py, 3, 0, Math.PI*2, true);
- ctx.closePath();
- ctx.fill();
- ctx.fillText(label, _px + 5, _py);
-}
-
-function draw(test, title, _at_x, _at_y, scale) {
- ctx.fillStyle = "rgba(0,0,0, 0.1)";
- ctx.font = "normal 50px Arial";
- ctx.fillText(title, 50, 50);
- ctx.font = "normal 10px Arial";
-
- var unit = scale * ticks;
- ctx.lineWidth = 1;
- var i;
- for (i = 0; i <= rows * ticks; ++i) {
- ctx.strokeStyle = (i % ticks) != 0 ? "rgb(160,160,160)" : "black";
- ctx.beginPath();
- ctx.moveTo(_at_x + 0, _at_y + i * scale);
- ctx.lineTo(_at_x + unit * columns, _at_y + i * scale);
- ctx.stroke();
- }
- for (i = 0; i <= columns * ticks; ++i) {
- ctx.strokeStyle = (i % ticks) != 0 ? "rgb(160,160,160)" : "black";
- ctx.beginPath();
- ctx.moveTo(_at_x + i * scale, _at_y + 0);
- ctx.lineTo(_at_x + i * scale, _at_y + unit * rows);
- ctx.stroke();
- }
-
- var xoffset = xStart * -unit + _at_x;
- var yoffset = yStart * -unit + _at_y;
-
- ctx.fillStyle = "rgb(40,80,60)"
- for (i = 0; i <= columns; i += (1 / ticks))
- {
- num = (xoffset - _at_x) / -unit + i;
- ctx.fillText(num.toFixed(0), i * unit + _at_y - 5, 10);
- }
- for (i = 0; i <= rows; i += (1 / ticks))
- {
- num = (yoffset - _at_x) / -unit + i;
- ctx.fillText(num.toFixed(0), 0, i * unit + _at_y + 0);
- }
-
- ctx.strokeStyle = "red";
- var contours, verbs, pts;
- ctx.beginPath();
- for (contours in test) {
- var contour = test[contours];
- if (contours == 2) ctx.strokeStyle = "blue";
- var first = true;
- for (verbs in contour) {
- var verb = contour[verbs];
- switch (verb.length) {
- case 2:
- if (first) {
- ctx.moveTo(xoffset + verb[0] * unit, yoffset + verb[1] * unit);
- first = false;
- } else
- ctx.lineTo(xoffset + verb[0] * unit, yoffset + verb[1] * unit);
- break;
- case 4:
- ctx.quadraticCurveTo(xoffset + verb[0] * unit, yoffset + verb[1] * unit,
- xoffset + verb[2] * unit, yoffset + verb[3] * unit);
- break;
- case 6:
- ctx.bezierCurveTo(xoffset + verb[0] * unit, yoffset + verb[1] * unit,
- xoffset + verb[2] * unit, yoffset + verb[3] * unit,
- xoffset + verb[4] * unit, yoffset + verb[5] * unit);
- break;
- }
- }
- ctx.closePath();
- }
- // uncomment if ever part of the standard
- // ctx.fillRule=hasXor ? evenodd : nonzero;
- ctx.stroke();
- ctx.fillStyle="rgba(192,192,255, 0.3)";
- ctx.fill();
-
- if (!draw_labels) {
- return;
- }
- ctx.fillStyle="blue";
- for (contours in test) {
- var contour = test[contours];
- for (verbs in contour) {
- var verb = contour[verbs];
- for (i = 0; i < verb.length; i += 2) {
- x = verb[i];
- y = verb[i + 1];
- drawPoint(x, y, xoffset, yoffset, unit);
- }
- }
- }
-}
-
-var mouseX = Infinity, mouseY;
-
-function calcXY() {
- var e = window.event;
- var tgt = e.target || e.srcElement;
- var left = tgt.offsetLeft;
- var top = tgt.offsetTop;
- var unit = scale * ticks;
- mouseX = (e.clientX - left - Math.ceil(at_x) + 1) / unit + xStart;
- mouseY = (e.clientY - top - Math.ceil(at_y)) / unit + yStart;
-}
-
-function handleMouseOver() {
- calcXY();
- var num = mouseX.toFixed(3) + ", " + mouseY.toFixed(3);
- ctx.beginPath();
- ctx.rect(300,0,72,9);
- ctx.fillStyle="white";
- ctx.fill();
- ctx.fillStyle="black";
- ctx.fillText(num, 300, 7);
-}
-
-function handleMouseClick() {
- calcXY();
-// drawInset();
-}
-
-function drawTop() {
- init(tests[testIndex]);
- redraw();
-}
-
-function redraw() {
- ctx.beginPath();
- ctx.rect(0, 0, ctx.canvas.width, ctx.canvas.height);
- ctx.fillStyle="white";
- ctx.fill();
- draw(tests[testIndex], testTitles[testIndex], at_x, at_y, scale);
-// if (insetScale != scale && mouseX != Infinity)
-// drawInset();
-}
-
-function doKeyPress(evt) {
- var char = String.fromCharCode(evt.charCode);
- switch (char) {
- case 'N':
- testIndex += 9;
- case 'n':
- if (++testIndex >= tests.length)
- testIndex = 0;
- mouseX = Infinity;
- drawTop();
- break;
- case 'P':
- testIndex -= 9;
- case 'p':
- if (--testIndex < 0)
- testIndex = tests.length - 1;
- mouseX = Infinity;
- drawTop();
- break;
- case 'T':
- case 't':
- break;
- case '-':
- drawTop();
- break;
- case '=':
- case '+':
- drawTop();
- break;
- case 'x':
- draw_labels ^= true;
- drawTop();
- break;
- }
-}
-
-function start() {
- for (i = 0; i < testDivs.length; ++i) {
- var title = testDivs[i].id.toString();
- var str = testDivs[i].firstChild.data;
- if (str.split("addRect").length > 1) {
- parseRect(str, title);
- } else {
- parse(str, title);
- }
- }
- drawTop();
- window.addEventListener('keypress', doKeyPress, true);
- window.onresize = function() {
- drawTop();
- }
-}
-
-</script>
-</head>
-
-<body onLoad="start();">
-<canvas id="canvas" width="750" height="500"
- onmousemove="handleMouseOver()"
- onclick="handleMouseClick()"
- ></canvas >
-</body>
-</html>
diff --git a/experimental/Intersection/qc.htm b/experimental/Intersection/qc.htm
deleted file mode 100644
index bae06b76a1..0000000000
--- a/experimental/Intersection/qc.htm
+++ /dev/null
@@ -1,2883 +0,0 @@
-<html>
-<head>
-<div style="height:0">
-
-<div id="cubic1">
-$1 = (Cubic &) @0x297c40: {{x = 60.776536520932126, y = 71.249307306133829}, {x = 87.107894191103014, y = 22.377669868235323}, {x = 1.4974754310666936, y = 68.069569937917208}, {x = 45.261946574441133, y = 17.536076632112298}}
-$3 = {{{x = 60.776536520932126, y = 71.249307306133829}, {x = 66.996745328074098, y = 59.419614231505768}, {x = 65.760655441289899, y = 53.975522936482086}}, {{x = 65.760655441289899, y = 53.975522936482086}, {x = 64.524565554505699, y = 48.531431641458411}, {x = 59.040356119613065, y = 46.936502854722001}}, {{x = 59.040356119613065, y = 46.936502854722001}, {x = 53.556146684720431, y = 45.341574067985597}, {x = 47.031996847537108, y = 45.059368518219323}}, {{x = 47.031996847537108, y = 45.059368518219323}, {x = 40.29980253329046, y = 44.781843489000011}, {x = 35.915024002796116, y = 43.168182836391942}}, {{x = 35.915024002796116, y = 43.168182836391942}, {x = 31.530245472301775, y = 41.554522183783902}, {x = 32.992157437282373, y = 35.838141687728616}}, {{x = 32.992157437282373, y = 35.838141687728616}, {x = 34.454069402262967, y = 30.121761191673329}, {x = 45.261946574441133, y = 17.536076632112298}}}
-</div>
-
-<div id="cubic2">
-$1 = {{x = 73.565270739405079, y = 11.505317181118446}, {x = 69.865863057722279, y = 35.56041113825534}, {x = 63.830000657509075, y = 90.821050755130614}, {x = 29.400041480269302, y = 26.497158886164968}}
-</div>
-
-<div id="cubic3">
-$3 = {{x = 69.729201388419241, y = 38.687735162064307}, {x = 24.764868814854356, y = 23.150171257159752}, {x = 84.928319083959011, y = 90.258844099128083}, {x = 80.39277404565027, y = 61.35338524419506}}
-</div>
-
-<div id="cubic1x0">
-{{14.5975863, 41.632436}, {16.3518929, 26.2639684}, {18.5165519, 7.68775139}, {8.03767257, 89.1628526}},
-{{14.5975863, 41.632436}, {8.03767257, 89.1628526}, {8.03767257, 89.1628526}},
-</div>
-
-<div id="cubic1x0x">
-{{14.5975863, 41.632436}, {16.3518929, 26.2639684}, {18.5165519, 7.68775139}, {8.03767257, 89.1628526}},
-{{14.5975863, 41.632436}, {8.03767257, 89.1628526}, {8.03767257, 89.1628526}},
-</div>
-
-<div id="cubic1x1">
-{{32.0437334, 59.0267425}, {62.4615541, 91.340573}, {61.0102145, 98.6747985}, {27.3387826, 82.9194526}},
-{{32.0437334, 59.0267425}, {75.9425223, 105.66184}, {27.3387826, 82.9194526}},
-</div>
-
-<div id="cubic1x1x">
-{{32.0437334, 59.0267425}, {62.4615541, 91.340573}, {61.0102145, 98.6747985}, {27.3387826, 82.9194526}},
-{{32.0437334, 59.0267425}, {77.7581975, 107.02498}, {27.3387826, 82.9194526}},
-</div>
-
-<div id="cubic1x2">
-{{57.8949944, 41.1707465}, {56.7368674, 76.5309905}, {56.356649, 86.19953}, {55.5002867, 93.318629}},
-{{57.8949944, 41.1707465}, {55.5002867, 93.318629}, {55.5002867, 93.318629}},
-</div>
-
-<div id="cubic1x2x">
-{{57.8949944, 41.1707465}, {56.7368674, 76.5309905}, {56.356649, 86.19953}, {55.5002867, 93.318629}},
-{{57.8949944, 41.1707465}, {55.5002867, 93.318629}, {55.5002867, 93.318629}},
-</div>
-
-<div id="cubic1x3">
-{{41.1844187, 86.52533}, {31.2211043, 33.1005529}, {20.992908, 27.8044979}, {10.1965708, 73.7658388}},
-{{41.1844187, 86.52533}, {26.1439273, 5.87597256}, {10.1965708, 73.7658388}},
-</div>
-
-<div id="cubic1x3x">
-{{41.1844187, 86.52533}, {31.2211043, 33.1005529}, {20.992908, 27.8044979}, {10.1965708, 73.7658388}},
-{{41.1844187, 86.52533}, {26.3152619, 5.60599593}, {10.1965708, 73.7658388}},
-</div>
-
-<div id="cubic1x4">
-{{51.1608132, 59.7881237}, {58.9955693, 38.5338731}, {38.8048957, 93.8817224}, {70.1083283, 10.6741861}},
-{{51.1608132, 59.7881237}, {70.1083283, 10.6741861}, {70.1083283, 10.6741861}},
-</div>
-
-<div id="cubic1x4x">
-{{51.1608132, 59.7881237}, {58.9955693, 38.5338731}, {38.8048957, 93.8817224}, {70.1083283, 10.6741861}},
-{{51.1608132, 59.7881237}, {70.1083283, 10.6741861}, {70.1083283, 10.6741861}},
-</div>
-
-<div id="cubic1x5">
-{{9.45225228, 64.0040808}, {16.5855418, 53.2003115}, {37.6356814, 42.8968969}, {68.1461999, 33.1817941}},
-{{9.45225228, 64.0040808}, {19.5957859, 48.641127}, {68.1461999, 33.1817941}},
-</div>
-
-<div id="cubic1x5x">
-{{9.45225228, 64.0040808}, {16.5855418, 53.2003115}, {37.6356814, 42.8968969}, {68.1461999, 33.1817941}},
-{{9.45225228, 64.0040808}, {21.2663043, 47.7764376}, {68.1461999, 33.1817941}},
-</div>
-
-<div id="cubic1x6">
-{{96.2293269, 26.2973682}, {79.8675829, 34.4649929}, {53.1353046, 45.0651411}, {9.82676512, 58.4413866}},
-{{96.2293269, 26.2973682}, {67.554114, 40.6117577}, {9.82676512, 58.4413866}},
-</div>
-
-<div id="cubic1x6x">
-{{96.2293269, 26.2973682}, {79.8675829, 34.4649929}, {53.1353046, 45.0651411}, {9.82676512, 58.4413866}},
-{{96.2293269, 26.2973682}, {73.2381426, 38.4629118}, {9.82676512, 58.4413866}},
-</div>
-
-<div id="cubic1x7">
-{{77.9926032, 21.6823036}, {14.4765247, 6.95017395}, {11.5735665, 16.9314125}, {66.2493838, 53.3932579}},
-{{77.9926032, 21.6823036}, {-12.9236155, 0.594894684}, {66.2493838, 53.3932579}},
-</div>
-
-<div id="cubic1x7x">
-{{77.9926032, 21.6823036}, {14.4765247, 6.95017395}, {11.5735665, 16.9314125}, {66.2493838, 53.3932579}},
-{{77.9926032, 21.6823036}, {-16.5229284, -0.857700571}, {66.2493838, 53.3932579}},
-</div>
-
-<div id="cubic1x8">
-{{56.479229, 46.4012343}, {65.5444116, 4.92526628}, {78.9504195, 19.6997536}, {93.7579262, 89.4649302}},
-{{56.479229, 46.4012343}, {70.7547833, -18.9137695}, {93.7579262, 89.4649302}},
-</div>
-
-<div id="cubic1x8x">
-{{56.479229, 46.4012343}, {65.5444116, 4.92526628}, {78.9504195, 19.6997536}, {93.7579262, 89.4649302}},
-{{56.479229, 46.4012343}, {70.8118345, -15.4977762}, {93.7579262, 89.4649302}},
-</div>
-
-<div id="cubic1x9">
-{{14.1826743, 68.2075081}, {63.5890486, 41.1398453}, {37.3805687, 55.2173676}, {38.296851, 55.1751163}},
-{{14.1826743, 68.2075081}, {38.296851, 55.1751163}, {38.296851, 55.1751163}},
-</div>
-
-<div id="cubic1x9x">
-{{14.1826743, 68.2075081}, {63.5890486, 41.1398453}, {37.3805687, 55.2173676}, {38.296851, 55.1751163}},
-{{14.1826743, 68.2075081}, {38.296851, 55.1751163}, {38.296851, 55.1751163}},
-</div>
-
-<div id="cubic2x0">
-{{27.9052884, 4.18132628}, {75.550717, 80.9000193}, {86.6244633, 97.3541595}, {31.358766, 46.7795742}},
-{{27.9052884, 4.18132628}, {66.5480157, 66.4038653}, {68.2236994, 73.2154296}},
-{{68.2236994, 73.2154296}, {70.5412458, 82.636132}, {31.358766, 46.7795742}},
-</div>
-
-<div id="cubic2x0x">
-{{27.9052884, 4.18132628}, {75.550717, 80.9000193}, {86.6244633, 97.3541595}, {31.358766, 46.7795742}},
-{{27.9052884, 4.18132628}, {64.5696024, 61.9317264}, {68.2236994, 73.2154296}},
-{{68.2236994, 73.2154296}, {71.8777964, 84.4991328}, {31.358766, 46.7795742}},
-</div>
-
-<div id="cubic2x1">
-{{55.6607299, 89.8878963}, {45.872586, 80.5522712}, {42.0218181, 60.6961261}, {19.7918636, 41.8513322}},
-{{55.6607299, 89.8878963}, {52.7119153, 87.0754092}, {42.3919757, 69.4355526}},
-{{42.3919757, 69.4355526}, {32.6126647, 52.7197915}, {19.7918636, 41.8513322}},
-</div>
-
-<div id="cubic2x1x">
-{{55.6607299, 89.8878963}, {45.872586, 80.5522712}, {42.0218181, 60.6961261}, {19.7918636, 41.8513322}},
-{{55.6607299, 89.8878963}, {49.0795145, 82.5258065}, {42.3919757, 69.4355526}},
-{{42.3919757, 69.4355526}, {35.7044369, 56.3452986}, {19.7918636, 41.8513322}},
-</div>
-
-<div id="cubic2x2">
-{{80.5982112, 14.1354079}, {73.8005055, 65.0951435}, {54.0762929, 60.254824}, {2.82780649, 26.9437232}},
-{{80.5982112, 14.1354079}, {75.7174786, 50.7243473}, {58.3820516, 52.1411292}},
-{{58.3820516, 52.1411292}, {43.4686812, 53.3599624}, {2.82780649, 26.9437232}},
-</div>
-
-<div id="cubic2x2x">
-{{80.5982112, 14.1354079}, {73.8005055, 65.0951435}, {54.0762929, 60.254824}, {2.82780649, 26.9437232}},
-{{80.5982112, 14.1354079}, {76.0811121, 51.5011698}, {58.3820516, 52.1411292}},
-{{58.3820516, 52.1411292}, {40.6829911, 52.7810886}, {2.82780649, 26.9437232}},
-</div>
-
-<div id="cubic2x3">
-{{1.6014867, 16.1869736}, {54.4660745, 11.3148647}, {68.9317074, 35.2054791}, {98.4868263, 68.0902175}},
-{{1.6014867, 16.1869736}, {36.7068582, 12.9515906}, {58.7852073, 27.9797778}},
-{{58.7852073, 27.9797778}, {68.1927213, 34.3832403}, {98.4868263, 68.0902175}},
-</div>
-
-<div id="cubic2x3x">
-{{1.6014867, 16.1869736}, {54.4660745, 11.3148647}, {68.9317074, 35.2054791}, {98.4868263, 68.0902175}},
-{{1.6014867, 16.1869736}, {39.5784138, 13.1506607}, {58.7852073, 27.9797778}},
-{{58.7852073, 27.9797778}, {77.9920009, 42.808895}, {98.4868263, 68.0902175}},
-</div>
-
-<div id="cubic2x4">
-{{23.0453529, 23.2462522}, {99.7603064, 71.4695575}, {88.8529841, 52.1034408}, {2.52897437, 4.4722111}},
-{{23.0453529, 23.2462522}, {83.1995453, 61.0594014}, {73.9267748, 49.8046823}},
-{{73.9267748, 49.8046823}, {64.9578598, 38.9187642}, {2.52897437, 4.4722111}},
-</div>
-
-<div id="cubic2x4x">
-{{23.0453529, 23.2462522}, {99.7603064, 71.4695575}, {88.8529841, 52.1034408}, {2.52897437, 4.4722111}},
-{{23.0453529, 23.2462522}, {80.2001434, 58.1848465}, {73.9267748, 49.8046823}},
-{{73.9267748, 49.8046823}, {67.6534063, 41.424518}, {2.52897437, 4.4722111}},
-</div>
-
-<div id="cubic2x5">
-{{64.4519328, 43.6345262}, {65.4821636, 58.7228333}, {54.6599207, 69.286817}, {3.532848, 76.5762786}},
-{{64.4519328, 43.6345262}, {65.2901892, 55.9112614}, {53.5513792, 63.0299695}},
-{{53.5513792, 63.0299695}, {39.721686, 71.4166414}, {3.532848, 76.5762786}},
-</div>
-
-<div id="cubic2x5x">
-{{64.4519328, 43.6345262}, {65.4821636, 58.7228333}, {54.6599207, 69.286817}, {3.532848, 76.5762786}},
-{{64.4519328, 43.6345262}, {66.113742, 54.9117003}, {53.5513792, 63.0299695}},
-{{53.5513792, 63.0299695}, {40.9890164, 71.1482387}, {3.532848, 76.5762786}},
-</div>
-
-<div id="cubic2x6">
-{{82.5366784, 93.9543251}, {90.3418213, 74.9907304}, {69.20575, 41.039441}, {49.884656, 11.4126389}},
-{{82.5366784, 93.9543251}, {87.7472455, 81.2945847}, {76.383006, 56.6821848}},
-{{76.383006, 56.6821848}, {69.0501277, 40.8008111}, {49.884656, 11.4126389}},
-</div>
-
-<div id="cubic2x6x">
-{{82.5366784, 93.9543251}, {90.3418213, 74.9907304}, {69.20575, 41.039441}, {49.884656, 11.4126389}},
-{{82.5366784, 93.9543251}, {87.4294046, 79.1281234}, {76.383006, 56.6821848}},
-{{76.383006, 56.6821848}, {65.3366074, 34.2362462}, {49.884656, 11.4126389}},
-</div>
-
-<div id="cubic2x7">
-{{81.6027334, 97.1400425}, {32.694003, 88.1076582}, {25.4108981, 80.9641684}, {64.7788314, 37.8185316}},
-{{81.6027334, 97.1400425}, {43.6639346, 90.1335672}, {40.0870335, 80.2717567}},
-{{40.0870335, 80.2717567}, {36.0922592, 69.2578356}, {64.7788314, 37.8185316}},
-</div>
-
-<div id="cubic2x7x">
-{{81.6027334, 97.1400425}, {32.694003, 88.1076582}, {25.4108981, 80.9641684}, {64.7788314, 37.8185316}},
-{{81.6027334, 97.1400425}, {44.7641414, 91.5498493}, {40.0870335, 80.2717567}},
-{{40.0870335, 80.2717567}, {35.4099255, 68.9936642}, {64.7788314, 37.8185316}},
-</div>
-
-<div id="cubic2x8">
-{{43.6332675, 44.3267048}, {98.9277035, 77.9134953}, {92.1152147, 80.4133992}, {7.99971512, 51.2120151}},
-{{43.6332675, 44.3267048}, {85.4039037, 69.6989069}, {78.0952172, 71.3149254}},
-{{78.0952172, 71.3149254}, {70.649222, 72.9613041}, {7.99971512, 51.2120151}},
-</div>
-
-<div id="cubic2x8x">
-{{43.6332675, 44.3267048}, {98.9277035, 77.9134953}, {92.1152147, 80.4133992}, {7.99971512, 51.2120151}},
-{{43.6332675, 44.3267048}, {85.5789722, 69.5359977}, {78.0952172, 71.3149254}},
-{{78.0952172, 71.3149254}, {70.6114621, 73.0938531}, {7.99971512, 51.2120151}},
-</div>
-
-<div id="cubic2x9">
-{{3.42763756, 8.30440876}, {72.1979502, 30.9497829}, {73.001545, 36.9676506}, {15.3033876, 4.03527813}},
-{{3.42763756, 8.30440876}, {62.7221525, 27.8294978}, {56.7911889, 27.0114984}},
-{{56.7911889, 27.0114984}, {55.1652933, 26.7872547}, {15.3033876, 4.03527813}},
-</div>
-
-<div id="cubic2x9x">
-{{3.42763756, 8.30440876}, {72.1979502, 30.9497829}, {73.001545, 36.9676506}, {15.3033876, 4.03527813}},
-{{3.42763756, 8.30440876}, {54.7095919, 25.9860248}, {56.7911889, 27.0114984}},
-{{56.7911889, 27.0114984}, {58.8727859, 28.036972}, {15.3033876, 4.03527813}},
-</div>
-
-<div id="cubic3x0">
-{{37.7493998, 54.1620116}, {0.928181503, 99.9465276}, {1.29019157, 84.2497321}, {85.2470221, 46.7010984}},
-{{37.7493998, 54.1620116}, {30.0262679, 63.7651662}, {19.9157535, 75.222785}},
-{{19.9157535, 75.222785}, {12.0739437, 84.1094218}, {23.0870945, 77.9306985}},
-{{23.0870945, 77.9306985}, {53.2236264, 61.0231583}, {85.2470221, 46.7010984}},
-</div>
-
-<div id="cubic3x0x">
-{{37.7493998, 54.1620116}, {0.928181503, 99.9465276}, {1.29019157, 84.2497321}, {85.2470221, 46.7010984}},
-{{37.7493998, 54.1620116}, {26.0576358, 68.4753229}, {19.9157535, 75.222785}},
-{{19.9157535, 75.222785}, {7.36020346, 87.8757618}, {23.0870945, 77.9306985}},
-{{23.0870945, 77.9306985}, {37.855802, 68.7339725}, {85.2470221, 46.7010984}},
-</div>
-
-<div id="cubic3x1">
-{{77.853445, 82.8493315}, {48.7140421, 36.904878}, {60.2845497, 2.42643608}, {81.1111786, 35.5792593}},
-{{77.853445, 82.8493315}, {64.326138, 61.5206609}, {61.1190571, 42.8070764}},
-{{61.1190571, 42.8070764}, {58.2548088, 26.0939491}, {64.5348786, 22.8899965}},
-{{64.5348786, 22.8899965}, {71.0512995, 19.5654629}, {81.1111786, 35.5792593}},
-</div>
-
-<div id="cubic3x1x">
-{{77.853445, 82.8493315}, {48.7140421, 36.904878}, {60.2845497, 2.42643608}, {81.1111786, 35.5792593}},
-{{77.853445, 82.8493315}, {63.5749823, 59.3570561}, {61.1190571, 42.8070764}},
-{{61.1190571, 42.8070764}, {58.6631319, 26.2570968}, {64.5348786, 22.8899965}},
-{{64.5348786, 22.8899965}, {70.4066254, 19.5228963}, {81.1111786, 35.5792593}},
-</div>
-
-<div id="cubic3x2">
-{{38.2012882, 49.0499648}, {82.7576585, 7.96646616}, {92.3967278, 11.8042378}, {93.8251679, 19.597347}},
-{{38.2012882, 49.0499648}, {58.8845939, 29.9787846}, {72.1076941, 21.4229661}},
-{{72.1076941, 21.4229661}, {83.1166319, 14.2997899}, {88.6707154, 14.6399404}},
-{{88.6707154, 14.6399404}, {92.9647013, 14.9029184}, {93.8251679, 19.597347}},
-</div>
-
-<div id="cubic3x2x">
-{{38.2012882, 49.0499648}, {82.7576585, 7.96646616}, {92.3967278, 11.8042378}, {93.8251679, 19.597347}},
-{{38.2012882, 49.0499648}, {60.2321893, 28.8875296}, {72.1076941, 21.4229661}},
-{{72.1076941, 21.4229661}, {83.983199, 13.9584026}, {88.6707154, 14.6399404}},
-{{88.6707154, 14.6399404}, {93.3582319, 15.3214782}, {93.8251679, 19.597347}},
-</div>
-
-<div id="cubic3x3">
-{{52.7120295, 31.0801866}, {64.6964272, 52.8517052}, {78.6098203, 95.2490945}, {51.5310243, 81.9254304}},
-{{52.7120295, 31.0801866}, {59.5211432, 43.4499986}, {63.7497522, 56.8993316}},
-{{63.7497522, 56.8993316}, {68.6258107, 72.4079153}, {66.5354307, 79.5030739}},
-{{66.5354307, 79.5030739}, {64.0124137, 88.0666872}, {51.5310243, 81.9254304}},
-</div>
-
-<div id="cubic3x3x">
-{{52.7120295, 31.0801866}, {64.6964272, 52.8517052}, {78.6098203, 95.2490945}, {51.5310243, 81.9254304}},
-{{52.7120295, 31.0801866}, {59.1016467, 42.6728619}, {63.7497522, 56.8993316}},
-{{63.7497522, 56.8993316}, {68.3978576, 71.1258013}, {66.5354307, 79.5030739}},
-{{66.5354307, 79.5030739}, {64.6730039, 87.8803465}, {51.5310243, 81.9254304}},
-</div>
-
-<div id="cubic3x4">
-{{20.7082833, 44.1170772}, {75.7169666, 75.0570675}, {84.1330966, 24.9551825}, {21.7528516, 0.176163297}},
-{{20.7082833, 44.1170772}, {46.6273271, 58.6954113}, {59.2896776, 51.9825439}},
-{{59.2896776, 51.9825439}, {71.1540672, 45.6927106}, {61.4307428, 29.4567029}},
-{{61.4307428, 29.4567029}, {50.807026, 11.71722}, {21.7528516, 0.176163297}},
-</div>
-
-<div id="cubic3x4x">
-{{20.7082833, 44.1170772}, {75.7169666, 75.0570675}, {84.1330966, 24.9551825}, {21.7528516, 0.176163297}},
-{{20.7082833, 44.1170772}, {48.4367344, 58.6022136}, {59.2896776, 51.9825439}},
-{{59.2896776, 51.9825439}, {70.1426209, 45.3628742}, {61.4307428, 29.4567029}},
-{{61.4307428, 29.4567029}, {52.7188646, 13.5505316}, {21.7528516, 0.176163297}},
-</div>
-
-<div id="cubic3x5">
-{{20.8291142, 74.9221559}, {16.6750469, 57.513008}, {21.1249099, 46.360262}, {76.9233116, 50.0985771}},
-{{20.8291142, 74.9221559}, {18.4755741, 65.0587801}, {21.1261573, 59.9182775}},
-{{21.1261573, 59.9182775}, {24.474036, 53.4254499}, {36.6579558, 51.0041468}},
-{{36.6579558, 51.0041468}, {50.2178533, 48.3093965}, {76.9233116, 50.0985771}},
-</div>
-
-<div id="cubic3x5x">
-{{20.8291142, 74.9221559}, {16.6750469, 57.513008}, {21.1249099, 46.360262}, {76.9233116, 50.0985771}},
-{{20.8291142, 74.9221559}, {18.3562971, 66.1376314}, {21.1261573, 59.9182775}},
-{{21.1261573, 59.9182775}, {23.8960175, 53.6989236}, {36.6579558, 51.0041468}},
-{{36.6579558, 51.0041468}, {49.4198942, 48.3093701}, {76.9233116, 50.0985771}},
-</div>
-
-<div id="cubic3x6">
-{{39.306348, 21.7912016}, {44.72463, 86.8568551}, {3.16400146, 77.3725818}, {0.981986477, 4.24671164}},
-{{39.306348, 21.7912016}, {41.8751537, 52.6388057}, {32.26342, 62.4108917}},
-{{32.26342, 62.4108917}, {23.2193358, 71.6058581}, {13.0917792, 55.754704}},
-{{13.0917792, 55.754704}, {2.00097021, 38.3959145}, {0.981986477, 4.24671164}},
-</div>
-
-<div id="cubic3x6x">
-{{39.306348, 21.7912016}, {44.72463, 86.8568551}, {3.16400146, 77.3725818}, {0.981986477, 4.24671164}},
-{{39.306348, 21.7912016}, {41.2158823, 54.2230253}, {32.26342, 62.4108917}},
-{{32.26342, 62.4108917}, {23.3109577, 70.5987581}, {13.0917792, 55.754704}},
-{{13.0917792, 55.754704}, {2.87260067, 40.9106498}, {0.981986477, 4.24671164}},
-</div>
-
-<div id="cubic3x7">
-{{85.4907277, 42.6604079}, {93.4752654, 38.7852218}, {63.2230996, 90.6357313}, {14.7351715, 54.0271501}},
-{{85.4907277, 42.6604079}, {92.9820656, 39.0245896}, {81.4704732, 52.0202764}},
-{{81.4704732, 52.0202764}, {71.0697229, 63.7619094}, {56.4037366, 66.489545}},
-{{56.4037366, 66.489545}, {36.2148038, 70.2443591}, {14.7351715, 54.0271501}},
-</div>
-
-<div id="cubic3x7x">
-{{85.4907277, 42.6604079}, {93.4752654, 38.7852218}, {63.2230996, 90.6357313}, {14.7351715, 54.0271501}},
-{{85.4907277, 42.6604079}, {89.2978026, 42.0578592}, {81.4704732, 52.0202764}},
-{{81.4704732, 52.0202764}, {73.6431437, 61.9826936}, {56.4037366, 66.489545}},
-{{56.4037366, 66.489545}, {39.1643295, 70.9963964}, {14.7351715, 54.0271501}},
-</div>
-
-<div id="cubic3x8">
-{{95.2957887, 36.3209844}, {46.7852652, 19.9519225}, {31.9607143, 63.7251956}, {29.3620354, 87.7284659}},
-{{95.2957887, 36.3209844}, {73.0036621, 28.7988805}, {57.2191042, 37.0396513}},
-{{57.2191042, 37.0396513}, {44.4309585, 43.7160611}, {36.8308235, 60.0949108}},
-{{36.8308235, 60.0949108}, {30.9912846, 72.6795466}, {29.3620354, 87.7284659}},
-</div>
-
-<div id="cubic3x8x">
-{{95.2957887, 36.3209844}, {46.7852652, 19.9519225}, {31.9607143, 63.7251956}, {29.3620354, 87.7284659}},
-{{95.2957887, 36.3209844}, {71.2392316, 28.8763825}, {57.2191042, 37.0396513}},
-{{57.2191042, 37.0396513}, {43.1989768, 45.20292}, {36.8308235, 60.0949108}},
-{{36.8308235, 60.0949108}, {30.4626702, 74.9869017}, {29.3620354, 87.7284659}},
-</div>
-
-<div id="cubic3x9">
-{{11.6274826, 23.1005334}, {50.665531, 35.5788199}, {73.2259434, 8.43082047}, {96.7997166, 12.8374226}},
-{{11.6274826, 23.1005334}, {26.8690196, 27.9724026}, {42.2684837, 25.6341105}},
-{{42.2684837, 25.6341105}, {51.3514943, 24.254924}, {67.0182186, 18.4582098}},
-{{67.0182186, 18.4582098}, {87.1065443, 11.0254957}, {96.7997166, 12.8374226}},
-</div>
-
-<div id="cubic3x9x">
-{{11.6274826, 23.1005334}, {50.665531, 35.5788199}, {73.2259434, 8.43082047}, {96.7997166, 12.8374226}},
-{{11.6274826, 23.1005334}, {28.7555518, 28.1569895}, {42.2684837, 25.6341105}},
-{{42.2684837, 25.6341105}, {55.7814156, 23.1112314}, {67.0182186, 18.4582098}},
-{{67.0182186, 18.4582098}, {82.5639521, 11.3566582}, {96.7997166, 12.8374226}},
-</div>
-
-<div id="cubic4x0">
-{{24.2578299, 1.34695745}, {38.313885, 41.465269}, {6.77689729, 99.312693}, {48.4308047, 76.5337766}},
-{{24.2578299, 1.34695745}, {27.9750096, 11.9564045}, {28.1705087, 26.7539994}},
-{{28.1705087, 26.7539994}, {28.2848367, 35.4076429}, {26.8433323, 51.6959666}},
-{{26.8433323, 51.6959666}, {24.9672902, 72.8943612}, {27.4957684, 77.9195086}},
-{{27.4957684, 77.9195086}, {31.4664535, 85.8109263}, {48.4308047, 76.5337766}},
-</div>
-
-<div id="cubic4x0x">
-{{24.2578299, 1.34695745}, {38.313885, 41.465269}, {6.77689729, 99.312693}, {48.4308047, 76.5337766}},
-{{24.2578299, 1.34695745}, {28.2364584, 13.5769276}, {28.1705087, 26.7539994}},
-{{28.1705087, 26.7539994}, {28.104559, 39.9310711}, {26.8433323, 51.6959666}},
-{{26.8433323, 51.6959666}, {24.5051265, 69.7176532}, {27.4957684, 77.9195086}},
-{{27.4957684, 77.9195086}, {30.4864104, 86.121364}, {48.4308047, 76.5337766}},
-</div>
-
-<div id="cubic4x1">
-{{3.18338154, 3.09354817}, {93.264044, 88.7879534}, {59.132973, 47.8778685}, {83.3354337, 18.6335197}},
-{{3.18338154, 3.09354817}, {35.8260971, 34.1468066}, {48.9325859, 44.6922254}},
-{{48.9325859, 44.6922254}, {62.4915199, 55.6016796}, {67.1257676, 54.3074276}},
-{{67.1257676, 54.3074276}, {70.2512267, 53.4345498}, {72.6465479, 43.2128608}},
-{{72.6465479, 43.2128608}, {76.4594277, 26.9419442}, {83.3354337, 18.6335197}},
-</div>
-
-<div id="cubic4x1x">
-{{3.18338154, 3.09354817}, {93.264044, 88.7879534}, {59.132973, 47.8778685}, {83.3354337, 18.6335197}},
-{{3.18338154, 3.09354817}, {34.807442, 33.2979688}, {48.9325859, 44.6922254}},
-{{48.9325859, 44.6922254}, {63.0577297, 56.086482}, {67.1257676, 54.3074276}},
-{{67.1257676, 54.3074276}, {71.1938054, 52.5283732}, {72.6465479, 43.2128608}},
-{{72.6465479, 43.2128608}, {74.0679283, 31.8888383}, {83.3354337, 18.6335197}},
-</div>
-
-<div id="cubic4x2">
-{{5.3607232, 97.6747591}, {19.6754743, 85.6972941}, {14.421376, 80.0662188}, {72.9397619, 98.5790647}},
-{{5.3607232, 97.6747591}, {7.15867444, 96.170374}, {9.99357731, 93.4972246}},
-{{9.99357731, 93.4972246}, {15.4658237, 88.3372129}, {19.1058065, 87.2914549}},
-{{19.1058065, 87.2914549}, {24.5745003, 85.7203128}, {35.9606711, 88.1040392}},
-{{35.9606711, 88.1040392}, {47.3960315, 90.4980635}, {72.9397619, 98.5790647}},
-</div>
-
-<div id="cubic4x2x">
-{{5.3607232, 97.6747591}, {19.6754743, 85.6972941}, {14.421376, 80.0662188}, {72.9397619, 98.5790647}},
-{{5.3607232, 97.6747591}, {8.01636596, 95.4093652}, {9.99357731, 93.4972246}},
-{{9.99357731, 93.4972246}, {14.161732, 88.9702622}, {19.1058065, 87.2914549}},
-{{19.1058065, 87.2914549}, {24.0498811, 85.6126476}, {35.9606711, 88.1040392}},
-{{35.9606711, 88.1040392}, {47.871461, 90.5954307}, {72.9397619, 98.5790647}},
-</div>
-
-<div id="cubic4x3">
-{{18.340571, 49.9760211}, {46.9862021, 97.0991299}, {45.0770262, 9.57918773}, {97.4081647, 39.0235061}},
-{{18.340571, 49.9760211}, {27.6759966, 65.333137}, {34.9254897, 64.1054159}},
-{{34.9254897, 64.1054159}, {39.46946, 63.3358824}, {47.9840785, 52.4199142}},
-{{47.9840785, 52.4199142}, {58.4594697, 38.9901831}, {66.2068641, 35.3036404}},
-{{66.2068641, 35.3036404}, {79.5296469, 28.9640886}, {97.4081647, 39.0235061}},
-</div>
-
-<div id="cubic4x3x">
-{{18.340571, 49.9760211}, {46.9862021, 97.0991299}, {45.0770262, 9.57918773}, {97.4081647, 39.0235061}},
-{{18.340571, 49.9760211}, {28.406995, 66.1423531}, {34.9254897, 64.1054159}},
-{{34.9254897, 64.1054159}, {41.4439844, 62.0684788}, {47.9840785, 52.4199142}},
-{{47.9840785, 52.4199142}, {54.9532374, 41.9238105}, {66.2068641, 35.3036404}},
-{{66.2068641, 35.3036404}, {77.4604907, 28.6834703}, {97.4081647, 39.0235061}},
-</div>
-
-<div id="cubic4x4">
-{{68.0670356, 2.66693188}, {23.1241074, 46.8739094}, {9.79601006, 41.5410025}, {79.6294187, 31.6402602}},
-{{68.0670356, 2.66693188}, {56.7853646, 13.7638629}, {41.0137122, 27.3042275}},
-{{41.0137122, 27.3042275}, {29.788878, 36.941033}, {31.0433353, 38.0354879}},
-{{31.0433353, 38.0354879}, {32.2977925, 39.1299429}, {51.0493703, 36.059867}},
-{{51.0493703, 36.059867}, {67.7999464, 33.3174024}, {79.6294187, 31.6402602}},
-</div>
-
-<div id="cubic4x4x">
-{{68.0670356, 2.66693188}, {23.1241074, 46.8739094}, {9.79601006, 41.5410025}, {79.6294187, 31.6402602}},
-{{68.0670356, 2.66693188}, {50.940695, 19.1344928}, {41.0137122, 27.3042275}},
-{{41.0137122, 27.3042275}, {29.4752637, 36.6674193}, {31.0433353, 38.0354879}},
-{{31.0433353, 38.0354879}, {32.6114068, 39.4035566}, {51.0493703, 36.059867}},
-{{51.0493703, 36.059867}, {61.9478496, 34.2106234}, {79.6294187, 31.6402602}},
-</div>
-
-<div id="cubic4x5">
-{{80.6109054, 27.4877124}, {85.9817399, 95.1019056}, {77.7276185, 68.083746}, {83.5185407, 96.1129614}},
-{{80.6109054, 27.4877124}, {82.5499811, 51.8990092}, {82.5259477, 65.0368853}},
-{{82.5259477, 65.0368853}, {82.5124299, 72.4264589}, {81.7002161, 78.1564815}},
-{{81.7002161, 78.1564815}, {81.2315331, 81.462956}, {81.4316783, 83.8990214}},
-{{81.4316783, 83.8990214}, {81.7199102, 87.4072321}, {83.5185407, 96.1129614}},
-</div>
-
-<div id="cubic4x5x">
-{{80.6109054, 27.4877124}, {85.9817399, 95.1019056}, {77.7276185, 68.083746}, {83.5185407, 96.1129614}},
-{{80.6109054, 27.4877124}, {82.6925268, 54.7439407}, {82.5259477, 65.0368853}},
-{{82.5259477, 65.0368853}, {82.3593687, 75.3298298}, {81.7002161, 78.1564815}},
-{{81.7002161, 78.1564815}, {81.2086421, 80.6624342}, {81.4316783, 83.8990214}},
-{{81.4316783, 83.8990214}, {81.6547145, 87.1356086}, {83.5185407, 96.1129614}},
-</div>
-
-<div id="cubic4x6">
-{{70.5424749, 7.37512261}, {53.6857094, 95.7185581}, {41.8065019, 41.8776796}, {38.1617001, 83.6927474}},
-{{70.5424749, 7.37512261}, {64.0240124, 41.5372735}, {57.0495799, 54.4661558}},
-{{57.0495799, 54.4661558}, {53.0372544, 61.9040203}, {46.633996, 64.0865108}},
-{{46.633996, 64.0865108}, {42.8562175, 65.3741311}, {41.4346736, 67.9484678}},
-{{41.4346736, 67.9484678}, {39.1777978, 72.0355437}, {38.1617001, 83.6927474}},
-</div>
-
-<div id="cubic4x6x">
-{{70.5424749, 7.37512261}, {53.6857094, 95.7185581}, {41.8065019, 41.8776796}, {38.1617001, 83.6927474}},
-{{70.5424749, 7.37512261}, {63.0887524, 44.8198844}, {57.0495799, 54.4661558}},
-{{57.0495799, 54.4661558}, {51.0104074, 64.1124273}, {46.633996, 64.0865108}},
-{{46.633996, 64.0865108}, {43.5741104, 64.6069899}, {41.4346736, 67.9484678}},
-{{41.4346736, 67.9484678}, {39.2952367, 71.2899457}, {38.1617001, 83.6927474}},
-</div>
-
-<div id="cubic4x7">
-{{24.0062249, 72.6211198}, {43.1612821, 11.6690897}, {22.3913226, 30.9587957}, {24.4801394, 37.7033828}},
-{{24.0062249, 72.6211198}, {30.5430063, 51.8208637}, {31.8675739, 40.5026282}},
-{{31.8675739, 40.5026282}, {32.9179067, 31.5276894}, {30.6430223, 29.7760199}},
-{{30.6430223, 29.7760199}, {28.7741669, 28.3369942}, {26.2185506, 31.7425273}},
-{{26.2185506, 31.7425273}, {23.6812077, 35.1237098}, {24.4801394, 37.7033828}},
-</div>
-
-<div id="cubic4x7x">
-{{24.0062249, 72.6211198}, {43.1612821, 11.6690897}, {22.3913226, 30.9587957}, {24.4801394, 37.7033828}},
-{{24.0062249, 72.6211198}, {30.9441221, 50.1265572}, {31.8675739, 40.5026282}},
-{{31.8675739, 40.5026282}, {32.7910257, 30.8786991}, {30.6430223, 29.7760199}},
-{{30.6430223, 29.7760199}, {28.4950189, 28.6733406}, {26.2185506, 31.7425273}},
-{{26.2185506, 31.7425273}, {23.9420823, 34.811714}, {24.4801394, 37.7033828}},
-</div>
-
-<div id="cubic4x8">
-{{83.4128604, 19.944285}, {3.59808416, 73.0005231}, {19.791118, 29.3197498}, {77.0346567, 21.4750355}},
-{{83.4128604, 19.944285}, {56.4409479, 37.8736494}, {40.6945347, 43.6697281}},
-{{40.6945347, 43.6697281}, {27.6832174, 48.4590486}, {28.8268904, 43.5475174}},
-{{28.8268904, 43.5475174}, {29.9619906, 38.6728026}, {42.6576802, 32.0063781}},
-{{42.6576802, 32.0063781}, {57.6563877, 24.1306537}, {77.0346567, 21.4750355}},
-</div>
-
-<div id="cubic4x8x">
-{{83.4128604, 19.944285}, {3.59808416, 73.0005231}, {19.791118, 29.3197498}, {77.0346567, 21.4750355}},
-{{83.4128604, 19.944285}, {53.6969963, 39.3225107}, {40.6945347, 43.6697281}},
-{{40.6945347, 43.6697281}, {27.6920731, 48.0169456}, {28.8268904, 43.5475174}},
-{{28.8268904, 43.5475174}, {29.9617077, 39.0780892}, {42.6576802, 32.0063781}},
-{{42.6576802, 32.0063781}, {55.3536527, 24.9346669}, {77.0346567, 21.4750355}},
-</div>
-
-<div id="cubic4x9">
-{{13.6133623, 99.7800201}, {2.79733483, 14.8064674}, {52.2975031, 64.1339272}, {98.9146078, 57.8132952}},
-{{13.6133623, 99.7800201}, {10.1036384, 72.2067072}, {14.9007617, 60.2808941}},
-{{14.9007617, 60.2808941}, {19.0431228, 49.9828423}, {30.5807774, 49.2954321}},
-{{30.5807774, 49.2954321}, {37.7022355, 48.8711377}, {56.117561, 53.190874}},
-{{56.117561, 53.190874}, {84.2814202, 59.7973522}, {98.9146078, 57.8132952}},
-</div>
-
-<div id="cubic4x9x">
-{{13.6133623, 99.7800201}, {2.79733483, 14.8064674}, {52.2975031, 64.1339272}, {98.9146078, 57.8132952}},
-{{13.6133623, 99.7800201}, {10.0919269, 71.197946}, {14.9007617, 60.2808941}},
-{{14.9007617, 60.2808941}, {19.7095965, 49.3638421}, {30.5807774, 49.2954321}},
-{{30.5807774, 49.2954321}, {41.4519583, 49.2270222}, {56.117561, 53.190874}},
-{{56.117561, 53.190874}, {76.476137, 59.3205959}, {98.9146078, 57.8132952}},
-</div>
-
-<div id="cubic5x0">
-{{73.5652707, 11.5053172}, {69.8658631, 35.5604111}, {63.8300007, 90.8210508}, {29.4000415, 26.4971589}},
-{{73.5652707, 11.5053172}, {73.3885843, 12.654206}, {73.0163837, 15.1491032}},
-{{73.0163837, 15.1491032}, {70.9175181, 29.2180034}, {69.2121151, 36.2586021}},
-{{69.2121151, 36.2586021}, {66.2435432, 48.5140774}, {62.0808557, 53.3239452}},
-{{62.0808557, 53.3239452}, {56.8541433, 59.3632637}, {49.5132747, 54.1388813}},
-{{49.5132747, 54.1388813}, {40.9233022, 48.0255311}, {29.4000415, 26.4971589}},
-</div>
-
-<div id="cubic5x0x">
-{{73.5652707, 11.5053172}, {69.8658631, 35.5604111}, {63.8300007, 90.8210508}, {29.4000415, 26.4971589}},
-{{73.5652707, 11.5053172}, {73.3009509, 13.2327574}, {73.0163837, 15.1491032}},
-{{73.0163837, 15.1491032}, {71.6823308, 25.1891102}, {69.2121151, 36.2586021}},
-{{69.2121151, 36.2586021}, {66.7418995, 47.328094}, {62.0808557, 53.3239452}},
-{{62.0808557, 53.3239452}, {57.4198119, 59.3197964}, {49.5132747, 54.1388813}},
-{{49.5132747, 54.1388813}, {41.6067374, 48.9579661}, {29.4000415, 26.4971589}},
-</div>
-
-<div id="cubic5x1">
-{{80.7539402, 31.4736433}, {77.5229567, 28.3334108}, {99.6348716, 63.2867312}, {60.0910899, 50.9480224}},
-{{80.7539402, 31.4736433}, {80.1293736, 30.8666193}, {81.0927918, 33.3061348}},
-{{81.0927918, 33.3061348}, {82.7770389, 37.5708941}, {83.4256875, 40.319949}},
-{{83.4256875, 40.319949}, {84.5951485, 45.2762733}, {83.5574674, 48.3997103}},
-{{83.5574674, 48.3997103}, {82.2131806, 52.4460356}, {77.2064841, 53.3431558}},
-{{77.2064841, 53.3431558}, {71.2104332, 54.4175525}, {60.0910899, 50.9480224}},
-</div>
-
-<div id="cubic5x1x">
-{{80.7539402, 31.4736433}, {77.5229567, 28.3334108}, {99.6348716, 63.2867312}, {60.0910899, 50.9480224}},
-{{80.7539402, 31.4736433}, {79.9741932, 30.7172975}, {81.0927918, 33.3061348}},
-{{81.0927918, 33.3061348}, {82.2743126, 36.0212723}, {83.4256875, 40.319949}},
-{{83.4256875, 40.319949}, {84.5770623, 44.6186258}, {83.5574674, 48.3997103}},
-{{83.5574674, 48.3997103}, {82.5378725, 52.1807949}, {77.2064841, 53.3431558}},
-{{77.2064841, 53.3431558}, {71.8750956, 54.5055166}, {60.0910899, 50.9480224}},
-</div>
-
-<div id="cubic5x2">
-{{30.9220007, 6.06626757}, {55.7590106, 41.691652}, {11.5944877, 68.5545306}, {95.99508, 89.3088364}},
-{{30.9220007, 6.06626757}, {36.6680413, 14.3081978}, {38.6632502, 23.8943374}},
-{{38.6632502, 23.8943374}, {39.8467707, 29.5806556}, {40.109652, 40.2122054}},
-{{40.109652, 40.2122054}, {40.4211241, 52.8088852}, {42.588681, 58.5795625}},
-{{42.588681, 58.5795625}, {46.141784, 68.0389732}, {57.1660752, 74.8906876}},
-{{57.1660752, 74.8906876}, {70.1317224, 82.9489754}, {95.99508, 89.3088364}},
-</div>
-
-<div id="cubic5x2x">
-{{30.9220007, 6.06626757}, {55.7590106, 41.691652}, {11.5944877, 68.5545306}, {95.99508, 89.3088364}},
-{{30.9220007, 6.06626757}, {37.1487855, 15.3683637}, {38.6632502, 23.8943374}},
-{{38.6632502, 23.8943374}, {40.1777149, 32.4203112}, {40.109652, 40.2122054}},
-{{40.109652, 40.2122054}, {39.8437309, 49.9303489}, {42.588681, 58.5795625}},
-{{42.588681, 58.5795625}, {45.3336311, 67.2287761}, {57.1660752, 74.8906876}},
-{{57.1660752, 74.8906876}, {68.9985192, 82.5525991}, {95.99508, 89.3088364}},
-</div>
-
-<div id="cubic5x3">
-{{74.7743754, 32.9274563}, {11.7577089, 11.8127863}, {37.4985242, 37.696964}, {72.8744837, 1.44809908}},
-{{74.7743754, 32.9274563}, {60.7273344, 28.2207866}, {49.5992486, 25.6169692}},
-{{49.5992486, 25.6169692}, {43.5981152, 24.2127874}, {37.944249, 23.3667683}},
-{{37.944249, 23.3667683}, {35.9715145, 23.0715771}, {37.4878767, 22.7373028}},
-{{37.4878767, 22.7373028}, {44.1459136, 21.2695724}, {50.3950023, 18.2059418}},
-{{50.3950023, 18.2059418}, {62.1391178, 12.4483612}, {72.8744837, 1.44809908}},
-</div>
-
-<div id="cubic5x3x">
-{{74.7743754, 32.9274563}, {11.7577089, 11.8127863}, {37.4985242, 37.696964}, {72.8744837, 1.44809908}},
-{{74.7743754, 32.9274563}, {58.4980331, 27.5812922}, {49.5992486, 25.6169692}},
-{{49.5992486, 25.6169692}, {40.7004642, 23.6526461}, {37.944249, 23.3667683}},
-{{37.944249, 23.3667683}, {35.0992403, 23.0813479}, {37.4878767, 22.7373028}},
-{{37.4878767, 22.7373028}, {40.7578786, 22.4379602}, {50.3950023, 18.2059418}},
-{{50.3950023, 18.2059418}, {60.0321261, 13.9739234}, {72.8744837, 1.44809908}},
-</div>
-
-<div id="cubic5x4">
-{{72.6117562, 85.7863012}, {10.3637705, 83.8910282}, {56.5110395, 81.0400843}, {40.6969416, 93.4977145}},
-{{72.6117562, 85.7863012}, {59.583082, 85.3896153}, {50.1257271, 84.8566602}},
-{{50.1257271, 84.8566602}, {45.0042708, 84.5680481}, {40.4221343, 84.1941021}},
-{{40.4221343, 84.1941021}, {38.6138335, 84.0465275}, {39.3498335, 84.2964765}},
-{{39.3498335, 84.2964765}, {42.6031074, 85.4013033}, {43.6650027, 86.8548971}},
-{{43.6650027, 86.8548971}, {45.661047, 89.587217}, {40.6969416, 93.4977145}},
-</div>
-
-<div id="cubic5x4x">
-{{72.6117562, 85.7863012}, {10.3637705, 83.8910282}, {56.5110395, 81.0400843}, {40.6969416, 93.4977145}},
-{{72.6117562, 85.7863012}, {57.6253009, 85.3070124}, {50.1257271, 84.8566602}},
-{{50.1257271, 84.8566602}, {42.6261532, 84.4063079}, {40.4221343, 84.1941021}},
-{{40.4221343, 84.1941021}, {37.9777583, 83.9471466}, {39.3498335, 84.2964765}},
-{{39.3498335, 84.2964765}, {41.4441267, 84.7344658}, {43.6650027, 86.8548971}},
-{{43.6650027, 86.8548971}, {45.8858786, 88.9753284}, {40.6969416, 93.4977145}},
-</div>
-
-<div id="cubic5x5">
-{{49.5466436, 30.4382438}, {75.5627334, 82.8610433}, {45.5550553, 43.8144668}, {89.743077, 11.8944428}},
-{{49.5466436, 30.4382438}, {54.1919031, 39.7985093}, {58.8653675, 50.331813}},
-{{58.8653675, 50.331813}, {61.2282341, 55.6573679}, {61.7133948, 56.0247083}},
-{{61.7133948, 56.0247083}, {62.1985554, 56.3920486}, {62.7466525, 53.2705356}},
-{{62.7466525, 53.2705356}, {64.4490529, 43.5750541}, {68.2227928, 36.1296005}},
-{{68.2227928, 36.1296005}, {75.1711506, 22.4207397}, {89.743077, 11.8944428}},
-</div>
-
-<div id="cubic5x5x">
-{{49.5466436, 30.4382438}, {75.5627334, 82.8610433}, {45.5550553, 43.8144668}, {89.743077, 11.8944428}},
-{{49.5466436, 30.4382438}, {56.3292139, 44.3383274}, {58.8653675, 50.331813}},
-{{58.8653675, 50.331813}, {61.106944, 55.5655329}, {61.7133948, 56.0247083}},
-{{61.7133948, 56.0247083}, {62.3198455, 56.4838837}, {62.7466525, 53.2705356}},
-{{62.7466525, 53.2705356}, {63.1064311, 47.7098594}, {68.2227928, 36.1296005}},
-{{68.2227928, 36.1296005}, {73.3391545, 24.5493417}, {89.743077, 11.8944428}},
-</div>
-
-<div id="cubic5x6">
-{{24.3042985, 82.344259}, {59.9615856, 74.3697725}, {32.7666043, 8.31767205}, {95.114078, 82.3081283}},
-{{24.3042985, 82.344259}, {33.0316107, 80.3924607}, {38.6135161, 73.199581}},
-{{38.6135161, 73.199581}, {41.8734961, 68.9987494}, {45.7986582, 59.6541823}},
-{{45.7986582, 59.6541823}, {49.7161349, 50.3279117}, {52.6598645, 48.50717}},
-{{52.6598645, 48.50717}, {57.3512738, 45.6054619}, {66.2796867, 52.394109}},
-{{66.2796867, 52.394109}, {76.3758191, 60.0706222}, {95.114078, 82.3081283}},
-</div>
-
-<div id="cubic5x6x">
-{{24.3042985, 82.344259}, {59.9615856, 74.3697725}, {32.7666043, 8.31767205}, {95.114078, 82.3081283}},
-{{24.3042985, 82.344259}, {33.965356, 79.8151924}, {38.6135161, 73.199581}},
-{{38.6135161, 73.199581}, {43.2616761, 66.5839696}, {45.7986582, 59.6541823}},
-{{45.7986582, 59.6541823}, {48.5966015, 51.6963295}, {52.6598645, 48.50717}},
-{{52.6598645, 48.50717}, {56.7231274, 45.3180106}, {66.2796867, 52.394109}},
-{{66.2796867, 52.394109}, {75.8362459, 59.4702074}, {95.114078, 82.3081283}},
-</div>
-
-<div id="cubic5x7">
-{{14.6365061, 95.7588134}, {18.3773411, 67.9719648}, {4.8126874, 86.837213}, {73.0391371, 68.7771361}},
-{{14.6365061, 95.7588134}, {15.2275148, 91.3688129}, {15.5044612, 85.7525859}},
-{{15.5044612, 85.7525859}, {15.7576453, 80.618239}, {16.904617, 79.6508905}},
-{{16.904617, 79.6508905}, {18.0515887, 78.683542}, {24.680235, 78.0137979}},
-{{24.680235, 78.0137979}, {33.9302732, 77.0791942}, {41.7459023, 75.745697}},
-{{41.7459023, 75.745697}, {55.7221394, 73.3610813}, {73.0391371, 68.7771361}},
-</div>
-
-<div id="cubic5x7x">
-{{14.6365061, 95.7588134}, {18.3773411, 67.9719648}, {4.8126874, 86.837213}, {73.0391371, 68.7771361}},
-{{14.6365061, 95.7588134}, {15.4253236, 89.2562084}, {15.5044612, 85.7525859}},
-{{15.5044612, 85.7525859}, {15.4709024, 80.8600761}, {16.904617, 79.6508905}},
-{{16.904617, 79.6508905}, {18.3383317, 78.4417048}, {24.680235, 78.0137979}},
-{{24.680235, 78.0137979}, {30.2055996, 77.5914828}, {41.7459023, 75.745697}},
-{{41.7459023, 75.745697}, {53.2862049, 73.8999113}, {73.0391371, 68.7771361}},
-</div>
-
-<div id="cubic5x8">
-{{11.3940197, 99.2884769}, {41.4314282, 38.0142946}, {6.25007991, 45.0930539}, {78.9565565, 22.8458219}},
-{{11.3940197, 99.2884769}, {17.9356966, 85.9439202}, {21.7417223, 74.0130457}},
-{{21.7417223, 74.0130457}, {23.9251358, 67.1686272}, {26.0700343, 57.3329391}},
-{{26.0700343, 57.3329391}, {28.2750992, 47.2213507}, {30.7090957, 43.764797}},
-{{30.7090957, 43.764797}, {34.2237869, 38.7735329}, {44.5059747, 34.4313542}},
-{{44.5059747, 34.4313542}, {53.4825656, 30.6405304}, {78.9565565, 22.8458219}},
-</div>
-
-<div id="cubic5x8x">
-{{11.3940197, 99.2884769}, {41.4314282, 38.0142946}, {6.25007991, 45.0930539}, {78.9565565, 22.8458219}},
-{{11.3940197, 99.2884769}, {18.6635437, 84.168545}, {21.7417223, 74.0130457}},
-{{21.7417223, 74.0130457}, {24.8199009, 63.8575464}, {26.0700343, 57.3329391}},
-{{26.0700343, 57.3329391}, {27.5370962, 48.6793447}, {30.7090957, 43.764797}},
-{{30.7090957, 43.764797}, {33.8810951, 38.8502494}, {44.5059747, 34.4313542}},
-{{44.5059747, 34.4313542}, {55.1308542, 30.012459}, {78.9565565, 22.8458219}},
-</div>
-
-<div id="cubic5x9">
-{{69.7292014, 38.6877352}, {24.7648688, 23.1501713}, {84.9283191, 90.2588441}, {80.392774, 61.3533852}},
-{{69.7292014, 38.6877352}, {57.2585085, 34.3784487}, {54.0073216, 37.8534623}},
-{{54.0073216, 37.8534623}, {51.2791269, 40.7694784}, {55.3644243, 48.2785885}},
-{{55.3644243, 48.2785885}, {59.0228346, 55.0030454}, {65.6488241, 61.3874162}},
-{{65.6488241, 61.3874162}, {72.4185069, 67.9102405}, {76.7088359, 68.6042477}},
-{{76.7088359, 68.6042477}, {81.6560742, 69.4045171}, {80.392774, 61.3533852}},
-</div>
-
-<div id="cubic5x9x">
-{{69.7292014, 38.6877352}, {24.7648688, 23.1501713}, {84.9283191, 90.2588441}, {80.392774, 61.3533852}},
-{{69.7292014, 38.6877352}, {56.5795552, 34.3837867}, {54.0073216, 37.8534623}},
-{{54.0073216, 37.8534623}, {51.4350879, 41.3231378}, {55.3644243, 48.2785885}},
-{{55.3644243, 48.2785885}, {59.2937606, 55.2340392}, {65.6488241, 61.3874162}},
-{{65.6488241, 61.3874162}, {72.0038877, 67.5407932}, {76.7088359, 68.6042477}},
-{{76.7088359, 68.6042477}, {81.413784, 69.6677022}, {80.392774, 61.3533852}},
-</div>
-
-<div id="cubic6x0">
-{{60.7765365, 71.2493073}, {87.1078942, 22.3776699}, {1.49747543, 68.0695699}, {45.2619466, 17.5360766}},
-{{60.7765365, 71.2493073}, {66.8034381, 60.063232}, {65.7606554, 53.9755229}},
-{{65.7606554, 53.9755229}, {64.9026034, 48.9662616}, {59.0403561, 46.9365029}},
-{{59.0403561, 46.9365029}, {55.5624487, 45.7323037}, {47.0319968, 45.0593685}},
-{{47.0319968, 45.0593685}, {38.6438055, 44.3976557}, {35.915024, 43.1681828}},
-{{35.915024, 43.1681828}, {31.4270492, 41.1460923}, {32.9921574, 35.8381417}},
-{{32.9921574, 35.8381417}, {34.8405988, 29.5692874}, {45.2619466, 17.5360766}},
-</div>
-
-<div id="cubic6x0x">
-{{60.7765365, 71.2493073}, {87.1078942, 22.3776699}, {1.49747543, 68.0695699}, {45.2619466, 17.5360766}},
-{{60.7765365, 71.2493073}, {66.9967453, 59.4196142}, {65.7606554, 53.9755229}},
-{{65.7606554, 53.9755229}, {64.5245656, 48.5314316}, {59.0403561, 46.9365029}},
-{{59.0403561, 46.9365029}, {53.5561467, 45.3415741}, {47.0319968, 45.0593685}},
-{{47.0319968, 45.0593685}, {40.2998025, 44.7818435}, {35.915024, 43.1681828}},
-{{35.915024, 43.1681828}, {31.5302455, 41.5545222}, {32.9921574, 35.8381417}},
-{{32.9921574, 35.8381417}, {34.4540694, 30.1217612}, {45.2619466, 17.5360766}},
-</div>
-
-<div id="cubic6x1">
-{{7.56463181, 38.7667716}, {53.1298274, 53.009038}, {22.9012888, 1.96013199}, {43.9383991, 72.6733402}},
-{{7.56463181, 38.7667716}, {18.0499753, 42.0441646}, {24.9041761, 41.2832621}},
-{{24.9041761, 41.2832621}, {30.0084481, 40.7166236}, {32.7855974, 37.9676099}},
-{{32.7855974, 37.9676099}, {34.25762, 36.5105005}, {35.0000192, 34.4010014}},
-{{35.0000192, 34.4010014}, {35.1477005, 33.9813707}, {35.2051475, 34.7029855}},
-{{35.2051475, 34.7029855}, {35.5299907, 38.7834725}, {36.7160087, 44.7150792}},
-{{36.7160087, 44.7150792}, {38.9607709, 55.9417619}, {43.9383991, 72.6733402}},
-</div>
-
-<div id="cubic6x1x">
-{{7.56463181, 38.7667716}, {53.1298274, 53.009038}, {22.9012888, 1.96013199}, {43.9383991, 72.6733402}},
-{{7.56463181, 38.7667716}, {19.0728251, 42.1807008}, {24.9041761, 41.2832621}},
-{{24.9041761, 41.2832621}, {30.7355271, 40.3858233}, {32.7855974, 37.9676099}},
-{{32.7855974, 37.9676099}, {34.8356678, 35.5493964}, {35.0000192, 34.4010014}},
-{{35.0000192, 34.4010014}, {35.1702591, 33.6960593}, {35.2051475, 34.7029855}},
-{{35.2051475, 34.7029855}, {35.1391248, 36.1152585}, {36.7160087, 44.7150792}},
-{{36.7160087, 44.7150792}, {38.2928925, 53.3148999}, {43.9383991, 72.6733402}},
-</div>
-
-<div id="cubic6x2">
-{{53.4808373, 52.4330519}, {42.3039286, 2.12741392}, {55.4457253, 76.3045082}, {49.8689114, 46.7937026}},
-{{53.4808373, 52.4330519}, {50.9719376, 41.1408598}, {49.8115514, 36.9274013}},
-{{49.8115514, 36.9274013}, {48.82027, 33.3279765}, {48.8115145, 34.8928161}},
-{{48.8115145, 34.8928161}, {48.8045445, 36.1385203}, {49.4292469, 40.7546742}},
-{{49.4292469, 40.7546742}, {49.7879548, 43.4052983}, {50.613269, 48.9383534}},
-{{50.613269, 48.9383534}, {51.3518777, 53.8901197}, {51.31236, 53.9808933}},
-{{51.31236, 53.9808933}, {51.2529165, 54.1174374}, {49.8689114, 46.7937026}},
-</div>
-
-<div id="cubic6x2x">
-{{53.4808373, 52.4330519}, {42.3039286, 2.12741392}, {55.4457253, 76.3045082}, {49.8689114, 46.7937026}},
-{{53.4808373, 52.4330519}, {50.8474472, 40.6156325}, {49.8115514, 36.9274013}},
-{{49.8115514, 36.9274013}, {48.7756556, 33.2391701}, {48.8115145, 34.8928161}},
-{{48.8115145, 34.8928161}, {48.8473733, 36.5464621}, {49.4292469, 40.7546742}},
-{{49.4292469, 40.7546742}, {50.0111204, 44.9628863}, {50.613269, 48.9383534}},
-{{50.613269, 48.9383534}, {51.3082301, 53.5085713}, {51.31236, 53.9808933}},
-{{51.31236, 53.9808933}, {51.31649, 54.4532153}, {49.8689114, 46.7937026}},
-</div>
-
-<div id="cubic6x3">
-{{30.270176, 50.8484091}, {9.21238377, 32.534054}, {99.8452993, 99.9447358}, {71.1751053, 39.994736}},
-{{30.270176, 50.8484091}, {26.1998702, 47.3083881}, {27.3542845, 47.6109361}},
-{{27.3542845, 47.6109361}, {28.1421178, 47.8174109}, {33.7377536, 50.9254737}},
-{{33.7377536, 50.9254737}, {43.6710144, 56.4428448}, {49.5826034, 59.2306974}},
-{{49.5826034, 59.2306974}, {60.0794163, 64.1809007}, {66.5061178, 65.1608314}},
-{{66.5061178, 65.1608314}, {74.7232814, 66.4137682}, {76.404788, 61.2406021}},
-{{76.404788, 61.2406021}, {78.4000331, 55.1022173}, {71.1751053, 39.994736}},
-</div>
-
-<div id="cubic6x3x">
-{{30.270176, 50.8484091}, {9.21238377, 32.534054}, {99.8452993, 99.9447358}, {71.1751053, 39.994736}},
-{{30.270176, 50.8484091}, {26.0151068, 47.1560011}, {27.3542845, 47.6109361}},
-{{27.3542845, 47.6109361}, {28.6934622, 48.0658712}, {33.7377536, 50.9254737}},
-{{33.7377536, 50.9254737}, {40.3775737, 54.7374488}, {49.5826034, 59.2306974}},
-{{49.5826034, 59.2306974}, {58.787633, 63.723946}, {66.5061178, 65.1608314}},
-{{66.5061178, 65.1608314}, {74.2246025, 66.5977168}, {76.404788, 61.2406021}},
-{{76.404788, 61.2406021}, {78.5849735, 55.8834875}, {71.1751053, 39.994736}},
-</div>
-
-<div id="cubic6x4">
-{{52.3256249, 36.7777584}, {23.7859194, 69.9470399}, {99.9000587, 20.2858463}, {44.2180221, 72.2977287}},
-{{52.3256249, 36.7777584}, {46.323817, 43.7531512}, {45.7451821, 46.7544892}},
-{{45.7451821, 46.7544892}, {45.2655359, 49.2423797}, {48.551811, 49.2476269}},
-{{48.551811, 49.2476269}, {50.5144448, 49.2507606}, {55.9087216, 48.0313516}},
-{{55.9087216, 48.0313516}, {62.3329105, 46.5791247}, {63.9943433, 47.0044226}},
-{{63.9943433, 47.0044226}, {66.7468982, 47.7090289}, {62.987381, 52.8381772}},
-{{62.987381, 52.8381772}, {58.5075376, 58.9500739}, {44.2180221, 72.2977287}},
-</div>
-
-<div id="cubic6x4x">
-{{52.3256249, 36.7777584}, {23.7859194, 69.9470399}, {99.9000587, 20.2858463}, {44.2180221, 72.2977287}},
-{{52.3256249, 36.7777584}, {46.0840368, 44.1087946}, {45.7451821, 46.7544892}},
-{{45.7451821, 46.7544892}, {45.4063273, 49.4001838}, {48.551811, 49.2476269}},
-{{48.551811, 49.2476269}, {51.6972946, 49.09507}, {55.9087216, 48.0313516}},
-{{55.9087216, 48.0313516}, {61.1409519, 46.6483554}, {63.9943433, 47.0044226}},
-{{63.9943433, 47.0044226}, {66.8477347, 47.3604898}, {62.987381, 52.8381772}},
-{{62.987381, 52.8381772}, {59.1270273, 58.3158645}, {44.2180221, 72.2977287}},
-</div>
-
-<div id="cubic6x5">
-{{42.9059103, 19.6341859}, {91.762872, 58.5903164}, {27.4474096, 8.61261101}, {52.1532298, 39.3337672}},
-{{42.9059103, 19.6341859}, {54.1145994, 28.5714415}, {58.004639, 31.7917065}},
-{{58.004639, 31.7917065}, {62.019725, 35.1154878}, {61.7728162, 35.2682181}},
-{{61.7728162, 35.2682181}, {61.6064162, 35.3711481}, {58.4041375, 33.5820691}},
-{{58.4041375, 33.5820691}, {53.244257, 30.6992989}, {50.8183004, 29.6863137}},
-{{50.8183004, 29.6863137}, {46.5331956, 27.8970204}, {46.2915313, 29.5538521}},
-{{46.2915313, 29.5538521}, {45.9839754, 31.662432}, {52.1532298, 39.3337672}},
-</div>
-
-<div id="cubic6x5x">
-{{42.9059103, 19.6341859}, {91.762872, 58.5903164}, {27.4474096, 8.61261101}, {52.1532298, 39.3337672}},
-{{42.9059103, 19.6341859}, {53.8121244, 28.322992}, {58.004639, 31.7917065}},
-{{58.004639, 31.7917065}, {62.1971535, 35.260421}, {61.7728162, 35.2682181}},
-{{61.7728162, 35.2682181}, {61.3484789, 35.2760153}, {58.4041375, 33.5820691}},
-{{58.4041375, 33.5820691}, {54.7626269, 31.4620033}, {50.8183004, 29.6863137}},
-{{50.8183004, 29.6863137}, {46.8739739, 27.9106241}, {46.2915313, 29.5538521}},
-{{46.2915313, 29.5538521}, {45.7090887, 31.1970802}, {52.1532298, 39.3337672}},
-</div>
-
-<div id="cubic6x6">
-{{73.4375576, 65.030414}, {66.1679208, 84.2450892}, {7.2134248, 36.0306381}, {66.9352454, 80.6694031}},
-{{73.4375576, 65.030414}, {71.5866063, 69.9227391}, {65.0188473, 69.7835224}},
-{{65.0188473, 69.7835224}, {60.0105733, 69.677362}, {52.4355896, 66.6514651}},
-{{52.4355896, 66.6514651}, {48.2960051, 64.9978699}, {42.4281173, 61.975806}},
-{{42.4281173, 61.975806}, {40.1794784, 60.817718}, {40.5562709, 61.1722188}},
-{{40.5562709, 61.1722188}, {40.9330633, 61.5267196}, {45.4424567, 64.8118124}},
-{{45.4424567, 64.8118124}, {56.3732534, 72.774897}, {66.9352454, 80.6694031}},
-</div>
-
-<div id="cubic6x6x">
-{{73.4375576, 65.030414}, {66.1679208, 84.2450892}, {7.2134248, 36.0306381}, {66.9352454, 80.6694031}},
-{{73.4375576, 65.030414}, {71.1118808, 70.1709551}, {65.0188473, 69.7835224}},
-{{65.0188473, 69.7835224}, {58.9258137, 69.3960897}, {52.4355896, 66.6514651}},
-{{52.4355896, 66.6514651}, {45.9453656, 63.9068405}, {42.4281173, 61.975806}},
-{{42.4281173, 61.975806}, {40.0852803, 60.7290928}, {40.5562709, 61.1722188}},
-{{40.5562709, 61.1722188}, {41.0272614, 61.6153448}, {45.4424567, 64.8118124}},
-{{45.4424567, 64.8118124}, {51.3278432, 69.0492921}, {66.9352454, 80.6694031}},
-</div>
-
-<div id="cubic6x7">
-{{46.6695473, 75.0819435}, {2.22400357, 78.828021}, {62.548768, 57.1436195}, {12.8128845, 46.150303}},
-{{46.6695473, 75.0819435}, {36.8374139, 75.9106415}, {32.735691, 75.1220326}},
-{{32.735691, 75.1220326}, {29.1601585, 74.4345905}, {29.1402184, 72.2922743}},
-{{29.1402184, 72.2922743}, {29.1278273, 70.9609985}, {31.0504514, 67.4052326}},
-{{31.0504514, 67.4052326}, {33.5289159, 62.8214769}, {33.7777617, 60.3248048}},
-{{33.7777617, 60.3248048}, {34.2044612, 56.0437252}, {30.1210496, 52.8325143}},
-{{30.1210496, 52.8325143}, {25.0685705, 48.8592251}, {12.8128845, 46.150303}},
-</div>
-
-<div id="cubic6x7x">
-{{46.6695473, 75.0819435}, {2.22400357, 78.828021}, {62.548768, 57.1436195}, {12.8128845, 46.150303}},
-{{46.6695473, 75.0819435}, {36.5139384, 75.9210204}, {32.735691, 75.1220326}},
-{{32.735691, 75.1220326}, {28.9574435, 74.3230448}, {29.1402184, 72.2922743}},
-{{29.1402184, 72.2922743}, {29.3229933, 70.2615038}, {31.0504514, 67.4052326}},
-{{31.0504514, 67.4052326}, {33.1016834, 64.1207271}, {33.7777617, 60.3248048}},
-{{33.7777617, 60.3248048}, {34.45384, 56.5288825}, {30.1210496, 52.8325143}},
-{{30.1210496, 52.8325143}, {25.7882591, 49.1361461}, {12.8128845, 46.150303}},
-</div>
-
-<div id="cubic6x8">
-{{55.3467924, 13.540705}, {78.628494, 9.09824134}, {14.1422475, 88.7534345}, {78.9736115, 9.48816133}},
-{{55.3467924, 13.540705}, {60.6017653, 12.5379851}, {60.6776079, 17.0952733}},
-{{60.6776079, 17.0952733}, {60.7373059, 20.6824519}, {57.5541656, 27.8149349}},
-{{57.5541656, 27.8149349}, {55.7485732, 31.8607373}, {51.7778474, 39.2052874}},
-{{51.7778474, 39.2052874}, {48.7947857, 44.7229805}, {49.1759091, 44.7804774}},
-{{49.1759091, 44.7804774}, {49.7203899, 44.8626187}, {56.152876, 37.2125188}},
-{{56.152876, 37.2125188}, {61.4648441, 30.8950413}, {78.9736115, 9.48816133}},
-</div>
-
-<div id="cubic6x8x">
-{{55.3467924, 13.540705}, {78.628494, 9.09824134}, {14.1422475, 88.7534345}, {78.9736115, 9.48816133}},
-{{55.3467924, 13.540705}, {60.8509374, 12.7149155}, {60.6776079, 17.0952733}},
-{{60.6776079, 17.0952733}, {60.5042785, 21.475631}, {57.5541656, 27.8149349}},
-{{57.5541656, 27.8149349}, {54.6040527, 34.1542387}, {51.7778474, 39.2052874}},
-{{51.7778474, 39.2052874}, {48.8652599, 44.4020133}, {49.1759091, 44.7804774}},
-{{49.1759091, 44.7804774}, {49.4865584, 45.1589416}, {56.152876, 37.2125188}},
-{{56.152876, 37.2125188}, {62.8191937, 29.2660961}, {78.9736115, 9.48816133}},
-</div>
-
-<div id="cubic6x9">
-{{6.436938, 85.6170305}, {65.4323691, 21.8280372}, {63.8217439, 52.0501321}, {6.57091737, 37.4082543}},
-{{6.436938, 85.6170305}, {18.3889022, 72.6939321}, {29.5730232, 62.1640306}},
-{{29.5730232, 62.1640306}, {35.8331919, 56.2700528}, {44.0352491, 49.2100734}},
-{{44.0352491, 49.2100734}, {50.0664784, 44.0186496}, {50.0976641, 43.1465107}},
-{{50.0976641, 43.1465107}, {50.1288498, 42.2743718}, {44.2847347, 42.2329622}},
-{{44.2847347, 42.2329622}, {36.0580615, 42.1746705}, {29.7656368, 41.5603994}},
-{{29.7656368, 41.5603994}, {18.5096561, 40.4615824}, {6.57091737, 37.4082543}},
-</div>
-
-<div id="cubic6x9x">
-{{6.436938, 85.6170305}, {65.4323691, 21.8280372}, {63.8217439, 52.0501321}, {6.57091737, 37.4082543}},
-{{6.436938, 85.6170305}, {20.1874324, 70.8746109}, {29.5730232, 62.1640306}},
-{{29.5730232, 62.1640306}, {38.958614, 53.4534502}, {44.0352491, 49.2100734}},
-{{44.0352491, 49.2100734}, {50.058682, 44.2366844}, {50.0976641, 43.1465107}},
-{{50.0976641, 43.1465107}, {50.1366462, 42.0563371}, {44.2847347, 42.2329622}},
-{{44.2847347, 42.2329622}, {39.2093652, 42.3394209}, {29.7656368, 41.5603994}},
-{{29.7656368, 41.5603994}, {20.3219083, 40.7813779}, {6.57091737, 37.4082543}},
-</div>
-
-<div id="cubic7x0">
-{{47.0675449, 64.2273128}, {68.4467872, 85.1524572}, {57.3478562, 45.4193099}, {62.340955, 64.4298956}},
-{{47.0675449, 64.2273128}, {52.2209452, 69.2712543}, {55.5069225, 70.2618397}},
-{{55.5069225, 70.2618397}, {58.2344663, 71.0840808}, {59.6132451, 69.0985913}},
-{{59.6132451, 69.0985913}, {60.6680756, 67.5795987}, {60.901578, 64.4621115}},
-{{60.901578, 64.4621115}, {61.029698, 62.7515845}, {60.8869865, 60.0769443}},
-{{60.8869865, 60.0769443}, {60.8258684, 58.931493}, {60.9363129, 59.2030029}},
-{{60.9363129, 59.2030029}, {61.0467573, 59.4745129}, {61.7705423, 62.2490239}},
-{{61.7705423, 62.2490239}, {62.1209644, 63.5923097}, {62.340955, 64.4298956}},
-</div>
-
-<div id="cubic7x0x">
-{{47.0675449, 64.2273128}, {68.4467872, 85.1524572}, {57.3478562, 45.4193099}, {62.340955, 64.4298956}},
-{{47.0675449, 64.2273128}, {52.5598806, 69.5095881}, {55.5069225, 70.2618397}},
-{{55.5069225, 70.2618397}, {58.4539644, 71.0140913}, {59.6132451, 69.0985913}},
-{{59.6132451, 69.0985913}, {60.7725259, 67.1830912}, {60.901578, 64.4621115}},
-{{60.901578, 64.4621115}, {61.0306302, 61.7411317}, {60.8869865, 60.0769443}},
-{{60.8869865, 60.0769443}, {60.7982573, 58.8636155}, {60.9363129, 59.2030029}},
-{{60.9363129, 59.2030029}, {61.0743684, 59.5423904}, {61.7705423, 62.2490239}},
-{{61.7705423, 62.2490239}, {62.0120077, 63.1760698}, {62.340955, 64.4298956}},
-</div>
-
-<div id="cubic7x1">
-{{44.6639438, 66.9040647}, {56.6149349, 27.2102873}, {23.2993796, 92.6723405}, {44.026369, 51.1832799}},
-{{44.6639438, 66.9040647}, {47.1627908, 58.6044453}, {47.3201686, 55.4528932}},
-{{47.3201686, 55.4528932}, {47.4533435, 52.7860125}, {45.9070214, 53.8259442}},
-{{45.9070214, 53.8259442}, {44.6909451, 54.6437792}, {42.4058247, 57.7914576}},
-{{42.4058247, 57.7914576}, {41.1108979, 59.5751769}, {38.7979012, 63.1176732}},
-{{38.7979012, 63.1176732}, {37.2505608, 65.4875199}, {37.097116, 65.5770977}},
-{{37.097116, 65.5770977}, {36.8720355, 65.7084948}, {38.3585854, 62.6270533}},
-{{38.3585854, 62.6270533}, {39.7438195, 59.7556272}, {44.026369, 51.1832799}},
-</div>
-
-<div id="cubic7x1x">
-{{44.6639438, 66.9040647}, {56.6149349, 27.2102873}, {23.2993796, 92.6723405}, {44.026369, 51.1832799}},
-{{44.6639438, 66.9040647}, {47.2570645, 58.1934532}, {47.3201686, 55.4528932}},
-{{47.3201686, 55.4528932}, {47.3832726, 52.7123331}, {45.9070214, 53.8259442}},
-{{45.9070214, 53.8259442}, {44.4307701, 54.9395554}, {42.4058247, 57.7914576}},
-{{42.4058247, 57.7914576}, {40.3808794, 60.6433599}, {38.7979012, 63.1176732}},
-{{38.7979012, 63.1176732}, {37.3874524, 65.3142201}, {37.097116, 65.5770977}},
-{{37.097116, 65.5770977}, {36.8067796, 65.8399752}, {38.3585854, 62.6270533}},
-{{38.3585854, 62.6270533}, {39.9103912, 59.4141313}, {44.026369, 51.1832799}},
-</div>
-
-<div id="cubic7x2">
-{{8.53545089, 55.3230609}, {14.6846658, 5.17757498}, {19.5026836, 81.6040195}, {18.7564744, 40.0648544}},
-{{8.53545089, 55.3230609}, {9.80938657, 44.9343975}, {11.1496907, 40.6303968}},
-{{11.1496907, 40.6303968}, {12.2999484, 36.9366756}, {13.510145, 37.7040519}},
-{{13.510145, 37.7040519}, {14.4789672, 38.3183745}, {15.5359245, 41.871143}},
-{{15.5359245, 41.871143}, {16.1464176, 43.9232035}, {17.1461401, 48.4587871}},
-{{17.1461401, 48.4587871}, {17.9290951, 52.0109309}, {18.2017805, 52.6665884}},
-{{18.2017805, 52.6665884}, {18.6299694, 53.6961462}, {18.7604053, 51.1306715}},
-{{18.7604053, 51.1306715}, {18.904388, 48.2987505}, {18.7564744, 40.0648544}},
-</div>
-
-<div id="cubic7x2x">
-{{8.53545089, 55.3230609}, {14.6846658, 5.17757498}, {19.5026836, 81.6040195}, {18.7564744, 40.0648544}},
-{{8.53545089, 55.3230609}, {9.89590602, 44.4510387}, {11.1496907, 40.6303968}},
-{{11.1496907, 40.6303968}, {12.4034754, 36.8097549}, {13.510145, 37.7040519}},
-{{13.510145, 37.7040519}, {14.6168146, 38.5983488}, {15.5359245, 41.871143}},
-{{15.5359245, 41.871143}, {16.4550345, 45.1439372}, {17.1461401, 48.4587871}},
-{{17.1461401, 48.4587871}, {17.7900216, 51.5253445}, {18.2017805, 52.6665884}},
-{{18.2017805, 52.6665884}, {18.6135393, 53.8078322}, {18.7604053, 51.1306715}},
-{{18.7604053, 51.1306715}, {18.9072713, 48.4535108}, {18.7564744, 40.0648544}},
-</div>
-
-<div id="cubic7x3">
-{{77.2429303, 21.9290386}, {61.3518447, 40.4530391}, {94.2286334, 0.642292155}, {95.0042533, 36.4855481}},
-{{77.2429303, 21.9290386}, {76.5648343, 22.7194849}, {75.4687566, 23.992131}},
-{{75.4687566, 23.992131}, {73.1344126, 26.702517}, {72.9524614, 27.0039848}},
-{{72.9524614, 27.0039848}, {72.7705102, 27.3054527}, {74.013147, 26.4038735}},
-{{74.013147, 26.4038735}, {76.9396956, 24.2805538}, {79.071521, 23.1293275}},
-{{79.071521, 23.1293275}, {82.9580525, 21.0305265}, {85.9547875, 20.9037075}},
-{{85.9547875, 20.9037075}, {89.8728448, 20.737899}, {92.1150103, 23.9485892}},
-{{92.1150103, 23.9485892}, {94.8166786, 27.8172686}, {95.0042533, 36.4855481}},
-</div>
-
-<div id="cubic7x3x">
-{{77.2429303, 21.9290386}, {61.3518447, 40.4530391}, {94.2286334, 0.642292155}, {95.0042533, 36.4855481}},
-{{77.2429303, 21.9290386}, {76.2273572, 23.1121054}, {75.4687566, 23.992131}},
-{{75.4687566, 23.992131}, {73.1799004, 26.6271501}, {72.9524614, 27.0039848}},
-{{72.9524614, 27.0039848}, {72.7250224, 27.3808196}, {74.013147, 26.4038735}},
-{{74.013147, 26.4038735}, {75.7676189, 25.0320659}, {79.071521, 23.1293275}},
-{{79.071521, 23.1293275}, {82.3754232, 21.226589}, {85.9547875, 20.9037075}},
-{{85.9547875, 20.9037075}, {89.5341519, 20.580826}, {92.1150103, 23.9485892}},
-{{92.1150103, 23.9485892}, {94.6958688, 27.3163524}, {95.0042533, 36.4855481}},
-</div>
-
-<div id="cubic7x4">
-{{85.1880251, 55.1384624}, {12.1381459, 5.8187271}, {95.3464197, 87.2766355}, {58.4136199, 57.7104629}},
-{{85.1880251, 55.1384624}, {69.4954757, 44.5436142}, {61.7319269, 40.861468}},
-{{61.7319269, 40.861468}, {55.009991, 37.6733448}, {54.1223283, 39.6260005}},
-{{54.1223283, 39.6260005}, {53.4043154, 41.2054652}, {56.5289517, 46.3315706}},
-{{56.5289517, 46.3315706}, {58.3527212, 49.323546}, {63.1215192, 55.8776895}},
-{{63.1215192, 55.8776895}, {66.7797089, 60.9054346}, {67.68997, 62.4640064}},
-{{67.68997, 62.4640064}, {69.1578236, 64.9773019}, {67.3518779, 64.1520255}},
-{{67.3518779, 64.1520255}, {65.2740366, 63.2024988}, {58.4136199, 57.7104629}},
-</div>
-
-<div id="cubic7x4x">
-{{85.1880251, 55.1384624}, {12.1381459, 5.8187271}, {95.3464197, 87.2766355}, {58.4136199, 57.7104629}},
-{{85.1880251, 55.1384624}, {68.7695663, 44.1020224}, {61.7319269, 40.861468}},
-{{61.7319269, 40.861468}, {54.6942874, 37.6209137}, {54.1223283, 39.6260005}},
-{{54.1223283, 39.6260005}, {53.5503693, 41.6310872}, {56.5289517, 46.3315706}},
-{{56.5289517, 46.3315706}, {59.5075341, 51.032054}, {63.1215192, 55.8776895}},
-{{63.1215192, 55.8776895}, {66.1706775, 59.9915119}, {67.68997, 62.4640064}},
-{{67.68997, 62.4640064}, {69.2092626, 64.9365008}, {67.3518779, 64.1520255}},
-{{67.3518779, 64.1520255}, {65.4944933, 63.3675501}, {58.4136199, 57.7104629}},
-</div>
-
-<div id="cubic7x5">
-{{8.65591127, 79.9006976}, {91.0247206, 52.4786449}, {8.58452539, 80.1182901}, {48.1023732, 56.5861463}},
-{{8.65591127, 79.9006976}, {10.1949106, 79.3883372}, {13.1021747, 78.4205896}},
-{{13.1021747, 78.4205896}, {33.3914306, 71.6668594}, {38.6134953, 69.8848279}},
-{{38.6134953, 69.8848279}, {45.9243859, 67.3899838}, {46.7629899, 66.8658296}},
-{{46.7629899, 66.8658296}, {47.3619928, 66.4914338}, {44.5359397, 66.7758818}},
-{{44.5359397, 66.7758818}, {40.3498242, 67.197223}, {38.6707421, 67.0021236}},
-{{38.6707421, 67.0021236}, {35.6941333, 66.6562593}, {37.1605001, 64.6054153}},
-{{37.1605001, 64.6054153}, {39.032712, 61.9869609}, {48.1023732, 56.5861463}},
-</div>
-
-<div id="cubic7x5x">
-{{8.65591127, 79.9006976}, {91.0247206, 52.4786449}, {8.58452539, 80.1182901}, {48.1023732, 56.5861463}},
-{{8.65591127, 79.9006976}, {10.9639426, 79.1323302}, {13.1021747, 78.4205896}},
-{{13.1021747, 78.4205896}, {31.0714516, 72.4500538}, {38.6134953, 69.8848279}},
-{{38.6134953, 69.8848279}, {46.155539, 67.319602}, {46.7629899, 66.8658296}},
-{{46.7629899, 66.8658296}, {47.3704409, 66.4120572}, {44.5359397, 66.7758818}},
-{{44.5359397, 66.7758818}, {41.5267469, 67.1697889}, {38.6707421, 67.0021236}},
-{{38.6707421, 67.0021236}, {35.8147372, 66.8344583}, {37.1605001, 64.6054153}},
-{{37.1605001, 64.6054153}, {38.5062629, 62.3763723}, {48.1023732, 56.5861463}},
-</div>
-
-<div id="cubic7x6">
-{{42.8441148, 81.0382013}, {9.0486696, 80.9900212}, {99.2855478, 92.2020003}, {39.0193165, 97.6524087}},
-{{42.8441148, 81.0382013}, {36.5292256, 81.0291985}, {35.3205259, 81.5652507}},
-{{35.3205259, 81.5652507}, {34.274399, 82.0292026}, {36.9288084, 83.0293311}},
-{{36.9288084, 83.0293311}, {38.5699459, 83.647679}, {43.916545, 85.1977854}},
-{{43.916545, 85.1977854}, {50.735588, 87.1747884}, {53.7318941, 88.2602772}},
-{{53.7318941, 88.2602772}, {58.8545207, 90.11608}, {59.9920782, 91.5927712}},
-{{59.9920782, 91.5927712}, {61.3953813, 93.4144333}, {56.9901885, 94.8414282}},
-{{56.9901885, 94.8414282}, {51.9120881, 96.4864013}, {39.0193165, 97.6524087}},
-</div>
-
-<div id="cubic7x6x">
-{{42.8441148, 81.0382013}, {9.0486696, 80.9900212}, {99.2855478, 92.2020003}, {39.0193165, 97.6524087}},
-{{42.8441148, 81.0382013}, {36.3303003, 81.0383861}, {35.3205259, 81.5652507}},
-{{35.3205259, 81.5652507}, {34.3107514, 82.0921153}, {36.9288084, 83.0293311}},
-{{36.9288084, 83.0293311}, {39.5468653, 83.9665469}, {43.916545, 85.1977854}},
-{{43.916545, 85.1977854}, {48.9996472, 86.6173008}, {53.7318941, 88.2602772}},
-{{53.7318941, 88.2602772}, {58.4641409, 89.9032535}, {59.9920782, 91.5927712}},
-{{59.9920782, 91.5927712}, {61.5200154, 93.2822889}, {56.9901885, 94.8414282}},
-{{56.9901885, 94.8414282}, {52.4603617, 96.4005675}, {39.0193165, 97.6524087}},
-</div>
-
-<div id="cubic7x7">
-{{70.2955832, 57.867012}, {70.8709129, 27.4331047}, {68.1912432, 90.2241446}, {97.1991291, 25.763215}},
-{{70.2955832, 57.867012}, {70.3286385, 56.1184463}, {70.3691418, 53.5027125}},
-{{70.3691418, 53.5027125}, {70.4294268, 49.6094598}, {70.5008735, 49.1586526}},
-{{70.5008735, 49.1586526}, {70.5723202, 48.7078455}, {70.9407155, 49.8962556}},
-{{70.9407155, 49.8962556}, {71.8329974, 52.7746761}, {72.7964345, 54.1820074}},
-{{72.7964345, 54.1820074}, {74.5546706, 56.7503333}, {77.0780289, 56.0896348}},
-{{77.0780289, 56.0896348}, {80.3799099, 55.2250934}, {84.85557, 48.8673125}},
-{{84.85557, 48.8673125}, {90.2513448, 41.2024868}, {97.1991291, 25.763215}},
-</div>
-
-<div id="cubic7x7x">
-{{70.2955832, 57.867012}, {70.8709129, 27.4331047}, {68.1912432, 90.2241446}, {97.1991291, 25.763215}},
-{{70.2955832, 57.867012}, {70.3435094, 55.2546173}, {70.3691418, 53.5027125}},
-{{70.3691418, 53.5027125}, {70.4115651, 49.7221615}, {70.5008735, 49.1586526}},
-{{70.5008735, 49.1586526}, {70.5901819, 48.5951437}, {70.9407155, 49.8962556}},
-{{70.9407155, 49.8962556}, {71.3958651, 51.7896844}, {72.7964345, 54.1820074}},
-{{72.7964345, 54.1820074}, {74.1970039, 56.5743304}, {77.0780289, 56.0896348}},
-{{77.0780289, 56.0896348}, {79.9590538, 55.6049393}, {84.85557, 48.8673125}},
-{{84.85557, 48.8673125}, {89.7520861, 42.1296858}, {97.1991291, 25.763215}},
-</div>
-
-<div id="cubic7x8">
-{{50.528201, 27.4745214}, {64.2810473, 71.5620589}, {43.5236709, 2.33669765}, {72.8774712, 51.6581711}},
-{{50.528201, 27.4745214}, {53.3761101, 36.6040713}, {54.38742, 39.6099548}},
-{{54.38742, 39.6099548}, {55.5064406, 42.9359834}, {55.7720854, 42.9677817}},
-{{55.7720854, 42.9677817}, {55.9546136, 42.9896307}, {55.8827854, 40.8375726}},
-{{55.8827854, 40.8375726}, {55.7725733, 37.5354848}, {55.9802468, 35.9707481}},
-{{55.9802468, 35.9707481}, {56.3474228, 33.2042239}, {57.7009449, 33.0167369}},
-{{57.7009449, 33.0167369}, {59.424989, 32.7779259}, {62.7612346, 36.6782932}},
-{{62.7612346, 36.6782932}, {66.7088662, 41.293425}, {72.8774712, 51.6581711}},
-</div>
-
-<div id="cubic7x8x">
-{{50.528201, 27.4745214}, {64.2810473, 71.5620589}, {43.5236709, 2.33669765}, {72.8774712, 51.6581711}},
-{{50.528201, 27.4745214}, {53.2265224, 36.1478361}, {54.38742, 39.6099548}},
-{{54.38742, 39.6099548}, {55.5483175, 43.0720735}, {55.7720854, 42.9677817}},
-{{55.7720854, 42.9677817}, {55.9958532, 42.8634898}, {55.8827854, 40.8375726}},
-{{55.8827854, 40.8375726}, {55.7402514, 38.5138013}, {55.9802468, 35.9707481}},
-{{55.9802468, 35.9707481}, {56.2202423, 33.4276949}, {57.7009449, 33.0167369}},
-{{57.7009449, 33.0167369}, {59.1816474, 32.6057789}, {62.7612346, 36.6782932}},
-{{62.7612346, 36.6782932}, {66.3408218, 40.7508075}, {72.8774712, 51.6581711}},
-</div>
-
-<div id="cubic7x9">
-{{30.3413925, 47.7835835}, {98.6874047, 39.210338}, {8.15117029, 96.7190508}, {57.0872154, 64.8290379}},
-{{30.3413925, 47.7835835}, {46.0782555, 45.8095694}, {52.5540659, 48.2453346}},
-{{52.5540659, 48.2453346}, {57.9511897, 50.2753703}, {56.8130484, 55.3244869}},
-{{56.8130484, 55.3244869}, {55.9369414, 59.2111449}, {51.1961195, 64.811489}},
-{{51.1961195, 64.811489}, {48.5753558, 67.9074035}, {43.7810591, 72.4967897}},
-{{43.7810591, 72.4967897}, {41.2648644, 74.905441}, {42.230691, 74.4021224}},
-{{42.230691, 74.4021224}, {43.1965176, 73.8988039}, {51.5076718, 68.470241}},
-{{51.5076718, 68.470241}, {54.9756852, 66.2050527}, {57.0872154, 64.8290379}},
-</div>
-
-<div id="cubic7x9x">
-{{30.3413925, 47.7835835}, {98.6874047, 39.210338}, {8.15117029, 96.7190508}, {57.0872154, 64.8290379}},
-{{30.3413925, 47.7835835}, {46.9458744, 45.8339148}, {52.5540659, 48.2453346}},
-{{52.5540659, 48.2453346}, {58.1622574, 50.6567543}, {56.8130484, 55.3244869}},
-{{56.8130484, 55.3244869}, {55.4638393, 59.9922194}, {51.1961195, 64.811489}},
-{{51.1961195, 64.811489}, {46.9283998, 69.6307587}, {43.7810591, 72.4967897}},
-{{43.7810591, 72.4967897}, {41.0234077, 75.0312707}, {42.230691, 74.4021224}},
-{{42.230691, 74.4021224}, {43.4379742, 73.7729742}, {51.5076718, 68.470241}},
-{{51.5076718, 68.470241}, {53.9259122, 66.8899375}, {57.0872154, 64.8290379}},
-</div>
-
-<div id="cubic8x0">
-{{42.5967063, 22.8420382}, {6.13525533, 15.2363991}, {78.1588409, 15.6382141}, {31.4640028, 15.4944166}},
-{{42.5967063, 22.8420382}, {34.7914244, 21.2139034}, {32.6593413, 19.878761}},
-{{32.6593413, 19.878761}, {30.8695713, 18.7579803}, {33.1023831, 17.8591237}},
-{{33.1023831, 17.8591237}, {34.8391625, 17.1599535}, {39.0195021, 16.5984277}},
-{{39.0195021, 16.5984277}, {41.3590736, 16.2841638}, {45.5043686, 15.9119743}},
-{{45.5043686, 15.9119743}, {47.7538437, 15.7100029}, {47.8024311, 15.6545014}},
-{{47.8024311, 15.6545014}, {47.8704535, 15.5767993}, {44.9932779, 15.5487509}},
-{{44.9932779, 15.5487509}, {42.9381525, 15.5287163}, {34.6690635, 15.5040796}},
-{{34.6690635, 15.5040796}, {32.6017407, 15.4979203}, {31.4640028, 15.4944166}},
-</div>
-
-<div id="cubic8x0x">
-{{42.5967063, 22.8420382}, {6.13525533, 15.2363991}, {78.1588409, 15.6382141}, {31.4640028, 15.4944166}},
-{{42.5967063, 22.8420382}, {34.4196308, 21.1014023}, {32.6593413, 19.878761}},
-{{32.6593413, 19.878761}, {30.8990517, 18.6561197}, {33.1023831, 17.8591237}},
-{{33.1023831, 17.8591237}, {35.3057145, 17.0621277}, {39.0195021, 16.5984277}},
-{{39.0195021, 16.5984277}, {42.7332897, 16.1347277}, {45.5043686, 15.9119743}},
-{{45.5043686, 15.9119743}, {47.6292231, 15.7339768}, {47.8024311, 15.6545014}},
-{{47.8024311, 15.6545014}, {47.9756391, 15.575026}, {44.9932779, 15.5487509}},
-{{44.9932779, 15.5487509}, {42.0109167, 15.5224759}, {34.6690635, 15.5040796}},
-{{34.6690635, 15.5040796}, {33.169788, 15.4996412}, {31.4640028, 15.4944166}},
-</div>
-
-<div id="cubic8x1">
-{{29.0323957, 47.4745379}, {4.55778772, 2.73824763}, {21.7278637, 80.2053625}, {11.5269861, 34.0549996}},
-{{29.0323957, 47.4745379}, {23.6693619, 37.6716337}, {20.3221199, 34.4936205}},
-{{20.3221199, 34.4936205}, {17.5126817, 31.826221}, {16.162445, 33.8631071}},
-{{16.162445, 33.8631071}, {15.1123784, 35.4471745}, {14.9546458, 39.8886357}},
-{{14.9546458, 39.8886357}, {14.8663892, 42.3737787}, {15.0999972, 46.8758445}},
-{{15.0999972, 46.8758445}, {15.2259779, 49.3037298}, {15.1224749, 49.3309043}},
-{{15.1224749, 49.3309043}, {14.9775707, 49.3689487}, {14.2215808, 46.1220869}},
-{{14.2215808, 46.1220869}, {13.6815881, 43.8028999}, {11.62512, 34.4989774}},
-{{11.62512, 34.4989774}, {11.559983, 34.2042829}, {11.5269861, 34.0549996}},
-</div>
-
-<div id="cubic8x1x">
-{{29.0323957, 47.4745379}, {4.55778772, 2.73824763}, {21.7278637, 80.2053625}, {11.5269861, 34.0549996}},
-{{29.0323957, 47.4745379}, {23.339767, 37.184683}, {20.3221199, 34.4936205}},
-{{20.3221199, 34.4936205}, {17.3044729, 31.802558}, {16.162445, 33.8631071}},
-{{16.162445, 33.8631071}, {15.0204171, 35.9236561}, {14.9546458, 39.8886357}},
-{{14.9546458, 39.8886357}, {14.8888745, 43.8536153}, {15.0999972, 46.8758445}},
-{{15.0999972, 46.8758445}, {15.2455546, 49.1755419}, {15.1224749, 49.3309043}},
-{{15.1224749, 49.3309043}, {14.9993952, 49.4862668}, {14.2215808, 46.1220869}},
-{{14.2215808, 46.1220869}, {13.4437665, 42.757907}, {11.62512, 34.4989774}},
-{{11.62512, 34.4989774}, {11.5764809, 34.2789225}, {11.5269861, 34.0549996}},
-</div>
-
-<div id="cubic8x2">
-{{30.5187597, 28.7944151}, {47.7341773, 68.3182353}, {24.579915, 14.6321317}, {22.237118, 39.2417454}},
-{{30.5187597, 28.7944151}, {30.823715, 29.4945431}, {31.3959629, 30.8080078}},
-{{31.3959629, 30.8080078}, {34.9281707, 38.9153861}, {35.7821411, 40.9504208}},
-{{35.7821411, 40.9504208}, {36.9776996, 43.7994693}, {36.8148424, 43.845334}},
-{{36.8148424, 43.845334}, {36.6985159, 43.8780945}, {35.3792396, 41.9741019}},
-{{35.3792396, 41.9741019}, {33.3589087, 39.0583404}, {32.0725075, 37.4554574}},
-{{32.0725075, 37.4554574}, {29.7893226, 34.6105606}, {28.0338583, 33.4024856}},
-{{28.0338583, 33.4024856}, {25.7901854, 31.8584352}, {24.3823693, 32.9522328}},
-{{24.3823693, 32.9522328}, {22.7123482, 34.2497498}, {22.237118, 39.2417454}},
-</div>
-
-<div id="cubic8x2x">
-{{30.5187597, 28.7944151}, {47.7341773, 68.3182353}, {24.579915, 14.6321317}, {22.237118, 39.2417454}},
-{{30.5187597, 28.7944151}, {30.9761076, 29.8443688}, {31.3959629, 30.8080078}},
-{{31.3959629, 30.8080078}, {34.5380678, 38.0012585}, {35.7821411, 40.9504208}},
-{{35.7821411, 40.9504208}, {37.0262144, 43.899583}, {36.8148424, 43.845334}},
-{{36.8148424, 43.845334}, {36.6034705, 43.791085}, {35.3792396, 41.9741019}},
-{{35.3792396, 41.9741019}, {34.0487375, 39.9904922}, {32.0725075, 37.4554574}},
-{{32.0725075, 37.4554574}, {30.0962775, 34.9204225}, {28.0338583, 33.4024856}},
-{{28.0338583, 33.4024856}, {25.9714391, 31.8845487}, {24.3823693, 32.9522328}},
-{{24.3823693, 32.9522328}, {22.7932996, 34.019917}, {22.237118, 39.2417454}},
-</div>
-
-<div id="cubic8x3">
-{{44.0194731, 35.2849254}, {33.7413378, 90.6639866}, {89.6236054, 3.93610117}, {54.0523993, 58.6752083}},
-{{44.0194731, 35.2849254}, {41.8034025, 47.2252151}, {43.4093427, 51.8147312}},
-{{43.4093427, 51.8147312}, {44.7573046, 55.6669869}, {48.7793294, 54.2868164}},
-{{48.7793294, 54.2868164}, {51.9073817, 53.2134153}, {56.6514498, 48.9586591}},
-{{56.6514498, 48.9586591}, {59.3060696, 46.5778416}, {63.5477208, 42.0877376}},
-{{63.5477208, 42.0877376}, {65.8388976, 39.6623562}, {66.0159848, 39.6831127}},
-{{66.0159848, 39.6831127}, {66.2639069, 39.7121719}, {64.0479481, 43.2239426}},
-{{64.0479481, 43.2239426}, {62.4651204, 45.7323502}, {55.9567221, 55.7452241}},
-{{55.9567221, 55.7452241}, {54.718939, 57.649497}, {54.0523993, 58.6752083}},
-</div>
-
-<div id="cubic8x3x">
-{{44.0194731, 35.2849254}, {33.7413378, 90.6639866}, {89.6236054, 3.93610117}, {54.0523993, 58.6752083}},
-{{44.0194731, 35.2849254}, {41.7846308, 47.8464432}, {43.4093427, 51.8147312}},
-{{43.4093427, 51.8147312}, {45.0340547, 55.7830192}, {48.7793294, 54.2868164}},
-{{48.7793294, 54.2868164}, {52.524604, 52.7906136}, {56.6514498, 48.9586591}},
-{{56.6514498, 48.9586591}, {60.7782955, 45.1267046}, {63.5477208, 42.0877376}},
-{{63.5477208, 42.0877376}, {65.6800669, 39.7784361}, {66.0159848, 39.6831127}},
-{{66.0159848, 39.6831127}, {66.3519027, 39.5877893}, {64.0479481, 43.2239426}},
-{{64.0479481, 43.2239426}, {61.7439935, 46.8600958}, {55.9567221, 55.7452241}},
-{{55.9567221, 55.7452241}, {55.0519496, 57.1371078}, {54.0523993, 58.6752083}},
-</div>
-
-<div id="cubic8x4">
-{{34.4823321, 44.5556425}, {46.6831036, 2.92242272}, {17.1586486, 85.4072306}, {39.3243103, 23.6824388}},
-{{34.4823321, 44.5556425}, {36.9549821, 36.1181121}, {37.4421857, 33.458373}},
-{{37.4421857, 33.458373}, {37.852416, 31.2188464}, {36.8498458, 33.1020754}},
-{{36.8498458, 33.1020754}, {36.0666826, 34.5731701}, {34.4114682, 38.5859621}},
-{{34.4114682, 38.5859621}, {33.4805756, 40.8427565}, {31.8332086, 45.009246}},
-{{31.8332086, 45.009246}, {30.8106719, 47.5954265}, {30.8033416, 47.5462886}},
-{{30.8033416, 47.5462886}, {30.793079, 47.4774956}, {32.1835801, 43.5816708}},
-{{32.1835801, 43.5816708}, {33.1767952, 40.7989388}, {37.1569859, 29.7171487}},
-{{37.1569859, 29.7171487}, {38.5382511, 25.8713805}, {39.3243103, 23.6824388}},
-</div>
-
-<div id="cubic8x4x">
-{{34.4823321, 44.5556425}, {46.6831036, 2.92242272}, {17.1586486, 85.4072306}, {39.3243103, 23.6824388}},
-{{34.4823321, 44.5556425}, {37.0635768, 35.7091664}, {37.4421857, 33.458373}},
-{{37.4421857, 33.458373}, {37.8207947, 31.2075797}, {36.8498458, 33.1020754}},
-{{36.8498458, 33.1020754}, {35.878897, 34.996571}, {34.4114682, 38.5859621}},
-{{34.4114682, 38.5859621}, {32.9440394, 42.1753532}, {31.8332086, 45.009246}},
-{{31.8332086, 45.009246}, {30.8636314, 47.4784019}, {30.8033416, 47.5462886}},
-{{30.8033416, 47.5462886}, {30.7430517, 47.6141753}, {32.1835801, 43.5816708}},
-{{32.1835801, 43.5816708}, {33.6241085, 39.5491663}, {37.1569859, 29.7171487}},
-{{37.1569859, 29.7171487}, {38.146263, 26.9628595}, {39.3243103, 23.6824388}},
-</div>
-
-<div id="cubic8x5">
-{{67.1009526, 65.7102964}, {92.9511368, 29.7558215}, {6.09136899, 77.6386629}, {73.0077305, 40.9268787}},
-{{67.1009526, 65.7102964}, {72.234988, 58.569475}, {72.0584002, 54.9887776}},
-{{72.0584002, 54.9887776}, {71.9092626, 51.9646911}, {67.9699024, 51.5063347}},
-{{67.9699024, 51.5063347}, {64.8799872, 51.1468138}, {59.401457, 52.3770387}},
-{{59.401457, 52.3770387}, {56.3059837, 53.072139}, {50.919062, 54.7149606}},
-{{50.919062, 54.7149606}, {47.1095083, 55.8767404}, {47.0889098, 55.6405516}},
-{{47.0889098, 55.6405516}, {47.0600718, 55.3098873}, {52.2780952, 52.3607383}},
-{{52.2780952, 52.3607383}, {56.0052548, 50.2542034}, {70.9344915, 42.0642523}},
-{{70.9344915, 42.0642523}, {72.2995322, 41.3154119}, {73.0077305, 40.9268787}},
-</div>
-
-<div id="cubic8x5x">
-{{67.1009526, 65.7102964}, {92.9511368, 29.7558215}, {6.09136899, 77.6386629}, {73.0077305, 40.9268787}},
-{{67.1009526, 65.7102964}, {72.4119125, 58.1790269}, {72.0584002, 54.9887776}},
-{{72.0584002, 54.9887776}, {71.7048879, 51.7985283}, {67.9699024, 51.5063347}},
-{{67.9699024, 51.5063347}, {64.2349168, 51.2141411}, {59.401457, 52.3770387}},
-{{59.401457, 52.3770387}, {54.5679971, 53.5399363}, {50.919062, 54.7149606}},
-{{50.919062, 54.7149606}, {47.3051356, 55.8776986}, {47.0889098, 55.6405516}},
-{{47.0889098, 55.6405516}, {46.8726839, 55.4034046}, {52.2780952, 52.3607383}},
-{{52.2780952, 52.3607383}, {57.6835065, 49.3180721}, {70.9344915, 42.0642523}},
-{{70.9344915, 42.0642523}, {71.9455119, 41.5096286}, {73.0077305, 40.9268787}},
-</div>
-
-<div id="cubic8x6">
-{{34.6917773, 64.7007906}, {26.1879157, 40.299837}, {19.3601908, 86.7271998}, {24.0468774, 55.867852}},
-{{34.6917773, 64.7007906}, {32.8936408, 59.5412235}, {30.9809892, 57.9762826}},
-{{30.9809892, 57.9762826}, {29.3733084, 56.6608702}, {27.7048898, 57.9022642}},
-{{27.7048898, 57.9022642}, {26.4047253, 58.8696572}, {25.0679408, 61.4005651}},
-{{25.0679408, 61.4005651}, {24.3182009, 62.820033}, {23.2746043, 65.3930147}},
-{{23.2746043, 65.3930147}, {22.674283, 66.8731035}, {22.5736375, 66.8767729}},
-{{22.5736375, 66.8767729}, {22.4327337, 66.88191}, {22.7095685, 64.8303341}},
-{{22.7095685, 64.8303341}, {22.9073076, 63.3649228}, {23.7989097, 57.4996081}},
-{{23.7989097, 57.4996081}, {23.9603141, 56.4378254}, {24.0468774, 55.867852}},
-</div>
-
-<div id="cubic8x6x">
-{{34.6917773, 64.7007906}, {26.1879157, 40.299837}, {19.3601908, 86.7271998}, {24.0468774, 55.867852}},
-{{34.6917773, 64.7007906}, {32.7532689, 59.2911428}, {30.9809892, 57.9762826}},
-{{30.9809892, 57.9762826}, {29.2087096, 56.6614223}, {27.7048898, 57.9022642}},
-{{27.7048898, 57.9022642}, {26.2010699, 59.1431061}, {25.0679408, 61.4005651}},
-{{25.0679408, 61.4005651}, {23.9348117, 63.658024}, {23.2746043, 65.3930147}},
-{{23.2746043, 65.3930147}, {22.7294605, 66.7981817}, {22.5736375, 66.8767729}},
-{{22.5736375, 66.8767729}, {22.4178145, 66.955364}, {22.7095685, 64.8303341}},
-{{22.7095685, 64.8303341}, {23.0013225, 62.7053042}, {23.7989097, 57.4996081}},
-{{23.7989097, 57.4996081}, {23.9170479, 56.7225788}, {24.0468774, 55.867852}},
-</div>
-
-<div id="cubic8x7">
-{{33.7213174, 54.1809799}, {19.7290722, 86.516309}, {79.6055485, 30.4535282}, {32.4492169, 73.9888241}},
-{{33.7213174, 54.1809799}, {30.929259, 60.6332771}, {31.7178101, 63.1685506}},
-{{31.7178101, 63.1685506}, {32.3822203, 65.3046982}, {35.5832592, 64.6365068}},
-{{35.5832592, 64.6365068}, {38.0860576, 64.1140676}, {42.1661464, 61.8599641}},
-{{42.1661464, 61.8599641}, {44.4631798, 60.5909351}, {48.3149537, 58.1140379}},
-{{48.3149537, 58.1140379}, {50.7761073, 56.5313841}, {50.8756876, 56.6229029}},
-{{50.8756876, 56.6229029}, {51.0150999, 56.7510292}, {48.1271345, 59.4792497}},
-{{48.1271345, 59.4792497}, {46.064302, 61.4279786}, {37.7133917, 69.1313755}},
-{{37.7133917, 69.1313755}, {34.3790695, 72.2071608}, {32.4492169, 73.9888241}},
-</div>
-
-<div id="cubic8x7x">
-{{33.7213174, 54.1809799}, {19.7290722, 86.516309}, {79.6055485, 30.4535282}, {32.4492169, 73.9888241}},
-{{33.7213174, 54.1809799}, {30.8583849, 60.9640583}, {31.7178101, 63.1685506}},
-{{31.7178101, 63.1685506}, {32.5772353, 65.3730429}, {35.5832592, 64.6365068}},
-{{35.5832592, 64.6365068}, {38.589283, 63.8999708}, {42.1661464, 61.8599641}},
-{{42.1661464, 61.8599641}, {45.7430098, 59.8199575}, {48.3149537, 58.1140379}},
-{{48.3149537, 58.1140379}, {50.6281545, 56.5876371}, {50.8756876, 56.6229029}},
-{{50.8756876, 56.6229029}, {51.1232206, 56.6581687}, {48.1271345, 59.4792497}},
-{{48.1271345, 59.4792497}, {45.1310483, 62.3003307}, {37.7133917, 69.1313755}},
-{{37.7133917, 69.1313755}, {35.340896, 71.3195506}, {32.4492169, 73.9888241}},
-</div>
-
-<div id="cubic8x8">
-{{53.9853472, 31.729689}, {80.8833995, 7.2950833}, {8.46509939, 72.9253675}, {56.6511208, 35.3872682}},
-{{53.9853472, 31.729689}, {54.6892116, 31.0902877}, {55.8968586, 29.9930402}},
-{{55.8968586, 29.9930402}, {59.7242319, 26.5155538}, {60.0744106, 26.2078693}},
-{{60.0744106, 26.2078693}, {60.4245892, 25.9001849}, {58.6982878, 27.5315648}},
-{{58.6982878, 27.5315648}, {54.8548255, 31.1636922}, {52.2592609, 33.6639071}},
-{{52.2592609, 33.6639071}, {47.5369986, 38.2126941}, {44.5524326, 41.278553}},
-{{44.5524326, 41.278553}, {40.6568202, 45.2802731}, {39.8604011, 46.6125979}},
-{{39.8604011, 46.6125979}, {38.901811, 48.2162178}, {42.4657645, 45.9031378}},
-{{42.4657645, 45.9031378}, {46.5800498, 43.232881}, {56.6511208, 35.3872682}},
-</div>
-
-<div id="cubic8x8x">
-{{53.9853472, 31.729689}, {80.8833995, 7.2950833}, {8.46509939, 72.9253675}, {56.6511208, 35.3872682}},
-{{53.9853472, 31.729689}, {55.0401587, 30.7714526}, {55.8968586, 29.9930402}},
-{{55.8968586, 29.9930402}, {59.6366873, 26.5924749}, {60.0744106, 26.2078693}},
-{{60.0744106, 26.2078693}, {60.5121339, 25.8232638}, {58.6982878, 27.5315648}},
-{{58.6982878, 27.5315648}, {56.3310494, 29.756797}, {52.2592609, 33.6639071}},
-{{52.2592609, 33.6639071}, {48.1874723, 37.5710172}, {44.5524326, 41.278553}},
-{{44.5524326, 41.278553}, {40.9173929, 44.9860887}, {39.8604011, 46.6125979}},
-{{39.8604011, 46.6125979}, {38.8034093, 48.2391072}, {42.4657645, 45.9031378}},
-{{42.4657645, 45.9031378}, {46.1281196, 43.5671684}, {56.6511208, 35.3872682}},
-</div>
-
-<div id="cubic8x9">
-{{73.1810322, 53.6088109}, {3.28446082, 1.93300047}, {87.9389074, 89.2160727}, {54.5340817, 54.3107021}},
-{{73.1810322, 53.6088109}, {58.5574459, 42.7973267}, {51.3867695, 38.9320081}},
-{{51.3867695, 38.9320081}, {45.1924119, 35.5929695}, {44.6615376, 37.4897176}},
-{{44.6615376, 37.4897176}, {44.2222697, 39.0591673}, {47.6643015, 44.1654891}},
-{{47.6643015, 44.1654891}, {50.2846557, 48.0528359}, {55.0540263, 53.8428721}},
-{{55.0540263, 53.8428721}, {57.6549797, 57.0004406}, {61.4896769, 61.4054165}},
-{{61.4896769, 61.4054165}, {62.8763033, 62.9982556}, {62.6160157, 62.7489128}},
-{{62.6160157, 62.7489128}, {62.3557281, 62.49957}, {59.4073763, 59.4106743}},
-{{59.4073763, 59.4106743}, {56.5808171, 56.449377}, {54.5340817, 54.3107021}},
-</div>
-
-<div id="cubic8x9x">
-{{73.1810322, 53.6088109}, {3.28446082, 1.93300047}, {87.9389074, 89.2160727}, {54.5340817, 54.3107021}},
-{{73.1810322, 53.6088109}, {57.8490138, 42.3222252}, {51.3867695, 38.9320081}},
-{{51.3867695, 38.9320081}, {44.9245252, 35.5417911}, {44.6615376, 37.4897176}},
-{{44.6615376, 37.4897176}, {44.3985499, 39.4376442}, {47.6643015, 44.1654891}},
-{{47.6643015, 44.1654891}, {50.9300531, 48.893334}, {55.0540263, 53.8428721}},
-{{55.0540263, 53.8428721}, {59.1779995, 58.7924103}, {61.4896769, 61.4054165}},
-{{61.4896769, 61.4054165}, {62.9413752, 63.0605913}, {62.6160157, 62.7489128}},
-{{62.6160157, 62.7489128}, {62.2906562, 62.4372343}, {59.4073763, 59.4106743}},
-{{59.4073763, 59.4106743}, {57.5885087, 57.5036974}, {54.5340817, 54.3107021}},
-</div>
-
-<div id="cubic4">
-{{24.2578299, 1.34695745}, {6.77689729, 99.312693}, {3.18338154, 3.09354817}, {59.132973, 47.8778685}},
-{{38.313885, 41.465269}, {48.4308047, 76.5337766}, {93.264044, 88.7879534}, {83.3354337, 18.6335197}}
-</div>
-
-<div id="cubic5">
-{{24.0062249, 72.6211198}, {22.3913226, 30.9587957}, {80.7539402, 31.4736433}, {99.6348716, 63.2867312}},
-{{43.1612821, 11.6690897}, {24.4801394, 37.7033828}, {77.5229567, 28.3334108}, {60.0910899, 50.9480224}}
-$6 = {{x = 24.006224853920855, y = 72.621119847810419}, {x = 24.119692298829129, y = 51.890688643515688}, {x = 38.700154924642845, y = 44.614929583485953}}
-(gdb) p q2
-$7 = {{x = 24.006224853920855, y = 72.621119847810419}, {x = 29.758671200376888, y = 31.764642512385173}, {x = 71.277052443896736, y = 42.309313461363033}}
-</div>
-
-<div id="quad1">
-{{x = 34.879150914024962, y = 83.862726601601125}, {x = 35.095810134304429, y = 83.693473210169543}, {x = 35.359284111931586, y = 83.488069234177502}}
-{{x = 54.503204203015471, y = 76.094098492518242}, {x = 51.366889541918894, y = 71.609856061299155}, {x = 46.53086955445437, y = 69.949863036494207}}
-</div>
-
-<div id="cubic6">
-{{x = 54.080923997834752, y = 38.089631608729078}, {x = 10.447347774378651, y = 88.574043981998258}, {x = 33.294667831293616, y = 83.482240551841556}, {x = 25.649263209500006, y = 87.166762066617025}}
-</div>
-
-<div id="quad2">
-{{x = 25.367434474345036, y = 50.4712103169743}, {x = 17.865013304933097, y = 37.356741010559439}, {x = 16.818988838905465, y = 37.682915484123129}}
-{{x = 16.818988838905465, y = 37.682915484123129}, {x = 15.772964372877833, y = 38.009089957686811}, {x = 20.624104547604965, y = 41.825131596683121}}
-</div>
-
-<div id="cubic7">
-{{x = 25.367434474345036, y = 50.4712103169743}, {x = 5.2367042308844178, y = 13.28800847441331}, {x = 21.031375239152169, y = 74.32364443052731}, {x = 60.821163496384933, y = 21.294883741668837}}
-</div>
-
-<div id="quad3">
-{{x = 36.148792695174222, y = 70.336952793070424}, {x = 36.141613037691357, y = 70.711654739870085}, {x = 36.154708826402597, y = 71.088492662905836}}
-{{x = 35.216235592661825, y = 70.580199617313212}, {x = 36.244476835123969, y = 71.010897787304074}, {x = 37.230244263238326, y = 71.423156953613102}}
-</div>
-
-<div id="quad4">
-{{x = 369.84860200000003, y = 145.68026699999999}, {x = 382.36041299999999, y = 121.298294}, {x = 406.20770299999998, y = 121.298294}}
-{{x = 369.850525, y = 145.67596399999999}, {x = 382.36291499999999, y = 121.29286999999999}, {x = 406.21127300000001, y = 121.29286999999999}}
-</div>
-
-<div id="quad5">
-{{x = 67.25299631583178, y = 21.109080184767524}, {x = 43.617595267398613, y = 33.658034168577529}, {x = 33.38371819435676, y = 44.214192553988745}}
-{{x = 40.476838859398541, y = 39.543209911285999}, {x = 36.701186108431131, y = 34.8817994016458}, {x = 30.102144288878023, y = 26.739063172945315}}
-</div>
-
-<div id="quad6">
-{{x = 59.981867574297752, y = 19.243986850744687}, {x = 59.992798861020468, y = 19.257454808070786}, {x = 60.003741189575571, y = 19.270930807443623}}
-{{x = 47.800898294803176, y = 89.697640756935641}, {x = 38.74069898238357, y = 58.416865487251982}, {x = 37.639862598936119, y = 44.208141075385868}}
-</div>
-
-<div id="cubic8">
-{{x = 53.674595921148828, y = 8.9336467482771944}, {x = 48.248201817389678, y = 7.5279448682106773}, {x = 89.942031162763953, y = 55.717752573880254}, {x = 81.402728418541486, y = 35.656530426655216}}
-{{x = 47.800898294803176, y = 89.697640756935641}, {x = 22.169400016856102, y = 1.1060833004797266}, {x = 48.267509205391399, y = 32.027215013293187}, {x = 79.306880794142785, y = 10.745507157754854}}
-</div>
-
-<div id="quad7">
-{{x = 33.567436351153468, y = 62.336347586395924}, {x = 35.200980274619084, y = 65.038561460144479}, {x = 36.479571811084995, y = 67.632178905412445}}
-{{x = 41.349524945572696, y = 67.886658677862641}, {x = 39.125562529359087, y = 67.429772735149214}, {x = 35.600314083992416, y = 66.705372160552685}}
-</div>
-
-<div id="quad8">
-{{x = 36.148792695174222, y = 70.336952793070424}, {x = 36.141613037691357, y = 70.711654739870085}, {x = 36.154708826402597, y = 71.088492662905836}}
-{{x = 35.216235592661825, y = 70.580199617313212}, {x = 36.244476835123969, y = 71.010897787304074}, {x = 37.230244263238326, y = 71.423156953613102}}
-</div>
-
-<div id="quad9">
-{{353.2948,194.351074}, {353.2948,173.767563}, {364.167572,160.819855}},
-{{360.416077,166.795715}, {370.126831,147.872162}, {388.635406,147.872162}},
-</div>
-
-<div id="quad10">
- {{8, 8}, {10, 10}, {8, -10}},
- {{8, 8}, {12, 12}, {14, 4}},
-</div>
-
-<div id="quad11">
-{{x = 50.934805397717923, y = 51.52391952648901}, {x = 56.803308902971423, y = 44.246234610627596}, {x = 69.776888596721406, y = 40.166645096692555}}
-{{x = 50.230212796400401, y = 38.386469101526998}, {x = 49.855620812184917, y = 38.818990392153609}, {x = 56.356567496227363, y = 47.229909093319407}}
-</div>
-
-<div id="cubic9">
-{{18.1312339, 31.6473732}, {95.5711034, 63.5350219}, {92.3283165, 62.0158945}, {18.5656052, 32.1268808}},
-{{97.402018, 35.7169972}, {33.1127443, 25.8935163}, {1.13970027, 54.9424981}, {56.4860195, 60.529264}},
-</div>
-
-<div id="cubic10">
-{{67.4265481, 37.9937726}, {23.4836959, 90.4768632}, {35.5970651, 79.8724826}, {75.3863417, 18.24489}},
-{{61.3365082, 82.6931328}, {44.6393809, 54.0748258}, {16.8156155, 20.0497047}, {41.866885, 56.7355037}},
-</div>
-
-<div id="cubic11">
-{{40.3684631, 72.7588382}, {85.2198593, 90.174892}, {31.9101421, 13.7580149}, {72.0483425, 16.4930846}},
-{{57.7943379, 49.4368549}, {69.4103137, 79.1415428}, {30.9563231, 82.9221187}, {99.2731298, 83.4922981}},
-</div>
-
-<div id="cubic12">
-{{98.3415562, 26.5353662}, {15.3721551, 59.8107939}, {77.1895742, 25.1742572}, {11.7326863, 91.2589209}},
-{{79.899867, 77.0640431}, {40.0129651, 97.9042774}, {3.74105489, 75.9095456}, {88.6837571, 7.90615282}},
-</div>
-
-<div id="cubic13">
-{{95.6513419, 12.1029701}, {63.4801516, 10.9081754}, {41.0209588, 39.2537121}, {65.9441362, 23.0970739}},
-{{14.6179238, 83.4452002}, {33.7032426, 50.3981092}, {37.1399002, 10.3032037}, {92.5218685, 15.0431467}},
-</div>
-
-<div id="cubic14">
-{{67.4265481, 37.9937726}, {23.4836959, 90.4768632}, {35.5970651, 79.8724826}, {75.3863417, 18.24489}},
-{{61.3365082, 82.6931328}, {44.6393809, 54.0748258}, {16.8156155, 20.0497047}, {41.866885, 56.7355037}},
-{{67.4265481,37.9937726}, {51.1295132,57.5422812}, {44.5947482,65.6442673}},
-{{44.5947482,65.6442673}, {35.2387481,77.3910511}, {43.2346162,66.2224493}},
-{{43.2346162,66.2224493}, {51.8234203,54.2750917}, {75.3863417,18.24489}},
-{{61.3365082,82.6931328}, {54.8250789,71.6639328}, {47.7274442,61.4049645}},
-{{47.7274442,61.4049645}, {40.6298095,51.1459962}, {35.9460478,45.2252785}},
-{{35.9460478,45.2252785}, {31.2622861,39.3045608}, {31.9924758,41.2901124}},
-{{31.9924758,41.2901124}, {32.7226655,43.275664}, {41.866885,56.7355037}},
-</div>
-
-<div id="quad12">
-{{x = 67.426548091427676, y = 37.993772624988935}, {x = 51.129513170665042, y = 57.542281234563646}, {x = 44.594748190899182, y = 65.644267382683879}}
-{{x = 61.336508189019057, y = 82.693132843213675}, {x = 54.825078921449354, y = 71.663932799212432}, {x = 47.727444217558926, y = 61.4049645128392}}
-</div>
-
-<div id="quad13">
-{{x = 53.774852327053594, y = 53.318060789841951}, {x = 45.787877803416805, y = 51.393492026284981}, {x = 46.703936967162392, y = 53.06860709822206}}
-{{x = 46.703936967162392, y = 53.06860709822206}, {x = 47.619996130907957, y = 54.74372217015916}, {x = 53.020051653535361, y = 48.633140968832024}}
-</div>
-
-<div id="cubic15">
-{{40.3684631, 72.7588382}, {85.2198593, 90.174892}, {31.9101421, 13.7580149}, {72.0483425, 16.4930846}},
-{{57.7943379, 49.4368549}, {69.4103137, 79.1415428}, {30.9563231, 82.9221187}, {99.2731298, 83.4922981}},
-</div>
-
-<div id="cubic16">
-{{98.3415562, 26.5353662}, {15.3721551, 59.8107939}, {77.1895742, 25.1742572}, {11.7326863, 91.2589209}},
-{{79.899867, 77.0640431}, {40.0129651, 97.9042774}, {3.74105489, 75.9095456}, {88.6837571, 7.90615282}},
-</div>
-
-<div id="cubic17">
-{{95.6513419, 12.1029701}, {63.4801516, 10.9081754}, {41.0209588, 39.2537121}, {65.9441362, 23.0970739}},
-{{14.6179238, 83.4452002}, {33.7032426, 50.3981092}, {37.1399002, 10.3032037}, {92.5218685, 15.0431467}},
-{{95.6513419,12.1029701}, {79.216947,12.1911515}, {68.1126831,18.0126375}},
-{{68.1126831,18.0126375}, {57.0084192,23.8341235}, {55.4198832,27.1619689}},
-{{55.4198832,27.1619689}, {53.8313472,30.4898143}, {65.9441362,23.0970739}},
-{{14.6179238,83.4452002}, {20.3825754,73.0912112}, {25.0377248,62.5209893}},
-{{25.0377248,62.5209893}, {33.2090045,41.6303758}, {46.9147771,27.3313746}},
-{{46.9147771,27.3313746}, {60.6205496,13.0323735}, {92.5218685,15.0431467}},
-</div>
-
-<div id="cubic18">
-{{55.7513494, 12.929877}, {46.4296358, 42.8887602}, {16.8160022, 26.5487217}, {4.93643419, 66.6494508}},
-{{12.4426199, 23.1121812}, {31.3921366, 7.64067448}, {4.36561578, 72.9044408}, {77.3190123, 0.63959742}},
-
-{{55.7513494,12.929877}, {52.399261,23.0070161}, {46.4958203,27.5595279}},
-{{46.4958203,27.5595279}, {40.5923795,32.1120397}, {33.5495747,34.9548738}},
-{{33.5495747,34.9548738}, {25.3214643,38.1279717}, {17.6150117,44.5570525}},
-{{17.6150117,44.5570525}, {9.90855921,50.9861334}, {4.93643419,66.6494508}},
-
-{{12.4426199,23.1121812}, {17.0040168,19.5021098}, {18.7553606,21.0894159}},
-{{18.7553606,21.0894159}, {20.5067044,22.676722}, {21.4650431,26.4450934}},
-{{21.4650431,26.4450934}, {22.5692754,31.7464864}, {26.4671516,34.648351}},
-{{26.4671516,34.648351}, {30.3650278,37.5502156}, {41.873704,30.8489321}},
-{{41.873704,30.8489321}, {53.3823801,24.1476487}, {77.3190123,0.63959742}},
-</div>
-
-<div id="quad14">
-{{67.4265481,37.9937726}, {51.1295132,57.5422812}, {44.5947482,65.6442674}},
-{{61.3365082,82.6931328}, {54.8250789,71.6639328}, {47.7274442,61.4049645}},
-</div>
-
-<div id="quad15">
-{{x = 80.897794748143198, y = 49.236332042718459}, {x = 81.082078218891212, y = 64.066749904488631}, {x = 69.972305057149981, y = 72.968595519850993}}
-{{x = 72.503745601281395, y = 32.952320736577882}, {x = 88.030880716061645, y = 38.137194847810164}, {x = 73.193774825517906, y = 67.773492479591397}}
-</div>
-
-<div id="cubic19">
-{{x = 34.560092601254624, y = 51.476349286491221}, {x = 27.498466254909744, y = 66.722346267999313}, {x = 42.500359724508769, y = 3.5458898188294325}, {x = 73.37353619438295, y = 89.022818994253328}}
-{{x = 63.002458057833124, y = 82.312578001205154}, {x = 2.4737262644217006, y = 75.917326135522373}, {x = 95.77018506628005, y = 9.5004089686555826}, {x = 6.5188364156143912, y = 62.083637231068508}}
-</div>
-
-<div id="cubic20">
- {{x = 42.449716172390481, y = 52.379709366885805}, {x = 27.896043159019225, y = 48.797373636065686}, {x = 92.770268299044233, y = 89.899302036454571}, {x = 12.102066544863426, y = 99.43241951960718}}
-{{x = 45.77532924980639, y = 45.958701495993274}, {x = 37.458701356062065, y = 68.393691335056758}, {x = 37.569326692060258, y = 27.673713456687381}, {x = 60.674866037757539, y = 62.47349659096146}}
-</div>
-
-<div id="cubic21">
-{{x = 26.192053931854691, y = 9.8504326817814416}, {x = 10.174241480498686, y = 98.476562741434464}, {x = 21.177712558385782, y = 33.814968789841501}, {x = 75.329030899018534, y = 55.02231980442177}}
-{{x = 56.222082700683771, y = 24.54395039218662}, {x = 95.589995289030483, y = 81.050822735322086}, {x = 28.180450866082897, y = 28.837706255185282}, {x = 60.128952916771617, y = 87.311672180570511}}
-</div>
-
-<div id="quad16">
-{{x = 67.965974918365831, y = 52.573040929556633}, {x = 67.973015821010591, y = 52.57495862082331}, {x = 67.980057838863502, y = 52.576878275262274}}
-{{x = 67.975025709349239, y = 52.572750461020817}, {x = 67.973101328974863, y = 52.57506284863603}, {x = 67.971173663444745, y = 52.577372136133093}}
-</div>
-
-<div id="quad17">
-{{x = 52.14807018377202, y = 65.012420045148644}, {x = 44.778669050208237, y = 66.315562705604378}, {x = 51.619118408823567, y = 63.787827046262684}}
-{{x = 30.004993234763383, y = 93.921296668202288}, {x = 53.384822003076991, y = 60.732180341802753}, {x = 58.652998934338584, y = 43.111073088306185}}
-</div>
-
-<div id="quad18">
-{{x = 369.850525, y = 145.67596399999999}, {x = 382.36291499999999, y = 121.29286999999999}, {x = 406.21127300000001, y = 121.29286999999999}}
-{{x = 369.962311, y = 137.976044}, {x = 383.97189300000002, y = 121.29286999999999}, {x = 406.21612499999998, y = 121.29286999999999}}
-</div>
-
-<div id="quad19">
-{{x = 406.23635899999999, y = 121.254936}, {x = 409.44567899999998, y = 121.254936}, {x = 412.97595200000001, y = 121.789818}}
-{{x = 406.23599200000001, y = 121.254936}, {x = 425.70590199999998, y = 121.254936}, {x = 439.71994000000001, y = 137.087616}}
-</div>
-
-<div id="cubic22">
-{{x = 7.5374809128872498, y = 82.441702896003477}, {x = 22.444346930107265, y = 22.138854312775123}, {x = 66.76091829629658, y = 50.753805856571446}, {x = 78.193478508942519, y = 97.7932997968948}}
-{{x = 97.700573130371311, y = 53.53260215070685}, {x = 87.72443481149358, y = 84.575876772671876}, {x = 19.215031396232092, y = 47.032676472809484}, {x = 11.989686410869325, y = 10.659507480757082}}
- {{7.53748091,82.4417029}, {15.5677076,52.942994}, {29.9404074,49.1672596}},
- {{29.9404074,49.1672596}, {44.3131071,45.3915253}, {58.1067559,59.5061814}},
- {{58.1067559,59.5061814}, {71.9004047,73.6208375}, {78.1934785,97.7932998}},
-
- {{97.7005731,53.5326022}, {91.6030843,68.4083459}, {72.6510251,64.2972928}},
- {{72.6510251,64.2972928}, {53.6989659,60.1862397}, {35.2053722,44.8391126}},
- {{35.2053722,44.8391126}, {16.7117786,29.4919856}, {11.9896864,10.6595075}},
-</div>
-
-<div id="quad20">
- {{29.9404074,49.1672596}, {44.3131071,45.3915253}, {58.1067559,59.5061814}},
- {{72.6510251,64.2972928}, {53.6989659,60.1862397}, {35.2053722,44.8391126}},
-</div>
-
-<div id="cubic23">
-{{x = 32.484981432782945, y = 75.082940782924624}, {x = 42.467313093350882, y = 48.131159948246157}, {x = 3.5963115764764657, y = 43.208665839959245}, {x = 79.442476890721579, y = 89.709102357602262}}
-{{x = 18.98573861410177, y = 93.308887208490106}, {x = 40.405250173250792, y = 91.039661826118675}, {x = 8.0467721950480584, y = 42.100282172719147}, {x = 40.883324221187891, y = 26.030185504830527}}
- {{32.4849814,75.0829408}, {35.4553509,65.5763004}, {33.5767697,60.2097835}},
- {{33.5767697,60.2097835}, {31.6981886,54.8432666}, {31.1663962,54.7302484}},
- {{31.1663962,54.7302484}, {31.1662882,54.7301074}, {31.1663969,54.7302485}},
- {{31.1663969,54.7302485}, {30.4117445,54.6146017}, {40.1631726,62.9428436}},
- {{40.1631726,62.9428436}, {49.9146008,71.2710854}, {79.4424769,89.7091024}},
-
- {{18.9857386,93.3088872}, {25.7662938,92.3417699}, {26.5917262,85.8225583}},
- {{26.5917262,85.8225583}, {27.4171586,79.3033467}, {26.141946,69.8089528}},
- {{26.141946,69.8089528}, {24.2922348,57.665767}, {26.0404936,45.4260361}},
- {{26.0404936,45.4260361}, {27.7887523,33.1863051}, {40.8833242,26.0301855}},
-</div>
-
-<div id="quad21">
- {{31.1663962,54.7302484}, {31.1662882,54.7301074}, {31.1663969,54.7302485}},
- {{26.0404936,45.4260361}, {27.7887523,33.1863051}, {40.8833242,26.0301855}},
-</div>
-
-<div id="cubic24">
-{{x = 65.454505973241524, y = 93.881892270353575}, {x = 45.867360264932437, y = 92.723972719499827}, {x = 2.1464054482739447, y = 74.636369140183717}, {x = 33.774068594804994, y = 40.770872887582925}}
-{{x = 72.963387832494163, y = 95.659300729473728}, {x = 11.809496633619768, y = 82.209921247423594}, {x = 13.456139067865974, y = 57.329313623406605}, {x = 36.060621606214262, y = 70.867335643091849}}
- {{65.454506,93.8818923}, {54.7397995,93.2922678}, {41.5072916,87.1234036}},
- {{41.5072916,87.1234036}, {28.2747836,80.9545395}, {23.5780771,69.3344126}},
- {{23.5780771,69.3344126}, {18.8813706,57.7142857}, {33.7740686,40.7708729}},
-
- {{72.9633878,95.6593007}, {42.7738746,88.4730382}, {31.1932785,80.2458029}},
- {{31.1932785,80.2458029}, {19.6126823,72.0185676}, {21.9918152,68.2892325}},
- {{21.9918152,68.2892325}, {24.370948,64.5598974}, {36.0606216,70.8673356}},
-</div>
-
-<div id="quad22">
- {{41.5072916,87.1234036}, {28.2747836,80.9545395}, {23.5780771,69.3344126}},
- {{72.9633878,95.6593007}, {42.7738746,88.4730382}, {31.1932785,80.2458029}},
-</div>
-
-<div id="cubic25">
-{{x = 39.765160968417838, y = 33.060396198677083}, {x = 5.1922921581157908, y = 66.854301452103215}, {x = 31.619281802149157, y = 25.269248720849514}, {x = 81.541621071073038, y = 70.025341524754353}}
-{{x = 46.078911165743556, y = 48.259962651999651}, {x = 20.24450549867214, y = 49.403916182650214}, {x = 0.26325131778756683, y = 24.46489805563581}, {x = 15.915006546264051, y = 83.515023059917155}}
- {{39.765161,33.0603962}, {30.6426004,41.804305}, {26.9359756,44.8138368}},
- {{26.9359756,44.8138368}, {21.5667569,48.8605535}, {26.2727712,47.6735862}},
- {{26.2727712,47.6735862}, {31.3832959,46.2642047}, {45.8264929,49.1528875}},
- {{45.8264929,49.1528875}, {60.2696898,52.0415702}, {81.5416211,70.0253415}},
-
- {{46.0789112,48.2599627}, {35.5887068,48.1941457}, {27.2014026,45.6924463}},
- {{27.2014026,45.6924463}, {19.5490336,43.4817863}, {15.020365,44.2719744}},
- {{15.020365,44.2719744}, {10.4916964,45.0621625}, {10.3896311,53.6689795}},
- {{10.3896311,53.6689795}, {10.2875658,62.2757965}, {15.9150065,83.5150231}},
-</div>
-
-<div id="cubic26">
-{{x = 95.837747722788592, y = 45.025976907939643}, {x = 16.564570095652982, y = 0.72959763963222402}, {x = 63.209855865319199, y = 68.047528419665767}, {x = 57.640240647662544, y = 59.524565264361243}}
-{{x = 51.593891741518817, y = 38.53849970667553}, {x = 62.34752929878772, y = 74.924924725166022}, {x = 74.810149322641152, y = 34.17966562983564}, {x = 29.368398119401373, y = 94.66719277886078}}
- {{95.8377477,45.0259769}, {72.4120612,32.1119735}, {61.9589898,30.3422249}},
- {{61.9589898,30.3422249}, {51.5059185,28.5724763}, {49.7502617,33.4480576}},
- {{49.7502617,33.4480576}, {47.9946048,38.3236388}, {50.6611618,45.345625}},
- {{50.6611618,45.345625}, {53.3277187,52.3676112}, {56.1412886,57.0370775}},
- {{56.1412886,57.0370775}, {58.9548585,61.7065438}, {57.6402406,59.5245653}},
-
- {{51.5938917,38.5384997}, {54.39659,47.5609728}, {56.9124968,51.2509862}},
- {{56.9124968,51.2509862}, {59.4284036,54.9409997}, {60.7901347,55.8937858}},
- {{60.7901347,55.8937858}, {63.1940269,56.8659601}, {59.551481,59.5998651}},
- {{59.551481,59.5998651}, {56.8806183,61.8512737}, {49.6576236,69.6523525}},
- {{49.6576236,69.6523525}, {42.434629,77.4534313}, {29.3683981,94.6671928}},
-</div>
-
-<div id="quad23">
-{{x = 56.14128857485079, y = 57.037077517172825}, {x = 58.954858484191291, y = 61.706543802985237}, {x = 57.640240647662544, y = 59.524565264361243}}
-{{x = 59.551480981235549, y = 59.599865066889976}, {x = 56.880618274428095, y = 61.851273706132794}, {x = 49.657623623535379, y = 69.652352522894546}}
-</div>
-
-<div id="cubic27">
-{{x = 56.14128857485079, y = 57.037077517172825}, {x = 57.779490695232283, y = 59.900114769069532}, {x = 58.754163691193881, y = 61.229157895422141}, {x = 57.640240647662544, y = 59.524565264361243}}
-{{x = 56.14128857485079, y = 57.037077517172825}, {x = 58.954858484191291, y = 61.706543802985237}, {x = 57.640240647662544, y = 59.524565264361243}}
-</div>
-
-<div id="testCubic1">
-{{0, 0}, {0, 1}, {1, 1}, {1, 0}},
-{{1, 0}, {0, 0}, {0, 1}, {1, 1}},
-
- {{0,0}, {0.0185185185,0.5}, {0.259259259,0.666666667}},
- {{0.259259259,0.666666667}, {0.5,0.833333333}, {0.740740741,0.666666667}},
- {{0.740740741,0.666666667}, {0.981481481,0.5}, {1,0}},
-
- {{1,0}, {0.5,0.0185185185}, {0.333333333,0.259259259}},
- {{0.333333333,0.259259259}, {0.166666667,0.5}, {0.333333333,0.740740741}},
- {{0.333333333,0.740740741}, {0.5,0.981481481}, {1,1}},
-</div>
-
-<div id="testCubic1a">
-{{x = 0.30075438676757493, y = 0.69070348972827045}, {x = 0.30339450221247349, y = 0.69543451478800855}, {x = 0.30613761677734441, y = 0.7001387457168422}, {x = 0.30898373046218741, y = 0.70481409186990207}}
-{{x = 0.29518590813009821, y = 0.69101626953781281}, {x = 0.29986125428315819, y = 0.69386238322265548}, {x = 0.30456548521199123, y = 0.69660549778752689}, {x = 0.30929651027172955, y = 0.69924561323242507}}
-</div>
-
-<div id="testCubic1b">
-{{x = 0.3039751936710845, y = 0.69622610811401087}, {x = 0.3037698832307662, y = 0.69610758676672113}}
-{{x = 0.3037698832307662, y = 0.69610758676672113}, {x = 0.30387252963474076, y = 0.69616688005807803}}
-{{x = 0.30387252963474076, y = 0.69616688005807803}, {x = 0.3039751936710845, y = 0.69622610811401087}}
-</div>
-
-<div id="cubicOp1d">
-{{0, 1}, {0, 2}, {1, 0}, {1, 0}},
-{{0, 1}, {0, 1}, {1, 0}, {2, 0}},
-
- {{0,1}, {0.0078125,1.35546875}, {0.15625,1.265625}},
- {{0.15625,1.265625}, {0.3046875,1.17578125}, {0.5,0.875}},
- {{0.5,0.875}, {0.6953125,0.57421875}, {0.84375,0.296875}},
- {{0.84375,0.296875}, {0.9921875,0.01953125}, {1,0}},
-
- {{0,1}, {0.00925925926,0.981481481}, {0.296296296,0.740740741}},
- {{0.296296296,0.740740741}, {0.583333333,0.5}, {1.03703704,0.259259259}},
- {{1.03703704,0.259259259}, {1.49074074,0.0185185185}, {2,0}},
-</div>
-
-<div id="cubicTest1">
-{{0, 1}, {5, 6}, {1, 0}, {1, 0}},
-{{0, 1}, {0, 1}, {1, 0}, {6, 5}},
- {{0,1}, {1.474,2.466}, {2.024,2.816}},
- {{2.024,2.816}, {2.574,3.166}, {2.512,2.808}},
- {{2.512,2.808}, {2.45,2.45}, {2.088,1.792}},
- {{2.088,1.792}, {1.726,1.134}, {1.376,0.584}},
- {{1.376,0.584}, {1.026,0.034}, {1,0}},
-
- {{0,1}, {-0.0277777778,0.935185185}, {0.444444444,0.925925926}},
- {{0.444444444,0.925925926}, {0.916666667,0.916666667}, {2.22222222,1.74074074}},
- {{2.22222222,1.74074074}, {3.52777778,2.56481481}, {6,5}},
-</div>
-
-<div id="cubicTest2">
-{{fX = 0, fY = 1}, {fX = 0, fY = 2}, {fX = 1, fY = 0}, {fX = 5, fY = 0}}
-{{fX = 0, fY = 1}, {fX = 0, fY = 5}, {fX = 1, fY = 0}, {fX = 2, fY = 0}}
-</div>
-
-<div id="cubicTest3">
-{{x = 0, y = 1}, {x = 1, y = 6}, {x = 1, y = 0}, {x = 2, y = 0}}
-{{x = 0, y = 1}, {x = 0, y = 2}, {x = 1, y = 0}, {x = 6, y = 1}}
- {{0,1}, {0.296,2.466}, {0.496,2.816}},
- {{0.496,2.816}, {0.696,3.166}, {0.848,2.808}},
- {{0.848,2.808}, {1,2.45}, {1.152,1.792}},
- {{1.152,1.792}, {1.304,1.134}, {1.504,0.584}},
- {{1.504,0.584}, {1.704,0.034}, {2,0}},
-
- {{0,1}, {-0.040150997,1.4850292}, {0.586736465,1.17347293}},
- {{0.586736465,1.17347293}, {1.11546634,0.936942311}, {2.40073788,0.7574854}},
- {{2.40073788,0.7574854}, {3.68600943,0.578028489}, {6,1}},
-</div>
-
-<div id="lineTest1">
-{{x = 1.3834888994942065, y = 0.93137912059586503}, {x = 1.3835184247369658, y = 0.93128386633972826}}
-{{x = 1.3834889487833637, y = 0.93138119876148517}, {x = 1.3835243637966514, y = 0.93137251518247632}}
-</div>
-
-<div id="lineQuad1">
-{{x = 0.5, y = 0.875}, {x = 0.65728065326954233, y = 0.63483143515742313}, {x = 0.78907579690950191, y = 0.3959256577144401}}
-{{x = 0.78906720197447666, y = 0.39595053259806418}, {x = 0.78966023971986588, y = 0.39559384654294}}}
-</div>
-
-<div id="lineQuad2">
-{{x = 0.78907579690950191, y = 0.3959256577144401}, {x = 0.78953800250469452, y = 0.39509830801181633}}
-{{x = 0.29629629629629628, y = 0.74074074074074081}, {x = 0.49667506598603178, y = 0.57646999653254238}, {x = 0.78906720197447666, y = 0.39595053259806418}}
-</div>
-
-<div id="x1">
-{{0.5,0.875}, {0.657581172,0.634357518}, {0.789538003,0.395098308}},
-{{0.296296296,0.740740741}, {0.496887363,0.576287939}, {0.78966024,0.395593847}},
-</div>
-
-<div id="x2">
-{{0.5,0.875}, {0.657280653,0.634831435}, {0.789075797,0.395925658}},
-{{0.296296296,0.740740741}, {0.496675066,0.576469997}, {0.789067202,0.395950533}},
-</div>
-
-<div id="x3">
-{{0.789075797,0.395925658}, {0.789538003,0.395098308}},
-{{0.296296296,0.740740741}, {0.496675066,0.576469997}, {0.789067202,0.395950533}},
-</div>
-
-<div id="x4">
-{{0.789538003,0.395098308}, {0.818060471,0.344004048}, {0.84375,0.296875}},
-{{0.296296296,0.740740741}, {0.496887363,0.576287939}, {0.78966024,0.395593847}},
-</div>
-
-<div id="x5">
-{{0.789538003,0.395098308}, {0.818060471,0.344004048}, {0.84375,0.296875}},
-{{0.78966024,0.395593847}, {0.908006316,0.324112697}, {1.03703704,0.259259259}},
-</div>
-
-<div id="cubicX">
-{{x = 0, y = 1}, {x = 0, y = 2}, {x = 1, y = 0}, {x = 1, y = 0}}
-{{x = 0, y = 1}, {x = 0, y = 2}, {x = 1, y = 0}, {x = 6, y = 1}}
-</div>
-
-<div id="cubicOp2d">
-{{0,2}, {0,1}, {1,0}, {1,0}},
-{{0,1}, {0,1}, {2,0}, {1,0}},
- {{0,2}, {0.0185185185,1.49074074}, {0.259259259,1.03703704}},
- {{0.259259259,1.03703704}, {0.5,0.583333333}, {0.740740741,0.296296296}},
- {{0.740740741,0.296296296}, {0.981481481,0.00925925926}, {1,0}},
-
- {{0,1}, {0.01953125,0.9921875}, {0.296875,0.84375}},
- {{0.296875,0.84375}, {0.57421875,0.6953125}, {0.875,0.5}},
- {{0.875,0.5}, {1.17578125,0.3046875}, {1.265625,0.15625}},
- {{1.265625,0.15625}, {1.35546875,0.0078125}, {1,0}},
-</div>
-
-<div id="cubicOp2da">
-{{0.395593847,0.78966024}, {0.576287939,0.496887363}, {0.740740741,0.296296296}},
-{{0.395098308,0.789538003}, {0.634357518,0.657581172}, {0.875,0.5}},
-</div>
-
-<div id="cubicOp3d">
-{{0,1}, {2,3}, {1,0}, {1,0}},
-{{0,1}, {0,1}, {1,0}, {3,2}},
- {{0,1}, {0.592,1.584}, {0.872,1.664}},
- {{0.872,1.664}, {1.152,1.744}, {1.216,1.512}},
- {{1.216,1.512}, {1.28,1.28}, {1.224,0.928}},
- {{1.224,0.928}, {1.168,0.576}, {1.088,0.296}},
- {{1.088,0.296}, {1.008,0.016}, {1,0}},
-
- {{0,1}, {0,0.962962963}, {0.333333333,0.814814815}},
- {{0.333333333,0.814814815}, {0.666666667,0.666666667}, {1.33333333,0.851851852}},
- {{1.33333333,0.851851852}, {2,1.03703704}, {3,2}},
-</div>
-
-<div id="cubicOp3da">
-{{1.224,0.928}, {1.17328164,0.604609714}, {1.09894996,0.336624845}},
-{{1.09895195,0.33662897}, {1.22307655,0.2359436}, {1.265625,0.15625}},
-</div>
-
-<div id="cubicOp3db">
-{{x = 1.2071879545809394, y = 0.82163474041730045}, {x = 1.1534203513372994, y = 0.52790870069930229}, {x = 1.0880000000000001, y = 0.29599999999999982}}
-{{x = 1.205732763658403, y = 0.81345617746834109}, {x = 1.267928895828891, y = 0.83008534558465619}, {x = 1.3333333333333333, y = 0.85185185185185175}}
-</div>
-
-<div id="cubicOp3dc">
-part=(1.20718795,0.82163474 1.17452925,0.632190117 1.1284272,0.444233064 1.088,0.296)
-quad=(1.20718795,0.82163474 1.15342035,0.527908701 1.088,0.296)
-part=(1.20573276,0.813456177 1.24719685,0.824565605 1.28973037,0.837317532 1.33333333,0.851851852)
-quad=(1.20573276,0.813456177 1.2679289,0.830085346 1.33333333,0.851851852)
-</div>
-
-<div id="cubicOp3dd">
-{{1.20718795,0.82163474 1.17452925,0.632190117 1.1284272,0.444233064 1.088,0.296)
-{{1.20718795,0.82163474 1.15342035,0.527908701 1.088,0.296)
-{{1.20568441,0.813443223 1.20570053,0.813447541 1.20571665,0.813451859 1.20573276,0.813456177)
-{{1.20568441,0.813443223 1.20570859,0.8134497 1.20573276,0.813456177)
-{{0.33333333333333326, y = 0.81481481481481488}, {x = 0.63396444791444551, y = 0.68743368362444768}, {x = 1.205732763658403, y = 0.81345617746834109}}
-</div>
-
-<div id="cubicOp3de">
-{{1.2071879545809394,0.82163474041730045}, {1.2065040319428038,0.81766753259119995}, {1.2058123269101506,0.81370135061854221}},
-{{1.205684411948591,0.81344322326274499}, {1.2057085875611198,0.81344969999329253}, {1.205732763658403,0.81345617746834109}},
-</div>
-
-<div id="cubicOp7">
-{{0,1}, {3,4}, {1,0}, {3,0}},
-{{0,1}, {0,3}, {1,0}, {4,3}},
-
- {{0,1}, {0.837764189,1.83435757}, {1.22841861,2.02640973}},
- {{1.22841861,2.02640973}, {1.61907304,2.21846188}, {1.74657491,1.9930452}},
- {{1.74657491,1.9930452}, {1.87407679,1.76762853}, {1.92238332,1.34957962}},
- {{1.92238332,1.34957962}, {1.97220681,0.867804601}, {2.17393047,0.447689071}},
- {{2.17393047,0.447689071}, {2.37565413,0.0275735418}, {3,0}},
-
- {{0,1}, {-0.00234073071,1.60655471}, {0.142631845,1.70125304}},
- {{0.142631845,1.70125304}, {0.28760442,1.79595137}, {0.60797907,1.68776977}},
- {{0.60797907,1.68776977}, {1.0447864,1.50810914}, {1.87464474,1.63655092}},
- {{1.87464474,1.63655092}, {2.70450308,1.76499271}, {4,3}},
-</div>
-
-<div id="cubicOp7a">
-{{x = 1.7465749139282332, y = 1.9930452039527999}, {x = 1.8417960084006277, y = 1.8552583419678612}, {x = 1.8799591210677749, y = 1.6157879692142081}, {x = 1.9223833226085514, y = 1.3495796165215643}}
-{{x = 0.6079790696638232, y = 1.6877697663020552}, {x = 0.90321659591661663, y = 1.6123550739533821}, {x = 1.3173732025571312, y = 1.5065640064343382}, {x = 1.8746447406062119, y = 1.636550924974228}}
-
-{{x = 1.7465749139282332, y = 1.9930452039527999}, {x = 1.8740767879671056, y = 1.7676285282679607}, {x = 1.9223833226085514, y = 1.3495796165215643}}
-{{x = 0.6079790696638232, y = 1.6877697663020552}, {x = 1.0447863962878021, y = 1.5081091374717195}, {x = 1.8746447406062119, y = 1.636550924974228}}
-</div>
-
-<div id="cubicOp7b">
-{{x = 1.7465749139282332, y = 1.9930452039527999}, {x = 1.8417960084006277, y = 1.8552583419678612}, {x = 1.8799591210677749, y = 1.6157879692142081}, {x = 1.9223833226085514, y = 1.3495796165215643}}
-{{x = 1.8746447406062119, y = 1.636550924974228}, {x = 2.4319162786552919, y = 1.7665378435141166}, {x = 3.1323027481129411, y = 2.1323027481129406}, {x = 4, y = 3}}
-{{x = 1.7465749139282332, y = 1.9930452039527999}, {x = 1.8740767879671056, y = 1.7676285282679607}, {x = 1.9223833226085514, y = 1.3495796165215643}}
-{{x = 1.8746447406062119, y = 1.636550924974228}, {x = 2.7045030849246219, y = 1.7649927124767357}, {x = 4, y = 3}}
-</div>
-
-<div id="cubicOp8">
-{{0,1}, {0,5}, {1,0}, {4,0}},
-{{0,1}, {0,4}, {1,0}, {5,0}},
-
- {{0,1}, {-0.00421781142,2.47981485}, {0.214213168,2.53784857}},
- {{0.214213168,2.53784857}, {0.432644147,2.59588228}, {0.924337655,1.94072717}},
- {{0.924337655,1.94072717}, {1.39158994,1.32418496}, {2.14967426,0.687365435}},
- {{2.14967426,0.687365435}, {2.90775858,0.0505459108}, {4,0}},
-
- {{0,1}, {-0.00720132722,2.05525633}, {0.206394399,2.10503282}},
- {{0.206394399,2.10503282}, {0.419990125,2.15480931}, {0.940798831,1.67439357}},
- {{0.940798831,1.67439357}, {1.48941875,1.16280321}, {2.47884711,0.60465921}},
- {{2.47884711,0.60465921}, {3.46827548,0.0465152042}, {5,0}},
-</div>
-
-<div id="cubicOp8a">
-{{x = 0.92433765471479945, y = 1.9407271660071879}, {x = 1.2518504275349398, y = 1.5283649441281617}, {x = 1.7179390069715588, y = 1.0614995059145118}}
-{{x = 0.94079883097732186, y = 1.6743935703752681}, {x = 1.2598825072629554, y = 1.3977856697533602}, {x = 1.7179167190286528, y = 1.0665031295527474}}
-</div>
-
-<div id="cubicOp9d">
-{{0,1}, {1,2}, {1,0}, {6,1}},
-{{0,1}, {1,6}, {1,0}, {2,1}},
-</div>
-
-<div id="cubicOp11d">
- Cubic cubic1 = {{0,1}, {3,4}, {1,0}, {5,1}};
- Cubic cubic2 = {{0,1}, {1,5}, {1,0}, {4,3}};
-
- {{0,1}, {1.10659493,2.10239153}, {1.50615334,2.12918252}},
- {{1.50615334,2.12918252}, {1.90571174,2.15597351}, {2.1530827,1.71245386}},
- {{2.1530827,1.71245386}, {2.39265628,1.2948736}, {2.98481198,0.986316183}},
- {{2.98481198,0.986316183}, {3.57696768,0.677758769}, {5,1}},
-
- {{0,1}, {0.351042317,2.40055211}, {0.610765407,2.56687524}},
- {{0.610765407,2.56687524}, {0.870488497,2.73319838}, {1.21251591,2.40319262}},
- {{1.21251591,2.40319262}, {1.57068059,2.04916077}, {2.21702741,1.98363478}},
- {{2.21702741,1.98363478}, {2.86337424,1.91810879}, {4,3}},
-</div>
-
-<div id="cubicOp12d">
-{{0, 1}, {1, 6}, {1, 0}, {1, 0}},
-{{0, 1}, {0, 1}, {1, 0}, {6, 1}},
-
- {{0,1}, {0.298,2.466}, {0.488,2.816}},
- {{0.488,2.816}, {0.678,3.166}, {0.784,2.808}},
- {{0.784,2.808}, {0.89,2.45}, {0.936,1.792}},
- {{0.936,1.792}, {0.982,1.134}, {0.992,0.584}},
- {{0.992,0.584}, {1.002,0.034}, {1,0}},
-
- {{0,1}, {-0.0277777778,0.972222222}, {0.444444444,0.777777778}},
- {{0.444444444,0.777777778}, {0.916666667,0.583333333}, {2.22222222,0.555555556}},
- {{2.22222222,0.555555556}, {3.52777778,0.527777778}, {6,1}},
-</div>
-
-<div id="cubicOp13d">
-{{0,1}, {4,5}, {1,0}, {5,3}},
-{{0,1}, {3,5}, {1,0}, {5,4}},
-
- {{0,1}, {1.48018645,2.46752265}, {1.93281168,2.58856757}},
- {{1.93281168,2.58856757}, {2.38543691,2.7096125}, {2.51967352,2.34531784}},
- {{2.51967352,2.34531784}, {2.65263731,2.00639194}, {3.1212119,1.98608967}},
- {{3.1212119,1.98608967}, {3.5897865,1.96578739}, {5,3}},
-
- {{0,1}, {1.05556321,2.39540407}, {1.46049052,2.58073968}},
- {{1.46049052,2.58073968}, {1.86541784,2.76607529}, {2.09544533,2.51981963}},
- {{2.09544533,2.51981963}, {2.33331524,2.25252128}, {2.92003302,2.39442311}},
- {{2.92003302,2.39442311}, {3.5067508,2.53632493}, {5,4}},
-</div>
-
-<div id="cubicTest4">
-{{x = 0, y = 1}, {x = 4, y = 5}, {x = 1, y = 0}, {x = 5, y = 3}}
-{{x = 0, y = 1}, {x = 1, y = 6}, {x = 1, y = 0}, {x = 2, y = 0}}
-</div>
-
-<div id="cubicTest5">
-{{x = 0, y = 1}, {x = 1, y = 6}, {x = 1, y = 0}, {x = 1, y = 0}}
-{{x = 0, y = 1}, {x = 1, y = 6}, {x = 1, y = 0}, {x = 2, y = 1}}
-</div>
-
-<div id="cubicTest6">
-{{x = 0, y = 1}, {x = 4, y = 5}, {x = 1, y = 0}, {x = 5, y = 3}}
-{{x = 4, y = 4}, {x = 3, y = 4}, {x = 1, y = 2}, {x = 0, y = 0}}
-</div>
-
-<div id="cubicTest7">
-{{x = 0, y = 1}, {x = 1.9274705288631189e-19, y = 1.0000000000000002}, {x = 0.0017190297609673323, y = 0.99828097023903239}, {x = 0.0053709083094631276, y = 0.99505672974365911}}
-</div>
-
-<div id="cubicOp16d">
-{{0,2},{0,1},{3,0},{1,0}},
-{{0,3},{0,1},{2,0},{1,0}},
-
- {{0,2}, {0.0229970175,1.6585632}, {0.366509308,1.33437416}},
- {{0.366509308,1.33437416}, {0.710021598,1.01018513}, {1.09808495,0.737739381}},
- {{1.09808495,0.737739381}, {1.40607875,0.517813127}, {1.57937247,0.352342403}},
- {{1.57937247,0.352342403}, {1.75266619,0.186871679}, {1.64451042,0.0942001592}},
- {{1.64451042,0.0942001592}, {1.53635465,0.00152863961}, {1,0}},
-
- {{0,3}, {0.0263932023,2.17082039}, {0.352786405,1.57082039}},
- {{0.352786405,1.57082039}, {0.679179607,0.970820393}, {0.988854382,0.6}},
- {{0.988854382,0.6}, {1.23200941,0.3}, {1.27672209,0.15}},
- {{1.27672209,0.15}, {1.32143477,9.25185854e-17}, {1,0}},
-</div>
-
-<div id="quadOp16d">
- {{1.64451042,0.0942001592}, {1.53635465,0.00152863961}, {1,0}},
- {{1.27672209,0.15}, {1.32143477,9.25185854e-17}, {1,0}},
-</div>
-
-<div id="cubicOp20d">
-{{0,6},{1,2},{1,0},{1,0}},
-{{0,1},{0,1},{6,0},{2,1}},
-
- {{0,6}, {0.71875,3}, {0.875,1.5}},
- {{0.875,1.5}, {1.03125,1.11022302e-16}, {1,0}},
-
- {{0,1}, {0.0625,0.98828125}, {0.875,0.859375}},
- {{0.875,0.859375}, {1.6875,0.73046875}, {2.5,0.625}},
- {{2.5,0.625}, {3.3125,0.51953125}, {3.375,0.578125}},
- {{3.375,0.578125}, {3.4375,0.63671875}, {2,1}},
-</div>
-
-<div id="cubicOp21d">
-{{1,2},{5,6},{1,0},{1,0}},
-{{0,1},{0,1},{2,1},{6,5}},
-
- {{1,2}, {2.176,3.168}, {2.536,3.328}},
- {{2.536,3.328}, {2.896,3.488}, {2.728,3.024}},
- {{2.728,3.024}, {2.56,2.56}, {2.152,1.856}},
- {{2.152,1.856}, {1.744,1.152}, {1.384,0.592}},
- {{1.384,0.592}, {1.024,0.032}, {1,0}},
-
- {{0,1}, {7.40148683e-17,0.962962963}, {0.666666667,1.14814815}},
- {{0.666666667,1.14814815}, {1.33333333,1.33333333}, {2.66666667,2.18518519}},
- {{2.66666667,2.18518519}, {4,3.03703704}, {6,5}},
-</div>
-
-<div id="quadOp21d">
- {{2.728,3.024}, {2.56,2.56}, {2.152,1.856}},
- {{0.666666667,1.14814815}, {1.33333333,1.33333333}, {2.66666667,2.18518519}},
-</div>
-
-<div id="cubicSelf1">
- {{3.34,8.98}, {1.95,10.27}, {3.76,7.65}, {4.96,10.64}},
-
- {{3.34,8.98}, {2.83363281,9.4265625}, {2.83796875,9.363125}},
- {{2.83796875,9.363125}, {2.84230469,9.2996875}, {3.17875,9.1725}},
- {{3.17875,9.1725}, {3.51519531,9.0453125}, {4.00515625,9.300625}},
- {{4.00515625,9.300625}, {4.49511719,9.5559375}, {4.96,10.64}},
-</div>
-
-<div id="quadSelf1">
- {{3.34,8.98}, {2.83363281,9.4265625}, {2.83796875,9.363125}},
- {{2.83796875,9.363125}, {2.84230469,9.2996875}, {3.17875,9.1725}},
-</div>
-
-<div id="cubicOp27d">
-{{0,1}, {3,6}, {1,0}, {5,2}},
-{{0,1}, {2,5}, {1,0}, {6,3}},
-
- {{0,1}, {1.11687388,2.858568}, {1.5151589,3.0010603}},
- {{1.5151589,3.0010603}, {1.91344391,3.14355261}, {2.16505631,2.55782454}},
- {{2.16505631,2.55782454}, {2.40541285,2.02193091}, {2.99836023,1.68247638}},
- {{2.99836023,1.68247638}, {3.5913076,1.34302184}, {5,2}},
-
- {{0,1}, {0.691228423,2.3859516}, {1.0489054,2.56156367}},
- {{1.0489054,2.56156367}, {1.40658238,2.73717574}, {1.80814127,2.41537795}},
- {{1.80814127,2.41537795}, {2.23475077,2.05922313}, {3.16529668,1.98358763}},
- {{3.16529668,1.98358763}, {4.0958426,1.90795214}, {6,3}},
-</div>
-
-<div id="quadOp27d">
- {{1.80814127,2.41537795}, {2.23475077,2.05922313}, {3.16529668,1.98358763}},
- {{2.16505631,2.55782454}, {2.40541285,2.02193091}, {2.99836023,1.68247638}},
-</div>
-
-<div id="cubicOp30d">
-{{0,1}, {2,5}, {6,0}, {5,3}},
-{{0,6}, {3,5}, {1,0}, {5,2}},
-
- {{0,1}, {0.585028897,2.1161006}, {1.31572211,2.42528354}},
- {{1.31572211,2.42528354}, {2.04641532,2.73446648}, {2.77656625,2.5918049}},
- {{2.77656625,2.5918049}, {3.50671719,2.44914333}, {4.09011926,2.20971038}},
- {{4.09011926,2.20971038}, {4.74608133,1.9335932}, {5.02469918,2.00694987}},
- {{5.02469918,2.00694987}, {5.30331702,2.08030653}, {5,3}},
-
- {{0,6}, {0.946962644,5.64705935}, {1.35765232,4.89865813}},
- {{1.35765232,4.89865813}, {1.768342,4.1502569}, {1.97833659,3.34197296}},
- {{1.97833659,3.34197296}, {2.2269947,2.25886123}, {2.79472921,1.73568666}},
- {{2.79472921,1.73568666}, {3.36246373,1.21251209}, {5,2}},
-</div>
-
-<div id="quadOp30d">
- {{4.09011926,2.20971038}, {4.74608133,1.9335932}, {5.02469918,2.00694987}},
- {{2.79472921,1.73568666}, {3.36246373,1.21251209}, {5,2}},
-</div>
-
-<div id="cubicOp34d">
-{{x = 1.0097960937999808, y = 2.2108396209439607}, {x = 1, y = 2.1969085233712229}, {x = 1, y = 2.1347920612232207}, {x = 1, y = 2}}
-{{x = 1.0097960937999808, y = 2.2108396209439607}, {x = 1.0242251996917398, y = 2.2313593593386498}, {x = 1.0599075827658746, y = 2.1473377437648784}, {x = 1.1481481481481481, y = 2.0370370370370372}}
-{{x = 1.0097960958786989, y = 2.2108396260650962}, {x = 0.73607693096853644, y = 1.9329854848088734}, {x = 0.40437628284615079, y = 1.5391683771282005}, {x = 0, y = 1}}
-{{x = 1.0097960958786989, y = 2.2108396260650962}, {x = 1.8566294376993437, y = 3.0704657726520206}, {x = 2.1484860084122528, y = 2.8201383770234716}, {x = 2.320499529631658, y = 2.3301248824079162}}
-</div>
-
-<div id="cubicOp34da">
-{{x = 1.0097960937999808, y = 2.2108396209439607}, {x = 1, y = 2.1969085233712229}, {x = 1, y = 2.1347920612232207}, {x = 1, y = 2}}
-{{x = 1.0097960937999808, y = 2.2108396209439607}, {x = 1.0242251996917398, y = 2.2313593593386498}, {x = 1.0599075827658746, y = 2.1473377437648784}, {x = 1.1481481481481481, y = 2.0370370370370372}}
-</div>
-
-<div id="cubicOp34db">
-{{1,2}, {1,3}, {1,0}, {5,3}},
-{{0,1}, {3,5}, {2,1}, {3,1}},
-
- {{1,2}, {0.984375,2.3359375}, {1.0625,2.15625}},
- {{1.0625,2.15625}, {1.140625,1.9765625}, {1.5,1.75}},
- {{1.5,1.75}, {1.859375,1.5234375}, {2.6875,1.71875}},
- {{2.6875,1.71875}, {3.515625,1.9140625}, {5,3}},
-
- {{0,1}, {0.983539095,2.30041152}, {1.47325103,2.61316872}},
- {{1.47325103,2.61316872}, {1.96296296,2.92592593}, {2.1563786,2.64609053}},
- {{2.1563786,2.64609053}, {2.34979424,2.36625514}, {2.44444444,1.88888889}},
- {{2.44444444,1.88888889}, {2.52083333,1.54166667}, {2.63888889,1.27777778}},
- {{2.63888889,1.27777778}, {2.75694444,1.01388889}, {3,1}},
-</div>
-
-<div id="quadOp34d">
- {{1,2}, {0.984375,2.3359375}, {1.0625,2.15625}},
- {{0,1}, {0.983539095,2.30041152}, {1.47325103,2.61316872}},
-</div>
-
-<div id="cubicOp35d">
-{{0,1}, {1,5}, {2,1}, {4,0}},
-{{1,2}, {0,4}, {1,0}, {5,1}},
-
- {{0,1}, {0.324417544,2.27953848}, {0.664376547,2.58940267}},
- {{0.664376547,2.58940267}, {1.00433555,2.89926686}, {1.39091893,2.58136885}},
- {{1.39091893,2.58136885}, {1.7775023,2.26347084}, {2.24179297,1.65972271}},
- {{2.24179297,1.65972271}, {2.61097963,1.18900727}, {3.04664862,0.731366192}},
- {{3.04664862,0.731366192}, {3.48231762,0.273725118}, {4,0}},
-
- {{1,2}, {0.62109375,2.70703125}, {0.640625,2.546875}},
- {{0.640625,2.546875}, {0.66015625,2.38671875}, {1.125,1.875}},
- {{1.125,1.875}, {1.58984375,1.36328125}, {2.546875,1.015625}},
- {{2.546875,1.015625}, {3.50390625,0.66796875}, {5,1}},
-</div>
-
-<div id="cubicOp35da">
-
-{{x = 0.44618727783085621, y = 2.2840286415243063}, {x = 0.51170845243761109, y = 2.4044088819954914}, {x = 0.57783675570457882, y = 2.4985733182515446}, {x = 0.64483584772311509, y = 2.5694222112973661}}
-{{x = 0.64244110111854291, y = 2.5673840215265367}, {x = 0.63479413812245555, y = 2.5620057200094775}, {x = 0.64115438240274059, y = 2.533597555954064}, {x = 0.6620248993310307, y = 2.4876932484482714}}
-
-</div>
-
-<div id="line0">
- {{2, 1}, {2, 1}},
-</div>
-
-<div id="line1">
- {{2, 1}, {1, 1}},
-</div>
-
-<div id="line2">
- {{2, 1}, {2, 2}}
-</div>
-
-<div id="line3">
- {{1, 1}, {2, 2}},
-</div>
-
-<div id="line4">
- {{3, 0}, {2, 1}},
-</div>
-
-<div id="line5">
- {{3, 2}, {1, 1}},
-</div>
-
-<div id="tri0">
- {{2, 0}, {3, 1}},
- {{3, 1}, {2, 2}},
- {{2, 2}, {2, 0}},
-</div>
-<div id="tri1">
- {{3, 1}, {2, 2}},
- {{2, 2}, {1, 1}},
- {{1, 1}, {3, 1}},
-</div>
-<div id="tri2">
- {{3, 0}, {2, 1}},
- {{2, 1}, {3, 2}},
- {{3, 2}, {3, 0}},
-</div>
-<div id="testQuad0">
- {{1, 1}, {2, 1}, {0, 2}},
-</div>
-<div id="testQuad1">
- {{0, 0}, {1, 1}, {3, 1}},
-</div>
-<div id="testQuad2">
- {{2, 0}, {1, 1}, {2, 2}},
-</div>
-<div id="testQuad3">
- {{4, 0}, {0, 1}, {4, 2}},
-</div>
-<div id="testQuad4">
- {{0, 0}, {0, 1}, {1, 1}},
-</div>
-
-<div id="cubicOp65d">
-{{0,1}, {1,5}, {1,0}, {1,0}},
-{{0,1}, {0,1}, {1,0}, {5,1}},
-</div>
-
-</div>
-
-<script type="text/javascript">
-
-var testDivs = [
- cubicOp65d,
- testQuad0,
- testQuad1,
- testQuad2,
- testQuad3,
- testQuad4,
- tri0,
- tri1,
- tri2,
- line0,
- line1,
- line2,
- line3,
- line4,
- line5,
- cubicOp35da,
- cubicOp35d,
- quadOp34d,
- cubicOp34db,
- cubicOp34d,
- cubicOp34da,
- quadOp30d,
- cubicOp30d,
- quadOp27d,
- cubicOp27d,
- quadSelf1,
- cubicSelf1,
- quadOp21d,
- cubicOp21d,
- cubicOp20d,
- quadOp16d,
- cubicOp16d,
- cubicTest7,
- cubicTest6,
- cubicTest5,
- cubicTest4,
- cubicOp13d,
- cubicOp12d,
- cubicOp11d,
- cubicOp9d,
- cubicOp8a,
- cubicOp8,
- cubicOp7b,
- cubicOp7a,
- cubicOp7,
- cubicOp3de,
- cubicOp3dd,
- cubicOp3dc,
- cubicOp3db,
- cubicOp3da,
- cubicOp3d,
- cubicOp2da,
- cubicOp2d,
- cubicX,
- x1,
- x2,
- x3,
- x4,
- x5,
- lineQuad2,
- lineQuad1,
- lineTest1,
- cubicTest3,
- cubicTest2,
- cubicTest1,
- cubicOp1d,
- testCubic1b,
- testCubic1a,
- testCubic1,
- cubic27,
- cubic26,
- quad23,
- cubic25,
- quad22,
- cubic24,
- quad21,
- cubic23,
- quad20,
- cubic22,
- quad19,
- quad18,
- quad17,
- quad16,
- cubic21,
- cubic20,
- cubic19,
- quad15,
- quad14,
- cubic18,
- cubic17,
- cubic16,
- cubic15,
- quad13,
- quad12,
- cubic14,
- cubic13,
- cubic12,
- cubic11,
- cubic10,
- cubic9,
- quad11,
- quad10,
- quad9,
- quad8,
- quad7,
- cubic8,
- quad6,
- quad5,
- quad4,
- quad3,
- cubic7,
- quad2,
- cubic6,
- quad1,
- cubic5,
- cubic4,
- cubic1x0,
- cubic1x0x,
- cubic1x1,
- cubic1x1x,
- cubic1x2,
- cubic1x2x,
- cubic1x3,
- cubic1x3x,
- cubic1x4,
- cubic1x4x,
- cubic1x5,
- cubic1x5x,
- cubic1x6,
- cubic1x6x,
- cubic1x7,
- cubic1x7x,
- cubic1x8,
- cubic1x8x,
- cubic1x9,
- cubic1x9x,
- cubic2x0,
- cubic2x0x,
- cubic2x1,
- cubic2x1x,
- cubic2x2,
- cubic2x2x,
- cubic2x3,
- cubic2x3x,
- cubic2x4,
- cubic2x4x,
- cubic2x5,
- cubic2x5x,
- cubic2x6,
- cubic2x6x,
- cubic2x7,
- cubic2x7x,
- cubic2x8,
- cubic2x8x,
- cubic2x9,
- cubic2x9x,
- cubic3x0,
- cubic3x0x,
- cubic3x1,
- cubic3x1x,
- cubic3x2,
- cubic3x2x,
- cubic3x3,
- cubic3x3x,
- cubic3x4,
- cubic3x4x,
- cubic3x5,
- cubic3x5x,
- cubic3x6,
- cubic3x6x,
- cubic3x7,
- cubic3x7x,
- cubic3x8,
- cubic3x8x,
- cubic3x9,
- cubic3x9x,
- cubic4x0,
- cubic4x0x,
- cubic4x1,
- cubic4x1x,
- cubic4x2,
- cubic4x2x,
- cubic4x3,
- cubic4x3x,
- cubic4x4,
- cubic4x4x,
- cubic4x5,
- cubic4x5x,
- cubic4x6,
- cubic4x6x,
- cubic4x7,
- cubic4x7x,
- cubic4x8,
- cubic4x8x,
- cubic4x9,
- cubic4x9x,
- cubic5x0,
- cubic5x0x,
- cubic5x1,
- cubic5x1x,
- cubic5x2,
- cubic5x2x,
- cubic5x3,
- cubic5x3x,
- cubic5x4,
- cubic5x4x,
- cubic5x5,
- cubic5x5x,
- cubic5x6,
- cubic5x6x,
- cubic5x7,
- cubic5x7x,
- cubic5x8,
- cubic5x8x,
- cubic5x9,
- cubic5x9x,
- cubic6x0,
- cubic6x0x,
- cubic6x1,
- cubic6x1x,
- cubic6x2,
- cubic6x2x,
- cubic6x3,
- cubic6x3x,
- cubic6x4,
- cubic6x4x,
- cubic6x5,
- cubic6x5x,
- cubic6x6,
- cubic6x6x,
- cubic6x7,
- cubic6x7x,
- cubic6x8,
- cubic6x8x,
- cubic6x9,
- cubic6x9x,
- cubic7x0,
- cubic7x0x,
- cubic7x1,
- cubic7x1x,
- cubic7x2,
- cubic7x2x,
- cubic7x3,
- cubic7x3x,
- cubic7x4,
- cubic7x4x,
- cubic7x5,
- cubic7x5x,
- cubic7x6,
- cubic7x6x,
- cubic7x7,
- cubic7x7x,
- cubic7x8,
- cubic7x8x,
- cubic7x9,
- cubic7x9x,
- cubic8x0,
- cubic8x0x,
- cubic8x1,
- cubic8x1x,
- cubic8x2,
- cubic8x2x,
- cubic8x3,
- cubic8x3x,
- cubic8x4,
- cubic8x4x,
- cubic8x5,
- cubic8x5x,
- cubic8x6,
- cubic8x6x,
- cubic8x7,
- cubic8x7x,
- cubic8x8,
- cubic8x8x,
- cubic8x9,
- cubic8x9x,
- cubic3,
- cubic2,
- cubic1,
-];
-
-var scale, columns, rows, xStart, yStart;
-
-var ticks = 10;
-var at_x = 13 + 0.5;
-var at_y = 23 + 0.5;
-var decimal_places = 3;
-var tests = [];
-var testTitles = [];
-var testIndex = 0;
-var ctx;
-var minScale = 1;
-var subscale = 1;
-var curveT = -1;
-var drawCubics = true;
-var drawQuads = true;
-var drawControlLines = true;
-var drawTangents = false;
-var drawGrid = true;
-var xmin, xmax, ymin, ymax;
-
-function parse(test, title) {
- var curveStrs = test.split("{{");
- if (curveStrs.length == 1)
- curveStrs = test.split("=(");
- var pattern = /[a-z$=]?-?\d+\.*\d*e?-?\d*/g;
- var curves = [];
- for (var c in curveStrs) {
- var curveStr = curveStrs[c];
- var points = curveStr.match(pattern);
- var pts = [];
- for (var wd in points) {
- var num = parseFloat(points[wd]);
- if (isNaN(num)) continue;
- pts.push(num);
- }
- if (pts.length > 2)
- curves.push(pts);
- }
- if (curves.length >= 1) {
- tests.push(curves);
- testTitles.push(title);
- }
-}
-
-function init(test) {
- var canvas = document.getElementById('canvas');
- if (!canvas.getContext) return;
- canvas.width = window.innerWidth - at_x;
- canvas.height = window.innerHeight - at_y;
- ctx = canvas.getContext('2d');
- xmin = Infinity;
- xmax = -Infinity;
- ymin = Infinity;
- ymax = -Infinity;
- for (var curves in test) {
- var curve = test[curves];
- var last = curve.length;
- for (var idx = 0; idx < last; idx += 2) {
- xmin = Math.min(xmin, curve[idx]);
- xmax = Math.max(xmax, curve[idx]);
- ymin = Math.min(ymin, curve[idx + 1]);
- ymax = Math.max(ymax, curve[idx + 1]);
- }
- }
- var testW = xmax - xmin;
- var testH = ymax - ymin;
- subscale = 1;
- while (testW * subscale < 0.1 && testH * subscale < 0.1) {
- subscale *= 10;
- }
- while (testW * subscale > 10 && testH * subscale > 10) {
- subscale /= 10;
- }
- calcFromScale();
-}
-
-function calcFromScale() {
- xStart = Math.floor(xmin * subscale) / subscale;
- yStart = Math.floor(ymin * subscale) / subscale;
- var xEnd = Math.ceil(xmin * subscale) / subscale;
- var yEnd = Math.ceil(ymin * subscale) / subscale;
- var cCelsW = Math.floor(ctx.canvas.width / 10);
- var cCelsH = Math.floor(ctx.canvas.height / 10);
- var testW = xEnd - xStart;
- var testH = yEnd - yStart;
- var scaleWH = 1;
- while (cCelsW > testW * scaleWH * 10 && cCelsH > testH * scaleWH * 10) {
- scaleWH *= 10;
- }
- while (cCelsW * 10 < testW * scaleWH && cCelsH * 10 < testH * scaleWH) {
- scaleWH /= 10;
- }
-
- columns = Math.ceil(xmax * subscale) - Math.floor(xmin * subscale) + 1;
- rows = Math.ceil(ymax * subscale) - Math.floor(ymin * subscale) + 1;
-
- var hscale = ctx.canvas.width / columns / ticks;
- var vscale = ctx.canvas.height / rows / ticks;
- minScale = Math.floor(Math.min(hscale, vscale));
- scale = minScale * subscale;
-}
-
-function drawPoint(px, py, xoffset, yoffset, unit) {
- var label = px.toFixed(decimal_places) + ", " + py.toFixed(decimal_places);
- var _px = px * unit + xoffset;
- var _py = py * unit + yoffset;
- ctx.beginPath();
- ctx.arc(_px, _py, 3, 0, Math.PI*2, true);
- ctx.closePath();
- ctx.fill();
- ctx.fillText(label, _px + 5, _py);
-}
-
-function draw(test, title, scale) {
- ctx.fillStyle = "rgba(0,0,0, 0.1)";
- ctx.font = "normal 50px Arial";
- ctx.fillText(title, 50, 50);
- ctx.font = "normal 10px Arial";
-
- var unit = scale * ticks;
- ctx.lineWidth = 1;
- if (drawGrid) {
- var i;
- for (i = 0; i <= rows * ticks; ++i) {
- ctx.strokeStyle = (i % ticks) != 0 ? "rgb(200,200,200)" : "black";
- ctx.beginPath();
- ctx.moveTo(at_x + 0, at_y + i * minScale);
- ctx.lineTo(at_x + ticks * columns * minScale, at_y + i * minScale);
- ctx.stroke();
- }
- for (i = 0; i <= columns * ticks; ++i) {
- ctx.strokeStyle = (i % ticks) != 0 ? "rgb(200,200,200)" : "black";
- ctx.beginPath();
- ctx.moveTo(at_x + i * minScale, at_y + 0);
- ctx.lineTo(at_x + i * minScale, at_y + ticks * rows * minScale);
- ctx.stroke();
- }
- }
- var xoffset = xStart * -unit + at_x;
- var yoffset = yStart * -unit + at_y;
-
- ctx.fillStyle = "rgb(40,80,60)"
- if (drawGrid) {
- for (i = 0; i <= columns; i += 1)
- {
- num = xStart + i / subscale;
- ctx.fillText(num.toFixed(decimal_places), xoffset + num * unit - 5, 10);
- }
- for (i = 0; i <= rows; i += 1)
- {
- num = yStart + i / subscale;
- ctx.fillText(num.toFixed(decimal_places), 0, yoffset + num * unit + 0);
- }
- }
- var curves, pts;
- for (curves in test) {
- var curve = test[curves];
- if (curve.length == 6 && !drawQuads) {
- continue;
- }
- if (curve.length == 8 && !drawCubics) {
- continue;
- }
- ctx.beginPath();
- ctx.moveTo(xoffset + curve[0] * unit, yoffset + curve[1] * unit);
- switch (curve.length) {
- case 4:
- ctx.lineTo(
- xoffset + curve[2] * unit, yoffset + curve[3] * unit);
- break;
- case 6:
- ctx.quadraticCurveTo(
- xoffset + curve[2] * unit, yoffset + curve[3] * unit,
- xoffset + curve[4] * unit, yoffset + curve[5] * unit);
- break;
- case 8:
- ctx.bezierCurveTo(
- xoffset + curve[2] * unit, yoffset + curve[3] * unit,
- xoffset + curve[4] * unit, yoffset + curve[5] * unit,
- xoffset + curve[6] * unit, yoffset + curve[7] * unit);
- break;
- }
- ctx.strokeStyle = drawQuads && drawCubics && curve.length == 6 ? "red" : "black";
- if (curve.length == 4) {
- ctx.strokeStyle = "blue";
- }
- ctx.stroke();
- if (drawControlLines && (curve.length == 6 || curve.length == 8)) {
- ctx.strokeStyle = "rgba(0,0,0, 0.3)";
- ctx.beginPath();
- ctx.moveTo(xoffset + curve[0] * unit, yoffset + curve[1] * unit);
- ctx.lineTo(xoffset + curve[2] * unit, yoffset + curve[3] * unit);
- ctx.lineTo(xoffset + curve[4] * unit, yoffset + curve[5] * unit);
- if (curve.length == 8)
- ctx.lineTo(xoffset + curve[6] * unit, yoffset + curve[7] * unit);
- // ctx.lineTo(xoffset + curve[0] * unit, yoffset + curve[1] * unit);
- ctx.stroke();
- }
- if (curveT >= 0 && curveT <= 1) {
- var x, y;
- var t = curveT;
- switch (curve.length) {
- case 4:
- var a = 1 - t;
- var b = t;
- x = a * curve[0] + b * curve[2];
- y = a * curve[1] + b * curve[3];
- break;
- case 6:
- var one_t = 1 - t;
- var a = one_t * one_t;
- var b = 2 * one_t * t;
- var c = t * t;
- x = a * curve[0] + b * curve[2] + c * curve[4];
- y = a * curve[1] + b * curve[3] + c * curve[5];
- break;
- case 8:
- var one_t = 1 - t;
- var one_t2 = one_t * one_t;
- var a = one_t2 * one_t;
- var b = 3 * one_t2 * t;
- var t2 = t * t;
- var c = 3 * one_t * t2;
- var d = t2 * t;
- x = a * curve[0] + b * curve[2] + c * curve[4] + d * curve[6];
- y = a * curve[1] + b * curve[3] + c * curve[5] + d * curve[7];
- break;
- }
- drawPoint(x, y, xoffset, yoffset, unit);
- var num = curveT.toFixed(decimal_places);
- ctx.beginPath();
- ctx.rect(200,10,200,10);
- ctx.fillStyle="white";
- ctx.fill();
- ctx.fillStyle="black";
- ctx.fillText(num, 230, 18);
- if (drawTangents && curve.length == 8) {
- var one_t = 1 - t;
- var a = curve[0];
- var b = curve[2];
- var c = curve[4];
- var d = curve[6];
- var dx = (b - a) * one_t * one_t + 2 * (c - b) * t * one_t + (d - c) * t * t;
- a = curve[1];
- b = curve[3];
- c = curve[5];
- d = curve[7];
- var dy = (b - a) * one_t * one_t + 2 * (c - b) * t * one_t + (d - c) * t * t;
- ctx.beginPath();
- ctx.moveTo(xoffset + (x - dx) * unit, yoffset + (y - dy) * unit);
- ctx.lineTo(xoffset + (x + dx) * unit, yoffset + (y + dy) * unit);
- ctx.stroke();
- }
- }
- }
-}
-
-function drawTop() {
- init(tests[testIndex]);
- redraw();
-}
-
-function redraw() {
- ctx.beginPath();
- ctx.rect(0, 0, ctx.canvas.width, ctx.canvas.height);
- ctx.fillStyle="white";
- ctx.fill();
- draw(tests[testIndex], testTitles[testIndex], scale);
-}
-
-function doKeyPress(evt) {
- var char = String.fromCharCode(evt.charCode);
- switch (char) {
- case 'c':
- drawCubics ^= true;
- redraw();
- break;
- case 'd':
- decimal_places++;
- redraw();
- break;
- case 'D':
- decimal_places--;
- if (decimal_places < 1) {
- decimal_places = 1;
- }
- redraw();
- break;
- case 'g':
- drawGrid ^= true;
- redraw();
- break;
- case 'l':
- drawControlLines ^= true;
- redraw();
- break;
- case 'N':
- testIndex += 9;
- case 'n':
- if (++testIndex >= tests.length)
- testIndex = 0;
- mouseX = Infinity;
- drawTop();
- break;
- case 'P':
- testIndex -= 9;
- case 'p':
- if (--testIndex < 0)
- testIndex = tests.length - 1;
- mouseX = Infinity;
- drawTop();
- break;
- case 'q':
- drawQuads ^= true;
- redraw();
- break;
- case 't':
- drawTangents ^= true;
- redraw();
- break;
- case 'x':
- drawCubics ^= true;
- drawQuads ^= true;
- redraw();
- break;
- case '-':
- case '_':
- subscale /= 2;
- calcFromScale();
- redraw();
- break;
- case '+':
- case '=':
- subscale *= 2;
- calcFromScale();
- redraw();
- break;
- }
-}
-
-function handleMouseClick() {
- var e = window.event;
- var tgt = e.target || e.srcElement;
- var min = tgt.offsetTop + Math.ceil(at_y);
- var max = min + ticks * rows * minScale;
- curveT = (e.clientY - min) / (max - min);
- redraw();
-}
-
-function calcXY() {
- var e = window.event;
- var tgt = e.target || e.srcElement;
- var left = tgt.offsetLeft;
- var top = tgt.offsetTop;
- var unit = scale * ticks;
- mouseX = (e.clientX - left - Math.ceil(at_x) + 1) / unit + xStart;
- mouseY = (e.clientY - top - Math.ceil(at_y)) / unit + yStart;
-}
-
-function handleMouseOver() {
- calcXY();
- var num = mouseX.toFixed(decimal_places) + ", " + mouseY.toFixed(decimal_places);
- ctx.beginPath();
- ctx.rect(30,10,200,10);
- ctx.fillStyle="white";
- ctx.fill();
- ctx.fillStyle="black";
- ctx.fillText(num, 30, 18);
-}
-
-function start() {
- for (i = 0; i < testDivs.length; ++i) {
- var title = testDivs[i].id.toString();
- var str = testDivs[i].firstChild.data;
- parse(str, title);
- }
- drawTop();
- window.addEventListener('keypress', doKeyPress, true);
- window.onresize = function() {
- drawTop();
- }
-}
-
-</script>
-</head>
-
-<body onLoad="start();">
-<canvas id="canvas" width="750" height="500"
- onmousemove="handleMouseOver()"
- onclick="handleMouseClick()"
- ></canvas >
-</body>
-</html>
diff --git a/experimental/Intersection/thingsToDo.txt b/experimental/Intersection/thingsToDo.txt
deleted file mode 100644
index f74d3ee126..0000000000
--- a/experimental/Intersection/thingsToDo.txt
+++ /dev/null
@@ -1,525 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-add unit test for quadratic horizontal intersection
-add unit test for cubic horizontal intersection with left/right
-add unit test for ActiveEdge::calcLeft (can currently loop forever)
-does ActiveEdge::isCoincidentWith need to support quad, cubic?
-figure out why variation in ActiveEdge::tooCloseToCall isn't better
-why does 'lastPtr - 2' in addIntersectingTs break testSimplifyTriangle22?
-add code to promote quad to cubic, or add quad/cubic intersection
-figure out why testSimplifySkinnyTriangle13 fails
-
-for quadratics and cubics, once various T values are added, see if consecutive
-Ts have ys that go up instead of down. If so, the edge needs to be broken.
-
-when splitting curves at inflection pts, should I retain the original curve
-data and note that the first/last T are no longer 0/1 ?
-I need to figure this out before I can proceed
-
-would it make sense to leave the InEdge alone, and add multiple copies of
-ActiveEdge, pointing to the same InEdge, where the copy has only the subset
-of Ts that need to be walked in reverse order?
-
-
--- A Digression Which Shows Why Resolving Coincidence Does Not Make Sense --
-
-Consider the following fine ASCII art:
-
- +------>-------+ +------>-------+
- | | | |
- ^ V ^ V
- | | | |
- +------<-------+ +------<-------+
- +------>-------+ +------<-------+
- | | | |
- ^ V V ^
- | | | |
- +------<-------+ +------>-------+
-
-(assume the bottom and top of the stacked rectangles are coincident)
-
-Simplifying said rectangles, regardless of rectangle direction, and regardless
-of winding or even/odd, eliminates the coincident edge, i.e., the result is
-always:
-
- +------>-------+
- | |
- | |
- | |
- ^ V
- | |
- | |
- | |
- +------<-------+
-
-But when the rectangles are enclosed in a larger rectangle:
-
-+-------->---------+ +-------->---------+
-| +------>-------+ | | +------>-------+ |
-| | | | | | | |
-| ^ V | | ^ V |
-| | | | | | | |
-| +------<-------+ | | +------<-------+ |
-| +------>-------+ | | +------<-------+ |
-| | | | | | | |
-| ^ V | | V ^ |
-| | | | | | | |
-| +------<-------+ | | +------>-------+ |
-+--------<---------+ +--------<---------+
-
-Simplifying them gives different results depending on the winding setting:
-
-winding:
-+-------->---------+ +-------->---------+
-| | | |
-| | | |
-| | | |
-| | | |
-| | | +------<-------+ |
-| | | | | |
-| | | V ^ |
-| | | | | |
-| | | +------>-------+ |
-+--------<---------+ +--------<---------+
-
-even odd:
-+-------->---------+ +-------->---------+
-| +------<-------+ | | +------<-------+ |
-| | | | | | | |
-| | | | | | | |
-| | | | | | | |
-| | | | | | | |
-| V ^ | | V ^ |
-| | | | | | | |
-| | | | | | | |
-| | | | | | | |
-| +------>-------+ | | +------>-------+ |
-+--------<---------+ +--------<---------+
-
-So, given the inner rectangles alone (e.g., given coincident pairs in some local
-context), we can't know whether to keep the coincident edges or not.
-
-
--- Thoughts About Sortless Ops --
-
-I can't come up with anything truly sortless. It seems that the crossings need
-to be sorted to know which segment is next on the outside, although sometimes
-we can use that it is not coincident just to follow the direction.
-
-If it is coincident or if there's more than two crossing segments, sorting
-seems inevitable.
-
-Likewise, to resolve whether one contour is inside another, it seems that
-sorting is required. Given a pair of segments on different contours, to know
-if one is inside of the other, I need to know for each which side of the edge
-is the inside/filled side. When the outer contour is walked, it seems like I
-could record the inside info. I guess when the inner contour is found, its
-inside sense is reversed (inside is above the top). But how do I know if the
-next contour is inside another? Maybe shoot out a line and brute-force
-intersect it with all the segments in all the other contours? If every contour
-has an extra segment when the intersections are computed, this may not be as
-crazy as it seems.
-
-Suppose each contour has one extra segment shooting straight up from the top
-(or straight up from any point on the segment). This ray is not intersected
-with the home contour, but is intersected with all other contours as part of
-the normal intersection engine. If it is possible to get from the T values to
-the other segments to the other contours, it would be straightforward to
-count the contour crossings and determine if the home contour is in another
-contour or not (if the count is even, not, if odd, is inside). By itself that
-doesn't tell us about winding, but it's a start.
-
-
-Since intersecting these rays is unrelated to computing other intersections,
-it can be lazily done once the contour is found.
-
-So
-repeat the following
-find the top segment of all contours
-trace the outside, marking touching first and last segments as inside
-continue tracing the touched segments with reversed outside/inside sense
-once the edges are exhausted, remaining must be disjoint contours
-send a ray from a disjoint point through all other contours
-count the crossings, determine if disjoint is inside or outside, then continue
-
-===
-
-On Quadratic (and Cubic) Intersections
-
-Currently, if only the end points touch, QuadracticIntersections does a lot of
-work to figure that out. Can I test for that up front, then short circuit the
-recursive search for the end points?
-
-Or, is there something defective in the current approach that makes the end
-point recursion go so deep? I'm seeing 56 stack frames (about 28 divides, but
-thankfully, no splits) to find one matching endpoint.
-
-
-Bezier curve focus may allow more quickly determining that end points with
-identical tangents are practically coicident for some range of T, but I don't
-understand the math yet to know.
-
-Another approach is to determine how flat the curve is to make good guesses
-about how far to move away in T before doing the intersection for the remainder
-and/or to determine whether one curve is to the inside or outside of another.
-According to Mike/Rob, the flatness for quadratics increases by 4 for each
-subdivision, and a crude guess of the curvature can be had by comparing P1 to
-(P0+P2)/2. By looking at the ULPS of the numbers, I can guess what value of
-T may be far enough that the curves diverge but don't cross.
-
-====
-
-Code I May Not Need Any More
-
- static bool CoincidentCandidate(const Angle* current) {
- const Segment* segment = current->segment();
- int min = SkMin32(current->start(), current->end());
- do {
- const Span& span = segment->fTs[min];
- if (span.fCoincident == Span::kStart_Coincidence) {
- return true;
- }
- } while (--min >= 0);
- return false;
- }
-
- static bool CoincidentHalf(const Angle* current, const Angle* next) {
- const Segment* other = next->segment();
- const Segment* segment = current->segment();
- int min = SkMin32(current->start(), current->end());
- const Span& minSpan = segment->fTs[min];
- if (minSpan.fOther == other) {
- return minSpan.fCoincident == Span::kStart_Coincidence;
- }
- int index = min;
- int spanCount = segment->fTs.count();
- while (++index < spanCount) {
- const Span& span = segment->fTs[index];
- if (minSpan.fT != span.fT) {
- break;
- }
- if (span.fOther != other) {
- continue;
- }
- return span.fCoincident == Span::kStart_Coincidence;
- }
- index = min;
- while (--index >= 0) {
- const Span& span = segment->fTs[index];
- if (span.fOther != other) {
- continue;
- }
- return span.fCoincident == Span::kStart_Coincidence;
- }
- return false;
- }
-
- static bool Coincident(const Angle* current, const Angle* next) {
- return CoincidentHalf(current, next) &&
- CoincidentHalf(next, current);
- }
-
- // If three lines cancel in a - b - c order, a - b may or may not
- // eliminate the edge that describes the b - c cancellation. Check done to
- // determine this.
- static bool CoincidentCancels(const Angle* current, const Angle* next) {
- int curMin = SkMin32(current->start(), current->end());
- if (current->segment()->fTs[curMin].fDone) {
- return false;
- }
- int nextMin = SkMin32(next->start(), next->end());
- if (next->segment()->fTs[nextMin].fDone) {
- return false;
- }
- return SkSign32(current->start() - current->end())
- != SkSign32(next->start() - next->end());
- }
-
- // FIXME: at this point, just have two functions for the different steps
- int coincidentEnd(int from, int step) const {
- double fromT = fTs[from].fT;
- int count = fTs.count();
- int to = from;
- while (step > 0 ? ++to < count : --to >= 0) {
- const Span& span = fTs[to];
- if ((step > 0 ? span.fT - fromT : fromT - span.fT) >= FLT_EPSILON ) {
- // FIXME: we assume that if the T changes, we don't care about
- // coincident -- but in nextSpan, we require that both the T
- // and actual loc change to represent a span. This asymettry may
- // be OK or may be trouble -- if trouble, probably will need to
- // detect coincidence earlier or sort differently
- break;
- }
-#if 01
- if (span.fCoincident == (step < 0 ? Span::kStart_Coincidence :
- Span::kEnd_Coincidence)) {
- from = to;
- }
-#else
- from = to;
-#endif
- }
- return from;
- }
-
- // once past current span, if step>0, look for coicident==1
- // if step<0, look for coincident==-1
- int nextSpanEnd(int from, int step) const {
- int result = nextSpan(from, step);
- if (result < 0) {
- return result;
- }
- return coincidentEnd(result, step);
- }
-
-
- void adjustFirst(const SkTDArray<Angle*>& sorted, int& first, int& winding,
- bool outside) {
- int firstIndex = first;
- int angleCount = sorted.count();
- if (true || outside) {
- const Angle* angle = sorted[firstIndex];
- int prior = firstIndex;
- do {
- if (--prior < 0) {
- prior = angleCount - 1;
- }
- if (prior == firstIndex) { // all are coincident with each other
- return;
- }
- if (!Coincident(sorted[prior], sorted[first])) {
- return;
- }
- winding += angle->sign();
- first = prior;
- angle = sorted[prior];
- winding -= angle->sign();
- } while (true);
- }
- do {
- int next = first + 1;
- if (next == angleCount) {
- next = 0;
- }
- if (next == firstIndex) { // all are coincident with each other
- return;
- }
- if (!Coincident(sorted[first], sorted[next])) {
- return;
- }
- first = next;
- } while (true);
- }
-
- bool nextIsCoincident = CoincidentCandidate(nextAngle);
- bool finalOrNoCoincident = true;
- bool pairCoincides = false;
- bool pairCancels = false;
- if (nextIsCoincident) {
- int followIndex = nextIndex + 1;
- if (followIndex == angleCount) {
- followIndex = 0;
- }
- const Angle* followAngle = sorted[followIndex];
- finalOrNoCoincident = !Coincident(nextAngle, followAngle);
- if ((pairCoincides = Coincident(angle, nextAngle))) {
- pairCancels = CoincidentCancels(angle, nextAngle);
- }
- }
- if (pairCancels && !foundAngle && !nextSegment->done()) {
- Segment* aSeg = angle->segment();
- // alreadyMarked |= aSeg == sorted[firstIndex]->segment();
- aSeg->markAndChaseCoincident(angle->start(), angle->end(),
- nextSegment);
- if (firstEdge) {
- return NULL;
- }
- }
- if (pairCoincides) {
- if (pairCancels) {
- goto doNext;
- }
- int minT = SkMin32(nextAngle->start(), nextAngle->end());
- bool markNext = abs(maxWinding) < abs(winding);
- if (markNext) {
- nextSegment->markDone(minT, winding);
- }
- int oldMinT = SkMin32(angle->start(), angle->end());
- if (true || !foundAngle) {
- // SkASSERT(0); // do we ever get here?
- Segment* aSeg = angle->segment();
- // alreadyMarked |= aSeg == sorted[firstIndex]->segment();
- aSeg->markDone(oldMinT, maxWinding);
- }
- }
-
- // OPTIMIZATION: uses tail recursion. Unwise?
- void innerCoincidentChase(int step, Segment* other) {
- // find other at index
- // SkASSERT(!done());
- const Span* start = NULL;
- const Span* end = NULL;
- int index, startIndex, endIndex;
- int count = fTs.count();
- for (index = 0; index < count; ++index) {
- const Span& span = fTs[index];
- if (!span.fCoincident || span.fOther != other) {
- continue;
- }
- if (!start) {
- startIndex = index;
- start = &span;
- } else {
- SkASSERT(!end);
- endIndex = index;
- end = &span;
- }
- }
- if (!end) {
- return;
- }
- bool thisDone = fTs[SkMin32(startIndex, endIndex)].fDone;
- bool otherDone = other->fTs[SkMin32(start->fOtherIndex,
- end->fOtherIndex)].fDone;
- if (thisDone && otherDone) {
- return;
- }
- Segment* next;
- Segment* nextOther;
- if (step < 0) {
- next = start->fT == 0 ? NULL : this;
- nextOther = other->fTs[start->fOtherIndex].fT > 1 - FLT_EPSILON ? NULL : other;
- } else {
- next = end->fT == 1 ? NULL : this;
- nextOther = other->fTs[end->fOtherIndex].fT < FLT_EPSILON ? NULL : other;
- }
- SkASSERT(!next || !nextOther);
- for (index = 0; index < count; ++index) {
- const Span& span = fTs[index];
- if (span.fCoincident || span.fOther == other) {
- continue;
- }
- bool checkNext = !next && (step < 0 ? span.fT < FLT_EPSILON
- && span.fOtherT > 1 - FLT_EPSILON : span.fT > 1 - FLT_EPSILON
- && span.fOtherT < FLT_EPSILON);
- bool checkOther = !nextOther && (step < 0 ? fabs(span.fT - start->fT) < FLT_EPSILON
- && span.fOtherT < FLT_EPSILON : fabs(span.fT - end->fT) < FLT_EPSILON
- && span.fOtherT > 1 - FLT_EPSILON);
- if (!checkNext && !checkOther) {
- continue;
- }
- Segment* oSegment = span.fOther;
- if (oSegment->done()) {
- continue;
- }
- int oCount = oSegment->fTs.count();
- for (int oIndex = 0; oIndex < oCount; ++oIndex) {
- const Span& oSpan = oSegment->fTs[oIndex];
- if (oSpan.fT >= FLT_EPSILON && oSpan.fT <= 1 - FLT_EPSILON) {
- continue;
- }
- if (!oSpan.fCoincident) {
- continue;
- }
- if (checkNext && (oSpan.fT < FLT_EPSILON ^ step < 0)) {
- next = oSegment;
- checkNext = false;
- }
- if (checkOther && (oSpan.fT > 1 - FLT_EPSILON ^ step < 0)) {
- nextOther = oSegment;
- checkOther = false;
- }
- }
- }
- // this needs to walk both spans in lock step, skipping edges that
- // are already marked done on one or the other
- markCanceled(startIndex, endIndex);
- if (next && nextOther) {
- next->innerCoincidentChase(step, nextOther);
- }
- }
-
- // cancel coincident edges in lock step
- void markCanceled(int start, int end) {
- if (done()) {
- return;
- }
- Segment* other = fTs[start].fOther;
- if (other->done()) {
- return;
- }
- if (start > end) {
- SkTSwap<int>(start, end);
- }
- double maxT = fTs[end].fT - FLT_EPSILON;
- int spanCount = fTs.count();
- // since these cancel, this walks up and other walks down
- int oStart = fTs[start].fOtherIndex;
- double oStartT = other->fTs[oStart].fT;
- while (oStartT - other->fTs[--oStart].fT < FLT_EPSILON)
- ;
- double startT = fTs[start].fT;
- while (start > 0 && startT - fTs[start - 1].fT < FLT_EPSILON) {
- --start;
- }
- do {
- Span* span = &fTs[start];
- Span* oSpan = &other->fTs[oStart];
- // find start of each, and see if both are not done
- bool markDone = !span->fDone && !oSpan->fDone;
- double spanT = span->fT;
- do {
- if (markDone) {
- span->fCanceled = true;
- #if DEBUG_MARK_DONE
- const SkPoint& pt = xyAtT(span);
- SkDebugf("%s segment=%d index=%d t=%1.9g pt=(%1.9g,%1.9g)\n",
- __FUNCTION__, fID, start, span->fT, pt.fX, pt.fY);
- #endif
- SkASSERT(!span->fDone);
- span->fDone = true;
- span->fWinding = 0;
- fDoneSpans++;
- }
- if (++start == spanCount) {
- break;
- }
- span = &fTs[start];
- } while (span->fT - spanT < FLT_EPSILON);
- double oSpanT = oSpan->fT;
- do {
- if (markDone) {
- oSpan->fCanceled = true;
- #if DEBUG_MARK_DONE
- const SkPoint& oPt = xyAtT(oSpan);
- SkDebugf("%s segment=%d index=%d t=%1.9g pt=(%1.9g,%1.9g)\n",
- __FUNCTION__, other->fID, oStart, oSpan->fT,
- oPt.fX, oPt.fY);
- #endif
- SkASSERT(!oSpan->fDone);
- oSpan->fDone = true;
- oSpan->fWinding = 0;
- other->fDoneSpans++;
- }
- if (--oStart < 0) {
- break;
- }
- oSpan = &other->fTs[oStart];
- } while (oSpanT - oSpan->fT < FLT_EPSILON);
- } while (fTs[start].fT <= maxT);
- }
-
- bool canceled(int start, int end) const {
- int min = SkMin32(start, end);
- return fTs[min].fCanceled;
- }
-
- void markAndChaseCoincident(int index, int endIndex, Segment* other) {
- int step = SkSign32(endIndex - index);
- innerCoincidentChase(step, other);
- }
-