diff options
author | reed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2009-11-17 19:39:51 +0000 |
---|---|---|
committer | reed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2009-11-17 19:39:51 +0000 |
commit | 3a0cd7f0e80115a8cf525c9e0cf231df06d30a42 (patch) | |
tree | 7aece44fddaf812b890031da281059789478010a /src/core/SkQuadClipper.cpp | |
parent | 77f0ef726f1f8b6769ed2509171afce8bac00b23 (diff) |
add explicit clamping after chopping w/ t to ensure we're in the clip
git-svn-id: http://skia.googlecode.com/svn/trunk@430 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/core/SkQuadClipper.cpp')
-rw-r--r-- | src/core/SkQuadClipper.cpp | 91 |
1 files changed, 79 insertions, 12 deletions
diff --git a/src/core/SkQuadClipper.cpp b/src/core/SkQuadClipper.cpp index 9d76298cae..5abbe8e4b2 100644 --- a/src/core/SkQuadClipper.cpp +++ b/src/core/SkQuadClipper.cpp @@ -17,6 +17,22 @@ #include "SkQuadClipper.h" #include "SkGeometry.h" +static bool quick_reject(const SkRect& bounds, const SkRect& clip) { + return bounds.fTop >= clip.fBottom || bounds.fBottom <= clip.fTop; +} + +static inline void clamp_le(SkScalar& value, SkScalar max) { + if (value > max) { + value = max; + } +} + +static inline void clamp_ge(SkScalar& value, SkScalar min) { + if (value < min) { + value = min; + } +} + static bool chopMonoQuadAt(SkScalar c0, SkScalar c1, SkScalar c2, SkScalar target, SkScalar* t) { /* Solve F(t) = y where F(t) := [0](1-t)^2 + 2[1]t(1-t) + [2]t^2 @@ -132,6 +148,8 @@ static void chop_quad_in_Y(SkPoint pts[3], const SkRect& clip) { 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 { @@ -149,6 +167,8 @@ static void chop_quad_in_Y(SkPoint pts[3], const SkRect& clip) { 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 { @@ -223,6 +243,8 @@ void SkQuadClipper2::clipMonoQuad(const SkPoint srcPts[3], const SkRect& clip) { if (chopMonoQuadAtX(pts, clip.fLeft, &t)) { SkChopQuadAt(pts, tmp, t); this->appendVLine(clip.fLeft, tmp[0].fY, tmp[2].fY, reverse); + clamp_ge(tmp[2].fX, clip.fLeft); + clamp_ge(tmp[3].fX, clip.fLeft); pts[0] = tmp[2]; pts[1] = tmp[3]; } else { @@ -236,6 +258,8 @@ void SkQuadClipper2::clipMonoQuad(const SkPoint srcPts[3], const SkRect& clip) { if (pts[2].fX > clip.fRight) { if (chopMonoQuadAtX(pts, clip.fRight, &t)) { SkChopQuadAt(pts, tmp, t); + clamp_le(tmp[1].fX, clip.fRight); + clamp_le(tmp[2].fX, clip.fRight); this->appendQuad(tmp, reverse); this->appendVLine(clip.fRight, tmp[2].fY, tmp[4].fY, reverse); } else { @@ -248,21 +272,14 @@ void SkQuadClipper2::clipMonoQuad(const SkPoint srcPts[3], const SkRect& clip) { } } -static bool quick_reject_quad(const SkPoint srcPts[3], const SkRect& clip) { - return (srcPts[0].fY <= clip.fTop && - srcPts[1].fY <= clip.fTop && - srcPts[2].fY <= clip.fTop) - || - (srcPts[0].fY >= clip.fBottom && - srcPts[1].fY >= clip.fBottom && - srcPts[2].fY >= clip.fBottom); -} - bool SkQuadClipper2::clipQuad(const SkPoint srcPts[3], const SkRect& clip) { fCurrPoint = fPoints; fCurrVerb = fVerbs; - if (!quick_reject_quad(srcPts, clip)) { + SkRect bounds; + bounds.set(srcPts, 3); + + if (!quick_reject(bounds, clip)) { SkPoint monoY[5]; int countY = SkChopQuadAtYExtrema(srcPts, monoY); for (int y = 0; y <= countY; y++) { @@ -283,6 +300,38 @@ bool SkQuadClipper2::clipQuad(const SkPoint srcPts[3], const SkRect& clip) { return SkPath::kDone_Verb != fVerbs[0]; } +/////////////////////////////////////////////////////////////////////////////// + +bool SkQuadClipper2::clipCubic(const SkPoint srcPts[4], const SkRect& clip) { + fCurrPoint = fPoints; + fCurrVerb = fVerbs; + + SkRect bounds; + bounds.set(srcPts, 4); + + if (!quick_reject(bounds, clip)) { + SkPoint monoY[5]; + int countY = SkChopQuadAtYExtrema(srcPts, monoY); + for (int y = 0; y <= countY; y++) { + SkPoint monoX[5]; + int countX = SkChopQuadAtXExtrema(&monoY[y * 2], monoX); + SkASSERT(countY + countX <= 3); + for (int x = 0; x <= countX; x++) { + this->clipMonoQuad(&monoX[x * 2], clip); + SkASSERT(fCurrVerb - fVerbs < kMaxVerbs); + SkASSERT(fCurrPoint - fPoints <= kMaxPoints); + } + } + } + + *fCurrVerb = SkPath::kDone_Verb; + fCurrPoint = fPoints; + fCurrVerb = fVerbs; + return SkPath::kDone_Verb != fVerbs[0]; +} + +/////////////////////////////////////////////////////////////////////////////// + void SkQuadClipper2::appendVLine(SkScalar x, SkScalar y0, SkScalar y1, bool reverse) { *fCurrVerb++ = SkPath::kLine_Verb; @@ -297,7 +346,7 @@ void SkQuadClipper2::appendVLine(SkScalar x, SkScalar y0, SkScalar y1, void SkQuadClipper2::appendQuad(const SkPoint pts[3], bool reverse) { *fCurrVerb++ = SkPath::kQuad_Verb; - + if (reverse) { fCurrPoint[0] = pts[2]; fCurrPoint[2] = pts[0]; @@ -309,6 +358,19 @@ void SkQuadClipper2::appendQuad(const SkPoint pts[3], bool reverse) { fCurrPoint += 3; } +void SkQuadClipper2::appendCubic(const SkPoint pts[4], bool reverse) { + *fCurrVerb++ = SkPath::kCubic_Verb; + + if (reverse) { + for (int i = 0; i < 4; i++) { + fCurrPoint[i] = pts[3 - i]; + } + } else { + memcpy(fCurrPoint, pts, 4 * sizeof(SkPoint)); + } + fCurrPoint += 4; +} + SkPath::Verb SkQuadClipper2::next(SkPoint pts[]) { SkPath::Verb verb = *fCurrVerb; @@ -323,6 +385,11 @@ SkPath::Verb SkQuadClipper2::next(SkPoint pts[]) { fCurrPoint += 3; fCurrVerb += 1; break; + case SkPath::kCubic_Verb: + memcpy(pts, fCurrPoint, 4 * sizeof(SkPoint)); + fCurrPoint += 4; + fCurrVerb += 1; + break; case SkPath::kDone_Verb: break; default: |