aboutsummaryrefslogtreecommitdiffhomepage
path: root/tests
diff options
context:
space:
mode:
authorGravatar reed <reed@google.com>2015-03-24 13:55:33 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-03-24 13:55:33 -0700
commit0dc4dd6dda9a7912f696b46d9c02155ec1d1ba5f (patch)
tree994c85a8e418986415175ddccc71adf924df3846 /tests
parent82dec0e16ae10026194ce45b67af931700510450 (diff)
Revert of pathops version two (patchset #16 id:150001 of https://codereview.chromium.org/1002693002/)
Reason for revert: ASAN investigation Original issue's description: > pathops version two > > R=reed@google.com > > marked 'no commit' to attempt to get trybots to run > > TBR=reed@google.com > > Committed: https://skia.googlesource.com/skia/+/ccec0f958ffc71a9986d236bc2eb335cb2111119 TBR=caryclark@google.com NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true Review URL: https://codereview.chromium.org/1029993002
Diffstat (limited to 'tests')
-rwxr-xr-xtests/PathOpsAngleIdeas.cpp51
-rw-r--r--tests/PathOpsAngleTest.cpp180
-rw-r--r--tests/PathOpsBattles.cpp43
-rw-r--r--tests/PathOpsBuilderTest.cpp11
-rw-r--r--tests/PathOpsCubicIntersectionTest.cpp214
-rw-r--r--tests/PathOpsCubicIntersectionTestData.cpp12
-rw-r--r--tests/PathOpsCubicLineIntersectionTest.cpp3
-rw-r--r--tests/PathOpsCubicQuadIntersectionTest.cpp233
-rw-r--r--tests/PathOpsCubicToQuadsTest.cpp198
-rw-r--r--tests/PathOpsDLineTest.cpp4
-rw-r--r--tests/PathOpsDPointTest.cpp1
-rw-r--r--tests/PathOpsDQuadTest.cpp63
-rw-r--r--tests/PathOpsDRectTest.cpp64
-rw-r--r--tests/PathOpsDTriangleTest.cpp70
-rwxr-xr-xtests/PathOpsDebug.cpp1338
-rw-r--r--tests/PathOpsExtendedTest.cpp82
-rw-r--r--tests/PathOpsExtendedTest.h7
-rwxr-xr-xtests/PathOpsFuzz763Test.cpp53
-rw-r--r--tests/PathOpsLineIntersectionTest.cpp43
-rw-r--r--tests/PathOpsOpCubicThreadedTest.cpp7
-rwxr-xr-xtests/PathOpsOpLoopThreadedTest.cpp45
-rw-r--r--tests/PathOpsOpTest.cpp388
-rw-r--r--tests/PathOpsQuadIntersectionTest.cpp82
-rw-r--r--tests/PathOpsQuadIntersectionTestData.cpp10
-rw-r--r--tests/PathOpsQuadParameterizationTest.cpp50
-rw-r--r--tests/PathOpsSimplifyFailTest.cpp5
-rw-r--r--tests/PathOpsSimplifyTest.cpp17
-rwxr-xr-xtests/PathOpsSkpTest.cpp109
-rw-r--r--tests/PathOpsTSectDebug.h161
-rw-r--r--tests/PathOpsTestCommon.cpp131
-rw-r--r--tests/PathOpsTestCommon.h1
-rw-r--r--tests/PathOpsThreeWayTest.cpp10
-rw-r--r--tests/PathOpsTightBoundsTest.cpp1
33 files changed, 1656 insertions, 2031 deletions
diff --git a/tests/PathOpsAngleIdeas.cpp b/tests/PathOpsAngleIdeas.cpp
index 1a2bce77f2..901cab2bb5 100755
--- a/tests/PathOpsAngleIdeas.cpp
+++ b/tests/PathOpsAngleIdeas.cpp
@@ -6,8 +6,8 @@
*/
#include "PathOpsTestCommon.h"
#include "SkIntersections.h"
-#include "SkOpContour.h"
#include "SkOpSegment.h"
+#include "SkPathOpsTriangle.h"
#include "SkRandom.h"
#include "SkTArray.h"
#include "SkTSort.h"
@@ -18,12 +18,12 @@ static bool gPathOpsAngleIdeasEnableBruteCheck = false;
class PathOpsAngleTester {
public:
- static int ConvexHullOverlaps(SkOpAngle& lh, SkOpAngle& rh) {
- return lh.convexHullOverlaps(&rh);
+ static int ConvexHullOverlaps(const SkOpAngle& lh, const SkOpAngle& rh) {
+ return lh.convexHullOverlaps(rh);
}
- static int EndsIntersect(SkOpAngle& lh, SkOpAngle& rh) {
- return lh.endsIntersect(&rh);
+ static int EndsIntersect(const SkOpAngle& lh, const SkOpAngle& rh) {
+ return lh.endsIntersect(rh);
}
};
@@ -406,29 +406,28 @@ static bool bruteForceCheck(skiatest::Reporter* reporter, const SkDQuad& quad1,
return ccw == upperRange.ccw;
}
-static void makeSegment(SkOpContour* contour, const SkDQuad& quad, SkPoint shortQuad[3],
- SkChunkAlloc* allocator) {
+class PathOpsSegmentTester {
+public:
+ static void ConstructQuad(SkOpSegment* segment, SkPoint shortQuad[3]) {
+ segment->debugConstructQuad(shortQuad);
+ }
+};
+
+static void makeSegment(const SkDQuad& quad, SkPoint shortQuad[3], SkOpSegment* result) {
shortQuad[0] = quad[0].asSkPoint();
shortQuad[1] = quad[1].asSkPoint();
shortQuad[2] = quad[2].asSkPoint();
- contour->addQuad(shortQuad, allocator);
+ PathOpsSegmentTester::ConstructQuad(result, shortQuad);
}
static void testQuadAngles(skiatest::Reporter* reporter, const SkDQuad& quad1, const SkDQuad& quad2,
- int testNo, SkChunkAlloc* allocator) {
+ int testNo) {
SkPoint shortQuads[2][3];
-
- SkOpContour contour;
- SkOpGlobalState state(NULL PATH_OPS_DEBUG_PARAMS(&contour));
- contour.init(&state, false, false);
- makeSegment(&contour, quad1, shortQuads[0], allocator);
- makeSegment(&contour, quad1, shortQuads[1], allocator);
- SkOpSegment* seg1 = contour.first();
- seg1->debugAddAngle(0, 1, allocator);
- SkOpSegment* seg2 = seg1->next();
- seg2->debugAddAngle(0, 1, allocator);
- int realOverlap = PathOpsAngleTester::ConvexHullOverlaps(*seg1->debugLastAngle(),
- *seg2->debugLastAngle());
+ SkOpSegment seg[2];
+ makeSegment(quad1, shortQuads[0], &seg[0]);
+ makeSegment(quad2, shortQuads[1], &seg[1]);
+ int realOverlap = PathOpsAngleTester::ConvexHullOverlaps(*seg[0].debugLastAngle(),
+ *seg[1].debugLastAngle());
const SkDPoint& origin = quad1[0];
REPORTER_ASSERT(reporter, origin == quad2[0]);
double a1s = atan2(origin.fY - quad1[1].fY, quad1[1].fX - origin.fX);
@@ -546,27 +545,25 @@ static void testQuadAngles(skiatest::Reporter* reporter, const SkDQuad& quad1, c
}
if (overlap < 0) {
SkDEBUGCODE(int realEnds =)
- PathOpsAngleTester::EndsIntersect(*seg1->debugLastAngle(),
- *seg2->debugLastAngle());
+ PathOpsAngleTester::EndsIntersect(*seg[0].debugLastAngle(),
+ *seg[1].debugLastAngle());
SkASSERT(realEnds == (firstInside ? 1 : 0));
}
bruteForce(reporter, quad1, quad2, firstInside);
}
DEF_TEST(PathOpsAngleOverlapHullsOne, reporter) {
- SkChunkAlloc allocator(4096);
// gPathOpsAngleIdeasVerbose = true;
const SkDQuad quads[] = {
{{{939.4808349609375, 914.355224609375}, {-357.7921142578125, 590.842529296875}, {736.8936767578125, -350.717529296875}}},
{{{939.4808349609375, 914.355224609375}, {-182.85418701171875, 634.4552001953125}, {-509.62615966796875, 576.1182861328125}}}
};
for (int index = 0; index < (int) SK_ARRAY_COUNT(quads); index += 2) {
- testQuadAngles(reporter, quads[index], quads[index + 1], 0, &allocator);
+ testQuadAngles(reporter, quads[index], quads[index + 1], 0);
}
}
DEF_TEST(PathOpsAngleOverlapHulls, reporter) {
- SkChunkAlloc allocator(4096);
if (!gPathOpsAngleIdeasVerbose) { // takes a while to run -- so exclude it by default
return;
}
@@ -590,7 +587,7 @@ DEF_TEST(PathOpsAngleOverlapHulls, reporter) {
if (i.used() > 1) {
continue;
}
- testQuadAngles(reporter, quad1, quad2, index, &allocator);
+ testQuadAngles(reporter, quad1, quad2, index);
}
}
diff --git a/tests/PathOpsAngleTest.cpp b/tests/PathOpsAngleTest.cpp
index db3e8644f1..faf61584e6 100644
--- a/tests/PathOpsAngleTest.cpp
+++ b/tests/PathOpsAngleTest.cpp
@@ -6,9 +6,10 @@
*/
#include "PathOpsTestCommon.h"
#include "SkIntersections.h"
-#include "SkOpContour.h"
#include "SkOpSegment.h"
+#include "SkPathOpsTriangle.h"
#include "SkRandom.h"
+#include "SkTArray.h"
#include "SkTSort.h"
#include "Test.h"
@@ -190,20 +191,20 @@ DEF_TEST(PathOpsAngleFindSlop, reporter) {
class PathOpsAngleTester {
public:
- static int After(SkOpAngle& lh, SkOpAngle& rh) {
+ static int After(const SkOpAngle& lh, const SkOpAngle& rh) {
return lh.after(&rh);
}
- static int ConvexHullOverlaps(SkOpAngle& lh, SkOpAngle& rh) {
- return lh.convexHullOverlaps(&rh);
+ static int ConvexHullOverlaps(const SkOpAngle& lh, const SkOpAngle& rh) {
+ return lh.convexHullOverlaps(rh);
}
- static int Orderable(SkOpAngle& lh, SkOpAngle& rh) {
- return lh.orderable(&rh);
+ static int Orderable(const SkOpAngle& lh, const SkOpAngle& rh) {
+ return lh.orderable(rh);
}
- static int EndsIntersect(SkOpAngle& lh, SkOpAngle& rh) {
- return lh.endsIntersect(&rh);
+ static int EndsIntersect(const SkOpAngle& lh, const SkOpAngle& rh) {
+ return lh.endsIntersect(rh);
}
static void SetNext(SkOpAngle& lh, SkOpAngle& rh) {
@@ -213,6 +214,18 @@ public:
class PathOpsSegmentTester {
public:
+ static void ConstructCubic(SkOpSegment* segment, SkPoint shortCubic[4]) {
+ segment->debugConstructCubic(shortCubic);
+ }
+
+ static void ConstructLine(SkOpSegment* segment, SkPoint shortLine[2]) {
+ segment->debugConstructLine(shortLine);
+ }
+
+ static void ConstructQuad(SkOpSegment* segment, SkPoint shortQuad[3]) {
+ segment->debugConstructQuad(shortQuad);
+ }
+
static void DebugReset(SkOpSegment* segment) {
segment->debugReset();
}
@@ -233,10 +246,7 @@ static CircleData circleDataSet[] = {
static const int circleDataSetSize = (int) SK_ARRAY_COUNT(circleDataSet);
DEF_TEST(PathOpsAngleCircle, reporter) {
- SkOpContour contour;
- SkOpGlobalState state(NULL PATH_OPS_DEBUG_PARAMS(&contour));
- contour.init(&state, false, false);
- SkChunkAlloc allocator(4096);
+ SkOpSegment segment[2];
for (int index = 0; index < circleDataSetSize; ++index) {
CircleData& data = circleDataSet[index];
for (int idx2 = 0; idx2 < data.fPtCount; ++idx2) {
@@ -244,21 +254,17 @@ DEF_TEST(PathOpsAngleCircle, reporter) {
}
switch (data.fPtCount) {
case 2:
- contour.addLine(data.fShortPts, &allocator);
+ PathOpsSegmentTester::ConstructLine(&segment[index], data.fShortPts);
break;
case 3:
- contour.addQuad(data.fShortPts, &allocator);
+ PathOpsSegmentTester::ConstructQuad(&segment[index], data.fShortPts);
break;
case 4:
- contour.addCubic(data.fShortPts, &allocator);
+ PathOpsSegmentTester::ConstructCubic(&segment[index], data.fShortPts);
break;
}
}
- SkOpSegment* first = contour.first();
- first->debugAddAngle(0, 1, &allocator);
- SkOpSegment* next = first->next();
- next->debugAddAngle(0, 1, &allocator);
- PathOpsAngleTester::Orderable(*first->debugLastAngle(), *next->debugLastAngle());
+ PathOpsAngleTester::Orderable(*segment[0].debugLastAngle(), *segment[1].debugLastAngle());
}
struct IntersectData {
@@ -373,39 +379,11 @@ static IntersectData intersectDataSet16[] = { // pathops_visualizer.htm:7419
{ {{{5.000,4.000}, {2.000,3.000}}}, 2, 0.5, 0, {} }, // pathops_visualizer.htm:7377
}; //
-// from skpi_gino_com_16
-static IntersectData intersectDataSet17[] = {
- { /*seg=7*/ {{{270.974121f, 770.025879f}, {234.948273f, 734}, {184, 734}}}
- , 3, 0.74590454, 0.547660352, {} },
- { /*seg=8*/ {{{185, 734}, {252.93103f, 734}, {308, 789.06897f}, {308, 857}}}
- , 4, 0.12052623, 0, {} },
- { /*seg=7*/ {{{270.974121f, 770.025879f}, {234.948273f, 734}, {184, 734}}}
- , 3, 0.74590454, 1, {} },
-};
-
-static IntersectData intersectDataSet18[] = {
- { /*seg=7*/ {{{270.974121f, 770.025879f}, {234.948273f, 734}, {184, 734}}}
- , 3, 0.74590454, 1, {} },
- { /*seg=8*/ {{{185, 734}, {252.93103f, 734}, {308, 789.06897f}, {308, 857}}}
- , 4, 0.12052623, 0.217351928, {} },
- { /*seg=7*/ {{{270.974121f, 770.025879f}, {234.948273f, 734}, {184, 734}}}
- , 3, 0.74590454, 0.547660352, {} },
-};
-
-static IntersectData intersectDataSet19[] = {
- { /*seg=1*/ {{{0, 1}, {3, 5}, {2, 1}, {3, 1}}}
- , 4, 0.135148995, 0.134791946, {} },
- { /*seg=3*/ {{{1, 2}, {1, 2.15061641f}, {1, 2.21049166f}, {1.01366711f, 2.21379328f}}}
- , 4, 0.956740456, 0.894913214, {} },
- { /*seg=1*/ {{{0, 1}, {3, 5}, {2, 1}, {3, 1}}}
- , 4, 0.135148995, 0.551812363, {} },
-};
-
#define I(x) intersectDataSet##x
static IntersectData* intersectDataSets[] = {
I(1), I(2), I(3), I(4), I(5), I(6), I(7), I(8), I(9), I(10),
- I(11), I(12), I(13), I(14), I(15), I(16), I(17), I(18), I(19),
+ I(11), I(12), I(13), I(14), I(15), I(16),
};
#undef I
@@ -413,55 +391,56 @@ static IntersectData* intersectDataSets[] = {
static const int intersectDataSetSizes[] = {
I(1), I(2), I(3), I(4), I(5), I(6), I(7), I(8), I(9), I(10),
- I(11), I(12), I(13), I(14), I(15), I(16), I(17), I(18), I(19),
+ I(11), I(12), I(13), I(14), I(15), I(16),
};
#undef I
static const int intersectDataSetsSize = (int) SK_ARRAY_COUNT(intersectDataSetSizes);
-struct FourPoints {
- SkPoint pts[4];
-};
-
DEF_TEST(PathOpsAngleAfter, reporter) {
- SkChunkAlloc allocator(4096);
- SkOpContour contour;
- SkOpGlobalState state(NULL PATH_OPS_DEBUG_PARAMS(&contour));
- contour.init(&state, false, false);
for (int index = intersectDataSetsSize - 1; index >= 0; --index) {
IntersectData* dataArray = intersectDataSets[index];
const int dataSize = intersectDataSetSizes[index];
+ SkOpSegment segment[3];
for (int index2 = 0; index2 < dataSize - 2; ++index2) {
- allocator.reset();
- contour.reset();
- for (int index3 = 0; index3 < 3; ++index3) {
+ for (int temp = 0; temp < (int) SK_ARRAY_COUNT(segment); ++temp) {
+ PathOpsSegmentTester::DebugReset(&segment[temp]);
+ }
+ for (int index3 = 0; index3 < (int) SK_ARRAY_COUNT(segment); ++index3) {
IntersectData& data = dataArray[index2 + index3];
- SkPoint* temp = (SkPoint*) SkOpTAllocator<FourPoints>::Allocate(&allocator);
+ SkPoint temp[4];
for (int idx2 = 0; idx2 < data.fPtCount; ++idx2) {
temp[idx2] = data.fPts.fPts[idx2].asSkPoint();
}
switch (data.fPtCount) {
case 2: {
- contour.addLine(temp, &allocator);
+ SkDLine seg = SkDLine::SubDivide(temp, data.fTStart,
+ data.fTStart < data.fTEnd ? 1 : 0);
+ data.fShortPts[0] = seg[0].asSkPoint();
+ data.fShortPts[1] = seg[1].asSkPoint();
+ PathOpsSegmentTester::ConstructLine(&segment[index3], data.fShortPts);
} break;
case 3: {
- contour.addQuad(temp, &allocator);
+ SkDQuad seg = SkDQuad::SubDivide(temp, data.fTStart, data.fTEnd);
+ data.fShortPts[0] = seg[0].asSkPoint();
+ data.fShortPts[1] = seg[1].asSkPoint();
+ data.fShortPts[2] = seg[2].asSkPoint();
+ PathOpsSegmentTester::ConstructQuad(&segment[index3], data.fShortPts);
} break;
case 4: {
- contour.addCubic(temp, &allocator);
+ SkDCubic seg = SkDCubic::SubDivide(temp, data.fTStart, data.fTEnd);
+ data.fShortPts[0] = seg[0].asSkPoint();
+ data.fShortPts[1] = seg[1].asSkPoint();
+ data.fShortPts[2] = seg[2].asSkPoint();
+ data.fShortPts[3] = seg[3].asSkPoint();
+ PathOpsSegmentTester::ConstructCubic(&segment[index3], data.fShortPts);
} break;
}
}
- SkOpSegment* seg1 = contour.first();
- seg1->debugAddAngle(dataArray[index2 + 0].fTStart, dataArray[index2 + 0].fTEnd, &allocator);
- SkOpSegment* seg2 = seg1->next();
- seg2->debugAddAngle(dataArray[index2 + 1].fTStart, dataArray[index2 + 1].fTEnd, &allocator);
- SkOpSegment* seg3 = seg2->next();
- seg3->debugAddAngle(dataArray[index2 + 2].fTStart, dataArray[index2 + 2].fTEnd, &allocator);
- SkOpAngle& angle1 = *seg1->debugLastAngle();
- SkOpAngle& angle2 = *seg2->debugLastAngle();
- SkOpAngle& angle3 = *seg3->debugLastAngle();
+ SkOpAngle& angle1 = *const_cast<SkOpAngle*>(segment[0].debugLastAngle());
+ SkOpAngle& angle2 = *const_cast<SkOpAngle*>(segment[1].debugLastAngle());
+ SkOpAngle& angle3 = *const_cast<SkOpAngle*>(segment[2].debugLastAngle());
PathOpsAngleTester::SetNext(angle1, angle3);
// These data sets are seeded when the set itself fails, so likely the dataset does not
// match the expected result. The tests above return 1 when first added, but
@@ -472,26 +451,35 @@ DEF_TEST(PathOpsAngleAfter, reporter) {
}
}
-void SkOpSegment::debugAddAngle(double startT, double endT, SkChunkAlloc* allocator) {
- SkOpPtT* startPtT = startT == 0 ? fHead.ptT() : startT == 1 ? fTail.ptT()
- : this->addT(startT, kNoAlias, allocator);
- SkOpPtT* endPtT = endT == 0 ? fHead.ptT() : endT == 1 ? fTail.ptT()
- : this->addT(endT, kNoAlias, allocator);
- SkOpAngle* angle = SkOpTAllocator<SkOpAngle>::Allocate(allocator);
- SkOpSpanBase* startSpan = &fHead;
- while (startSpan->ptT() != startPtT) {
- startSpan = startSpan->upCast()->next();
- }
- SkOpSpanBase* endSpan = &fHead;
- while (endSpan->ptT() != endPtT) {
- endSpan = endSpan->upCast()->next();
- }
- angle->set(startSpan, endSpan);
- if (startT < endT) {
- startSpan->upCast()->setToAngle(angle);
- endSpan->setFromAngle(angle);
- } else {
- endSpan->upCast()->setToAngle(angle);
- startSpan->setFromAngle(angle);
- }
+void SkOpSegment::debugConstruct() {
+ addStartSpan(1);
+ addEndSpan(1);
+ debugAddAngle(0, 1);
+}
+
+void SkOpSegment::debugAddAngle(int start, int end) {
+ SkASSERT(start != end);
+ SkOpAngle& angle = fAngles.push_back();
+ angle.set(this, start, end);
+}
+
+void SkOpSegment::debugConstructCubic(SkPoint shortQuad[4]) {
+ addCubic(shortQuad, false, false);
+ addT(NULL, shortQuad[0], 0);
+ addT(NULL, shortQuad[3], 1);
+ debugConstruct();
+}
+
+void SkOpSegment::debugConstructLine(SkPoint shortQuad[2]) {
+ addLine(shortQuad, false, false);
+ addT(NULL, shortQuad[0], 0);
+ addT(NULL, shortQuad[1], 1);
+ debugConstruct();
+}
+
+void SkOpSegment::debugConstructQuad(SkPoint shortQuad[3]) {
+ addQuad(shortQuad, false, false);
+ addT(NULL, shortQuad[0], 0);
+ addT(NULL, shortQuad[2], 1);
+ debugConstruct();
}
diff --git a/tests/PathOpsBattles.cpp b/tests/PathOpsBattles.cpp
index fbe12c01b5..455f2e967b 100644
--- a/tests/PathOpsBattles.cpp
+++ b/tests/PathOpsBattles.cpp
@@ -59,6 +59,7 @@ path2.lineTo(SkBits2Float(0x422c58d6), SkBits2Float(0x422705c1));
path2.cubicTo(SkBits2Float(0x42383446), SkBits2Float(0x421ac98f), SkBits2Float(0x4242b98a), SkBits2Float(0x420d5308), SkBits2Float(0x424bbb17), SkBits2Float(0x41fdb8ee));
path2.lineTo(SkBits2Float(0x428ce9ef), SkBits2Float(0x422f7dc6));
path2.close();
+// SkOpSegment.cpp:3488: failed assertion "other->fTs[min].fWindSum == oppWinding"
testPathOp(reporter, path1, path2, kUnion_PathOp, filename);
}
@@ -1295,7 +1296,7 @@ path.lineTo(SkBits2Float(0x4285e672), SkBits2Float(0xc2443b5f));
path.close();
SkPath path2(path);
- testPathOp(reporter, path1, path2, (SkPathOp) 2, filename);
+ testPathOpCheck(reporter, path1, path2, (SkPathOp) 2, filename, FLAGS_runFail);
}
// op end success 1
@@ -1511,7 +1512,7 @@ path.lineTo(SkBits2Float(0x42a3a81d), SkBits2Float(0xc15e595e));
path.close();
SkPath path2(path);
- testPathOp(reporter, path1, path2, (SkPathOp) 2, filename);
+ testPathOpCheck(reporter, path1, path2, (SkPathOp) 2, filename, FLAGS_runFail);
}
// op end success 1
@@ -1753,7 +1754,7 @@ path.lineTo(SkBits2Float(0x4039d102), SkBits2Float(0xc2a5e5fe));
path.close();
SkPath path2(path);
- testPathOp(reporter, path1, path2, (SkPathOp) 2, filename);
+ testPathOpCheck(reporter, path1, path2, (SkPathOp) 2, filename, FLAGS_runFail);
}
// op end success 1
@@ -1883,7 +1884,11 @@ path.lineTo(SkBits2Float(0x3ee8b040), SkBits2Float(0xc2a5ff5d));
path.close();
SkPath path2(path);
- testPathOp(reporter, path1, path2, (SkPathOp) 2, filename);
+ if (FLAGS_runFail) {
+ testPathOp(reporter, path1, path2, (SkPathOp) 2, filename);
+ } else {
+ testPathFailOp(reporter, path1, path2, (SkPathOp) 2, filename);
+ }
}
// op end success 1
@@ -3977,7 +3982,7 @@ path.lineTo(SkBits2Float(0x42a38b52), SkBits2Float(0xc1639578));
path.close();
SkPath path2(path);
- testPathOp(reporter, path1, path2, (SkPathOp) 2, filename);
+ testPathOpCheck(reporter, path1, path2, (SkPathOp) 2, filename, FLAGS_runFail);
}
// op end success 1
@@ -4087,7 +4092,7 @@ path.lineTo(SkBits2Float(0x42a5fe22), SkBits2Float(0x3f4744a1));
path.close();
SkPath path2(path);
- testPathOp(reporter, path1, path2, (SkPathOp) 2, filename);
+ testPathOpCheck(reporter, path1, path2, (SkPathOp) 2, filename, FLAGS_runFail);
}
// op end success 1
@@ -4235,7 +4240,7 @@ path.lineTo(SkBits2Float(0x429c4e4c), SkBits2Float(0x41df969b));
path.close();
SkPath path2(path);
- testPathOp(reporter, path1, path2, (SkPathOp) 2, filename);
+ testPathOpCheck(reporter, path1, path2, (SkPathOp) 2, filename, FLAGS_runFail);
}
// op end success 1
@@ -4409,7 +4414,7 @@ path.lineTo(SkBits2Float(0x428cfdb5), SkBits2Float(0x422f3e36));
path.close();
SkPath path2(path);
- testPathOp(reporter, path1, path2, (SkPathOp) 2, filename);
+ testPathOpCheck(reporter, path1, path2, (SkPathOp) 2, filename, FLAGS_runFail);
}
// op end success 1
@@ -4831,7 +4836,7 @@ path.lineTo(SkBits2Float(0x425b4ae0), SkBits2Float(0x427944c0));
path.close();
SkPath path2(path);
- testPathOpCheck(reporter, path1, path2, (SkPathOp) 2, filename, FLAGS_runFail);
+ testPathOp(reporter, path1, path2, (SkPathOp) 2, filename);
}
// op end success 1
@@ -4951,7 +4956,7 @@ path.lineTo(SkBits2Float(0x424f88ba), SkBits2Float(0x428191f0));
path.close();
SkPath path2(path);
- testPathOp(reporter, path1, path2, (SkPathOp) 2, filename);
+ testPathOpCheck(reporter, path1, path2, (SkPathOp) 2, filename, FLAGS_runFail);
}
// op end success 1
@@ -5362,7 +5367,7 @@ path.lineTo(SkBits2Float(0x3fc9081a), SkBits2Float(0xc2a5f864));
path.close();
SkPath path2(path);
- testPathOp(reporter, path1, path2, (SkPathOp) 2, filename);
+ testPathOpCheck(reporter, path1, path2, (SkPathOp) 2, filename, FLAGS_runFail);
}
// op end success 1
@@ -5438,7 +5443,7 @@ path.lineTo(SkBits2Float(0x40848cae), SkBits2Float(0xc2a5cb0c));
path.close();
SkPath path2(path);
- testPathOp(reporter, path1, path2, (SkPathOp) 2, filename);
+ testPathOpCheck(reporter, path1, path2, (SkPathOp) 2, filename, FLAGS_runFail);
}
// op end success 1
@@ -6292,7 +6297,7 @@ path.lineTo(SkBits2Float(0x429ff91f), SkBits2Float(0xc1b14b8a));
path.close();
SkPath path2(path);
- testPathOp(reporter, path1, path2, (SkPathOp) 2, filename);
+ testPathOpCheck(reporter, path1, path2, (SkPathOp) 2, filename, FLAGS_runFail);
}
// op end success 1
@@ -7049,7 +7054,7 @@ path.lineTo(SkBits2Float(0x4273ad4f), SkBits2Float(0x42617d52));
path.close();
SkPath path2(path);
- testPathOp(reporter, path1, path2, (SkPathOp) 2, filename);
+ testPathOpCheck(reporter, path1, path2, (SkPathOp) 2, filename, FLAGS_runFail);
}
// op end success 1
@@ -7438,7 +7443,7 @@ path.lineTo(SkBits2Float(0x427e3109), SkBits2Float(0x42559108));
path.close();
SkPath path2(path);
- testPathOp(reporter, path1, path2, (SkPathOp) 2, filename);
+ testPathOpCheck(reporter, path1, path2, (SkPathOp) 2, filename, FLAGS_runFail);
}
// op end success 1
@@ -7555,7 +7560,7 @@ path.lineTo(SkBits2Float(0x4279eebd), SkBits2Float(0x425a890e));
path.close();
SkPath path2(path);
- testPathOp(reporter, path1, path2, (SkPathOp) 2, filename);
+ testPathOpCheck(reporter, path1, path2, (SkPathOp) 2, filename, FLAGS_runFail);
}
// op end success 1
@@ -7858,7 +7863,7 @@ path.lineTo(SkBits2Float(0x42759f2b), SkBits2Float(0x425f5e9b));
path.close();
SkPath path2(path);
- testPathOp(reporter, path1, path2, (SkPathOp) 2, filename);
+ testPathOpCheck(reporter, path1, path2, (SkPathOp) 2, filename, FLAGS_runFail);
}
// op end success 1
@@ -10681,7 +10686,7 @@ path.close();
testPathOp(reporter, path1, path2, (SkPathOp) 2, filename);
}
-static void (*firstTest)(skiatest::Reporter* , const char* filename) = battleOp1394;
+static void (*firstTest)(skiatest::Reporter* , const char* filename) = battleOp68;
static void (*stopTest)(skiatest::Reporter* , const char* filename) = 0;
static struct TestDesc tests[] = {
@@ -11123,5 +11128,5 @@ DEF_TEST(PathOpsBattle, reporter) {
#if DEBUG_SHOW_TEST_NAME
strncpy(DEBUG_FILENAME_STRING, "", DEBUG_FILENAME_STRING_LENGTH);
#endif
- RunTestSet(reporter, tests, testCount, firstTest, NULL, stopTest, runReverse);
+ RunTestSet(reporter, tests, testCount, firstTest, stopTest, runReverse);
}
diff --git a/tests/PathOpsBuilderTest.cpp b/tests/PathOpsBuilderTest.cpp
index 5fdeb3e2b9..1eadebc550 100644
--- a/tests/PathOpsBuilderTest.cpp
+++ b/tests/PathOpsBuilderTest.cpp
@@ -4,10 +4,7 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
-
-#include "PathOpsExtendedTest.h"
#include "PathOpsTestCommon.h"
-#include "SkBitmap.h"
#include "Test.h"
DEF_TEST(PathOpsBuilder, reporter) {
@@ -25,7 +22,6 @@ DEF_TEST(PathOpsBuilder, reporter) {
REPORTER_ASSERT(reporter, result.isEmpty());
SkPath rectPath;
- rectPath.setFillType(SkPath::kEvenOdd_FillType);
rectPath.addRect(0, 1, 2, 3, SkPath::kCW_Direction);
builder.add(rectPath, kUnion_PathOp);
REPORTER_ASSERT(reporter, builder.resolve(&result));
@@ -37,14 +33,13 @@ DEF_TEST(PathOpsBuilder, reporter) {
REPORTER_ASSERT(reporter, rectPath == result);
rectPath.reset();
- rectPath.setFillType(SkPath::kEvenOdd_FillType);
rectPath.addRect(0, 1, 2, 3, SkPath::kCCW_Direction);
builder.add(rectPath, kUnion_PathOp);
REPORTER_ASSERT(reporter, builder.resolve(&result));
REPORTER_ASSERT(reporter, result.isRect(NULL, &closed, &dir));
REPORTER_ASSERT(reporter, closed);
REPORTER_ASSERT(reporter, dir == SkPath::kCCW_Direction);
- REPORTER_ASSERT(reporter, rectPath == result);
+ REPORTER_ASSERT(reporter, rectPath == result);
builder.add(rectPath, kDifference_PathOp);
REPORTER_ASSERT(reporter, builder.resolve(&result));
@@ -74,7 +69,5 @@ DEF_TEST(PathOpsBuilder, reporter) {
builder.add(circle2, kUnion_PathOp);
builder.add(circle3, kDifference_PathOp);
REPORTER_ASSERT(reporter, builder.resolve(&result));
- SkBitmap bitmap;
- int pixelDiff = comparePaths(reporter, __FUNCTION__, opCompare, result, bitmap);
- REPORTER_ASSERT(reporter, pixelDiff == 0);
+ REPORTER_ASSERT(reporter, opCompare == result);
}
diff --git a/tests/PathOpsCubicIntersectionTest.cpp b/tests/PathOpsCubicIntersectionTest.cpp
index a424c50c55..b6a9e5910a 100644
--- a/tests/PathOpsCubicIntersectionTest.cpp
+++ b/tests/PathOpsCubicIntersectionTest.cpp
@@ -6,7 +6,6 @@
*/
#include "PathOpsCubicIntersectionTestData.h"
#include "PathOpsTestCommon.h"
-#include "SkGeometry.h"
#include "SkIntersections.h"
#include "SkPathOpsRect.h"
#include "SkReduceOrder.h"
@@ -163,60 +162,6 @@ static const SkDCubic testSet[] = {
const int testSetCount = (int) SK_ARRAY_COUNT(testSet);
static const SkDCubic newTestSet[] = {
-{{{980.026001,1481.276}, {980.026001,1481.276}, {980.02594,1481.27576}, {980.025879,1481.27527}}},
-{{{980.025879,1481.27527}, {980.025452,1481.27222}, {980.023743,1481.26038}, {980.02179,1481.24072}}},
-
-{{{1.80943513,3.07782435}, {1.66686702,2.16806936}, {1.68301272,0}, {3,0}}},
-{{{0,1}, {0,3}, {3,2}, {5,2}}},
-
-{{{3.4386673,2.66977954}, {4.06668949,2.17046738}, {4.78887367,1.59629118}, {6,2}}},
-{{{1.71985495,3.49467373}, {2.11620402,2.7201426}, {2.91897964,1.15138781}, {6,3}}},
-
-{{{0,1}, {0.392703831,1.78540766}, {0.219947904,2.05676103}, {0.218561709,2.05630541}}},
-{{{0.218561709,2.05630541}, {0.216418028,2.05560064}, {0.624105453,1.40486407}, {4.16666651,1.00000012}}},
-
-{{{0, 1}, {3, 5}, {2, 1}, {3, 1}}},
-{{{1.01366711f, 2.21379328f}, {1.09074128f, 2.23241305f}, {1.60246587f, 0.451849401f}, {5, 3}}},
-
-{{{0, 1}, {0.541499972f, 3.16599989f}, {1.08299994f, 2.69299984f}, {2.10083938f, 1.80391729f}}},
-{{{0.806384504f, 2.85426903f}, {1.52740121f, 1.99355423f}, {2.81689167f, 0.454222918f}, {5, 1}}},
-
-{{{0, 1}, {1.90192389f, 2.90192389f}, {2.59807634f, 2.79422879f}, {3.1076951f, 2.71539044f}}},
-{{{2, 3}, {2.36602545f, 3.36602545f}, {2.330127f, 3.06217766f}, {2.28460979f, 2.67691422f}}},
-
-{{{0, 1}, {1.90192389f, 2.90192389f}, {2.59807634f, 2.79422879f}, {3.1076951f, 2.71539044f}}},
-{{{2.28460979f, 2.67691422f}, {2.20577145f, 2.00961876f}, {2.09807634f, 1.09807622f}, {4, 3}}},
-
-{{{0, 1}, {0.8211091160774231, 2.0948121547698975}, {0.91805583238601685, 2.515404224395752}, {0.91621249914169312, 2.5146586894989014}}},
-{{{0.91621249914169312, 2.5146586894989014}, {0.91132104396820068, 2.5126807689666748}, {0.21079301834106445, -0.45617169141769409}, {10.5, -1.6666665077209473}}},
-
-{{{42.6237564,68.9841232}, {32.449646,81.963089}, {14.7713947,103.565269}, {12.6310005,105.247002}}},
-{{{37.2640038,95.3540039}, {37.2640038,95.3540039}, {11.3710003,83.7339935}, {-25.0779991,124.912003}}},
-
-{{{0,1}, {4,5}, {6,0}, {1,0}}},
-{{{0,6}, {0,1}, {1,0}, {5,4}}},
-
-{{{0,1}, {4,6}, {5,1}, {6,2}}},
-{{{1,5}, {2,6}, {1,0}, {6,4}}},
-
-{{{322, 896.04803466796875}, {314.09201049804687, 833.4376220703125}, {260.24713134765625, 785}, {195, 785}}},
-{{{195, 785}, {265.14016723632812, 785}, {322, 842.30755615234375}, {322, 913}}},
-
-{{{1, 4}, {4, 5}, {3, 2}, {6, 3}}},
-{{{2, 3}, {3, 6}, {4, 1}, {5, 4}}},
-
-{{{67, 913}, {67, 917.388916015625}, {67.224380493164063, 921.72576904296875}, {67.662384033203125, 926}}},
-{{{194, 1041}, {123.85984039306641, 1041}, {67, 983.69244384765625}, {67, 913}}},
-
-{{{1,4}, {1,5}, {6,0}, {5,1}}},
-{{{0,6}, {1,5}, {4,1}, {5,1}}},
-
-{{{0,1}, {4,5}, {6,0}, {1,0}}},
-{{{0,6}, {0,1}, {1,0}, {5,4}}},
-
-{{{0,1}, {4,6}, {2,0}, {2,0}}},
-{{{0,2}, {0,2}, {1,0}, {6,4}}},
-
{{{980.9000244140625, 1474.3280029296875}, {980.9000244140625, 1474.3280029296875}, {978.89300537109375, 1471.95703125}, {981.791015625, 1469.487060546875}}},
{{{981.791015625, 1469.487060546875}, {981.791015625, 1469.4859619140625}, {983.3580322265625, 1472.72900390625}, {980.9000244140625, 1474.3280029296875}}},
@@ -361,6 +306,7 @@ static const SkDCubic newTestSet[] = {
};
const int newTestSetCount = (int) SK_ARRAY_COUNT(newTestSet);
+
static void oneOff(skiatest::Reporter* reporter, const SkDCubic& cubic1, const SkDCubic& cubic2,
bool coin) {
SkASSERT(ValidCubic(cubic1));
@@ -374,22 +320,28 @@ static void oneOff(skiatest::Reporter* reporter, const SkDCubic& cubic1, const S
cubic2[0].fX, cubic2[0].fY, cubic2[1].fX, cubic2[1].fY,
cubic2[2].fX, cubic2[2].fY, cubic2[3].fX, cubic2[3].fY);
#endif
-#if DEBUG_T_SECT_DUMP > 1
- gDumpTSectNum = 0;
-#endif
- SkIntersections intersections;
- intersections.intersect(cubic1, cubic2);
-#if DEBUG_T_SECT_DUMP == 3
- SkDebugf("</div>\n\n");
- SkDebugf("<script type=\"text/javascript\">\n\n");
- SkDebugf("var testDivs = [\n");
- for (int index = 1; index <= gDumpTSectNum; ++index) {
- SkDebugf("sect%d,\n", index);
+ SkTArray<SkDQuad, true> quads1;
+ CubicToQuads(cubic1, cubic1.calcPrecision(), quads1);
+#if ONE_OFF_DEBUG
+ SkDebugf("computed quadratics set 1\n");
+ for (int index = 0; index < quads1.count(); ++index) {
+ const SkDQuad& q = quads1[index];
+ SkDebugf(" {{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}},\n", q[0].fX, q[0].fY,
+ q[1].fX, q[1].fY, q[2].fX, q[2].fY);
}
#endif
- if (coin && intersections.used() != 2) {
- SkDebugf("");
+ SkTArray<SkDQuad, true> quads2;
+ CubicToQuads(cubic2, cubic2.calcPrecision(), quads2);
+#if ONE_OFF_DEBUG
+ SkDebugf("computed quadratics set 2\n");
+ for (int index = 0; index < quads2.count(); ++index) {
+ const SkDQuad& q = quads2[index];
+ SkDebugf(" {{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}},\n", q[0].fX, q[0].fY,
+ q[1].fX, q[1].fY, q[2].fX, q[2].fY);
}
+#endif
+ SkIntersections intersections;
+ intersections.intersect(cubic1, cubic2);
REPORTER_ASSERT(reporter, !coin || intersections.used() == 2);
double tt1, tt2;
SkDPoint xy1, xy2;
@@ -606,30 +558,37 @@ int selfSetCount = (int) SK_ARRAY_COUNT(selfSet);
static void selfOneOff(skiatest::Reporter* reporter, int index) {
const SkDCubic& cubic = selfSet[index];
- SkPoint c[4];
- for (int i = 0; i < 4; ++i) {
- c[i] = cubic[i].asSkPoint();
+#if ONE_OFF_DEBUG
+ int idx2;
+ double max[3];
+ int ts = cubic.findMaxCurvature(max);
+ for (idx2 = 0; idx2 < ts; ++idx2) {
+ SkDebugf("%s max[%d]=%1.9g (%1.9g, %1.9g)\n", __FUNCTION__, idx2,
+ max[idx2], cubic.ptAtT(max[idx2]).fX, cubic.ptAtT(max[idx2]).fY);
}
- SkScalar loopT;
- SkScalar d[3];
- SkCubicType cubicType = SkClassifyCubic(c, d);
- if (SkDCubic::ComplexBreak(c, &loopT) && cubicType == SkCubicType::kLoop_SkCubicType) {
- SkIntersections i;
- SkPoint twoCubics[7];
- SkChopCubicAt(c, twoCubics, loopT);
- SkDCubic chopped[2];
- chopped[0].set(&twoCubics[0]);
- chopped[1].set(&twoCubics[3]);
- int result = i.intersect(chopped[0], chopped[1]);
- REPORTER_ASSERT(reporter, result == 2);
- REPORTER_ASSERT(reporter, i.used() == 2);
- for (int index = 0; index < result; ++index) {
- SkDPoint pt1 = chopped[0].ptAtT(i[0][index]);
- SkDPoint pt2 = chopped[1].ptAtT(i[1][index]);
- REPORTER_ASSERT(reporter, pt1.approximatelyEqual(pt2));
- reporter->bumpTestCount();
- }
+ SkTArray<double, true> ts1;
+ SkTArray<SkDQuad, true> quads1;
+ cubic.toQuadraticTs(cubic.calcPrecision(), &ts1);
+ for (idx2 = 0; idx2 < ts1.count(); ++idx2) {
+ SkDebugf("%s t[%d]=%1.9g\n", __FUNCTION__, idx2, ts1[idx2]);
+ }
+ CubicToQuads(cubic, cubic.calcPrecision(), quads1);
+ for (idx2 = 0; idx2 < quads1.count(); ++idx2) {
+ const SkDQuad& q = quads1[idx2];
+ SkDebugf(" {{{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}}},\n",
+ q[0].fX, q[0].fY, q[1].fX, q[1].fY, q[2].fX, q[2].fY);
}
+ SkDebugf("\n");
+#endif
+ SkIntersections i;
+ int result = i.intersect(cubic);
+ REPORTER_ASSERT(reporter, result == 1);
+ REPORTER_ASSERT(reporter, i.used() == 1);
+ REPORTER_ASSERT(reporter, !approximately_equal(i[0][0], i[1][0]));
+ SkDPoint pt1 = cubic.ptAtT(i[0][0]);
+ SkDPoint pt2 = cubic.ptAtT(i[1][0]);
+ REPORTER_ASSERT(reporter, pt1.approximatelyEqual(pt2));
+ reporter->bumpTestCount();
}
static void cubicIntersectionSelfTest(skiatest::Reporter* reporter) {
@@ -640,12 +599,12 @@ static void cubicIntersectionSelfTest(skiatest::Reporter* reporter) {
}
static const SkDCubic coinSet[] = {
- {{{2, 3}, {0, 4}, {3, 2}, {5, 3}}},
- {{{2, 3}, {0, 4}, {3, 2}, {5, 3}}},
-
{{{317, 711}, {322.52285766601562, 711}, {327, 715.4771728515625}, {327, 721}}},
{{{324.07107543945312, 713.928955078125}, {324.4051513671875, 714.26300048828125},
{324.71566772460937, 714.62060546875}, {325, 714.9990234375}}},
+
+ {{{2, 3}, {0, 4}, {3, 2}, {5, 3}}},
+ {{{2, 3}, {0, 4}, {3, 2}, {5, 3}}},
};
static int coinSetCount = (int) SK_ARRAY_COUNT(coinSet);
@@ -683,72 +642,3 @@ DEF_TEST(PathOpsCubicIntersection, reporter) {
if (false) CubicIntersection_IntersectionFinder();
if (false) CubicIntersection_RandTest(reporter);
}
-
-static void binaryTest(const SkDCubic& cubic1, const SkDCubic& cubic2,
- skiatest::Reporter* reporter) {
- SkASSERT(ValidCubic(cubic1));
- SkASSERT(ValidCubic(cubic2));
- SkIntersections intersections;
- SkReduceOrder reduce1, reduce2;
- int order1 = reduce1.reduce(cubic1, SkReduceOrder::kNo_Quadratics);
- int order2 = reduce2.reduce(cubic2, SkReduceOrder::kNo_Quadratics);
- if (order1 == 4 && order2 == 4) {
- intersections.intersect(cubic1, cubic2);
- } else {
- intersections.reset();
- }
- SkIntersections intersections2;
- (void) intersections2.intersect(cubic1, cubic2);
- REPORTER_ASSERT(reporter, intersections.used() <= intersections2.used()
- || intersections[0][0] + 0.01 > intersections[0][1]);
- for (int index = 0; index < intersections2.used(); ++index) {
-// SkASSERT(intersections.pt(index).approximatelyEqual(intersections2.pt(index)));
- double tt1 = intersections2[0][index];
- SkDPoint xy1 = cubic1.ptAtT(tt1);
- double tt2 = intersections2[1][index];
- SkDPoint xy2 = cubic2.ptAtT(tt2);
- REPORTER_ASSERT(reporter, xy1.approximatelyEqual(xy2));
- }
-}
-
-DEF_TEST(PathOpsCubicBinaryTest, reporter) {
- int outer = 0;
- int inner = outer + 1;
- do {
- const SkDCubic& cubic1 = testSet[outer];
- const SkDCubic& cubic2 = testSet[inner];
- binaryTest(cubic1, cubic2, reporter);
- inner += 2;
- outer += 2;
- } while (outer < (int) testSetCount);
-}
-
-DEF_TEST(PathOpsCubicBinaryNew, reporter) {
- int outer = 62;
- int inner = outer + 1;
- do {
- const SkDCubic& cubic1 = newTestSet[outer];
- const SkDCubic& cubic2 = newTestSet[inner];
- binaryTest(cubic1, cubic2, reporter);
- inner += 2;
- outer += 2;
- } while (outer < (int) newTestSetCount);
-}
-
-DEF_TEST(PathOpsCubicBinaryStd, reporter) {
- const int firstTest = 0;
- for (size_t index = firstTest; index < tests_count; ++index) {
- const SkDCubic& cubic1 = tests[index][0];
- const SkDCubic& cubic2 = tests[index][1];
- binaryTest(cubic1, cubic2, reporter);
- }
-}
-
-DEF_TEST(PathOpsCubicBinaryCoin, reporter) {
- int firstFail = 0;
- for (int index = firstFail; index < coinSetCount; index += 2) {
- const SkDCubic& cubic1 = coinSet[index];
- const SkDCubic& cubic2 = coinSet[index + 1];
- binaryTest(cubic1, cubic2, reporter);
- }
-}
diff --git a/tests/PathOpsCubicIntersectionTestData.cpp b/tests/PathOpsCubicIntersectionTestData.cpp
index 7f725ef9fd..31056d2552 100644
--- a/tests/PathOpsCubicIntersectionTestData.cpp
+++ b/tests/PathOpsCubicIntersectionTestData.cpp
@@ -46,8 +46,8 @@ const SkDCubic pointDegenerates[] = {
const size_t pointDegenerates_count = SK_ARRAY_COUNT(pointDegenerates);
const SkDCubic notPointDegenerates[] = {
- {{{1 + FLT_EPSILON * 8, 1}, {1, FLT_EPSILON * 8}, {1, 1}, {1, 1}}},
- {{{1 + FLT_EPSILON * 8, 1}, {1 - FLT_EPSILON * 8, 1}, {1, 1}, {1, 1}}}
+ {{{1 + FLT_EPSILON * 2, 1}, {1, FLT_EPSILON * 2}, {1, 1}, {1, 1}}},
+ {{{1 + FLT_EPSILON * 2, 1}, {1 - FLT_EPSILON * 2, 1}, {1, 1}, {1, 1}}}
};
const size_t notPointDegenerates_count =
@@ -156,8 +156,8 @@ const SkDCubic notLines[] = {
const size_t notLines_count = SK_ARRAY_COUNT(notLines);
-static const double E = FLT_EPSILON * 8;
-static const double F = FLT_EPSILON * 8;
+static const double E = FLT_EPSILON * 2;
+static const double F = FLT_EPSILON * 3;
const SkDCubic modEpsilonLines[] = {
{{{0, E}, {0, 0}, {0, 0}, {1, 0}}}, // horizontal
@@ -187,8 +187,8 @@ const SkDCubic modEpsilonLines[] = {
{{{1, 1}, {2, 2}, {2, 2+E}, {1, 1}}},
{{{1, 1}, {1, 1+E}, {3, 3}, {3, 3}}}, // first-middle middle-last coincident
{{{1, 1}, {2+E, 2}, {3, 3}, {4, 4}}}, // no coincident
- {{{1, 1}, {3, 3}, {2, 2}, {4, 4+F+F}}}, // INVESTIGATE: why the epsilon is bigger
- {{{1, 1+F+F}, {2, 2}, {4, 4}, {3, 3}}}, // INVESTIGATE: why the epsilon is bigger
+ {{{1, 1}, {3, 3}, {2, 2}, {4, 4+F}}}, // INVESTIGATE: why the epsilon is bigger
+ {{{1, 1+F}, {2, 2}, {4, 4}, {3, 3}}}, // INVESTIGATE: why the epsilon is bigger
{{{1, 1}, {3, 3}, {4, 4+E}, {2, 2}}},
{{{1, 1}, {4, 4}, {2, 2}, {3, 3+E}}},
{{{1, 1}, {4, 4}, {3, 3}, {2+E, 2}}},
diff --git a/tests/PathOpsCubicLineIntersectionTest.cpp b/tests/PathOpsCubicLineIntersectionTest.cpp
index 6fdce3cb18..234a53805f 100644
--- a/tests/PathOpsCubicLineIntersectionTest.cpp
+++ b/tests/PathOpsCubicLineIntersectionTest.cpp
@@ -49,9 +49,6 @@ static void testFail(skiatest::Reporter* reporter, int iIndex) {
}
static lineCubic lineCubicTests[] = {
- {{{{0.468027353,4}, {1.06734705,1.33333337}, {1.36700678,0}, {3,0}}},
- {{{2,1}, {0,1}}}},
-
{{{{-634.60540771484375, -481.262939453125}, {266.2696533203125, -752.70867919921875},
{-751.8370361328125, -317.37921142578125}, {-969.7427978515625, 824.7255859375}}},
{{{-287.9506133720805678, -557.1376476615772617},
diff --git a/tests/PathOpsCubicQuadIntersectionTest.cpp b/tests/PathOpsCubicQuadIntersectionTest.cpp
index d1ce05b638..967dfc7f4e 100644
--- a/tests/PathOpsCubicQuadIntersectionTest.cpp
+++ b/tests/PathOpsCubicQuadIntersectionTest.cpp
@@ -15,32 +15,44 @@
static struct quadCubic {
SkDCubic cubic;
SkDQuad quad;
+ int answerCount;
+ SkDPoint answers[2];
} quadCubicTests[] = {
+#if 0 // FIXME : this should not fail (root problem behind skpcarrot_is24 )
{{{{1020.08099,672.161987}, {1020.08002,630.73999}, {986.502014,597.161987}, {945.080994,597.161987}}},
- {{{1020,672}, {1020,640.93396}, {998.03302,618.96698}}}},
+ {{{1020,672}, {1020,640.93396}, {998.03302,618.96698}}}, 1,
+ {{1019.421, 662.449}}},
+#endif
{{{{778, 14089}, {778, 14091.208984375}, {776.20916748046875, 14093}, {774, 14093}}},
- {{{778, 14089}, {777.99957275390625, 14090.65625}, {776.82843017578125, 14091.828125}}}},
+ {{{778, 14089}, {777.99957275390625, 14090.65625}, {776.82843017578125, 14091.828125}}}, 2,
+ {{778, 14089}, {776.82855609581270,14091.828250841330}}},
{{{{1110, 817}, {1110.55225f, 817}, {1111, 817.447693f}, {1111, 818}}},
- {{{1110.70715f, 817.292908f}, {1110.41406f, 817.000122f}, {1110, 817}}}},
+ {{{1110.70715f, 817.292908f}, {1110.41406f, 817.000122f}, {1110, 817}}}, 2,
+ {{1110, 817}, {1110.70715f, 817.292908f}}},
{{{{1110, 817}, {1110.55225f, 817}, {1111, 817.447693f}, {1111, 818}}},
- {{{1111, 818}, {1110.99988f, 817.585876f}, {1110.70715f, 817.292908f}}}},
+ {{{1111, 818}, {1110.99988f, 817.585876f}, {1110.70715f, 817.292908f}}}, 2,
+ {{1110.70715f, 817.292908f}, {1111, 818}}},
{{{{55, 207}, {52.238574981689453, 207}, {50, 204.76142883300781}, {50, 202}}},
{{{55, 207}, {52.929431915283203, 206.99949645996094},
- {51.464466094970703, 205.53553771972656}}}},
+ {51.464466094970703, 205.53553771972656}}}, 2,
+ {{55, 207}, {51.464466094970703, 205.53553771972656}}},
{{{{49, 47}, {49, 74.614250183105469}, {26.614250183105469, 97}, {-1, 97}}},
{{{-8.659739592076221e-015, 96.991401672363281}, {20.065492630004883, 96.645187377929688},
- {34.355339050292969, 82.355339050292969}}}},
+ {34.355339050292969, 82.355339050292969}}}, 2,
+ {{34.355339050292969,82.355339050292969}, {34.28654835573549, 82.424006509351585}}},
{{{{10,234}, {10,229.58172607421875}, {13.581720352172852,226}, {18,226}}},
- {{{18,226}, {14.686291694641113,226}, {12.342399597167969,228.3424072265625}}}},
+ {{{18,226}, {14.686291694641113,226}, {12.342399597167969,228.3424072265625}}}, 1,
+ {{18,226}, {0,0}}},
{{{{10,234}, {10,229.58172607421875}, {13.581720352172852,226}, {18,226}}},
- {{{12.342399597167969,228.3424072265625}, {10,230.68629455566406}, {10,234}}}},
+ {{{12.342399597167969,228.3424072265625}, {10,230.68629455566406}, {10,234}}}, 1,
+ {{10,234}, {0,0}}},
};
static const int quadCubicTests_count = (int) SK_ARRAY_COUNT(quadCubicTests);
@@ -63,9 +75,9 @@ static void cubicQuadIntersection(skiatest::Reporter* reporter, int index) {
SkDebugf("[%d] quad order=%d\n", iIndex, order2);
REPORTER_ASSERT(reporter, 0);
}
- SkDCubic quadToCubic = quad.toCubic();
SkIntersections i;
- int roots = i.intersect(cubic, quadToCubic);
+ int roots = i.intersect(cubic, quad);
+ SkASSERT(roots == quadCubicTests[index].answerCount);
for (int pt = 0; pt < roots; ++pt) {
double tt1 = i[0][pt];
SkDPoint xy1 = cubic.ptAtT(tt1);
@@ -76,6 +88,15 @@ static void cubicQuadIntersection(skiatest::Reporter* reporter, int index) {
__FUNCTION__, iIndex, pt, tt1, xy1.fX, xy1.fY, tt2, xy2.fX, xy2.fY);
}
REPORTER_ASSERT(reporter, xy1.approximatelyEqual(xy2));
+ bool found = false;
+ for (int idx2 = 0; idx2 < quadCubicTests[index].answerCount; ++idx2) {
+ found |= quadCubicTests[index].answers[idx2].approximatelyEqual(xy1);
+ }
+ if (!found) {
+ SkDebugf("%s [%d,%d] xy1=(%g,%g) != \n",
+ __FUNCTION__, iIndex, pt, xy1.fX, xy1.fY);
+ }
+ REPORTER_ASSERT(reporter, found);
}
reporter->bumpTestCount();
}
@@ -90,3 +111,195 @@ DEF_TEST(PathOpsCubicQuadIntersection, reporter) {
DEF_TEST(PathOpsCubicQuadIntersectionOneOff, reporter) {
cubicQuadIntersection(reporter, 0);
}
+
+static bool gPathOpCubicQuadSlopVerbose = false;
+static const int kCubicToQuadSubdivisionDepth = 8; // slots reserved for cubic to quads subdivision
+
+// determine that slop required after quad/quad finds a candidate intersection
+// use the cross of the tangents plus the distance from 1 or 0 as knobs
+DEF_TEST(PathOpsCubicQuadSlop, reporter) {
+ // create a random non-selfintersecting cubic
+ // break it into quadratics
+ // offset the quadratic, measuring the slop required to find the intersection
+ if (!gPathOpCubicQuadSlopVerbose) { // takes a while to run -- so exclude it by default
+ return;
+ }
+ int results[101];
+ sk_bzero(results, sizeof(results));
+ double minCross[101];
+ sk_bzero(minCross, sizeof(minCross));
+ double maxCross[101];
+ sk_bzero(maxCross, sizeof(maxCross));
+ double sumCross[101];
+ sk_bzero(sumCross, sizeof(sumCross));
+ int foundOne = 0;
+ int slopCount = 1;
+ SkRandom ran;
+ for (int index = 0; index < 10000000; ++index) {
+ if (index % 1000 == 999) SkDebugf(".");
+ SkDCubic cubic = {{
+ {ran.nextRangeF(-1000, 1000), ran.nextRangeF(-1000, 1000)},
+ {ran.nextRangeF(-1000, 1000), ran.nextRangeF(-1000, 1000)},
+ {ran.nextRangeF(-1000, 1000), ran.nextRangeF(-1000, 1000)},
+ {ran.nextRangeF(-1000, 1000), ran.nextRangeF(-1000, 1000)}
+ }};
+ SkIntersections i;
+ if (i.intersect(cubic)) {
+ continue;
+ }
+ SkSTArray<kCubicToQuadSubdivisionDepth, double, true> ts;
+ cubic.toQuadraticTs(cubic.calcPrecision(), &ts);
+ double tStart = 0;
+ int tsCount = ts.count();
+ for (int i1 = 0; i1 <= tsCount; ++i1) {
+ const double tEnd = i1 < tsCount ? ts[i1] : 1;
+ SkDCubic part = cubic.subDivide(tStart, tEnd);
+ SkDQuad quad = part.toQuad();
+ SkReduceOrder reducer;
+ int order = reducer.reduce(quad);
+ if (order != 3) {
+ continue;
+ }
+ for (int i2 = 0; i2 < 100; ++i2) {
+ SkDPoint endDisplacement = {ran.nextRangeF(-100, 100), ran.nextRangeF(-100, 100)};
+ SkDQuad nearby = {{
+ {quad[0].fX + endDisplacement.fX, quad[0].fY + endDisplacement.fY},
+ {quad[1].fX + ran.nextRangeF(-100, 100), quad[1].fY + ran.nextRangeF(-100, 100)},
+ {quad[2].fX - endDisplacement.fX, quad[2].fY - endDisplacement.fY}
+ }};
+ order = reducer.reduce(nearby);
+ if (order != 3) {
+ continue;
+ }
+ SkIntersections locals;
+ locals.allowNear(false);
+ locals.intersect(quad, nearby);
+ if (locals.used() != 1) {
+ continue;
+ }
+ // brute force find actual intersection
+ SkDLine cubicLine = {{ {0, 0}, {cubic[0].fX, cubic[0].fY } }};
+ SkIntersections liner;
+ int i3;
+ int found = -1;
+ int foundErr = true;
+ for (i3 = 1; i3 <= 1000; ++i3) {
+ cubicLine[0] = cubicLine[1];
+ cubicLine[1] = cubic.ptAtT(i3 / 1000.);
+ liner.reset();
+ liner.allowNear(false);
+ liner.intersect(nearby, cubicLine);
+ if (liner.used() == 0) {
+ continue;
+ }
+ if (liner.used() > 1) {
+ foundErr = true;
+ break;
+ }
+ if (found > 0) {
+ foundErr = true;
+ break;
+ }
+ foundErr = false;
+ found = i3;
+ }
+ if (foundErr) {
+ continue;
+ }
+ SkDVector dist = liner.pt(0) - locals.pt(0);
+ SkDVector qV = nearby.dxdyAtT(locals[0][0]);
+ double cubicT = (found - 1 + liner[1][0]) / 1000.;
+ SkDVector cV = cubic.dxdyAtT(cubicT);
+ double qxc = qV.crossCheck(cV);
+ double qvLen = qV.length();
+ double cvLen = cV.length();
+ double maxLen = SkTMax(qvLen, cvLen);
+ qxc /= maxLen;
+ double quadT = tStart + (tEnd - tStart) * locals[0][0];
+ double diffT = fabs(cubicT - quadT);
+ int diffIdx = (int) (diffT * 100);
+ results[diffIdx]++;
+ double absQxc = fabs(qxc);
+ if (sumCross[diffIdx] == 0) {
+ minCross[diffIdx] = maxCross[diffIdx] = sumCross[diffIdx] = absQxc;
+ } else {
+ minCross[diffIdx] = SkTMin(minCross[diffIdx], absQxc);
+ maxCross[diffIdx] = SkTMax(maxCross[diffIdx], absQxc);
+ sumCross[diffIdx] += absQxc;
+ }
+ if (diffIdx >= 20) {
+#if 01
+ SkDebugf("cubic={{{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}}}"
+ " quad={{{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}}}"
+ " {{{%1.9g,%1.9g}, {%1.9g,%1.9g}}}"
+ " qT=%1.9g cT=%1.9g dist=%1.9g cross=%1.9g\n",
+ cubic[0].fX, cubic[0].fY, cubic[1].fX, cubic[1].fY,
+ cubic[2].fX, cubic[2].fY, cubic[3].fX, cubic[3].fY,
+ nearby[0].fX, nearby[0].fY, nearby[1].fX, nearby[1].fY,
+ nearby[2].fX, nearby[2].fY,
+ liner.pt(0).fX, liner.pt(0).fY,
+ locals.pt(0).fX, locals.pt(0).fY, quadT, cubicT, dist.length(), qxc);
+#else
+ SkDebugf("qT=%1.9g cT=%1.9g dist=%1.9g cross=%1.9g\n",
+ quadT, cubicT, dist.length(), qxc);
+ SkDebugf("<div id=\"slop%d\">\n", ++slopCount);
+ SkDebugf("{{{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}}}\n"
+ "{{{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}}}\n"
+ "{{{%1.9g,%1.9g}, {%1.9g,%1.9g}}}\n",
+ cubic[0].fX, cubic[0].fY, cubic[1].fX, cubic[1].fY,
+ cubic[2].fX, cubic[2].fY, cubic[3].fX, cubic[3].fY,
+ nearby[0].fX, nearby[0].fY, nearby[1].fX, nearby[1].fY,
+ nearby[2].fX, nearby[2].fY,
+ liner.pt(0).fX, liner.pt(0).fY,
+ locals.pt(0).fX, locals.pt(0).fY);
+ SkDebugf("</div>\n\n");
+#endif
+ }
+ ++foundOne;
+ }
+ tStart = tEnd;
+ }
+ if (++foundOne >= 100000) {
+ break;
+ }
+ }
+#if 01
+ SkDebugf("slopCount=%d\n", slopCount);
+ int max = 100;
+ while (results[max] == 0) {
+ --max;
+ }
+ for (int i = 0; i <= max; ++i) {
+ if (i > 0 && i % 10 == 0) {
+ SkDebugf("\n");
+ }
+ SkDebugf("%d ", results[i]);
+ }
+ SkDebugf("min\n");
+ for (int i = 0; i <= max; ++i) {
+ if (i > 0 && i % 10 == 0) {
+ SkDebugf("\n");
+ }
+ SkDebugf("%1.9g ", minCross[i]);
+ }
+ SkDebugf("max\n");
+ for (int i = 0; i <= max; ++i) {
+ if (i > 0 && i % 10 == 0) {
+ SkDebugf("\n");
+ }
+ SkDebugf("%1.9g ", maxCross[i]);
+ }
+ SkDebugf("avg\n");
+ for (int i = 0; i <= max; ++i) {
+ if (i > 0 && i % 10 == 0) {
+ SkDebugf("\n");
+ }
+ SkDebugf("%1.9g ", sumCross[i] / results[i]);
+ }
+#else
+ for (int i = 1; i < slopCount; ++i) {
+ SkDebugf(" slop%d,\n", i);
+ }
+#endif
+ SkDebugf("\n");
+}
diff --git a/tests/PathOpsCubicToQuadsTest.cpp b/tests/PathOpsCubicToQuadsTest.cpp
new file mode 100644
index 0000000000..ab22a83ca8
--- /dev/null
+++ b/tests/PathOpsCubicToQuadsTest.cpp
@@ -0,0 +1,198 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "PathOpsCubicIntersectionTestData.h"
+#include "PathOpsQuadIntersectionTestData.h"
+#include "PathOpsTestCommon.h"
+#include "SkGeometry.h"
+#include "SkIntersections.h"
+#include "SkPathOpsRect.h"
+#include "SkReduceOrder.h"
+#include "Test.h"
+
+static void test(skiatest::Reporter* reporter, const SkDCubic* cubics, const char* name,
+ int firstTest, size_t testCount) {
+ for (size_t index = firstTest; index < testCount; ++index) {
+ const SkDCubic& cubic = cubics[index];
+ SkASSERT(ValidCubic(cubic));
+ double precision = cubic.calcPrecision();
+ SkTArray<SkDQuad, true> quads;
+ CubicToQuads(cubic, precision, quads);
+ if (quads.count() != 1 && quads.count() != 2) {
+ SkDebugf("%s [%d] cubic to quadratics failed count=%d\n", name, static_cast<int>(index),
+ quads.count());
+ }
+ REPORTER_ASSERT(reporter, quads.count() == 1);
+ }
+}
+
+static void test(skiatest::Reporter* reporter, const SkDQuad* quadTests, const char* name,
+ int firstTest, size_t testCount) {
+ for (size_t index = firstTest; index < testCount; ++index) {
+ const SkDQuad& quad = quadTests[index];
+ SkASSERT(ValidQuad(quad));
+ SkDCubic cubic = quad.toCubic();
+ double precision = cubic.calcPrecision();
+ SkTArray<SkDQuad, true> quads;
+ CubicToQuads(cubic, precision, quads);
+ if (quads.count() != 1 && quads.count() != 2) {
+ SkDebugf("%s [%d] cubic to quadratics failed count=%d\n", name, static_cast<int>(index),
+ quads.count());
+ }
+ REPORTER_ASSERT(reporter, quads.count() <= 2);
+ }
+}
+
+static void testC(skiatest::Reporter* reporter, const SkDCubic* cubics, const char* name,
+ int firstTest, size_t testCount) {
+ // test if computed line end points are valid
+ for (size_t index = firstTest; index < testCount; ++index) {
+ const SkDCubic& cubic = cubics[index];
+ SkASSERT(ValidCubic(cubic));
+ double precision = cubic.calcPrecision();
+ SkTArray<SkDQuad, true> quads;
+ CubicToQuads(cubic, precision, quads);
+ if (!AlmostEqualUlps(cubic[0].fX, quads[0][0].fX)
+ || !AlmostEqualUlps(cubic[0].fY, quads[0][0].fY)) {
+ SkDebugf("[%d] unmatched start\n", static_cast<int>(index));
+ REPORTER_ASSERT(reporter, 0);
+ }
+ int last = quads.count() - 1;
+ if (!AlmostEqualUlps(cubic[3].fX, quads[last][2].fX)
+ || !AlmostEqualUlps(cubic[3].fY, quads[last][2].fY)) {
+ SkDebugf("[%d] unmatched end\n", static_cast<int>(index));
+ REPORTER_ASSERT(reporter, 0);
+ }
+ }
+}
+
+static void testC(skiatest::Reporter* reporter, const SkDCubic(* cubics)[2], const char* name,
+ int firstTest, size_t testCount) {
+ for (size_t index = firstTest; index < testCount; ++index) {
+ for (int idx2 = 0; idx2 < 2; ++idx2) {
+ const SkDCubic& cubic = cubics[index][idx2];
+ SkASSERT(ValidCubic(cubic));
+ double precision = cubic.calcPrecision();
+ SkTArray<SkDQuad, true> quads;
+ CubicToQuads(cubic, precision, quads);
+ if (!AlmostEqualUlps(cubic[0].fX, quads[0][0].fX)
+ || !AlmostEqualUlps(cubic[0].fY, quads[0][0].fY)) {
+ SkDebugf("[%d][%d] unmatched start\n", static_cast<int>(index), idx2);
+ REPORTER_ASSERT(reporter, 0);
+ }
+ int last = quads.count() - 1;
+ if (!AlmostEqualUlps(cubic[3].fX, quads[last][2].fX)
+ || !AlmostEqualUlps(cubic[3].fY, quads[last][2].fY)) {
+ SkDebugf("[%d][%d] unmatched end\n", static_cast<int>(index), idx2);
+ REPORTER_ASSERT(reporter, 0);
+ }
+ }
+ }
+}
+
+DEF_TEST(CubicToQuads, reporter) {
+ enum {
+ RunAll,
+ RunPointDegenerates,
+ RunNotPointDegenerates,
+ RunLines,
+ RunNotLines,
+ RunModEpsilonLines,
+ RunLessEpsilonLines,
+ RunNegEpsilonLines,
+ RunQuadraticLines,
+ RunQuadraticModLines,
+ RunComputedLines,
+ RunComputedTests,
+ RunNone
+ } run = RunAll;
+ int firstTestIndex = 0;
+#if 0
+ run = RunComputedLines;
+ firstTestIndex = 18;
+#endif
+ int firstPointDegeneratesTest = run == RunAll ? 0 : run == RunPointDegenerates
+ ? firstTestIndex : SK_MaxS32;
+ int firstNotPointDegeneratesTest = run == RunAll ? 0 : run == RunNotPointDegenerates
+ ? firstTestIndex : SK_MaxS32;
+ int firstLinesTest = run == RunAll ? 0 : run == RunLines ? firstTestIndex : SK_MaxS32;
+ int firstNotLinesTest = run == RunAll ? 0 : run == RunNotLines ? firstTestIndex : SK_MaxS32;
+ int firstModEpsilonTest = run == RunAll ? 0 : run == RunModEpsilonLines
+ ? firstTestIndex : SK_MaxS32;
+ int firstLessEpsilonTest = run == RunAll ? 0 : run == RunLessEpsilonLines
+ ? firstTestIndex : SK_MaxS32;
+ int firstNegEpsilonTest = run == RunAll ? 0 : run == RunNegEpsilonLines
+ ? firstTestIndex : SK_MaxS32;
+ int firstQuadraticLineTest = run == RunAll ? 0 : run == RunQuadraticLines
+ ? firstTestIndex : SK_MaxS32;
+ int firstQuadraticModLineTest = run == RunAll ? 0 : run == RunQuadraticModLines
+ ? firstTestIndex : SK_MaxS32;
+ int firstComputedLinesTest = run == RunAll ? 0 : run == RunComputedLines
+ ? firstTestIndex : SK_MaxS32;
+ int firstComputedCubicsTest = run == RunAll ? 0 : run == RunComputedTests
+ ? firstTestIndex : SK_MaxS32;
+
+ test(reporter, pointDegenerates, "pointDegenerates", firstPointDegeneratesTest,
+ pointDegenerates_count);
+ testC(reporter, notPointDegenerates, "notPointDegenerates", firstNotPointDegeneratesTest,
+ notPointDegenerates_count);
+ test(reporter, lines, "lines", firstLinesTest, lines_count);
+ testC(reporter, notLines, "notLines", firstNotLinesTest, notLines_count);
+ testC(reporter, modEpsilonLines, "modEpsilonLines", firstModEpsilonTest, modEpsilonLines_count);
+ test(reporter, lessEpsilonLines, "lessEpsilonLines", firstLessEpsilonTest,
+ lessEpsilonLines_count);
+ test(reporter, negEpsilonLines, "negEpsilonLines", firstNegEpsilonTest, negEpsilonLines_count);
+ test(reporter, quadraticLines, "quadraticLines", firstQuadraticLineTest, quadraticLines_count);
+ test(reporter, quadraticModEpsilonLines, "quadraticModEpsilonLines", firstQuadraticModLineTest,
+ quadraticModEpsilonLines_count);
+ testC(reporter, lines, "computed lines", firstComputedLinesTest, lines_count);
+ testC(reporter, tests, "computed tests", firstComputedCubicsTest, tests_count);
+}
+
+static SkDCubic locals[] = {
+ {{{0, 1}, {1.9274705288631189e-19, 1.0000000000000002},
+ {0.0017190297609673323, 0.99828097023903239},
+ {0.0053709083094631276, 0.99505672974365911}}},
+ {{{14.5975863, 41.632436}, {16.3518929, 26.2639684}, {18.5165519, 7.68775139},
+ {8.03767257, 89.1628526}}},
+ {{{69.7292014, 38.6877352}, {24.7648688, 23.1501713}, {84.9283191, 90.2588441},
+ {80.392774, 61.3533852}}},
+ {{{60.776536520932126, 71.249307306133829}, {87.107894191103014, 22.377669868235323},
+ {1.4974754310666936, 68.069569937917208}, {45.261946574441133, 17.536076632112298}}},
+};
+
+static size_t localsCount = SK_ARRAY_COUNT(locals);
+
+#define DEBUG_CRASH 0
+#define TEST_AVERAGE_END_POINTS 0 // must take const off to test
+extern const bool AVERAGE_END_POINTS;
+
+static void oneOff(skiatest::Reporter* reporter, size_t x) {
+ const SkDCubic& cubic = locals[x];
+ SkASSERT(ValidCubic(cubic));
+ const SkPoint skcubic[4] = {
+ {static_cast<float>(cubic[0].fX), static_cast<float>(cubic[0].fY)},
+ {static_cast<float>(cubic[1].fX), static_cast<float>(cubic[1].fY)},
+ {static_cast<float>(cubic[2].fX), static_cast<float>(cubic[2].fY)},
+ {static_cast<float>(cubic[3].fX), static_cast<float>(cubic[3].fY)}};
+ SkScalar skinflect[2];
+ int skin = SkFindCubicInflections(skcubic, skinflect);
+ if (false) SkDebugf("%s %d %1.9g\n", __FUNCTION__, skin, skinflect[0]);
+ SkTArray<SkDQuad, true> quads;
+ double precision = cubic.calcPrecision();
+ CubicToQuads(cubic, precision, quads);
+ if (false) SkDebugf("%s quads=%d\n", __FUNCTION__, quads.count());
+}
+
+DEF_TEST(CubicsToQuadratics_OneOff_Loop, reporter) {
+ for (size_t x = 0; x < localsCount; ++x) {
+ oneOff(reporter, x);
+ }
+}
+
+DEF_TEST(CubicsToQuadratics_OneOff_Single, reporter) {
+ oneOff(reporter, 0);
+}
diff --git a/tests/PathOpsDLineTest.cpp b/tests/PathOpsDLineTest.cpp
index bfad134f77..dd86dd39e3 100644
--- a/tests/PathOpsDLineTest.cpp
+++ b/tests/PathOpsDLineTest.cpp
@@ -43,6 +43,10 @@ DEF_TEST(PathOpsLineUtilities, reporter) {
SkDebugf("%s [%d] expected left\n", __FUNCTION__, index);
REPORTER_ASSERT(reporter, 0);
}
+ line2 = line.subDivide(1, 0);
+ REPORTER_ASSERT(reporter, line[0] == line2[1] && line[1] == line2[0]);
+ line2 = SkDLine::SubDivide(pts, 1, 0);
+ REPORTER_ASSERT(reporter, line[0] == line2[1] && line[1] == line2[0]);
SkDPoint mid = line.ptAtT(.5);
REPORTER_ASSERT(reporter, approximately_equal((line[0].fX + line[1].fX) / 2, mid.fX));
REPORTER_ASSERT(reporter, approximately_equal((line[0].fY + line[1].fY) / 2, mid.fY));
diff --git a/tests/PathOpsDPointTest.cpp b/tests/PathOpsDPointTest.cpp
index e197d5d618..186d691d10 100644
--- a/tests/PathOpsDPointTest.cpp
+++ b/tests/PathOpsDPointTest.cpp
@@ -38,6 +38,7 @@ DEF_TEST(PathOpsDPoint, reporter) {
REPORTER_ASSERT(reporter, p == pt);
REPORTER_ASSERT(reporter, p.approximatelyEqual(sPt));
REPORTER_ASSERT(reporter, p.roughlyEqual(pt));
+ REPORTER_ASSERT(reporter, p.moreRoughlyEqual(pt));
p.fX = p.fY = 0;
REPORTER_ASSERT(reporter, p.fX == 0 && p.fY == 0);
REPORTER_ASSERT(reporter, p.approximatelyZero());
diff --git a/tests/PathOpsDQuadTest.cpp b/tests/PathOpsDQuadTest.cpp
new file mode 100644
index 0000000000..bd29ff11ba
--- /dev/null
+++ b/tests/PathOpsDQuadTest.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "PathOpsTestCommon.h"
+#include "SkPath.h"
+#include "SkPathOpsQuad.h"
+#include "SkRRect.h"
+#include "Test.h"
+
+static const SkDQuad tests[] = {
+ {{{1, 1}, {2, 1}, {0, 2}}},
+ {{{0, 0}, {1, 1}, {3, 1}}},
+ {{{2, 0}, {1, 1}, {2, 2}}},
+ {{{4, 0}, {0, 1}, {4, 2}}},
+ {{{0, 0}, {0, 1}, {1, 1}}},
+};
+
+static const SkDPoint inPoint[]= {
+ {1, 1.2},
+ {1, 0.8},
+ {1.8, 1},
+ {1.5, 1},
+ {0.4999, 0.5}, // was 0.5, 0.5; points on the hull are considered outside
+};
+
+static const SkDPoint outPoint[]= {
+ {1, 1.6},
+ {1, 1.5},
+ {2.2, 1},
+ {1.5, 1.5},
+ {1.1, 0.5},
+};
+
+static const size_t tests_count = SK_ARRAY_COUNT(tests);
+
+DEF_TEST(PathOpsDQuad, reporter) {
+ for (size_t index = 0; index < tests_count; ++index) {
+ const SkDQuad& quad = tests[index];
+ SkASSERT(ValidQuad(quad));
+ bool result = quad.pointInHull(inPoint[index]);
+ if (!result) {
+ SkDebugf("%s [%d] expected in hull\n", __FUNCTION__, index);
+ REPORTER_ASSERT(reporter, 0);
+ }
+ result = quad.pointInHull(outPoint[index]);
+ if (result) {
+ SkDebugf("%s [%d] expected outside hull\n", __FUNCTION__, index);
+ REPORTER_ASSERT(reporter, 0);
+ }
+ }
+}
+
+DEF_TEST(PathOpsRRect, reporter) {
+ SkPath path;
+ SkRRect rRect;
+ SkRect rect = {135, 143, 250, 177};
+ SkVector radii[4] = {{8, 8}, {8, 8}, {0, 0}, {0, 0}};
+ rRect.setRectRadii(rect, radii);
+ path.addRRect(rRect);
+}
diff --git a/tests/PathOpsDRectTest.cpp b/tests/PathOpsDRectTest.cpp
index 70d39d15c0..874e82b69a 100644
--- a/tests/PathOpsDRectTest.cpp
+++ b/tests/PathOpsDRectTest.cpp
@@ -11,6 +11,15 @@
#include "SkPathOpsRect.h"
#include "Test.h"
+static const SkDLine lineTests[] = {
+ {{{2, 1}, {2, 1}}},
+ {{{2, 1}, {1, 1}}},
+ {{{2, 1}, {2, 2}}},
+ {{{1, 1}, {2, 2}}},
+ {{{3, 0}, {2, 1}}},
+ {{{3, 2}, {1, 1}}},
+};
+
static const SkDQuad quadTests[] = {
{{{1, 1}, {2, 1}, {0, 2}}},
{{{0, 0}, {1, 1}, {3, 1}}},
@@ -25,31 +34,44 @@ static const SkDCubic cubicTests[] = {
{{{3, 0}, {2, 1}, {3, 2}, {1, 1}}},
};
+static const size_t lineTests_count = SK_ARRAY_COUNT(lineTests);
static const size_t quadTests_count = SK_ARRAY_COUNT(quadTests);
static const size_t cubicTests_count = SK_ARRAY_COUNT(cubicTests);
-static void setRawBounds(const SkDQuad& quad, SkDRect* rect) {
- rect->set(quad[0]);
- rect->add(quad[1]);
- rect->add(quad[2]);
-}
-
-static void setRawBounds(const SkDCubic& cubic, SkDRect* rect) {
- rect->set(cubic[0]);
- rect->add(cubic[1]);
- rect->add(cubic[2]);
- rect->add(cubic[3]);
-}
-
DEF_TEST(PathOpsDRect, reporter) {
size_t index;
SkDRect rect, rect2;
+ for (index = 0; index < lineTests_count; ++index) {
+ const SkDLine& line = lineTests[index];
+ SkASSERT(ValidLine(line));
+ rect.setBounds(line);
+ REPORTER_ASSERT(reporter, rect.fLeft == SkTMin(line[0].fX, line[1].fX));
+ REPORTER_ASSERT(reporter, rect.fTop == SkTMin(line[0].fY, line[1].fY));
+ REPORTER_ASSERT(reporter, rect.fRight == SkTMax(line[0].fX, line[1].fX));
+ REPORTER_ASSERT(reporter, rect.fBottom == SkTMax(line[0].fY, line[1].fY));
+ rect2.set(line[0]);
+ rect2.add(line[1]);
+ REPORTER_ASSERT(reporter, rect2.fLeft == SkTMin(line[0].fX, line[1].fX));
+ REPORTER_ASSERT(reporter, rect2.fTop == SkTMin(line[0].fY, line[1].fY));
+ REPORTER_ASSERT(reporter, rect2.fRight == SkTMax(line[0].fX, line[1].fX));
+ REPORTER_ASSERT(reporter, rect2.fBottom == SkTMax(line[0].fY, line[1].fY));
+ REPORTER_ASSERT(reporter, rect.contains(line[0]));
+ REPORTER_ASSERT(reporter, rect.intersects(&rect2));
+ }
for (index = 0; index < quadTests_count; ++index) {
const SkDQuad& quad = quadTests[index];
SkASSERT(ValidQuad(quad));
- setRawBounds(quad, &rect);
+ rect.setRawBounds(quad);
+ REPORTER_ASSERT(reporter, rect.fLeft == SkTMin(quad[0].fX,
+ SkTMin(quad[1].fX, quad[2].fX)));
+ REPORTER_ASSERT(reporter, rect.fTop == SkTMin(quad[0].fY,
+ SkTMin(quad[1].fY, quad[2].fY)));
+ REPORTER_ASSERT(reporter, rect.fRight == SkTMax(quad[0].fX,
+ SkTMax(quad[1].fX, quad[2].fX)));
+ REPORTER_ASSERT(reporter, rect.fBottom == SkTMax(quad[0].fY,
+ SkTMax(quad[1].fY, quad[2].fY)));
rect2.setBounds(quad);
- REPORTER_ASSERT(reporter, rect.intersects(rect2));
+ REPORTER_ASSERT(reporter, rect.intersects(&rect2));
// FIXME: add a recursive box subdivision method to verify that tight bounds is correct
SkDPoint leftTop = {rect2.fLeft, rect2.fTop};
REPORTER_ASSERT(reporter, rect.contains(leftTop));
@@ -59,9 +81,17 @@ DEF_TEST(PathOpsDRect, reporter) {
for (index = 0; index < cubicTests_count; ++index) {
const SkDCubic& cubic = cubicTests[index];
SkASSERT(ValidCubic(cubic));
- setRawBounds(cubic, &rect);
+ rect.setRawBounds(cubic);
+ REPORTER_ASSERT(reporter, rect.fLeft == SkTMin(cubic[0].fX,
+ SkTMin(cubic[1].fX, SkTMin(cubic[2].fX, cubic[3].fX))));
+ REPORTER_ASSERT(reporter, rect.fTop == SkTMin(cubic[0].fY,
+ SkTMin(cubic[1].fY, SkTMin(cubic[2].fY, cubic[3].fY))));
+ REPORTER_ASSERT(reporter, rect.fRight == SkTMax(cubic[0].fX,
+ SkTMax(cubic[1].fX, SkTMax(cubic[2].fX, cubic[3].fX))));
+ REPORTER_ASSERT(reporter, rect.fBottom == SkTMax(cubic[0].fY,
+ SkTMax(cubic[1].fY, SkTMax(cubic[2].fY, cubic[3].fY))));
rect2.setBounds(cubic);
- REPORTER_ASSERT(reporter, rect.intersects(rect2));
+ REPORTER_ASSERT(reporter, rect.intersects(&rect2));
// FIXME: add a recursive box subdivision method to verify that tight bounds is correct
SkDPoint leftTop = {rect2.fLeft, rect2.fTop};
REPORTER_ASSERT(reporter, rect.contains(leftTop));
diff --git a/tests/PathOpsDTriangleTest.cpp b/tests/PathOpsDTriangleTest.cpp
new file mode 100644
index 0000000000..b5e2d414a7
--- /dev/null
+++ b/tests/PathOpsDTriangleTest.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "PathOpsTestCommon.h"
+#include "SkPathOpsTriangle.h"
+#include "Test.h"
+
+static const SkDTriangle tests[] = {
+ {{{2, 0}, {3, 1}, {2, 2}}},
+ {{{3, 1}, {2, 2}, {1, 1}}},
+ {{{3, 0}, {2, 1}, {3, 2}}},
+};
+
+static const SkDPoint inPoint[] = {
+ {2.5, 1},
+ {2, 1.5},
+ {2.5, 1},
+};
+
+static const SkDPoint outPoint[] = {
+ {3, 0},
+ {2.5, 2},
+ {2.5, 2},
+};
+
+static const size_t tests_count = SK_ARRAY_COUNT(tests);
+
+DEF_TEST(PathOpsTriangleUtilities, reporter) {
+ for (size_t index = 0; index < tests_count; ++index) {
+ const SkDTriangle& triangle = tests[index];
+ SkASSERT(ValidTriangle(triangle));
+ bool result = triangle.contains(inPoint[index]);
+ if (!result) {
+ SkDebugf("%s [%d] expected point in triangle\n", __FUNCTION__, index);
+ REPORTER_ASSERT(reporter, 0);
+ }
+ result = triangle.contains(outPoint[index]);
+ if (result) {
+ SkDebugf("%s [%d] expected point outside triangle\n", __FUNCTION__, index);
+ REPORTER_ASSERT(reporter, 0);
+ }
+ }
+}
+
+static const SkDTriangle oneOff[] = {
+ {{{271.03291625750461, 5.0402503630087025e-05}, {275.21652430019037, 3.6997300650817753},
+ {279.25839233398438, 7.7416000366210938}}},
+
+ {{{271.03291625750461, 5.0402503617874572e-05}, {275.21652430019037, 3.6997300650817877},
+ {279.25839233398438, 7.7416000366210938}}}
+};
+
+static const size_t oneOff_count = SK_ARRAY_COUNT(oneOff);
+
+DEF_TEST(PathOpsTriangleOneOff, reporter) {
+ for (size_t index = 0; index < oneOff_count; ++index) {
+ const SkDTriangle& triangle = oneOff[index];
+ SkASSERT(ValidTriangle(triangle));
+ for (int inner = 0; inner < 3; ++inner) {
+ bool result = triangle.contains(triangle.fPts[inner]);
+ if (result) {
+ SkDebugf("%s [%d][%d] point on triangle is not in\n", __FUNCTION__, index, inner);
+ REPORTER_ASSERT(reporter, 0);
+ }
+ }
+ }
+}
diff --git a/tests/PathOpsDebug.cpp b/tests/PathOpsDebug.cpp
index 9930453d01..c4fbbfa695 100755
--- a/tests/PathOpsDebug.cpp
+++ b/tests/PathOpsDebug.cpp
@@ -1,12 +1,3 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "PathOpsTSectDebug.h"
-#include "SkOpCoincidence.h"
#include "SkOpContour.h"
#include "SkIntersectionHelper.h"
#include "SkOpSegment.h"
@@ -59,6 +50,7 @@ static void output_points(const SkPoint* pts, int count) {
SkDebugf(", ");
}
}
+ SkDebugf(");\n");
}
static void showPathContours(SkPath::RawIter& iter, const char* pathName) {
@@ -69,27 +61,18 @@ static void showPathContours(SkPath::RawIter& iter, const char* pathName) {
case SkPath::kMove_Verb:
SkDebugf(" %s.moveTo(", pathName);
output_points(&pts[0], 1);
- SkDebugf(");\n");
continue;
case SkPath::kLine_Verb:
SkDebugf(" %s.lineTo(", pathName);
output_points(&pts[1], 1);
- SkDebugf(");\n");
break;
case SkPath::kQuad_Verb:
SkDebugf(" %s.quadTo(", pathName);
output_points(&pts[1], 2);
- SkDebugf(");\n");
- break;
- case SkPath::kConic_Verb:
- SkDebugf(" %s.conicTo(", pathName);
- output_points(&pts[1], 2);
- SkDebugf(", %1.9gf);\n", iter.conicWeight());
break;
case SkPath::kCubic_Verb:
SkDebugf(" %s.cubicTo(", pathName);
output_points(&pts[1], 3);
- SkDebugf(");\n");
break;
case SkPath::kClose_Verb:
SkDebugf(" %s.close();\n", pathName);
@@ -185,393 +168,6 @@ void SkPathOpsDebug::WindingPrintf(int wind) {
}
#endif
-void SkDCubic::dump() const {
- dumpInner();
- SkDebugf("}},\n");
-}
-
-void SkDCubic::dumpID(int id) const {
- dumpInner();
- SkDebugf("}} id=%d\n", id);
-}
-
-static inline bool double_is_NaN(double x) { return x != x; }
-
-void SkDCubic::dumpInner() const {
- SkDebugf("{{");
- int index = 0;
- do {
- if (index != 0) {
- if (double_is_NaN(fPts[index].fX) && double_is_NaN(fPts[index].fY)) {
- return;
- }
- SkDebugf(", ");
- }
- fPts[index].dump();
- } while (++index < 3);
- if (double_is_NaN(fPts[index].fX) && double_is_NaN(fPts[index].fY)) {
- return;
- }
- SkDebugf(", ");
- fPts[index].dump();
-}
-
-void SkDLine::dump() const {
- SkDebugf("{{");
- fPts[0].dump();
- SkDebugf(", ");
- fPts[1].dump();
- SkDebugf("}},\n");
-}
-
-void SkDPoint::dump() const {
- SkDebugf("{");
- DebugDumpDouble(fX);
- SkDebugf(", ");
- DebugDumpDouble(fY);
- SkDebugf("}");
-}
-
-void SkDPoint::Dump(const SkPoint& pt) {
- SkDebugf("{");
- DebugDumpFloat(pt.fX);
- SkDebugf(", ");
- DebugDumpFloat(pt.fY);
- SkDebugf("}");
-}
-
-void SkDPoint::DumpHex(const SkPoint& pt) {
- SkDebugf("{");
- DebugDumpHexFloat(pt.fX);
- SkDebugf(", ");
- DebugDumpHexFloat(pt.fY);
- SkDebugf("}");
-}
-
-void SkDQuad::dump() const {
- dumpInner();
- SkDebugf("}},\n");
-}
-
-void SkDQuad::dumpID(int id) const {
- dumpInner();
- SkDebugf("}} id=%d\n", id);
-}
-
-void SkDQuad::dumpInner() const {
- SkDebugf("{{");
- int index = 0;
- do {
- fPts[index].dump();
- SkDebugf(", ");
- } while (++index < 2);
- fPts[index].dump();
-}
-
-void SkIntersections::dump() const {
- SkDebugf("used=%d of %d", fUsed, fMax);
- for (int index = 0; index < fUsed; ++index) {
- SkDebugf(" t=(%s%1.9g,%s%1.9g) pt=(%1.9g,%1.9g)",
- fIsCoincident[0] & (1 << index) ? "*" : "", fT[0][index],
- fIsCoincident[1] & (1 << index) ? "*" : "", fT[1][index],
- fPt[index].fX, fPt[index].fY);
- if (index < 2 && fNearlySame[index]) {
- SkDebugf(" pt2=(%1.9g,%1.9g)",fPt2[index].fX, fPt2[index].fY);
- }
- }
- SkDebugf("\n");
-}
-
-const SkOpAngle* SkPathOpsDebug::DebugAngleAngle(const SkOpAngle* angle, int id) {
- return angle->debugAngle(id);
-}
-
-SkOpContour* SkPathOpsDebug::DebugAngleContour(SkOpAngle* angle, int id) {
- return angle->debugContour(id);
-}
-
-const SkOpPtT* SkPathOpsDebug::DebugAnglePtT(const SkOpAngle* angle, int id) {
- return angle->debugPtT(id);
-}
-
-const SkOpSegment* SkPathOpsDebug::DebugAngleSegment(const SkOpAngle* angle, int id) {
- return angle->debugSegment(id);
-}
-
-const SkOpSpanBase* SkPathOpsDebug::DebugAngleSpan(const SkOpAngle* angle, int id) {
- return angle->debugSpan(id);
-}
-
-const SkOpAngle* SkPathOpsDebug::DebugContourAngle(SkOpContour* contour, int id) {
- return contour->debugAngle(id);
-}
-
-SkOpContour* SkPathOpsDebug::DebugContourContour(SkOpContour* contour, int id) {
- return contour->debugContour(id);
-}
-
-const SkOpPtT* SkPathOpsDebug::DebugContourPtT(SkOpContour* contour, int id) {
- return contour->debugPtT(id);
-}
-
-const SkOpSegment* SkPathOpsDebug::DebugContourSegment(SkOpContour* contour, int id) {
- return contour->debugSegment(id);
-}
-
-const SkOpSpanBase* SkPathOpsDebug::DebugContourSpan(SkOpContour* contour, int id) {
- return contour->debugSpan(id);
-}
-
-const SkOpAngle* SkPathOpsDebug::DebugPtTAngle(const SkOpPtT* ptT, int id) {
- return ptT->debugAngle(id);
-}
-
-SkOpContour* SkPathOpsDebug::DebugPtTContour(SkOpPtT* ptT, int id) {
- return ptT->debugContour(id);
-}
-
-const SkOpPtT* SkPathOpsDebug::DebugPtTPtT(const SkOpPtT* ptT, int id) {
- return ptT->debugPtT(id);
-}
-
-const SkOpSegment* SkPathOpsDebug::DebugPtTSegment(const SkOpPtT* ptT, int id) {
- return ptT->debugSegment(id);
-}
-
-const SkOpSpanBase* SkPathOpsDebug::DebugPtTSpan(const SkOpPtT* ptT, int id) {
- return ptT->debugSpan(id);
-}
-
-const SkOpAngle* SkPathOpsDebug::DebugSegmentAngle(const SkOpSegment* span, int id) {
- return span->debugAngle(id);
-}
-
-SkOpContour* SkPathOpsDebug::DebugSegmentContour(SkOpSegment* span, int id) {
- return span->debugContour(id);
-}
-
-const SkOpPtT* SkPathOpsDebug::DebugSegmentPtT(const SkOpSegment* span, int id) {
- return span->debugPtT(id);
-}
-
-const SkOpSegment* SkPathOpsDebug::DebugSegmentSegment(const SkOpSegment* span, int id) {
- return span->debugSegment(id);
-}
-
-const SkOpSpanBase* SkPathOpsDebug::DebugSegmentSpan(const SkOpSegment* span, int id) {
- return span->debugSpan(id);
-}
-
-const SkOpAngle* SkPathOpsDebug::DebugSpanAngle(const SkOpSpanBase* span, int id) {
- return span->debugAngle(id);
-}
-
-SkOpContour* SkPathOpsDebug::DebugSpanContour(SkOpSpanBase* span, int id) {
- return span->debugContour(id);
-}
-
-const SkOpPtT* SkPathOpsDebug::DebugSpanPtT(const SkOpSpanBase* span, int id) {
- return span->debugPtT(id);
-}
-
-const SkOpSegment* SkPathOpsDebug::DebugSpanSegment(const SkOpSpanBase* span, int id) {
- return span->debugSegment(id);
-}
-
-const SkOpSpanBase* SkPathOpsDebug::DebugSpanSpan(const SkOpSpanBase* span, int id) {
- return span->debugSpan(id);
-}
-
-void SkPathOpsDebug::DumpContours(SkTDArray<SkOpContour* >* contours) {
- int count = contours->count();
- for (int index = 0; index < count; ++index) {
- (*contours)[index]->dump();
- }
-}
-
-void SkPathOpsDebug::DumpContoursAll(SkTDArray<SkOpContour* >* contours) {
- int count = contours->count();
- for (int index = 0; index < count; ++index) {
- (*contours)[index]->dumpAll();
- }
-}
-
-void SkPathOpsDebug::DumpContoursAngles(const SkTDArray<SkOpContour* >* contours) {
- int count = contours->count();
- for (int index = 0; index < count; ++index) {
- (*contours)[index]->dumpAngles();
- }
-}
-
-void SkPathOpsDebug::DumpContoursPts(const SkTDArray<SkOpContour* >* contours) {
- int count = contours->count();
- for (int index = 0; index < count; ++index) {
- (*contours)[index]->dumpPts();
- }
-}
-
-void SkPathOpsDebug::DumpContoursPt(const SkTDArray<SkOpContour* >* contours, int segmentID) {
- int count = contours->count();
- for (int index = 0; index < count; ++index) {
- (*contours)[index]->dumpPt(segmentID);
- }
-}
-
-void SkPathOpsDebug::DumpContoursSegment(const SkTDArray<SkOpContour* >* contours,
- int segmentID) {
- if (contours->count()) {
- (*contours)[0]->dumpSegment(segmentID);
- }
-}
-
-void SkPathOpsDebug::DumpContoursSpan(const SkTDArray<SkOpContour* >* contours,
- int spanID) {
- if (contours->count()) {
- (*contours)[0]->dumpSpan(spanID);
- }
-}
-
-void SkPathOpsDebug::DumpContoursSpans(const SkTDArray<SkOpContour* >* contours) {
- int count = contours->count();
- for (int index = 0; index < count; ++index) {
- (*contours)[index]->dumpSpans();
- }
-}
-
-const SkTSpan<SkDCubic>* DebugSpan(const SkTSect<SkDCubic>* sect, int id) {
- return sect->debugSpan(id);
-}
-
-const SkTSpan<SkDQuad>* DebugSpan(const SkTSect<SkDQuad>* sect, int id) {
- return sect->debugSpan(id);
-}
-
-const SkTSpan<SkDCubic>* DebugT(const SkTSect<SkDCubic>* sect, double t) {
- return sect->debugT(t);
-}
-
-const SkTSpan<SkDQuad>* DebugT(const SkTSect<SkDQuad>* sect, double t) {
- return sect->debugT(t);
-}
-
-const SkTSpan<SkDCubic>* DebugSpan(const SkTSpan<SkDCubic>* span, int id) {
- return span->debugSpan(id);
-}
-
-const SkTSpan<SkDQuad>* DebugSpan(const SkTSpan<SkDQuad>* span, int id) {
- return span->debugSpan(id);
-}
-
-const SkTSpan<SkDCubic>* DebugT(const SkTSpan<SkDCubic>* span, double t) {
- return span->debugT(t);
-}
-
-const SkTSpan<SkDQuad>* DebugT(const SkTSpan<SkDQuad>* span, double t) {
- return span->debugT(t);
-}
-
-void Dump(const SkTSect<SkDCubic>* sect) {
- sect->dump();
-}
-
-void Dump(const SkTSect<SkDQuad>* sect) {
- sect->dump();
-}
-
-void Dump(const SkTSpan<SkDCubic>* span) {
- span->dump();
-}
-
-void Dump(const SkTSpan<SkDQuad>* span) {
- span->dump();
-}
-
-void DumpBoth(SkTSect<SkDCubic>* sect1, SkTSect<SkDCubic>* sect2) {
- sect1->dumpBoth(sect2);
-}
-
-void DumpBoth(SkTSect<SkDQuad>* sect1, SkTSect<SkDQuad>* sect2) {
- sect1->dumpBoth(sect2);
-}
-
-void DumpCoin(SkTSect<SkDCubic>* sect1) {
- sect1->dumpCoin();
-}
-
-void DumpCoin(SkTSect<SkDQuad>* sect1) {
- sect1->dumpCoin();
-}
-
-void DumpCoinCurves(SkTSect<SkDCubic>* sect1) {
- sect1->dumpCoinCurves();
-}
-
-void DumpCoinCurves(SkTSect<SkDQuad>* sect1) {
- sect1->dumpCoinCurves();
-}
-
-void DumpCurves(const SkTSect<SkDQuad>* sect) {
- sect->dumpCurves();
-}
-
-void DumpCurves(const SkTSect<SkDCubic>* sect) {
- sect->dumpCurves();
-}
-
-static void dumpTestCase(const SkDQuad& quad1, const SkDQuad& quad2, int testNo) {
- SkDebugf("\n<div id=\"quad%d\">\n", testNo);
- quad1.dumpInner();
- SkDebugf("}}, ");
- quad2.dump();
- SkDebugf("</div>\n\n");
-}
-
-static void dumpTestTrailer() {
- SkDebugf("</div>\n\n<script type=\"text/javascript\">\n\n");
- SkDebugf(" var testDivs = [\n");
-}
-
-static void dumpTestList(int testNo, double min) {
- SkDebugf(" quad%d,", testNo);
- if (min > 0) {
- SkDebugf(" // %1.9g", min);
- }
- SkDebugf("\n");
-}
-
-void DumpQ(const SkDQuad& quad1, const SkDQuad& quad2, int testNo) {
- SkDebugf("\n");
- dumpTestCase(quad1, quad2, testNo);
- dumpTestTrailer();
- dumpTestList(testNo, 0);
- SkDebugf("\n");
-}
-
-void DumpT(const SkDQuad& quad, double t) {
- SkDLine line = {{quad.ptAtT(t), quad[0]}};
- line.dump();
-}
-
-const SkOpAngle* SkOpAngle::debugAngle(int id) const {
- return this->segment()->debugAngle(id);
-}
-
-SkOpContour* SkOpAngle::debugContour(int id) {
- return this->segment()->debugContour(id);
-}
-
-const SkOpPtT* SkOpAngle::debugPtT(int id) const {
- return this->segment()->debugPtT(id);
-}
-
-const SkOpSegment* SkOpAngle::debugSegment(int id) const {
- return this->segment()->debugSegment(id);
-}
-
-const SkOpSpanBase* SkOpAngle::debugSpan(int id) const {
- return this->segment()->debugSpan(id);
-}
-
void SkOpAngle::dump() const {
dumpOne(true);
SkDebugf("\n");
@@ -579,39 +175,44 @@ void SkOpAngle::dump() const {
void SkOpAngle::dumpOne(bool functionHeader) const {
// fSegment->debugValidate();
- const SkOpSegment* segment = this->segment();
- const SkOpSpan& mSpan = *fStart->starter(fEnd);
+ const SkOpSpan& mSpan = fSegment->span(SkMin32(fStart, fEnd));
if (functionHeader) {
SkDebugf("%s ", __FUNCTION__);
}
- SkDebugf("[%d", segment->debugID());
+ SkDebugf("[%d", fSegment->debugID());
SkDebugf("/%d", debugID());
SkDebugf("] next=");
if (fNext) {
- SkDebugf("%d", fNext->fStart->segment()->debugID());
+ SkDebugf("%d", fNext->fSegment->debugID());
SkDebugf("/%d", fNext->debugID());
} else {
SkDebugf("?");
}
SkDebugf(" sect=%d/%d ", fSectorStart, fSectorEnd);
- SkDebugf(" s=%1.9g [%d] e=%1.9g [%d]", fStart->t(), fStart->debugID(),
- fEnd->t(), fEnd->debugID());
- SkDebugf(" sgn=%d windVal=%d", this->sign(), mSpan.windValue());
+ SkDebugf(" s=%1.9g [%d] e=%1.9g [%d]", fSegment->span(fStart).fT, fStart,
+ fSegment->span(fEnd).fT, fEnd);
+ SkDebugf(" sgn=%d windVal=%d", sign(), mSpan.fWindValue);
SkDebugf(" windSum=");
- SkPathOpsDebug::WindingPrintf(mSpan.windSum());
- if (mSpan.oppValue() != 0 || mSpan.oppSum() != SK_MinS32) {
- SkDebugf(" oppVal=%d", mSpan.oppValue());
+ SkPathOpsDebug::WindingPrintf(mSpan.fWindSum);
+ if (mSpan.fOppValue != 0 || mSpan.fOppSum != SK_MinS32) {
+ SkDebugf(" oppVal=%d", mSpan.fOppValue);
SkDebugf(" oppSum=");
- SkPathOpsDebug::WindingPrintf(mSpan.oppSum());
+ SkPathOpsDebug::WindingPrintf(mSpan.fOppSum);
}
- if (mSpan.done()) {
+ if (mSpan.fDone) {
SkDebugf(" done");
}
if (unorderable()) {
SkDebugf(" unorderable");
}
- if (segment->operand()) {
+ if (small()) {
+ SkDebugf(" small");
+ }
+ if (mSpan.fTiny) {
+ SkDebugf(" tiny");
+ }
+ if (fSegment->operand()) {
SkDebugf(" operand");
}
if (fStop) {
@@ -626,7 +227,7 @@ void SkOpAngle::dumpTo(const SkOpSegment* segment, const SkOpAngle* to) const {
do {
SkDebugf("%s", indent);
next->dumpOne(false);
- if (segment == next->fStart->segment()) {
+ if (segment == next->fSegment) {
if (this == fNext) {
SkDebugf(" << from");
}
@@ -640,15 +241,6 @@ void SkOpAngle::dumpTo(const SkOpSegment* segment, const SkOpAngle* to) const {
} while (next && next != first);
}
-void SkOpAngle::dumpCurves() const {
- const SkOpAngle* first = this;
- const SkOpAngle* next = this;
- do {
- next->fCurvePart.dumpID(next->segment()->debugID());
- next = next->fNext;
- } while (next && next != first);
-}
-
void SkOpAngle::dumpLoop() const {
const SkOpAngle* first = this;
const SkOpAngle* next = this;
@@ -659,541 +251,647 @@ void SkOpAngle::dumpLoop() const {
} while (next && next != first);
}
-void SkOpAngle::dumpTest() const {
+void SkOpAngle::dumpPartials() const {
const SkOpAngle* first = this;
const SkOpAngle* next = this;
do {
- SkDebugf("{ ");
- SkOpSegment* segment = next->segment();
- segment->dumpPts();
- SkDebugf(", %d, %1.9g, %1.9g, {} },\n", SkPathOpsVerbToPoints(segment->verb()) + 1,
- next->start()->t(), next->end()->t());
+ next->fCurvePart.dumpNumber();
next = next->fNext;
} while (next && next != first);
}
-bool SkOpPtT::debugMatchID(int id) const {
- int limit = this->debugLoopLimit(false);
- int loop = 0;
- const SkOpPtT* ptT = this;
- do {
- if (ptT->debugID() == id) {
- return true;
+void SkOpAngleSet::dump() const {
+ // FIXME: unimplemented
+/* This requires access to the internal SkChunkAlloc data
+ Defer implementing this until it is needed for debugging
+*/
+ SkASSERT(0);
+}
+
+void SkOpContour::dump() const {
+ int segmentCount = fSegments.count();
+ SkDebugf("((SkOpContour*) 0x%p) [%d]\n", this, debugID());
+ for (int test = 0; test < segmentCount; ++test) {
+ SkDebugf(" [%d] ((SkOpSegment*) 0x%p) [%d]\n", test, &fSegments[test],
+ fSegments[test].debugID());
+ }
+}
+
+void SkOpContour::dumpAngles() const {
+ int segmentCount = fSegments.count();
+ SkDebugf("((SkOpContour*) 0x%p) [%d]\n", this, debugID());
+ for (int test = 0; test < segmentCount; ++test) {
+ SkDebugf(" [%d] ", test);
+ fSegments[test].dumpAngles();
+ }
+}
+
+void SkOpContour::dumpCoincidence(const SkCoincidence& coin) const {
+ int thisIndex = coin.fSegments[0];
+ const SkOpSegment& s1 = fSegments[thisIndex];
+ int otherIndex = coin.fSegments[1];
+ const SkOpSegment& s2 = coin.fOther->fSegments[otherIndex];
+ SkDebugf("((SkOpSegment*) 0x%p) [%d] ((SkOpSegment*) 0x%p) [%d]\n", &s1, s1.debugID(),
+ &s2, s2.debugID());
+ for (int index = 0; index < 2; ++index) {
+ SkDebugf(" {%1.9gf, %1.9gf}", coin.fPts[0][index].fX, coin.fPts[0][index].fY);
+ if (coin.fNearly[index]) {
+ SkDebugf(" {%1.9gf, %1.9gf}", coin.fPts[1][index].fX, coin.fPts[1][index].fY);
}
- } while ((!limit || ++loop <= limit) && (ptT = ptT->next()) && ptT != this);
- return false;
+ SkDebugf(" seg1t=%1.9g seg2t=%1.9g\n", coin.fTs[0][index], coin.fTs[1][index]);
+ }
}
-const SkOpAngle* SkOpPtT::debugAngle(int id) const {
- return this->span()->debugAngle(id);
+void SkOpContour::dumpCoincidences() const {
+ int count = fCoincidences.count();
+ if (count > 0) {
+ SkDebugf("fCoincidences count=%d\n", count);
+ for (int test = 0; test < count; ++test) {
+ dumpCoincidence(fCoincidences[test]);
+ }
+ }
+ count = fPartialCoincidences.count();
+ if (count == 0) {
+ return;
+ }
+ SkDebugf("fPartialCoincidences count=%d\n", count);
+ for (int test = 0; test < count; ++test) {
+ dumpCoincidence(fPartialCoincidences[test]);
+ }
}
-SkOpContour* SkOpPtT::debugContour(int id) {
- return this->span()->debugContour(id);
+void SkOpContour::dumpPt(int index) const {
+ int segmentCount = fSegments.count();
+ for (int test = 0; test < segmentCount; ++test) {
+ const SkOpSegment& segment = fSegments[test];
+ if (segment.debugID() == index) {
+ fSegments[test].dumpPts();
+ }
+ }
}
-const SkOpPtT* SkOpPtT::debugPtT(int id) const {
- return this->span()->debugPtT(id);
+void SkOpContour::dumpPts() const {
+ int segmentCount = fSegments.count();
+ SkDebugf("((SkOpContour*) 0x%p) [%d]\n", this, debugID());
+ for (int test = 0; test < segmentCount; ++test) {
+ SkDebugf(" [%d] ", test);
+ fSegments[test].dumpPts();
+ }
}
-const SkOpSegment* SkOpPtT::debugSegment(int id) const {
- return this->span()->debugSegment(id);
+void SkOpContour::dumpSpan(int index) const {
+ int segmentCount = fSegments.count();
+ for (int test = 0; test < segmentCount; ++test) {
+ const SkOpSegment& segment = fSegments[test];
+ if (segment.debugID() == index) {
+ fSegments[test].dumpSpans();
+ }
+ }
}
-const SkOpSpanBase* SkOpPtT::debugSpan(int id) const {
- return this->span()->debugSpan(id);
+void SkOpContour::dumpSpans() const {
+ int segmentCount = fSegments.count();
+ SkDebugf("((SkOpContour*) 0x%p) [%d]\n", this, debugID());
+ for (int test = 0; test < segmentCount; ++test) {
+ SkDebugf(" [%d] ", test);
+ fSegments[test].dumpSpans();
+ }
}
-void SkOpPtT::dump() const {
- SkDebugf("seg=%d span=%d ptT=%d",
- this->segment()->debugID(), this->span()->debugID(), this->debugID());
- this->dumpBase();
- SkDebugf("\n");
+void SkDCubic::dump() const {
+ SkDebugf("{{");
+ int index = 0;
+ do {
+ fPts[index].dump();
+ SkDebugf(", ");
+ } while (++index < 3);
+ fPts[index].dump();
+ SkDebugf("}}\n");
}
-void SkOpPtT::dumpAll() const {
- contour()->indentDump();
- const SkOpPtT* next = this;
- int limit = debugLoopLimit(true);
- int loop = 0;
+void SkDCubic::dumpNumber() const {
+ SkDebugf("{{");
+ int index = 0;
+ bool dumpedOne = false;
do {
- SkDebugf("%.*s", contour()->debugIndent(), " ");
- SkDebugf("seg=%d span=%d ptT=%d",
- next->segment()->debugID(), next->span()->debugID(), next->debugID());
- next->dumpBase();
- SkDebugf("\n");
- if (limit && ++loop >= limit) {
- SkDebugf("*** abort loop ***\n");
- break;
+ if (!(fPts[index].fX == fPts[index].fX && fPts[index].fY == fPts[index].fY)) {
+ continue;
+ }
+ if (dumpedOne) {
+ SkDebugf(", ");
+ }
+ fPts[index].dump();
+ dumpedOne = true;
+ } while (++index < 3);
+ if (fPts[index].fX == fPts[index].fX && fPts[index].fY == fPts[index].fY) {
+ if (dumpedOne) {
+ SkDebugf(", ");
}
- } while ((next = next->fNext) && next != this);
- contour()->outdentDump();
+ fPts[index].dump();
+ }
+ SkDebugf("}}\n");
}
-void SkOpPtT::dumpBase() const {
- SkDebugf(" t=%1.9g pt=(%1.9g,%1.9g)%s%s", this->fT, this->fPt.fX, this->fPt.fY,
- this->fDuplicatePt ? " dup" : "", this->fDeleted ? " deleted" : "");
+void SkDLine::dump() const {
+ SkDebugf("{{");
+ fPts[0].dump();
+ SkDebugf(", ");
+ fPts[1].dump();
+ SkDebugf("}}\n");
}
-const SkOpAngle* SkOpSpanBase::debugAngle(int id) const {
- return this->segment()->debugAngle(id);
+void SkDPoint::dump() const {
+ SkDebugf("{");
+ DebugDumpDouble(fX);
+ SkDebugf(", ");
+ DebugDumpDouble(fY);
+ SkDebugf("}");
}
-SkOpContour* SkOpSpanBase::debugContour(int id) {
- return this->segment()->debugContour(id);
+void SkDPoint::Dump(const SkPoint& pt) {
+ SkDebugf("{");
+ DebugDumpFloat(pt.fX);
+ SkDebugf(", ");
+ DebugDumpFloat(pt.fY);
+ SkDebugf("}");
}
-const SkOpPtT* SkOpSpanBase::debugPtT(int id) const {
- return this->segment()->debugPtT(id);
+void SkDPoint::DumpHex(const SkPoint& pt) {
+ SkDebugf("{");
+ DebugDumpHexFloat(pt.fX);
+ SkDebugf(", ");
+ DebugDumpHexFloat(pt.fY);
+ SkDebugf("}");
}
-const SkOpSegment* SkOpSpanBase::debugSegment(int id) const {
- return this->segment()->debugSegment(id);
+void SkDQuad::dump() const {
+ dumpComma("");
}
-const SkOpSpanBase* SkOpSpanBase::debugSpan(int id) const {
- return this->segment()->debugSpan(id);
+void SkDQuad::dumpComma(const char* comma) const {
+ SkDebugf("{{");
+ int index = 0;
+ do {
+ fPts[index].dump();
+ SkDebugf(", ");
+ } while (++index < 2);
+ fPts[index].dump();
+ SkDebugf("}}%s\n", comma ? comma : "");
}
-void SkOpSpanBase::dump() const {
- this->dumpAll();
- SkDebugf("\n");
+void SkIntersectionHelper::dump() const {
+ SkDPoint::Dump(pts()[0]);
+ SkDPoint::Dump(pts()[1]);
+ if (verb() >= SkPath::kQuad_Verb) {
+ SkDPoint::Dump(pts()[2]);
+ }
+ if (verb() >= SkPath::kCubic_Verb) {
+ SkDPoint::Dump(pts()[3]);
+ }
}
-void SkOpSpanBase::dumpAll() const {
- SkDebugf("%.*s", contour()->debugIndent(), " ");
- SkDebugf("seg=%d span=%d", this->segment()->debugID(), this->debugID());
- this->dumpBase();
- SkDebugf("\n");
- this->fPtT.dumpAll();
+const SkTDArray<SkOpSpan>& SkOpSegment::debugSpans() const {
+ return fTs;
}
-void SkOpSpanBase::dumpBase() const {
- if (this->fAligned) {
- SkDebugf(" aligned");
- }
- if (this->fChased) {
- SkDebugf(" chased");
- }
- if (!this->final()) {
- this->upCast()->dumpSpan();
- }
- const SkOpSpanBase* coin = this->coinEnd();
- if (this != coin) {
- SkDebugf(" coinEnd seg/span=%d/%d", coin->segment()->debugID(), coin->debugID());
- } else if (this->final() || !this->upCast()->isCoincident()) {
- const SkOpPtT* oPt = this->ptT()->next();
- SkDebugf(" seg/span=%d/%d", oPt->segment()->debugID(), oPt->span()->debugID());
+void SkOpSegment::dumpAngles() const {
+ SkDebugf("((SkOpSegment*) 0x%p) [%d]\n", this, debugID());
+ const SkOpAngle* fromAngle = NULL;
+ const SkOpAngle* toAngle = NULL;
+ for (int index = 0; index < count(); ++index) {
+ const SkOpAngle* fAngle = fTs[index].fFromAngle;
+ const SkOpAngle* tAngle = fTs[index].fToAngle;
+ if (fromAngle == fAngle && toAngle == tAngle) {
+ continue;
+ }
+ if (fAngle) {
+ SkDebugf(" [%d] from=%d ", index, fAngle->debugID());
+ fAngle->dumpTo(this, tAngle);
+ }
+ if (tAngle) {
+ SkDebugf(" [%d] to=%d ", index, tAngle->debugID());
+ tAngle->dumpTo(this, fAngle);
+ }
+ fromAngle = fAngle;
+ toAngle = tAngle;
}
}
-void SkOpSpanBase::dumpCoin() const {
- const SkOpSpan* span = this->upCastable();
- if (!span) {
+void SkOpSegment::dumpContour(int firstID, int lastID) const {
+ if (debugID() < 0) {
return;
}
- if (!span->isCoincident()) {
- return;
+ const SkOpSegment* test = this - (debugID() - 1);
+ test += (firstID - 1);
+ const SkOpSegment* last = test + (lastID - firstID);
+ while (test <= last) {
+ test->dumpSpans();
+ ++test;
}
- span->dumpCoin();
}
-void SkOpSpan::dumpCoin() const {
- const SkOpSpan* coincident = fCoincident;
- bool ok = debugCoinLoopCheck();
- this->dump();
- int loop = 0;
+void SkOpSegment::dumpPts() const {
+ int last = SkPathOpsVerbToPoints(fVerb);
+ SkDebugf("((SkOpSegment*) 0x%p) [%d] {{", this, debugID());
+ int index = 0;
do {
- coincident->dump();
- if (!ok && ++loop > 10) {
- SkDebugf("*** abort loop ***\n");
- break;
+ SkDPoint::Dump(fPts[index]);
+ SkDebugf(", ");
+ } while (++index < last);
+ SkDPoint::Dump(fPts[index]);
+ SkDebugf("}}\n");
+}
+
+void SkOpSegment::dumpHexPts() const {
+ int last = SkPathOpsVerbToPoints(fVerb);
+ SkDebugf("((SkOpSegment*) 0x%p) [%d] {{", this, debugID());
+ int index = 0;
+ do {
+ SkDPoint::DumpHex(fPts[index]);
+ SkDebugf(", ");
+ } while (++index < last);
+ SkDPoint::DumpHex(fPts[index]);
+ SkDebugf("}}\n");
+}
+
+void SkOpSegment::dumpDPts() const {
+ int count = SkPathOpsVerbToPoints(fVerb);
+ SkDebugf("((SkOpSegment*) 0x%p) [%d] {{", this, debugID());
+ int index = 0;
+ do {
+ SkDPoint dPt = {fPts[index].fX, fPts[index].fY};
+ dPt.dump();
+ if (index != count) {
+ SkDebugf(", ");
}
- } while ((coincident = coincident->fCoincident) != this);
+ } while (++index <= count);
+ SkDebugf("}}\n");
}
-bool SkOpSpan::dumpSpan() const {
- SkOpSpan* coin = fCoincident;
- if (this != coin) {
- SkDebugf(" coinStart seg/span=%d/%d", coin->segment()->debugID(), coin->debugID());
+void SkOpSegment::dumpSpans() const {
+ int count = this->count();
+ SkDebugf("((SkOpSegment*) 0x%p) [%d]\n", this, debugID());
+ for (int index = 0; index < count; ++index) {
+ const SkOpSpan& span = this->span(index);
+ SkDebugf(" [%d] ", index);
+ span.dumpOne();
}
- SkDebugf(" windVal=%d", this->windValue());
- SkDebugf(" windSum=");
- SkPathOpsDebug::WindingPrintf(this->windSum());
- if (this->oppValue() != 0 || this->oppSum() != SK_MinS32) {
- SkDebugf(" oppVal=%d", this->oppValue());
- SkDebugf(" oppSum=");
- SkPathOpsDebug::WindingPrintf(this->oppSum());
+}
+
+void SkPathOpsDebug::DumpCoincidence(const SkTArray<SkOpContour, true>& contours) {
+ int count = contours.count();
+ for (int index = 0; index < count; ++index) {
+ contours[index].dumpCoincidences();
}
- if (this->done()) {
- SkDebugf(" done");
+}
+
+void SkPathOpsDebug::DumpCoincidence(const SkTArray<SkOpContour* , true>& contours) {
+ int count = contours.count();
+ for (int index = 0; index < count; ++index) {
+ contours[index]->dumpCoincidences();
}
- return this != coin;
}
-const SkOpAngle* SkOpSegment::debugAngle(int id) const {
- return this->contour()->debugAngle(id);
+void SkPathOpsDebug::DumpContours(const SkTArray<SkOpContour, true>& contours) {
+ int count = contours.count();
+ for (int index = 0; index < count; ++index) {
+ contours[index].dump();
+ }
}
-SkOpContour* SkOpSegment::debugContour(int id) {
- return this->contour()->debugContour(id);
+void SkPathOpsDebug::DumpContours(const SkTArray<SkOpContour* , true>& contours) {
+ int count = contours.count();
+ for (int index = 0; index < count; ++index) {
+ contours[index]->dump();
+ }
}
-const SkOpPtT* SkOpSegment::debugPtT(int id) const {
- return this->contour()->debugPtT(id);
+void SkPathOpsDebug::DumpContourAngles(const SkTArray<SkOpContour, true>& contours) {
+ int count = contours.count();
+ for (int index = 0; index < count; ++index) {
+ contours[index].dumpAngles();
+ }
}
-const SkOpSegment* SkOpSegment::debugSegment(int id) const {
- return this->contour()->debugSegment(id);
+void SkPathOpsDebug::DumpContourAngles(const SkTArray<SkOpContour* , true>& contours) {
+ int count = contours.count();
+ for (int index = 0; index < count; ++index) {
+ contours[index]->dumpAngles();
+ }
}
-const SkOpSpanBase* SkOpSegment::debugSpan(int id) const {
- return this->contour()->debugSpan(id);
+void SkPathOpsDebug::DumpContourPts(const SkTArray<SkOpContour, true>& contours) {
+ int count = contours.count();
+ for (int index = 0; index < count; ++index) {
+ contours[index].dumpPts();
+ }
}
-void SkOpSegment::dump() const {
- SkDebugf("%.*s", contour()->debugIndent(), " ");
- this->dumpPts();
- const SkOpSpanBase* span = &fHead;
- contour()->indentDump();
- do {
- SkDebugf("%.*s span=%d ", contour()->debugIndent(), " ", span->debugID());
- span->ptT()->dumpBase();
- span->dumpBase();
- SkDebugf("\n");
- } while (!span->final() && (span = span->upCast()->next()));
- contour()->outdentDump();
+void SkPathOpsDebug::DumpContourPts(const SkTArray<SkOpContour* , true>& contours) {
+ int count = contours.count();
+ for (int index = 0; index < count; ++index) {
+ contours[index]->dumpPts();
+ }
}
-void SkOpSegment::dumpAll() const {
- SkDebugf("%.*s", contour()->debugIndent(), " ");
- this->dumpPts();
- const SkOpSpanBase* span = &fHead;
- contour()->indentDump();
- do {
- span->dumpAll();
- } while (!span->final() && (span = span->upCast()->next()));
- contour()->outdentDump();
+void SkPathOpsDebug::DumpContourPt(const SkTArray<SkOpContour, true>& contours, int segmentID) {
+ int count = contours.count();
+ for (int index = 0; index < count; ++index) {
+ contours[index].dumpPt(segmentID);
+ }
}
-void SkOpSegment::dumpAngles() const {
- SkDebugf("seg=%d\n", debugID());
- const SkOpSpanBase* span = &fHead;
- do {
- const SkOpAngle* fAngle = span->fromAngle();
- const SkOpAngle* tAngle = span->final() ? NULL : span->upCast()->toAngle();
- if (fAngle) {
- SkDebugf(" span=%d from=%d ", span->debugID(), fAngle->debugID());
- fAngle->dumpTo(this, tAngle);
- }
- if (tAngle) {
- SkDebugf(" span=%d to=%d ", span->debugID(), tAngle->debugID());
- tAngle->dumpTo(this, fAngle);
- }
- } while (!span->final() && (span = span->upCast()->next()));
+void SkPathOpsDebug::DumpContourPt(const SkTArray<SkOpContour* , true>& contours, int segmentID) {
+ int count = contours.count();
+ for (int index = 0; index < count; ++index) {
+ contours[index]->dumpPt(segmentID);
+ }
}
-void SkOpSegment::dumpCoin() const {
- const SkOpSpan* span = &fHead;
- do {
- span->dumpCoin();
- } while ((span = span->next()->upCastable()));
+void SkPathOpsDebug::DumpContourSpans(const SkTArray<SkOpContour, true>& contours) {
+ int count = contours.count();
+ for (int index = 0; index < count; ++index) {
+ contours[index].dumpSpans();
+ }
}
-void SkOpSegment::dumpPts() const {
- int last = SkPathOpsVerbToPoints(fVerb);
- SkDebugf("seg=%d {{", this->debugID());
- int index = 0;
- do {
- SkDPoint::Dump(fPts[index]);
- SkDebugf(", ");
- } while (++index < last);
- SkDPoint::Dump(fPts[index]);
- SkDebugf("}}\n");
+void SkPathOpsDebug::DumpContourSpans(const SkTArray<SkOpContour* , true>& contours) {
+ int count = contours.count();
+ for (int index = 0; index < count; ++index) {
+ contours[index]->dumpSpans();
+ }
}
-void SkCoincidentSpans::dump() const {
- SkDebugf("- seg=%d span=%d ptT=%d ", fCoinPtTStart->segment()->debugID(),
- fCoinPtTStart->span()->debugID(), fCoinPtTStart->debugID());
- fCoinPtTStart->dumpBase();
- SkDebugf(" span=%d ptT=%d ", fCoinPtTEnd->span()->debugID(), fCoinPtTEnd->debugID());
- fCoinPtTEnd->dumpBase();
- if (fCoinPtTStart->segment()->operand()) {
- SkDebugf(" operand");
+void SkPathOpsDebug::DumpContourSpan(const SkTArray<SkOpContour, true>& contours, int segmentID) {
+ int count = contours.count();
+ for (int index = 0; index < count; ++index) {
+ contours[index].dumpSpan(segmentID);
}
- if (fCoinPtTStart->segment()->isXor()) {
- SkDebugf(" xor");
+}
+
+void SkPathOpsDebug::DumpContourSpan(const SkTArray<SkOpContour* , true>& contours, int segmentID) {
+ int count = contours.count();
+ for (int index = 0; index < count; ++index) {
+ contours[index]->dumpSpan(segmentID);
}
- SkDebugf("\n");
- SkDebugf("+ seg=%d span=%d ptT=%d ", fOppPtTStart->segment()->debugID(),
- fOppPtTStart->span()->debugID(), fOppPtTStart->debugID());
- fOppPtTStart->dumpBase();
- SkDebugf(" span=%d ptT=%d ", fOppPtTEnd->span()->debugID(), fOppPtTEnd->debugID());
- fOppPtTEnd->dumpBase();
- if (fOppPtTStart->segment()->operand()) {
- SkDebugf(" operand");
+}
+
+void SkPathOpsDebug::DumpSpans(const SkTDArray<SkOpSpan *>& spans) {
+ int count = spans.count();
+ for (int index = 0; index < count; ++index) {
+ const SkOpSpan* span = spans[index];
+ const SkOpSpan& oSpan = span->fOther->span(span->fOtherIndex);
+ const SkOpSegment* segment = oSpan.fOther;
+ SkDebugf("((SkOpSegment*) 0x%p) [%d] ", segment, segment->debugID());
+ SkDebugf("spanIndex:%d ", oSpan.fOtherIndex);
+ span->dumpOne();
+ }
+}
+
+// this does not require that other T index is initialized or correct
+const SkOpSegment* SkOpSpan::debugToSegment(ptrdiff_t* spanIndex) const {
+ if (!fOther) {
+ return NULL;
+ }
+ int oppCount = fOther->count();
+ for (int index = 0; index < oppCount; ++index) {
+ const SkOpSpan& otherSpan = fOther->span(index);
+ double otherTestT = otherSpan.fT;
+ if (otherTestT < fOtherT) {
+ continue;
+ }
+ SkASSERT(otherTestT == fOtherT);
+ const SkOpSegment* candidate = otherSpan.fOther;
+ const SkOpSpan* first = candidate->debugSpans().begin();
+ const SkOpSpan* last = candidate->debugSpans().end() - 1;
+ if (first <= this && this <= last) {
+ if (spanIndex) {
+ *spanIndex = this - first;
+ }
+ return candidate;
+ }
}
- if (fOppPtTStart->segment()->isXor()) {
- SkDebugf(" xor");
+ SkASSERT(0);
+ return NULL;
+}
+
+void SkOpSpan::dumpOne() const {
+ SkDebugf("t=");
+ DebugDumpDouble(fT);
+ SkDebugf(" pt=");
+ SkDPoint::Dump(fPt);
+ if (fOther) {
+ SkDebugf(" other.fID=%d", fOther->debugID());
+ SkDebugf(" [%d] otherT=", fOtherIndex);
+ DebugDumpDouble(fOtherT);
+ } else {
+ SkDebugf(" other.fID=? [?] otherT=?");
+ }
+ if (fWindSum != SK_MinS32) {
+ SkDebugf(" windSum=%d", fWindSum);
+ }
+ if (fOppSum != SK_MinS32 && (SkPathOpsDebug::ValidWind(fOppSum) || fOppValue != 0)) {
+ SkDebugf(" oppSum=%d", fOppSum);
+ }
+ SkDebugf(" windValue=%d", fWindValue);
+ if (SkPathOpsDebug::ValidWind(fOppSum) || fOppValue != 0) {
+ SkDebugf(" oppValue=%d", fOppValue);
+ }
+ if (fFromAngle && fFromAngle->debugID()) {
+ SkDebugf(" from=%d", fFromAngle->debugID());
+ }
+ if (fToAngle && fToAngle->debugID()) {
+ SkDebugf(" to=%d", fToAngle->debugID());
+ }
+ if (fChased) {
+ SkDebugf(" chased");
+ }
+ if (fCoincident) {
+ SkDebugf(" coincident");
+ }
+ if (fDone) {
+ SkDebugf(" done");
+ }
+ if (fLoop) {
+ SkDebugf(" loop");
+ }
+ if (fMultiple) {
+ SkDebugf(" multiple");
+ }
+ if (fNear) {
+ SkDebugf(" near");
+ }
+ if (fSmall) {
+ SkDebugf(" small");
+ }
+ if (fTiny) {
+ SkDebugf(" tiny");
}
SkDebugf("\n");
}
-void SkOpCoincidence::dump() const {
- SkCoincidentSpans* span = fHead;
- while (span) {
- span->dump();
- span = span->fNext;
+void SkOpSpan::dump() const {
+ ptrdiff_t spanIndex;
+ const SkOpSegment* segment = debugToSegment(&spanIndex);
+ if (segment) {
+ SkDebugf("((SkOpSegment*) 0x%p) [%d]\n", segment, segment->debugID());
+ SkDebugf(" [%d] ", spanIndex);
+ } else {
+ SkDebugf("((SkOpSegment*) ?) [?]\n");
+ SkDebugf(" [?] ");
}
+ dumpOne();
}
-void SkOpContour::dump() {
- SkDebugf("contour=%d count=%d\n", this->debugID(), fCount);
- if (!fCount) {
- return;
- }
- const SkOpSegment* segment = &fHead;
- PATH_OPS_DEBUG_CODE(fIndent = 0);
- indentDump();
- do {
- segment->dump();
- } while ((segment = segment->next()));
- outdentDump();
+void Dump(const SkTArray<class SkOpContour, true>& contours) {
+ SkPathOpsDebug::DumpContours(contours);
}
-void SkOpContour::dumpAll() {
- SkDebugf("contour=%d count=%d\n", this->debugID(), fCount);
- if (!fCount) {
- return;
- }
- const SkOpSegment* segment = &fHead;
- PATH_OPS_DEBUG_CODE(fIndent = 0);
- indentDump();
- do {
- segment->dumpAll();
- } while ((segment = segment->next()));
- outdentDump();
+void Dump(const SkTArray<class SkOpContour* , true>& contours) {
+ SkPathOpsDebug::DumpContours(contours);
}
+void Dump(const SkTArray<class SkOpContour, true>* contours) {
+ SkPathOpsDebug::DumpContours(*contours);
+}
-void SkOpContour::dumpAngles() const {
- SkDebugf("contour=%d\n", this->debugID());
- const SkOpSegment* segment = &fHead;
- do {
- SkDebugf(" seg=%d ", segment->debugID());
- segment->dumpAngles();
- } while ((segment = segment->next()));
+void Dump(const SkTArray<class SkOpContour* , true>* contours) {
+ SkPathOpsDebug::DumpContours(*contours);
}
-void SkOpContour::dumpPt(int index) const {
- const SkOpSegment* segment = &fHead;
- do {
- if (segment->debugID() == index) {
- segment->dumpPts();
- }
- } while ((segment = segment->next()));
+void Dump(const SkTDArray<SkOpSpan *>& chase) {
+ SkPathOpsDebug::DumpSpans(chase);
}
-void SkOpContour::dumpPts() const {
- SkDebugf("contour=%d\n", this->debugID());
- const SkOpSegment* segment = &fHead;
- do {
- SkDebugf(" seg=%d ", segment->debugID());
- segment->dumpPts();
- } while ((segment = segment->next()));
+void Dump(const SkTDArray<SkOpSpan *>* chase) {
+ SkPathOpsDebug::DumpSpans(*chase);
}
-void SkOpContour::dumpPtsX() const {
- if (!this->fCount) {
- SkDebugf("<empty>\n");
- return;
- }
- const SkOpSegment* segment = &fHead;
- do {
- segment->dumpPts();
- } while ((segment = segment->next()));
+void DumpAngles(const SkTArray<class SkOpContour, true>& contours) {
+ SkPathOpsDebug::DumpContourAngles(contours);
}
-void SkOpContour::dumpSegment(int index) const {
- debugSegment(index)->dump();
+void DumpAngles(const SkTArray<class SkOpContour* , true>& contours) {
+ SkPathOpsDebug::DumpContourAngles(contours);
}
-void SkOpContour::dumpSegments(SkPathOp op) const {
- bool firstOp = false;
- const SkOpContour* c = this;
- do {
- if (!firstOp && c->operand()) {
-#if DEBUG_ACTIVE_OP
- SkDebugf("op %s\n", SkPathOpsDebug::kPathOpStr[op]);
-#endif
- firstOp = true;
- }
- c->dumpPtsX();
- } while ((c = c->next()));
+void DumpAngles(const SkTArray<class SkOpContour, true>* contours) {
+ SkPathOpsDebug::DumpContourAngles(*contours);
}
-void SkOpContour::dumpSpan(int index) const {
- debugSpan(index)->dump();
+void DumpAngles(const SkTArray<class SkOpContour* , true>* contours) {
+ SkPathOpsDebug::DumpContourAngles(*contours);
}
-void SkOpContour::dumpSpans() const {
- SkDebugf("contour=%d\n", this->debugID());
- const SkOpSegment* segment = &fHead;
- do {
- SkDebugf(" seg=%d ", segment->debugID());
- segment->dump();
- } while ((segment = segment->next()));
+void DumpCoin(const SkTArray<class SkOpContour, true>& contours) {
+ SkPathOpsDebug::DumpCoincidence(contours);
}
-#ifdef SK_DEBUG
-const SkOpAngle* SkOpGlobalState::debugAngle(int id) const {
- const SkOpContour* contour = fHead;
- do {
- const SkOpSegment* segment = contour->first();
- while (segment) {
- const SkOpSpan* span = segment->head();
- do {
- SkOpAngle* angle = span->fromAngle();
- if (angle && angle->debugID() == id) {
- return angle;
- }
- angle = span->toAngle();
- if (angle && angle->debugID() == id) {
- return angle;
- }
- } while ((span = span->next()->upCastable()));
- const SkOpSpanBase* tail = segment->tail();
- SkOpAngle* angle = tail->fromAngle();
- if (angle && angle->debugID() == id) {
- return angle;
- }
- segment = segment->next();
- }
- } while ((contour = contour->next()));
- return NULL;
+void DumpCoin(const SkTArray<class SkOpContour* , true>& contours) {
+ SkPathOpsDebug::DumpCoincidence(contours);
}
-SkOpContour* SkOpGlobalState::debugContour(int id) {
- SkOpContour* contour = fHead;
- do {
- if (contour->debugID() == id) {
- return contour;
- }
- } while ((contour = contour->next()));
- return NULL;
+void DumpCoin(const SkTArray<class SkOpContour, true>* contours) {
+ SkPathOpsDebug::DumpCoincidence(*contours);
}
-const SkOpPtT* SkOpGlobalState::debugPtT(int id) const {
- const SkOpContour* contour = fHead;
- do {
- const SkOpSegment* segment = contour->first();
- while (segment) {
- const SkOpSpan* span = segment->head();
- do {
- const SkOpPtT* ptT = span->ptT();
- if (ptT->debugMatchID(id)) {
- return ptT;
- }
- } while ((span = span->next()->upCastable()));
- const SkOpSpanBase* tail = segment->tail();
- const SkOpPtT* ptT = tail->ptT();
- if (ptT->debugMatchID(id)) {
- return ptT;
- }
- segment = segment->next();
- }
- } while ((contour = contour->next()));
- return NULL;
+void DumpCoin(const SkTArray<class SkOpContour* , true>* contours) {
+ SkPathOpsDebug::DumpCoincidence(*contours);
}
-const SkOpSegment* SkOpGlobalState::debugSegment(int id) const {
- const SkOpContour* contour = fHead;
- do {
- const SkOpSegment* segment = contour->first();
- while (segment) {
- if (segment->debugID() == id) {
- return segment;
- }
- segment = segment->next();
- }
- } while ((contour = contour->next()));
- return NULL;
+void DumpSpans(const SkTArray<class SkOpContour, true>& contours) {
+ SkPathOpsDebug::DumpContourSpans(contours);
}
-const SkOpSpanBase* SkOpGlobalState::debugSpan(int id) const {
- const SkOpContour* contour = fHead;
- do {
- const SkOpSegment* segment = contour->first();
- while (segment) {
- const SkOpSpan* span = segment->head();
- do {
- if (span->debugID() == id) {
- return span;
- }
- } while ((span = span->next()->upCastable()));
- const SkOpSpanBase* tail = segment->tail();
- if (tail->debugID() == id) {
- return tail;
- }
- segment = segment->next();
- }
- } while ((contour = contour->next()));
- return NULL;
+void DumpSpans(const SkTArray<class SkOpContour* , true>& contours) {
+ SkPathOpsDebug::DumpContourSpans(contours);
}
-#endif
-const SkOpAngle* DebugAngle(const SkTArray<SkOpContour*, true>* contours, int id) {
- return (*contours)[0]->debugAngle(id);
+void DumpSpans(const SkTArray<class SkOpContour, true>* contours) {
+ SkPathOpsDebug::DumpContourSpans(*contours);
}
-SkOpContour* DumpContour(const SkTArray<SkOpContour*, true>* contours, int id) {
- return (*contours)[0]->debugContour(id);
+void DumpSpans(const SkTArray<class SkOpContour* , true>* contours) {
+ SkPathOpsDebug::DumpContourSpans(*contours);
}
-const SkOpPtT* DebugPtT(const SkTArray<SkOpContour*, true>* contours, int id) {
- return (*contours)[0]->debugPtT(id);
+void DumpSpan(const SkTArray<class SkOpContour, true>& contours, int segmentID) {
+ SkPathOpsDebug::DumpContourSpan(contours, segmentID);
}
-const SkOpSegment* DebugSegment(const SkTArray<SkOpContour*, true>* contours, int id) {
- return (*contours)[0]->debugSegment(id);
+void DumpSpan(const SkTArray<class SkOpContour* , true>& contours, int segmentID) {
+ SkPathOpsDebug::DumpContourSpan(contours, segmentID);
}
-const SkOpSpanBase* DebugSpan(const SkTArray<SkOpContour*, true>* contours, int id) {
- return (*contours)[0]->debugSpan(id);
+void DumpSpan(const SkTArray<class SkOpContour, true>* contours, int segmentID) {
+ SkPathOpsDebug::DumpContourSpan(*contours, segmentID);
}
-void Dump(SkTDArray<SkOpContour* >* contours) {
- SkPathOpsDebug::DumpContours(contours);
+void DumpSpan(const SkTArray<class SkOpContour* , true>* contours, int segmentID) {
+ SkPathOpsDebug::DumpContourSpan(*contours, segmentID);
}
-void DumpAll(SkTDArray<SkOpContour* >* contours) {
- SkPathOpsDebug::DumpContoursAll(contours);
+void DumpPts(const SkTArray<class SkOpContour, true>& contours) {
+ SkPathOpsDebug::DumpContourPts(contours);
}
-void DumpAngles(const SkTDArray<SkOpContour* >* contours) {
- SkPathOpsDebug::DumpContoursAngles(contours);
+void DumpPts(const SkTArray<class SkOpContour* , true>& contours) {
+ SkPathOpsDebug::DumpContourPts(contours);
}
-void DumpSegment(const SkTDArray<SkOpContour* >* contours, int segmentID) {
- SkPathOpsDebug::DumpContoursSegment(contours, segmentID);
+void DumpPts(const SkTArray<class SkOpContour, true>* contours) {
+ SkPathOpsDebug::DumpContourPts(*contours);
}
-void DumpSpan(const SkTDArray<SkOpContour* >* contours, int spanID) {
- SkPathOpsDebug::DumpContoursSpan(contours, spanID);
+void DumpPts(const SkTArray<class SkOpContour* , true>* contours) {
+ SkPathOpsDebug::DumpContourPts(*contours);
}
-void DumpSpans(const SkTDArray<SkOpContour* >* contours) {
- SkPathOpsDebug::DumpContoursSpans(contours);
+void DumpPt(const SkTArray<class SkOpContour, true>& contours, int segmentID) {
+ SkPathOpsDebug::DumpContourPt(contours, segmentID);
}
-void DumpPt(const SkTDArray<SkOpContour* >* contours, int segmentID) {
- SkPathOpsDebug::DumpContoursPt(contours, segmentID);
+void DumpPt(const SkTArray<class SkOpContour* , true>& contours, int segmentID) {
+ SkPathOpsDebug::DumpContourPt(contours, segmentID);
}
-void DumpPts(const SkTDArray<SkOpContour* >* contours) {
- SkPathOpsDebug::DumpContoursPts(contours);
+void DumpPt(const SkTArray<class SkOpContour, true>* contours, int segmentID) {
+ SkPathOpsDebug::DumpContourPt(*contours, segmentID);
}
-#if DEBUG_T_SECT_DUMP > 1
-int gDumpTSectNum;
-#endif
+void DumpPt(const SkTArray<class SkOpContour* , true>* contours, int segmentID) {
+ SkPathOpsDebug::DumpContourPt(*contours, segmentID);
+}
+
+static void dumpTestCase(const SkDQuad& quad1, const SkDQuad& quad2, int testNo) {
+ SkDebugf("<div id=\"quad%d\">\n", testNo);
+ quad1.dumpComma(",");
+ quad2.dump();
+ SkDebugf("</div>\n\n");
+}
+
+static void dumpTestTrailer() {
+ SkDebugf("</div>\n\n<script type=\"text/javascript\">\n\n");
+ SkDebugf(" var testDivs = [\n");
+}
+
+static void dumpTestList(int testNo, double min) {
+ SkDebugf(" quad%d,", testNo);
+ if (min > 0) {
+ SkDebugf(" // %1.9g", min);
+ }
+ SkDebugf("\n");
+}
+
+void DumpQ(const SkDQuad& quad1, const SkDQuad& quad2, int testNo) {
+ SkDebugf("\n");
+ dumpTestCase(quad1, quad2, testNo);
+ dumpTestTrailer();
+ dumpTestList(testNo, 0);
+ SkDebugf("\n");
+}
+
+void DumpT(const SkDQuad& quad, double t) {
+ SkDLine line = {{quad.ptAtT(t), quad[0]}};
+ line.dump();
+}
diff --git a/tests/PathOpsExtendedTest.cpp b/tests/PathOpsExtendedTest.cpp
index 4a806c2a51..e0d30ba0b3 100644
--- a/tests/PathOpsExtendedTest.cpp
+++ b/tests/PathOpsExtendedTest.cpp
@@ -24,7 +24,6 @@
__SK_FORCE_IMAGE_DECODER_LINKING;
DEFINE_bool2(runFail, f, false, "run tests known to fail.");
-DEFINE_bool2(runBinary, f, false, "run tests known to fail binary sect.");
static const char marker[] =
"</div>\n"
@@ -48,6 +47,10 @@ static const char* opSuffixes[] = {
"o",
};
+static bool gShowPath = false;
+static bool gComparePathsAssert = true;
+static bool gPathStrAssert = true;
+
#if DEBUG_SHOW_TEST_NAME
static void showPathData(const SkPath& path) {
SkPath::RawIter iter(path);
@@ -79,13 +82,6 @@ static void showPathData(const SkPath& path) {
lastPt = pts[2];
lastPtSet = true;
break;
- case SkPath::kConic_Verb:
- SkDebugf("{{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}}, //weight=%1.9g\n",
- pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY,
- iter.conicWeight());
- lastPt = pts[2];
- lastPtSet = true;
- break;
case SkPath::kCubic_Verb:
SkDebugf("{{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}},\n",
pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY,
@@ -277,7 +273,7 @@ bool drawAsciiPaths(const SkPath& one, const SkPath& two, bool drawPaths) {
return true;
}
-int comparePaths(skiatest::Reporter* reporter, const char* filename, const SkPath& one,
+static int comparePaths(skiatest::Reporter* reporter, const char* filename, const SkPath& one,
const SkPath& two, SkBitmap& bitmap) {
int errors2x2;
SkPath scaledOne, scaledTwo;
@@ -286,6 +282,7 @@ int comparePaths(skiatest::Reporter* reporter, const char* filename, const SkPat
return 0;
}
const int MAX_ERRORS = 9;
+ REPORTER_ASSERT(reporter, errors2x2 <= MAX_ERRORS || !gComparePathsAssert);
return errors2x2 > MAX_ERRORS ? errors2x2 : 0;
}
@@ -306,7 +303,7 @@ static void showPathOpPath(const char* testName, const SkPath& one, const SkPath
*gTestOp.append() = shapeOp;
++gTestNo;
SkDebugf(" SkPath path, pathB;\n");
-#if 0 && DEBUG_SHOW_TEST_NAME
+#if DEBUG_SHOW_TEST_NAME
SkPathOpsDebug::ShowOnePath(a, "path", false);
SkPathOpsDebug::ShowOnePath(b, "pathB", false);
#endif
@@ -337,14 +334,17 @@ static int comparePaths(skiatest::Reporter* reporter, const char* testName, cons
return 0;
}
if (errors2x2 == 0) {
+ if (gShowPath) {
+ showPathOpPath(testName, one, two, a, b, scaledOne, scaledTwo, shapeOp, scale);
+ }
return 0;
}
- if (errors2x2 > MAX_ERRORS) {
+ if (errors2x2 > MAX_ERRORS && gComparePathsAssert) {
SkAutoMutexAcquire autoM(compareDebugOut3);
SkDebugf("\n*** this test fails ***\n");
showPathOpPath(testName, one, two, a, b, scaledOne, scaledTwo, shapeOp, scale);
REPORTER_ASSERT(reporter, 0);
- } else if (errors2x2 == MAX_ERRORS || errors2x2 == MAX_ERRORS - 1) {
+ } else if (gShowPath || errors2x2 == MAX_ERRORS || errors2x2 == MAX_ERRORS - 1) {
SkAutoMutexAcquire autoM(compareDebugOut4);
showPathOpPath(testName, one, two, a, b, scaledOne, scaledTwo, shapeOp, scale);
}
@@ -367,7 +367,7 @@ static void writeTestName(const char* nameSuffix, SkMemoryWStream& outFile) {
static void outputToStream(const char* pathStr, const char* pathPrefix, const char* nameSuffix,
const char* testFunction, bool twoPaths, SkMemoryWStream& outFile) {
#if 0
- outFile.writeText("\n<div id=\"");
+ outFile.writeText("<div id=\"");
writeTestName(nameSuffix, outFile);
outFile.writeText("\">\n");
if (pathPrefix) {
@@ -412,12 +412,15 @@ static void outputToStream(const char* pathStr, const char* pathPrefix, const ch
}
SK_DECLARE_STATIC_MUTEX(simplifyDebugOut);
-
bool testSimplify(SkPath& path, bool useXor, SkPath& out, PathOpsThreadState& state,
const char* pathStr) {
SkPath::FillType fillType = useXor ? SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType;
path.setFillType(fillType);
- state.fReporter->bumpTestCount();
+#if DEBUG_SHOW_TEST_NAME
+ if (gShowPath) {
+ SkPathOpsDebug::ShowOnePath(path, "path", false);
+ }
+#endif
if (!Simplify(path, &out)) {
SkDebugf("%s did not expect failure\n", __FUNCTION__);
REPORTER_ASSERT(state.fReporter, 0);
@@ -427,7 +430,7 @@ bool testSimplify(SkPath& path, bool useXor, SkPath& out, PathOpsThreadState& st
return true;
}
int result = comparePaths(state.fReporter, NULL, path, out, *state.fBitmap);
- if (result) {
+ if (result && gPathStrAssert) {
SkAutoMutexAcquire autoM(simplifyDebugOut);
char temp[8192];
sk_bzero(temp, sizeof(temp));
@@ -447,39 +450,23 @@ bool testSimplify(SkPath& path, bool useXor, SkPath& out, PathOpsThreadState& st
return result == 0;
}
-static bool inner_simplify(skiatest::Reporter* reporter, const SkPath& path, const char* filename,
- bool checkFail) {
-#if 0 && DEBUG_SHOW_TEST_NAME
+bool testSimplify(skiatest::Reporter* reporter, const SkPath& path, const char* filename) {
+#if DEBUG_SHOW_TEST_NAME
showPathData(path);
#endif
SkPath out;
if (!Simplify(path, &out)) {
- SkDebugf("%s did not expect %s failure\n", __FUNCTION__, filename);
+ SkDebugf("%s did not expect failure\n", __FUNCTION__);
REPORTER_ASSERT(reporter, 0);
return false;
}
SkBitmap bitmap;
- int errors = comparePaths(reporter, filename, path, out, bitmap);
- if (!checkFail) {
- if (!errors) {
- SkDebugf("%s failing test %s now succeeds\n", __FUNCTION__, filename);
- REPORTER_ASSERT(reporter, 0);
- return false;
- }
- } else if (errors) {
+ int result = comparePaths(reporter, filename, path, out, bitmap);
+ if (result && gPathStrAssert) {
REPORTER_ASSERT(reporter, 0);
}
reporter->bumpTestCount();
- return errors == 0;
-}
-
-bool testSimplify(skiatest::Reporter* reporter, const SkPath& path, const char* filename) {
- return inner_simplify(reporter, path, filename, true);
-}
-
-bool testSimplifyCheck(skiatest::Reporter* reporter, const SkPath& path, const char* filename,
- bool checkFail) {
- return inner_simplify(reporter, path, filename, checkFail);
+ return result == 0;
}
#if DEBUG_SHOW_TEST_NAME
@@ -493,7 +480,7 @@ static void showName(const SkPath& a, const SkPath& b, const SkPathOp shapeOp) {
static bool innerPathOp(skiatest::Reporter* reporter, const SkPath& a, const SkPath& b,
const SkPathOp shapeOp, const char* testName, bool threaded, bool expectSuccess) {
-#if 0 && DEBUG_SHOW_TEST_NAME
+#if DEBUG_SHOW_TEST_NAME
showName(a, b, shapeOp);
#endif
SkPath out;
@@ -502,7 +489,7 @@ static bool innerPathOp(skiatest::Reporter* reporter, const SkPath& a, const SkP
REPORTER_ASSERT(reporter, 0);
return false;
}
- if (!reporter->verbose()) {
+ if (threaded && !reporter->verbose()) {
return true;
}
SkPath pathOut, scaledPathOut;
@@ -531,7 +518,7 @@ static bool innerPathOp(skiatest::Reporter* reporter, const SkPath& a, const SkP
scaledOut.setFillType(out.getFillType());
int result = comparePaths(reporter, testName, pathOut, scaledPathOut, out, scaledOut, bitmap,
a, b, shapeOp, scale, expectSuccess);
- if (result) {
+ if (result && gPathStrAssert) {
REPORTER_ASSERT(reporter, 0);
}
reporter->bumpTestCount();
@@ -617,7 +604,6 @@ void outputProgress(char* ramStr, const char* pathStr, SkPathOp op) {
void RunTestSet(skiatest::Reporter* reporter, TestDesc tests[], size_t count,
void (*firstTest)(skiatest::Reporter* , const char* filename),
- void (*skipTest)(skiatest::Reporter* , const char* filename),
void (*stopTest)(skiatest::Reporter* , const char* filename), bool reverse) {
size_t index;
if (firstTest) {
@@ -626,7 +612,8 @@ void RunTestSet(skiatest::Reporter* reporter, TestDesc tests[], size_t count,
--index;
}
#if DEBUG_SHOW_TEST_NAME
- SkDebugf("\n<div id=\"%s\">\n", tests[index].str);
+ SkDebugf("<div id=\"%s\">\n", tests[index].str);
+ SkDebugf(" %s [%s]\n", __FUNCTION__, tests[index].str);
#endif
(*tests[index].fun)(reporter, tests[index].str);
if (tests[index].fun == stopTest) {
@@ -635,14 +622,11 @@ void RunTestSet(skiatest::Reporter* reporter, TestDesc tests[], size_t count,
}
index = reverse ? count - 1 : 0;
size_t last = reverse ? 0 : count - 1;
- bool foundSkip = !skipTest;
do {
- if (tests[index].fun == skipTest) {
- foundSkip = true;
- }
- if (foundSkip && tests[index].fun != firstTest) {
+ if (tests[index].fun != firstTest) {
#if DEBUG_SHOW_TEST_NAME
- SkDebugf("\n<div id=\"%s\">\n", tests[index].str);
+ SkDebugf("<div id=\"%s\">\n", tests[index].str);
+ SkDebugf(" %s [%s]\n", __FUNCTION__, tests[index].str);
#endif
(*tests[index].fun)(reporter, tests[index].str);
}
diff --git a/tests/PathOpsExtendedTest.h b/tests/PathOpsExtendedTest.h
index 0428457b50..5f7e972f49 100644
--- a/tests/PathOpsExtendedTest.h
+++ b/tests/PathOpsExtendedTest.h
@@ -17,7 +17,6 @@
#include "Test.h"
DECLARE_bool(runFail);
-DECLARE_bool(runBinary);
struct PathOpsThreadState;
@@ -27,8 +26,7 @@ struct TestDesc {
};
//extern int comparePaths(const SkPath& one, const SkPath& two);
-extern int comparePaths(skiatest::Reporter* reporter, const char* filename,
- const SkPath& one, const SkPath& two, SkBitmap& bitmap);
+extern int comparePaths(const SkPath& one, const SkPath& two, SkBitmap& bitmap);
extern bool drawAsciiPaths(const SkPath& one, const SkPath& two, bool drawPaths);
extern void showOp(const SkPathOp op);
extern bool testPathOp(skiatest::Reporter* reporter, const SkPath& a, const SkPath& b,
@@ -42,8 +40,6 @@ extern bool testThreadedPathOp(skiatest::Reporter* reporter, const SkPath& a, co
extern bool testSimplify(SkPath& path, bool useXor, SkPath& out, PathOpsThreadState& state,
const char* pathStr);
extern bool testSimplify(skiatest::Reporter* reporter, const SkPath& path, const char* filename);
-extern bool testSimplifyCheck(skiatest::Reporter* reporter, const SkPath& path,
- const char* filename, bool checkFail);
void initializeTests(skiatest::Reporter* reporter, const char* testName);
void outputProgress(char* ramStr, const char* pathStr, SkPath::FillType );
@@ -51,7 +47,6 @@ void outputProgress(char* ramStr, const char* pathStr, SkPathOp op);
void RunTestSet(skiatest::Reporter* reporter, TestDesc tests[], size_t count,
void (*firstTest)(skiatest::Reporter* , const char* filename),
- void (*skipTest)(skiatest::Reporter* , const char* filename),
void (*stopTest)(skiatest::Reporter* , const char* filename), bool reverse);
void ShowTestArray();
void ShowTestName(PathOpsThreadState* data, int a, int b, int c, int d);
diff --git a/tests/PathOpsFuzz763Test.cpp b/tests/PathOpsFuzz763Test.cpp
index 64eb81924c..cd851a78cc 100755
--- a/tests/PathOpsFuzz763Test.cpp
+++ b/tests/PathOpsFuzz763Test.cpp
@@ -121,6 +121,11 @@ path.close();
}
static void fuzz763_378(skiatest::Reporter* reporter, const char* filename) {
+#ifdef SK_BUILD_FOR_ANDROID
+ if (!FLAGS_runFail) {
+ return; // fails on nexus 9 in release, possibly related to fused multiply-add
+ }
+#endif
SkPath path;
path.setFillType((SkPath::FillType) 1);
path.moveTo(SkBits2Float(0x41013776), SkBits2Float(0xc25007a8));
@@ -214,6 +219,11 @@ path.close();
}
static void fuzz763_378b(skiatest::Reporter* reporter, const char* filename) {
+#ifdef SK_BUILD_FOR_ANDROID
+ if (!FLAGS_runFail) {
+ return; // fails on nexus 9 in release, possibly related to fused multiply-add
+ }
+#endif
SkPath path;
path.setFillType((SkPath::FillType) 1);
path.moveTo(-47.1494f, 4.35143f);
@@ -233,7 +243,7 @@ path.quadTo(SkBits2Float(0xc21f39d4), SkBits2Float(0x41979b1c), SkBits2Float(0xc
path.quadTo(SkBits2Float(0xc238d4f6), SkBits2Float(0x41a554c0), SkBits2Float(0xc2444fb0), SkBits2Float(0x419813d4));
path.close();
SkPath path2(path);
- testPathOp(reporter, path1, path2, (SkPathOp) 2, filename);
+ testPathOpCheck(reporter, path1, path2, (SkPathOp) 2, filename, FLAGS_runFail);
}
static void fuzz763_378c(skiatest::Reporter* reporter, const char* filename) {
@@ -254,7 +264,7 @@ static void fuzz763_378c(skiatest::Reporter* reporter, const char* filename) {
path.quadTo(-39.8065f, 18.9507f, -43.0072f, 19.8086f);
path.close();
SkPath path2(path);
- testPathOpCheck(reporter, path1, path2, (SkPathOp) 2, filename, FLAGS_runFail);
+ testPathOp(reporter, path1, path2, (SkPathOp) 2, filename);
}
static void fuzz763_378d(skiatest::Reporter* reporter, const char* filename) {
@@ -495,7 +505,7 @@ path.quadTo(SkBits2Float(0xc2382594), SkBits2Float(0x41a85c76), SkBits2Float(0xc
path.close();
SkPath path2(path);
- testPathOpCheck(reporter, path1, path2, (SkPathOp) 2, filename, FLAGS_runFail);
+ testPathOp(reporter, path1, path2, (SkPathOp) 2, filename);
}
static void fuzz763_8712(skiatest::Reporter* reporter, const char* filename) {
@@ -585,7 +595,7 @@ path.quadTo(SkBits2Float(0xc236ec77), SkBits2Float(0x41ad9cd6), SkBits2Float(0xc
path.close();
SkPath path2(path);
- testPathOp(reporter, path1, path2, (SkPathOp) 2, filename);
+ testPathOpCheck(reporter, path1, path2, (SkPathOp) 2, filename, FLAGS_runFail);
}
static void fuzz763_8712a(skiatest::Reporter* reporter, const char* filename) {
@@ -620,7 +630,7 @@ path.quadTo(SkBits2Float(0xc236ec77), SkBits2Float(0x41ad9cd6), SkBits2Float(0xc
path.close();
SkPath path2(path);
- testPathOp(reporter, path1, path2, (SkPathOp) 2, filename);
+ testPathOpCheck(reporter, path1, path2, (SkPathOp) 2, filename, FLAGS_runFail);
}
static void fuzz763_4014(skiatest::Reporter* reporter, const char* filename) {
@@ -709,7 +719,7 @@ path.quadTo(SkBits2Float(0xc23c5ebc), SkBits2Float(0x41948044), SkBits2Float(0xc
path.close();
SkPath path2(path);
- testPathOp(reporter, path1, path2, (SkPathOp) 2, filename);
+ testPathOpCheck(reporter, path1, path2, (SkPathOp) 2, filename, FLAGS_runFail);
}
static void fuzz763_4014a(skiatest::Reporter* reporter, const char* filename) {
@@ -932,7 +942,7 @@ path.quadTo(SkBits2Float(0x42240000), SkBits2Float(0x41ed7d86), SkBits2Float(0x4
path.close();
SkPath path2(path);
- testPathOpCheck(reporter, path1, path2, (SkPathOp) 2, filename, FLAGS_runFail);
+ testPathOp(reporter, path1, path2, (SkPathOp) 2, filename);
}
static void fuzz763_24588(skiatest::Reporter* reporter, const char* filename) {
@@ -1131,6 +1141,7 @@ path.close();
testPathOp(reporter, path1, path2, (SkPathOp) 2, filename);
}
+//SkOpSegment.cpp:3475: failed assertion "firstAngle"
static void fuzz763_17370(skiatest::Reporter* reporter, const char* filename) {
SkPath path;
path.setFillType((SkPath::FillType) 1);
@@ -1436,7 +1447,7 @@ path.quadTo(SkBits2Float(0x421fbff7), SkBits2Float(0x41f8ceed), SkBits2Float(0x4
path.close();
SkPath path2(path);
- testPathOp(reporter, path1, path2, (SkPathOp) 2, filename);
+ testPathOpCheck(reporter, path1, path2, (SkPathOp) 2, filename, FLAGS_runFail);
}
static void fuzz763_1597464(skiatest::Reporter* reporter, const char* filename) {
@@ -1531,10 +1542,10 @@ path.close();
testPathOp(reporter, path1, path2, (SkPathOp) 2, filename);
}
+// SkOpSegment.cpp:4010: failed assertion "span->fOppSum == -0x7FFFFFFF || span->fOppSum == oppWinding
static void fuzz763_34974(skiatest::Reporter* reporter, const char* filename) {
SkPath path;
path.setFillType((SkPath::FillType) 1);
-#if 00
path.moveTo(SkBits2Float(0x41015326), SkBits2Float(0xc2500694));
path.quadTo(SkBits2Float(0x412f3e30), SkBits2Float(0xc256a6fa), SkBits2Float(0x41627462), SkBits2Float(0xc253387e));
path.quadTo(SkBits2Float(0x418ad549), SkBits2Float(0xc24fca02), SkBits2Float(0x41981613), SkBits2Float(0xc2444f40));
@@ -1545,8 +1556,6 @@ path.quadTo(SkBits2Float(0x40d9eeca), SkBits2Float(0xc218d592), SkBits2Float(0x4
path.quadTo(SkBits2Float(0x405fd0f0), SkBits2Float(0xc22fcb17), SkBits2Float(0x408b5c58), SkBits2Float(0xc23c98a3));
path.quadTo(SkBits2Float(0x40a6d038), SkBits2Float(0xc249662f), SkBits2Float(0x41015326), SkBits2Float(0xc2500694));
path.close();
-#endif
-#if 000
path.moveTo(SkBits2Float(0xc21a9c18), SkBits2Float(0xc21aa524));
path.quadTo(SkBits2Float(0xc2113c71), SkBits2Float(0xc2240440), SkBits2Float(0xc203fb34), SkBits2Float(0xc22403dc));
path.quadTo(SkBits2Float(0xc1ed73ee), SkBits2Float(0xc2240379), SkBits2Float(0xc1dab5b7), SkBits2Float(0xc21aa3d1));
@@ -1557,8 +1566,6 @@ path.quadTo(SkBits2Float(0xc2113e50), SkBits2Float(0xc1c8087f), SkBits2Float(0xc
path.quadTo(SkBits2Float(0xc223fc87), SkBits2Float(0xc1ed871e), SkBits2Float(0xc223fc24), SkBits2Float(0xc20404cc));
path.quadTo(SkBits2Float(0xc223fbc0), SkBits2Float(0xc2114609), SkBits2Float(0xc21a9c18), SkBits2Float(0xc21aa524));
path.close();
-#endif
-#if 00
path.moveTo(SkBits2Float(0xc19e6455), SkBits2Float(0xc19e6455));
path.quadTo(SkBits2Float(0xc1399153), SkBits2Float(0xc1e00000), SkBits2Float(0x00000000), SkBits2Float(0xc1e00000));
path.quadTo(SkBits2Float(0x41399153), SkBits2Float(0xc1e00000), SkBits2Float(0x419e6455), SkBits2Float(0xc19e6455));
@@ -1575,15 +1582,11 @@ path.quadTo(SkBits2Float(0xc15b75ce), SkBits2Float(0x41cf0dc3), SkBits2Float(0xc
path.quadTo(SkBits2Float(0xc1e00000), SkBits2Float(0x41399153), SkBits2Float(0xc1e00000), SkBits2Float(0x00000000));
path.quadTo(SkBits2Float(0xc1e00000), SkBits2Float(0xc1399153), SkBits2Float(0xc19e6455), SkBits2Float(0xc19e6455));
path.close();
-#endif
-#if 01
path.moveTo(SkBits2Float(0xc2533a24), SkBits2Float(0x41625bba));
path.lineTo(SkBits2Float(0xc2533ab2), SkBits2Float(0x4162536e));
path.lineTo(SkBits2Float(0xc2533af7), SkBits2Float(0x41624f68));
path.quadTo(SkBits2Float(0xc2533a8e), SkBits2Float(0x41625591), SkBits2Float(0xc2533a24), SkBits2Float(0x41625bba));
path.close();
-#endif
-#if 0
path.moveTo(SkBits2Float(0x41dac664), SkBits2Float(0x41dab723));
path.quadTo(SkBits2Float(0x41ed82ea), SkBits2Float(0x41c80000), SkBits2Float(0x42040000), SkBits2Float(0x41c80000));
path.quadTo(SkBits2Float(0x4211413d), SkBits2Float(0x41c80000), SkBits2Float(0x421aa09e), SkBits2Float(0x41dabec3));
@@ -1599,8 +1602,6 @@ path.quadTo(SkBits2Float(0x41dab5bf), SkBits2Float(0x41dac7c8), SkBits2Float(0x4
path.lineTo(SkBits2Float(0x41dabec3), SkBits2Float(0x41dabec3));
path.quadTo(SkBits2Float(0x41dac293), SkBits2Float(0x41dabaf3), SkBits2Float(0x41dac664), SkBits2Float(0x41dab723));
path.close();
-#endif
-#if 00001
path.moveTo(SkBits2Float(0xc23c9951), SkBits2Float(0x408b2180));
path.quadTo(SkBits2Float(0xc22fcba2), SkBits2Float(0x405f6340), SkBits2Float(0xc2245122), SkBits2Float(0x40a4b85c));
path.quadTo(SkBits2Float(0xc218dd36), SkBits2Float(0x40d9a0b8), SkBits2Float(0xc2156c96), SkBits2Float(0x411fdb9a));
@@ -1621,12 +1622,10 @@ path.lineTo(SkBits2Float(0xc2533b22), SkBits2Float(0x41624cea));
path.quadTo(SkBits2Float(0xc256a842), SkBits2Float(0x412f19c8), SkBits2Float(0xc25007d7), SkBits2Float(0x410132b2));
path.quadTo(SkBits2Float(0xc24966ff), SkBits2Float(0x40a69160), SkBits2Float(0xc23c9951), SkBits2Float(0x408b2180));
path.close();
-#endif
SkPath path1(path);
path.reset();
path.setFillType((SkPath::FillType) 0);
-#if 01
path.moveTo(SkBits2Float(0xc2445236), SkBits2Float(0x419806c2));
path.quadTo(SkBits2Float(0xc24fccb6), SkBits2Float(0x418ac513), SkBits2Float(0xc2533ab2), SkBits2Float(0x4162536e));
path.quadTo(SkBits2Float(0xc256a8ae), SkBits2Float(0x412f1cb2), SkBits2Float(0xc25007d7), SkBits2Float(0x410132b2));
@@ -1637,9 +1636,9 @@ path.quadTo(SkBits2Float(0xc211faaa), SkBits2Float(0x41534d02), SkBits2Float(0xc
path.quadTo(SkBits2Float(0xc21f3c59), SkBits2Float(0x41979082), SkBits2Float(0xc22c0a07), SkBits2Float(0x419e6c7a));
path.quadTo(SkBits2Float(0xc238d7b6), SkBits2Float(0x41a54872), SkBits2Float(0xc2445236), SkBits2Float(0x419806c2));
path.close();
-#endif
+
SkPath path2(path);
- testPathOp(reporter, path1, path2, (SkPathOp) 2, filename);
+ testPathOpCheck(reporter, path1, path2, (SkPathOp) 2, filename, FLAGS_runFail);
}
static void fuzz763_2211264(skiatest::Reporter* reporter, const char* filename) {
@@ -2198,10 +2197,13 @@ path.quadTo(SkBits2Float(0x424a2ff8), SkBits2Float(0xc02cd470), SkBits2Float(0x4
path.close();
SkPath path2(path);
- testPathOpCheck(reporter, path1, path2, (SkPathOp) 2, filename, FLAGS_runFail);
+ testPathOp(reporter, path1, path2, (SkPathOp) 2, filename);
}
static void fuzz763_2674194(skiatest::Reporter* reporter, const char* filename) {
+ if (!FLAGS_runFail) { // FIXME: asserts in alignSpanState
+ return;
+ }
SkPath path;
path.setFillType((SkPath::FillType) 1);
path.moveTo(SkBits2Float(0xbfb16e10), SkBits2Float(0xc252733b));
@@ -2394,7 +2396,6 @@ path.close();
testPathOp(reporter, path1, path2, (SkPathOp) 2, filename);
}
-static void (*skipTest)(skiatest::Reporter* , const char* filename) = 0;
static void (*firstTest)(skiatest::Reporter* , const char* filename) = fuzz763_2674194;
static void (*stopTest)(skiatest::Reporter* , const char* filename) = 0;
@@ -2439,5 +2440,5 @@ DEF_TEST(PathOpsFuzz763, reporter) {
#if DEBUG_SHOW_TEST_NAME
strncpy(DEBUG_FILENAME_STRING, "", DEBUG_FILENAME_STRING_LENGTH);
#endif
- RunTestSet(reporter, tests, testCount, firstTest, skipTest, stopTest, runReverse);
+ RunTestSet(reporter, tests, testCount, firstTest, stopTest, runReverse);
}
diff --git a/tests/PathOpsLineIntersectionTest.cpp b/tests/PathOpsLineIntersectionTest.cpp
index bc0259c9c9..105187be64 100644
--- a/tests/PathOpsLineIntersectionTest.cpp
+++ b/tests/PathOpsLineIntersectionTest.cpp
@@ -11,9 +11,6 @@
// FIXME: add tests for intersecting, non-intersecting, degenerate, coincident
static const SkDLine tests[][2] = {
-{{{{0.00010360032320022583, 1.0172703415155411}, {0.00014114845544099808, 1.0200891587883234}}},
- {{{0.00010259449481964111, 1.017270140349865}, {0.00018215179443359375, 1.022890567779541}}}},
-
#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}}}},
@@ -85,13 +82,10 @@ static const SkDLine coincidentTests[][2] = {
static const size_t coincidentTests_count = SK_ARRAY_COUNT(coincidentTests);
static void check_results(skiatest::Reporter* reporter, const SkDLine& line1, const SkDLine& line2,
- const SkIntersections& ts, bool nearAllowed) {
+ const SkIntersections& ts) {
for (int i = 0; i < ts.used(); ++i) {
SkDPoint result1 = line1.ptAtT(ts[0][i]);
SkDPoint result2 = line2.ptAtT(ts[1][i]);
- if (nearAllowed && result1.roughlyEqual(result2)) {
- continue;
- }
if (!result1.approximatelyEqual(result2) && !ts.nearlySame(i)) {
REPORTER_ASSERT(reporter, ts.used() != 1);
result2 = line2.ptAtT(ts[1][i ^ 1]);
@@ -104,16 +98,14 @@ static void check_results(skiatest::Reporter* reporter, const SkDLine& line1, co
}
}
-static void testOne(skiatest::Reporter* reporter, const SkDLine& line1, const SkDLine& line2,
- bool nearAllowed) {
+static void testOne(skiatest::Reporter* reporter, const SkDLine& line1, const SkDLine& line2) {
SkASSERT(ValidLine(line1));
SkASSERT(ValidLine(line2));
SkIntersections i;
- i.allowNear(nearAllowed);
int pts = i.intersect(line1, line2);
REPORTER_ASSERT(reporter, pts);
REPORTER_ASSERT(reporter, pts == i.used());
- check_results(reporter, line1, line2, i, nearAllowed);
+ check_results(reporter, line1, line2, i);
if (line1[0] == line1[1] || line2[0] == line2[1]) {
return;
}
@@ -122,28 +114,28 @@ static void testOne(skiatest::Reporter* reporter, const SkDLine& line1, const Sk
double right = SkTMax(line1[0].fX, line1[1].fX);
SkIntersections ts;
ts.horizontal(line2, left, right, line1[0].fY, line1[0].fX != left);
- check_results(reporter, line2, line1, ts, nearAllowed);
+ check_results(reporter, line2, line1, ts);
}
if (line2[0].fY == line2[1].fY) {
double left = SkTMin(line2[0].fX, line2[1].fX);
double right = SkTMax(line2[0].fX, line2[1].fX);
SkIntersections ts;
ts.horizontal(line1, left, right, line2[0].fY, line2[0].fX != left);
- check_results(reporter, line1, line2, ts, nearAllowed);
+ check_results(reporter, line1, line2, ts);
}
if (line1[0].fX == line1[1].fX) {
double top = SkTMin(line1[0].fY, line1[1].fY);
double bottom = SkTMax(line1[0].fY, line1[1].fY);
SkIntersections ts;
ts.vertical(line2, top, bottom, line1[0].fX, line1[0].fY != top);
- check_results(reporter, line2, line1, ts, nearAllowed);
+ check_results(reporter, line2, line1, ts);
}
if (line2[0].fX == line2[1].fX) {
double top = SkTMin(line2[0].fY, line2[1].fY);
double bottom = SkTMax(line2[0].fY, line2[1].fY);
SkIntersections ts;
ts.vertical(line1, top, bottom, line2[0].fX, line2[0].fY != top);
- check_results(reporter, line1, line2, ts, nearAllowed);
+ check_results(reporter, line1, line2, ts);
}
reporter->bumpTestCount();
}
@@ -156,7 +148,7 @@ static void testOneCoincident(skiatest::Reporter* reporter, const SkDLine& line1
int pts = ts.intersect(line1, line2);
REPORTER_ASSERT(reporter, pts == 2);
REPORTER_ASSERT(reporter, pts == ts.used());
- check_results(reporter, line1, line2, ts, false);
+ check_results(reporter, line1, line2, ts);
if (line1[0] == line1[1] || line2[0] == line2[1]) {
return;
}
@@ -167,7 +159,7 @@ static void testOneCoincident(skiatest::Reporter* reporter, const SkDLine& line1
ts.horizontal(line2, left, right, line1[0].fY, line1[0].fX != left);
REPORTER_ASSERT(reporter, pts == 2);
REPORTER_ASSERT(reporter, pts == ts.used());
- check_results(reporter, line2, line1, ts, false);
+ check_results(reporter, line2, line1, ts);
}
if (line2[0].fY == line2[1].fY) {
double left = SkTMin(line2[0].fX, line2[1].fX);
@@ -176,7 +168,7 @@ static void testOneCoincident(skiatest::Reporter* reporter, const SkDLine& line1
ts.horizontal(line1, left, right, line2[0].fY, line2[0].fX != left);
REPORTER_ASSERT(reporter, pts == 2);
REPORTER_ASSERT(reporter, pts == ts.used());
- check_results(reporter, line1, line2, ts, false);
+ check_results(reporter, line1, line2, ts);
}
if (line1[0].fX == line1[1].fX) {
double top = SkTMin(line1[0].fY, line1[1].fY);
@@ -185,7 +177,7 @@ static void testOneCoincident(skiatest::Reporter* reporter, const SkDLine& line1
ts.vertical(line2, top, bottom, line1[0].fX, line1[0].fY != top);
REPORTER_ASSERT(reporter, pts == 2);
REPORTER_ASSERT(reporter, pts == ts.used());
- check_results(reporter, line2, line1, ts, false);
+ check_results(reporter, line2, line1, ts);
}
if (line2[0].fX == line2[1].fX) {
double top = SkTMin(line2[0].fY, line2[1].fY);
@@ -194,7 +186,7 @@ static void testOneCoincident(skiatest::Reporter* reporter, const SkDLine& line1
ts.vertical(line1, top, bottom, line2[0].fX, line2[0].fY != top);
REPORTER_ASSERT(reporter, pts == 2);
REPORTER_ASSERT(reporter, pts == ts.used());
- check_results(reporter, line1, line2, ts, false);
+ check_results(reporter, line1, line2, ts);
}
reporter->bumpTestCount();
}
@@ -209,7 +201,7 @@ DEF_TEST(PathOpsLineIntersection, reporter) {
for (index = 0; index < tests_count; ++index) {
const SkDLine& line1 = tests[index][0];
const SkDLine& line2 = tests[index][1];
- testOne(reporter, line1, line2, true);
+ testOne(reporter, line1, line2);
}
for (index = 0; index < noIntersect_count; ++index) {
const SkDLine& line1 = noIntersect[index][0];
@@ -225,13 +217,8 @@ DEF_TEST(PathOpsLineIntersection, reporter) {
DEF_TEST(PathOpsLineIntersectionOneOff, reporter) {
int index = 0;
SkASSERT(index < (int) tests_count);
- testOne(reporter, tests[index][0], tests[index][1], true);
-}
-
-DEF_TEST(PathOpsLineIntersectionExactOneOff, reporter) {
- int index = 0;
- SkASSERT(index < (int) tests_count);
- testOne(reporter, tests[index][0], tests[index][1], false);
+ testOne(reporter, tests[index][0], tests[index][1]);
+ testOne(reporter, tests[1][0], tests[1][1]);
}
DEF_TEST(PathOpsLineIntersectionOneCoincident, reporter) {
diff --git a/tests/PathOpsOpCubicThreadedTest.cpp b/tests/PathOpsOpCubicThreadedTest.cpp
index 5815cf66f7..751ccc5f1b 100644
--- a/tests/PathOpsOpCubicThreadedTest.cpp
+++ b/tests/PathOpsOpCubicThreadedTest.cpp
@@ -27,10 +27,6 @@ static void testOpCubicsMain(PathOpsThreadState* data) {
SkPath pathA, pathB;
if (progress) {
char* str = pathStr;
- const int loopNo = 129;
- str += sprintf(str, "static void cubicOp%d(skiatest::Reporter* reporter,"
- " const char* filename) {\n", loopNo);
- str += sprintf(str, " SkPath path, pathB;\n");
str += sprintf(str, " path.setFillType(SkPath::k%s_FillType);\n",
e == SkPath::kWinding_FillType ? "Winding" : e == SkPath::kEvenOdd_FillType
? "EvenOdd" : "?UNDEFINED");
@@ -45,9 +41,6 @@ static void testOpCubicsMain(PathOpsThreadState* data) {
str += sprintf(str, " pathB.cubicTo(%d,%d, %d,%d, %d,%d);\n", c, d,
state.fB, state.fA, state.fD, state.fC);
str += sprintf(str, " pathB.close();\n");
- str += sprintf(str, " testPathOp(reporter, path, pathB, kDifference_PathOp,"
- " filename);\n");
- str += sprintf(str, "}\n");
}
pathA.setFillType((SkPath::FillType) e);
pathA.moveTo(SkIntToScalar(state.fA), SkIntToScalar(state.fB));
diff --git a/tests/PathOpsOpLoopThreadedTest.cpp b/tests/PathOpsOpLoopThreadedTest.cpp
index 40bf2cbeef..c50e23bae9 100755
--- a/tests/PathOpsOpLoopThreadedTest.cpp
+++ b/tests/PathOpsOpLoopThreadedTest.cpp
@@ -7,24 +7,6 @@
#include "PathOpsExtendedTest.h"
#include "PathOpsThreadedCommon.h"
-static int add_point(char* str, SkScalar x, SkScalar y) {
- int result;
- int asInt = SkScalarRoundToInt(x);
- if (SkIntToScalar(asInt) == x) {
- result = sprintf(str, "%d", asInt);
- } else {
- result = sprintf(str, "%1.9gf", x);
- }
- result += sprintf(str + result, ",");
- asInt = SkScalarRoundToInt(y);
- if (SkIntToScalar(asInt) == y) {
- result += sprintf(str + result, "%d", asInt);
- } else {
- result += sprintf(str + result, "%1.9gf", y);
- }
- return result;
-}
-
static void testOpLoopsMain(PathOpsThreadState* data) {
#if DEBUG_SHOW_TEST_NAME
strncpy(DEBUG_FILENAME_STRING, "", DEBUG_FILENAME_STRING_LENGTH);
@@ -53,27 +35,14 @@ static void testOpLoopsMain(PathOpsThreadState* data) {
SkPath pathA, pathB;
if (progress) {
char* str = pathStr;
- const int loopNo = 7;
- str += sprintf(str, "static void loop%d(skiatest::Reporter* reporter,"
- " const char* filename) {\n", loopNo);
- str += sprintf(str, " SkPath path, pathB;\n");
str += sprintf(str, " path.moveTo(%d,%d);\n", a, b);
- str += sprintf(str, " path.cubicTo(%d,%d, ", c, d);
- str += add_point(str, endC.fX, endC.fY);
- str += sprintf(str, ", ");
- str += add_point(str, endD.fX, endD.fY);
- str += sprintf(str, ");\n");
+ str += sprintf(str, " path.cubicTo(%d,%d, %1.9gf,%1.9gf, %1.9gf,%1.9gf);\n",
+ c, d, endC.fX, endC.fY, endD.fX, endD.fY);
str += sprintf(str, " path.close();\n");
str += sprintf(str, " pathB.moveTo(%d,%d);\n", c, d);
- str += sprintf(str, " pathB.cubicTo(");
- str += add_point(str, endC.fX, endC.fY);
- str += sprintf(str, ", ");
- str += add_point(str, endD.fX, endD.fY);
- str += sprintf(str, ", %d,%d);\n", a, b);
+ str += sprintf(str, " pathB.cubicTo(%1.9gf,%1.9gf, %1.9gf,%1.9gf, %d,%d);\n",
+ endC.fX, endC.fY, endD.fX, endD.fY, a, b);
str += sprintf(str, " pathB.close();\n");
- str += sprintf(str, " testPathOp(reporter, path, pathB, kIntersect_PathOp,"
- " filename);\n");
- str += sprintf(str, "}\n");
}
pathA.moveTo(SkIntToScalar(a), SkIntToScalar(b));
pathA.cubicTo(SkIntToScalar(c), SkIntToScalar(d), endC.fX, endC.fY, endD.fX, endD.fY);
@@ -93,6 +62,9 @@ static void testOpLoopsMain(PathOpsThreadState* data) {
}
DEF_TEST(PathOpsOpLoopsThreaded, reporter) {
+ if (!FLAGS_runFail) {
+ return;
+ }
initializeTests(reporter, "cubicOp");
PathOpsThreadedTestRunner testRunner(reporter);
for (int a = 0; a < 6; ++a) { // outermost
@@ -112,6 +84,9 @@ finish:
}
DEF_TEST(PathOpsOpLoops, reporter) {
+ if (!FLAGS_runFail) {
+ return;
+ }
initializeTests(reporter, "cubicOp");
PathOpsThreadState state;
state.fReporter = reporter;
diff --git a/tests/PathOpsOpTest.cpp b/tests/PathOpsOpTest.cpp
index 6b50cc920c..fbfa0b56a7 100644
--- a/tests/PathOpsOpTest.cpp
+++ b/tests/PathOpsOpTest.cpp
@@ -713,6 +713,11 @@ static void cubicOp37d(skiatest::Reporter* reporter, const char* filename) {
testPathOp(reporter, path, pathB, kDifference_PathOp, filename);
}
+// this fails to detect a cubic/cubic intersection
+// the slight overlap is missed when the cubics are approximated by quadratics
+// and the subsequent line/cubic intersection also (correctly) misses the intersection
+// if the line/cubic was a matching line/approx.quadratic then the missing intersection
+// could have been detected
static void cubicOp38d(skiatest::Reporter* reporter, const char* filename) {
SkPath path, pathB;
path.setFillType(SkPath::kWinding_FillType);
@@ -1790,6 +1795,9 @@ static void cubicOp85d(skiatest::Reporter* reporter, const char* filename) {
testPathOp(reporter, path, pathB, kDifference_PathOp, filename);
}
+// this fails because the pair of nearly coincident cubics intersect at the ends
+// but the line connected to one of the cubics at the same point does not intersect
+// the other
static void skpkkiste_to98(skiatest::Reporter* reporter, const char* filename) {
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
@@ -1926,7 +1934,7 @@ static void issue1417(skiatest::Reporter* reporter, const char* filename) {
path2.lineTo(113.232177734375f, 173.5789947509765625f);
path2.lineTo(113.232177734375f, 173.5789947509765625f);
path2.close();
- // FIXME : difficult data, circle back later
+
testPathOp(reporter, path1, path2, kUnion_PathOp, filename);
}
@@ -2048,6 +2056,9 @@ static void rectOp3x(skiatest::Reporter* reporter, const char* filename) {
testPathOp(reporter, path, pathB, kXOR_PathOp, filename);
}
+// this fails to generate two interior line segments
+// an earlier pathops succeeded, but still failed to generate one interior line segment
+// (but was saved by assemble, which works around a single line missing segment)
static void issue1435(skiatest::Reporter* reporter, const char* filename) {
SkPath path1;
path1.moveTo(160, 60);
@@ -2245,7 +2256,7 @@ static void cubicOp91u(skiatest::Reporter* reporter, const char* filename) {
testPathOp(reporter, path, pathB, kUnion_PathOp, filename);
}
-static void skpaaalgarve_org53(skiatest::Reporter* reporter, const char* filename) {
+static void skpaaalgarve_org53(skiatest::Reporter* reporter, const char* filename) { // add t cancel
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
path.moveTo(-1.24344979e-014f, 348);
@@ -2266,7 +2277,7 @@ static void skpaaalgarve_org53(skiatest::Reporter* reporter, const char* filenam
testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
-static void skpabcspark_ca103(skiatest::Reporter* reporter, const char* filename) {
+static void skpabcspark_ca103(skiatest::Reporter* reporter, const char* filename) { // add t cancel
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
path.moveTo(1.99840144e-015f, 494);
@@ -2289,7 +2300,7 @@ static void skpabcspark_ca103(skiatest::Reporter* reporter, const char* filename
testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
-static void skpacesoftech_com47(skiatest::Reporter* reporter, const char* filename) {
+static void skpacesoftech_com47(skiatest::Reporter* reporter, const char* filename) { // partial coincidence
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
path.moveTo(670.537415f, 285);
@@ -2315,7 +2326,7 @@ static void skpacesoftech_com47(skiatest::Reporter* reporter, const char* filena
testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
-static void skpact_com43(skiatest::Reporter* reporter, const char* filename) {
+static void skpact_com43(skiatest::Reporter* reporter, const char* filename) { // bridge op
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
path.moveTo(1.45716772e-016f, 924.336121f);
@@ -2340,7 +2351,7 @@ static void skpact_com43(skiatest::Reporter* reporter, const char* filename) {
testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
-static void skpadbox_lt8(skiatest::Reporter* reporter, const char* filename) {
+static void skpadbox_lt8(skiatest::Reporter* reporter, const char* filename) { // zero span
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
path.moveTo(320.097229f, 628.573669f);
@@ -2364,7 +2375,7 @@ static void skpadbox_lt8(skiatest::Reporter* reporter, const char* filename) {
testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
-static void skpadindex_de4(skiatest::Reporter* reporter, const char* filename) {
+static void skpadindex_de4(skiatest::Reporter* reporter, const char* filename) { // find chase op
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
path.moveTo(0, 926);
@@ -2383,7 +2394,7 @@ static void skpadindex_de4(skiatest::Reporter* reporter, const char* filename) {
testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
-static void skpadithya_putr4_blogspot_com551(skiatest::Reporter* reporter, const char* filename) {
+static void skpadithya_putr4_blogspot_com551(skiatest::Reporter* reporter, const char* filename) { // calc common
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
path.moveTo(205.605804f, 142.334625f);
@@ -2407,7 +2418,7 @@ static void skpadithya_putr4_blogspot_com551(skiatest::Reporter* reporter, const
testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
-static void skpadspert_de11(skiatest::Reporter* reporter, const char* filename) {
+static void skpadspert_de11(skiatest::Reporter* reporter, const char* filename) { // mark and chase winding
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
path.moveTo(-4.4408921e-016f, 682.5f);
@@ -2428,7 +2439,7 @@ static void skpadspert_de11(skiatest::Reporter* reporter, const char* filename)
testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
-static void skpaiaigames_com870(skiatest::Reporter* reporter, const char* filename) {
+static void skpaiaigames_com870(skiatest::Reporter* reporter, const char* filename) { // cubic/cubic intersect
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
path.moveTo(324.071075f, 845.071045f);
@@ -2455,7 +2466,7 @@ static void skpaiaigames_com870(skiatest::Reporter* reporter, const char* filena
pathB.cubicTo(145, 715.477173f, 149.477158f, 711, 155, 711);
pathB.lineTo(317, 711);
pathB.close();
- testPathOpCheck(reporter, path, pathB, kIntersect_PathOp, filename, FLAGS_runFail);
+ testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
static void cubicOp92i(skiatest::Reporter* reporter, const char* filename) {
@@ -2713,6 +2724,7 @@ static void skpcarpetplanet_ru22(skiatest::Reporter* reporter, const char* filen
testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
+// this fails because cubic/quad misses an intersection (failure is isolated in c/q int test)
static void skpcarrot_is24(skiatest::Reporter* reporter, const char* filename) {
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
@@ -2736,7 +2748,7 @@ static void skpcarrot_is24(skiatest::Reporter* reporter, const char* filename) {
pathB.cubicTo(1019.77502f, 679.955017f, 1020.08099f, 676.094971f, 1020.08099f, 672.161987f);
pathB.cubicTo(1020.08002f, 630.73999f, 986.502014f, 597.161987f, 945.080994f, 597.161987f);
pathB.close();
- testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
+ testPathOpCheck(reporter, path, pathB, kIntersect_PathOp, filename, FLAGS_runFail);
}
static void skpbangalorenest_com4(skiatest::Reporter* reporter, const char* filename) {
@@ -3235,6 +3247,7 @@ static void findFirst1(skiatest::Reporter* reporter, const char* filename) {
testPathOp(reporter, path, pathB, kDifference_PathOp, filename);
}
+// triggers addSimpleAngle with non-zero argument
static void cubicOp112(skiatest::Reporter* reporter, const char* filename) {
SkPath path, pathB;
path.setFillType(SkPath::kWinding_FillType);
@@ -3269,7 +3282,7 @@ static void cubicOp114(skiatest::Reporter* reporter, const char* filename) {
pathB.moveTo(1, 3);
pathB.cubicTo(-1, 2, 3.5f, 1.33333337f, 0, 1);
pathB.close();
- testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
+ testPathOpCheck(reporter, path, pathB, kIntersect_PathOp, filename, FLAGS_runFail);
}
static void cubicOp114asQuad(skiatest::Reporter* reporter, const char* filename) {
@@ -3451,7 +3464,7 @@ static void issue2753(skiatest::Reporter* reporter, const char* filename) {
path2.cubicTo(188.201f, 117.601f, 174.801f, 93, 39, 124.001f);
path2.close();
- testPathOp(reporter, path1, path2, kUnion_PathOp, filename);
+ testPathOpCheck(reporter, path1, path2, kUnion_PathOp, filename, FLAGS_runFail);
}
static void issue2808(skiatest::Reporter* reporter, const char* filename) {
@@ -3496,335 +3509,12 @@ static void cubicOp115(skiatest::Reporter* reporter, const char* filename) {
testPathOp(reporter, path, pathB, kDifference_PathOp, filename);
}
-static void testRect1(skiatest::Reporter* reporter, const char* filename) {
- SkPath path, path2;
- path.addRect(0, 0, 60, 60, SkPath::kCCW_Direction);
- path.addRect(30, 20, 50, 50, SkPath::kCCW_Direction);
- path.addRect(24, 20, 36, 30, SkPath::kCCW_Direction);
-// path.addRect(32, 24, 36, 41, SkPath::kCCW_Direction);
- testPathOp(reporter, path, path2, kUnion_PathOp, filename);
-}
-
-static void testRect2(skiatest::Reporter* reporter, const char* filename) {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.addRect(0, 0, 1, 1, SkPath::kCW_Direction);
- path.addRect(4, 4, 5, 5, SkPath::kCW_Direction);
- pathB.setFillType(SkPath::kEvenOdd_FillType);
- pathB.addRect(0, 0, 2, 2, SkPath::kCW_Direction);
- pathB.addRect(0, 0, 6, 6, SkPath::kCW_Direction);
- testPathOp(reporter, path, pathB, kDifference_PathOp, filename);
-}
-
-static void cubicOp116(skiatest::Reporter* reporter, const char* filename) {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(4,6, 2,0, 2,0);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,2);
- pathB.cubicTo(0,2, 1,0, 6,4);
- pathB.close();
- testPathOp(reporter, path, pathB, kDifference_PathOp, filename);
-}
-
-static void cubicOp117(skiatest::Reporter* reporter, const char* filename) {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(4,5, 6,0, 1,0);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,6);
- pathB.cubicTo(0,1, 1,0, 5,4);
- pathB.close();
- testPathOp(reporter, path, pathB, kDifference_PathOp, filename);
-}
-
-static void cubicOp118(skiatest::Reporter* reporter, const char* filename) {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(4,6, 5,1, 6,2);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(1,5);
- pathB.cubicTo(2,6, 1,0, 6,4);
- pathB.close();
- testPathOp(reporter, path, pathB, kDifference_PathOp, filename);
-}
-
-static void loop1(skiatest::Reporter* reporter, const char* filename) {
- SkPath path, pathB;
- path.moveTo(0,1);
- path.cubicTo(1,5, -5.66666651f,3.33333349f, 8.83333302f,2.33333349f);
- path.close();
- pathB.moveTo(1,5);
- pathB.cubicTo(-5.66666651f,3.33333349f, 8.83333302f,2.33333349f, 0,1);
- pathB.close();
- testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
-}
-
-#include "SkPathOpsCubic.h"
-
-static void loop1asQuad(skiatest::Reporter* reporter, const char* filename) {
- SkDCubic c1 = {{{0,1}, {1,5}, {-5.66666651f,3.33333349f}, {8.83333302f,2.33333349f}}};
- SkDCubic c2 = {{{1,5}, {-5.66666651f,3.33333349f}, {8.83333302f,2.33333349f}, {0,1}}};
- double c1InflectionTs[2], c2InflectionTs[2];
- SkDEBUGCODE(int c1InfTCount =) c1.findInflections(c1InflectionTs);
- SkASSERT(c1InfTCount == 2);
- SkDEBUGCODE(int c2InfTCount =) c2.findInflections(c2InflectionTs);
- SkASSERT(c2InfTCount == 1);
- SkASSERT(c1InflectionTs[0] > c1InflectionTs[1]);
- SkDCubicPair c1pair = c1.chopAt(c1InflectionTs[0]);
- SkDCubicPair c1apair = c1pair.first().chopAt(c1InflectionTs[1]);
- SkDCubicPair c2pair = c2.chopAt(c2InflectionTs[0]);
- SkDQuad q1[2] = { c1pair.first().toQuad(), c1pair.second().toQuad() };
- SkDQuad q1a[2] = { c1apair.first().toQuad(), c1apair.second().toQuad() };
- SkDQuad q2[2] = { c2pair.first().toQuad(), c2pair.second().toQuad() };
- SkPath path, pathB;
- path.moveTo(q1a[0].fPts[0].asSkPoint());
- path.quadTo(q1a[0].fPts[1].asSkPoint(), q1a[0].fPts[2].asSkPoint());
- path.quadTo(q1a[1].fPts[1].asSkPoint(), q1a[1].fPts[2].asSkPoint());
- path.quadTo(q1[1].fPts[1].asSkPoint(), q1[1].fPts[2].asSkPoint());
- path.close();
- pathB.moveTo(q2[0].fPts[0].asSkPoint());
- pathB.quadTo(q2[0].fPts[1].asSkPoint(), q2[0].fPts[2].asSkPoint());
- pathB.quadTo(q2[1].fPts[1].asSkPoint(), q2[1].fPts[2].asSkPoint());
- pathB.close();
- testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
-}
-
-static void loop2(skiatest::Reporter* reporter, const char* filename) {
- SkPath path, pathB;
- path.moveTo(0,1);
- path.cubicTo(3,4, 3.f,4.f, 4.5f,1.5f);
- path.close();
- pathB.moveTo(3,4);
- pathB.cubicTo(3.f,4.f, 4.5f,1.5f, 0,1);
- pathB.close();
- testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
-}
-
-static void loop3(skiatest::Reporter* reporter, const char* filename) {
- SkPath path, pathB;
- path.moveTo(0,1);
- path.cubicTo(3,5, -3.66666651f,0, 10.5f,-1.66666651f);
- path.close();
- pathB.moveTo(3,5);
- pathB.cubicTo(-3.66666651f,0, 10.5f,-1.66666651f, 0,1);
- pathB.close();
- testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
-}
-
-static void loop4(skiatest::Reporter* reporter, const char* filename) {
- SkPath path, pathB;
- path.moveTo(0,5);
- path.cubicTo(1,5, 1,4, 0.833333313f,3);
- path.close();
- pathB.moveTo(1,5);
- pathB.cubicTo(1,4, 0.833333313f,3, 0,5);
- pathB.close();
- testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
-}
-
-#include "SkParsePath.h"
-
-static void issue3517(skiatest::Reporter* reporter, const char* filename) {
- SkPath path, pathB;
-
- const char str[] = "M31.35 57.75L31.35 57.75C31.9 57.7486 32.45 57.7948 33 57.7413C33.55 57.6878 34.1 57.5014 34.65 57.4291C35.2 57.3569 35.75 57.3223 36.3 57.3079C36.85 57.2935 37.4 57.3143 37.95 57.3428C38.5 57.3712 39.05 57.4112 39.6 57.4786C40.15 57.546 40.7 57.7029 41.25 57.7472C41.8 57.7916 42.35 57.7962 42.9 57.7445C43.45 57.6928 44 57.5345 44.55 57.4373C45.1 57.34 45.65 57.2115 46.2 57.1611C46.75 57.1107 47.3 57.1371 47.85 57.1349C48.4 57.1327 48.95 57.144 49.5 57.1478C50.05 57.1516 50.6 57.1553 51.15 57.1579C51.7 57.1605 52.25 57.1601 52.8 57.1634C53.35 57.1667 53.9 57.1731 54.45 57.1776C55 57.182 55.55 57.1916 56.1 57.19C56.65 57.1884 57.2 57.178 57.75 57.168C58.3 57.158 58.85 57.1355 59.4 57.1299C59.95 57.1243 60.5 57.1338 61.05 57.1345C61.6 57.1352 62.15 57.124 62.7 57.134C63.25 57.1441 63.8 57.1731 64.35 57.195C64.9 57.2169 65.45 57.2532 66 57.2655C66.55 57.2778 67.1 57.2647 67.65 57.2687C68.2 57.2728 68.75 57.267 69.3 57.2896C69.85 57.3122 70.4 57.371 70.95 57.4044C71.5 57.4377 72.05 57.4668 72.6 57.4896C73.15 57.5123 73.7 57.545 74.25 57.5408C74.8 57.5365 75.35 57.5068 75.9 57.4641C76.45 57.4213 77 57.3244 77.55 57.2842C78.1 57.244 78.65 57.2163 79.2 57.2228C79.75 57.2293 80.3 57.29 80.85 57.3232C81.4 57.3563 81.95 57.396 82.5 57.4219C83.05 57.4478 83.6 57.4637 84.15 57.4787C84.7 57.4937 85.25 57.5011 85.8 57.5121C86.35 57.523 86.9 57.5411 87.45 57.5444C88 57.5477 88.55 57.5663 89.1 57.5318C89.65 57.4972 90.2 57.3126 90.75 57.337C91.3 57.3613 91.85 57.6088 92.4 57.6776C92.95 57.7465 93.5 57.7379 94.05 57.75C94.6 57.7621 95.15 57.75 95.7 57.75L95.7 57.75L31.35 57.75Z";
- SkParsePath::FromSVGString(str, &path);
-
- const char strB[] = "M31.35 57.75L31.35 57.75C31.9 57.7514 32.45 57.7052 33 57.7587C33.55 57.8122 34.1 57.9986 34.65 58.0709C35.2 58.1431 35.75 58.1777 36.3 58.1921C36.85 58.2065 37.4 58.1857 37.95 58.1572C38.5 58.1288 39.05 58.0888 39.6 58.0214C40.15 57.954 40.7 57.7971 41.25 57.7528C41.8 57.7084 42.35 57.7038 42.9 57.7555C43.45 57.8072 44 57.9655 44.55 58.0627C45.1 58.16 45.65 58.2885 46.2 58.3389C46.75 58.3893 47.3 58.3629 47.85 58.3651C48.4 58.3673 48.95 58.356 49.5 58.3522C50.05 58.3484 50.6 58.3447 51.15 58.3421C51.7 58.3395 52.25 58.3399 52.8 58.3366C53.35 58.3333 53.9 58.3269 54.45 58.3224C55 58.318 55.55 58.3084 56.1 58.31C56.65 58.3116 57.2 58.322 57.75 58.332C58.3 58.342 58.85 58.3645 59.4 58.3701C59.95 58.3757 60.5 58.3662 61.05 58.3655C61.6 58.3648 62.15 58.376 62.7 58.366C63.25 58.3559 63.8 58.3269 64.35 58.305C64.9 58.2831 65.45 58.2468 66 58.2345C66.55 58.2222 67.1 58.2353 67.65 58.2313C68.2 58.2272 68.75 58.233 69.3 58.2104C69.85 58.1878 70.4 58.129 70.95 58.0956C71.5 58.0623 72.05 58.0332 72.6 58.0104C73.15 57.9877 73.7 57.955 74.25 57.9592C74.8 57.9635 75.35 57.9932 75.9 58.0359C76.45 58.0787 77 58.1756 77.55 58.2158C78.1 58.256 78.65 58.2837 79.2 58.2772C79.75 58.2707 80.3 58.21 80.85 58.1768C81.4 58.1437 81.95 58.104 82.5 58.0781C83.05 58.0522 83.6 58.0363 84.15 58.0213C84.7 58.0063 85.25 57.9989 85.8 57.9879C86.35 57.977 86.9 57.9589 87.45 57.9556C88 57.9523 88.55 57.9337 89.1 57.9682C89.65 58.0028 90.2 58.1874 90.75 58.163C91.3 58.1387 91.85 57.8912 92.4 57.8224C92.95 57.7535 93.5 57.7621 94.05 57.75C94.6 57.7379 95.15 57.75 95.7 57.75L95.7 57.75L31.35 57.75Z";
- SkParsePath::FromSVGString(strB, &pathB);
- testPathOp(reporter, path, pathB, kUnion_PathOp, filename);
-}
-
-static void cubicOp119(skiatest::Reporter* reporter, const char* filename) {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(3,5, 2,1, 3,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(1,2);
- pathB.cubicTo(1,3, 1,0, 5,3);
- pathB.close();
- testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
-}
-
-static void cubicOp120(skiatest::Reporter* reporter, const char* filename) {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(2,4, 2,1, 4,0);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(1,2);
- pathB.cubicTo(0,4, 1,0, 4,2);
- pathB.close();
- testPathOp(reporter, path, pathB, kDifference_PathOp, filename);
-}
-
-static void cubicOp121(skiatest::Reporter* reporter, const char* filename) {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(3,4, 3,2, 4,3);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(2,3);
- pathB.cubicTo(3,4, 1,0, 4,3);
- pathB.close();
- testPathOp(reporter, path, pathB, kDifference_PathOp, filename);
-}
-
-// FIXME : haven't debugged this failure yet
-static void cubicOp122(skiatest::Reporter* reporter, const char* filename) {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(3,5, 4,1, 4,0);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(1,4);
- pathB.cubicTo(0,4, 1,0, 5,3);
- pathB.close();
- testPathOp(reporter, path, pathB, kDifference_PathOp, filename);
-}
-
-static void cubicOp123(skiatest::Reporter* reporter, const char* filename) {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(1,5, 2,0, 6,0);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,2);
- pathB.cubicTo(0,6, 1,0, 5,1);
- pathB.close();
- testPathOp(reporter, path, pathB, kDifference_PathOp, filename);
-}
-
-static void loop5(skiatest::Reporter* reporter, const char* filename) {
- SkPath path, pathB;
- path.moveTo(0,2);
- path.cubicTo(1,2, 1,1.66666663f, 0.833333313f,1.33333325f);
- path.close();
- pathB.moveTo(1,2);
- pathB.cubicTo(1,1.66666663f, 0.833333313f,1.33333325f, 0,2);
- pathB.close();
- testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
-}
-
-static void loop6(skiatest::Reporter* reporter, const char* filename) {
- SkPath path, pathB;
- path.moveTo(0,1);
- path.cubicTo(1,3, -1.66666675f,1.66666663f, 4.16666651f,1.00000012f);
- path.close();
- pathB.moveTo(1,3);
- pathB.cubicTo(-1.66666675f,1.66666663f, 4.16666651f,1.00000012f, 0,1);
- pathB.close();
- testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
-}
-
-static void cubicOp124(skiatest::Reporter* reporter, const char* filename) {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(1,5, 6,0, 3,0);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,6);
- pathB.cubicTo(0,3, 1,0, 5,1);
- pathB.close();
- testPathOp(reporter, path, pathB, kDifference_PathOp, filename);
-}
-
-static void cubicOp125(skiatest::Reporter* reporter, const char* filename) {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(3,6, 3,1, 6,2);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(1,3);
- pathB.cubicTo(2,6, 1,0, 6,3);
- pathB.close();
- testPathOp(reporter, path, pathB, kDifference_PathOp, filename);
-}
-
-static void cubicOp126(skiatest::Reporter* reporter, const char* filename) {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(0,3, 6,0, 2,1);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,6);
- pathB.cubicTo(1,2, 1,0, 3,0);
- pathB.close();
- testPathOp(reporter, path, pathB, kDifference_PathOp, filename);
-}
-
-static void cubicOp127(skiatest::Reporter* reporter, const char* filename) {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(1,5, 6,0, 3,0);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(0,6);
- pathB.cubicTo(0,3, 1,0, 5,1);
- pathB.close();
- testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
-}
-
-static void cubicOp128(skiatest::Reporter* reporter, const char* filename) {
- SkPath path, pathB;
- path.setFillType(SkPath::kWinding_FillType);
- path.moveTo(0,1);
- path.cubicTo(0,3, 3,2, 5,2);
- path.close();
- pathB.setFillType(SkPath::kWinding_FillType);
- pathB.moveTo(2,3);
- pathB.cubicTo(2,5, 1,0, 3,0);
- pathB.close();
- testPathOp(reporter, path, pathB, kDifference_PathOp, filename);
-}
-
-static void (*skipTest)(skiatest::Reporter* , const char* filename) = 0;
static void (*firstTest)(skiatest::Reporter* , const char* filename) = 0;
static void (*stopTest)(skiatest::Reporter* , const char* filename) = 0;
static struct TestDesc tests[] = {
- TEST(cubicOp128),
- TEST(cubicOp127),
- TEST(cubicOp126),
- TEST(cubicOp125),
- TEST(cubicOp124),
- TEST(loop6),
- TEST(loop5),
- TEST(cubicOp123),
- TEST(cubicOp122),
- TEST(cubicOp121),
- TEST(cubicOp120),
- TEST(cubicOp119),
- TEST(loop4),
- TEST(loop3),
- TEST(loop2),
- TEST(loop1asQuad),
- TEST(loop1),
- TEST(issue3517),
- TEST(cubicOp118),
- TEST(cubicOp117),
- TEST(cubicOp116),
- TEST(testRect2),
- TEST(testRect1),
TEST(cubicOp115),
- TEST(issue2753),
+ TEST(issue2753), // FIXME: pair of cubics miss intersection
TEST(cubicOp114), // FIXME: curve with inflection is ordered the wrong way
TEST(issue2808),
TEST(cubicOp114asQuad),
@@ -3837,6 +3527,8 @@ static struct TestDesc tests[] = {
TEST(kari1),
TEST(quadOp10i),
TEST(cubicOp113),
+ // fails because a cubic/quadratic intersection is missed
+ // the internal quad/quad is far enough away from the real cubic/quad that it is rejected
TEST(skpcarrot_is24),
TEST(issue1417),
TEST(cubicOp112),
@@ -3863,7 +3555,7 @@ static struct TestDesc tests[] = {
TEST(issue1435),
TEST(cubicOp98x),
TEST(cubicOp97x),
- TEST(skpcarpetplanet_ru22),
+ TEST(skpcarpetplanet_ru22), // cubic/cubic intersect detects unwanted coincidence
TEST(cubicOp96d),
TEST(cubicOp95u),
TEST(skpadbox_lt15),
@@ -4055,11 +3747,11 @@ DEF_TEST(PathOpsOp, reporter) {
strncpy(DEBUG_FILENAME_STRING, "", DEBUG_FILENAME_STRING_LENGTH);
#endif
if (runSubTests && runSubTestsFirst) {
- RunTestSet(reporter, subTests, subTestCount, firstSubTest, NULL, stopTest, runReverse);
+ RunTestSet(reporter, subTests, subTestCount, firstSubTest, stopTest, runReverse);
}
- RunTestSet(reporter, tests, testCount, firstTest, skipTest, stopTest, runReverse);
+ RunTestSet(reporter, tests, testCount, firstTest, stopTest, runReverse);
if (runSubTests && !runSubTestsFirst) {
- RunTestSet(reporter, subTests, subTestCount, firstSubTest, NULL, stopTest, runReverse);
+ RunTestSet(reporter, subTests, subTestCount, firstSubTest, stopTest, runReverse);
}
}
@@ -4068,7 +3760,7 @@ static void bufferOverflow(skiatest::Reporter* reporter, const char* filename) {
path.addRect(0,0, 300,170141183460469231731687303715884105728.f);
SkPath pathB;
pathB.addRect(0,0, 300,16);
- testPathOp(reporter, path, pathB, kUnion_PathOp, filename);
+ testPathFailOp(reporter, path, pathB, kUnion_PathOp, filename);
}
// m 100,0 60,170 -160,-110 200,0 -170,11000000000 z
@@ -4088,7 +3780,7 @@ static void fuzz433(skiatest::Reporter* reporter, const char* filename) {
path2.lineTo(-170 + 20,11000000000.0f + 20);
path2.close();
- testPathOpCheck(reporter, path1, path2, kIntersect_PathOp, filename, FLAGS_runFail);
+ testPathFailOp(reporter, path1, path2, kIntersect_PathOp, filename);
}
static void fuzz433b(skiatest::Reporter* reporter, const char* filename) {
@@ -4111,7 +3803,7 @@ static void fuzz433b(skiatest::Reporter* reporter, const char* filename) {
path2.lineTo(190, 60);
path2.close();
- testPathOpCheck(reporter, path1, path2, kUnion_PathOp, filename, FLAGS_runFail);
+ testPathFailOp(reporter, path1, path2, kUnion_PathOp, filename);
}
static void fuzz487a(skiatest::Reporter* reporter, const char* filename) {
@@ -4157,7 +3849,7 @@ path.lineTo(SkBits2Float(0x432c8000), SkBits2Float(0x42c00000));
path.close();
SkPath path2(path);
- testPathOpCheck(reporter, path1, path2, (SkPathOp) 2, filename, FLAGS_runFail);
+ testPathFailOp(reporter, path1, path2, (SkPathOp) 2, filename);
}
static void fuzz487b(skiatest::Reporter* reporter, const char* filename) {
@@ -4203,7 +3895,7 @@ path.lineTo(SkBits2Float(0x432c8000), SkBits2Float(0x42c00000));
path.close();
SkPath path2(path);
- testPathOpCheck(reporter, path1, path2, (SkPathOp) 2, filename, FLAGS_runFail);
+ testPathFailOp(reporter, path1, path2, (SkPathOp) 2, filename);
}
static void fuzz714(skiatest::Reporter* reporter, const char* filename) {
@@ -4270,5 +3962,5 @@ DEF_TEST(PathOpsFailOp, reporter) {
#if DEBUG_SHOW_TEST_NAME
strncpy(DEBUG_FILENAME_STRING, "", DEBUG_FILENAME_STRING_LENGTH);
#endif
- RunTestSet(reporter, failTests, failTestCount, NULL, NULL, NULL, false);
+ RunTestSet(reporter, failTests, failTestCount, 0, 0, false);
}
diff --git a/tests/PathOpsQuadIntersectionTest.cpp b/tests/PathOpsQuadIntersectionTest.cpp
index 0455802e3b..565098af81 100644
--- a/tests/PathOpsQuadIntersectionTest.cpp
+++ b/tests/PathOpsQuadIntersectionTest.cpp
@@ -53,36 +53,6 @@ static void standardTestCases(skiatest::Reporter* reporter) {
}
static const SkDQuad testSet[] = {
-{{{4981.9990234375, 1590}, {4981.9990234375, 1617.7523193359375}, {4962.375, 1637.3760986328125}}},
-{{{4962.3759765625, 1637.3760986328125}, {4982, 1617.7523193359375}, {4982, 1590}}},
-
-{{{48.7416f, 7.74160004f}, {96.4831848f, -40}, {164, -40}}},
-{{{56.9671326f, 0}, {52.7835083f, 3.69968891f}, {48.7416f, 7.74160004f}}},
-
-{{{138, 80}, {147.15692138671875, 80}, {155.12803649902344, 82.86279296875}}},
-{{{155.12803649902344, 82.86279296875}, {153.14971923828125, 82.152290344238281}, {151.09841918945312, 81.618133544921875}}},
-
-{{{88, 130}, {88, 131.54483032226562}, {88.081489562988281, 133.0560302734375}}},
-{{{88.081489562988281, 133.0560302734375}, {88, 131.54483032226562}, {88, 130}}},
-
-{{{0.59987992,2.14448452}, {0.775417507,1.95606446}, {1.00564098,1.79310346}}},
-{{{1.00564098,1.79310346}, {1.25936198,1.615623}, {1.35901463,1.46834028}}},
-
-{{{3,0}, {0,1}, {3,2}}},
-{{{2,0}, {1,1}, {2,2}}},
-
-{{{38.656852722167969, 38.656852722167969}, {38.651023864746094, 38.662681579589844}, {38.644744873046875, 38.668937683105469}}},
-{{{38.656852722167969, 38.656852722167969}, {36.313709259033203, 41}, {33, 41}}},
-
-{{{4914.9990234375, 1523}, {4942.75146484375, 1523}, {4962.375, 1542.6239013671875}}},
-{{{4962.3759765625, 1542.6239013671875}, {4942.75244140625, 1523}, {4915, 1523}}},
-
-{{{4867.623046875, 1637.3760986328125}, {4847.9990234375, 1617.7523193359375}, {4847.9990234375, 1590}}},
-{{{4848, 1590}, {4848, 1617.7523193359375}, {4867.6240234375, 1637.3760986328125}}},
-
-{{{102.64466094970703, 165.3553466796875}, {110.79246520996094, 173.50314331054687}, {120.81797790527344, 177.11778259277344}}},
-{{{113.232177734375, 173.57899475097656}, {116.88026428222656, 175.69805908203125}, {120.81797790527344, 177.11778259277344}}},
-
{{{-37.3484879,10.0192947}, {-36.4966316,13.2140198}, {-38.1506348,16.0788383}}},
{{{-38.1462746,16.08918}, {-36.4904327,13.2193804}, {-37.3484879,10.0192947}}},
@@ -350,8 +320,6 @@ static void oneOffTests(skiatest::Reporter* reporter) {
}
static const SkDQuad coincidentTestSet[] = {
- {{{4914.9990234375, 1523}, {4942.75146484375, 1523}, {4962.375, 1542.6239013671875}}},
- {{{4962.3759765625, 1542.6239013671875}, {4942.75244140625, 1523}, {4915, 1523}}},
#if 0
{{{97.9337615966796875,100}, {88,112.94264984130859375}, {88,130}}},
{{{88,130}, {88,124.80951690673828125}, {88.91983795166015625,120}}},
@@ -371,9 +339,9 @@ static void coincidentTestOne(skiatest::Reporter* reporter, int test1, int test2
SkASSERT(ValidQuad(quad2));
SkIntersections intersections2;
intersections2.intersect(quad1, quad2);
- REPORTER_ASSERT(reporter, intersections2.coincidentUsed() >= 2);
- REPORTER_ASSERT(reporter, intersections2.used() >= 2);
- for (int pt = 0; pt < intersections2.coincidentUsed(); pt += 2) {
+ REPORTER_ASSERT(reporter, intersections2.coincidentUsed() == 2);
+ REPORTER_ASSERT(reporter, intersections2.used() == 2);
+ for (int pt = 0; pt < intersections2.coincidentUsed(); ++pt) {
double tt1 = intersections2[0][pt];
double tt2 = intersections2[1][pt];
SkDPoint pt1 = quad1.ptAtT(tt1);
@@ -422,8 +390,9 @@ static void pointFinder(const SkDQuad& q1, const SkDQuad& q2) {
left[1] = ((const SkDLine&) q1[1]).isLeft(q2[index]);
SkDLine diag = {{q1[0], q1[2]}};
left[2] = diag.isLeft(q2[index]);
- SkDebugf("%s left=(%d, %d, %d)\n", __FUNCTION__, floatSign(left[0]),
- floatSign(left[1]), floatSign(left[2]));
+ SkDebugf("%s left=(%d, %d, %d) inHull=%s\n", __FUNCTION__, floatSign(left[0]),
+ floatSign(left[1]), floatSign(left[2]),
+ q1.pointInHull(q2[index]) ? "true" : "false");
}
SkDebugf("\n");
}
@@ -550,14 +519,6 @@ static void QuadraticIntersection_IntersectionFinder() {
intersectionFinder(0, 1);
}
-DEF_TEST(PathOpsQuadIntersectionOneOff, reporter) {
- oneOffTest1(reporter, 10, 11);
-}
-
-DEF_TEST(PathOpsQuadIntersectionCoincidenceOneOff, reporter) {
- coincidentTestOne(reporter, 0, 1);
-}
-
DEF_TEST(PathOpsQuadIntersection, reporter) {
oneOffTests(reporter);
coincidentTest(reporter);
@@ -566,31 +527,10 @@ DEF_TEST(PathOpsQuadIntersection, reporter) {
if (false) QuadraticIntersection_PointFinder();
}
-#include "SkCommonFlags.h"
+DEF_TEST(PathOpsQuadIntersectionCoincidenceOneOff, reporter) {
+ coincidentTestOne(reporter, 0, 1);
+}
-DEF_TEST(PathOpsQuadBinaryProfile, reporter) {
- if (!FLAGS_veryVerbose) {
- return;
- }
- SkIntersections intersections;
- for (int x = 0; x < 100; ++x) {
- int outer = 0;
- int inner = outer + 1;
- do {
- const SkDQuad& quad1 = testSet[outer];
- const SkDQuad& quad2 = testSet[inner];
- (void) intersections.intersect(quad1, quad2);
- REPORTER_ASSERT(reporter, intersections.used() >= 0); // make sure code isn't tossed
- inner += 2;
- outer += 2;
- } while (outer < (int) testSetCount);
- }
- for (int x = 0; x < 100; ++x) {
- for (size_t test = 0; test < quadraticTests_count; ++test) {
- const SkDQuad& quad1 = quadraticTests[test][0];
- const SkDQuad& quad2 = quadraticTests[test][1];
- (void) intersections.intersect(quad1, quad2);
- REPORTER_ASSERT(reporter, intersections.used() >= 0); // make sure code isn't tossed
- }
- }
+DEF_TEST(PathOpsQuadIntersectionOneOff, reporter) {
+ oneOffTest1(reporter, 0, 1);
}
diff --git a/tests/PathOpsQuadIntersectionTestData.cpp b/tests/PathOpsQuadIntersectionTestData.cpp
index f51f9518bd..0706efcf45 100644
--- a/tests/PathOpsQuadIntersectionTestData.cpp
+++ b/tests/PathOpsQuadIntersectionTestData.cpp
@@ -44,10 +44,10 @@ const SkDQuad quadraticLines[] = {
const size_t quadraticLines_count = SK_ARRAY_COUNT(quadraticLines);
-static const double F = FLT_EPSILON * 32;
-static const double H = FLT_EPSILON * 32;
-static const double J = FLT_EPSILON * 32;
-static const double K = FLT_EPSILON * 32; // INVESTIGATE: why are larger multiples necessary?
+static const double F = FLT_EPSILON * 3;
+static const double H = FLT_EPSILON * 4;
+static const double J = FLT_EPSILON * 5;
+static const double K = FLT_EPSILON * 8; // INVESTIGATE: why are larger multiples necessary?
const SkDQuad quadraticModEpsilonLines[] = {
{{{0, F}, {0, 0}, {1, 0}}},
@@ -64,7 +64,7 @@ const SkDQuad quadraticModEpsilonLines[] = {
{{{1, 1+J}, {2, 2}, {3, 3}}},
{{{1, 1}, {3, 3}, {3+F, 3}}},
{{{1, 1}, {1+F, 1}, {2, 2}}},
- {{{1, 1}, {2, 2}, {1, 1+K}}},
+ {{{1, 1}, {2, 2}, {1, 1+F}}},
{{{1, 1}, {1, 1+F}, {3, 3}}},
{{{1+H, 1}, {2, 2}, {4, 4}}}, // no coincident
{{{1, 1+K}, {3, 3}, {4, 4}}},
diff --git a/tests/PathOpsQuadParameterizationTest.cpp b/tests/PathOpsQuadParameterizationTest.cpp
new file mode 100644
index 0000000000..c7a2e8725e
--- /dev/null
+++ b/tests/PathOpsQuadParameterizationTest.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "SkDQuadImplicit.h"
+#include "SkPathOpsQuad.h"
+#include "Test.h"
+
+static bool point_on_parameterized_curve(const SkDQuad& quad, const SkDPoint& point) {
+ SkDQuadImplicit q(quad);
+ double xx = q.x2() * point.fX * point.fX;
+ double xy = q.xy() * point.fX * point.fY;
+ double yy = q.y2() * point.fY * point.fY;
+ double x = q.x() * point.fX;
+ double y = q.y() * point.fY;
+ double c = q.c();
+ double sum = xx + xy + yy + x + y + c;
+ return approximately_zero(sum);
+}
+
+static const SkDQuad quadratics[] = {
+ {{{0, 0}, {1, 0}, {1, 1}}},
+};
+
+static const int quadratics_count = (int) SK_ARRAY_COUNT(quadratics);
+
+DEF_TEST(PathOpsQuadImplicit, reporter) {
+ // split large quadratic
+ // compare original, parts, to see if the are coincident
+ for (int index = 0; index < quadratics_count; ++index) {
+ const SkDQuad& test = quadratics[index];
+ SkDQuadPair split = test.chopAt(0.5);
+ SkDQuad midThird = test.subDivide(1.0/3, 2.0/3);
+ const SkDQuad* quads[] = {
+ &test, &midThird, &split.first(), &split.second()
+ };
+ int quadsCount = (int) SK_ARRAY_COUNT(quads);
+ for (int one = 0; one < quadsCount; ++one) {
+ for (int two = 0; two < quadsCount; ++two) {
+ for (int inner = 0; inner < 3; inner += 2) {
+ REPORTER_ASSERT(reporter, point_on_parameterized_curve(*quads[one],
+ (*quads[two])[inner]));
+ }
+ REPORTER_ASSERT(reporter, SkDQuadImplicit::Match(*quads[one], *quads[two]));
+ }
+ }
+ }
+}
diff --git a/tests/PathOpsSimplifyFailTest.cpp b/tests/PathOpsSimplifyFailTest.cpp
index 53e33bca8f..2a4b0a0025 100644
--- a/tests/PathOpsSimplifyFailTest.cpp
+++ b/tests/PathOpsSimplifyFailTest.cpp
@@ -86,7 +86,10 @@ static void dontFailOne(skiatest::Reporter* reporter, int index) {
SkPath result;
result.setFillType(SkPath::kWinding_FillType);
bool success = Simplify(path, &result);
- REPORTER_ASSERT(reporter, success);
+ // linux 32 debug fails test 13 because the quad is not treated as linear
+ // there's no error in the math that I can find -- it looks like a processor
+ // or compiler bug -- so for now, allow either to work
+ REPORTER_ASSERT(reporter, success || index == 13);
REPORTER_ASSERT(reporter, result.getFillType() != SkPath::kWinding_FillType);
reporter->bumpTestCount();
}
diff --git a/tests/PathOpsSimplifyTest.cpp b/tests/PathOpsSimplifyTest.cpp
index 6a7b42510b..88547a0f04 100644
--- a/tests/PathOpsSimplifyTest.cpp
+++ b/tests/PathOpsSimplifyTest.cpp
@@ -3649,7 +3649,7 @@ static void testTriangles2(skiatest::Reporter* reporter, const char* filename) {
testSimplify(reporter, path, filename);
}
-// A test for this case:
+// A test this for this case:
// contourA has two segments that are coincident
// contourB has two segments that are coincident in the same place
// each ends up with +2/0 pairs for winding count
@@ -4506,6 +4506,8 @@ static void testQuads47(skiatest::Reporter* reporter, const char* filename) {
testSimplify(reporter, path, filename);
}
+// this fails because there is a short unorderable segment and the unordered state isn't handled
+// correctly later on.
static void testQuads46x(skiatest::Reporter* reporter, const char* filename) {
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
@@ -4677,9 +4679,7 @@ static void testRect3(skiatest::Reporter* reporter, const char* filename) {
testSimplify(reporter, path, filename);
}
-static void (*skipTest)(skiatest::Reporter* , const char* filename) = 0;
-static void (*firstTest)(skiatest::Reporter* , const char* filename) = testCubic2;
-static void (*stopTest)(skiatest::Reporter* , const char* filename) = 0;
+static void (*firstTest)(skiatest::Reporter* , const char* filename) = 0;
static TestDesc tests[] = {
TEST(testRect3),
@@ -4738,7 +4738,7 @@ static TestDesc tests[] = {
TEST(testQuadralateral3),
TEST(testDegenerate5),
TEST(testQuad12),
- TEST(testQuadratic51),
+ TEST(testQuadratic51), // has unorderable angles
TEST(testQuad8),
TEST(testQuad11),
TEST(testQuad10),
@@ -5111,13 +5111,14 @@ static void (*firstSubTest)(skiatest::Reporter* , const char* filename) = 0;
static bool runSubTests = false;
static bool runSubTestsFirst = false;
static bool runReverse = false;
+static void (*stopTest)(skiatest::Reporter* , const char* filename) = 0;
DEF_TEST(PathOpsSimplify, reporter) {
if (runSubTests && runSubTestsFirst) {
- RunTestSet(reporter, subTests, subTestCount, firstSubTest, NULL, stopTest, runReverse);
+ RunTestSet(reporter, subTests, subTestCount, firstSubTest, stopTest, runReverse);
}
- RunTestSet(reporter, tests, testCount, firstTest, skipTest, stopTest, runReverse);
+ RunTestSet(reporter, tests, testCount, firstTest, stopTest, runReverse);
if (runSubTests && !runSubTestsFirst) {
- RunTestSet(reporter, subTests, subTestCount, firstSubTest, NULL, stopTest, runReverse);
+ RunTestSet(reporter, subTests, subTestCount, firstSubTest, stopTest, runReverse);
}
}
diff --git a/tests/PathOpsSkpTest.cpp b/tests/PathOpsSkpTest.cpp
index 58a69ad1ea..6af790f72a 100755
--- a/tests/PathOpsSkpTest.cpp
+++ b/tests/PathOpsSkpTest.cpp
@@ -896,6 +896,19 @@ static void skpsd_graphic_net104(skiatest::Reporter* reporter, const char* filen
testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
+/* this cubic/quad pair
+ c = 430,280 430,278.895416 473.876068,278 528,278
+ q = 430,280 430.009796,277.101196 458.703552,275.050262
+ only intersect at the shared point (430,280)
+ they sort backwards because the tangent from pt[0] to control pt[1]
+ c' = (0.00000000000000000, -1.1045837402343750)
+ q' = (0.0097961425781250000, -2.8988037109375000)
+ suggests that the quad is counterclockwise of the cubic, when the reverse is true
+ the angle code is fooled because the control pt[1] of both the quad and cubic
+ is far away from cubic cntl [2] and quad pt [2].
+ Maybe in angle setup, this instability can be detected to suppress sorting on the initial tangent
+ Or the error term can be passed to NearRay that is magnified by the distance from the next ctrl?
+ */
static void skpnaoxrane_ru23(skiatest::Reporter* reporter, const char* filename) {
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
@@ -928,6 +941,11 @@ static void skpnaoxrane_ru23(skiatest::Reporter* reporter, const char* filename)
testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
+/* didn't investigate thoroughly, but looks to be missorting quad and cubic
+ {{468.507751,560.724426}, {467.275146,552.856262}, {465.84668,547.288391}}
+ {{463.779907,542.671143}, {464.829529,542.672974}, {466.946289,550.755676}, {468.507751,560.724426}}
+ decision maker is case 14 leftLessThanRight
+ */
static void skptcmevents_org23(skiatest::Reporter* reporter, const char* filename) {
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
@@ -1061,7 +1079,7 @@ static void skpmlk_com326(skiatest::Reporter* reporter, const char* filename) {
pathB.lineTo(149, 675);
pathB.cubicTo(149, 672.790833f, 151.238571f, 671, 154, 671);
pathB.close();
- testPathOpCheck(reporter, path, pathB, kIntersect_PathOp, filename, FLAGS_runFail);
+ testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
static void skpcyclist_friends_gr52(skiatest::Reporter* reporter, const char* filename) {
@@ -1087,12 +1105,10 @@ static void skpcyclist_friends_gr52(skiatest::Reporter* reporter, const char* fi
pathB.cubicTo(52.238575f, 207, 50, 204.761429f, 50, 202);
pathB.lineTo(50, 183);
pathB.close();
- // FIXME: this generates quads and cubics that are (correctly) not coincident unlike the old code
- // however, somewhere the angles are sorted incorrectly and the winding is computed to be -1/-2
- // but I can't find the error
testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
+/* cubic ends just above opp line */
static void skpwww_fj_p_com_22(skiatest::Reporter* reporter, const char* filename) {
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
@@ -1112,6 +1128,7 @@ static void skpwww_fj_p_com_22(skiatest::Reporter* reporter, const char* filenam
testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
+// pair of lines are not quite coincident, so sorting line/cubic fails (i think)
static void skpwww_lavoixdunord_fr_11(skiatest::Reporter* reporter, const char* filename) {
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
@@ -1144,6 +1161,9 @@ static void skpwww_lavoixdunord_fr_11(skiatest::Reporter* reporter, const char*
testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
+// pair of curves have nearly the same initial tangent but are sorting by
+// that alone sorts them incorrectly. Need to detect that tangents are nearly
+// identical and not reliable by themselves
static void skppptv_com_62(skiatest::Reporter* reporter, const char* filename) {
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
@@ -1170,6 +1190,7 @@ static void skppptv_com_62(skiatest::Reporter* reporter, const char* filename) {
testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
+// nearly identical to lavoixdunord -- to not-quite-coincident lines
static void skpwww_booking_com_68(skiatest::Reporter* reporter, const char* filename) {
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
@@ -1202,6 +1223,7 @@ static void skpwww_booking_com_68(skiatest::Reporter* reporter, const char* file
testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
+// visually looks like lavoixdunord and www_booking_com
static void skpwww_despegar_com_mx_272(skiatest::Reporter* reporter, const char* filename) {
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
@@ -1561,6 +1583,11 @@ static void skpskpicture15(skiatest::Reporter* reporter, const char* filename) {
testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
+/* Three edges are partially coincident. Only one of the three knows about the other two.
+ Subsequently, when the angle loop is created, it misses one of the edges.
+ After coincident edges are processed, probably need a check-and-correct that makes sure the
+ coincidences are all self-consistent.
+ */
static void skpelpais_com_18(skiatest::Reporter* reporter, const char* filename) {
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
@@ -1579,6 +1606,13 @@ static void skpelpais_com_18(skiatest::Reporter* reporter, const char* filename)
testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
+/* this generates a pair of lines that are essentially coincident; but the next line at a right
+ angle is not treated as if it intersects at the same point.
+ There are several of options:
+ move the intersection of the right angle line to the coincident point (should 'near' do this?
+ construct another coincident pair from the right angle line to the coincident point
+ treat the intersection as simple and not coincident
+ */
static void skpnamecheap_com_405(skiatest::Reporter* reporter, const char* filename) {
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
@@ -1597,6 +1631,7 @@ static void skpnamecheap_com_405(skiatest::Reporter* reporter, const char* filen
testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
+// fails on angle insert -- haven't investigated yet
static void skpwww_alrakoba_net_62(skiatest::Reporter* reporter, const char* filename) {
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
@@ -1622,6 +1657,7 @@ static void skpwww_alrakoba_net_62(skiatest::Reporter* reporter, const char* fil
testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
+/* asserts in alignSpanState looks like a coincident related bug */
static void skpwww_cityads_ru_249(skiatest::Reporter* reporter, const char* filename) {
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
@@ -1658,6 +1694,7 @@ static void skpwww_cityads_ru_249(skiatest::Reporter* reporter, const char* file
testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
+// fails on angle insert
static void skpwww_dealnews_com_315(skiatest::Reporter* reporter, const char* filename) {
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
@@ -1684,6 +1721,7 @@ static void skpwww_dealnews_com_315(skiatest::Reporter* reporter, const char* fi
testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
+// fails in intersections insert
static void skpwww_inmotionhosting_com_9(skiatest::Reporter* reporter, const char* filename) {
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
@@ -1728,6 +1766,7 @@ static void skpwww_alucinados_net_101(skiatest::Reporter* reporter, const char*
testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
+// /SkOpContour.cpp:278: failed assertion "!approximately_negative(oEndT - oStartT)
static void skpwww_hairjobsearch_com_31(skiatest::Reporter* reporter, const char* filename) {
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
@@ -1748,6 +1787,7 @@ static void skpwww_hairjobsearch_com_31(skiatest::Reporter* reporter, const char
testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
+// SkOpSegment::checkSmallCoincidence; line 1958 SkASSERT(span.fWindValue);
static void skpwww_heartiste_wordpress_com_86(skiatest::Reporter* reporter, const char* filename) {
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
@@ -1785,6 +1825,7 @@ static void skpwww_argus_presse_fr_41(skiatest::Reporter* reporter, const char*
testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
+// SkOpSegment::checkSmallCoincidence; line 1958 SkASSERT(span.fWindValue);
static void skpwww_320kbps_net_2231(skiatest::Reporter* reporter, const char* filename) {
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
@@ -1803,6 +1844,7 @@ static void skpwww_320kbps_net_2231(skiatest::Reporter* reporter, const char* fi
testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
+// debugValidateLoop loop sum fails
static void skpwww_exystence_net_61(skiatest::Reporter* reporter, const char* filename) {
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
@@ -1821,6 +1863,7 @@ static void skpwww_exystence_net_61(skiatest::Reporter* reporter, const char* fi
testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
+// debugValidateLoop loop sum fails
static void skpwww_trashness_com_36(skiatest::Reporter* reporter, const char* filename) {
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
@@ -1839,6 +1882,7 @@ static void skpwww_trashness_com_36(skiatest::Reporter* reporter, const char* fi
testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
+// SkIntersections::lineVertical fUsed >= fMax
static void skpwww_getgold_jp_731(skiatest::Reporter* reporter, const char* filename) {
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
@@ -1860,6 +1904,7 @@ static void skpwww_getgold_jp_731(skiatest::Reporter* reporter, const char* file
testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
+// SkOpContour::calcPartialCoincidentWinding SkASSERT(!approximately_negative(endT - startT));
static void skpwww_maturesupertube_com_21(skiatest::Reporter* reporter, const char* filename) {
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
@@ -1900,6 +1945,7 @@ static void skpwww_maturesupertube_com_21(skiatest::Reporter* reporter, const ch
testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
+// can't find winding of remaining vertical edges
static void skpwww_hubbyscook_com_22(skiatest::Reporter* reporter, const char* filename) {
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
@@ -1947,6 +1993,7 @@ static void skpwww_gruposejaumdivulgador_com_br_4(skiatest::Reporter* reporter,
testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
+// asserts in bridgeOp simple->isClosed()
static void skpwww_phototransferapp_com_24(skiatest::Reporter* reporter, const char* filename) {
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
@@ -2087,6 +2134,7 @@ static void skpwww_cooksnaps_com_32a(skiatest::Reporter* reporter, const char* f
testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
+// !simple->isClosed()
static void skpwww_contextualnewsfeeds_com_346(skiatest::Reporter* reporter, const char* filename) {
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
@@ -2110,6 +2158,7 @@ static void skpwww_contextualnewsfeeds_com_346(skiatest::Reporter* reporter, con
testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
+// line quad intersection SkIntersections::assert
static void skpwww_pindosiya_com_99(skiatest::Reporter* reporter, const char* filename) {
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
@@ -2131,6 +2180,7 @@ static void skpwww_pindosiya_com_99(skiatest::Reporter* reporter, const char* fi
testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
+// SkOpAngle::setSector SkASSERT(fSectorStart >= 0);
static void skpwww_karnivool_com_au_11(skiatest::Reporter* reporter, const char* filename) {
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
@@ -2253,6 +2303,7 @@ static void skpwww_artblart_com_8(skiatest::Reporter* reporter, const char* file
testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
+// joinCoincidence / findT / assert
static void skpwww_jessicaslens_wordpress_com_222(skiatest::Reporter* reporter, const char* filename) {
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
@@ -2281,6 +2332,7 @@ static void skpwww_jessicaslens_wordpress_com_222(skiatest::Reporter* reporter,
testPathOp(reporter, path, pathB, kDifference_PathOp, filename);
}
+// joinCoincidence / findT / assert
static void skpwww_simplysaru_com_40(skiatest::Reporter* reporter, const char* filename) {
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
@@ -2309,6 +2361,7 @@ static void skpwww_simplysaru_com_40(skiatest::Reporter* reporter, const char* f
testPathOp(reporter, path, pathB, kDifference_PathOp, filename);
}
+// cubic-cubic intersection reduce checkLinear assert
static void skpwww_partsdata_de_53(skiatest::Reporter* reporter, const char* filename) {
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
@@ -2607,6 +2660,7 @@ static void skpwww_partsdata_de_53(skiatest::Reporter* reporter, const char* fil
testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
+// SkOpAngle::setSector SkASSERT(fSectorStart >= 0);
static void skpwww_seopack_blogspot_com_2153(skiatest::Reporter* reporter, const char* filename) {
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
@@ -2630,6 +2684,7 @@ static void skpwww_seopack_blogspot_com_2153(skiatest::Reporter* reporter, const
testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
+// joinCoincidence / findT / assert
static void skpwww_lokado_de_173(skiatest::Reporter* reporter, const char* filename) {
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
@@ -2666,6 +2721,7 @@ static void skpwww_lokado_de_173(skiatest::Reporter* reporter, const char* filen
testPathOp(reporter, path, pathB, kDifference_PathOp, filename);
}
+// !simple->isClosed()
static void skpwww_wartepop_blogspot_com_br_6(skiatest::Reporter* reporter, const char* filename) {
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
@@ -2730,6 +2786,7 @@ static void skpwww_wartepop_blogspot_com_br_6a(skiatest::Reporter* reporter, con
testPathOp(reporter, path, pathB, kDifference_PathOp, filename);
}
+// !simple->isClosed()
static void skpwww_odia_com_br_26(skiatest::Reporter* reporter, const char* filename) {
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
@@ -2813,6 +2870,7 @@ static void skpwww_evolvehq_com_210(skiatest::Reporter* reporter, const char* fi
testPathOp(reporter, path, pathB, kDifference_PathOp, filename);
}
+// hangs
static void skpwww_catingueiraonline_com_352(skiatest::Reporter* reporter, const char* filename) {
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
@@ -2831,6 +2889,7 @@ static void skpwww_catingueiraonline_com_352(skiatest::Reporter* reporter, const
testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
+// hangs
static void skpwww_galaxystwo_com_4(skiatest::Reporter* reporter, const char* filename) {
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
@@ -3554,7 +3613,12 @@ static void skpwww_devbridge_com_22(skiatest::Reporter* reporter, const char* fi
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);
+ if (FLAGS_runFail) {
+ testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
+ } else {
+ // INVESTIGATE : why this normal test takes fail case (test has never worked)
+ testPathFailOp(reporter, path, pathB, kIntersect_PathOp, filename);
+ }
}
static void skpwww_alamdi_com_3(skiatest::Reporter* reporter, const char* filename) {
@@ -3643,6 +3707,7 @@ static void skpwww_firstunitedbank_com_19(skiatest::Reporter* reporter, const ch
testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
+// 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);
@@ -3662,6 +3727,7 @@ static void skpwww_shinydemos_com_5(skiatest::Reporter* reporter, const char* fi
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);
@@ -3715,7 +3781,11 @@ static void skpwww_shinydemos_com_15(skiatest::Reporter* reporter, const char* f
testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
}
+// SkOpSegment.cpp:4398: failed assertion "!span->fDone"
static void skpwww_lptemp_com_5(skiatest::Reporter* reporter, const char* filename) {
+ if (/* 0 && */ !FLAGS_runFail) { // has never worked MUST BE FIXED BEFORE NEXT CHECKIN
+ return;
+ }
SkPath path;
path.setFillType(SkPath::kEvenOdd_FillType);
path.moveTo(78.6429825f, 3150.97632f);
@@ -3744,36 +3814,12 @@ static void skpwww_lptemp_com_5(skiatest::Reporter* reporter, const char* filena
pathB.lineTo(77.6666718f, 3153.3335f);
pathB.cubicTo(77.6666718f, 3151.49268f, 79.15905f, 3150, 81, 3150);
pathB.close();
- testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
-}
-
-static void skpwww_educationalcraft_com_4a(skiatest::Reporter* reporter, const char* filename) {
- SkPath path;
- path.setFillType(SkPath::kEvenOdd_FillType);
- path.moveTo(941, 1494);
- path.lineTo(941, 1464);
- path.lineTo(985, 1464);
- path.lineTo(985, 1494);
- path.lineTo(941, 1494);
- path.close();
- SkPath pathB;
- pathB.setFillType(SkPath::kWinding_FillType);
-
-pathB.moveTo(984.546021f, 1478.31494f);
-pathB.cubicTo(984.546021f, 1478.31494f, 984.543213f, 1478.32239f, 984.537598f, 1478.33655f);
-pathB.cubicTo(984.419006f, 1478.63477f, 983.044373f, 1481.90405f, 980.026001f, 1481.276f);
-pathB.cubicTo(980.026001f, 1481.276f, 980.02594f, 1481.27576f, 980.025879f, 1481.27527f);
-pathB.cubicTo(980.018494f, 1481.22131f, 979.602478f, 1478.38831f, 984.546021f, 1478.31494f);
- testPathOp(reporter, path, pathB, kIntersect_PathOp, filename);
-
+ testPathOpCheck(reporter, path, pathB, kIntersect_PathOp, filename, FLAGS_runFail);
}
-static void (*skipTest)(skiatest::Reporter* , const char* filename) = 0;
static void (*firstTest)(skiatest::Reporter* , const char* filename) = 0;
-static void (*stopTest)(skiatest::Reporter* , const char* filename) = 0;
static struct TestDesc tests[] = {
- TEST(skpwww_educationalcraft_com_4a),
TEST(skpwww_lptemp_com_3),
TEST(skpwww_shinydemos_com_5),
TEST(skpwww_lptemp_com_5),
@@ -3893,10 +3939,11 @@ static struct TestDesc tests[] = {
static const size_t testCount = SK_ARRAY_COUNT(tests);
static bool runReverse = false;
+static void (*stopTest)(skiatest::Reporter* , const char* filename) = 0;
DEF_TEST(PathOpsSkp, reporter) {
#if DEBUG_SHOW_TEST_NAME
strncpy(DEBUG_FILENAME_STRING, "", DEBUG_FILENAME_STRING_LENGTH);
#endif
- RunTestSet(reporter, tests, testCount, firstTest, skipTest, stopTest, runReverse);
+ RunTestSet(reporter, tests, testCount, firstTest, stopTest, runReverse);
}
diff --git a/tests/PathOpsTSectDebug.h b/tests/PathOpsTSectDebug.h
index b4715e63e0..5f8915f681 100644
--- a/tests/PathOpsTSectDebug.h
+++ b/tests/PathOpsTSectDebug.h
@@ -8,158 +8,77 @@
#include "SkPathOpsTSect.h"
template<typename TCurve>
-const SkTSpan<TCurve>* SkTSect<TCurve>::debugSpan(int id) const {
- const SkTSpan<TCurve>* test = fHead;
- do {
- if (test->debugID() == id) {
- return test;
- }
- } while ((test = test->next()));
-#ifndef SK_RELEASE
- test = fOppSect->fHead;
- do {
- if (test->debugID() == id) {
- return test;
- }
- } while ((test = test->next()));
-#endif
- return NULL;
-}
-
-template<typename TCurve>
-const SkTSpan<TCurve>* SkTSect<TCurve>::debugT(double t) const {
- const SkTSpan<TCurve>* test = fHead;
- const SkTSpan<TCurve>* closest = NULL;
- double bestDist = DBL_MAX;
- do {
- if (between(test->fStartT, t, test->fEndT)) {
- return test;
- }
- double testDist = SkTMin(fabs(test->fStartT - t), fabs(test->fEndT - t));
- if (bestDist > testDist) {
- bestDist = testDist;
- closest = test;
- }
- } while ((test = test->next()));
- SkASSERT(closest);
- return closest;
-}
-
-template<typename TCurve>
void SkTSect<TCurve>::dump() const {
- dumpCommon(fHead);
-}
-
-extern int gDumpTSectNum;
-
-template<typename TCurve>
-void SkTSect<TCurve>::dumpBoth(SkTSect* opp) const {
-#if DEBUG_T_SECT_DUMP <= 2
-#if DEBUG_T_SECT_DUMP == 2
- SkDebugf("%d ", ++gDumpTSectNum);
-#endif
- this->dump();
- SkDebugf(" ");
- opp->dump();
- SkDebugf("\n");
-#elif DEBUG_T_SECT_DUMP == 3
- SkDebugf("<div id=\"sect%d\">\n", ++gDumpTSectNum);
- if (this->fHead) {
- this->dumpCurves();
- }
- if (opp->fHead) {
- PATH_OPS_DEBUG_CODE(opp->dumpCurves());
- }
- SkDebugf("</div>\n\n");
-#endif
-}
-
-template<typename TCurve>
-void SkTSect<TCurve>::dumpBounds(int id) const {
- const SkTSpan<TCurve>* bounded = debugSpan(id);
- if (!bounded) {
- SkDebugf("no span matches %d\n", id);
- return;
- }
- const SkTSpan<TCurve>* test = bounded->debugOpp()->fHead;
- do {
- if (test->findOppSpan(bounded)) {
- test->dump();
- }
- } while ((test = test->next()));
-}
-
-template<typename TCurve>
-void SkTSect<TCurve>::dumpCoin() const {
- dumpCommon(fCoincident);
-}
-
-template<typename TCurve>
-void SkTSect<TCurve>::dumpCoinCurves() const {
- dumpCommonCurves(fCoincident);
-}
-
-template<typename TCurve>
-void SkTSect<TCurve>::dumpCommon(const SkTSpan<TCurve>* test) const {
SkDebugf("id=%d", debugID());
+ const SkTSpan<TCurve>* test = fHead;
if (!test) {
SkDebugf(" (empty)");
return;
}
do {
SkDebugf(" ");
- test->dump();
+ test->dump(this);
} while ((test = test->next()));
}
template<typename TCurve>
-void SkTSect<TCurve>::dumpCommonCurves(const SkTSpan<TCurve>* test) const {
- do {
- test->fPart.dumpID(test->debugID());
- } while ((test = test->next()));
+void SkTSect<TCurve>::dumpBoth(const SkTSect& opp) const {
+ dump();
+ SkDebugf(" ");
+ opp.dump();
+ SkDebugf("\n");
+}
+
+template<typename TCurve>
+void SkTSect<TCurve>::dumpBoth(const SkTSect* opp) const {
+ dumpBoth(*opp);
}
template<typename TCurve>
void SkTSect<TCurve>::dumpCurves() const {
- dumpCommonCurves(fHead);
+ const SkTSpan<TCurve>* test = fHead;
+ do {
+ test->fPart.dump();
+ } while ((test = test->next()));
}
+#if !DEBUG_T_SECT
template<typename TCurve>
-const SkTSpan<TCurve>* SkTSpan<TCurve>::debugSpan(int id) const {
- return PATH_OPS_DEBUG_RELEASE(fDebugSect->debugSpan(id), NULL);
+int SkTSpan<TCurve>::debugID(const SkTSect<TCurve>* sect) const {
+ if (!sect) {
+ return -1;
+ }
+ int id = 1;
+ const SkTSpan* test = sect->fHead;
+ while (test && test != this) {
+ ++id;
+ test = test->fNext;
+ }
+ return id;
}
+#endif
template<typename TCurve>
-const SkTSpan<TCurve>* SkTSpan<TCurve>::debugT(double t) const {
- return PATH_OPS_DEBUG_RELEASE(fDebugSect->debugT(t), NULL);
+void SkTSpan<TCurve>::dumpID(const SkTSect<TCurve>* sect) const {
+ if (fCoinStart.isCoincident()) {
+ SkDebugf("%c", '*');
+ }
+ SkDebugf("%d", debugID(sect));
+ if (fCoinEnd.isCoincident()) {
+ SkDebugf("%c", '*');
+ }
}
template<typename TCurve>
-void SkTSpan<TCurve>::dump() const {
- dumpID();
+void SkTSpan<TCurve>::dump(const SkTSect<TCurve>* sect) const {
+ dumpID(sect);
SkDebugf("=(%g,%g) [", fStartT, fEndT);
for (int index = 0; index < fBounded.count(); ++index) {
SkTSpan* span = fBounded[index];
- span->dumpID();
+ span->dumpID(sect);
if (index < fBounded.count() - 1) {
SkDebugf(",");
}
}
SkDebugf("]");
}
-
-template<typename TCurve>
-void SkTSpan<TCurve>::dumpBounds(int id) const {
- PATH_OPS_DEBUG_CODE(fDebugSect->dumpBounds(id));
-}
-
-template<typename TCurve>
-void SkTSpan<TCurve>::dumpID() const {
- if (fCoinStart.isCoincident()) {
- SkDebugf("%c", '*');
- }
- SkDebugf("%d", debugID());
- if (fCoinEnd.isCoincident()) {
- SkDebugf("%c", '*');
- }
-}
diff --git a/tests/PathOpsTestCommon.cpp b/tests/PathOpsTestCommon.cpp
index f1cba8ed8b..60a12ee56e 100644
--- a/tests/PathOpsTestCommon.cpp
+++ b/tests/PathOpsTestCommon.cpp
@@ -9,129 +9,11 @@
#include "SkPathOpsCubic.h"
#include "SkPathOpsLine.h"
#include "SkPathOpsQuad.h"
-#include "SkReduceOrder.h"
-#include "SkTSort.h"
-
-static double calc_t_div(const SkDCubic& cubic, double precision, double start) {
- const double adjust = sqrt(3.) / 36;
- SkDCubic sub;
- const SkDCubic* cPtr;
- if (start == 0) {
- cPtr = &cubic;
- } else {
- // OPTIMIZE: special-case half-split ?
- sub = cubic.subDivide(start, 1);
- cPtr = &sub;
- }
- const SkDCubic& c = *cPtr;
- double dx = c[3].fX - 3 * (c[2].fX - c[1].fX) - c[0].fX;
- double dy = c[3].fY - 3 * (c[2].fY - c[1].fY) - c[0].fY;
- double dist = sqrt(dx * dx + dy * dy);
- double tDiv3 = precision / (adjust * dist);
- double t = SkDCubeRoot(tDiv3);
- if (start > 0) {
- t = start + (1 - start) * t;
- }
- return t;
-}
-
-static bool add_simple_ts(const SkDCubic& cubic, double precision, SkTArray<double, true>* ts) {
- double tDiv = calc_t_div(cubic, precision, 0);
- if (tDiv >= 1) {
- return true;
- }
- if (tDiv >= 0.5) {
- ts->push_back(0.5);
- return true;
- }
- return false;
-}
-
-static void addTs(const SkDCubic& cubic, double precision, double start, double end,
- SkTArray<double, true>* ts) {
- double tDiv = calc_t_div(cubic, precision, 0);
- double parts = ceil(1.0 / tDiv);
- for (double index = 0; index < parts; ++index) {
- double newT = start + (index / parts) * (end - start);
- if (newT > 0 && newT < 1) {
- ts->push_back(newT);
- }
- }
-}
-
-static void toQuadraticTs(const SkDCubic* cubic, double precision, SkTArray<double, true>* ts) {
- SkReduceOrder reducer;
- int order = reducer.reduce(*cubic, SkReduceOrder::kAllow_Quadratics);
- if (order < 3) {
- return;
- }
- double inflectT[5];
- int inflections = cubic->findInflections(inflectT);
- SkASSERT(inflections <= 2);
- if (!cubic->endsAreExtremaInXOrY()) {
- inflections += cubic->findMaxCurvature(&inflectT[inflections]);
- SkASSERT(inflections <= 5);
- }
- SkTQSort<double>(inflectT, &inflectT[inflections - 1]);
- // OPTIMIZATION: is this filtering common enough that it needs to be pulled out into its
- // own subroutine?
- while (inflections && approximately_less_than_zero(inflectT[0])) {
- memmove(inflectT, &inflectT[1], sizeof(inflectT[0]) * --inflections);
- }
- int start = 0;
- int next = 1;
- while (next < inflections) {
- if (!approximately_equal(inflectT[start], inflectT[next])) {
- ++start;
- ++next;
- continue;
- }
- memmove(&inflectT[start], &inflectT[next], sizeof(inflectT[0]) * (--inflections - start));
- }
-
- while (inflections && approximately_greater_than_one(inflectT[inflections - 1])) {
- --inflections;
- }
- SkDCubicPair pair;
- if (inflections == 1) {
- pair = cubic->chopAt(inflectT[0]);
- int orderP1 = reducer.reduce(pair.first(), SkReduceOrder::kNo_Quadratics);
- if (orderP1 < 2) {
- --inflections;
- } else {
- int orderP2 = reducer.reduce(pair.second(), SkReduceOrder::kNo_Quadratics);
- if (orderP2 < 2) {
- --inflections;
- }
- }
- }
- if (inflections == 0 && add_simple_ts(*cubic, precision, ts)) {
- return;
- }
- if (inflections == 1) {
- pair = cubic->chopAt(inflectT[0]);
- addTs(pair.first(), precision, 0, inflectT[0], ts);
- addTs(pair.second(), precision, inflectT[0], 1, ts);
- return;
- }
- if (inflections > 1) {
- SkDCubic part = cubic->subDivide(0, inflectT[0]);
- addTs(part, precision, 0, inflectT[0], ts);
- int last = inflections - 1;
- for (int idx = 0; idx < last; ++idx) {
- part = cubic->subDivide(inflectT[idx], inflectT[idx + 1]);
- addTs(part, precision, inflectT[idx], inflectT[idx + 1], ts);
- }
- part = cubic->subDivide(inflectT[last], 1);
- addTs(part, precision, inflectT[last], 1, ts);
- return;
- }
- addTs(*cubic, precision, 0, 1, ts);
-}
+#include "SkPathOpsTriangle.h"
void CubicToQuads(const SkDCubic& cubic, double precision, SkTArray<SkDQuad, true>& quads) {
SkTArray<double, true> ts;
- toQuadraticTs(&cubic, precision, &ts);
+ cubic.toQuadraticTs(precision, &ts);
if (ts.count() <= 0) {
SkDQuad quad = cubic.toQuad();
quads.push_back(quad);
@@ -298,6 +180,15 @@ bool ValidQuad(const SkDQuad& quad) {
return true;
}
+bool ValidTriangle(const SkDTriangle& triangle) {
+ for (int index = 0; index < 3; ++index) {
+ if (!ValidPoint(triangle.fPts[index])) {
+ return false;
+ }
+ }
+ return true;
+}
+
bool ValidVector(const SkDVector& v) {
if (SkDoubleIsNaN(v.fX)) {
return false;
diff --git a/tests/PathOpsTestCommon.h b/tests/PathOpsTestCommon.h
index 7a72ff29a5..0c42bfbb05 100644
--- a/tests/PathOpsTestCommon.h
+++ b/tests/PathOpsTestCommon.h
@@ -21,6 +21,7 @@ bool ValidLine(const SkDLine& line);
bool ValidPoint(const SkDPoint& pt);
bool ValidPoints(const SkPoint* pts, int count);
bool ValidQuad(const SkDQuad& quad);
+bool ValidTriangle(const SkDTriangle& triangle);
bool ValidVector(const SkDVector& v);
#endif
diff --git a/tests/PathOpsThreeWayTest.cpp b/tests/PathOpsThreeWayTest.cpp
index bf634f9f7e..15d6e54927 100644
--- a/tests/PathOpsThreeWayTest.cpp
+++ b/tests/PathOpsThreeWayTest.cpp
@@ -49,16 +49,14 @@ static void testSetTest(skiatest::Reporter* reporter, int index) {
const Curve& iTest = testSet.tests[inner];
SkIntersections* i = combos.append();
sk_bzero(i, sizeof(SkIntersections));
- SkDLine oLine = {{ oTest.curve[0], oTest.curve[1] }};
- SkDLine iLine = {{ iTest.curve[0], iTest.curve[1] }};
if (oTest.ptCount == 1 && iTest.ptCount == 1) {
- i->intersect(oLine, iLine);
+ i->intersect(*(const SkDLine*) &oTest.curve, *(const SkDLine*) &iTest.curve);
} else if (oTest.ptCount == 1 && iTest.ptCount == 4) {
- i->intersect(iTest.curve, oLine);
+ i->intersect(iTest.curve, *(const SkDLine*) &oTest.curve);
} else if (oTest.ptCount == 4 && iTest.ptCount == 1) {
- i->intersect(oTest.curve, iLine);
+ i->intersect(oTest.curve, *(const SkDLine*) &oTest.curve);
} else if (oTest.ptCount == 4 && iTest.ptCount == 4) {
- i->intersect(oTest.curve, iTest.curve);
+ i->intersectB(oTest.curve, iTest.curve);
} else {
SkASSERT(0);
}
diff --git a/tests/PathOpsTightBoundsTest.cpp b/tests/PathOpsTightBoundsTest.cpp
index d50c26a547..cea37520b1 100644
--- a/tests/PathOpsTightBoundsTest.cpp
+++ b/tests/PathOpsTightBoundsTest.cpp
@@ -8,6 +8,7 @@
#include "PathOpsThreadedCommon.h"
#include "SkCanvas.h"
#include "SkRandom.h"
+#include "SkTArray.h"
#include "SkTSort.h"
#include "Test.h"