// 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) { // are we partially above if (pts[0].fY < clip.fTop) { SkScalar t; if (chopMonoCubicAtY(pts, clip.fTop, &t)) { SkPoint tmp[7]; SkChopCubicAt(pts, tmp, t); // tmp[3, 4, 5].fY should all be to the below clip.fTop. // Since we can't trust the numerics of // the chopper, we force those conditions now 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) { SkScalar t; if (chopMonoCubicAtY(pts, clip.fBottom, &t)) { SkPoint tmp[7]; SkChopCubicAt(pts, tmp, t); tmp[3].fY = clip.fBottom; clamp_le(tmp[2].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); } } } }
bool SkCubicClipper::clipCubic(const SkPoint srcPts[4], SkPoint dst[4]) { bool reverse; // we need the data to be monotonically descending in Y if (srcPts[0].fY > srcPts[3].fY) { dst[0] = srcPts[3]; dst[1] = srcPts[2]; dst[2] = srcPts[1]; dst[3] = srcPts[0]; reverse = true; } else { memcpy(dst, srcPts, 4 * sizeof(SkPoint)); reverse = false; } // are we completely above or below const SkScalar ctop = fClip.fTop; const SkScalar cbot = fClip.fBottom; if (dst[3].fY <= ctop || dst[0].fY >= cbot) { return false; } SkScalar t; SkPoint tmp[7]; // for SkChopCubicAt // are we partially above if (dst[0].fY < ctop && chopMonoCubicAtY(dst, ctop, &t)) { SkChopCubicAt(dst, tmp, t); dst[0] = tmp[3]; dst[1] = tmp[4]; dst[2] = tmp[5]; } // are we partially below if (dst[3].fY > cbot && chopMonoCubicAtY(dst, cbot, &t)) { SkChopCubicAt(dst, tmp, t); dst[1] = tmp[1]; dst[2] = tmp[2]; dst[3] = tmp[3]; } if (reverse) { SkTSwap<SkPoint>(dst[0], dst[3]); SkTSwap<SkPoint>(dst[1], dst[2]); } return true; }
// 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); } } } }