void SkEvalCubicAt(const SkPoint src[4], SkScalar t, SkPoint* loc, SkVector* tangent, SkVector* curvature) { SkASSERT(src); SkASSERT(t >= 0 && t <= SK_Scalar1); if (loc) { loc->set(eval_cubic(&src[0].fX, t), eval_cubic(&src[0].fY, t)); } if (tangent) { // The derivative equation returns a zero tangent vector when t is 0 or 1, and the // adjacent control point is equal to the end point. In this case, use the // next control point or the end points to compute the tangent. if ((t == 0 && src[0] == src[1]) || (t == 1 && src[2] == src[3])) { if (t == 0) { *tangent = src[2] - src[0]; } else { *tangent = src[3] - src[1]; } if (!tangent->fX && !tangent->fY) { *tangent = src[3] - src[0]; } } else { tangent->set(eval_cubic_derivative(&src[0].fX, t), eval_cubic_derivative(&src[0].fY, t)); } } if (curvature) { curvature->set(eval_cubic_2ndDerivative(&src[0].fX, t), eval_cubic_2ndDerivative(&src[0].fY, t)); } }
void SkEvalCubicAt(const SkPoint src[4], SkScalar t, SkPoint* loc, SkVector* tangent, SkVector* curvature) { SkASSERT(src); SkASSERT(t >= 0 && t <= SK_Scalar1); if (loc) loc->set(eval_cubic(&src[0].fX, t), eval_cubic(&src[0].fY, t)); if (tangent) tangent->set(eval_cubic_derivative(&src[0].fX, t), eval_cubic_derivative(&src[0].fY, t)); if (curvature) curvature->set(eval_cubic_2ndDerivative(&src[0].fX, t), eval_cubic_2ndDerivative(&src[0].fY, t)); }
SkScalar SkUnitCubicInterp(SkScalar value, SkScalar bx, SkScalar by, SkScalar cx, SkScalar cy) { // pin to the unit-square, and convert to 2.14 Dot14 x = pin_and_convert(value); if (x == 0) return 0; if (x == Dot14_ONE) return SK_Scalar1; Dot14 b = pin_and_convert(bx); Dot14 c = pin_and_convert(cx); // Now compute our coefficients from the control points // t -> 3b // t^2 -> 3c - 6b // t^3 -> 3b - 3c + 1 Dot14 A = 3*b; Dot14 B = 3*(c - 2*b); Dot14 C = 3*(b - c) + Dot14_ONE; // Now search for a t value given x Dot14 t = Dot14_HALF; Dot14 dt = Dot14_HALF; for (int i = 0; i < 13; i++) { dt >>= 1; Dot14 guess = eval_cubic(t, A, B, C); if (x < guess) { t -= dt; } else { t += dt; } } // Now we have t, so compute the coeff for Y and evaluate b = pin_and_convert(by); c = pin_and_convert(cy); A = 3*b; B = 3*(c - 2*b); C = 3*(b - c) + Dot14_ONE; return SkFixedToScalar(eval_cubic(t, A, B, C) << 2); }