diff options
author | Baligh Uddin <baligh@google.com> | 2013-11-01 16:01:55 -0700 |
---|---|---|
committer | Baligh Uddin <baligh@google.com> | 2013-11-01 16:01:55 -0700 |
commit | ec502fb532582da0f3141560bc451df3902ce463 (patch) | |
tree | bfd8e692b73dee4749734ca317b4707988dfae3a /core/SkQuadClipper.cpp | |
parent | 5588ded0ae11d6fa36e1771747b82b7831db906b (diff) | |
parent | 53a521c76400a3e6d64dc96396390b746ec1e48e (diff) | |
download | src-ec502fb532582da0f3141560bc451df3902ce463.tar.gz |
Merge remote-tracking branch 'origin/kitkat-dev'chromium_org-pre-replicationidea133
Diffstat (limited to 'core/SkQuadClipper.cpp')
-rw-r--r-- | core/SkQuadClipper.cpp | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/core/SkQuadClipper.cpp b/core/SkQuadClipper.cpp new file mode 100644 index 00000000..a67a23f9 --- /dev/null +++ b/core/SkQuadClipper.cpp @@ -0,0 +1,128 @@ + +/* + * Copyright 2009 The Android Open Source Project + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + + +#include "SkQuadClipper.h" +#include "SkGeometry.h" + +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; + } +} + +SkQuadClipper::SkQuadClipper() { + fClip.setEmpty(); +} + +void SkQuadClipper::setClip(const SkIRect& clip) { + // conver to scalars, since that's where we'll see the points + fClip.set(clip); +} + +/////////////////////////////////////////////////////////////////////////////// + +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 + * We solve for t, using quadratic equation, hence we have to rearrange + * our cooefficents to look like At^2 + Bt + C + */ + SkScalar A = c0 - c1 - c1 + c2; + SkScalar B = 2*(c1 - c0); + SkScalar C = c0 - target; + + SkScalar roots[2]; // we only expect one, but make room for 2 for safety + int count = SkFindUnitQuadRoots(A, B, C, roots); + if (count) { + *t = roots[0]; + return true; + } + return false; +} + +static bool chopMonoQuadAtY(SkPoint pts[3], SkScalar y, SkScalar* t) { + return chopMonoQuadAt(pts[0].fY, pts[1].fY, pts[2].fY, y, t); +} + +/////////////////////////////////////////////////////////////////////////////// + +/* 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 increasing 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) { + if (chopMonoQuadAtY(dst, ctop, &t)) { + // take the 2nd chopped quad + SkChopQuadAt(dst, tmp, t); + dst[0] = tmp[2]; + dst[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 (dst[i].fY < ctop) { + dst[i].fY = ctop; + } + } + } + } + + // are we partially below + if (dst[2].fY > cbot) { + if (chopMonoQuadAtY(dst, cbot, &t)) { + SkChopQuadAt(dst, tmp, t); + dst[1] = tmp[1]; + dst[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 (dst[i].fY > cbot) { + dst[i].fY = cbot; + } + } + } + } + + if (reverse) { + SkTSwap<SkPoint>(dst[0], dst[2]); + } + return true; +} |