Index: src/pathops/SkDQuadLineIntersection.cpp |
diff --git a/src/pathops/SkDQuadLineIntersection.cpp b/src/pathops/SkDQuadLineIntersection.cpp |
index 9df2dc248ab01e37b123f7b9da2dd4d408d89b12..58b3060ab3db63b372dde8419d9f03ddd5f51312 100644 |
--- a/src/pathops/SkDQuadLineIntersection.cpp |
+++ b/src/pathops/SkDQuadLineIntersection.cpp |
@@ -89,10 +89,15 @@ Thus, if the slope of the line tends towards vertical, we use: |
class LineQuadraticIntersections { |
public: |
+ enum PinTPoint { |
+ kPointUninitialized, |
+ kPointInitialized |
+ }; |
+ |
LineQuadraticIntersections(const SkDQuad& q, const SkDLine& l, SkIntersections* i) |
- : quad(q) |
- , line(l) |
- , intersections(i) |
+ : fQuad(q) |
+ , fLine(l) |
+ , fIntersections(i) |
, fAllowNear(true) { |
} |
@@ -116,11 +121,11 @@ public: |
for each of the three points (e.g. n = 0 to 2) |
quad[n].fY' = (quad[n].fY - line[0].fY) * A - (quad[n].fX - line[0].fX) * O |
*/ |
- double adj = line[1].fX - line[0].fX; |
- double opp = line[1].fY - line[0].fY; |
+ double adj = fLine[1].fX - fLine[0].fX; |
+ double opp = fLine[1].fY - fLine[0].fY; |
double r[3]; |
for (int n = 0; n < 3; ++n) { |
- r[n] = (quad[n].fY - line[0].fY) * adj - (quad[n].fX - line[0].fX) * opp; |
+ r[n] = (fQuad[n].fY - fLine[0].fY) * adj - (fQuad[n].fX - fLine[0].fX) * opp; |
} |
double A = r[2]; |
double B = r[1]; |
@@ -137,21 +142,21 @@ public: |
for (int index = 0; index < roots; ++index) { |
double quadT = rootVals[index]; |
double lineT = findLineT(quadT); |
- if (PinTs(&quadT, &lineT)) { |
- SkDPoint pt = line.xyAtT(lineT); |
- intersections->insert(quadT, lineT, pt); |
+ SkDPoint pt; |
+ if (pinTs(&quadT, &lineT, &pt, kPointUninitialized)) { |
+ fIntersections->insert(quadT, lineT, pt); |
} |
} |
if (fAllowNear) { |
addNearEndPoints(); |
} |
- return intersections->used(); |
+ return fIntersections->used(); |
} |
int horizontalIntersect(double axisIntercept, double roots[2]) { |
- double D = quad[2].fY; // f |
- double E = quad[1].fY; // e |
- double F = quad[0].fY; // d |
+ double D = fQuad[2].fY; // f |
+ double E = fQuad[1].fY; // e |
+ double F = fQuad[0].fY; // d |
D += F - 2 * E; // D = d - 2*e + f |
E -= F; // E = -(d - e) |
F -= axisIntercept; |
@@ -164,25 +169,25 @@ public: |
int roots = horizontalIntersect(axisIntercept, rootVals); |
for (int index = 0; index < roots; ++index) { |
double quadT = rootVals[index]; |
- SkDPoint pt = quad.xyAtT(quadT); |
+ SkDPoint pt = fQuad.ptAtT(quadT); |
double lineT = (pt.fX - left) / (right - left); |
- if (PinTs(&quadT, &lineT)) { |
- intersections->insert(quadT, lineT, pt); |
+ if (pinTs(&quadT, &lineT, &pt, kPointInitialized)) { |
+ fIntersections->insert(quadT, lineT, pt); |
} |
} |
if (fAllowNear) { |
addNearHorizontalEndPoints(left, right, axisIntercept); |
} |
if (flipped) { |
- intersections->flip(); |
+ fIntersections->flip(); |
} |
- return intersections->used(); |
+ return fIntersections->used(); |
} |
int verticalIntersect(double axisIntercept, double roots[2]) { |
- double D = quad[2].fX; // f |
- double E = quad[1].fX; // e |
- double F = quad[0].fX; // d |
+ double D = fQuad[2].fX; // f |
+ double E = fQuad[1].fX; // e |
+ double F = fQuad[0].fX; // d |
D += F - 2 * E; // D = d - 2*e + f |
E -= F; // E = -(d - e) |
F -= axisIntercept; |
@@ -195,107 +200,107 @@ public: |
int roots = verticalIntersect(axisIntercept, rootVals); |
for (int index = 0; index < roots; ++index) { |
double quadT = rootVals[index]; |
- SkDPoint pt = quad.xyAtT(quadT); |
+ SkDPoint pt = fQuad.ptAtT(quadT); |
double lineT = (pt.fY - top) / (bottom - top); |
- if (PinTs(&quadT, &lineT)) { |
- intersections->insert(quadT, lineT, pt); |
+ if (pinTs(&quadT, &lineT, &pt, kPointInitialized)) { |
+ fIntersections->insert(quadT, lineT, pt); |
} |
} |
if (fAllowNear) { |
addNearVerticalEndPoints(top, bottom, axisIntercept); |
} |
if (flipped) { |
- intersections->flip(); |
+ fIntersections->flip(); |
} |
- return intersections->used(); |
+ return fIntersections->used(); |
} |
protected: |
// add endpoints first to get zero and one t values exactly |
void addExactEndPoints() { |
for (int qIndex = 0; qIndex < 3; qIndex += 2) { |
- double lineT = line.exactPoint(quad[qIndex]); |
+ double lineT = fLine.exactPoint(fQuad[qIndex]); |
if (lineT < 0) { |
continue; |
} |
double quadT = (double) (qIndex >> 1); |
- intersections->insert(quadT, lineT, quad[qIndex]); |
+ fIntersections->insert(quadT, lineT, fQuad[qIndex]); |
} |
} |
void addNearEndPoints() { |
for (int qIndex = 0; qIndex < 3; qIndex += 2) { |
double quadT = (double) (qIndex >> 1); |
- if (intersections->hasT(quadT)) { |
+ if (fIntersections->hasT(quadT)) { |
continue; |
} |
- double lineT = line.nearPoint(quad[qIndex]); |
+ double lineT = fLine.nearPoint(fQuad[qIndex]); |
if (lineT < 0) { |
continue; |
} |
- intersections->insert(quadT, lineT, quad[qIndex]); |
+ fIntersections->insert(quadT, lineT, fQuad[qIndex]); |
} |
// FIXME: see if line end is nearly on quad |
} |
void addExactHorizontalEndPoints(double left, double right, double y) { |
for (int qIndex = 0; qIndex < 3; qIndex += 2) { |
- double lineT = SkDLine::ExactPointH(quad[qIndex], left, right, y); |
+ double lineT = SkDLine::ExactPointH(fQuad[qIndex], left, right, y); |
if (lineT < 0) { |
continue; |
} |
double quadT = (double) (qIndex >> 1); |
- intersections->insert(quadT, lineT, quad[qIndex]); |
+ fIntersections->insert(quadT, lineT, fQuad[qIndex]); |
} |
} |
void addNearHorizontalEndPoints(double left, double right, double y) { |
for (int qIndex = 0; qIndex < 3; qIndex += 2) { |
double quadT = (double) (qIndex >> 1); |
- if (intersections->hasT(quadT)) { |
+ if (fIntersections->hasT(quadT)) { |
continue; |
} |
- double lineT = SkDLine::NearPointH(quad[qIndex], left, right, y); |
+ double lineT = SkDLine::NearPointH(fQuad[qIndex], left, right, y); |
if (lineT < 0) { |
continue; |
} |
- intersections->insert(quadT, lineT, quad[qIndex]); |
+ fIntersections->insert(quadT, lineT, fQuad[qIndex]); |
} |
// FIXME: see if line end is nearly on quad |
} |
void addExactVerticalEndPoints(double top, double bottom, double x) { |
for (int qIndex = 0; qIndex < 3; qIndex += 2) { |
- double lineT = SkDLine::ExactPointV(quad[qIndex], top, bottom, x); |
+ double lineT = SkDLine::ExactPointV(fQuad[qIndex], top, bottom, x); |
if (lineT < 0) { |
continue; |
} |
double quadT = (double) (qIndex >> 1); |
- intersections->insert(quadT, lineT, quad[qIndex]); |
+ fIntersections->insert(quadT, lineT, fQuad[qIndex]); |
} |
} |
void addNearVerticalEndPoints(double top, double bottom, double x) { |
for (int qIndex = 0; qIndex < 3; qIndex += 2) { |
double quadT = (double) (qIndex >> 1); |
- if (intersections->hasT(quadT)) { |
+ if (fIntersections->hasT(quadT)) { |
continue; |
} |
- double lineT = SkDLine::NearPointV(quad[qIndex], top, bottom, x); |
+ double lineT = SkDLine::NearPointV(fQuad[qIndex], top, bottom, x); |
if (lineT < 0) { |
continue; |
} |
- intersections->insert(quadT, lineT, quad[qIndex]); |
+ fIntersections->insert(quadT, lineT, fQuad[qIndex]); |
} |
// FIXME: see if line end is nearly on quad |
} |
double findLineT(double t) { |
- SkDPoint xy = quad.xyAtT(t); |
- double dx = line[1].fX - line[0].fX; |
- double dy = line[1].fY - line[0].fY; |
- double dxT = (xy.fX - line[0].fX) / dx; |
- double dyT = (xy.fY - line[0].fY) / dy; |
+ SkDPoint xy = fQuad.ptAtT(t); |
+ double dx = fLine[1].fX - fLine[0].fX; |
+ double dy = fLine[1].fY - fLine[0].fY; |
+ double dxT = (xy.fX - fLine[0].fX) / dx; |
+ double dyT = (xy.fY - fLine[0].fY) / dy; |
if (!between(FLT_EPSILON, dxT, 1 - FLT_EPSILON) && between(0, dyT, 1)) { |
return dyT; |
} |
@@ -305,22 +310,27 @@ protected: |
return fabs(dx) > fabs(dy) ? dxT : dyT; |
} |
- static bool PinTs(double* quadT, double* lineT) { |
+ bool pinTs(double* quadT, double* lineT, SkDPoint* pt, PinTPoint ptSet) { |
if (!approximately_one_or_less(*lineT)) { |
return false; |
} |
if (!approximately_zero_or_more(*lineT)) { |
return false; |
} |
- *quadT = SkPinT(*quadT); |
- *lineT = SkPinT(*lineT); |
+ double qT = *quadT = SkPinT(*quadT); |
+ double lT = *lineT = SkPinT(*lineT); |
+ if (lT == 0 || lT == 1 || (ptSet == kPointUninitialized && qT != 0 && qT != 1)) { |
+ *pt = fLine.ptAtT(lT); |
+ } else if (ptSet == kPointUninitialized) { |
+ *pt = fQuad.ptAtT(qT); |
+ } |
return true; |
} |
private: |
- const SkDQuad& quad; |
- const SkDLine& line; |
- SkIntersections* intersections; |
+ const SkDQuad& fQuad; |
+ const SkDLine& fLine; |
+ SkIntersections* fIntersections; |
bool fAllowNear; |
}; |
@@ -332,7 +342,7 @@ static double horizontalIntersect(const SkDQuad& quad, const SkDPoint& pt) { |
int roots = q.horizontalIntersect(pt.fY, rootVals); |
for (int index = 0; index < roots; ++index) { |
double t = rootVals[index]; |
- SkDPoint qPt = quad.xyAtT(t); |
+ SkDPoint qPt = quad.ptAtT(t); |
if (AlmostEqualUlps(qPt.fX, pt.fX)) { |
return t; |
} |
@@ -347,7 +357,7 @@ static double verticalIntersect(const SkDQuad& quad, const SkDPoint& pt) { |
int roots = q.verticalIntersect(pt.fX, rootVals); |
for (int index = 0; index < roots; ++index) { |
double t = rootVals[index]; |
- SkDPoint qPt = quad.xyAtT(t); |
+ SkDPoint qPt = quad.ptAtT(t); |
if (AlmostEqualUlps(qPt.fY, pt.fY)) { |
return t; |
} |
@@ -364,13 +374,15 @@ double SkIntersections::Axial(const SkDQuad& q1, const SkDPoint& p, bool vertica |
int SkIntersections::horizontal(const SkDQuad& quad, double left, double right, double y, |
bool flipped) { |
- LineQuadraticIntersections q(quad, *(static_cast<SkDLine*>(0)), this); |
+ SkDLine line = {{{ left, y }, { right, y }}}; |
+ LineQuadraticIntersections q(quad, line, this); |
return q.horizontalIntersect(y, left, right, flipped); |
} |
int SkIntersections::vertical(const SkDQuad& quad, double top, double bottom, double x, |
bool flipped) { |
- LineQuadraticIntersections q(quad, *(static_cast<SkDLine*>(0)), this); |
+ SkDLine line = {{{ x, top }, { x, bottom }}}; |
+ LineQuadraticIntersections q(quad, line, this); |
return q.verticalIntersect(x, top, bottom, flipped); |
} |
@@ -384,7 +396,7 @@ int SkIntersections::intersectRay(const SkDQuad& quad, const SkDLine& line) { |
LineQuadraticIntersections q(quad, line, this); |
fUsed = q.intersectRay(fT[0]); |
for (int index = 0; index < fUsed; ++index) { |
- fPt[index] = quad.xyAtT(fT[0][index]); |
+ fPt[index] = quad.ptAtT(fT[0][index]); |
} |
return fUsed; |
} |