Ejemplo n.º 1
0
static int check_linear(const Cubic& cubic, Cubic& reduction,
        int minX, int maxX, int minY, int maxY) {
    int startIndex = 0;
    int endIndex = 3;
    while (cubic[startIndex].approximatelyEqual(cubic[endIndex])) {
        --endIndex;
        if (endIndex == 0) {
            printf("%s shouldn't get here if all four points are about equal", __FUNCTION__);
            assert(0);
        }
    }
    if (!isLinear(cubic, startIndex, endIndex)) {
        return 0;
    }
    // four are colinear: return line formed by outside
    reduction[0] = cubic[0];
    reduction[1] = cubic[3];
    int sameSide1;
    int sameSide2;
    bool useX = cubic[maxX].x - cubic[minX].x >= cubic[maxY].y - cubic[minY].y;
    if (useX) {
        sameSide1 = sign(cubic[0].x - cubic[1].x) + sign(cubic[3].x - cubic[1].x);
        sameSide2 = sign(cubic[0].x - cubic[2].x) + sign(cubic[3].x - cubic[2].x);
    } else {
        sameSide1 = sign(cubic[0].y - cubic[1].y) + sign(cubic[3].y - cubic[1].y);
        sameSide2 = sign(cubic[0].y - cubic[2].y) + sign(cubic[3].y - cubic[2].y);
    }
    if (sameSide1 == sameSide2 && (sameSide1 & 3) != 2) {
        return 2;
    }
    double tValues[2];
    int roots;
    if (useX) {
        roots = findExtrema(cubic[0].x, cubic[1].x, cubic[2].x, cubic[3].x, tValues);
    } else {
        roots = findExtrema(cubic[0].y, cubic[1].y, cubic[2].y, cubic[3].y, tValues);
    }
    for (int index = 0; index < roots; ++index) {
        _Point extrema;
        extrema.x = interp_cubic_coords(&cubic[0].x, tValues[index]);
        extrema.y = interp_cubic_coords(&cubic[0].y, tValues[index]);
        // sameSide > 0 means mid is smaller than either [0] or [3], so replace smaller
        int replace;
        if (useX) {
            if (extrema.x < cubic[0].x ^ extrema.x < cubic[3].x) {
                continue;
            }
            replace = (extrema.x < cubic[0].x | extrema.x < cubic[3].x)
                    ^ cubic[0].x < cubic[3].x;
        } else {
            if (extrema.y < cubic[0].y ^ extrema.y < cubic[3].y) {
                continue;
            }
            replace = (extrema.y < cubic[0].y | extrema.y < cubic[3].y)
                    ^ cubic[0].y < cubic[3].y;
        }
        reduction[replace] = extrema;
    }
    return 2;
}
void SkChopCubicAt(const SkPoint src[4], SkPoint dst[7], SkScalar t)
{
    SkASSERT(t > 0 && t < SK_Scalar1);

    interp_cubic_coords(&src[0].fX, &dst[0].fX, t);
    interp_cubic_coords(&src[0].fY, &dst[0].fY, t);
}
Ejemplo n.º 3
0
SkDCubic SkDCubic::subDivide(double t1, double t2) const {
    if (t1 == 0 || t2 == 1) {
        if (t1 == 0 && t2 == 1) {
            return *this;
        }
        SkDCubicPair pair = chopAt(t1 == 0 ? t2 : t1);
        SkDCubic dst = t1 == 0 ? pair.first() : pair.second();
        return dst;
    }
    SkDCubic dst;
    double ax = dst[0].fX = interp_cubic_coords(&fPts[0].fX, t1);
    double ay = dst[0].fY = interp_cubic_coords(&fPts[0].fY, t1);
    double ex = interp_cubic_coords(&fPts[0].fX, (t1*2+t2)/3);
    double ey = interp_cubic_coords(&fPts[0].fY, (t1*2+t2)/3);
    double fx = interp_cubic_coords(&fPts[0].fX, (t1+t2*2)/3);
    double fy = interp_cubic_coords(&fPts[0].fY, (t1+t2*2)/3);
    double dx = dst[3].fX = interp_cubic_coords(&fPts[0].fX, t2);
    double dy = dst[3].fY = interp_cubic_coords(&fPts[0].fY, t2);
    double mx = ex * 27 - ax * 8 - dx;
    double my = ey * 27 - ay * 8 - dy;
    double nx = fx * 27 - ax - dx * 8;
    double ny = fy * 27 - ay - dy * 8;
    /* bx = */ dst[1].fX = (mx * 2 - nx) / 18;
    /* by = */ dst[1].fY = (my * 2 - ny) / 18;
    /* cx = */ dst[2].fX = (nx * 2 - mx) / 18;
    /* cy = */ dst[2].fY = (ny * 2 - my) / 18;
    // FIXME: call align() ?
    return dst;
}
Ejemplo n.º 4
0
void chop_at(const Cubic& src, CubicPair& dst, double t)
{
    if (t == 0.5) {
        dst.pts[0] = src[0];
        dst.pts[1].x = (src[0].x + src[1].x) / 2;
        dst.pts[1].y = (src[0].y + src[1].y) / 2;
        dst.pts[2].x = (src[0].x + 2 * src[1].x + src[2].x) / 4;
        dst.pts[2].y = (src[0].y + 2 * src[1].y + src[2].y) / 4;
        dst.pts[3].x = (src[0].x + 3 * (src[1].x + src[2].x) + src[3].x) / 8;
        dst.pts[3].y = (src[0].y + 3 * (src[1].y + src[2].y) + src[3].y) / 8;
        dst.pts[4].x = (src[1].x + 2 * src[2].x + src[3].x) / 4;
        dst.pts[4].y = (src[1].y + 2 * src[2].y + src[3].y) / 4;
        dst.pts[5].x = (src[2].x + src[3].x) / 2;
        dst.pts[5].y = (src[2].y + src[3].y) / 2;
        dst.pts[6] = src[3];
        return;
    }
    interp_cubic_coords(&src[0].x, &dst.pts[0].x, t);
    interp_cubic_coords(&src[0].y, &dst.pts[0].y, t);
}
Ejemplo n.º 5
0
void SkDCubic::subDivide(const SkDPoint& a, const SkDPoint& d,
                         double t1, double t2, SkDPoint dst[2]) const {
    SkASSERT(t1 != t2);
#if 0
    double ex = interp_cubic_coords(&fPts[0].fX, (t1 * 2 + t2) / 3);
    double ey = interp_cubic_coords(&fPts[0].fY, (t1 * 2 + t2) / 3);
    double fx = interp_cubic_coords(&fPts[0].fX, (t1 + t2 * 2) / 3);
    double fy = interp_cubic_coords(&fPts[0].fY, (t1 + t2 * 2) / 3);
    double mx = ex * 27 - a.fX * 8 - d.fX;
    double my = ey * 27 - a.fY * 8 - d.fY;
    double nx = fx * 27 - a.fX - d.fX * 8;
    double ny = fy * 27 - a.fY - d.fY * 8;
    /* bx = */ dst[0].fX = (mx * 2 - nx) / 18;
    /* by = */ dst[0].fY = (my * 2 - ny) / 18;
    /* cx = */ dst[1].fX = (nx * 2 - mx) / 18;
    /* cy = */ dst[1].fY = (ny * 2 - my) / 18;
#else
    // this approach assumes that the control points computed directly are accurate enough
    SkDCubic sub = subDivide(t1, t2);
    dst[0] = sub[1] + (a - sub[0]);
    dst[1] = sub[2] + (d - sub[3]);
#endif
    if (t1 == 0 || t2 == 0) {
        align(0, 1, t1 == 0 ? &dst[0] : &dst[1]);
    }
    if (t1 == 1 || t2 == 1) {
        align(3, 2, t1 == 1 ? &dst[0] : &dst[1]);
    }
    if (AlmostBequalUlps(dst[0].fX, a.fX)) {
        dst[0].fX = a.fX;
    }
    if (AlmostBequalUlps(dst[0].fY, a.fY)) {
        dst[0].fY = a.fY;
    }
    if (AlmostBequalUlps(dst[1].fX, d.fX)) {
        dst[1].fX = d.fX;
    }
    if (AlmostBequalUlps(dst[1].fY, d.fY)) {
        dst[1].fY = d.fY;
    }
}
Ejemplo n.º 6
0
SkDCubicPair SkDCubic::chopAt(double t) const {
    SkDCubicPair dst;
    if (t == 0.5) {
        dst.pts[0] = fPts[0];
        dst.pts[1].fX = (fPts[0].fX + fPts[1].fX) / 2;
        dst.pts[1].fY = (fPts[0].fY + fPts[1].fY) / 2;
        dst.pts[2].fX = (fPts[0].fX + 2 * fPts[1].fX + fPts[2].fX) / 4;
        dst.pts[2].fY = (fPts[0].fY + 2 * fPts[1].fY + fPts[2].fY) / 4;
        dst.pts[3].fX = (fPts[0].fX + 3 * (fPts[1].fX + fPts[2].fX) + fPts[3].fX) / 8;
        dst.pts[3].fY = (fPts[0].fY + 3 * (fPts[1].fY + fPts[2].fY) + fPts[3].fY) / 8;
        dst.pts[4].fX = (fPts[1].fX + 2 * fPts[2].fX + fPts[3].fX) / 4;
        dst.pts[4].fY = (fPts[1].fY + 2 * fPts[2].fY + fPts[3].fY) / 4;
        dst.pts[5].fX = (fPts[2].fX + fPts[3].fX) / 2;
        dst.pts[5].fY = (fPts[2].fY + fPts[3].fY) / 2;
        dst.pts[6] = fPts[3];
        return dst;
    }
    interp_cubic_coords(&fPts[0].fX, &dst.pts[0].fX, t);
    interp_cubic_coords(&fPts[0].fY, &dst.pts[0].fY, t);
    return dst;
}
Ejemplo n.º 7
0
void sub_divide(const Cubic& src, double t1, double t2, Cubic& dst) {
    double ax = dst[0].x = interp_cubic_coords(&src[0].x, t1);
    double ay = dst[0].y = interp_cubic_coords(&src[0].y, t1);
    double ex = interp_cubic_coords(&src[0].x, (t1*2+t2)/3);
    double ey = interp_cubic_coords(&src[0].y, (t1*2+t2)/3);
    double fx = interp_cubic_coords(&src[0].x, (t1+t2*2)/3);
    double fy = interp_cubic_coords(&src[0].y, (t1+t2*2)/3);
    double dx = dst[3].x = interp_cubic_coords(&src[0].x, t2);
    double dy = dst[3].y = interp_cubic_coords(&src[0].y, t2);
    double mx = ex * 27 - ax * 8 - dx;
    double my = ey * 27 - ay * 8 - dy;
    double nx = fx * 27 - ax - dx * 8;
    double ny = fy * 27 - ay - dy * 8;
    /* bx = */ dst[1].x = (mx * 2 - nx) / 18;
    /* by = */ dst[1].y = (my * 2 - ny) / 18;
    /* cx = */ dst[2].x = (nx * 2 - mx) / 18;
    /* cy = */ dst[2].y = (ny * 2 - my) / 18;
}
Ejemplo n.º 8
0
static int horizontal_line(const Cubic& cubic, Cubic& reduction) {
    double tValues[2];
    reduction[0] = cubic[0];
    reduction[1] = cubic[3];
    int smaller = reduction[1].x > reduction[0].x;
    int larger = smaller ^ 1;
    int roots = findExtrema(cubic[0].x, cubic[1].x, cubic[2].x, cubic[3].x, tValues);
    for (int index = 0; index < roots; ++index) {
        double xExtrema = interp_cubic_coords(&cubic[0].x, tValues[index]);
        if (reduction[smaller].x > xExtrema) {
            reduction[smaller].x = xExtrema;
            continue;
        }
        if (reduction[larger].x < xExtrema) {
            reduction[larger].x = xExtrema;
        }
    }
    return 2;
}
Ejemplo n.º 9
0
static int vertical_line(const Cubic& cubic, Cubic& reduction) {
    double tValues[2];
    reduction[0] = cubic[0];
    reduction[1] = cubic[3];
    int smaller = reduction[1].y > reduction[0].y;
    int larger = smaller ^ 1;
    int roots = findExtrema(cubic[0].y, cubic[1].y, cubic[2].y, cubic[3].y, tValues);
    for (int index = 0; index < roots; ++index) {
        double yExtrema = interp_cubic_coords(&cubic[0].y, tValues[index]);
        if (reduction[smaller].y > yExtrema) {
            reduction[smaller].y = yExtrema;
            continue;
        }
        if (reduction[larger].y < yExtrema) {
            reduction[larger].y = yExtrema;
        }
    }
    return 2;
}
Ejemplo n.º 10
0
void chop_at(const Cubic& src, CubicPair& dst, double t)
{
    interp_cubic_coords(&src[0].x, &dst.pts[0].x, t);
    interp_cubic_coords(&src[0].y, &dst.pts[0].y, t);
}
Ejemplo n.º 11
0
static int check_linear(const Cubic& cubic, Cubic& reduction,
        int minX, int maxX, int minY, int maxY) {
    int startIndex = 0;
    int endIndex = 3;
    while (cubic[startIndex].approximatelyEqual(cubic[endIndex])) {
        --endIndex;
        if (endIndex == 0) {
            printf("%s shouldn't get here if all four points are about equal", __FUNCTION__);
            assert(0);
        }
    }
    LineParameters lineParameters;
    lineParameters.cubicEndPoints(cubic, startIndex, endIndex);
    double normalSquared = lineParameters.normalSquared();
    double distance[2]; // distance is not normalized
    int mask = other_two(startIndex, endIndex);
    int inner1 = startIndex ^ mask;
    int inner2 = endIndex ^ mask;
    lineParameters.controlPtDistance(cubic, inner1, inner2, distance);
    double limit = normalSquared * SquaredEpsilon;
    int index;
    for (index = 0; index < 2; ++index) {
        double distSq = distance[index];
        distSq *= distSq;
        if (distSq > limit) {
            return 0;
        }
    }
    // four are colinear: return line formed by outside
    reduction[0] = cubic[0];
    reduction[1] = cubic[3];
    int sameSide1;
    int sameSide2;
    bool useX = cubic[maxX].x - cubic[minX].x >= cubic[maxY].y - cubic[minY].y;
    if (useX) {
        sameSide1 = sign(cubic[0].x - cubic[1].x) + sign(cubic[3].x - cubic[1].x);
        sameSide2 = sign(cubic[0].x - cubic[2].x) + sign(cubic[3].x - cubic[2].x);
    } else {
        sameSide1 = sign(cubic[0].y - cubic[1].y) + sign(cubic[3].y - cubic[1].y);
        sameSide2 = sign(cubic[0].y - cubic[2].y) + sign(cubic[3].y - cubic[2].y);
    }
    if (sameSide1 == sameSide2 && (sameSide1 & 3) != 2) {
        return 2;
    }
    double tValues[2];
    int roots;
    if (useX) {
        roots = SkFindCubicExtrema(cubic[0].x, cubic[1].x, cubic[2].x, cubic[3].x, tValues);
    } else {
        roots = SkFindCubicExtrema(cubic[0].y, cubic[1].y, cubic[2].y, cubic[3].y, tValues);
    }
    for (index = 0; index < roots; ++index) {
        _Point extrema;
        extrema.x = interp_cubic_coords(&cubic[0].x, tValues[index]);
        extrema.y = interp_cubic_coords(&cubic[0].y, tValues[index]);
        // sameSide > 0 means mid is smaller than either [0] or [3], so replace smaller
        int replace;
        if (useX) {
            if (extrema.x < cubic[0].x ^ extrema.x < cubic[3].x) {
                continue;
            }
            replace = (extrema.x < cubic[0].x | extrema.x < cubic[3].x)
                    ^ cubic[0].x < cubic[3].x;
        } else {
            if (extrema.y < cubic[0].y ^ extrema.y < cubic[3].y) {
                continue;
            }
            replace = (extrema.y < cubic[0].y | extrema.y < cubic[3].y)
                    ^ cubic[0].y < cubic[3].y;
        }
        reduction[replace] = extrema;
    }
    return 2;
}