diff options
author | caryclark <caryclark@google.com> | 2014-07-18 05:08:14 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-07-18 05:08:14 -0700 |
commit | 19eb3b2f0aa6dce5c0335230a8930e90733e5d5d (patch) | |
tree | bb3bd2ef885609b5eda366f238cc31dfaae0884d | |
parent | 384b0202c040034ba1e8f2e3789a01e4b05a6a2b (diff) |
update pathops core and tests
split out skpclip (the test of 1M pictures) into its own project
TBR=reed
Author: caryclark@google.com
Review URL: https://codereview.chromium.org/400033002
-rw-r--r-- | gyp/most.gyp | 1 | ||||
-rwxr-xr-x | gyp/pathops_skpclip.gyp | 46 | ||||
-rw-r--r-- | gyp/pathops_unittest.gyp | 1 | ||||
-rw-r--r-- | src/pathops/SkDLineIntersection.cpp | 31 | ||||
-rw-r--r-- | src/pathops/SkOpSegment.cpp | 78 | ||||
-rw-r--r-- | src/pathops/SkPathOpsDebug.cpp | 1 | ||||
-rw-r--r-- | src/pathops/SkPathOpsDebug.h | 1 | ||||
-rwxr-xr-x | tests/PathOpsDebug.cpp | 132 | ||||
-rw-r--r-- | tests/PathOpsExtendedTest.cpp | 143 | ||||
-rw-r--r-- | tests/PathOpsLineIntersectionTest.cpp | 4 | ||||
-rw-r--r-- | tests/PathOpsOpTest.cpp | 26 | ||||
-rw-r--r-- | tests/PathOpsSimplifyTest.cpp | 11 | ||||
-rwxr-xr-x | tests/PathOpsSkpClipTest.cpp | 1126 | ||||
-rwxr-xr-x | tests/PathOpsSkpTest.cpp | 226 | ||||
-rw-r--r-- | tools/pathops_sorter.htm | 6 | ||||
-rw-r--r-- | tools/pathops_visualizer.htm | 214 |
16 files changed, 1229 insertions, 818 deletions
diff --git a/gyp/most.gyp b/gyp/most.gyp index 4675add4dd..6c791b7881 100644 --- a/gyp/most.gyp +++ b/gyp/most.gyp @@ -21,6 +21,7 @@ 'tests.gyp:tests', 'tools.gyp:tools', 'pathops_unittest.gyp:*', + 'pathops_skpclip.gyp:*', # 'pdfviewer.gyp:pdfviewer', 'dm.gyp:dm', ], diff --git a/gyp/pathops_skpclip.gyp b/gyp/pathops_skpclip.gyp new file mode 100755 index 0000000000..a1e51d65f8 --- /dev/null +++ b/gyp/pathops_skpclip.gyp @@ -0,0 +1,46 @@ +# GYP file to build pathops skp clip test. +{ + 'includes': [ + 'apptype_console.gypi', + ], + 'targets': [ + { + 'target_name': 'pathops_skpclip', + 'type': 'executable', + 'include_dirs': [ + '../src/core', + '../src/effects', + '../src/lazy', + '../src/pathops', + '../src/pipe/utils', + '../src/utils', + ], + 'dependencies': [ + 'flags.gyp:flags', + 'skia_lib.gyp:skia_lib', + 'tools.gyp:crash_handler', + 'tools.gyp:resources', + ], + 'sources': [ + '../tests/PathOpsDebug.cpp', + '../tests/PathOpsSkpClipTest.cpp', + ], + 'conditions': [ + [ 'skia_android_framework == 1', { + 'libraries': [ + '-lskia', + ], + 'libraries!': [ + '-lz', + '-llog', + ], + }], + [ 'skia_gpu == 1', { + 'include_dirs': [ + '../src/gpu', + ], + }], + ], + }, + ], +} diff --git a/gyp/pathops_unittest.gyp b/gyp/pathops_unittest.gyp index 190b4f3816..b8f6835f48 100644 --- a/gyp/pathops_unittest.gyp +++ b/gyp/pathops_unittest.gyp @@ -16,7 +16,6 @@ '../tests/PathOpsCubicLineIntersectionIdeas.cpp', '../tests/PathOpsDebug.cpp', '../tests/PathOpsOpLoopThreadedTest.cpp', - '../tests/PathOpsSkpClipTest.cpp', '../tests/skia_test.cpp', ], 'conditions': [ diff --git a/src/pathops/SkDLineIntersection.cpp b/src/pathops/SkDLineIntersection.cpp index 9ae0107173..b209474066 100644 --- a/src/pathops/SkDLineIntersection.cpp +++ b/src/pathops/SkDLineIntersection.cpp @@ -173,21 +173,24 @@ int SkIntersections::intersect(const SkDLine& a, const SkDLine& b) { nearCount += t >= 0; } if (nearCount > 0) { - for (int iA = 0; iA < 2; ++iA) { - if (!aNotB[iA]) { - continue; - } - int nearer = aNearB[iA] > 0.5; - if (!bNotA[nearer]) { - continue; + // Skip if each segment contributes to one end point. + if (nearCount != 2 || aNotB[0] == aNotB[1]) { + for (int iA = 0; iA < 2; ++iA) { + if (!aNotB[iA]) { + continue; + } + int nearer = aNearB[iA] > 0.5; + if (!bNotA[nearer]) { + continue; + } + SkASSERT(a[iA] != b[nearer]); + SkASSERT(iA == (bNearA[nearer] > 0.5)); + fNearlySame[iA] = true; + insertNear(iA, nearer, a[iA], b[nearer]); + aNearB[iA] = -1; + bNearA[nearer] = -1; + nearCount -= 2; } - SkASSERT(a[iA] != b[nearer]); - SkASSERT(iA == (bNearA[nearer] > 0.5)); - fNearlySame[iA] = true; - insertNear(iA, nearer, a[iA], b[nearer]); - aNearB[iA] = -1; - bNearA[nearer] = -1; - nearCount -= 2; } if (nearCount > 0) { for (int iA = 0; iA < 2; ++iA) { diff --git a/src/pathops/SkOpSegment.cpp b/src/pathops/SkOpSegment.cpp index 4e8b5d28d9..f6d989b18a 100644 --- a/src/pathops/SkOpSegment.cpp +++ b/src/pathops/SkOpSegment.cpp @@ -405,12 +405,14 @@ void SkOpSegment::addCurveTo(int start, int end, SkPathWriter* path, bool active } void SkOpSegment::addEndSpan(int endIndex) { + SkASSERT(span(endIndex).fT == 1 || (span(endIndex).fTiny + && approximately_greater_than_one(span(endIndex).fT))); int spanCount = fTs.count(); int startIndex = endIndex - 1; while (fTs[startIndex].fT == 1 || fTs[startIndex].fTiny) { - ++startIndex; - SkASSERT(startIndex < spanCount - 1); - ++endIndex; + --startIndex; + SkASSERT(startIndex > 0); + --endIndex; } SkOpAngle& angle = fAngles.push_back(); angle.set(this, spanCount - 1, startIndex); @@ -815,7 +817,11 @@ int SkOpSegment::addSelfT(const SkPoint& pt, double newT) { // FIXME? assert that only one other span has a valid windValue or oppValue void SkOpSegment::addSimpleAngle(int index) { SkOpSpan* span = &fTs[index]; - if (index == 0) { + int idx; + int start, end; + if (span->fT == 0) { + idx = 0; + span = &fTs[0]; do { if (span->fToAngle) { SkASSERT(span->fToAngle->loopCount() == 2); @@ -823,13 +829,15 @@ void SkOpSegment::addSimpleAngle(int index) { span->fFromAngle = span->fToAngle->next(); return; } - span = &fTs[++index]; + span = &fTs[++idx]; } while (span->fT == 0); - SkASSERT(index == 1); - index = 0; - SkASSERT(!fTs[0].fTiny && fTs[1].fT > 0); - addStartSpan(1); + SkASSERT(!fTs[0].fTiny && fTs[idx].fT > 0); + addStartSpan(idx); + start = 0; + end = idx; } else { + idx = count() - 1; + span = &fTs[idx]; do { if (span->fFromAngle) { SkASSERT(span->fFromAngle->loopCount() == 2); @@ -837,29 +845,48 @@ void SkOpSegment::addSimpleAngle(int index) { span->fToAngle = span->fFromAngle->next(); return; } - span = &fTs[--index]; + span = &fTs[--idx]; } while (span->fT == 1); - SkASSERT(index == count() - 2); - index = count() - 1; - SkASSERT(!fTs[index - 1].fTiny && fTs[index - 1].fT < 1); - addEndSpan(index); + SkASSERT(!fTs[idx].fTiny && fTs[idx].fT < 1); + addEndSpan(++idx); + start = idx; + end = count(); } - span = &fTs[index]; - SkOpSegment* other = span->fOther; - SkOpSpan& oSpan = other->fTs[span->fOtherIndex]; + SkOpSegment* other; + SkOpSpan* oSpan; + index = start; + do { + span = &fTs[index]; + other = span->fOther; + int oFrom = span->fOtherIndex; + oSpan = &other->fTs[oFrom]; + if (oSpan->fT < 1 && oSpan->fWindValue) { + break; + } + if (oSpan->fT == 0) { + continue; + } + oFrom = other->nextExactSpan(oFrom, -1); + SkOpSpan* oFromSpan = &other->fTs[oFrom]; + SkASSERT(oFromSpan->fT < 1); + if (oFromSpan->fWindValue) { + break; + } + } while (++index < end); SkOpAngle* angle, * oAngle; - if (index == 0) { + if (span->fT == 0) { SkASSERT(span->fOtherIndex - 1 >= 0); SkASSERT(span->fOtherT == 1); - SkDEBUGCODE(SkOpSpan& oPrior = other->fTs[span->fOtherIndex - 1]); + SkDEBUGCODE(int oPriorIndex = other->nextExactSpan(span->fOtherIndex, -1)); + SkDEBUGCODE(const SkOpSpan& oPrior = other->span(oPriorIndex)); SkASSERT(!oPrior.fTiny && oPrior.fT < 1); other->addEndSpan(span->fOtherIndex); angle = span->fToAngle; - oAngle = oSpan.fFromAngle; + oAngle = oSpan->fFromAngle; } else { SkASSERT(span->fOtherIndex + 1 < other->count()); SkASSERT(span->fOtherT == 0); - SkASSERT(!oSpan.fTiny && (other->fTs[span->fOtherIndex + 1].fT > 0 + SkASSERT(!oSpan->fTiny && (other->fTs[span->fOtherIndex + 1].fT > 0 || (other->fTs[span->fOtherIndex + 1].fFromAngle == NULL && other->fTs[span->fOtherIndex + 1].fToAngle == NULL))); int oIndex = 1; @@ -873,7 +900,7 @@ void SkOpSegment::addSimpleAngle(int index) { } while (true); other->addStartSpan(oIndex); angle = span->fFromAngle; - oAngle = oSpan.fToAngle; + oAngle = oSpan->fToAngle; } angle->insert(oAngle); } @@ -1348,7 +1375,10 @@ void SkOpSegment::addTCoincident(const SkPoint& startPt, const SkPoint& endPt, d success = true; break; } - oPeek = &other->fTs[++oPeekIndex]; + if (++oPeekIndex == oCount) { + break; + } + oPeek = &other->fTs[oPeekIndex]; } while (endPt == oPeek->fPt); } if (success) { @@ -3402,7 +3432,7 @@ SkOpSpan* SkOpSegment::markAndChaseWinding(const SkOpAngle* angle, int winding) SkOpSegment* other = this; while ((other = other->nextChase(&index, &step, &min, &last))) { if (other->fTs[min].fWindSum != SK_MinS32) { - SkASSERT(other->fTs[min].fWindSum == winding); +// SkASSERT(other->fTs[min].fWindSum == winding); SkASSERT(!last); break; } diff --git a/src/pathops/SkPathOpsDebug.cpp b/src/pathops/SkPathOpsDebug.cpp index 96029b340b..7db93f5e96 100644 --- a/src/pathops/SkPathOpsDebug.cpp +++ b/src/pathops/SkPathOpsDebug.cpp @@ -108,6 +108,7 @@ void SkOpAngle::debugLoop() const { const SkOpAngle* next = this; do { next->dumpOne(true); + SkDebugf("\n"); next = next->fNext; } while (next && next != first); } diff --git a/src/pathops/SkPathOpsDebug.h b/src/pathops/SkPathOpsDebug.h index 9dc562fea1..211c503aad 100644 --- a/src/pathops/SkPathOpsDebug.h +++ b/src/pathops/SkPathOpsDebug.h @@ -169,6 +169,7 @@ public: SkPathOpsDebug::DeleteNameStr))) static void BumpTestName(char* ); #endif + static void ShowOnePath(const SkPath& path, const char* name, bool includeDeclaration); static void ShowPath(const SkPath& one, const SkPath& two, SkPathOp op, const char* name); static void DumpCoincidence(const SkTArray<class SkOpContour, true>& contours); static void DumpCoincidence(const SkTArray<class SkOpContour* , true>& contours); diff --git a/tests/PathOpsDebug.cpp b/tests/PathOpsDebug.cpp index af60318532..8ac38aaf6d 100755 --- a/tests/PathOpsDebug.cpp +++ b/tests/PathOpsDebug.cpp @@ -1,6 +1,7 @@ #include "SkOpContour.h" #include "SkIntersectionHelper.h" #include "SkOpSegment.h" +#include "SkString.h" inline void DebugDumpDouble(double x) { if (x == floor(x)) { @@ -18,6 +19,137 @@ inline void DebugDumpFloat(float x) { } } + +#if DEBUG_SHOW_TEST_NAME + +static void output_scalar(SkScalar num) { + if (num == (int) num) { + SkDebugf("%d", (int) num); + } else { + SkString str; + str.printf("%1.9g", num); + int width = (int) str.size(); + const char* cStr = str.c_str(); + while (cStr[width - 1] == '0') { + --width; + } + str.resize(width); + SkDebugf("%sf", str.c_str()); + } +} + +static void output_points(const SkPoint* pts, int count) { + for (int index = 0; index < count; ++index) { + output_scalar(pts[index].fX); + SkDebugf(", "); + output_scalar(pts[index].fY); + if (index + 1 < count) { + SkDebugf(", "); + } + } + SkDebugf(");\n"); +} + +static void showPathContours(SkPath::RawIter& iter, const char* pathName) { + uint8_t verb; + SkPoint pts[4]; + while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { + switch (verb) { + case SkPath::kMove_Verb: + SkDebugf(" %s.moveTo(", pathName); + output_points(&pts[0], 1); + continue; + case SkPath::kLine_Verb: + SkDebugf(" %s.lineTo(", pathName); + output_points(&pts[1], 1); + break; + case SkPath::kQuad_Verb: + SkDebugf(" %s.quadTo(", pathName); + output_points(&pts[1], 2); + break; + case SkPath::kCubic_Verb: + SkDebugf(" %s.cubicTo(", pathName); + output_points(&pts[1], 3); + break; + case SkPath::kClose_Verb: + SkDebugf(" %s.close();\n", pathName); + break; + default: + SkDEBUGFAIL("bad verb"); + return; + } + } +} + +static const char* gFillTypeStr[] = { + "kWinding_FillType", + "kEvenOdd_FillType", + "kInverseWinding_FillType", + "kInverseEvenOdd_FillType" +}; + +void SkPathOpsDebug::ShowOnePath(const SkPath& path, const char* name, bool includeDeclaration) { + SkPath::RawIter iter(path); +#define SUPPORT_RECT_CONTOUR_DETECTION 0 +#if SUPPORT_RECT_CONTOUR_DETECTION + 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; + } +#endif + SkPath::FillType fillType = path.getFillType(); + SkASSERT(fillType >= SkPath::kWinding_FillType && fillType <= SkPath::kInverseEvenOdd_FillType); + if (includeDeclaration) { + SkDebugf(" SkPath %s;\n", name); + } + SkDebugf(" %s.setFillType(SkPath::%s);\n", name, gFillTypeStr[fillType]); + iter.setPath(path); + showPathContours(iter, name); +} + +static void show_function_header(const char* functionName) { + SkDebugf("\nstatic void %s(skiatest::Reporter* reporter, const char* filename) {\n", functionName); + if (strcmp("skphealth_com76", functionName) == 0) { + SkDebugf("found it\n"); + } +} + +static const char* gOpStrs[] = { + "kDifference_PathOp", + "kIntersect_PathOp", + "kUnion_PathOp", + "kXor_PathOp", + "kReverseDifference_PathOp", +}; + +static void show_op(SkPathOp op, const char* pathOne, const char* pathTwo) { + SkDebugf(" testPathOp(reporter, %s, %s, %s, filename);\n", pathOne, pathTwo, gOpStrs[op]); + SkDebugf("}\n"); +} + +SK_DECLARE_STATIC_MUTEX(gTestMutex); + +void SkPathOpsDebug::ShowPath(const SkPath& a, const SkPath& b, SkPathOp shapeOp, + const char* testName) { + SkAutoMutexAcquire ac(gTestMutex); + show_function_header(testName); + ShowOnePath(a, "path", true); + ShowOnePath(b, "pathB", true); + show_op(shapeOp, "path", "pathB"); +} +#endif + // if not defined by PathOpsDebug.cpp ... #if !defined SK_DEBUG && FORCE_RELEASE bool SkPathOpsDebug::ValidWind(int wind) { diff --git a/tests/PathOpsExtendedTest.cpp b/tests/PathOpsExtendedTest.cpp index fe3d24d6a0..2d741261a6 100644 --- a/tests/PathOpsExtendedTest.cpp +++ b/tests/PathOpsExtendedTest.cpp @@ -49,102 +49,6 @@ static bool gShowPath = false; static bool gComparePathsAssert = true; static bool gPathStrAssert = true; -static const char* gFillTypeStr[] = { - "kWinding_FillType", - "kEvenOdd_FillType", - "kInverseWinding_FillType", - "kInverseEvenOdd_FillType" -}; - -static void output_scalar(SkScalar num) { - if (num == (int) num) { - SkDebugf("%d", (int) num); - } else { - SkString str; - str.printf("%1.9g", num); - int width = (int) str.size(); - const char* cStr = str.c_str(); - while (cStr[width - 1] == '0') { - --width; - } - str.resize(width); - SkDebugf("%sf", str.c_str()); - } -} - -static void output_points(const SkPoint* pts, int count) { - for (int index = 0; index < count; ++index) { - output_scalar(pts[index].fX); - SkDebugf(", "); - output_scalar(pts[index].fY); - if (index + 1 < count) { - SkDebugf(", "); - } - } - SkDebugf(");\n"); -} - -static void showPathContours(SkPath::RawIter& iter, const char* pathName) { - uint8_t verb; - SkPoint pts[4]; - while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { - switch (verb) { - case SkPath::kMove_Verb: - SkDebugf(" %s.moveTo(", pathName); - output_points(&pts[0], 1); - continue; - case SkPath::kLine_Verb: - SkDebugf(" %s.lineTo(", pathName); - output_points(&pts[1], 1); - break; - case SkPath::kQuad_Verb: - SkDebugf(" %s.quadTo(", pathName); - output_points(&pts[1], 2); - break; - case SkPath::kCubic_Verb: - SkDebugf(" %s.cubicTo(", pathName); - output_points(&pts[1], 3); - break; - case SkPath::kClose_Verb: - SkDebugf(" %s.close();\n", pathName); - break; - default: - SkDEBUGFAIL("bad verb"); - return; - } - } -} - -static void showPath(const SkPath& path, const char* pathName, bool includeDeclaration) { - SkPath::RawIter iter(path); -#define SUPPORT_RECT_CONTOUR_DETECTION 0 -#if SUPPORT_RECT_CONTOUR_DETECTION - 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; - } -#endif - SkPath::FillType fillType = path.getFillType(); - SkASSERT(fillType >= SkPath::kWinding_FillType && fillType <= SkPath::kInverseEvenOdd_FillType); - if (includeDeclaration) { - SkDebugf(" SkPath %s;\n", pathName); - } - SkDebugf(" %s.setFillType(SkPath::%s);\n", pathName, gFillTypeStr[fillType]); - iter.setPath(path); - showPathContours(iter, pathName); -} - #if DEBUG_SHOW_TEST_NAME static void showPathData(const SkPath& path) { SkPath::RawIter iter(path); @@ -225,29 +129,6 @@ void showOp(const SkPathOp op) { } #if DEBUG_SHOW_TEST_NAME - -void ShowFunctionHeader(const char* functionName) { - SkDebugf("\nstatic void %s(skiatest::Reporter* reporter, const char* filename) {\n", functionName); - if (strcmp("skphealth_com76", functionName) == 0) { - SkDebugf("found it\n"); - } -} - -static const char* gOpStrs[] = { - "kDifference_PathOp", - "kIntersect_PathOp", - "kUnion_PathOp", - "kXor_PathOp", - "kReverseDifference_PathOp", -}; - -void ShowOp(SkPathOp op, const char* pathOne, const char* pathTwo) { - SkDebugf(" testPathOp(reporter, %s, %s, %s, filename);\n", pathOne, pathTwo, gOpStrs[op]); - SkDebugf("}\n"); -} -#endif - -#if DEBUG_SHOW_TEST_NAME static char hexorator(int x) { if (x < 10) { return x + '0'; @@ -420,8 +301,10 @@ static void showPathOpPath(const char* testName, const SkPath& one, const SkPath *gTestOp.append() = shapeOp; ++gTestNo; SkDebugf(" SkPath path, pathB;\n"); - showPath(a, "path", false); - showPath(b, "pathB", false); +#if DEBUG_SHOW_TEST_NAME + SkPathOpsDebug::ShowOnePath(a, "path", false); + SkPathOpsDebug::ShowOnePath(b, "pathB", false); +#endif SkDebugf(" testPathOp(reporter, path, pathB, %s, filename);\n", opStrs[shapeOp]); SkDebugf("}\n"); drawAsciiPaths(scaledOne, scaledTwo, true); @@ -523,9 +406,11 @@ bool testSimplify(SkPath& path, bool useXor, SkPath& out, PathOpsThreadState& st const char* pathStr) { SkPath::FillType fillType = useXor ? SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType; path.setFillType(fillType); +#if DEBUG_SHOW_TEST_NAME if (gShowPath) { - showPath(path, "path", false); + SkPathOpsDebug::ShowOnePath(path, "path", false); } +#endif if (!Simplify(path, &out)) { SkDebugf("%s did not expect failure\n", __FUNCTION__); REPORTER_ASSERT(state.fReporter, 0); @@ -576,20 +461,6 @@ bool testSimplify(skiatest::Reporter* reporter, const SkPath& path, const char* } #if DEBUG_SHOW_TEST_NAME - -SK_DECLARE_STATIC_MUTEX(gTestMutex); - -void SkPathOpsDebug::ShowPath(const SkPath& a, const SkPath& b, SkPathOp shapeOp, - const char* testName) { - SkAutoMutexAcquire ac(gTestMutex); - ShowFunctionHeader(testName); - showPath(a, "path", true); - showPath(b, "pathB", true); - ShowOp(shapeOp, "path", "pathB"); -} -#endif - -#if DEBUG_SHOW_TEST_NAME static void showName(const SkPath& a, const SkPath& b, const SkPathOp shapeOp) { SkDebugf("\n"); showPathData(a); diff --git a/tests/PathOpsLineIntersectionTest.cpp b/tests/PathOpsLineIntersectionTest.cpp index 379c2f16f9..0c6aac65d9 100644 --- a/tests/PathOpsLineIntersectionTest.cpp +++ b/tests/PathOpsLineIntersectionTest.cpp @@ -11,6 +11,10 @@ // FIXME: add tests for intersecting, non-intersecting, degenerate, coincident static const SkDLine tests[][2] = { +#if 0 + // these do intersect at a pair of points, but not close enough for check results liking + {{{{365.848175,5081.15186}, {368,5103}}}, {{{367.967712,5102.61084}, {368.278717,5105.71045}}}}, +#endif {{{{30,20}, {30,50}}}, {{{24,30}, {36,30}}}}, {{{{323,193}, {-317,193}}}, {{{0,994}, {0,0}}}}, {{{{90,230}, {160,60}}}, {{{60,120}, {260,120}}}}, diff --git a/tests/PathOpsOpTest.cpp b/tests/PathOpsOpTest.cpp index 1d63bd7ab6..b7babd3af6 100644 --- a/tests/PathOpsOpTest.cpp +++ b/tests/PathOpsOpTest.cpp @@ -3461,10 +3461,36 @@ static void rects4(skiatest::Reporter* reporter, const char* filename) { testPathOp(reporter, path, pathB, kDifference_PathOp, filename); } +#define TEST_ISSUE_2753 0 +#if TEST_ISSUE_2753 +static void issue2753(skiatest::Reporter* reporter, const char* filename) { + SkPath path1; + path1.moveTo(142.701f, 110.568f); + path1.lineTo(142.957f, 100); + path1.lineTo(153.835f, 100); + path1.lineTo(154.592f, 108.188f); + path1.cubicTo(154.592f, 108.188f, 153.173f, 108.483f, 152.83f, 109.412f); + path1.cubicTo(152.83f, 109.412f, 142.701f, 110.568f, 142.701f, 110.568f); + path1.close(); + + SkPath path2; + path2.moveTo(39, 124.001f); + path2.cubicTo(39, 124.001f, 50.6f, 117.001f, 50.6f, 117.001f); + path2.cubicTo(50.6f, 117.001f, 164.601f, 85.2f, 188.201f, 117.601f); + path2.cubicTo(188.201f, 117.601f, 174.801f, 93, 39, 124.001f); + path2.close(); + + testPathOp(reporter, path1, path2, kUnion_PathOp, filename); +} +#endif + static void (*firstTest)(skiatest::Reporter* , const char* filename) = 0; static void (*stopTest)(skiatest::Reporter* , const char* filename) = 0; static struct TestDesc tests[] = { +#if TEST_ISSUE_2753 // FIXME: pair of cubics miss intersection + TEST(issue2753), +#endif #if CUBIC_OP_114 // FIXME: curve with inflection is ordered the wrong way TEST(cubicOp114), #endif diff --git a/tests/PathOpsSimplifyTest.cpp b/tests/PathOpsSimplifyTest.cpp index 4bfab14488..88547a0f04 100644 --- a/tests/PathOpsSimplifyTest.cpp +++ b/tests/PathOpsSimplifyTest.cpp @@ -4669,9 +4669,20 @@ static void testQuadralateral10(skiatest::Reporter* reporter, const char* filena testSimplify(reporter, path, filename); } +static void testRect3(skiatest::Reporter* reporter, const char* filename) { + SkPath path; + path.setFillType(SkPath::kEvenOdd_FillType); + path.addRect(0, 0, 60, 60, SkPath::kCCW_Direction); + path.addRect(10, 30, 40, 30, SkPath::kCCW_Direction); + path.addRect(24, 6, 36, 36, SkPath::kCCW_Direction); + path.addRect(32, 6, 36, 41, SkPath::kCCW_Direction); + testSimplify(reporter, path, filename); +} + static void (*firstTest)(skiatest::Reporter* , const char* filename) = 0; static TestDesc tests[] = { + TEST(testRect3), TEST(testQuadralateral10), TEST(testQuads61), TEST(testQuads60), diff --git a/tests/PathOpsSkpClipTest.cpp b/tests/PathOpsSkpClipTest.cpp index da505451da..0e3cee9f4e 100755 --- a/tests/PathOpsSkpClipTest.cpp +++ b/tests/PathOpsSkpClipTest.cpp @@ -1,9 +1,13 @@ - +#include "CrashHandler.h" +// #include "OverwriteLine.h" +#include "Resources.h" #include "SkBitmap.h" #include "SkCanvas.h" #include "SkColor.h" #include "SkColorPriv.h" +#include "SkCommandLineFlags.h" #include "SkDevice.h" +#include "SkForceLinking.h" #include "SkGraphics.h" #include "SkImageDecoder.h" #include "SkImageEncoder.h" @@ -16,209 +20,133 @@ #include "SkString.h" #include "SkTArray.h" #include "SkTDArray.h" +#include "SkTemplates.h" #include "SkThreadPool.h" #include "SkTime.h" -#include "Test.h" + +__SK_FORCE_IMAGE_DECODER_LINKING; + +/* add local exceptions here */ +/* TODO : add command flag interface */ +const struct SkipOverTest { + int directory; + const char* filename; + bool blamePathOps; +} skipOver[] = { + { 2, "http___www_groupon_sg_.skp", false}, // SkAAClip::Builder::addRun SkASSERT(fBounds.contains(x, y)); + { 6, "http___www_googleventures_com_.skp", true}, // addTCoincident SkASSERT(test->fT < 1); + { 7, "http___www_foxsports_nl_.skp", true}, // (no repro on mac) addT SkASSERT(this != other || fVerb == SkPath::kCubic_Verb) + {13, "http___www_modernqigong_com_.skp", false}, // SkAAClip::Builder::addRun SkASSERT(fBounds.contains(x, y)); + {14, "http___www_devbridge_com_.skp", true}, // checkSmallCoincidence SkASSERT(!next->fSmall || checkMultiple); + {16, "http___www_1023world_net_.skp", true}, // bitmap decode assert (corrupt skp?) + {19, "http___www_alamdi_com_.skp", true}, // cubic/quad intersection + {26, "http___www_liveencounters_net_.skp", true}, // (no repro on mac) checkSmall addT:549 (line, expects cubic) + {28, "http___www_encros_fr_.skp", false}, // SkAAClip::Builder::addRun SkASSERT(fBounds.contains(x, y)); + {37, "http___www_familysurvivalprotocol_wordpress_com_.skp", true}, // bumpSpan SkASSERT(span->fOppValue >= 0); + {39, "http___sufeinet_com_.skp", false}, // bitmap decode assert (corrupt skp?) + {41, "http___www_rano360_com_.skp", true}, // checkSmallCoincidence SkASSERT(!next->fSmall || checkMultiple); + {44, "http___www_firstunitedbank_com_.skp", true}, // addTCancel SkASSERT(oIndex > 0); + {46, "http___www_shinydemos_com_.skp", true}, // addSimpleAngle SkASSERT(index == count() - 2); + {48, "http___www_familysurvivalprotocol_com_.skp", true}, // bumpSpan SkASSERT "span->fOppValue >= 0" + {57, "http___www_lptemp_com_.skp", true}, // addTCoincident oPeek = &other->fTs[++oPeekIndex]; + {71, "http___www_1milyonkahraman_org_.skp", true}, // addTCoincident SkASSERT(test->fT < 1); + {88, "http___www_apuntesdelechuza_wordpress_com_.skp", true}, // bumpSpan SkASSERT "span->fOppValue >= 0" + {89, "http___www_mobilizedconsulting_com_.skp", true}, // addTCancel SkASSERT(oIndex > 0); + {93, "http___www_simple_living_in_suffolk_co_uk_.skp", true}, // bumpSpan SkASSERT "span->fOppValue >= 0" +}; + +size_t skipOverCount = sizeof(skipOver) / sizeof(skipOver[0]); + + +/* customize file in/out here */ +/* TODO : add command flag interface */ +#define CHROME_VERSION "1e5dfa4-4a995df" +#define SUMMARY_RUN 1 #ifdef SK_BUILD_FOR_WIN + #define DRIVE_SPEC "D:" #define PATH_SLASH "\\" - #define IN_DIR "D:\\skp\\slave" - #define OUT_DIR "D:\\skpOut\\1\\" #else + #define DRIVE_SPEC "" #define PATH_SLASH "/" - #define IN_DIR "/skp/2311328-7fc2228/slave" - #define OUT_DIR "/skpOut/4/" #endif -const struct { - int directory; - const char* filename; -} skipOverSept[] = { - { 3, "http___www_americascup_com_.skp"}, // !simple->closed() - {18, "http___www_argus_presse_fr_.skp"}, // can't find winding of remaining vertical edge - {31, "http___www_narayana_verlag_de_.skp"}, // !simple->closed() - {36, "http___www_educationalcraft_com_.skp"}, // cubic / cubic near end / assert in SkIntersections::insert - {44, "http___www_cooksnaps_com_.skp"}, // !simple->isClosed() - {48, "http___www_narayana_publishers_com_.skp"}, // !simple->isClosed() - {51, "http___www_freedominthe50states_org_.skp"}, // corrupt dash data - {52, "http___www_aceinfographics_com_.skp"}, // right angle winding assert - {53, "http___www_lojaanabotafogo_com_br_.skp"}, // rrect validate assert - {57, "http___www_vantageproduction_com_.skp"}, // !isClosed() - {64, "http___www_etiqadd_com_.skp"}, // !simple->closed() - {84, "http___www_swapspacesystems_com_.skp"}, // !simple->closed() - {90, "http___www_tcmevents_org_.skp"}, // !simple->closed() - {96, "http___www_paseoitaigara_com_br_.skp"}, // !simple->closed() - {98, "http___www_mortgagemarketguide_com_.skp"}, // !simple->closed() - {99, "http___www_kitcheninspirations_wordpress_com_.skp"}, // checkSmall / bumpSpan -}; +#define IN_DIR_PRE DRIVE_SPEC PATH_SLASH "skps" PATH_SLASH "slave" +#define OUT_DIR_PRE DRIVE_SPEC PATH_SLASH "skpOut" PATH_SLASH "slave" +#define OUT_DIR_SUM DRIVE_SPEC PATH_SLASH "skpOut" PATH_SLASH "summary" +#define DIR_POST PATH_SLASH "All" PATH_SLASH CHROME_VERSION + +static const char outOpDir[] = "opClip"; +static const char outOldDir[] = "oldClip"; +static const char outStatusDir[] = "statusTest"; + +static SkString get_in_path(int dirNo, const char* filename) { + SkString path; + SkASSERT(dirNo); + path.appendf("%s%d%s", IN_DIR_PRE, dirNo, DIR_POST); + if (!sk_exists(path.c_str())) { + SkDebugf("could not read %s\n", path.c_str()); + return SkString(); + } + if (filename) { + path.appendf("%s%s", PATH_SLASH, filename); + if (!sk_exists(path.c_str())) { + SkDebugf("could not read %s\n", path.c_str()); + return SkString(); + } + } + return path; +} + +static void make_recursive_dir(const SkString& path) { + if (sk_exists(path.c_str())) { + return; + } + const char* pathStr = path.c_str(); + int last = (int) path.size(); + do { + while (last > 0 && pathStr[--last] != PATH_SLASH[0]) + ; + SkASSERT(last > 0); + SkString shorter(pathStr, last); + if (sk_mkdir(shorter.c_str())) { + break; + } + } while (true); + do { + while (last < (int) path.size() && pathStr[++last] != PATH_SLASH[0]) + ; + SkString shorter(pathStr, last); + SkAssertResult(sk_mkdir(shorter.c_str())); + } while (last < (int) path.size()); +} + +static SkString get_out_path(int dirNo, const char* dirName) { + SkString path; + SkASSERT(dirNo); + SkASSERT(dirName); + path.appendf("%s%d%s%s%s", OUT_DIR_PRE, dirNo, DIR_POST, PATH_SLASH, dirName); + make_recursive_dir(path); + return path; +} + +static SkString get_sum_path(const char* dirName) { + SkString path; + SkASSERT(dirName); + path.appendf("%s%d%s%s", OUT_DIR_SUM, SUMMARY_RUN, PATH_SLASH, dirName); + SkDebugf("%s\n", path.c_str()); + make_recursive_dir(path); + return path; +} + +static SkString make_png_name(const char* filename) { + SkString pngName = SkString(filename); + pngName.remove(pngName.size() - 3, 3); + pngName.append("png"); + return pngName; +} -/* stats -97 http___www_brandyandvinca_com_.skp pixelError=3 -95 http___www_into_asia_com_.skp pixelError=12 -93 http___www_lunarplanner_com_.skp pixelError=14 -98 http___www_lovelyitalia_com_.skp pixelError=17 -90 http___www_inter_partner_blogspot_com_.skp pixelError=18 -99 http___www_maxarea_com_.skp pixelError=26 -98 http___www_maroonsnet_org_.skp pixelError=33 -92 http___www_belinaart_ru_.skp pixelError=50 -100 http___www_chroot_ro_.skp pixelError=62 -99 http___www_hsbrands_com_.skp pixelError=98 -95 http___www_tournamentindicator_com_.skp pixelError=122 -93 http___www_businesses_com_au_.skp pixelError=162 -90 http___www_regenesys_net_.skp pixelError=182 -88 http___www_1863544208148625103_c18eac63985503fa85b06358959c1ba27fc36f82_blogspot_com_.skp pixelError=186 -97 http___www_pregacoesevangelica_com_br_.skp pixelError=240 -77 http___www_zhenggang_org_.skp pixelError=284 -96 http___slidesharemailer_com_.skp pixelError=522 -94 http___www_gensteel_com_.skp pixelError=555 -68 http___www_jf_eti_br_.skp pixelError=610 -83 http___www_swishiat_com_.skp pixelError=706 -96 http___www_matusikmissive_com_au_.skp pixelError=2580 -95 http___www_momentumnation_com_.skp pixelError=3938 -92 http___www_rssowl_com_.skp pixelError=5113 -96 http___www_sexxygirl_tv_.skp pixelError=7605 -99 http___www_georgevalah_wordpress_com_.skp pixelError=8386 -78 http___www_furbo_org_.skp pixelError=8656 -78 http___www_djxhemary_wordpress_com_.skp pixelError=8976 -100 http___www_mindcontrolblackassassins_com_.skp pixelError=31950 -98 http___bababillgates_free_fr_.skp pixelError=40237 -98 http___hepatite_ro_.skp pixelError=44370 -86 http___www_somethingwagging_com_.skp pixelError=47794 -84 http___www_beverageuniverse_com_.skp pixelError=65450 -50 http___www_aveksa_com_.skp pixelError=68194 -10 http___www_publiker_pl_.skp pixelError=89997 -61 http___www_dominos_co_id_.skp pixelError=476868 -87 http___www_du_edu_om_.skp time=46 -87 http___www_bigload_de_.skp time=46 -100 http___www_home_forum_com_.skp time=48 -97 http___www_hotamateurchat_com_.skp time=48 -97 http___www_myrsky_com_cn_.skp time=48 -98 http___www_techiegeex_com_.skp time=49 -82 http___www_fashionoutletsofchicago_com_.skp time=50 -77 http___www_dynamischbureau_nl_.skp time=50 -82 http___www_mayihelpu_co_in_.skp time=50 -84 http___www_vbox7_com_user_history_viewers_.skp time=50 -85 http___www_ktokogda_com_.skp time=50 -85 http___www_propertyturkeysale_com_.skp time=50 -85 http___www_51play_com_.skp time=50 -86 http___www_bayalarm_com_.skp time=50 -87 http___www_eaglepictures_com_.skp time=50 -88 http___www_atlasakvaryum_com_.skp time=50 -91 http___www_pioneerchryslerjeep_com_.skp time=50 -94 http___www_thepulsemag_com_.skp time=50 -95 http___www_dcshoes_com_ph_.skp time=50 -96 http___www_montrealmassage_ca_.skp time=50 -96 http___www_jkshahclasses_com_.skp time=50 -96 http___www_webcamconsult_com_.skp time=51 -100 http___www_bsoscblog_com_.skp time=52 -95 http___www_flaktwoods_com_.skp time=53 -91 http___www_qivivo_com_.skp time=54 -90 http___www_unitender_com_.skp time=56 -97 http___www_casinogaming_com_.skp time=56 -97 http___www_rootdownload_com_.skp time=56 -94 http___www_aspa_ev_de_.skp time=57 -98 http___www_tenpieknyswiat_pl_.skp time=57 -93 http___www_transocean_de_.skp time=58 -94 http___www_vdo2_blogspot_com_.skp time=58 -94 http___www_asmaissexy_com_br_.skp time=58 -100 http___www_prefeiturasjm_com_br_.skp time=60 -100 http___www_eduinsuranceclick_blogspot_com_.skp time=60 -96 http___www_bobdunsire_com_.skp time=61 -96 http___www_omgkettlecorn_com_.skp time=61 -85 http___www_fbbsessions_com_.skp time=62 -86 http___www_hector_ru_.skp time=62 -87 http___www_wereldsupporter_nl_.skp time=62 -90 http___www_arello_com_.skp time=62 -93 http___www_bayerplastics_com_.skp time=62 -93 http___www_superandolamovida_com_ar_.skp time=62 -96 http___www_med_rbf_ru_.skp time=62 -81 http___www_carnegiescience_edu_.skp time=65 -87 http___www_asanewengland_com_.skp time=65 -92 http___www_turkce_karakter_appspot_com_.skp time=65 -94 http___www_k3a_org_.skp time=65 -96 http___www_powermaccenter_com_.skp time=65 -98 http___www_avto49_ru_.skp time=67 -100 http___www_hetoldeambaecht_nl_.skp time=68 -95 http___www_marine_ie_.skp time=69 -96 http___www_quebecvapeboutique_com_.skp time=69 -95 http___www_brays_ingles_com_.skp time=70 -100 http___www_lacondesa_com_.skp time=72 -95 http___www_timbarrathai_com_au_.skp time=76 -95 http___www_cuissedegrenouille_com_.skp time=76 -95 http___www_iwama51_ru_.skp time=76 -99 http___www_fotoantologia_it_.skp time=76 -92 http___www_indian_architects_com_.skp time=78 -92 http___www_totalwomanspa_com_.skp time=78 -100 http___www_fachverband_spielhallen_de_.skp time=83 -93 http___www_golshanemehr_ir_.skp time=84 -95 http___www_maryesses_com_.skp time=84 -99 http___www_ddcorp_ca_.skp time=89 -90 http___www_brontops_com_.skp time=89 -94 http___www_robgolding_com_.skp time=89 -91 http___www_tecban_com_br_.skp time=91 -98 http___www_costamesakarate_com_.skp time=100 -95 http___www_monsexyblog_com_.skp time=103 -97 http___www_stornowaygazette_co_uk_.skp time=103 -93 http___www_fitforaframe_com_.skp time=104 -98 http___www_intentionoftheday_com_.skp time=113 -100 http___www_tailgateclothing_com_.skp time=117 -95 http___www_senbros_com_.skp time=118 -93 http___www_lettoblog_com_.skp time=121 -94 http___www_maxineschallenge_com_au_.skp time=125 -95 http___www_savvycard_net_.skp time=127 -95 http___www_open_ac_mu_.skp time=129 -96 http___www_avgindia_in_.skp time=135 -97 http___www_stocktonseaview_com_.skp time=135 -96 http___www_distroller_com_.skp time=142 -94 http___www_travoggalop_dk_.skp time=144 -100 http___www_history_im_.skp time=144 -94 http___www_playradio_sk_.skp time=145 -92 http___www_linglongglass_com_.skp time=151 -97 http___www_bizzna_com_.skp time=151 -96 http___www_spiros_ws_.skp time=154 -91 http___www_rosen_meents_co_il_.skp time=156 -81 http___www_hoteldeluxeportland_com_.skp time=158 -92 http___www_freetennis_org_.skp time=161 -93 http___www_aircharternetwork_com_au_.skp time=161 -94 http___www_austinparks_org_.skp time=165 -89 http___www_bevvy_co_.skp time=168 -91 http___www_sosyalhile_net_.skp time=168 -98 http___www_minvih_gob_ve_.skp time=171 -89 http___www_streetfoodmtl_com_.skp time=172 -92 http___www_loveslatinas_tumblr_com_.skp time=178 -93 http___www_madbites_co_in_.skp time=180 -94 http___www_rocktarah_ir_.skp time=185 -97 http___www_penthouselife_com_.skp time=185 -96 http___www_appymonkey_com_.skp time=196 -92 http___www_pasargadhotels_com_.skp time=203 -99 http___www_marina_mil_pe_.skp time=203 -89 http___www_kays_co_uk_.skp time=205 -77 http___www_334588_com_.skp time=211 -83 http___www_trendbad24_de_.skp time=211 -81 http___www_cdnetworks_co_kr_.skp time=216 -94 http___www_schellgames_com_.skp time=223 -95 http___www_juliaweddingnews_cn_.skp time=230 -92 http___www_xcrafters_pl_.skp time=253 -93 http___www_pondoo_com_.skp time=253 -96 http___www_helsinkicapitalpartners_fi_.skp time=255 -88 http___www_nadtexican_com_.skp time=259 -85 http___www_canstockphoto_hu_.skp time=266 -78 http___www_ecovacs_com_cn_.skp time=271 -93 http___www_brookfieldplaceny_com_.skp time=334 -93 http___www_fmastrengthtraining_com_.skp time=337 -94 http___www_turtleonthebeach_com_.skp time=394 -90 http___www_temptationthemovie_com_.skp time=413 -95 http___www_patongsawaddi_com_.skp time=491 -91 http___www_online_radio_appspot_com_.skp time=511 -68 http___www_richardmiller_co_uk_.skp time=528 -63 http___www_eschrade_com_.skp time=543 -55 http___www_interaction_inf_br_.skp time=625 -38 http___www_huskyliners_com_.skp time=632 -86 http___granda_net_.skp time=1067 -24 http___www_cocacolafm_com_br_.skp time=1081 -*/ - -size_t skipOverSeptCount = sizeof(skipOverSept) / sizeof(skipOverSept[0]); +//////////////////////////////////////////////////////// enum TestStep { kCompareBits, @@ -238,6 +166,13 @@ struct TestResult { fTestStep = kCompareBits; fScale = 1; } + + void init(int dirNo, const SkString& filename) { + fDirNo = dirNo; + strcpy(fFilename, filename.c_str()); + fTestStep = kCompareBits; + fScale = 1; + } SkString status() { SkString outStr; @@ -262,14 +197,6 @@ struct TestResult { } - static void Test(int dirNo, const char* filename, TestStep testStep) { - TestResult test; - test.init(dirNo); - test.fTestStep = testStep; - strcpy(test.fFilename, filename); - test.testOne(); - } - void test(int dirNo, const SkString& filename) { init(dirNo); strcpy(fFilename, filename.c_str()); @@ -277,7 +204,7 @@ struct TestResult { } void testOne(); - + char fFilename[kMaxLength]; TestStep fTestStep; int fDirNo; @@ -308,28 +235,24 @@ public: }; struct TestState { - void init(int dirNo, skiatest::Reporter* reporter) { - fReporter = reporter; + void init(int dirNo) { fResult.init(dirNo); } SkTDArray<SortByPixel> fPixelWorst; SkTDArray<SortByTime> fSlowest; - skiatest::Reporter* fReporter; TestResult fResult; }; struct TestRunner { - TestRunner(skiatest::Reporter* reporter, int threadCount) - : fNumThreads(threadCount) - , fReporter(reporter) { + TestRunner(int threadCount) + : fNumThreads(threadCount) { } ~TestRunner(); void render(); int fNumThreads; SkTDArray<class TestRunnable*> fRunnables; - skiatest::Reporter* fReporter; }; class TestRunnable : public SkRunnable { @@ -347,7 +270,7 @@ public: class TestRunnableDir : public TestRunnable { public: TestRunnableDir(void (*testFun)(TestState*), int dirNo, TestRunner* runner) { - fState.init(dirNo, runner->fReporter); + fState.init(dirNo); fTestFun = testFun; } @@ -356,7 +279,7 @@ public: class TestRunnableFile : public TestRunnable { public: TestRunnableFile(void (*testFun)(TestState*), int dirNo, const char* name, TestRunner* runner) { - fState.init(dirNo, runner->fReporter); + fState.init(dirNo); strcpy(fState.fResult.fFilename, name); fTestFun = testFun; } @@ -385,74 +308,6 @@ void TestRunner::render() { //////////////////////////////////////////////// -static const char outOpDir[] = OUT_DIR "opClip"; -static const char outOldDir[] = OUT_DIR "oldClip"; -static const char outSkpDir[] = OUT_DIR "skpTest"; -static const char outDiffDir[] = OUT_DIR "outTest"; -static const char outStatusDir[] = OUT_DIR "statusTest"; - -static SkString make_filepath(int dirNo, const char* dir, const char* name) { - SkString path(dir); - if (dirNo) { - path.appendf("%d", dirNo); - } - path.append(PATH_SLASH); - path.append(name); - return path; -} - -static SkString make_in_dir_name(int dirNo) { - SkString dirName(IN_DIR); - dirName.appendf("%d", dirNo); - if (!sk_exists(dirName.c_str())) { - SkDebugf("could not read dir %s\n", dirName.c_str()); - return SkString(); - } - return dirName; -} - -static SkString make_stat_dir_name(int dirNo) { - SkString dirName(outStatusDir); - dirName.appendf("%d", dirNo); - if (!sk_exists(dirName.c_str())) { - SkDebugf("could not read dir %s\n", dirName.c_str()); - return SkString(); - } - return dirName; -} - -static bool make_one_out_dir(const char* outDirStr) { - SkString outDir = make_filepath(0, outDirStr, ""); - if (!sk_exists(outDir.c_str())) { - if (!sk_mkdir(outDir.c_str())) { - SkDebugf("could not create dir %s\n", outDir.c_str()); - return false; - } - } - return true; -} - -static bool make_out_dirs() { - SkString outDir = make_filepath(0, OUT_DIR, ""); - if (!sk_exists(outDir.c_str())) { - if (!sk_mkdir(outDir.c_str())) { - SkDebugf("could not create dir %s\n", outDir.c_str()); - return false; - } - } - return make_one_out_dir(outOldDir) - && make_one_out_dir(outOpDir) - && make_one_out_dir(outSkpDir) - && make_one_out_dir(outDiffDir) - && make_one_out_dir(outStatusDir); -} - -static SkString make_png_name(const char* filename) { - SkString pngName = SkString(filename); - pngName.remove(pngName.size() - 3, 3); - pngName.append("png"); - return pngName; -} static int similarBits(const SkBitmap& gr, const SkBitmap& sk) { const int kRowCount = 3; @@ -574,9 +429,9 @@ static void drawPict(SkPicture* pic, SkCanvas* canvas, int scale) { } static void writePict(const SkBitmap& bitmap, const char* outDir, const char* pngName) { - SkString outFile = make_filepath(0, outDir, pngName); - if (!SkImageEncoder::EncodeFile(outFile.c_str(), bitmap, - SkImageEncoder::kPNG_Type, 100)) { + SkString outFile = get_sum_path(outDir); + outFile.appendf("%s%s", PATH_SLASH, pngName); + if (!SkImageEncoder::EncodeFile(outFile.c_str(), bitmap, SkImageEncoder::kPNG_Type, 100)) { SkDebugf("unable to encode gr %s (width=%d height=%d)\n", pngName, bitmap.width(), bitmap.height()); } @@ -607,7 +462,7 @@ void TestResult::testOne() { strncpy(DEBUG_FILENAME_STRING, "", DEBUG_FILENAME_STRING_LENGTH); } #endif - SkString path = make_filepath(fDirNo, IN_DIR, fFilename); + SkString path = get_in_path(fDirNo, fFilename); SkFILEStream stream(path.c_str()); if (!stream.isValid()) { SkDebugf("invalid stream %s\n", path.c_str()); @@ -665,189 +520,255 @@ finish: } } -static SkString makeStatusString(int dirNo) { - SkString statName; - statName.printf("stats%d.txt", dirNo); - SkString statusFile = make_filepath(0, outStatusDir, statName.c_str()); - return statusFile; +DEFINE_string2(match, m, "PathOpsSkpClipThreaded", + "[~][^]substring[$] [...] of test name to run.\n" + "Multiple matches may be separated by spaces.\n" + "~ causes a matching test to always be skipped\n" + "^ requires the start of the test to match\n" + "$ requires the end of the test to match\n" + "^ and $ requires an exact match\n" + "If a test does not match any list entry,\n" + "it is skipped unless some list entry starts with ~"); +DEFINE_string2(dir, d, NULL, "range of directories (e.g., 1-100)"); +DEFINE_string2(skp, s, NULL, "skp to test"); +DEFINE_bool2(single, z, false, "run tests on a single thread internally."); +DEFINE_int32(testIndex, 0, "override local test index (PathOpsSkpClipOneOff only)."); +DEFINE_int32(threads, SkThreadPool::kThreadPerCore, + "Run threadsafe tests on a threadpool with this many threads."); +DEFINE_bool2(verbose, v, false, "enable verbose output."); + +static bool verbose() { + return FLAGS_verbose; +} + +static int getThreadCount() { + return FLAGS_single ? 1 : FLAGS_threads; } -class PreParser { +class Dirs { public: - PreParser(int dirNo, bool threaded) - : fDirNo(dirNo) - , fIndex(0) - , fThreaded(threaded) { - SkString statusPath = makeStatusString(dirNo); - if (!sk_exists(statusPath.c_str())) { - return; + Dirs() { + reset(); + sk_bzero(fRun, sizeof(fRun)); + fSet = false; + } + + int first() const { + int index = 0; + while (++index < kMaxDir) { + if (fRun[index]) { + return index; + } } - SkFILEStream reader; - reader.setPath(statusPath.c_str()); - while (fetch(reader, &fResults.push_back())) + SkASSERT(0); + return -1; + } + + int last() const { + int index = kMaxDir; + while (--index > 0 && !fRun[index]) ; - fResults.pop_back(); + return index; } - bool fetch(SkFILEStream& reader, TestResult* result) { - char c; - int i = 0; - result->init(fDirNo); - result->fPixelError = 0; - result->fTime = 0; - do { - bool readOne = reader.read(&c, 1) != 0; - if (!readOne) { -// SkASSERT(i == 0); // the current text may be incomplete -- if so, ignore it - return false; + int next() { + while (++fIndex < kMaxDir) { + if (fRun[fIndex]) { + return fIndex; } - if (c == ' ') { - result->fFilename[i++] = '\0'; - break; - } - result->fFilename[i++] = c; - SkASSERT(i < kMaxLength); - } while (true); - do { - if (!reader.read(&c, 1)) { - return false; - } - if (c == ' ') { - break; - } - SkASSERT(c >= '0' && c <= '9'); - result->fPixelError = result->fPixelError * 10 + (c - '0'); - } while (true); - bool minus = false; - do { - if (!reader.read(&c, 1)) { - return false; - } - if (c == '\n') { - break; - } - if (c == '-') { - minus = true; - continue; - } - SkASSERT(c >= '0' && c <= '9'); - result->fTime = result->fTime * 10 + (c - '0'); - } while (true); - if (minus) { - result->fTime = -result->fTime; } - return true; + return -1; } - bool match(const SkString& filename, SkFILEWStream* stream, TestResult* result) { - if (fThreaded) { - for (int index = 0; index < fResults.count(); ++index) { - const TestResult& test = fResults[index]; - if (filename.equals(test.fFilename)) { - *result = test; - SkString outStr(result->status()); - stream->write(outStr.c_str(), outStr.size()); - return true; - } - } - } else if (fIndex < fResults.count()) { - *result = fResults[fIndex++]; - SkASSERT(filename.equals(result->fFilename)); - SkString outStr(result->status()); - stream->write(outStr.c_str(), outStr.size()); - return true; + void reset() { + fIndex = -1; + } + + void set(int start, int end) { + while (start < end) { + fRun[start++] = 1; + } + fSet = true; + } + + void setDefault() { + if (!fSet) { + set(1, 100); } - return false; } private: - int fDirNo; + enum { + kMaxDir = 101 + }; + char fRun[kMaxDir]; int fIndex; - SkTArray<TestResult, true> fResults; - bool fThreaded; -}; + bool fSet; +} gDirs; + +class Filenames { +public: + Filenames() + : fIndex(-1) { + } + + const char* next() { + while (fNames && ++fIndex < fNames->count()) { + return (*fNames)[fIndex]; + } + return NULL; + } + + void set(const SkCommandLineFlags::StringArray& names) { + fNames = &names; + } + +private: + int fIndex; + const SkCommandLineFlags::StringArray* fNames; +} gNames; + +static bool buildTestDir(int dirNo, int firstDirNo, + SkTDArray<TestResult>* tests, SkTDArray<SortByName*>* sorted) { + SkString dirName = get_out_path(dirNo, outStatusDir); + if (!dirName.size()) { + return false; + } + SkOSFile::Iter iter(dirName.c_str(), "skp"); + SkString filename; + while (iter.next(&filename)) { + TestResult test; + test.init(dirNo); + SkString spaceFile(filename); + char* spaces = spaceFile.writable_str(); + int spaceSize = (int) spaceFile.size(); + for (int index = 0; index < spaceSize; ++index) { + if (spaces[index] == '.') { + spaces[index] = ' '; + } + } + int success = sscanf(spaces, "%s %d %d skp", test.fFilename, + &test.fPixelError, &test.fTime); + if (success < 3) { + SkDebugf("failed to scan %s matched=%d\n", filename.c_str(), success); + return false; + } + *tests[dirNo - firstDirNo].append() = test; + } + if (!sorted) { + return true; + } + SkTDArray<TestResult>& testSet = tests[dirNo - firstDirNo]; + int count = testSet.count(); + for (int index = 0; index < count; ++index) { + *sorted[dirNo - firstDirNo].append() = (SortByName*) &testSet[index]; + } + if (sorted[dirNo - firstDirNo].count()) { + SkTQSort<SortByName>(sorted[dirNo - firstDirNo].begin(), + sorted[dirNo - firstDirNo].end() - 1); + if (verbose()) { + SkDebugf("+"); + } + } + return true; +} + +static void testSkpClip(TestState* data) { + data->fResult.testOne(); + SkString statName(data->fResult.fFilename); + SkASSERT(statName.endsWith(".skp")); + statName.remove(statName.size() - 4, 4); + statName.appendf(".%d.%d.skp", data->fResult.fPixelError, data->fResult.fTime); + SkString statusFile = get_out_path(data->fResult.fDirNo, outStatusDir); + if (!statusFile.size()) { + SkDebugf("failed to create %s", statusFile.c_str()); + return; + } + statusFile.appendf("%s%s", PATH_SLASH, statName.c_str()); + SkFILE* file = sk_fopen(statusFile.c_str(), kWrite_SkFILE_Flag); + if (!file) { + SkDebugf("failed to create %s", statusFile.c_str()); + return; + } + sk_fclose(file); + if (verbose()) { + if (data->fResult.fPixelError || data->fResult.fTime) { + SkDebugf("%s", data->fResult.progress().c_str()); + } else { + SkDebugf("."); + } + } +} + +bool Less(const SortByName& a, const SortByName& b); +bool Less(const SortByName& a, const SortByName& b) { + return a < b; +} static bool doOneDir(TestState* state, bool threaded) { int dirNo = state->fResult.fDirNo; - skiatest::Reporter* reporter = state->fReporter; - SkString dirName = make_in_dir_name(dirNo); + SkString dirName = get_in_path(dirNo, NULL); if (!dirName.size()) { return false; } + SkTDArray<TestResult> tests[1]; + SkTDArray<SortByName*> sorted[1]; + if (!buildTestDir(dirNo, dirNo, tests, sorted)) { + return false; + } SkOSFile::Iter iter(dirName.c_str(), "skp"); SkString filename; - int testCount = 0; - PreParser preParser(dirNo, threaded); - SkFILEWStream statusStream(makeStatusString(dirNo).c_str()); while (iter.next(&filename)) { - for (size_t index = 0; index < skipOverSeptCount; ++index) { - if (skipOverSept[index].directory == dirNo - && strcmp(filename.c_str(), skipOverSept[index].filename) == 0) { + for (size_t index = 0; index < skipOverCount; ++index) { + if (skipOver[index].directory == dirNo + && strcmp(filename.c_str(), skipOver[index].filename) == 0) { goto checkEarlyExit; } } - if (preParser.match(filename, &statusStream, &state->fResult)) { - (void) addError(state, state->fResult); - ++testCount; - goto checkEarlyExit; - } { - TestResult& result = state->fResult; - result.test(dirNo, filename); - SkString outStr(result.status()); - statusStream.write(outStr.c_str(), outStr.size()); - statusStream.flush(); - if (addError(state, result)) { - SkDebugf("%s", result.progress().c_str()); + SortByName name; + name.init(dirNo); + strncpy(name.fFilename, filename.c_str(), filename.size() - 4); // drop .skp + int count = sorted[0].count(); + int idx = SkTSearch<SortByName, Less>(sorted[0].begin(), count, &name, sizeof(&name)); + if (idx >= 0) { + SortByName* found = sorted[0][idx]; + (void) addError(state, *found); + continue; } - } - ++testCount; - if (reporter->verbose()) { - SkDebugf("."); - if (++testCount % 100 == 0) { - SkDebugf("%d\n", testCount); + TestResult test; + test.init(dirNo, filename); + state->fResult = test; + testSkpClip(state); +#if 0 // artificially limit to a few while debugging code + static int debugLimit = 0; + if (++debugLimit == 5) { + return true; } +#endif } checkEarlyExit: - if (0 && testCount >= 1) { - return true; - } + ; } return true; } -static bool initTest() { +static void initTest() { #if !defined SK_BUILD_FOR_WIN && !defined SK_BUILD_FOR_MAC SK_CONF_SET("images.jpeg.suppressDecoderWarnings", true); SK_CONF_SET("images.png.suppressDecoderWarnings", true); #endif - return make_out_dirs(); } -static bool initUberTest(int firstDirNo, int lastDirNo) { - if (!initTest()) { - return false; - } - for (int index = firstDirNo; index <= lastDirNo; ++index) { - SkString statusDir(outStatusDir); - statusDir.appendf("%d", index); - if (!make_one_out_dir(statusDir.c_str())) { - return false; - } - } - return true; -} - - static void testSkpClipEncode(TestState* data) { data->fResult.testOne(); - if (data->fReporter->verbose()) { - SkDebugf("+"); + if (verbose()) { + SkDebugf("+"); } } -static void encodeFound(skiatest::Reporter* reporter, TestState& state) { - if (reporter->verbose()) { +static void encodeFound(TestState& state) { + if (verbose()) { if (state.fPixelWorst.count()) { SkTDArray<SortByPixel*> worst; for (int index = 0; index < state.fPixelWorst.count(); ++index) { @@ -873,9 +794,8 @@ static void encodeFound(skiatest::Reporter* reporter, TestState& state) { } } } - - int threadCount = reporter->allowThreaded() ? SkThreadPool::kThreadPerCore : 1; - TestRunner testRunner(reporter, threadCount); + int threadCount = getThreadCount(); + TestRunner testRunner(threadCount); for (int index = 0; index < state.fPixelWorst.count(); ++index) { const TestResult& result = state.fPixelWorst[index]; SkString filename(result.fFilename); @@ -886,28 +806,50 @@ static void encodeFound(skiatest::Reporter* reporter, TestState& state) { (&testSkpClipEncode, result.fDirNo, filename.c_str(), &testRunner)); } testRunner.render(); -#if 0 - for (int index = 0; index < state.fPixelWorst.count(); ++index) { - const TestResult& result = state.fPixelWorst[index]; - SkString filename(result.fFilename); - if (!filename.endsWith(".skp")) { - filename.append(".skp"); - } - TestResult::Test(result.fDirNo, filename.c_str(), kEncodeFiles); - if (reporter->verbose()) SkDebugf("+"); - } -#endif } -DEF_TEST(PathOpsSkpClip, reporter) { - if (!initTest()) { - return; - } +class Test { +public: + Test() {} + virtual ~Test() {} + + const char* getName() { onGetName(&fName); return fName.c_str(); } + void run() { onRun(); } + +protected: + virtual void onGetName(SkString*) = 0; + virtual void onRun() = 0; + +private: + SkString fName; +}; + +typedef SkTRegistry<Test*(*)(void*)> TestRegistry; + +#define DEF_TEST(name) \ + static void test_##name(); \ + class name##Class : public Test { \ + public: \ + static Test* Factory(void*) { return SkNEW(name##Class); } \ + protected: \ + virtual void onGetName(SkString* name) SK_OVERRIDE { \ + name->set(#name); \ + } \ + virtual void onRun() SK_OVERRIDE { test_##name(); } \ + }; \ + static TestRegistry gReg_##name##Class(name##Class::Factory); \ + static void test_##name() + +DEF_TEST(PathOpsSkpClip) { + gDirs.setDefault(); + initTest(); SkTArray<TestResult, true> errors; TestState state; - state.init(0, reporter); - for (int dirNo = 1; dirNo <= 100; ++dirNo) { - if (reporter->verbose()) { + state.init(0); + int dirNo; + gDirs.reset(); + while ((dirNo = gDirs.next()) > 0) { + if (verbose()) { SkDebugf("dirNo=%d\n", dirNo); } state.fResult.fDirNo = dirNo; @@ -915,28 +857,29 @@ DEF_TEST(PathOpsSkpClip, reporter) { break; } } - encodeFound(reporter, state); + encodeFound(state); } static void testSkpClipMain(TestState* data) { (void) doOneDir(data, true); } -DEF_TEST(PathOpsSkpClipThreaded, reporter) { - if (!initTest()) { - return; - } - int threadCount = reporter->allowThreaded() ? SkThreadPool::kThreadPerCore : 1; - TestRunner testRunner(reporter, threadCount); - const int firstDirNo = 1; - for (int dirNo = firstDirNo; dirNo <= 100; ++dirNo) { +DEF_TEST(PathOpsSkpClipThreaded) { + gDirs.setDefault(); + initTest(); + int threadCount = getThreadCount(); + TestRunner testRunner(threadCount); + int dirNo; + gDirs.reset(); + while ((dirNo = gDirs.next()) > 0) { *testRunner.fRunnables.append() = SkNEW_ARGS(TestRunnableDir, (&testSkpClipMain, dirNo, &testRunner)); } testRunner.render(); TestState state; - state.init(0, reporter); - for (int dirNo = firstDirNo; dirNo <= 100; ++dirNo) { + state.init(0); + gDirs.reset(); + while ((dirNo = gDirs.next()) > 0) { TestState& testState = testRunner.fRunnables[dirNo - 1]->fState; SkASSERT(testState.fResult.fDirNo == dirNo); for (int inner = 0; inner < testState.fPixelWorst.count(); ++inner) { @@ -946,124 +889,59 @@ DEF_TEST(PathOpsSkpClipThreaded, reporter) { addError(&state, testState.fSlowest[inner]); } } - encodeFound(reporter, state); -} - -static void testSkpClipUber(TestState* data) { - data->fResult.testOne(); - SkString dirName = make_stat_dir_name(data->fResult.fDirNo); - if (!dirName.size()) { - return; - } - SkString statName(data->fResult.fFilename); - SkASSERT(statName.endsWith(".skp")); - statName.remove(statName.size() - 4, 4); - statName.appendf(".%d.%d.skp", data->fResult.fPixelError, data->fResult.fTime); - SkString statusFile = make_filepath(data->fResult.fDirNo, outStatusDir, statName.c_str()); - SkFILE* file = sk_fopen(statusFile.c_str(), kWrite_SkFILE_Flag); - if (!file) { - SkDebugf("failed to create %s", statusFile.c_str()); - return; - } - sk_fclose(file); - if (data->fReporter->verbose()) { - if (data->fResult.fPixelError || data->fResult.fTime) { - SkDebugf("%s", data->fResult.progress().c_str()); - } else { - SkDebugf("."); - } - } + encodeFound(state); } - -static bool buildTests(skiatest::Reporter* reporter, int firstDirNo, int lastDirNo, SkTDArray<TestResult>* tests, - SkTDArray<SortByName*>* sorted) { - for (int dirNo = firstDirNo; dirNo <= lastDirNo; ++dirNo) { - SkString dirName = make_stat_dir_name(dirNo); - if (!dirName.size()) { + +static bool buildTests(SkTDArray<TestResult>* tests, SkTDArray<SortByName*>* sorted) { + int firstDirNo = gDirs.first(); + int dirNo; + while ((dirNo = gDirs.next()) > 0) { + if (!buildTestDir(dirNo, firstDirNo, tests, sorted)) { return false; } - SkOSFile::Iter iter(dirName.c_str(), "skp"); - SkString filename; - while (iter.next(&filename)) { - TestResult test; - test.init(dirNo); - SkString spaceFile(filename); - char* spaces = spaceFile.writable_str(); - int spaceSize = (int) spaceFile.size(); - for (int index = 0; index < spaceSize; ++index) { - if (spaces[index] == '.') { - spaces[index] = ' '; - } - } - int success = sscanf(spaces, "%s %d %d skp", test.fFilename, - &test.fPixelError, &test.fTime); - if (success < 3) { - SkDebugf("failed to scan %s matched=%d\n", filename.c_str(), success); - return false; - } - *tests[dirNo - firstDirNo].append() = test; - } - if (!sorted) { - continue; - } - SkTDArray<TestResult>& testSet = tests[dirNo - firstDirNo]; - int count = testSet.count(); - for (int index = 0; index < count; ++index) { - *sorted[dirNo - firstDirNo].append() = (SortByName*) &testSet[index]; - } - if (sorted[dirNo - firstDirNo].count()) { - SkTQSort<SortByName>(sorted[dirNo - firstDirNo].begin(), - sorted[dirNo - firstDirNo].end() - 1); - if (reporter->verbose()) { - SkDebugf("+"); - } - } } return true; } -bool Less(const SortByName& a, const SortByName& b); -bool Less(const SortByName& a, const SortByName& b) { - return a < b; -} - -DEF_TEST(PathOpsSkpClipUberThreaded, reporter) { - const int firstDirNo = 1; - const int lastDirNo = 100; - if (!initUberTest(firstDirNo, lastDirNo)) { +DEF_TEST(PathOpsSkpClipUberThreaded) { + gDirs.setDefault(); + const int firstDirNo = gDirs.next(); + const int lastDirNo = gDirs.last(); + initTest(); + int dirCount = lastDirNo - firstDirNo + 1; + SkAutoTDeleteArray<SkTDArray<TestResult> > tests(new SkTDArray<TestResult>[dirCount]); + SkAutoTDeleteArray<SkTDArray<SortByName*> > sorted(new SkTDArray<SortByName*>[dirCount]); + if (!buildTests(tests.get(), sorted.get())) { return; } - const int dirCount = lastDirNo - firstDirNo + 1; - SkTDArray<TestResult> tests[dirCount]; - SkTDArray<SortByName*> sorted[dirCount]; - if (!buildTests(reporter, firstDirNo, lastDirNo, tests, sorted)) { - return; - } - int threadCount = reporter->allowThreaded() ? SkThreadPool::kThreadPerCore : 1; - TestRunner testRunner(reporter, threadCount); - for (int dirNo = firstDirNo; dirNo <= lastDirNo; ++dirNo) { - SkString dirName = make_in_dir_name(dirNo); + int threadCount = getThreadCount(); + TestRunner testRunner(threadCount); + int dirNo; + gDirs.reset(); + while ((dirNo = gDirs.next()) > 0) { + SkString dirName = get_in_path(dirNo, NULL); if (!dirName.size()) { continue; } SkOSFile::Iter iter(dirName.c_str(), "skp"); SkString filename; while (iter.next(&filename)) { - int count; - SortByName name; - for (size_t index = 0; index < skipOverSeptCount; ++index) { - if (skipOverSept[index].directory == dirNo - && strcmp(filename.c_str(), skipOverSept[index].filename) == 0) { + for (size_t index = 0; index < skipOverCount; ++index) { + if (skipOver[index].directory == dirNo + && strcmp(filename.c_str(), skipOver[index].filename) == 0) { goto checkEarlyExit; } } - name.init(dirNo); - strncpy(name.fFilename, filename.c_str(), filename.size() - 4); // drop .skp - count = sorted[dirNo - firstDirNo].count(); - if (SkTSearch<SortByName, Less>(sorted[dirNo - firstDirNo].begin(), - count, &name, sizeof(&name)) < 0) { - *testRunner.fRunnables.append() = SkNEW_ARGS(TestRunnableFile, - (&testSkpClipUber, dirNo, filename.c_str(), &testRunner)); + { + SortByName name; + name.init(dirNo); + strncpy(name.fFilename, filename.c_str(), filename.size() - 4); // drop .skp + int count = sorted.get()[dirNo - firstDirNo].count(); + if (SkTSearch<SortByName, Less>(sorted.get()[dirNo - firstDirNo].begin(), + count, &name, sizeof(&name)) < 0) { + *testRunner.fRunnables.append() = SkNEW_ARGS(TestRunnableFile, + (&testSkpClip, dirNo, filename.c_str(), &testRunner)); + } } checkEarlyExit: ; @@ -1071,13 +949,13 @@ DEF_TEST(PathOpsSkpClipUberThreaded, reporter) { } testRunner.render(); - SkTDArray<TestResult> results[dirCount]; - if (!buildTests(reporter, firstDirNo, lastDirNo, results, NULL)) { + SkAutoTDeleteArray<SkTDArray<TestResult> > results(new SkTDArray<TestResult>[dirCount]); + if (!buildTests(results.get(), NULL)) { return; } SkTDArray<TestResult> allResults; for (int dirNo = firstDirNo; dirNo <= lastDirNo; ++dirNo) { - SkTDArray<TestResult>& array = results[dirNo - firstDirNo]; + SkTDArray<TestResult>& array = results.get()[dirNo - firstDirNo]; allResults.append(array.count(), array.begin()); } int allCount = allResults.count(); @@ -1100,22 +978,144 @@ DEF_TEST(PathOpsSkpClipUberThreaded, reporter) { *state.fSlowest.append() = *times[allCount - inner - 1]; } } - encodeFound(reporter, state); + encodeFound(state); } -DEF_TEST(PathOpsSkpClipOneOff, reporter) { - if (!initTest()) { - return; +DEF_TEST(PathOpsSkpClipOneOff) { + const int testIndex = FLAGS_testIndex; + int dirNo = gDirs.next(); + if (dirNo < 0) { + dirNo = skipOver[testIndex].directory; + } + const char* skp = gNames.next(); + if (!skp) { + skp = skipOver[testIndex].filename; } - const int testIndex = 43 - 37; - int dirNo = skipOverSept[testIndex].directory; - SkAssertResult(make_in_dir_name(dirNo).size()); - SkString filename(skipOverSept[testIndex].filename); + initTest(); + SkAssertResult(get_in_path(dirNo, skp).size()); + SkString filename(skp); TestResult state; state.test(dirNo, filename); - if (reporter->verbose()) { + if (verbose()) { SkDebugf("%s", state.status().c_str()); } state.fTestStep = kEncodeFiles; state.testOne(); } + +DEF_TEST(PathOpsTestSkipped) { + for (size_t index = 0; index < skipOverCount; ++index) { + const SkipOverTest& skip = skipOver[index]; + if (!skip.blamePathOps) { + continue; + } + int dirNo = skip.directory; + const char* skp = skip.filename; + initTest(); + SkAssertResult(get_in_path(dirNo, skp).size()); + SkString filename(skp); + TestResult state; + state.test(dirNo, filename); + if (verbose()) { + SkDebugf("%s", state.status().c_str()); + } + state.fTestStep = kEncodeFiles; + state.testOne(); + } +} + +DEF_TEST(PathOpsCopyFails) { + FLAGS_verbose = true; + for (size_t index = 0; index < skipOverCount; ++index) { + int dirNo = skipOver[index].directory; + SkDebugf("mkdir -p " IN_DIR_PRE "%d" DIR_POST "\n", dirNo); + } + for (size_t index = 0; index < skipOverCount; ++index) { + int dirNo = skipOver[index].directory; + const char* filename = skipOver[index].filename; + SkDebugf("rsync -av cary-linux.cnc:/tera" PATH_SLASH "skps" PATH_SLASH "slave" + "%d" DIR_POST "/%s " IN_DIR_PRE "%d" DIR_POST "\n", dirNo, filename, dirNo); + } +} + +template TestRegistry* TestRegistry::gHead; + +class Iter { +public: + Iter() { this->reset(); } + void reset() { fReg = TestRegistry::Head(); } + + Test* next() { + if (fReg) { + TestRegistry::Factory fact = fReg->factory(); + fReg = fReg->next(); + Test* test = fact(NULL); + return test; + } + return NULL; + } + +private: + const TestRegistry* fReg; +}; + +int tool_main(int argc, char** argv); +int tool_main(int argc, char** argv) { + SetupCrashHandler(); + SkCommandLineFlags::SetUsage(""); + SkCommandLineFlags::Parse(argc, argv); + SkGraphics::Init(); + SkString header("PathOps SkpClip:"); + if (!FLAGS_match.isEmpty()) { + header.appendf(" --match"); + for (int index = 0; index < FLAGS_match.count(); ++index) { + header.appendf(" %s", FLAGS_match[index]); + } + } + if (!FLAGS_dir.isEmpty()) { + int count = FLAGS_dir.count(); + for (int i = 0; i < count; ++i) { + const char* range = FLAGS_dir[i]; + const char* dash = strchr(range, '-'); + if (!dash) { + dash = strchr(range, ','); + } + int first = atoi(range); + int last = dash ? atoi(dash + 1) : first; + if (!first || !last) { + SkDebugf("couldn't parse --dir %s\n", range); + return 1; + } + gDirs.set(first, last); + } + } + if (!FLAGS_skp.isEmpty()) { + gNames.set(FLAGS_skp); + } +#ifdef SK_DEBUG + header.append(" SK_DEBUG"); +#else + header.append(" SK_RELEASE"); +#endif + header.appendf(" skia_arch_width=%d", (int)sizeof(void*) * 8); + if (FLAGS_verbose) { + header.appendf("\n"); + } + SkDebugf(header.c_str()); + Iter iter; + Test* test; + while ((test = iter.next()) != NULL) { + SkAutoTDelete<Test> owned(test); + if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, test->getName())) { + test->run(); + } + } + SkGraphics::Term(); + return 0; +} + +#if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL) +int main(int argc, char * const argv[]) { + return tool_main(argc, (char**) argv); +} +#endif diff --git a/tests/PathOpsSkpTest.cpp b/tests/PathOpsSkpTest.cpp index d62e326278..2da38f4166 100755 --- a/tests/PathOpsSkpTest.cpp +++ b/tests/PathOpsSkpTest.cpp @@ -8,6 +8,8 @@ #define TEST(name) { name, #name } +#define TEST_NEW_FAILURES 0 + static void skpcheeseandburger_com225(skiatest::Reporter* reporter, const char* filename) { SkPath path; path.setFillType(SkPath::kEvenOdd_FillType); @@ -3547,9 +3549,233 @@ static void skpwww_mortgagemarketguide_com_109(skiatest::Reporter* reporter, con testPathOp(reporter, path, pathB, kIntersect_PathOp, filename); } +static void skpwww_9to5mac_com_64(skiatest::Reporter* reporter, const char* filename) { + SkPath path; + path.setFillType(SkPath::kEvenOdd_FillType); + path.moveTo(365, 5101); + path.lineTo(365, 5082); + path.lineTo(366, 5083); + path.lineTo(367, 5092.96631f); + path.lineTo(367, 5100); + path.quadTo(367, 5101.50537f, 367.967712f, 5102.61084f); + path.lineTo(368.278717f, 5105.71045f); + path.quadTo(367.277618f, 5105.34863f, 366.464478f, 5104.53564f); + path.quadTo(365, 5103.07129f, 365, 5101); + path.close(); + SkPath pathB; + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(365, 5082); + pathB.lineTo(365.848175f, 5081.15186f); + pathB.lineTo(368, 5103); + pathB.lineTo(365, 5106); + testPathOp(reporter, path, pathB, kIntersect_PathOp, filename); +} + +#if TEST_NEW_FAILURES +// addTCoincident SkASSERT(test->fT < 1); +static void skpwww_googleventures_com_32(skiatest::Reporter* reporter, const char* filename) { + SkPath path; + path.setFillType(SkPath::kEvenOdd_FillType); + path.moveTo(725.911682f, 898.767456f); + path.lineTo(741.232544f, 885.911682f); + path.lineTo(754.088318f, 901.232544f); + path.lineTo(738.767456f, 914.088318f); + path.lineTo(725.911682f, 898.767456f); + path.close(); + SkPath pathB; + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(728.37677f, 870.59082f); + pathB.lineTo(754.088257f, 901.232605f); + pathB.lineTo(738.767395f, 914.088379f); + pathB.lineTo(713.055908f, 883.446594f); + pathB.close(); + testPathOp(reporter, path, pathB, kIntersect_PathOp, filename); +} + +// checkSmallCoincidence failed assertion "!next->fSmall || checkMultiple" +static void skpwww_devbridge_com_22(skiatest::Reporter* reporter, const char* filename) { + SkPath path; + path.setFillType(SkPath::kEvenOdd_FillType); + path.moveTo(4915, 1523); + path.quadTo(4887.24756f, 1523, 4867.62402f, 1542.6239f); + path.quadTo(4848, 1562.24768f, 4848, 1590); + path.quadTo(4848, 1617.75232f, 4867.62402f, 1637.3761f); + path.quadTo(4887.24756f, 1657, 4915, 1657); + path.quadTo(4942.75244f, 1657, 4962.37598f, 1637.3761f); + path.quadTo(4982, 1617.75232f, 4982, 1590); + path.quadTo(4982, 1562.24768f, 4962.37598f, 1542.6239f); + path.quadTo(4942.75244f, 1523, 4915, 1523); + path.close(); + SkPath pathB; + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(4981.99902f, 1590); + pathB.quadTo(4981.99902f, 1617.75232f, 4962.375f, 1637.3761f); + pathB.quadTo(4942.75146f, 1657, 4914.99902f, 1657); + pathB.quadTo(4887.24658f, 1657, 4867.62305f, 1637.3761f); + pathB.quadTo(4847.99902f, 1617.75232f, 4847.99902f, 1590); + pathB.quadTo(4847.99902f, 1562.24768f, 4867.62305f, 1542.6239f); + pathB.quadTo(4887.24658f, 1523, 4914.99902f, 1523); + pathB.quadTo(4942.75146f, 1523, 4962.375f, 1542.6239f); + pathB.quadTo(4981.99902f, 1562.24768f, 4981.99902f, 1590); + pathB.close(); + testPathOp(reporter, path, pathB, kIntersect_PathOp, filename); +} + +// cubic/quad intersection +static void skpwww_alamdi_com_3(skiatest::Reporter* reporter, const char* filename) { + SkPath path; + path.setFillType(SkPath::kEvenOdd_FillType); + path.moveTo(10210.8789f, 5315.87891f); + path.quadTo(10211.7578f, 5315, 10213, 5315); + path.lineTo(10230, 5315); + path.quadTo(10231.2422f, 5315, 10232.1211f, 5315.87891f); + path.quadTo(10233, 5316.75732f, 10233, 5318); + path.lineTo(10233, 5338); + path.quadTo(10233, 5339.24268f, 10232.1211f, 5340.12109f); + path.quadTo(10231.2422f, 5341, 10230, 5341); + path.lineTo(10213, 5341); + path.quadTo(10211.7578f, 5341, 10210.8789f, 5340.12109f); + path.quadTo(10210, 5339.24268f, 10210, 5338); + path.lineTo(10210, 5318); + path.quadTo(10210, 5316.75732f, 10210.8789f, 5315.87891f); + path.close(); + SkPath pathB; + pathB.setFillType(SkPath::kEvenOdd_FillType); + pathB.moveTo(10213, 5315); + pathB.lineTo(10230, 5315); + pathB.cubicTo(10231.6572f, 5315, 10233, 5316.34326f, 10233, 5318); + pathB.lineTo(10233, 5338); + pathB.cubicTo(10233, 5339.10449f, 10231.6572f, 5340, 10230, 5340); + pathB.lineTo(10213, 5340); + pathB.cubicTo(10211.3428f, 5340, 10210, 5339.10449f, 10210, 5338); + pathB.lineTo(10210, 5318); + pathB.cubicTo(10210, 5316.34326f, 10211.3428f, 5315, 10213, 5315); + pathB.close(); + testPathOp(reporter, path, pathB, kIntersect_PathOp, filename); +} + +// bumpSpan failed assertion "span->fOppValue >= 0" +static void skpwww_familysurvivalprotocol_wordpress_com_61(skiatest::Reporter* reporter, const char* filename) { + SkPath path; + path.setFillType(SkPath::kEvenOdd_FillType); + path.moveTo(143, 14557); + path.lineTo(165, 14557); + path.lineTo(165, 14555.9902f); + path.lineTo(143, 14556); + path.lineTo(143, 14557); + path.close(); + SkPath pathB; + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(143, 14557); + pathB.lineTo(143, 14555.9902f); + pathB.lineTo(165, 14556); + pathB.lineTo(165, 14557); + testPathOp(reporter, path, pathB, kIntersect_PathOp, filename); +} + +// addTCancel: failed assertion "oIndex > 0" +static void skpwww_firstunitedbank_com_19(skiatest::Reporter* reporter, const char* filename) { + SkPath path; + path.setFillType(SkPath::kEvenOdd_FillType); + path.moveTo(808.585815f, 11673.5859f); + path.quadTo(809.17157f, 11673, 810, 11673); + path.lineTo(1032, 11673); + path.quadTo(1038.21326f, 11673, 1042.60657f, 11677.3936f); + path.quadTo(1047, 11681.7871f, 1047, 11688); + path.quadTo(1047, 11682.2012f, 1042.60657f, 11678.1006f); + path.quadTo(1038.21326f, 11674, 1032, 11674); + path.lineTo(810, 11674); + path.quadTo(809.585815f, 11674, 809.292908f, 11674.293f); + path.quadTo(809, 11674.5859f, 809, 11675); + path.lineTo(809, 11701); + path.quadTo(809, 11701.4141f, 809.292908f, 11701.707f); + path.quadTo(809.585815f, 11702, 810, 11702); + path.lineTo(1032, 11702); + path.quadTo(1038.21326f, 11702, 1042.60657f, 11697.8994f); + path.quadTo(1047, 11693.7988f, 1047, 11688); + path.quadTo(1047, 11694.2129f, 1042.60657f, 11698.6064f); + path.quadTo(1038.21326f, 11703, 1032, 11703); + path.lineTo(810, 11703); + path.quadTo(809.17157f, 11703, 808.585815f, 11702.4141f); + path.quadTo(808, 11701.8281f, 808, 11701); + path.lineTo(808, 11675); + path.quadTo(808, 11674.1719f, 808.585815f, 11673.5859f); + path.close(); + SkPath pathB; + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(808, 11703); + pathB.lineTo(809.5f, 11701.5f); + pathB.lineTo(1062.91907f, 11687.0811f); + pathB.lineTo(1047, 11703); + testPathOp(reporter, path, pathB, kIntersect_PathOp, filename); +} +#endif + +// addSimpleAngle: failed assertion "index == count() - 2" +static void skpwww_shinydemos_com_5(skiatest::Reporter* reporter, const char* filename) { + SkPath path; + path.setFillType(SkPath::kEvenOdd_FillType); + path.moveTo(205.884888f, 648.203857f); + path.lineTo(771.570374f, 82.5183716f); + path.lineTo(1110.98169f, 421.929626f); + path.lineTo(545.296143f, 987.615112f); + path.lineTo(205.884888f, 648.203857f); + path.close(); + SkPath pathB; + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(771.570374f, 82.5183716f); + pathB.lineTo(1110.98169f, 421.929626f); + pathB.lineTo(545.296204f, 987.615051f); + pathB.lineTo(205.884949f, 648.203796f); + pathB.close(); + testPathOp(reporter, path, pathB, kIntersect_PathOp, filename); +} + +// addTCoincident oPeek = &other->fTs[++oPeekIndex]; +static void skpwww_lptemp_com_3(skiatest::Reporter* reporter, const char* filename) { + SkPath path; + path.setFillType(SkPath::kEvenOdd_FillType); + path.moveTo(78.6429825f, 1394.30969f); + path.quadTo(79.6192932f, 1393.33337f, 81.0000076f, 1393.33337f); + path.lineTo(341, 1393.33337f); + path.quadTo(342.380707f, 1393.33337f, 343.357025f, 1394.30969f); + path.quadTo(344.333344f, 1395.28601f, 344.333344f, 1396.66675f); + path.lineTo(344.333344f, 1465.66663f); + path.quadTo(344.333344f, 1467.04736f, 343.357025f, 1468.02368f); + path.quadTo(342.380707f, 1469, 341, 1469); + path.lineTo(81.0000076f, 1469); + path.quadTo(79.6192932f, 1469, 78.6429825f, 1468.02368f); + path.quadTo(77.6666718f, 1467.04736f, 77.6666718f, 1465.66663f); + path.lineTo(77.6666718f, 1396.66675f); + path.quadTo(77.6666718f, 1395.28601f, 78.6429825f, 1394.30969f); + path.close(); + SkPath pathB; + pathB.setFillType(SkPath::kEvenOdd_FillType); + pathB.moveTo(81, 1393.33337f); + pathB.lineTo(341, 1393.33337f); + pathB.cubicTo(342.840942f, 1393.33337f, 344.333344f, 1394.82568f, 344.333344f, 1396.66675f); + pathB.lineTo(344.333344f, 1465.66675f); + pathB.cubicTo(344.333344f, 1467.32361f, 342.840942f, 1468.66675f, 341, 1468.66675f); + pathB.lineTo(81, 1468.66675f); + pathB.cubicTo(79.15905f, 1468.66675f, 77.6666718f, 1467.32361f, 77.6666718f, 1465.66675f); + pathB.lineTo(77.6666718f, 1396.66675f); + pathB.cubicTo(77.6666718f, 1394.82568f, 79.15905f, 1393.33337f, 81, 1393.33337f); + pathB.close(); + testPathOp(reporter, path, pathB, kIntersect_PathOp, filename); +} + static void (*firstTest)(skiatest::Reporter* , const char* filename) = 0; static struct TestDesc tests[] = { + TEST(skpwww_lptemp_com_3), + TEST(skpwww_shinydemos_com_5), +#if TEST_NEW_FAILURES + TEST(skpwww_familysurvivalprotocol_wordpress_com_61), + TEST(skpwww_alamdi_com_3), + TEST(skpwww_devbridge_com_22), + TEST(skpwww_googleventures_com_32), +#endif + TEST(skpwww_9to5mac_com_64), TEST(skpwww_wartepop_blogspot_com_br_6), TEST(skpwww_wartepop_blogspot_com_br_6a), TEST(skpwww_cooksnaps_com_32a), diff --git a/tools/pathops_sorter.htm b/tools/pathops_sorter.htm index aac151af21..79a2c16955 100644 --- a/tools/pathops_sorter.htm +++ b/tools/pathops_sorter.htm @@ -953,11 +953,17 @@ op intersect {{{1020, 672}, {1020, 640.93395999999996}, {998.03301999999996, 618.96698000000004}}} </div> +<div id="skpwww_9to5mac_com_64"> +{{{{365.848175,5081.15186}, {368,5103}}}, +{{{367.967712,5102.61084}, {368.278717,5105.71045}}}}, +</div> + </div> <script type="text/javascript"> var testDivs = [ + skpwww_9to5mac_com_64, skpcarrot_is24x, skpwww_wartepop_blogspot_com_br_6, skpwww_wartepop_blogspot_com_br_6a, diff --git a/tools/pathops_visualizer.htm b/tools/pathops_visualizer.htm index 9872b38682..7c109ee3e1 100644 --- a/tools/pathops_visualizer.htm +++ b/tools/pathops_visualizer.htm @@ -2,85 +2,139 @@ <head> <div height="0" hidden="true"> -<div id="skpwww_argus_presse_fr_41"> - RunTestSet [skpwww_argus_presse_fr_41] - -{{1000,343}, {165,343}}, -{{165,343}, {165,364.869873}}, -{{165,364.869873}, {1000,364.869873}}, -{{1000,364.869873}, {1000,343}}, -op intersect -{{165,343.000031}, {1000,343.000031}}, -{{1000,343.000031}, {1000,364.869904}}, -{{1000,364.869904}, {165,364.869904}}, -{{165,364.869904}, {165,343.000031}}, -debugShowLineIntersection wtTs[0]=0 {{165,343}, {165,364.869873}} {{165,343}} wnTs[0]=1 {{1000,343}, {165,343}} -debugShowLineIntersection wtTs[0]=1 {{1000,364.869873}, {1000,343}} {{1000,343}} wnTs[0]=0 {{1000,343}, {165,343}} -debugShowLineIntersection wtTs[0]=0 {{165,364.869873}, {1000,364.869873}} {{165,364.869873}} wnTs[0]=1 {{165,343}, {165,364.869873}} -debugShowLineIntersection wtTs[0]=0 {{1000,364.869873}, {1000,343}} {{1000,364.869873}} wnTs[0]=1 {{165,364.869873}, {1000,364.869873}} -debugShowLineIntersection wtTs[0]=0 {{165,343.000031}, {1000,343.000031}} {{165,343}} wtTs[1]=1 {{1000,343}} wnTs[0]=1 {{1000,343}, {165,343}} wnTs[1]=0 -debugShowLineIntersection wtTs[0]=0 {{1000,343.000031}, {1000,364.869904}} {{1000,343.000031}} wnTs[0]=0 {{1000,343}, {165,343}} -debugShowLineIntersection wtTs[0]=1 {{165,364.869904}, {165,343.000031}} {{165,343.000031}} wnTs[0]=1 {{1000,343}, {165,343}} -debugShowLineIntersection wtTs[0]=0 {{165,343.000031}, {1000,343.000031}} {{165,343}} wnTs[0]=0 {{165,343}, {165,364.869873}} -debugShowLineIntersection wtTs[0]=1 {{1000,364.869904}, {165,364.869904}} {{165,364.869873}} wnTs[0]=1 {{165,343}, {165,364.869873}} -debugShowLineIntersection wtTs[0]=0 {{165,364.869904}, {165,343.000031}} {{165,364.869904}} wtTs[1]=1 {{165,343.000031}} wnTs[0]=1 {{165,343}, {165,364.869873}} wnTs[1]=1.39541634e-006 -debugShowLineIntersection wtTs[0]=1 {{1000,343.000031}, {1000,364.869904}} {{1000,364.869904}} wnTs[0]=1 {{165,364.869873}, {1000,364.869873}} -debugShowLineIntersection wtTs[0]=0 {{1000,364.869904}, {165,364.869904}} {{1000,364.869873}} wtTs[1]=1 {{165,364.869873}} wnTs[0]=1 {{165,364.869873}, {1000,364.869873}} wnTs[1]=0 -debugShowLineIntersection wtTs[0]=0 {{165,364.869904}, {165,343.000031}} {{165,364.869904}} wnTs[0]=0 {{165,364.869873}, {1000,364.869873}} -debugShowLineIntersection wtTs[0]=1 {{165,343.000031}, {1000,343.000031}} {{1000,343}} wnTs[0]=1 {{1000,364.869873}, {1000,343}} -debugShowLineIntersection wtTs[0]=0 {{1000,343.000031}, {1000,364.869904}} {{1000,343.000031}} wtTs[1]=1 {{1000,364.869904}} wnTs[0]=0.999999 {{1000,364.869873}, {1000,343}} wnTs[1]=0 -debugShowLineIntersection wtTs[0]=0 {{1000,364.869904}, {165,364.869904}} {{1000,364.869873}} wnTs[0]=0 {{1000,364.869873}, {1000,343}} -debugShowLineIntersection wtTs[0]=0 {{1000,343.000031}, {1000,364.869904}} {{1000,343.000031}} wnTs[0]=1 {{165,343.000031}, {1000,343.000031}} -debugShowLineIntersection wtTs[0]=1 {{165,364.869904}, {165,343.000031}} {{165,343.000031}} wnTs[0]=0 {{165,343.000031}, {1000,343.000031}} -debugShowLineIntersection wtTs[0]=0 {{1000,364.869904}, {165,364.869904}} {{1000,364.869904}} wnTs[0]=1 {{1000,343.000031}, {1000,364.869904}} -debugShowLineIntersection wtTs[0]=0 {{165,364.869904}, {165,343.000031}} {{165,364.869904}} wnTs[0]=1 {{1000,364.869904}, {165,364.869904}} -SkOpSegment::debugShowTs - id=0 [o=3,5 t=0 1000,343.000031 w=1 o=0] [o=7,1 t=1 165,343 w=1 o=0] -SkOpSegment::debugShowTs o id=4 [o=7,1 t=0 165,343 w=1 o=0] [o=3,5 t=1 1000,343.000031 w=1 o=0] operand -SkOpSegment::debugShowTs + id=0 [o=3,5 t=0 1000,343.000031 w=1 o=0] [o=7,1 t=1 165,343 w=1 o=0] -SkOpSegment::debugShowTs o id=4 [o=7,1 t=0 165,343 w=1 o=0] [o=3,5 t=1 1000,343.000031 w=1 o=0] operand -SkOpSegment::debugShowTs - id=1 [o=4,0 t=0 165,343 w=1 o=0] [o=6,2 t=1 165,364.869873 w=1 o=0] -SkOpSegment::debugShowTs o id=7 [o=6,2 t=0 165,364.869904 w=1 o=0] [o=4,0 t=1 165,343.000031 w=1 o=0] operand -SkOpSegment::addTPair addTPair this=1 1.39541634e-006 other=7 1 -SkOpSegment::addTPair addTPair this=7 0 other=1 1 -SkOpSegment::debugShowTs + id=1 [o=4,0 t=0 165,343 w=1 o=0] [o=7 t=1.4e-006 165,343.000031 w=1 o=0] [o=7,6,2 t=1 165,364.869873 w=1 o=0] -SkOpSegment::debugShowTs o id=7 [o=1,6,2 t=0 165,364.869904 w=1 o=0] [o=1,4,0 t=1 165,343.000031 w=1 o=0] operand -SkOpSegment::debugShowTs - id=2 [o=1,7 t=0 165,364.869904 w=1 o=0] [o=5,3 t=1 1000,364.869873 w=1 o=0] -SkOpSegment::debugShowTs o id=6 [o=5,3 t=0 1000,364.869873 w=1 o=0] [o=1,7 t=1 165,364.869904 w=1 o=0] operand -SkOpSegment::debugShowTs + id=2 [o=1,7 t=0 165,364.869904 w=1 o=0] [o=5,3 t=1 1000,364.869873 w=1 o=0] -SkOpSegment::debugShowTs o id=6 [o=5,3 t=0 1000,364.869873 w=1 o=0] [o=1,7 t=1 165,364.869904 w=1 o=0] operand -SkOpSegment::debugShowTs - id=3 [o=6,2 t=0 1000,364.869873 w=1 o=0] [o=4,0 t=1 1000,343 w=1 o=0] -SkOpSegment::debugShowTs o id=5 [o=4,0 t=0 1000,343.000031 w=1 o=0] [o=6,2 t=1 1000,364.869904 w=1 o=0] operand -SkOpSegment::addTPair addTPair this=3 0 other=5 1 -SkOpSegment::addTPair addTPair this=5 0 other=3 0.999998605 -SkOpSegment::debugShowTs + id=3 [o=6,2,5 t=0 1000,364.869904 w=1 o=0] [o=5 t=1 1000,343.000031 w=1 o=0] [o=4,0 t=1 1000,343 w=1 o=0] -SkOpSegment::debugShowTs o id=5 [o=3,4,0 t=0 1000,343.000031 w=1 o=0] [o=3,6,2 t=1 1000,364.869904 w=1 o=0] operand -SkOpContour::calcCoincidentWinding count=4 -SkOpSegment::debugShowTs p id=0 [o=3,5 t=0 1000,343.000031 w=1 o=-1] [o=7,1 t=1 165,343 w=1 o=0] -SkOpSegment::debugShowTs o id=4 [o=7,1 t=0 165,343 w=0 o=0] [o=3,5 t=1 1000,343.000031 w=1 o=0] operand done -SkOpSegment::debugShowTs p id=1 [o=4,0 t=0 165,343 w=1 o=0] [o=7 t=1.4e-006 165,343.000031 w=1 o=-1] [o=7,6,2 t=1 165,364.869873 w=1 o=0] -SkOpSegment::debugShowTs o id=7 [o=1,6,2 t=0 165,364.869904 w=0 o=0] [o=1,4,0 t=1 165,343.000031 w=1 o=0] operand done -SkOpSegment::debugShowTs p id=2 [o=1,7 t=0 165,364.869904 w=1 o=-1] [o=5,3 t=1 1000,364.869873 w=1 o=0] -SkOpSegment::debugShowTs o id=6 [o=5,3 t=0 1000,364.869873 w=0 o=0] [o=1,7 t=1 165,364.869904 w=1 o=0] operand done -SkOpSegment::debugShowTs p id=3 [o=6,2,5 t=0 1000,364.869904 w=1 o=-1] [o=5 t=1 1000,343.000031 w=1 o=0] [o=4,0 t=1 1000,343 w=1 o=0] -SkOpSegment::debugShowTs o id=5 [o=3,4,0 t=0 1000,343.000031 w=0 o=0] [o=3,6,2 t=1 1000,364.869904 w=1 o=0] operand done -SkOpSegment::addTPair addTPair this=0 0 other=4 1 -SkOpSegment::addTPair addTPair this=0 1 other=4 0 -SkOpSegment::addTPair addTPair this=6 1 other=2 0 -SkOpSegment::addTPair addTPair duplicate this=2 0 other=6 1 -SkOpSegment::addTPair addTPair this=2 1 other=6 0 -SkOpContour::joinCoincidence count=4 -SkOpSegment::sortAngles [0] tStart=0 [0] -SkOpSegment::sortAngles [0] tStart=1 [5] -SkOpSegment::sortAngles [1] tStart=1.39541634e-006 [2] -SkOpSegment::sortAngles [1] tStart=1 [5] -SkOpSegment::sortAngles [2] tStart=1 [5] -SkOpSegment::sortAngles [3] tStart=0.999998605 [3] -SkOpSegment::debugShowActiveSpans id=0 (1000,343 165,343) t=0 (1000,343) tEnd=1 other=3 otherT=1 otherIndex=5 windSum=? windValue=1 oppValue=-1 -SkOpSegment::debugShowActiveSpans id=1 (165,343 165,364.869873) t=1.39541634e-006 (165,343.000031) tEnd=1 other=7 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=-1 -SkOpSegment::debugShowActiveSpans id=2 (165,364.869873 1000,364.869873) t=0 (165,364.869873) tEnd=1 other=6 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=-1 -SkOpSegment::debugShowActiveSpans id=3 (1000,364.869873 1000,343) t=0 (1000,364.869873) tEnd=0.999998605 other=6 otherT=0 otherIndex=2 windSum=? windValue=1 oppValue=-1 -Assemble - +<div id="issue2753"> + RunTestSet [issue2753] + +{{142.701004,110.568001}, {142.957001,100}}, +{{142.957001,100}, {153.835007,100}}, +{{153.835007,100}, {154.591995,108.188004}}, +{{154.591995,108.188004}, {154.591995,108.188004}, {153.173004,108.483002}, {152.830002,109.412003}}, +{{152.830002,109.412003}, {152.830002,109.412003}, {142.701004,110.568001}, {142.701004,110.568001}}, +op union +{{39,124.000999}, {39,124.000999}, {50.5999985,117.000999}, {50.5999985,117.000999}}, +{{50.5999985,117.000999}, {50.5999985,117.000999}, {164.600998,85.1999969}, {188.201004,117.600998}}, +{{188.201004,117.600998}, {188.201004,117.600998}, {174.800995,93}, {39,124.000999}}, +debugShowCubicIntersection no self intersect {{154.591995,108.188004}, {154.591995,108.188004}, {153.173004,108.483002}, {152.830002,109.412003}} +debugShowLineIntersection wtTs[0]=1 {{142.701004,110.568001}, {142.957001,100}} {{142.957001,100}} wnTs[0]=0 {{142.957001,100}, {153.835007,100}} +debugShowLineIntersection wtTs[0]=0 {{142.701004,110.568001}, {142.957001,100}} {{142.701004,110.568001}} wnTs[0]=1 {{152.830002,109.412003}, {142.701004,110.568001}} +debugShowLineIntersection wtTs[0]=0 {{153.835007,100}, {154.591995,108.188004}} {{153.835007,100}} wnTs[0]=1 {{142.957001,100}, {153.835007,100}} +debugShowCubicLineIntersection wtTs[0]=0 {{154.591995,108.188004}, {154.591995,108.188004}, {153.173004,108.483002}, {152.830002,109.412003}} {{154.591995,108.188004}} wnTs[0]=1 {{153.835007,100}, {154.591995,108.188004}} +debugShowCubicLineIntersection wtTs[0]=1 {{154.591995,108.188004}, {154.591995,108.188004}, {153.173004,108.483002}, {152.830002,109.412003}} {{152.830002,109.412003}} wnTs[0]=0 {{152.830002,109.412003}, {142.701004,110.568001}} +debugShowCubicLineIntersection wtTs[0]=0.671281996 {{50.5999985,117.000999}, {50.5999985,117.000999}, {164.600998,85.1999969}, {188.201004,117.600998}} {{142.883102,103.050758}} wnTs[0]=0.711321 {{142.701004,110.568001}, {142.957001,100}} +debugShowCubicLineIntersection wtTs[0]=0.642192755 {{188.201004,117.600998}, {188.201004,117.600998}, {174.800995,93}, {39,124.000999}} {{142.753387,108.405373}} wnTs[0]=0.204639 {{142.701004,110.568001}, {142.957001,100}} +debugShowCubicLineIntersection wtTs[0]=0.734814757 {{50.5999985,117.000999}, {50.5999985,117.000999}, {164.600998,85.1999969}, {188.201004,117.600998}} {{154.165848,103.578537}} wnTs[0]=0.437047 {{153.835007,100}, {154.591995,108.188004}} +debugShowCubicIntersection no intersect {{154.591995,108.188004}, {154.591995,108.188004}, {153.173004,108.483002}, {152.830002,109.412003}} {{50.5999985,117.000999}, {50.5999985,117.000999}, {164.600998,85.1999969}, {188.201004,117.600998}} +debugShowCubicIntersection no intersect {{154.591995,108.188004}, {154.591995,108.188004}, {153.173004,108.483002}, {152.830002,109.412003}} {{188.201004,117.600998}, {188.201004,117.600998}, {174.800995,93}, {39,124.000999}} +debugShowCubicLineIntersection no intersect {{50.5999985,117.000999}, {50.5999985,117.000999}, {164.600998,85.1999969}, {188.201004,117.600998}} {{152.830002,109.412003}, {142.701004,110.568001}} +debugShowCubicLineIntersection no intersect {{188.201004,117.600998}, {188.201004,117.600998}, {174.800995,93}, {39,124.000999}} {{152.830002,109.412003}, {142.701004,110.568001}} +debugShowCubicIntersection no self intersect {{50.5999985,117.000999}, {50.5999985,117.000999}, {164.600998,85.1999969}, {188.201004,117.600998}} +debugShowCubicIntersection no self intersect {{188.201004,117.600998}, {188.201004,117.600998}, {174.800995,93}, {39,124.000999}} +debugShowCubicLineIntersection wtTs[0]=0 {{50.5999985,117.000999}, {50.5999985,117.000999}, {164.600998,85.1999969}, {188.201004,117.600998}} {{50.5999985,117.000999}} wnTs[0]=1 {{39,124.000999}, {50.5999985,117.000999}} +debugShowCubicLineIntersection wtTs[0]=1 {{188.201004,117.600998}, {188.201004,117.600998}, {174.800995,93}, {39,124.000999}} {{39,124.000999}} wnTs[0]=0 {{39,124.000999}, {50.5999985,117.000999}} +debugShowCubicIntersection wtTs[0]=1 {{50.5999985,117.000999}, {50.5999985,117.000999}, {164.600998,85.1999969}, {188.201004,117.600998}} {{188.201004,117.600998}} wnTs[0]=0 {{188.201004,117.600998}, {188.201004,117.600998}, {174.800995,93}, {39,124.000999}} +SkOpSegment::sortAngles [0] tStart=0.204639461 [1] +SkOpAngle::after [0/1] 21/21 tStart=0.204639461 tEnd=0 < [7/1] 1/29 tStart=0.642192755 tEnd=0 < [0/2] 5/5 tStart=0.204639461 tEnd=0.711321242 T 4 +SkOpAngle::after [0/1] 21/21 tStart=0.204639461 tEnd=0 < [7/2] 17/17 tStart=0.642192755 tEnd=1 < [7/1] 1/29 tStart=0.642192755 tEnd=0 F 4 +SkOpAngle::after [7/1] 1/29 tStart=0.642192755 tEnd=0 < [7/2] 17/17 tStart=0.642192755 tEnd=1 < [0/2] 5/5 tStart=0.204639461 tEnd=0.711321242 F 4 +SkOpAngle::after [0/2] 5/5 tStart=0.204639461 tEnd=0.711321242 < [7/2] 17/17 tStart=0.642192755 tEnd=1 < [0/1] 21/21 tStart=0.204639461 tEnd=0 T 4 +SkOpSegment::sortAngles [0] tStart=0.711321242 [2] +SkOpAngle::after [0/3] 21/21 tStart=0.711321242 tEnd=0.204639461 < [6/1] 13/17 tStart=0.671281996 tEnd=0 < [0/4] 5/5 tStart=0.711321242 tEnd=1 F 4 +SkOpAngle::after [0/3] 21/21 tStart=0.711321242 tEnd=0.204639461 < [6/2] 29/29 tStart=0.671281996 tEnd=0.734814757 < [0/4] 5/5 tStart=0.711321242 tEnd=1 T 4 +SkOpSegment::sortAngles [2] tStart=0.437046747 [1] +SkOpAngle::after [2/1] 9/9 tStart=0.437046747 tEnd=0 < [6/3] 13/13 tStart=0.734814757 tEnd=0.671281996 < [2/2] 25/25 tStart=0.437046747 tEnd=1 T 4 +SkOpAngle::after [2/1] 9/9 tStart=0.437046747 tEnd=0 < [6/4] 29/29 tStart=0.734814757 tEnd=1 < [6/3] 13/13 tStart=0.734814757 tEnd=0.671281996 F 4 +SkOpAngle::after [6/3] 13/13 tStart=0.734814757 tEnd=0.671281996 < [6/4] 29/29 tStart=0.734814757 tEnd=1 < [2/2] 25/25 tStart=0.437046747 tEnd=1 F 4 +SkOpAngle::after [2/2] 25/25 tStart=0.437046747 tEnd=1 < [6/4] 29/29 tStart=0.734814757 tEnd=1 < [2/1] 9/9 tStart=0.437046747 tEnd=0 T 4 +SkOpSegment::debugShowActiveSpans id=0 (142.701004,110.568001 142.957001,100) t=0 (142.701004,110.568001) tEnd=0.204639461 other=4 otherT=1 otherIndex=1 windSum=? windValue=1 oppValue=0 +SkOpSegment::debugShowActiveSpans id=0 (142.701004,110.568001 142.957001,100) t=0.204639461 (142.753387,108.405373) tEnd=0.711321242 other=7 otherT=0.642192755 otherIndex=1 windSum=? windValue=1 oppValue=0 +SkOpSegment::debugShowActiveSpans id=0 (142.701004,110.568001 142.957001,100) t=0.711321242 (142.883102,103.050758) tEnd=1 other=6 otherT=0.671281996 otherIndex=1 windSum=? windValue=1 oppValue=0 +SkOpSegment::debugShowActiveSpans id=1 (142.957001,100 153.835007,100) t=0 (142.957001,100) tEnd=1 other=0 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0 +SkOpSegment::debugShowActiveSpans id=2 (153.835007,100 154.591995,108.188004) t=0 (153.835007,100) tEnd=0.437046747 other=1 otherT=1 otherIndex=1 windSum=? windValue=1 oppValue=0 +SkOpSegment::debugShowActiveSpans id=2 (153.835007,100 154.591995,108.188004) t=0.437046747 (154.165848,103.578537) tEnd=1 other=6 otherT=0.734814757 otherIndex=2 windSum=? windValue=1 oppValue=0 +SkOpSegment::debugShowActiveSpans id=3 (154.591995,108.188004 154.591995,108.188004 153.173004,108.483002 152.830002,109.412003) t=0 (154.591995,108.188004) tEnd=1 other=2 otherT=1 otherIndex=2 windSum=? windValue=1 oppValue=0 +SkOpSegment::debugShowActiveSpans id=4 (152.830002,109.412003 142.701004,110.568001) t=0 (152.830002,109.412003) tEnd=1 other=3 otherT=1 otherIndex=1 windSum=? windValue=1 oppValue=0 +SkOpSegment::debugShowActiveSpans id=5 (39,124.000999 50.5999985,117.000999) t=0 (39,124.000999) tEnd=1 other=7 otherT=1 otherIndex=2 windSum=? windValue=1 oppValue=0 +SkOpSegment::debugShowActiveSpans id=6 (50.5999985,117.000999 50.5999985,117.000999 164.600998,85.1999969 188.201004,117.600998) t=0 (50.5999985,117.000999) tEnd=0.671281996 other=5 otherT=1 otherIndex=1 windSum=? windValue=1 oppValue=0 +SkOpSegment::debugShowActiveSpans id=6 (50.5999985,117.000999 50.5999985,117.000999 164.600998,85.1999969 188.201004,117.600998) t=0.671281996 (142.883102,103.050758) tEnd=0.734814757 other=0 otherT=0.711321242 otherIndex=2 windSum=? windValue=1 oppValue=0 +SkOpSegment::debugShowActiveSpans id=6 (50.5999985,117.000999 50.5999985,117.000999 164.600998,85.1999969 188.201004,117.600998) t=0.734814757 (154.165848,103.578537) tEnd=1 other=2 otherT=0.437046747 otherIndex=1 windSum=? windValue=1 oppValue=0 +SkOpSegment::debugShowActiveSpans id=7 (188.201004,117.600998 188.201004,117.600998 174.800995,93 39,124.000999) t=0 (188.201004,117.600998) tEnd=0.642192755 other=6 otherT=1 otherIndex=3 windSum=? windValue=1 oppValue=0 +SkOpSegment::debugShowActiveSpans id=7 (188.201004,117.600998 188.201004,117.600998 174.800995,93 39,124.000999) t=0.642192755 (142.753387,108.405373) tEnd=1 other=0 otherT=0.204639461 otherIndex=1 windSum=? windValue=1 oppValue=0 +SkOpSegment::findTop +SkOpAngle::dumpOne [0/5] next=1/1 sect=21/21 s=1 [3] e=0.711321242 [2] sgn=1 windVal=1 windSum=? +SkOpAngle::dumpOne [1/1] next=0/5 sect=31/31 s=0 [0] e=1 [1] sgn=-1 windVal=1 windSum=? stop +SkOpSegment::markWinding id=0 (142.701004,110.568001 142.957001,100) t=0.711321242 [2] (142.883102,103.050758) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0 +SkOpSegment::nextChase mismatched signs +SkOpSegment::markWinding id=1 (142.957001,100 153.835007,100) t=0 [0] (142.957001,100) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0 +SkOpSegment::markWinding id=2 (153.835007,100 154.591995,108.188004) t=0 [0] (153.835007,100) tEnd=0.437046747 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0 +SkOpSegment::markWinding id=0 (142.701004,110.568001 142.957001,100) t=0.711321242 [2] (142.883102,103.050758) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0 +SkOpSegment::activeOp id=0 t=0.711321242 tEnd=1 op=union miFrom=1 miTo=0 suFrom=0 suTo=0 result=1 +SkOpSegment::nextChase mismatched signs +SkOpSegment::findNextOp simple +SkOpSegment::markDoneBinary id=0 (142.701004,110.568001 142.957001,100) t=0.711321242 [2] (142.883102,103.050758) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0 +bridgeOp current id=0 from=(142.883102,103.050758) to=(142.957001,100) +SkOpSegment::findNextOp simple +SkOpSegment::markDoneBinary id=1 (142.957001,100 153.835007,100) t=0 [0] (142.957001,100) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0 +bridgeOp current id=1 from=(142.957001,100) to=(153.835007,100) +path.moveTo(142.883102,103.050758); +path.lineTo(142.957001,100); +SkOpSegment::markWinding id=6 (50.5999985,117.000999 50.5999985,117.000999 164.600998,85.1999969 188.201004,117.600998) t=0.671281996 [1] (142.883102,103.050758) tEnd=0.734814757 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=0 +SkOpSegment::markAngle last id=6 windSum=-1 small=0 +SkOpSegment::markWinding id=2 (153.835007,100 154.591995,108.188004) t=0.437046747 [1] (154.165848,103.578537) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=0 +SkOpSegment::markWinding id=3 (154.591995,108.188004 154.591995,108.188004 153.173004,108.483002 152.830002,109.412003) t=0 [0] (154.591995,108.188004) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=0 +SkOpSegment::markWinding id=4 (152.830002,109.412003 142.701004,110.568001) t=0 [0] (152.830002,109.412003) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=0 +SkOpSegment::markWinding id=0 (142.701004,110.568001 142.957001,100) t=0 [0] (142.701004,110.568001) tEnd=0.204639461 newWindSum=-1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=0 +SkOpSegment::markAngle last id=0 windSum=? small=0 +SkOpSegment::markWinding id=6 (50.5999985,117.000999 50.5999985,117.000999 164.600998,85.1999969 188.201004,117.600998) t=0.734814757 [2] (154.165848,103.578537) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0 +SkOpSegment::markWinding id=7 (188.201004,117.600998 188.201004,117.600998 174.800995,93 39,124.000999) t=0 [0] (188.201004,117.600998) tEnd=0.642192755 newWindSum=-1 newOppSum=0 oppSum=? windSum=? windValue=1 oppValue=0 +SkOpSegment::markAngle last id=7 windSum=? small=0 +SkOpSegment::findNextOp +SkOpAngle::dumpOne [2/1] next=6/3 sect=9/9 s=0.437046747 [1] e=0 [0] sgn=1 windVal=1 windSum=-1 oppVal=0 oppSum=0 +SkOpAngle::dumpOne [6/3] next=2/2 sect=13/13 s=0.734814757 [2] e=0.671281996 [1] sgn=1 windVal=1 windSum=-1 oppVal=0 oppSum=-1 operand +SkOpAngle::dumpOne [2/2] next=6/4 sect=25/25 s=0.437046747 [1] e=1 [2] sgn=-1 windVal=1 windSum=-1 oppVal=0 oppSum=-1 +SkOpAngle::dumpOne [6/4] next=2/1 sect=29/29 s=0.734814757 [2] e=1 [3] sgn=-1 windVal=1 windSum=-1 oppVal=0 oppSum=0 operand +SkOpSegment::activeOp id=6 t=0.734814757 tEnd=0.671281996 op=union miFrom=1 miTo=1 suFrom=0 suTo=1 result=0 +SkOpSegment::markDoneBinary id=6 (50.5999985,117.000999 50.5999985,117.000999 164.600998,85.1999969 188.201004,117.600998) t=0.671281996 [1] (142.883102,103.050758) tEnd=0.734814757 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=0 +SkOpSegment::findNextOp chase.append id=6 windSum=-1 small=0 +SkOpSegment::activeOp id=2 t=0.437046747 tEnd=1 op=union miFrom=1 miTo=0 suFrom=1 suTo=1 result=0 +SkOpSegment::markDoneBinary id=2 (153.835007,100 154.591995,108.188004) t=0.437046747 [1] (154.165848,103.578537) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=0 +SkOpSegment::markDoneBinary id=3 (154.591995,108.188004 154.591995,108.188004 153.173004,108.483002 152.830002,109.412003) t=0 [0] (154.591995,108.188004) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=0 +SkOpSegment::markDoneBinary id=4 (152.830002,109.412003 142.701004,110.568001) t=0 [0] (152.830002,109.412003) tEnd=1 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=0 +SkOpSegment::markDoneBinary id=0 (142.701004,110.568001 142.957001,100) t=0 [0] (142.701004,110.568001) tEnd=0.204639461 newWindSum=-1 newOppSum=-1 oppSum=-1 windSum=-1 windValue=1 oppValue=0 +SkOpSegment::findNextOp chase.append id=0 windSum=-2147483647 small=0 +SkOpSegment::activeOp id=6 t=0.734814757 tEnd=1 op=union miFrom=0 miTo=0 suFrom=1 suTo=0 result=1 +SkOpSegment::findNextOp chase.append id=7 windSum=-2147483647 small=0 +SkOpSegment::markDoneBinary id=2 (153.835007,100 154.591995,108.188004) t=0 [0] (153.835007,100) tEnd=0.437046747 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0 +SkOpSegment::findNextOp from:[2] to:[6] start=2 end=3 +bridgeOp current id=2 from=(153.835007,100) to=(154.165848,103.578537) +path.lineTo(153.835007,100); +SkOpSegment::findNextOp simple +SkOpSegment::markDoneBinary id=6 (50.5999985,117.000999 50.5999985,117.000999 164.600998,85.1999969 188.201004,117.600998) t=0.734814757 [2] (154.165848,103.578537) tEnd=1 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0 +bridgeOp current id=6 from=(154.165848,103.578537) to=(188.201004,117.600998) +path.lineTo(154.165848,103.578537); +path.cubicTo(169.326965,104.931351, 181.942627,109.008728, 188.201004,117.600998); +SkOpSegment::markWinding id=0 (142.701004,110.568001 142.957001,100) t=0.204639461 [1] (142.753387,108.405373) tEnd=0.711321242 newWindSum=1 newOppSum=-1 oppSum=? windSum=? windValue=1 oppValue=0 +SkOpSegment::markAngle last id=0 windSum=-1 small=0 +SkOpSegment::markWinding id=7 (188.201004,117.600998 188.201004,117.600998 174.800995,93 39,124.000999) t=0.642192755 [1] (142.753387,108.405373) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=0 +SkOpSegment::markWinding id=5 (39,124.000999 50.5999985,117.000999) t=0 [0] (39,124.000999) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=0 +SkOpSegment::markWinding id=6 (50.5999985,117.000999 50.5999985,117.000999 164.600998,85.1999969 188.201004,117.600998) t=0 [0] (50.5999985,117.000999) tEnd=0.671281996 newWindSum=-1 newOppSum=1 oppSum=? windSum=? windValue=1 oppValue=0 +SkOpSegment::markAngle last id=6 windSum=-1 small=0 +SkOpSegment::findNextOp +SkOpAngle::dumpOne [7/1] next=0/2 sect=1/29 s=0.642192755 [1] e=0 [0] sgn=1 windVal=1 windSum=-1 oppVal=0 oppSum=0 operand +SkOpAngle::dumpOne [0/2] next=7/2 sect=5/5 s=0.204639461 [1] e=0.711321242 [2] sgn=-1 windVal=1 windSum=1 oppVal=0 oppSum=-1 +SkOpAngle::dumpOne [7/2] next=0/1 sect=17/17 s=0.642192755 [1] e=1 [2] sgn=-1 windVal=1 windSum=-1 oppVal=0 oppSum=1 operand +SkOpAngle::dumpOne [0/1] next=7/1 sect=21/21 s=0.204639461 [1] e=0 [0] sgn=1 windVal=1 windSum=-1 oppVal=0 oppSum=-1 done +SkOpSegment::activeOp id=0 t=0.204639461 tEnd=0.711321242 op=union miFrom=0 miTo=1 suFrom=1 suTo=1 result=0 +SkOpSegment::markDoneBinary id=0 (142.701004,110.568001 142.957001,100) t=0.204639461 [1] (142.753387,108.405373) tEnd=0.711321242 newWindSum=1 newOppSum=-1 oppSum=-1 windSum=1 windValue=1 oppValue=0 +SkOpSegment::findNextOp chase.append id=0 windSum=-1 small=0 +SkOpSegment::activeOp id=7 t=0.642192755 tEnd=1 op=union miFrom=1 miTo=1 suFrom=1 suTo=0 result=0 +SkOpSegment::markDoneBinary id=7 (188.201004,117.600998 188.201004,117.600998 174.800995,93 39,124.000999) t=0.642192755 [1] (142.753387,108.405373) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1 oppValue=0 +SkOpSegment::markDoneBinary id=5 (39,124.000999 50.5999985,117.000999) t=0 [0] (39,124.000999) tEnd=1 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1 oppValue=0 +SkOpSegment::markDoneBinary id=6 (50.5999985,117.000999 50.5999985,117.000999 164.600998,85.1999969 188.201004,117.600998) t=0 [0] (50.5999985,117.000999) tEnd=0.671281996 newWindSum=-1 newOppSum=1 oppSum=1 windSum=-1 windValue=1 oppValue=0 +SkOpSegment::activeOp id=0 t=0.204639461 tEnd=0 op=union miFrom=1 miTo=0 suFrom=0 suTo=0 result=1 +SkOpSegment::markDoneBinary id=7 (188.201004,117.600998 188.201004,117.600998 174.800995,93 39,124.000999) t=0 [0] (188.201004,117.600998) tEnd=0.642192755 newWindSum=-1 newOppSum=0 oppSum=0 windSum=-1 windValue=1 oppValue=0 +SkOpSegment::findNextOp from:[7] to:[0] start=1 end=0 +bridgeOp current id=7 from=(188.201004,117.600998) to=(142.753387,108.405373) +path.cubicTo(188.201004,117.600998, 182.674683,107.455261, 142.753387,108.405373); </div> </div> @@ -88,7 +142,7 @@ Assemble <script type="text/javascript"> var testDivs = [ - skpwww_argus_presse_fr_41, + issue2753, ]; var decimal_places = 3; // make this 3 to show more precision |