Esempio n. 1
0
int SkOpSegment::debugInflections(int tStart, int tEnd) const {
    if (fVerb != SkPath::kCubic_Verb) {
        return false;
    }
    SkDCubic dst = SkDCubic::SubDivide(fPts, fTs[tStart].fT, fTs[tEnd].fT);
    double inflections[2];
    return dst.findInflections(inflections);
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
void CubicPathToSimple(const SkPath& cubicPath, SkPath* simplePath) {
    simplePath->reset();
    SkDCubic cubic;
    SkPath::RawIter iter(cubicPath);
    uint8_t verb;
    SkPoint pts[4];
    while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
        switch (verb) {
            case SkPath::kMove_Verb:
                simplePath->moveTo(pts[0].fX, pts[0].fY);
                continue;
            case SkPath::kLine_Verb:
                simplePath->lineTo(pts[1].fX, pts[1].fY);
                break;
            case SkPath::kQuad_Verb:
                simplePath->quadTo(pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY);
                break;
            case SkPath::kCubic_Verb: {
                cubic.set(pts);
                double tInflects[2];
                int inflections = cubic.findInflections(tInflects);
                if (inflections > 1 && tInflects[0] > tInflects[1]) {
                    SkTSwap(tInflects[0], tInflects[1]);
                }
                double lo = 0;
                for (int index = 0; index <= inflections; ++index) {
                    double hi = index < inflections ? tInflects[index] : 1;
                    SkDCubic part = cubic.subDivide(lo, hi);
                    SkPoint cPts[3];
                    cPts[0] = part[1].asSkPoint();
                    cPts[1] = part[2].asSkPoint();
                    cPts[2] = part[3].asSkPoint();
                    simplePath->cubicTo(cPts[0].fX, cPts[0].fY, cPts[1].fX, cPts[1].fY,
                            cPts[2].fX, cPts[2].fY);
                    lo = hi;
                }
                break;
            } 
            case SkPath::kClose_Verb:
                 simplePath->close();
                break;
            default:
                SkDEBUGFAIL("bad verb");
                return;
        }
    }
}
Esempio n. 4
0
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;
}