aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar caryclark <caryclark@google.com>2015-08-18 07:12:43 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-08-18 07:12:44 -0700
commit94c902e63d77641cadd76155c2b248d04f63b560 (patch)
treebe27444690e07e19d1faadeaa2ea4017fafe3f49 /src
parentf82c13fced695e0f1c0bb1760374ab1d77cd4026 (diff)
fix pathops fuzz failures
If a curve has the identical start and control points, the initial or final tangent can't be trivally determined. The perpendicular to the tangent is used to measure coincidence. Add logic for cubics, quadratics, and conics, to use the secondary control points or the end points if the initial control point alone can't determine the tangent. Add debugging (currently untriggered by exhaustive testing) to detect zero-length tangents which are not at the curve endpoints. Increase the number of temporary intersecions gathered from 10 to 12 but reduce the max passed in by cubic intersection from 27 to 12. Also, add checks if the max passed exceeds the storage allocated. When cleaning up parallel lines, choose the intersection which is on the end of both segments over the intersection which is on the end of a single segment. TBR=reed@google.com BUG=425140,516266 Review URL: https://codereview.chromium.org/1288863004
Diffstat (limited to 'src')
-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
7 files changed, 42 insertions, 6 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);