SkDPoint SkDQuad::subDivide(const SkDPoint& a, const SkDPoint& c, double t1, double t2) const { SkASSERT(t1 != t2); SkDPoint b; SkDQuad sub = subDivide(t1, t2); SkDLine b0 = {{a, sub[1] + (a - sub[0])}}; SkDLine b1 = {{c, sub[1] + (c - sub[2])}}; SkIntersections i; i.intersectRay(b0, b1); if (i.used() == 1 && i[0][0] >= 0 && i[1][0] >= 0) { b = i.pt(0); } else { SkASSERT(i.used() <= 2); b = SkDPoint::Mid(b0[1], b1[1]); } if (t1 == 0 || t2 == 0) { align(0, &b); } if (t1 == 1 || t2 == 1) { align(2, &b); } if (AlmostBequalUlps(b.fX, a.fX)) { b.fX = a.fX; } else if (AlmostBequalUlps(b.fX, c.fX)) { b.fX = c.fX; } if (AlmostBequalUlps(b.fY, a.fY)) { b.fY = a.fY; } else if (AlmostBequalUlps(b.fY, c.fY)) { b.fY = c.fY; } return b; }
void SkDCubic::subDivide(const SkDPoint& a, const SkDPoint& d, double t1, double t2, SkDPoint dst[2]) const { SkASSERT(t1 != t2); // this approach assumes that the control points computed directly are accurate enough SkDCubic sub = subDivide(t1, t2); dst[0] = sub[1] + (a - sub[0]); dst[1] = sub[2] + (d - sub[3]); if (t1 == 0 || t2 == 0) { align(0, 1, t1 == 0 ? &dst[0] : &dst[1]); } if (t1 == 1 || t2 == 1) { align(3, 2, t1 == 1 ? &dst[0] : &dst[1]); } if (AlmostBequalUlps(dst[0].fX, a.fX)) { dst[0].fX = a.fX; } if (AlmostBequalUlps(dst[0].fY, a.fY)) { dst[0].fY = a.fY; } if (AlmostBequalUlps(dst[1].fX, d.fX)) { dst[1].fX = d.fX; } if (AlmostBequalUlps(dst[1].fY, d.fY)) { dst[1].fY = d.fY; } }
void SkDCubic::subDivide(const SkDPoint& a, const SkDPoint& d, double t1, double t2, SkDPoint dst[2]) const { SkASSERT(t1 != t2); #if 0 double ex = interp_cubic_coords(&fPts[0].fX, (t1 * 2 + t2) / 3); double ey = interp_cubic_coords(&fPts[0].fY, (t1 * 2 + t2) / 3); double fx = interp_cubic_coords(&fPts[0].fX, (t1 + t2 * 2) / 3); double fy = interp_cubic_coords(&fPts[0].fY, (t1 + t2 * 2) / 3); double mx = ex * 27 - a.fX * 8 - d.fX; double my = ey * 27 - a.fY * 8 - d.fY; double nx = fx * 27 - a.fX - d.fX * 8; double ny = fy * 27 - a.fY - d.fY * 8; /* bx = */ dst[0].fX = (mx * 2 - nx) / 18; /* by = */ dst[0].fY = (my * 2 - ny) / 18; /* cx = */ dst[1].fX = (nx * 2 - mx) / 18; /* cy = */ dst[1].fY = (ny * 2 - my) / 18; #else // this approach assumes that the control points computed directly are accurate enough SkDCubic sub = subDivide(t1, t2); dst[0] = sub[1] + (a - sub[0]); dst[1] = sub[2] + (d - sub[3]); #endif if (t1 == 0 || t2 == 0) { align(0, 1, t1 == 0 ? &dst[0] : &dst[1]); } if (t1 == 1 || t2 == 1) { align(3, 2, t1 == 1 ? &dst[0] : &dst[1]); } if (AlmostBequalUlps(dst[0].fX, a.fX)) { dst[0].fX = a.fX; } if (AlmostBequalUlps(dst[0].fY, a.fY)) { dst[0].fY = a.fY; } if (AlmostBequalUlps(dst[1].fX, d.fX)) { dst[1].fX = d.fX; } if (AlmostBequalUlps(dst[1].fY, d.fY)) { dst[1].fY = d.fY; } }
SkDPoint SkDQuad::subDivide(const SkDPoint& a, const SkDPoint& c, double t1, double t2) const { SkASSERT(t1 != t2); SkDPoint b; #if 0 // this approach assumes that the control point computed directly is accurate enough double dx = interp_quad_coords(&fPts[0].fX, (t1 + t2) / 2); double dy = interp_quad_coords(&fPts[0].fY, (t1 + t2) / 2); b.fX = 2 * dx - (a.fX + c.fX) / 2; b.fY = 2 * dy - (a.fY + c.fY) / 2; #else SkDQuad sub = subDivide(t1, t2); SkDLine b0 = {{a, sub[1] + (a - sub[0])}}; SkDLine b1 = {{c, sub[1] + (c - sub[2])}}; SkIntersections i; i.intersectRay(b0, b1); if (i.used() == 1 && i[0][0] >= 0 && i[1][0] >= 0) { b = i.pt(0); } else { SkASSERT(i.used() <= 2); b = SkDPoint::Mid(b0[1], b1[1]); } #endif if (t1 == 0 || t2 == 0) { align(0, &b); } if (t1 == 1 || t2 == 1) { align(2, &b); } if (AlmostBequalUlps(b.fX, a.fX)) { b.fX = a.fX; } else if (AlmostBequalUlps(b.fX, c.fX)) { b.fX = c.fX; } if (AlmostBequalUlps(b.fY, a.fY)) { b.fY = a.fY; } else if (AlmostBequalUlps(b.fY, c.fY)) { b.fY = c.fY; } return b; }
double SkDLine::NearPointV(const SkDPoint& xy, double top, double bottom, double x) { if (!AlmostBequalUlps(xy.fX, x)) { return -1; } if (!AlmostBetweenUlps(top, xy.fY, bottom)) { return -1; } double t = (xy.fY - top) / (bottom - top); t = SkPinT(t); SkASSERT(between(0, t, 1)); double realPtY = (1 - t) * top + t * bottom; SkDVector distU = {xy.fX - x, xy.fY - realPtY}; double distSq = distU.fX * distU.fX + distU.fY * distU.fY; double dist = sqrt(distSq); // OPTIMIZATION: can we compare against distSq instead ? double tiniest = SkTMin(SkTMin(x, top), bottom); double largest = SkTMax(SkTMax(x, top), bottom); largest = SkTMax(largest, -tiniest); if (!AlmostEqualUlps(largest, largest + dist)) { // is the dist within ULPS tolerance? return -1; } return t; }
double SkDLine::NearPointH(const SkDPoint& xy, double left, double right, double y) { if (!AlmostBequalUlps(xy.fY, y)) { return -1; } if (!AlmostBetweenUlps(left, xy.fX, right)) { return -1; } double t = (xy.fX - left) / (right - left); t = SkPinT(t); SkASSERT(between(0, t, 1)); double realPtX = (1 - t) * left + t * right; SkDVector distU = {xy.fY - y, xy.fX - realPtX}; double distSq = distU.fX * distU.fX + distU.fY * distU.fY; double dist = sqrt(distSq); // OPTIMIZATION: can we compare against distSq instead ? double tiniest = SkTMin(SkTMin(y, left), right); double largest = SkTMax(SkTMax(y, left), right); largest = SkTMax(largest, -tiniest); if (!AlmostEqualUlps(largest, largest + dist)) { // is the dist within ULPS tolerance? return -1; } return t; }