Index: src/core/SkEdgeClipper.cpp |
diff --git a/src/core/SkEdgeClipper.cpp b/src/core/SkEdgeClipper.cpp |
index 96fac6121f317c59b1b5c0f63957517aa801b9fe..02fb4530fdf375ca866ab7f76f1c2997aa6e3b28 100644 |
--- a/src/core/SkEdgeClipper.cpp |
+++ b/src/core/SkEdgeClipper.cpp |
@@ -270,6 +270,34 @@ static void chop_cubic_in_Y(SkPoint pts[4], const SkRect& clip) { |
} |
} |
+static void chop_mono_cubic_at_x(SkPoint pts[4], SkScalar x, SkPoint tmp[7]) { |
reed1
2015/08/20 14:24:45
perhaps rename
pts -> src or orig
tmp -> dst or ch
|
+ if (SkChopMonoCubicAtX(pts, x, tmp)) { |
+ return; |
+ } |
+ SkScalar t = 0.5f; |
+ SkScalar lastT; |
+ SkScalar bestT SK_INIT_TO_AVOID_WARNING; |
+ SkScalar step = 0.25f; |
+ SkScalar D = pts[0].fX; |
+ SkScalar A = pts[3].fX + 3*(pts[1].fX - pts[2].fX) - D; |
+ SkScalar B = 3*(pts[2].fX - pts[1].fX - pts[1].fX + D); |
+ SkScalar C = 3*(pts[1].fX - D); |
+ x -= D; |
+ SkScalar closest = SK_ScalarMax; |
+ do { |
+ SkScalar loc = ((A * t + B) * t + C) * t; |
+ SkScalar dist = SkScalarAbs(loc - x); |
+ if (closest > dist) { |
+ closest = dist; |
+ bestT = t; |
+ } |
+ lastT = t; |
+ t += loc < x ? step : -step; |
+ step *= 0.5f; |
+ } while (closest > 0.25f && lastT != t); |
+ SkChopCubicAt(pts, tmp, bestT); |
+} |
+ |
// srcPts[] must be monotonic in X and Y |
void SkEdgeClipper::clipMonoCubic(const SkPoint src[4], const SkRect& clip) { |
SkPoint pts[4]; |
@@ -305,40 +333,29 @@ void SkEdgeClipper::clipMonoCubic(const SkPoint src[4], const SkRect& clip) { |
// are we partially to the left |
if (pts[0].fX < clip.fLeft) { |
SkPoint tmp[7]; |
- if (SkChopMonoCubicAtX(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]; |
- } 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; |
- } |
+ 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]; |
- if (SkChopMonoCubicAtX(pts, clip.fRight, tmp)) { |
- tmp[3].fX = clip.fRight; |
- clamp_le(tmp[2].fX, clip.fRight); |
+ 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 { |
- // 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); |
- } |
+ this->appendCubic(tmp, reverse); |
+ this->appendVLine(clip.fRight, tmp[3].fY, tmp[6].fY, reverse); |
} else { // wholly inside the clip |
this->appendCubic(pts, reverse); |
} |