void GrPathUtils::getCubicKLM(const SkPoint p[4], SkScalar klm[9]) { SkScalar d[3]; calc_cubic_inflection_func(p, d); CubicType cType = classify_cubic(p, d); SkScalar controlK[4]; SkScalar controlL[4]; SkScalar controlM[4]; if (kSerpentine_CubicType == cType || (kCusp_CubicType == cType && 0.f != d[0])) { set_serp_klm(d, controlK, controlL, controlM); } else if (kLoop_CubicType == cType) { set_loop_klm(d, controlK, controlL, controlM); } else if (kCusp_CubicType == cType) { SkASSERT(0.f == d[0]); set_cusp_klm(d, controlK, controlL, controlM); } else if (kQuadratic_CubicType == cType) { set_quadratic_klm(d, controlK, controlL, controlM); } calc_cubic_klm(p, controlK, controlL, controlM, klm, &klm[3], &klm[6]); }
SkCubicType SkClassifyCubic(const SkPoint src[4], SkScalar d[3]) { calc_cubic_inflection_func(src, d); return classify_cubic(src, d); }
int GrPathUtils::chopCubicAtLoopIntersection(const SkPoint src[4], SkPoint dst[10], SkScalar klm[9], SkScalar klm_rev[3]) { // Variable to store the two parametric values at the loop double point SkScalar smallS = 0.f; SkScalar largeS = 0.f; SkScalar d[3]; calc_cubic_inflection_func(src, d); CubicType cType = classify_cubic(src, d); int chop_count = 0; if (kLoop_CubicType == cType) { SkScalar tempSqrt = SkScalarSqrt(4.f * d[0] * d[2] - 3.f * d[1] * d[1]); SkScalar ls = d[1] - tempSqrt; SkScalar lt = 2.f * d[0]; SkScalar ms = d[1] + tempSqrt; SkScalar mt = 2.f * d[0]; ls = ls / lt; ms = ms / mt; // need to have t values sorted since this is what is expected by SkChopCubicAt if (ls <= ms) { smallS = ls; largeS = ms; } else { smallS = ms; largeS = ls; } SkScalar chop_ts[2]; if (smallS > 0.f && smallS < 1.f) { chop_ts[chop_count++] = smallS; } if (largeS > 0.f && largeS < 1.f) { chop_ts[chop_count++] = largeS; } if(dst) { SkChopCubicAt(src, dst, chop_ts, chop_count); } } else { if (dst) { memcpy(dst, src, sizeof(SkPoint) * 4); } } if (klm && klm_rev) { // Set klm_rev to to match the sub_section of cubic that needs to have its orientation // flipped. This will always be the section that is the "loop" if (2 == chop_count) { klm_rev[0] = 1.f; klm_rev[1] = -1.f; klm_rev[2] = 1.f; } else if (1 == chop_count) { if (smallS < 0.f) { klm_rev[0] = -1.f; klm_rev[1] = 1.f; } else { klm_rev[0] = 1.f; klm_rev[1] = -1.f; } } else { if (smallS < 0.f && largeS > 1.f) { klm_rev[0] = -1.f; } else { klm_rev[0] = 1.f; } } SkScalar controlK[4]; SkScalar controlL[4]; SkScalar controlM[4]; if (kSerpentine_CubicType == cType || (kCusp_CubicType == cType && 0.f != d[0])) { set_serp_klm(d, controlK, controlL, controlM); } else if (kLoop_CubicType == cType) { set_loop_klm(d, controlK, controlL, controlM); } else if (kCusp_CubicType == cType) { SkASSERT(0.f == d[0]); set_cusp_klm(d, controlK, controlL, controlM); } else if (kQuadratic_CubicType == cType) { set_quadratic_klm(d, controlK, controlL, controlM); } calc_cubic_klm(src, controlK, controlL, controlM, klm, &klm[3], &klm[6]); } return chop_count + 1; }