SkDQuadPair SkDQuad::chopAt(double t) const { SkDQuadPair dst; interp_quad_coords(&fPts[0].fX, &dst.pts[0].fX, t); interp_quad_coords(&fPts[0].fY, &dst.pts[0].fY, t); return dst; }
void SkChopQuadAt(const SkPoint src[3], SkPoint dst[5], SkScalar t) { SkASSERT(t > 0 && t < SK_Scalar1); interp_quad_coords(&src[0].fX, &dst[0].fX, t); interp_quad_coords(&src[0].fY, &dst[0].fY, t); }
static int check_linear(const Quadratic& quad, Quadratic& reduction, int minX, int maxX, int minY, int maxY) { int startIndex = 0; int endIndex = 2; while (quad[startIndex].approximatelyEqual(quad[endIndex])) { --endIndex; if (endIndex == 0) { printf("%s shouldn't get here if all four points are about equal", __FUNCTION__); assert(0); } } if (!isLinear(quad, startIndex, endIndex)) { return 0; } // four are colinear: return line formed by outside reduction[0] = quad[0]; reduction[1] = quad[2]; int sameSide; bool useX = quad[maxX].x - quad[minX].x >= quad[maxY].y - quad[minY].y; if (useX) { sameSide = sign(quad[0].x - quad[1].x) + sign(quad[2].x - quad[1].x); } else { sameSide = sign(quad[0].y - quad[1].y) + sign(quad[2].y - quad[1].y); } if ((sameSide & 3) != 2) { return 2; } double tValue; int root; if (useX) { root = findExtrema(quad[0].x, quad[1].x, quad[2].x, &tValue); } else { root = findExtrema(quad[0].y, quad[1].y, quad[2].y, &tValue); } if (root) { _Point extrema; extrema.x = interp_quad_coords(quad[0].x, quad[1].x, quad[2].x, tValue); extrema.y = interp_quad_coords(quad[0].x, quad[1].x, quad[2].x, tValue); // sameSide > 0 means mid is smaller than either [0] or [2], so replace smaller int replace; if (useX) { if (extrema.x < quad[0].x ^ extrema.x < quad[2].x) { return 2; } replace = (extrema.x < quad[0].x | extrema.x < quad[2].x) ^ (quad[0].x < quad[2].x); } else { if (extrema.y < quad[0].y ^ extrema.y < quad[2].y) { return 2; } replace = (extrema.y < quad[0].y | extrema.y < quad[2].y) ^ (quad[0].y < quad[2].y); } reduction[replace] = extrema; } return 2; }
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; }
static int horizontal_line(const Quadratic& quad, Quadratic& reduction) { double tValue; reduction[0] = quad[0]; reduction[1] = quad[2]; int smaller = reduction[1].x > reduction[0].x; int larger = smaller ^ 1; if (findExtrema(quad[0].x, quad[1].x, quad[2].x, &tValue)) { double xExtrema = interp_quad_coords(quad[0].x, quad[1].x, quad[2].x, tValue); if (reduction[smaller].x > xExtrema) { reduction[smaller].x = xExtrema; } else if (reduction[larger].x < xExtrema) { reduction[larger].x = xExtrema; } } return 2; }
static int vertical_line(const Quadratic& quad, Quadratic& reduction) { double tValue; reduction[0] = quad[0]; reduction[1] = quad[2]; int smaller = reduction[1].y > reduction[0].y; int larger = smaller ^ 1; if (findExtrema(quad[0].y, quad[1].y, quad[2].y, &tValue)) { double yExtrema = interp_quad_coords(quad[0].y, quad[1].y, quad[2].y, tValue); if (reduction[smaller].y > yExtrema) { reduction[smaller].y = yExtrema; } else if (reduction[larger].y < yExtrema) { reduction[larger].y = yExtrema; } } return 2; }
// OPTIMIZE : special case either or both of t1 = 0, t2 = 1 SkDQuad SkDQuad::subDivide(double t1, double t2) const { SkDQuad dst; double ax = dst[0].fX = interp_quad_coords(&fPts[0].fX, t1); double ay = dst[0].fY = interp_quad_coords(&fPts[0].fY, t1); double dx = interp_quad_coords(&fPts[0].fX, (t1 + t2) / 2); double dy = interp_quad_coords(&fPts[0].fY, (t1 + t2) / 2); double cx = dst[2].fX = interp_quad_coords(&fPts[0].fX, t2); double cy = dst[2].fY = interp_quad_coords(&fPts[0].fY, t2); /* bx = */ dst[1].fX = 2 * dx - (ax + cx) / 2; /* by = */ dst[1].fY = 2 * dy - (ay + cy) / 2; return dst; }