1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/core/SkQuadClipper.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,114 @@ 1.4 +/* 1.5 + * Copyright 2009 The Android Open Source Project 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license that can be 1.8 + * found in the LICENSE file. 1.9 + */ 1.10 + 1.11 +#include "SkQuadClipper.h" 1.12 +#include "SkGeometry.h" 1.13 + 1.14 +SkQuadClipper::SkQuadClipper() { 1.15 + fClip.setEmpty(); 1.16 +} 1.17 + 1.18 +void SkQuadClipper::setClip(const SkIRect& clip) { 1.19 + // conver to scalars, since that's where we'll see the points 1.20 + fClip.set(clip); 1.21 +} 1.22 + 1.23 +/////////////////////////////////////////////////////////////////////////////// 1.24 + 1.25 +static bool chopMonoQuadAt(SkScalar c0, SkScalar c1, SkScalar c2, 1.26 + SkScalar target, SkScalar* t) { 1.27 + /* Solve F(t) = y where F(t) := [0](1-t)^2 + 2[1]t(1-t) + [2]t^2 1.28 + * We solve for t, using quadratic equation, hence we have to rearrange 1.29 + * our cooefficents to look like At^2 + Bt + C 1.30 + */ 1.31 + SkScalar A = c0 - c1 - c1 + c2; 1.32 + SkScalar B = 2*(c1 - c0); 1.33 + SkScalar C = c0 - target; 1.34 + 1.35 + SkScalar roots[2]; // we only expect one, but make room for 2 for safety 1.36 + int count = SkFindUnitQuadRoots(A, B, C, roots); 1.37 + if (count) { 1.38 + *t = roots[0]; 1.39 + return true; 1.40 + } 1.41 + return false; 1.42 +} 1.43 + 1.44 +static bool chopMonoQuadAtY(SkPoint pts[3], SkScalar y, SkScalar* t) { 1.45 + return chopMonoQuadAt(pts[0].fY, pts[1].fY, pts[2].fY, y, t); 1.46 +} 1.47 + 1.48 +/////////////////////////////////////////////////////////////////////////////// 1.49 + 1.50 +/* If we somehow returned the fact that we had to flip the pts in Y, we could 1.51 + communicate that to setQuadratic, and then avoid having to flip it back 1.52 + here (only to have setQuadratic do the flip again) 1.53 + */ 1.54 +bool SkQuadClipper::clipQuad(const SkPoint srcPts[3], SkPoint dst[3]) { 1.55 + bool reverse; 1.56 + 1.57 + // we need the data to be monotonically increasing in Y 1.58 + if (srcPts[0].fY > srcPts[2].fY) { 1.59 + dst[0] = srcPts[2]; 1.60 + dst[1] = srcPts[1]; 1.61 + dst[2] = srcPts[0]; 1.62 + reverse = true; 1.63 + } else { 1.64 + memcpy(dst, srcPts, 3 * sizeof(SkPoint)); 1.65 + reverse = false; 1.66 + } 1.67 + 1.68 + // are we completely above or below 1.69 + const SkScalar ctop = fClip.fTop; 1.70 + const SkScalar cbot = fClip.fBottom; 1.71 + if (dst[2].fY <= ctop || dst[0].fY >= cbot) { 1.72 + return false; 1.73 + } 1.74 + 1.75 + SkScalar t; 1.76 + SkPoint tmp[5]; // for SkChopQuadAt 1.77 + 1.78 + // are we partially above 1.79 + if (dst[0].fY < ctop) { 1.80 + if (chopMonoQuadAtY(dst, ctop, &t)) { 1.81 + // take the 2nd chopped quad 1.82 + SkChopQuadAt(dst, tmp, t); 1.83 + dst[0] = tmp[2]; 1.84 + dst[1] = tmp[3]; 1.85 + } else { 1.86 + // if chopMonoQuadAtY failed, then we may have hit inexact numerics 1.87 + // so we just clamp against the top 1.88 + for (int i = 0; i < 3; i++) { 1.89 + if (dst[i].fY < ctop) { 1.90 + dst[i].fY = ctop; 1.91 + } 1.92 + } 1.93 + } 1.94 + } 1.95 + 1.96 + // are we partially below 1.97 + if (dst[2].fY > cbot) { 1.98 + if (chopMonoQuadAtY(dst, cbot, &t)) { 1.99 + SkChopQuadAt(dst, tmp, t); 1.100 + dst[1] = tmp[1]; 1.101 + dst[2] = tmp[2]; 1.102 + } else { 1.103 + // if chopMonoQuadAtY failed, then we may have hit inexact numerics 1.104 + // so we just clamp against the bottom 1.105 + for (int i = 0; i < 3; i++) { 1.106 + if (dst[i].fY > cbot) { 1.107 + dst[i].fY = cbot; 1.108 + } 1.109 + } 1.110 + } 1.111 + } 1.112 + 1.113 + if (reverse) { 1.114 + SkTSwap<SkPoint>(dst[0], dst[2]); 1.115 + } 1.116 + return true; 1.117 +}