bool SkDCubic::ComplexBreak(const SkPoint pointsPtr[4], SkScalar* t) { SkScalar d[3]; SkCubicType cubicType = SkClassifyCubic(pointsPtr, d); if (cubicType == kLoop_SkCubicType) { // crib code from gpu path utils that finds t values where loop self-intersects // use it to find mid of t values which should be a friendly place to chop 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]; if (roughly_between(0, ls, lt) && roughly_between(0, ms, mt)) { ls = ls / lt; ms = ms / mt; SkASSERT(roughly_between(0, ls, 1) && roughly_between(0, ms, 1)); *t = (ls + ms) / 2; SkASSERT(roughly_between(0, *t, 1)); return *t > 0 && *t < 1; } } else if (kSerpentine_SkCubicType == cubicType || kCusp_SkCubicType == cubicType) { SkDCubic cubic; cubic.set(pointsPtr); double inflectionTs[2]; int infTCount = cubic.findInflections(inflectionTs); if (infTCount == 2) { double maxCurvature[3]; int roots = cubic.findMaxCurvature(maxCurvature); #if DEBUG_CUBIC_SPLIT SkDebugf("%s\n", __FUNCTION__); cubic.dump(); for (int index = 0; index < infTCount; ++index) { SkDebugf("inflectionsTs[%d]=%1.9g ", index, inflectionTs[index]); SkDPoint pt = cubic.ptAtT(inflectionTs[index]); SkDVector dPt = cubic.dxdyAtT(inflectionTs[index]); SkDLine perp = {{pt - dPt, pt + dPt}}; perp.dump(); } for (int index = 0; index < roots; ++index) { SkDebugf("maxCurvature[%d]=%1.9g ", index, maxCurvature[index]); SkDPoint pt = cubic.ptAtT(maxCurvature[index]); SkDVector dPt = cubic.dxdyAtT(maxCurvature[index]); SkDLine perp = {{pt - dPt, pt + dPt}}; perp.dump(); } #endif for (int index = 0; index < roots; ++index) { if (between(inflectionTs[0], maxCurvature[index], inflectionTs[1])) { *t = maxCurvature[index]; return *t > 0 && *t < 1; } } } else if (infTCount == 1) { *t = inflectionTs[0]; return *t > 0 && *t < 1; } } return false; }
void DumpT(const SkDQuad& quad, double t) { SkDLine line = {{quad.ptAtT(t), quad[0]}}; line.dump(); }
int SkDCubic::ComplexBreak(const SkPoint pointsPtr[4], SkScalar* t) { SkDCubic cubic; cubic.set(pointsPtr); if (cubic.monotonicInX() && cubic.monotonicInY()) { return 0; } SkScalar d[3]; SkCubicType cubicType = SkClassifyCubic(pointsPtr, d); switch (cubicType) { case kLoop_SkCubicType: { // crib code from gpu path utils that finds t values where loop self-intersects // use it to find mid of t values which should be a friendly place to chop 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]; if (roughly_between(0, ls, lt) && roughly_between(0, ms, mt)) { ls = ls / lt; ms = ms / mt; SkASSERT(roughly_between(0, ls, 1) && roughly_between(0, ms, 1)); t[0] = (ls + ms) / 2; SkASSERT(roughly_between(0, *t, 1)); return (int) (t[0] > 0 && t[0] < 1); } } // fall through if no t value found case kSerpentine_SkCubicType: case kCusp_SkCubicType: { double inflectionTs[2]; int infTCount = cubic.findInflections(inflectionTs); double maxCurvature[3]; int roots = cubic.findMaxCurvature(maxCurvature); #if DEBUG_CUBIC_SPLIT SkDebugf("%s\n", __FUNCTION__); cubic.dump(); for (int index = 0; index < infTCount; ++index) { SkDebugf("inflectionsTs[%d]=%1.9g ", index, inflectionTs[index]); SkDPoint pt = cubic.ptAtT(inflectionTs[index]); SkDVector dPt = cubic.dxdyAtT(inflectionTs[index]); SkDLine perp = {{pt - dPt, pt + dPt}}; perp.dump(); } for (int index = 0; index < roots; ++index) { SkDebugf("maxCurvature[%d]=%1.9g ", index, maxCurvature[index]); SkDPoint pt = cubic.ptAtT(maxCurvature[index]); SkDVector dPt = cubic.dxdyAtT(maxCurvature[index]); SkDLine perp = {{pt - dPt, pt + dPt}}; perp.dump(); } #endif if (infTCount == 2) { for (int index = 0; index < roots; ++index) { if (between(inflectionTs[0], maxCurvature[index], inflectionTs[1])) { t[0] = maxCurvature[index]; return (int) (t[0] > 0 && t[0] < 1); } } } else { int resultCount = 0; // FIXME: constant found through experimentation -- maybe there's a better way.... double precision = cubic.calcPrecision() * 2; for (int index = 0; index < roots; ++index) { double testT = maxCurvature[index]; if (0 >= testT || testT >= 1) { continue; } // don't call dxdyAtT since we want (0,0) results SkDVector dPt = { derivative_at_t(&cubic.fPts[0].fX, testT), derivative_at_t(&cubic.fPts[0].fY, testT) }; double dPtLen = dPt.length(); if (dPtLen < precision) { t[resultCount++] = testT; } } if (!resultCount && infTCount == 1) { t[0] = inflectionTs[0]; resultCount = (int) (t[0] > 0 && t[0] < 1); } return resultCount; } } default: ; } return 0; }