static int vertical_coincident(const SkDLine& line, double x) { double min = line[0].fX; double max = line[1].fX; if (min > max) { SkTSwap(min, max); } if (!precisely_between(min, x, max)) { return 0; } if (AlmostEqualUlps(min, max)) { return 2; } return 1; }
int SkIntersections::vertical(const SkDLine& line, double x) { double min = line[0].fX; double max = line[1].fX; if (min > max) { SkTSwap(min, max); } if (!precisely_between(min, x, max)) { return fUsed = 0; } if (AlmostEqualUlps(min, max)) { fT[0][0] = 0; fT[0][1] = 1; return fUsed = 2; } fT[0][0] = (x - line[0].fX) / (line[1].fX - line[0].fX); return fUsed = 1; }
int SkIntersections::vertical(const SkDLine& line, double top, double bottom, double x, bool flipped) { int result = vertical(line, x); switch (result) { case 0: break; case 1: { double yIntercept = line[0].fY + fT[0][0] * (line[1].fY - line[0].fY); if (!precisely_between(top, yIntercept, bottom)) { return fUsed = 0; } fT[1][0] = (yIntercept - top) / (bottom - top); break; } case 2: double a0 = line[0].fY; double a1 = line[1].fY; double b0 = flipped ? bottom : top; double b1 = flipped ? top : bottom; // FIXME: share common code above double at0 = (a0 - b0) / (a0 - a1); double at1 = (a0 - b1) / (a0 - a1); if ((at0 < 0 && at1 < 0) || (at0 > 1 && at1 > 1)) { return fUsed = 0; } fT[0][0] = SkTMax(SkTMin(at0, 1.0), 0.0); fT[0][1] = SkTMax(SkTMin(at1, 1.0), 0.0); int bIn = (a0 - a1) * (b0 - b1) < 0; fT[1][bIn] = SkTMax(SkTMin((b0 - a0) / (b0 - b1), 1.0), 0.0); fT[1][!bIn] = SkTMax(SkTMin((b0 - a1) / (b0 - b1), 1.0), 0.0); bool second = fabs(fT[0][0] - fT[0][1]) > FLT_EPSILON; SkASSERT((fabs(fT[1][0] - fT[1][1]) <= FLT_EPSILON) ^ second); return computePoints(line, 1 + second); } if (flipped) { // OPTIMIZATION: instead of swapping, pass original line, use [1].fY - [0].fY for (int index = 0; index < result; ++index) { fT[1][index] = 1 - fT[1][index]; } } return computePoints(line, result); }
int SkIntersections::horizontal(const SkDLine& line, double left, double right, double y, bool flipped) { int result = horizontal(line, y); switch (result) { case 0: break; case 1: { double xIntercept = line[0].fX + fT[0][0] * (line[1].fX - line[0].fX); if (!precisely_between(left, xIntercept, right)) { return fUsed = 0; } fT[1][0] = (xIntercept - left) / (right - left); break; } case 2: double a0 = line[0].fX; double a1 = line[1].fX; double b0 = flipped ? right : left; double b1 = flipped ? left : right; // FIXME: share common code below double at0 = (a0 - b0) / (a0 - a1); double at1 = (a0 - b1) / (a0 - a1); if ((at0 < 0 && at1 < 0) || (at0 > 1 && at1 > 1)) { return fUsed = 0; } fT[0][0] = SkTMax(SkTMin(at0, 1.0), 0.0); fT[0][1] = SkTMax(SkTMin(at1, 1.0), 0.0); int bIn = (a0 - a1) * (b0 - b1) < 0; fT[1][bIn] = SkTMax(SkTMin((b0 - a0) / (b0 - b1), 1.0), 0.0); fT[1][!bIn] = SkTMax(SkTMin((b0 - a1) / (b0 - b1), 1.0), 0.0); bool second = fabs(fT[0][0] - fT[0][1]) > FLT_EPSILON; SkASSERT((fabs(fT[1][0] - fT[1][1]) <= FLT_EPSILON) ^ second); return computePoints(line, 1 + second); } if (flipped) { // OPTIMIZATION: instead of swapping, pass original line, use [1].fX - [0].fX for (int index = 0; index < result; ++index) { fT[1][index] = 1 - fT[1][index]; } } return computePoints(line, result); }
int SkIntersections::vertical(const SkDLine& line, double top, double bottom, double x, bool flipped) { // see if end points intersect the opposite line double t; if (checkEndPoint(x, top, line, &t, false)) { insert(t, flipped, x, top); } if (top != bottom) { if (checkEndPoint(x, bottom,line, &t, false)) { insert(t, !flipped, x, bottom); } for (int index = 0; index < 2; ++index) { if (!checkEndPointV(line[index], top, bottom, x, flipped, &t)) { continue; } insert( index, t, line[index]); } } if (used() > 0) { SkASSERT(fUsed <= 2); return used(); // coincident lines are returned here } int result = vertical(line, x); if (!result) { return 0; } SkASSERT(result == 1); double yIntercept = line[0].fY + fT[0][0] * (line[1].fY - line[0].fY); if (!precisely_between(top, yIntercept, bottom)) { return fUsed = 0; } fT[1][0] = (yIntercept - top) / (bottom - top); if (flipped) { // OPTIMIZATION: instead of swapping, pass original line, use [1].fY - [0].fY for (int index = 0; index < result; ++index) { fT[1][index] = 1 - fT[1][index]; } } return computePoints(line, result); }
int SkIntersections::horizontal(const SkDLine& line, double left, double right, double y, bool flipped) { // see if end points intersect the opposite line double t; if (checkEndPoint(left, y, line, &t, true)) { insert(t, flipped, left, y); } if (left != right) { if (checkEndPoint(right, y, line, &t, true)) { insert(t, !flipped, right, y); } for (int index = 0; index < 2; ++index) { if (!checkEndPointH(line[index], left, right, y, flipped, &t)) { continue; } insert(index, t, line[index]); } } if (used() > 0) { SkASSERT(fUsed <= 2); return used(); // coincident lines are returned here } int result = horizontal(line, y); if (!result) { return 0; } SkASSERT(result == 1); double xIntercept = line[0].fX + fT[0][0] * (line[1].fX - line[0].fX); if (!precisely_between(left, xIntercept, right)) { return fUsed = 0; } fT[1][0] = (xIntercept - left) / (right - left); if (flipped) { // OPTIMIZATION: ? instead of swapping, pass original line, use [1].fX - [0].fX for (int index = 0; index < result; ++index) { fT[1][index] = 1 - fT[1][index]; } } return computePoints(line, result); }
bool SkDCubic::monotonicInY() const { return precisely_between(fPts[0].fY, fPts[1].fY, fPts[3].fY) && precisely_between(fPts[0].fY, fPts[2].fY, fPts[3].fY); }