// 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 to clean up imprecise numerics in the chop 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 to clean up imprecise numerics in the chop clamp_le(tmp[1].fY, clip.fBottom); 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; } } } } }
/* If we somehow returned the fact that we had to flip the pts in Y, we could communicate that to setQuadratic, and then avoid having to flip it back here (only to have setQuadratic do the flip again) */ bool SkQuadClipper::clipQuad(const SkPoint srcPts[3], SkPoint dst[3]) { bool reverse; // we need the data to be monotonically descending in Y if (srcPts[0].fY > srcPts[2].fY) { dst[0] = srcPts[2]; dst[1] = srcPts[1]; dst[2] = srcPts[0]; reverse = true; } else { memcpy(dst, srcPts, 3 * sizeof(SkPoint)); reverse = false; } // are we completely above or below const SkScalar ctop = fClip.fTop; const SkScalar cbot = fClip.fBottom; if (dst[2].fY <= ctop || dst[0].fY >= cbot) { return false; } SkScalar t; SkPoint tmp[5]; // for SkChopQuadAt // are we partially above if (dst[0].fY < ctop && chopMonoQuadAtY(dst, ctop, &t)) { SkChopQuadAt(dst, tmp, t); dst[0] = tmp[2]; dst[1] = tmp[3]; } // are we partially below if (dst[2].fY > cbot && chopMonoQuadAtY(dst, cbot, &t)) { SkChopQuadAt(dst, tmp, t); dst[1] = tmp[1]; dst[2] = tmp[2]; } if (reverse) { SkTSwap<SkPoint>(dst[0], dst[2]); } return true; }