aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/pathops/SkDLineIntersection.cpp11
-rw-r--r--src/pathops/SkIntersections.cpp1
-rw-r--r--src/pathops/SkIntersections.h5
-rw-r--r--src/pathops/SkPathOpsConic.cpp8
-rw-r--r--src/pathops/SkPathOpsCubic.cpp13
-rw-r--r--src/pathops/SkPathOpsQuad.cpp8
-rw-r--r--src/pathops/SkPathOpsTSect.h2
-rw-r--r--tests/PathOpsCubicIntersectionTest.cpp5
-rw-r--r--tests/PathOpsOpTest.cpp14
9 files changed, 60 insertions, 7 deletions
diff --git a/src/pathops/SkDLineIntersection.cpp b/src/pathops/SkDLineIntersection.cpp
index 5fd8e7fdb7..bfbbc7e07e 100644
--- a/src/pathops/SkDLineIntersection.cpp
+++ b/src/pathops/SkDLineIntersection.cpp
@@ -12,11 +12,16 @@ void SkIntersections::cleanUpParallelLines(bool parallel) {
removeOne(1);
}
if (fUsed == 2 && !parallel) {
- bool startMatch = fT[0][0] == 0 || fT[1][0] == 0 || fT[1][0] == 1;
- bool endMatch = fT[0][1] == 1 || fT[1][1] == 0 || fT[1][1] == 1;
+ bool startMatch = fT[0][0] == 0 || zero_or_one(fT[1][0]);
+ bool endMatch = fT[0][1] == 1 || zero_or_one(fT[1][1]);
if ((!startMatch && !endMatch) || approximately_equal(fT[0][0], fT[0][1])) {
SkASSERT(startMatch || endMatch);
- removeOne(endMatch);
+ if (startMatch && endMatch && (fT[0][0] != 0 || !zero_or_one(fT[1][0]))
+ && fT[0][1] == 1 && zero_or_one(fT[1][1])) {
+ removeOne(0);
+ } else {
+ removeOne(endMatch);
+ }
}
}
if (fUsed == 2) {
diff --git a/src/pathops/SkIntersections.cpp b/src/pathops/SkIntersections.cpp
index 7caf04bf4d..9683796a5b 100644
--- a/src/pathops/SkIntersections.cpp
+++ b/src/pathops/SkIntersections.cpp
@@ -87,6 +87,7 @@ int SkIntersections::insert(double one, double two, const SkDPoint& pt) {
fT[0][index] = one;
fT[1][index] = two;
++fUsed;
+ SkASSERT(fUsed <= SK_ARRAY_COUNT(fPt));
return index;
}
diff --git a/src/pathops/SkIntersections.h b/src/pathops/SkIntersections.h
index c12db38b6c..ac9276beec 100644
--- a/src/pathops/SkIntersections.h
+++ b/src/pathops/SkIntersections.h
@@ -188,6 +188,7 @@ public:
}
void setMax(int max) {
+ SkASSERT(max <= (int) SK_ARRAY_COUNT(fPt));
fMax = max;
}
@@ -286,9 +287,9 @@ private:
void cleanUpParallelLines(bool parallel);
void computePoints(const SkDLine& line, int used);
- SkDPoint fPt[10]; // FIXME: since scans store points as SkPoint, this should also
+ SkDPoint fPt[12]; // FIXME: since scans store points as SkPoint, this should also
SkDPoint fPt2[2]; // used by nearly same to store alternate intersection point
- double fT[2][10];
+ double fT[2][12];
uint16_t fIsCoincident[2]; // bit set for each curve's coincident T
bool fNearlySame[2]; // true if end points nearly match
unsigned char fUsed;
diff --git a/src/pathops/SkPathOpsConic.cpp b/src/pathops/SkPathOpsConic.cpp
index 82353d67b5..013136bd82 100644
--- a/src/pathops/SkPathOpsConic.cpp
+++ b/src/pathops/SkPathOpsConic.cpp
@@ -48,6 +48,14 @@ SkDVector SkDConic::dxdyAtT(double t) const {
conic_eval_tan(&fPts[0].fX, fWeight, t),
conic_eval_tan(&fPts[0].fY, fWeight, t)
};
+ if (result.fX == 0 && result.fY == 0) {
+ if (zero_or_one(t)) {
+ result = fPts[2] - fPts[0];
+ } else {
+ // incomplete
+ SkDebugf("!k");
+ }
+ }
return result;
}
diff --git a/src/pathops/SkPathOpsCubic.cpp b/src/pathops/SkPathOpsCubic.cpp
index 972c510643..f82bc3530c 100644
--- a/src/pathops/SkPathOpsCubic.cpp
+++ b/src/pathops/SkPathOpsCubic.cpp
@@ -474,6 +474,19 @@ static double derivative_at_t(const double* src, double t) {
// OPTIMIZE? compute t^2, t(1-t), and (1-t)^2 and pass them to another version of derivative at t?
SkDVector SkDCubic::dxdyAtT(double t) const {
SkDVector result = { derivative_at_t(&fPts[0].fX, t), derivative_at_t(&fPts[0].fY, t) };
+ if (result.fX == 0 && result.fY == 0) {
+ if (t == 0) {
+ result = fPts[2] - fPts[0];
+ } else if (t == 1) {
+ result = fPts[3] - fPts[1];
+ } else {
+ // incomplete
+ SkDebugf("!c");
+ }
+ if (result.fX == 0 && result.fY == 0 && zero_or_one(t)) {
+ result = fPts[3] - fPts[0];
+ }
+ }
return result;
}
diff --git a/src/pathops/SkPathOpsQuad.cpp b/src/pathops/SkPathOpsQuad.cpp
index 717d8bc03d..12b9658ce7 100644
--- a/src/pathops/SkPathOpsQuad.cpp
+++ b/src/pathops/SkPathOpsQuad.cpp
@@ -161,6 +161,14 @@ SkDVector SkDQuad::dxdyAtT(double t) const {
double c = t;
SkDVector result = { a * fPts[0].fX + b * fPts[1].fX + c * fPts[2].fX,
a * fPts[0].fY + b * fPts[1].fY + c * fPts[2].fY };
+ if (result.fX == 0 && result.fY == 0) {
+ if (zero_or_one(t)) {
+ result = fPts[2] - fPts[0];
+ } else {
+ // incomplete
+ SkDebugf("!q");
+ }
+ }
return result;
}
diff --git a/src/pathops/SkPathOpsTSect.h b/src/pathops/SkPathOpsTSect.h
index 4cf5978d95..50e12791f7 100644
--- a/src/pathops/SkPathOpsTSect.h
+++ b/src/pathops/SkPathOpsTSect.h
@@ -1907,7 +1907,7 @@ void SkTSect<TCurve, OppCurve>::BinarySearch(SkTSect<TCurve, OppCurve>* sect1,
SkDEBUGCODE(sect1->fOppSect = sect2);
SkDEBUGCODE(sect2->fOppSect = sect1);
intersections->reset();
- intersections->setMax(TCurve::kMaxIntersections * 3); // give extra for slop
+ intersections->setMax(TCurve::kMaxIntersections + 3); // give extra for slop
SkTSpan<TCurve, OppCurve>* span1 = sect1->fHead;
SkTSpan<OppCurve, TCurve>* span2 = sect2->fHead;
int oppSect, sect = sect1->intersects(span1, sect2, span2, &oppSect);
diff --git a/tests/PathOpsCubicIntersectionTest.cpp b/tests/PathOpsCubicIntersectionTest.cpp
index 138e6f484f..75a5cc3ef4 100644
--- a/tests/PathOpsCubicIntersectionTest.cpp
+++ b/tests/PathOpsCubicIntersectionTest.cpp
@@ -653,6 +653,11 @@ static void cubicIntersectionSelfTest(skiatest::Reporter* reporter) {
}
static const SkDCubic coinSet[] = {
+ {{{297.04998779296875, 43.928997039794922}, {297.04998779296875, 43.928997039794922},
+ {300.69699096679688, 45.391998291015625}, {306.92498779296875, 43.08599853515625}}},
+ {{{297.04998779296875, 43.928997039794922}, {297.04998779296875, 43.928997039794922},
+ {300.69699096679688, 45.391998291015625}, {306.92498779296875, 43.08599853515625}}},
+
{{{2, 3}, {0, 4}, {3, 2}, {5, 3}}},
{{{2, 3}, {0, 4}, {3, 2}, {5, 3}}},
diff --git a/tests/PathOpsOpTest.cpp b/tests/PathOpsOpTest.cpp
index 637bd042d2..fbe0116eb5 100644
--- a/tests/PathOpsOpTest.cpp
+++ b/tests/PathOpsOpTest.cpp
@@ -5153,13 +5153,25 @@ static void cubics45u(skiatest::Reporter* reporter, const char* filename) {
testPathOp(reporter, path, pathB, kUnion_SkPathOp, filename);
}
+static void fuzz38(skiatest::Reporter* reporter, const char* filename) {
+ SkPath path, pathB;
+ path.moveTo(100.34f, 303.312f);
+ path.lineTo(-1e+08, 303.312f);
+ path.lineTo(102, 310.156f);
+ path.lineTo(100.34f, 310.156f);
+ path.lineTo(100.34f, 303.312f);
+ path.close();
+ testPathOpCheck(reporter, path, pathB, kUnion_SkPathOp, filename, FLAGS_runFail);
+}
+
static void (*skipTest)(skiatest::Reporter* , const char* filename) = 0;
-static void (*firstTest)(skiatest::Reporter* , const char* filename) = loops63i;
+static void (*firstTest)(skiatest::Reporter* , const char* filename) = 0;
static void (*stopTest)(skiatest::Reporter* , const char* filename) = 0;
#define TEST(name) { name, #name }
static struct TestDesc tests[] = {
+ TEST(fuzz38),
TEST(cubics44d),
TEST(cubics45u),
TEST(loops61i),