示例#1
0
// srcPts[] must be monotonic in X and Y
void SkEdgeClipper::clipMonoCubic(const SkPoint src[4], const SkRect& clip) {
    SkPoint pts[4];
    bool reverse = sort_increasing_Y(pts, src, 4);

    // are we completely above or below
    if (pts[3].fY <= clip.fTop || pts[0].fY >= clip.fBottom) {
        return;
    }

    // Now chop so that pts is contained within clip in Y
    chop_cubic_in_Y(pts, clip);

    if (pts[0].fX > pts[3].fX) {
        SkTSwap<SkPoint>(pts[0], pts[3]);
        SkTSwap<SkPoint>(pts[1], pts[2]);
        reverse = !reverse;
    }

    // Now chop in X has needed, and record the segments

    if (pts[3].fX <= clip.fLeft) {  // wholly to the left
        this->appendVLine(clip.fLeft, pts[0].fY, pts[3].fY, reverse);
        return;
    }
    if (pts[0].fX >= clip.fRight) {  // wholly to the right
        if (!this->canCullToTheRight()) {
            this->appendVLine(clip.fRight, pts[0].fY, pts[3].fY, reverse);
        }
        return;
    }

    // are we partially to the left
    if (pts[0].fX < clip.fLeft) {
        SkPoint tmp[7];
        chop_mono_cubic_at_x(pts, clip.fLeft, tmp);
        this->appendVLine(clip.fLeft, tmp[0].fY, tmp[3].fY, reverse);

        // tmp[3, 4].fX should all be to the right of clip.fLeft.
        // Since we can't trust the numerics of
        // the chopper, we force those conditions now
        tmp[3].fX = clip.fLeft;
        clamp_ge(tmp[4].fX, clip.fLeft);

        pts[0] = tmp[3];
        pts[1] = tmp[4];
        pts[2] = tmp[5];
    }

    // are we partially to the right
    if (pts[3].fX > clip.fRight) {
        SkPoint tmp[7];
        chop_mono_cubic_at_x(pts, clip.fRight, tmp);
        tmp[3].fX = clip.fRight;
        clamp_le(tmp[2].fX, clip.fRight);

        this->appendCubic(tmp, reverse);
        this->appendVLine(clip.fRight, tmp[3].fY, tmp[6].fY, reverse);
    } else {    // wholly inside the clip
        this->appendCubic(pts, reverse);
    }
}
示例#2
0
// srcPts[] must be monotonic in X and Y
void SkEdgeClipper::clipMonoCubic(const SkPoint src[4], const SkRect& clip) {
    SkPoint pts[4];
    bool reverse = sort_increasing_Y(pts, src, 4);
    
    // are we completely above or below
    if (pts[3].fY <= clip.fTop || pts[0].fY >= clip.fBottom) {
        return;
    }

    // Now chop so that pts is contained within clip in Y
    chop_cubic_in_Y(pts, clip);

    if (pts[0].fX > pts[3].fX) {
        SkTSwap<SkPoint>(pts[0], pts[3]);
        SkTSwap<SkPoint>(pts[1], pts[2]);
        reverse = !reverse;
    }
    
    // Now chop in X has needed, and record the segments
    
    if (pts[3].fX <= clip.fLeft) {  // wholly to the left
        this->appendVLine(clip.fLeft, pts[0].fY, pts[3].fY, reverse);
        return;
    }
    if (pts[0].fX >= clip.fRight) {  // wholly to the right
        this->appendVLine(clip.fRight, pts[0].fY, pts[3].fY, reverse);
        return;
    }
    
    SkScalar t;
    SkPoint tmp[7];
    
    // are we partially to the left
    if (pts[0].fX < clip.fLeft) {
        if (chopMonoCubicAtX(pts, clip.fLeft, &t)) {
            SkChopCubicAt(pts, tmp, t);
            this->appendVLine(clip.fLeft, tmp[0].fY, tmp[3].fY, reverse);
            clamp_ge(tmp[3].fX, clip.fLeft);
            clamp_ge(tmp[4].fX, clip.fLeft);
            clamp_ge(tmp[5].fX, clip.fLeft);
            pts[0] = tmp[3];
            pts[1] = tmp[4];
            pts[2] = tmp[5];
        } else {
            // if chopMonocubicAtY failed, then we may have hit inexact numerics
            // so we just clamp against the left
            this->appendVLine(clip.fLeft, pts[0].fY, pts[3].fY, reverse);
            return;
        }
    }
    
    // are we partially to the right
    if (pts[3].fX > clip.fRight) {
        if (chopMonoCubicAtX(pts, clip.fRight, &t)) {
            SkChopCubicAt(pts, tmp, t);
            clamp_le(tmp[1].fX, clip.fRight);
            clamp_le(tmp[2].fX, clip.fRight);
            clamp_le(tmp[3].fX, clip.fRight);
            this->appendCubic(tmp, reverse);
            this->appendVLine(clip.fRight, tmp[3].fY, tmp[6].fY, reverse);
        } else {
            // if chopMonoCubicAtX failed, then we may have hit inexact numerics
            // so we just clamp against the right
            this->appendVLine(clip.fRight, pts[0].fY, pts[3].fY, reverse);
        }
    } else {    // wholly inside the clip
        this->appendCubic(pts, reverse);
    }
}
示例#3
0
// srcPts[] must be monotonic in X and Y
void SkEdgeClipper::clipMonoQuad(const SkPoint srcPts[3], const SkRect& clip) {
    SkPoint pts[3];
    bool reverse = sort_increasing_Y(pts, srcPts, 3);

    // are we completely above or below
    if (pts[2].fY <= clip.fTop || pts[0].fY >= clip.fBottom) {
        return;
    }

    // Now chop so that pts is contained within clip in Y
    chop_quad_in_Y(pts, clip);

    if (pts[0].fX > pts[2].fX) {
        SkTSwap<SkPoint>(pts[0], pts[2]);
        reverse = !reverse;
    }
    SkASSERT(pts[0].fX <= pts[1].fX);
    SkASSERT(pts[1].fX <= pts[2].fX);

    // Now chop in X has needed, and record the segments

    if (pts[2].fX <= clip.fLeft) {  // wholly to the left
        this->appendVLine(clip.fLeft, pts[0].fY, pts[2].fY, reverse);
        return;
    }
    if (pts[0].fX >= clip.fRight) {  // wholly to the right
        if (!this->canCullToTheRight()) {
            this->appendVLine(clip.fRight, pts[0].fY, pts[2].fY, reverse);
        }
        return;
    }

    SkScalar t;
    SkPoint tmp[5]; // for SkChopQuadAt

    // are we partially to the left
    if (pts[0].fX < clip.fLeft) {
        if (chopMonoQuadAtX(pts, clip.fLeft, &t)) {
            SkChopQuadAt(pts, tmp, t);
            this->appendVLine(clip.fLeft, tmp[0].fY, tmp[2].fY, reverse);
            // clamp to clean up imprecise numerics in the chop
            tmp[2].fX = clip.fLeft;
            clamp_ge(tmp[3].fX, clip.fLeft);

            pts[0] = tmp[2];
            pts[1] = tmp[3];
        } else {
            // if chopMonoQuadAtY failed, then we may have hit inexact numerics
            // so we just clamp against the left
            this->appendVLine(clip.fLeft, pts[0].fY, pts[2].fY, reverse);
            return;
        }
    }

    // are we partially to the right
    if (pts[2].fX > clip.fRight) {
        if (chopMonoQuadAtX(pts, clip.fRight, &t)) {
            SkChopQuadAt(pts, tmp, t);
            // clamp to clean up imprecise numerics in the chop
            clamp_le(tmp[1].fX, clip.fRight);
            tmp[2].fX = clip.fRight;

            this->appendQuad(tmp, reverse);
            this->appendVLine(clip.fRight, tmp[2].fY, tmp[4].fY, reverse);
        } else {
            // if chopMonoQuadAtY failed, then we may have hit inexact numerics
            // so we just clamp against the right
            this->appendVLine(clip.fRight, pts[0].fY, pts[2].fY, reverse);
        }
    } else {    // wholly inside the clip
        this->appendQuad(pts, reverse);
    }
}