diff options
author | caryclark <caryclark@google.com> | 2015-01-29 10:43:09 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-01-29 10:43:09 -0800 |
commit | 17a2b5473d0144d10749ef8d26a10fbdab580226 (patch) | |
tree | 6e1d4b8db55db4dedb6d28f975eef294bd7ab1a8 /experimental/Intersection | |
parent | f75a130c459596c23595d1bf0654863ab5fe3541 (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/Intersection')
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 = ⊂ - } - 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() = ∠ - 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); - } - |