static void lookNearEnd(const SkDQuad& q1, const SkDQuad& q2, int testT,
        const SkIntersections& orig, bool swap, SkIntersections* i) {
    if (orig.used() == 1 && orig[!swap][0] == testT) {
        return;
    }
    if (orig.used() == 2 && orig[!swap][1] == testT) {
        return;
    }
    SkDLine tmpLine;
    int testTIndex = testT << 1;
    tmpLine[0] = tmpLine[1] = q2[testTIndex];
    tmpLine[1].fX += q2[1].fY - q2[testTIndex].fY;
    tmpLine[1].fY -= q2[1].fX - q2[testTIndex].fX;
    SkIntersections impTs;
    impTs.intersectRay(q1, tmpLine);
    for (int index = 0; index < impTs.used(); ++index) {
        SkDPoint realPt = impTs.pt(index);
        if (!tmpLine[0].approximatelyEqualHalf(realPt)) {
            continue;
        }
        if (swap) {
            i->insert(testT, impTs[0][index], tmpLine[0]);
        } else {
            i->insert(impTs[0][index], testT, tmpLine[0]);
        }
    }
}
// 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.
bool SkIntersections::cubicExactEnd(const SkDCubic& cubic1, bool start, const SkDCubic& cubic2) {
    int t1Index = start ? 0 : 3;
    double testT = (double) !start;
    bool swap = swapped();
    // quad/quad at this point checks to see if exact matches have already been found
    // cubic/cubic can't reject so easily since cubics can intersect same point more than once
    SkDLine tmpLine;
    tmpLine[0] = tmpLine[1] = cubic2[t1Index];
    tmpLine[1].fX += cubic2[2 - start].fY - cubic2[t1Index].fY;
    tmpLine[1].fY -= cubic2[2 - start].fX - cubic2[t1Index].fX;
    SkIntersections impTs;
    impTs.allowNear(false);
    impTs.intersectRay(cubic1, tmpLine);
    for (int index = 0; index < impTs.used(); ++index) {
        SkDPoint realPt = impTs.pt(index);
        if (!tmpLine[0].approximatelyEqual(realPt)) {
            continue;
        }
        if (swap) {
            cubicInsert(testT, impTs[0][index], tmpLine[0], cubic2, cubic1);
        } else {
            cubicInsert(impTs[0][index], testT, tmpLine[0], cubic1, cubic2);
        }
        return true;
    }
    return false;
}
Example #3
0
SkDPoint SkDQuad::subDivide(const SkDPoint& a, const SkDPoint& c, double t1, double t2) const {
    SkASSERT(t1 != t2);
    SkDPoint b;
    SkDQuad sub = subDivide(t1, t2);
    SkDLine b0 = {{a, sub[1] + (a - sub[0])}};
    SkDLine b1 = {{c, sub[1] + (c - sub[2])}};
    SkIntersections i;
    i.intersectRay(b0, b1);
    if (i.used() == 1 && i[0][0] >= 0 && i[1][0] >= 0) {
        b = i.pt(0);
    } else {
        SkASSERT(i.used() <= 2);
        b = SkDPoint::Mid(b0[1], b1[1]);
    }
    if (t1 == 0 || t2 == 0) {
        align(0, &b);
    }
    if (t1 == 1 || t2 == 1) {
        align(2, &b);
    }
    if (AlmostBequalUlps(b.fX, a.fX)) {
        b.fX = a.fX;
    } else if (AlmostBequalUlps(b.fX, c.fX)) {
        b.fX = c.fX;
    }
    if (AlmostBequalUlps(b.fY, a.fY)) {
        b.fY = a.fY;
    } else if (AlmostBequalUlps(b.fY, c.fY)) {
        b.fY = c.fY;
    }
    return b;
}
Example #4
0
SkDPoint SkDQuad::subDivide(const SkDPoint& a, const SkDPoint& c, double t1, double t2) const {
    SkASSERT(t1 != t2);
    SkDPoint b;
#if 0
    // this approach assumes that the control point computed directly is accurate enough
    double dx = interp_quad_coords(&fPts[0].fX, (t1 + t2) / 2);
    double dy = interp_quad_coords(&fPts[0].fY, (t1 + t2) / 2);
    b.fX = 2 * dx - (a.fX + c.fX) / 2;
    b.fY = 2 * dy - (a.fY + c.fY) / 2;
#else
    SkDQuad sub = subDivide(t1, t2);
    SkDLine b0 = {{a, sub[1] + (a - sub[0])}};
    SkDLine b1 = {{c, sub[1] + (c - sub[2])}};
    SkIntersections i;
    i.intersectRay(b0, b1);
    if (i.used() == 1 && i[0][0] >= 0 && i[1][0] >= 0) {
        b = i.pt(0);
    } else {
        SkASSERT(i.used() <= 2);
        b = SkDPoint::Mid(b0[1], b1[1]);
    }
#endif
    if (t1 == 0 || t2 == 0) {
        align(0, &b);
    }
    if (t1 == 1 || t2 == 1) {
        align(2, &b);
    }
    if (AlmostBequalUlps(b.fX, a.fX)) {
        b.fX = a.fX;
    } else if (AlmostBequalUlps(b.fX, c.fX)) {
        b.fX = c.fX;
    }
    if (AlmostBequalUlps(b.fY, a.fY)) {
        b.fY = a.fY;
    } else if (AlmostBequalUlps(b.fY, c.fY)) {
        b.fY = c.fY;
    }
    return b;
}