示例#1
0
// Modify pts[] in place so that it is clipped in Y to the clip rect
static void chop_cubic_in_Y(SkPoint pts[4], const SkRect& clip) {
    SkScalar t;
    SkPoint tmp[7]; // for SkChopCubicAt
    
    // are we partially above
    if (pts[0].fY < clip.fTop) {
        if (chopMonoCubicAtY(pts, clip.fTop, &t)) {
            SkChopCubicAt(pts, tmp, t);
            // given the imprecision of computing t, we just slam our Y coord
            // to the top of the clip. This also saves us in the bad case where
            // the t was soooo bad that the entire segment could have been
            // below fBottom
            tmp[3].fY = clip.fTop;
            clamp_ge(tmp[4].fY, clip.fTop);
            clamp_ge(tmp[5].fY, clip.fTop);
            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 top
            for (int i = 0; i < 4; i++) {
                clamp_ge(pts[i].fY, clip.fTop);
            }
        }
    }
    
    // are we partially below
    if (pts[3].fY > clip.fBottom) {
        if (chopMonoCubicAtY(pts, clip.fBottom, &t)) {
            SkChopCubicAt(pts, tmp, t);
            clamp_le(tmp[1].fY, clip.fBottom);
            clamp_le(tmp[2].fY, clip.fBottom);
            clamp_le(tmp[3].fY, clip.fBottom);
            pts[1] = tmp[1];
            pts[2] = tmp[2];
            pts[3] = tmp[3];
        } else {
            // if chopMonoCubicAtY failed, then we may have hit inexact numerics
            // so we just clamp against the bottom
            for (int i = 0; i < 4; i++) {
                clamp_le(pts[i].fY, clip.fBottom);
            }
        }
    }
}
示例#2
0
// Modify pts[] in place so that it is clipped in Y to the clip rect
static void chop_quad_in_Y(SkPoint pts[3], const SkRect& clip) {
    SkScalar t;
    SkPoint tmp[5]; // for SkChopQuadAt

    // are we partially above
    if (pts[0].fY < clip.fTop) {
        if (chopMonoQuadAtY(pts, clip.fTop, &t)) {
            // take the 2nd chopped quad
            SkChopQuadAt(pts, tmp, t);
            clamp_ge(tmp[2].fY, clip.fTop);
            clamp_ge(tmp[3].fY, clip.fTop);
            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 top
            for (int i = 0; i < 3; i++) {
                if (pts[i].fY < clip.fTop) {
                    pts[i].fY = clip.fTop;
                }
            }
        }
    }
    
    // are we partially below
    if (pts[2].fY > clip.fBottom) {
        if (chopMonoQuadAtY(pts, clip.fBottom, &t)) {
            SkChopQuadAt(pts, tmp, t);
            clamp_le(tmp[1].fY, clip.fBottom);
            clamp_le(tmp[2].fY, clip.fBottom);
            pts[1] = tmp[1];
            pts[2] = tmp[2];
        } else {
            // if chopMonoQuadAtY failed, then we may have hit inexact numerics
            // so we just clamp against the bottom
            for (int i = 0; i < 3; i++) {
                if (pts[i].fY > clip.fBottom) {
                    pts[i].fY = clip.fBottom;
                }
            }
        }
    }
}
示例#3
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);
    }
}
示例#4
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);
    }
}
示例#5
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);
    }
}