Example #1
0
static bool intersectEnd(const Cubic& cubic1, bool start, const Cubic& cubic2, const _Rect& bounds2,
        Intersections& i) {
    _Line line1;
    line1[0] = line1[1] = cubic1[start ? 0 : 3];
    _Point dxy1 = line1[0] - cubic1[start ? 1 : 2];
    dxy1 /= precisionUnit;
    line1[1] += dxy1;
    _Rect line1Bounds;
    line1Bounds.setBounds(line1);
    if (!bounds2.intersects(line1Bounds)) {
        return false;
    }
    _Line line2;
    line2[0] = line2[1] = line1[0];
    _Point dxy2 = line2[0] - cubic1[start ? 3 : 0];
    dxy2 /= precisionUnit;
    line2[1] += dxy2;
#if 0 // this is so close to the first bounds test it isn't worth the short circuit test
    _Rect line2Bounds;
    line2Bounds.setBounds(line2);
    if (!bounds2.intersects(line2Bounds)) {
        return false;
    }
#endif
    Intersections local1;
    if (!intersect(cubic2, line1, local1)) {
        return false;
    }
    Intersections local2;
    if (!intersect(cubic2, line2, local2)) {
        return false;
    }
    double tMin, tMax;
    tMin = tMax = local1.fT[0][0];
    for (int index = 1; index < local1.fUsed; ++index) {
        tMin = std::min(tMin, local1.fT[0][index]);
        tMax = std::max(tMax, local1.fT[0][index]);
    }
    for (int index = 1; index < local2.fUsed; ++index) {
        tMin = std::min(tMin, local2.fT[0][index]);
        tMax = std::max(tMax, local2.fT[0][index]);
    }
#if SK_DEBUG
    debugDepth = 0;
#endif
    return intersect2(cubic1, start ? 0 : 1, start ? 1.0 / precisionUnit : 1 - 1.0 / precisionUnit,
            cubic2, tMin, tMax, 1, i);
}
// intersect the end of the cubic with the other. Try lines from the end to control and opposite
// end to determine range of t on opposite cubic.
static bool intersectEnd(const Cubic& cubic1, bool start, const Cubic& cubic2, const _Rect& bounds2,
        Intersections& i) {
 //   bool selfIntersect = cubic1 == cubic2;
    _Line line;
    int t1Index = start ? 0 : 3;
    line[0] = cubic1[t1Index];
    // don't bother if the two cubics are connnected
#if 0
    if (!selfIntersect && (line[0].approximatelyEqual(cubic2[0])
            || line[0].approximatelyEqual(cubic2[3]))) {
        return false;
    }
#endif
    bool result = false;
    SkTDArray<double> tVals; // OPTIMIZE: replace with hard-sized array
    for (int index = 0; index < 4; ++index) {
        if (index == t1Index) {
            continue;
        }
        _Vector dxy1 = cubic1[index] - line[0];
        dxy1 /= gPrecisionUnit;
        line[1] = line[0] + dxy1;
        _Rect lineBounds;
        lineBounds.setBounds(line);
        if (!bounds2.intersects(lineBounds)) {
            continue;
        }
        Intersections local;
        if (!intersect(cubic2, line, local)) {
            continue;
        }
        for (int idx2 = 0; idx2 < local.used(); ++idx2) {
            double foundT = local.fT[0][idx2];
            if (approximately_less_than_zero(foundT)
                    || approximately_greater_than_one(foundT)) {
                continue;
            }
            if (local.fPt[idx2].approximatelyEqual(line[0])) {
                if (i.swapped()) { // FIXME: insert should respect swap
                    i.insert(foundT, start ? 0 : 1, line[0]);
                } else {
                    i.insert(start ? 0 : 1, foundT, line[0]);
                }
                result = true;
            } else {
                *tVals.append() = local.fT[0][idx2];
            }
        }
    }
    if (tVals.count() == 0) {
        return result;
    }
    QSort<double>(tVals.begin(), tVals.end() - 1);
    double tMin1 = start ? 0 : 1 - LINE_FRACTION;
    double tMax1 = start ? LINE_FRACTION : 1;
    int tIdx = 0;
    do {
        int tLast = tIdx;
        while (tLast + 1 < tVals.count() && roughly_equal(tVals[tLast + 1], tVals[tIdx])) {
            ++tLast;
        }
        double tMin2 = SkTMax(tVals[tIdx] - LINE_FRACTION, 0.0);
        double tMax2 = SkTMin(tVals[tLast] + LINE_FRACTION, 1.0);
        int lastUsed = i.used();
        result |= intersect3(cubic1, tMin1, tMax1, cubic2, tMin2, tMax2, 1, i);
        if (lastUsed == i.used()) {
            tMin2 = SkTMax(tVals[tIdx] - (1.0 / gPrecisionUnit), 0.0);
            tMax2 = SkTMin(tVals[tLast] + (1.0 / gPrecisionUnit), 1.0);
            result |= intersect3(cubic1, tMin1, tMax1, cubic2, tMin2, tMax2, 1, i);
        }
        tIdx = tLast + 1;
    } while (tIdx < tVals.count());
    return result;
}