Exemple #1
0
int SkDCubic::searchRoots(double extremeTs[6], int extrema, double axisIntercept,
        SearchAxis xAxis, double* validRoots) const {
    extrema += findInflections(&extremeTs[extrema]);
    extremeTs[extrema++] = 0;
    extremeTs[extrema] = 1;
    SkASSERT(extrema < 6);
    SkTQSort(extremeTs, extremeTs + extrema);
    int validCount = 0;
    for (int index = 0; index < extrema; ) {
        double min = extremeTs[index];
        double max = extremeTs[++index];
        if (min == max) {
            continue;
        }
        double newT = binarySearch(min, max, axisIntercept, xAxis);
        if (newT >= 0) {
            if (validCount >= 3) {
                return 0;
            }
            validRoots[validCount++] = newT;
        }
    }
    return validCount;
}
Exemple #2
0
// flavor that returns T values only, deferring computing the quads until they are needed
// FIXME: when called from recursive intersect 2, this could take the original cubic
// and do a more precise job when calling chop at and sub divide by computing the fractional ts.
// it would still take the prechopped cubic for reduce order and find cubic inflections
void SkDCubic::toQuadraticTs(double precision, SkTDArray<double>* ts) const {
    SkReduceOrder reducer;
    int order = reducer.reduce(*this, SkReduceOrder::kAllow_Quadratics, SkReduceOrder::kFill_Style);
    if (order < 3) {
        return;
    }
    double inflectT[5];
    int inflections = findInflections(inflectT);
    SkASSERT(inflections <= 2);
    if (!endsAreExtremaInXOrY()) {
        inflections += findMaxCurvature(&inflectT[inflections]);
        SkASSERT(inflections <= 5);
    }
    QSort<double>(inflectT, &inflectT[inflections - 1]);
    // OPTIMIZATION: is this filtering common enough that it needs to be pulled out into its
    // own subroutine?
    while (inflections && approximately_less_than_zero(inflectT[0])) {
        memmove(inflectT, &inflectT[1], sizeof(inflectT[0]) * --inflections);
    }
    int start = 0;
    do {
        int next = start + 1;
        if (next >= inflections) {
            break;
        }
        if (!approximately_equal(inflectT[start], inflectT[next])) {
            ++start;
            continue;
        }
        memmove(&inflectT[start], &inflectT[next], sizeof(inflectT[0]) * (--inflections - start));
    } while (true);
    while (inflections && approximately_greater_than_one(inflectT[inflections - 1])) {
        --inflections;
    }
    SkDCubicPair pair;
    if (inflections == 1) {
        pair = chopAt(inflectT[0]);
        int orderP1 = reducer.reduce(pair.first(), SkReduceOrder::kNo_Quadratics,
                SkReduceOrder::kFill_Style);
        if (orderP1 < 2) {
            --inflections;
        } else {
            int orderP2 = reducer.reduce(pair.second(), SkReduceOrder::kNo_Quadratics,
                    SkReduceOrder::kFill_Style);
            if (orderP2 < 2) {
                --inflections;
            }
        }
    }
    if (inflections == 0 && add_simple_ts(*this, precision, ts)) {
        return;
    }
    if (inflections == 1) {
        pair = chopAt(inflectT[0]);
        addTs(pair.first(), precision, 0, inflectT[0], ts);
        addTs(pair.second(), precision, inflectT[0], 1, ts);
        return;
    }
    if (inflections > 1) {
        SkDCubic part = subDivide(0, inflectT[0]);
        addTs(part, precision, 0, inflectT[0], ts);
        int last = inflections - 1;
        for (int idx = 0; idx < last; ++idx) {
            part = subDivide(inflectT[idx], inflectT[idx + 1]);
            addTs(part, precision, inflectT[idx], inflectT[idx + 1], ts);
        }
        part = subDivide(inflectT[last], 1);
        addTs(part, precision, inflectT[last], 1, ts);
        return;
    }
    addTs(*this, precision, 0, 1, ts);
}