aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/core/SkGeometry.cpp390
1 files changed, 153 insertions, 237 deletions
diff --git a/src/core/SkGeometry.cpp b/src/core/SkGeometry.cpp
index 574954019e..76d3a3f4f6 100644
--- a/src/core/SkGeometry.cpp
+++ b/src/core/SkGeometry.cpp
@@ -69,9 +69,9 @@ bool SkXRayCrossesLine(const SkXRay& pt, const SkPoint pts[2], bool* ambiguous)
////////////////////////////////////////////////////////////////////////
-static int is_not_monotonic(float a, float b, float c) {
- float ab = a - b;
- float bc = b - c;
+static int is_not_monotonic(SkScalar a, SkScalar b, SkScalar c) {
+ SkScalar ab = a - b;
+ SkScalar bc = b - c;
if (ab < 0) {
bc = -bc;
}
@@ -80,31 +80,30 @@ static int is_not_monotonic(float a, float b, float c) {
////////////////////////////////////////////////////////////////////////
-static bool is_unit_interval(SkScalar x)
-{
+static bool is_unit_interval(SkScalar x) {
return x > 0 && x < SK_Scalar1;
}
-static int valid_unit_divide(SkScalar numer, SkScalar denom, SkScalar* ratio)
-{
+static int valid_unit_divide(SkScalar numer, SkScalar denom, SkScalar* ratio) {
SkASSERT(ratio);
- if (numer < 0)
- {
+ if (numer < 0) {
numer = -numer;
denom = -denom;
}
- if (denom == 0 || numer == 0 || numer >= denom)
+ if (denom == 0 || numer == 0 || numer >= denom) {
return 0;
+ }
SkScalar r = SkScalarDiv(numer, denom);
if (SkScalarIsNaN(r)) {
return 0;
}
SkASSERT(r >= 0 && r < SK_Scalar1);
- if (r == 0) // catch underflow if numer <<<< denom
+ if (r == 0) { // catch underflow if numer <<<< denom
return 0;
+ }
*ratio = r;
return 1;
}
@@ -115,26 +114,25 @@ static int valid_unit_divide(SkScalar numer, SkScalar denom, SkScalar* ratio)
x1 = Q / A
x2 = C / Q
*/
-int SkFindUnitQuadRoots(SkScalar A, SkScalar B, SkScalar C, SkScalar roots[2])
-{
+int SkFindUnitQuadRoots(SkScalar A, SkScalar B, SkScalar C, SkScalar roots[2]) {
SkASSERT(roots);
- if (A == 0)
+ if (A == 0) {
return valid_unit_divide(-C, B, roots);
+ }
SkScalar* r = roots;
- float R = B*B - 4*A*C;
+ SkScalar R = B*B - 4*A*C;
if (R < 0 || SkScalarIsNaN(R)) { // complex roots
return 0;
}
- R = sk_float_sqrt(R);
+ R = SkScalarSqrt(R);
SkScalar Q = (B < 0) ? -(B-R)/2 : -(B+R)/2;
r += valid_unit_divide(Q, A, r);
r += valid_unit_divide(C, Q, r);
- if (r - roots == 2)
- {
+ if (r - roots == 2) {
if (roots[0] > roots[1])
SkTSwap<SkScalar>(roots[0], roots[1]);
else if (roots[0] == roots[1]) // nearly-equal?
@@ -146,8 +144,7 @@ int SkFindUnitQuadRoots(SkScalar A, SkScalar B, SkScalar C, SkScalar roots[2])
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
-static SkScalar eval_quad(const SkScalar src[], SkScalar t)
-{
+static SkScalar eval_quad(const SkScalar src[], SkScalar t) {
SkASSERT(src);
SkASSERT(t >= 0 && t <= SK_Scalar1);
@@ -163,52 +160,50 @@ static SkScalar eval_quad(const SkScalar src[], SkScalar t)
#endif
}
-static SkScalar eval_quad_derivative(const SkScalar src[], SkScalar t)
-{
+static SkScalar eval_quad_derivative(const SkScalar src[], SkScalar t) {
SkScalar A = src[4] - 2 * src[2] + src[0];
SkScalar B = src[2] - src[0];
return 2 * SkScalarMulAdd(A, t, B);
}
-static SkScalar eval_quad_derivative_at_half(const SkScalar src[])
-{
+static SkScalar eval_quad_derivative_at_half(const SkScalar src[]) {
SkScalar A = src[4] - 2 * src[2] + src[0];
SkScalar B = src[2] - src[0];
return A + 2 * B;
}
-void SkEvalQuadAt(const SkPoint src[3], SkScalar t, SkPoint* pt, SkVector* tangent)
-{
+void SkEvalQuadAt(const SkPoint src[3], SkScalar t, SkPoint* pt,
+ SkVector* tangent) {
SkASSERT(src);
SkASSERT(t >= 0 && t <= SK_Scalar1);
- if (pt)
+ if (pt) {
pt->set(eval_quad(&src[0].fX, t), eval_quad(&src[0].fY, t));
- if (tangent)
+ }
+ if (tangent) {
tangent->set(eval_quad_derivative(&src[0].fX, t),
eval_quad_derivative(&src[0].fY, t));
+ }
}
-void SkEvalQuadAtHalf(const SkPoint src[3], SkPoint* pt, SkVector* tangent)
-{
+void SkEvalQuadAtHalf(const SkPoint src[3], SkPoint* pt, SkVector* tangent) {
SkASSERT(src);
- if (pt)
- {
+ if (pt) {
SkScalar x01 = SkScalarAve(src[0].fX, src[1].fX);
SkScalar y01 = SkScalarAve(src[0].fY, src[1].fY);
SkScalar x12 = SkScalarAve(src[1].fX, src[2].fX);
SkScalar y12 = SkScalarAve(src[1].fY, src[2].fY);
pt->set(SkScalarAve(x01, x12), SkScalarAve(y01, y12));
}
- if (tangent)
+ if (tangent) {
tangent->set(eval_quad_derivative_at_half(&src[0].fX),
eval_quad_derivative_at_half(&src[0].fY));
+ }
}
-static void interp_quad_coords(const SkScalar* src, SkScalar* dst, SkScalar t)
-{
+static void interp_quad_coords(const SkScalar* src, SkScalar* dst, SkScalar t) {
SkScalar ab = SkScalarInterp(src[0], src[2], t);
SkScalar bc = SkScalarInterp(src[2], src[4], t);
@@ -219,16 +214,14 @@ static void interp_quad_coords(const SkScalar* src, SkScalar* dst, SkScalar t)
dst[8] = src[4];
}
-void SkChopQuadAt(const SkPoint src[3], SkPoint dst[5], SkScalar t)
-{
+void SkChopQuadAt(const SkPoint src[3], SkPoint dst[5], SkScalar t) {
SkASSERT(t > 0 && t < SK_Scalar1);
interp_quad_coords(&src[0].fX, &dst[0].fX, t);
interp_quad_coords(&src[0].fY, &dst[0].fY, t);
}
-void SkChopQuadAtHalf(const SkPoint src[3], SkPoint dst[5])
-{
+void SkChopQuadAtHalf(const SkPoint src[3], SkPoint dst[5]) {
SkScalar x01 = SkScalarAve(src[0].fX, src[1].fX);
SkScalar y01 = SkScalarAve(src[0].fY, src[1].fY);
SkScalar x12 = SkScalarAve(src[1].fX, src[2].fX);
@@ -246,49 +239,31 @@ void SkChopQuadAtHalf(const SkPoint src[3], SkPoint dst[5])
B = 2(b - a)
Solve for t, only if it fits between 0 < t < 1
*/
-int SkFindQuadExtrema(SkScalar a, SkScalar b, SkScalar c, SkScalar tValue[1])
-{
+int SkFindQuadExtrema(SkScalar a, SkScalar b, SkScalar c, SkScalar tValue[1]) {
/* At + B == 0
t = -B / A
*/
return valid_unit_divide(a - b, a - b - b + c, tValue);
}
-static inline void flatten_double_quad_extrema(SkScalar coords[14])
-{
+static inline void flatten_double_quad_extrema(SkScalar coords[14]) {
coords[2] = coords[6] = coords[4];
}
/* Returns 0 for 1 quad, and 1 for two quads, either way the answer is
stored in dst[]. Guarantees that the 1/2 quads will be monotonic.
*/
-int SkChopQuadAtYExtrema(const SkPoint src[3], SkPoint dst[5])
-{
+int SkChopQuadAtYExtrema(const SkPoint src[3], SkPoint dst[5]) {
SkASSERT(src);
SkASSERT(dst);
-#if 0
- static bool once = true;
- if (once)
- {
- once = false;
- SkPoint s[3] = { 0, 26398, 0, 26331, 0, 20621428 };
- SkPoint d[6];
-
- int n = SkChopQuadAtYExtrema(s, d);
- SkDebugf("chop=%d, Y=[%x %x %x %x %x %x]\n", n, d[0].fY, d[1].fY, d[2].fY, d[3].fY, d[4].fY, d[5].fY);
- }
-#endif
-
SkScalar a = src[0].fY;
SkScalar b = src[1].fY;
SkScalar c = src[2].fY;
- if (is_not_monotonic(a, b, c))
- {
+ if (is_not_monotonic(a, b, c)) {
SkScalar tValue;
- if (valid_unit_divide(a - b, a - b - b + c, &tValue))
- {
+ if (valid_unit_divide(a - b, a - b - b + c, &tValue)) {
SkChopQuadAt(src, dst, tValue);
flatten_double_quad_extrema(&dst[0].fY);
return 1;
@@ -306,8 +281,7 @@ int SkChopQuadAtYExtrema(const SkPoint src[3], SkPoint dst[5])
/* Returns 0 for 1 quad, and 1 for two quads, either way the answer is
stored in dst[]. Guarantees that the 1/2 quads will be monotonic.
*/
-int SkChopQuadAtXExtrema(const SkPoint src[3], SkPoint dst[5])
-{
+int SkChopQuadAtXExtrema(const SkPoint src[3], SkPoint dst[5]) {
SkASSERT(src);
SkASSERT(dst);
@@ -344,7 +318,7 @@ int SkChopQuadAtXExtrema(const SkPoint src[3], SkPoint dst[5])
//
// t = - (Ax Bx + Ay By) / (Bx ^ 2 + By ^ 2)
//
-float SkFindQuadMaxCurvature(const SkPoint src[3]) {
+SkScalar SkFindQuadMaxCurvature(const SkPoint src[3]) {
SkScalar Ax = src[1].fX - src[0].fX;
SkScalar Ay = src[1].fY - src[0].fY;
SkScalar Bx = src[0].fX - src[1].fX - src[1].fX + src[2].fX;
@@ -355,8 +329,7 @@ float SkFindQuadMaxCurvature(const SkPoint src[3]) {
return t;
}
-int SkChopQuadAtMaxCurvature(const SkPoint src[3], SkPoint dst[5])
-{
+int SkChopQuadAtMaxCurvature(const SkPoint src[3], SkPoint dst[5]) {
SkScalar t = SkFindQuadMaxCurvature(src);
if (t == 0) {
memcpy(dst, src, 3 * sizeof(SkPoint));
@@ -379,35 +352,35 @@ void SkConvertQuadToCubic(const SkPoint src[3], SkPoint dst[4]) {
dst[3] = src[2];
}
-////////////////////////////////////////////////////////////////////////////////////////
-///// CUBICS // CUBICS // CUBICS // CUBICS // CUBICS // CUBICS // CUBICS // CUBICS /////
-////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+///// CUBICS // CUBICS // CUBICS // CUBICS // CUBICS // CUBICS // CUBICS /////
+//////////////////////////////////////////////////////////////////////////////
-static void get_cubic_coeff(const SkScalar pt[], SkScalar coeff[4])
-{
+static void get_cubic_coeff(const SkScalar pt[], SkScalar coeff[4]) {
coeff[0] = pt[6] + 3*(pt[2] - pt[4]) - pt[0];
coeff[1] = 3*(pt[4] - pt[2] - pt[2] + pt[0]);
coeff[2] = 3*(pt[2] - pt[0]);
coeff[3] = pt[0];
}
-void SkGetCubicCoeff(const SkPoint pts[4], SkScalar cx[4], SkScalar cy[4])
-{
+void SkGetCubicCoeff(const SkPoint pts[4], SkScalar cx[4], SkScalar cy[4]) {
SkASSERT(pts);
- if (cx)
+ if (cx) {
get_cubic_coeff(&pts[0].fX, cx);
- if (cy)
+ }
+ if (cy) {
get_cubic_coeff(&pts[0].fY, cy);
+ }
}
-static SkScalar eval_cubic(const SkScalar src[], SkScalar t)
-{
+static SkScalar eval_cubic(const SkScalar src[], SkScalar t) {
SkASSERT(src);
SkASSERT(t >= 0 && t <= SK_Scalar1);
- if (t == 0)
+ if (t == 0) {
return src[0];
+ }
#ifdef DIRECT_EVAL_OF_POLYNOMIALS
SkScalar D = src[0];
@@ -428,15 +401,13 @@ static SkScalar eval_cubic(const SkScalar src[], SkScalar t)
/** return At^2 + Bt + C
*/
-static SkScalar eval_quadratic(SkScalar A, SkScalar B, SkScalar C, SkScalar t)
-{
+static SkScalar eval_quadratic(SkScalar A, SkScalar B, SkScalar C, SkScalar t) {
SkASSERT(t >= 0 && t <= SK_Scalar1);
return SkScalarMulAdd(SkScalarMulAdd(A, t, B), t, C);
}
-static SkScalar eval_cubic_derivative(const SkScalar src[], SkScalar t)
-{
+static SkScalar eval_cubic_derivative(const SkScalar src[], SkScalar t) {
SkScalar A = src[6] + 3*(src[2] - src[4]) - src[0];
SkScalar B = 2*(src[4] - 2 * src[2] + src[0]);
SkScalar C = src[2] - src[0];
@@ -444,27 +415,29 @@ static SkScalar eval_cubic_derivative(const SkScalar src[], SkScalar t)
return eval_quadratic(A, B, C, t);
}
-static SkScalar eval_cubic_2ndDerivative(const SkScalar src[], SkScalar t)
-{
+static SkScalar eval_cubic_2ndDerivative(const SkScalar src[], SkScalar t) {
SkScalar A = src[6] + 3*(src[2] - src[4]) - src[0];
SkScalar B = src[4] - 2 * src[2] + src[0];
return SkScalarMulAdd(A, t, B);
}
-void SkEvalCubicAt(const SkPoint src[4], SkScalar t, SkPoint* loc, SkVector* tangent, SkVector* curvature)
-{
+void SkEvalCubicAt(const SkPoint src[4], SkScalar t, SkPoint* loc,
+ SkVector* tangent, SkVector* curvature) {
SkASSERT(src);
SkASSERT(t >= 0 && t <= SK_Scalar1);
- if (loc)
+ if (loc) {
loc->set(eval_cubic(&src[0].fX, t), eval_cubic(&src[0].fY, t));
- if (tangent)
+ }
+ if (tangent) {
tangent->set(eval_cubic_derivative(&src[0].fX, t),
eval_cubic_derivative(&src[0].fY, t));
- if (curvature)
+ }
+ if (curvature) {
curvature->set(eval_cubic_2ndDerivative(&src[0].fX, t),
eval_cubic_2ndDerivative(&src[0].fY, t));
+ }
}
/** Cubic'(t) = At^2 + Bt + C, where
@@ -473,8 +446,8 @@ void SkEvalCubicAt(const SkPoint src[4], SkScalar t, SkPoint* loc, SkVector* tan
C = 3(b - a)
Solve for t, keeping only those that fit betwee 0 < t < 1
*/
-int SkFindCubicExtrema(SkScalar a, SkScalar b, SkScalar c, SkScalar d, SkScalar tValues[2])
-{
+int SkFindCubicExtrema(SkScalar a, SkScalar b, SkScalar c, SkScalar d,
+ SkScalar tValues[2]) {
// we divide A,B,C by 3 to simplify
SkScalar A = d - a + 3*(b - c);
SkScalar B = 2*(a - b - b + c);
@@ -483,8 +456,8 @@ int SkFindCubicExtrema(SkScalar a, SkScalar b, SkScalar c, SkScalar d, SkScalar
return SkFindUnitQuadRoots(A, B, C, tValues);
}
-static void interp_cubic_coords(const SkScalar* src, SkScalar* dst, SkScalar t)
-{
+static void interp_cubic_coords(const SkScalar* src, SkScalar* dst,
+ SkScalar t) {
SkScalar ab = SkScalarInterp(src[0], src[2], t);
SkScalar bc = SkScalarInterp(src[2], src[4], t);
SkScalar cd = SkScalarInterp(src[4], src[6], t);
@@ -501,8 +474,7 @@ static void interp_cubic_coords(const SkScalar* src, SkScalar* dst, SkScalar t)
dst[12] = src[6];
}
-void SkChopCubicAt(const SkPoint src[4], SkPoint dst[7], SkScalar t)
-{
+void SkChopCubicAt(const SkPoint src[4], SkPoint dst[7], SkScalar t) {
SkASSERT(t > 0 && t < SK_Scalar1);
interp_cubic_coords(&src[0].fX, &dst[0].fX, t);
@@ -532,8 +504,8 @@ void SkChopCubicAt(const SkPoint src[4], SkPoint dst[7], SkScalar t)
}
*/
-void SkChopCubicAt(const SkPoint src[4], SkPoint dst[], const SkScalar tValues[], int roots)
-{
+void SkChopCubicAt(const SkPoint src[4], SkPoint dst[],
+ const SkScalar tValues[], int roots) {
#ifdef SK_DEBUG
{
for (int i = 0; i < roots - 1; i++)
@@ -545,20 +517,18 @@ void SkChopCubicAt(const SkPoint src[4], SkPoint dst[], const SkScalar tValues[]
}
#endif
- if (dst)
- {
- if (roots == 0) // nothing to chop
+ if (dst) {
+ if (roots == 0) { // nothing to chop
memcpy(dst, src, 4*sizeof(SkPoint));
- else
- {
+ } else {
SkScalar t = tValues[0];
SkPoint tmp[4];
- for (int i = 0; i < roots; i++)
- {
+ for (int i = 0; i < roots; i++) {
SkChopCubicAt(src, dst, t);
- if (i == roots - 1)
+ if (i == roots - 1) {
break;
+ }
dst += 3;
// have src point to the remaining cubic (after the chop)
@@ -577,8 +547,7 @@ void SkChopCubicAt(const SkPoint src[4], SkPoint dst[], const SkScalar tValues[]
}
}
-void SkChopCubicAtHalf(const SkPoint src[4], SkPoint dst[7])
-{
+void SkChopCubicAtHalf(const SkPoint src[4], SkPoint dst[7]) {
SkScalar x01 = SkScalarAve(src[0].fX, src[1].fX);
SkScalar y01 = SkScalarAve(src[0].fY, src[1].fY);
SkScalar x12 = SkScalarAve(src[1].fX, src[2].fX);
@@ -600,8 +569,7 @@ void SkChopCubicAtHalf(const SkPoint src[4], SkPoint dst[7])
dst[6] = src[3];
}
-static void flatten_double_cubic_extrema(SkScalar coords[14])
-{
+static void flatten_double_cubic_extrema(SkScalar coords[14]) {
coords[4] = coords[8] = coords[6];
}
@@ -656,8 +624,7 @@ int SkChopCubicAtXExtrema(const SkPoint src[4], SkPoint dst[10]) {
C = d - 3c + 3b - a
(BxCy - ByCx)t^2 + (AxCy - AyCx)t + AxBy - AyBx == 0
*/
-int SkFindCubicInflections(const SkPoint src[4], SkScalar tValues[])
-{
+int SkFindCubicInflections(const SkPoint src[4], SkScalar tValues[]) {
SkScalar Ax = src[1].fX - src[0].fX;
SkScalar Ay = src[1].fY - src[0].fY;
SkScalar Bx = src[2].fX - 2 * src[1].fX + src[0].fX;
@@ -668,23 +635,21 @@ int SkFindCubicInflections(const SkPoint src[4], SkScalar tValues[])
return SkFindUnitQuadRoots(Bx*Cy - By*Cx, Ax*Cy - Ay*Cx, Ax*By - Ay*Bx, tValues);
}
-int SkChopCubicAtInflections(const SkPoint src[], SkPoint dst[10])
-{
+int SkChopCubicAtInflections(const SkPoint src[], SkPoint dst[10]) {
SkScalar tValues[2];
int count = SkFindCubicInflections(src, tValues);
- if (dst)
- {
- if (count == 0)
+ if (dst) {
+ if (count == 0) {
memcpy(dst, src, 4 * sizeof(SkPoint));
- else
+ } else {
SkChopCubicAt(src, dst, tValues, count);
+ }
}
return count + 1;
}
-template <typename T> void bubble_sort(T array[], int count)
-{
+template <typename T> void bubble_sort(T array[], int count) {
for (int i = count - 1; i > 0; --i)
for (int j = i; j > 0; --j)
if (array[j] < array[j-1])
@@ -695,45 +660,11 @@ template <typename T> void bubble_sort(T array[], int count)
}
}
-// newton refinement
-#if 0
-static SkScalar refine_cubic_root(const SkFP coeff[4], SkScalar root)
-{
- // x1 = x0 - f(t) / f'(t)
-
- SkFP T = SkScalarToFloat(root);
- SkFP N, D;
-
- // f' = 3*coeff[0]*T^2 + 2*coeff[1]*T + coeff[2]
- D = SkFPMul(SkFPMul(coeff[0], SkFPMul(T,T)), 3);
- D = SkFPAdd(D, SkFPMulInt(SkFPMul(coeff[1], T), 2));
- D = SkFPAdd(D, coeff[2]);
-
- if (D == 0)
- return root;
-
- // f = coeff[0]*T^3 + coeff[1]*T^2 + coeff[2]*T + coeff[3]
- N = SkFPMul(SkFPMul(SkFPMul(T, T), T), coeff[0]);
- N = SkFPAdd(N, SkFPMul(SkFPMul(T, T), coeff[1]));
- N = SkFPAdd(N, SkFPMul(T, coeff[2]));
- N = SkFPAdd(N, coeff[3]);
-
- if (N)
- {
- SkScalar delta = SkFPToScalar(SkFPDiv(N, D));
-
- if (delta)
- root -= delta;
- }
- return root;
-}
-#endif
-
/**
* Given an array and count, remove all pair-wise duplicates from the array,
* keeping the existing sorting, and return the new count
*/
-static int collaps_duplicates(float array[], int count) {
+static int collaps_duplicates(SkScalar array[], int count) {
for (int n = count; n > 1; --n) {
if (array[0] == array[1]) {
for (int i = 1; i < n; ++i) {
@@ -755,15 +686,15 @@ static void test_collaps_duplicates() {
static bool gOnce;
if (gOnce) { return; }
gOnce = true;
- const float src0[] = { 0 };
- const float src1[] = { 0, 0 };
- const float src2[] = { 0, 1 };
- const float src3[] = { 0, 0, 0 };
- const float src4[] = { 0, 0, 1 };
- const float src5[] = { 0, 1, 1 };
- const float src6[] = { 0, 1, 2 };
+ const SkScalar src0[] = { 0 };
+ const SkScalar src1[] = { 0, 0 };
+ const SkScalar src2[] = { 0, 1 };
+ const SkScalar src3[] = { 0, 0, 0 };
+ const SkScalar src4[] = { 0, 0, 1 };
+ const SkScalar src5[] = { 0, 1, 1 };
+ const SkScalar src6[] = { 0, 1, 2 };
const struct {
- const float* fData;
+ const SkScalar* fData;
int fCount;
int fCollapsedCount;
} data[] = {
@@ -776,7 +707,7 @@ static void test_collaps_duplicates() {
{ TEST_COLLAPS_ENTRY(src6), 3 },
};
for (size_t i = 0; i < SK_ARRAY_COUNT(data); ++i) {
- float dst[3];
+ SkScalar dst[3];
memcpy(dst, data[i].fData, data[i].fCount * sizeof(dst[0]));
int count = collaps_duplicates(dst, data[i].fCount);
SkASSERT(data[i].fCollapsedCount == count);
@@ -788,7 +719,7 @@ static void test_collaps_duplicates() {
#endif
static SkScalar SkScalarCubeRoot(SkScalar x) {
- return sk_float_pow(x, 0.3333333f);
+ return SkScalarPow(x, 0.3333333f);
}
/* Solve coeff(t) == 0, returning the number of roots that
@@ -798,10 +729,8 @@ static SkScalar SkScalarCubeRoot(SkScalar x) {
Eliminates repeated roots (so that all tValues are distinct, and are always
in increasing order.
*/
-static int solve_cubic_polynomial(const SkScalar coeff[4], SkScalar tValues[3])
-{
- if (SkScalarNearlyZero(coeff[0])) // we're just a quadratic
- {
+static int solve_cubic_poly(const SkScalar coeff[4], SkScalar tValues[3]) {
+ if (SkScalarNearlyZero(coeff[0])) { // we're just a quadratic
return SkFindUnitQuadRoots(coeff[1], coeff[2], coeff[3], tValues);
}
@@ -825,23 +754,22 @@ static int solve_cubic_polynomial(const SkScalar coeff[4], SkScalar tValues[3])
SkScalar* roots = tValues;
SkScalar r;
- if (R2MinusQ3 < 0) // we have 3 real roots
- {
- float theta = sk_float_acos(R / sk_float_sqrt(Q3));
- float neg2RootQ = -2 * sk_float_sqrt(Q);
+ if (R2MinusQ3 < 0) { // we have 3 real roots
+ SkScalar theta = SkScalarACos(R / SkScalarSqrt(Q3));
+ SkScalar neg2RootQ = -2 * SkScalarSqrt(Q);
- r = neg2RootQ * sk_float_cos(theta/3) - adiv3;
- if (is_unit_interval(r))
+ r = neg2RootQ * SkScalarCos(theta/3) - adiv3;
+ if (is_unit_interval(r)) {
*roots++ = r;
-
- r = neg2RootQ * sk_float_cos((theta + 2*SK_ScalarPI)/3) - adiv3;
- if (is_unit_interval(r))
+ }
+ r = neg2RootQ * SkScalarCos((theta + 2*SK_ScalarPI)/3) - adiv3;
+ if (is_unit_interval(r)) {
*roots++ = r;
-
- r = neg2RootQ * sk_float_cos((theta - 2*SK_ScalarPI)/3) - adiv3;
- if (is_unit_interval(r))
+ }
+ r = neg2RootQ * SkScalarCos((theta - 2*SK_ScalarPI)/3) - adiv3;
+ if (is_unit_interval(r)) {
*roots++ = r;
-
+ }
SkDEBUGCODE(test_collaps_duplicates();)
// now sort the roots
@@ -850,19 +778,19 @@ static int solve_cubic_polynomial(const SkScalar coeff[4], SkScalar tValues[3])
bubble_sort(tValues, count);
count = collaps_duplicates(tValues, count);
roots = tValues + count; // so we compute the proper count below
- }
- else // we have 1 real root
- {
+ } else { // we have 1 real root
SkScalar A = SkScalarAbs(R) + SkScalarSqrt(R2MinusQ3);
A = SkScalarCubeRoot(A);
- if (R > 0)
+ if (R > 0) {
A = -A;
-
- if (A != 0)
+ }
+ if (A != 0) {
A += Q / A;
+ }
r = A - adiv3;
- if (is_unit_interval(r))
+ if (is_unit_interval(r)) {
*roots++ = r;
+ }
}
return (int)(roots - tValues);
@@ -879,8 +807,7 @@ static int solve_cubic_polynomial(const SkScalar coeff[4], SkScalar tValues[3])
F' dot F'' -> CCt^3 + 3BCt^2 + (2BB + CA)t + AB
*/
-static void formulate_F1DotF2(const SkScalar src[], SkScalar coeff[4])
-{
+static void formulate_F1DotF2(const SkScalar src[], SkScalar coeff[4]) {
SkScalar a = src[2] - src[0];
SkScalar b = src[4] - 2 * src[2] + src[0];
SkScalar c = src[6] + 3 * (src[2] - src[4]) - src[0];
@@ -891,10 +818,6 @@ static void formulate_F1DotF2(const SkScalar src[], SkScalar coeff[4])
coeff[3] = a * b;
}
-// EXPERIMENTAL: can set this to zero to accept all t-values 0 < t < 1
-//#define kMinTValueForChopping (SK_Scalar1 / 256)
-#define kMinTValueForChopping 0
-
/* Looking for F' dot F'' == 0
A = b - a
@@ -906,51 +829,54 @@ static void formulate_F1DotF2(const SkScalar src[], SkScalar coeff[4])
F' dot F'' -> CCt^3 + 3BCt^2 + (2BB + CA)t + AB
*/
-int SkFindCubicMaxCurvature(const SkPoint src[4], SkScalar tValues[3])
-{
+int SkFindCubicMaxCurvature(const SkPoint src[4], SkScalar tValues[3]) {
SkScalar coeffX[4], coeffY[4];
int i;
formulate_F1DotF2(&src[0].fX, coeffX);
formulate_F1DotF2(&src[0].fY, coeffY);
- for (i = 0; i < 4; i++)
+ for (i = 0; i < 4; i++) {
coeffX[i] += coeffY[i];
+ }
SkScalar t[3];
- int count = solve_cubic_polynomial(coeffX, t);
+ int count = solve_cubic_poly(coeffX, t);
int maxCount = 0;
// now remove extrema where the curvature is zero (mins)
// !!!! need a test for this !!!!
- for (i = 0; i < count; i++)
- {
+ for (i = 0; i < count; i++) {
// if (not_min_curvature())
- if (t[i] > kMinTValueForChopping && t[i] < SK_Scalar1 - kMinTValueForChopping)
+ if (t[i] > 0 && t[i] < SK_Scalar1) {
tValues[maxCount++] = t[i];
+ }
}
return maxCount;
}
-int SkChopCubicAtMaxCurvature(const SkPoint src[4], SkPoint dst[13], SkScalar tValues[3])
-{
+int SkChopCubicAtMaxCurvature(const SkPoint src[4], SkPoint dst[13],
+ SkScalar tValues[3]) {
SkScalar t_storage[3];
- if (tValues == NULL)
+ if (tValues == NULL) {
tValues = t_storage;
+ }
int count = SkFindCubicMaxCurvature(src, tValues);
if (dst) {
- if (count == 0)
+ if (count == 0) {
memcpy(dst, src, 4 * sizeof(SkPoint));
- else
+ } else {
SkChopCubicAt(src, dst, tValues, count);
+ }
}
return count + 1;
}
-bool SkXRayCrossesMonotonicCubic(const SkXRay& pt, const SkPoint cubic[4], bool* ambiguous) {
+bool SkXRayCrossesMonotonicCubic(const SkXRay& pt, const SkPoint cubic[4],
+ bool* ambiguous) {
if (ambiguous) {
*ambiguous = false;
}
@@ -1064,13 +990,13 @@ int SkNumXRayCrossingsForCubic(const SkXRay& pt, const SkPoint cubic[4], bool* a
}
return num_crossings;
}
-////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
/* Find t value for quadratic [a, b, c] = d.
Return 0 if there is no solution within [0, 1)
*/
-static SkScalar quad_solve(SkScalar a, SkScalar b, SkScalar c, SkScalar d)
-{
+static SkScalar quad_solve(SkScalar a, SkScalar b, SkScalar c, SkScalar d) {
// At^2 + Bt + C = d
SkScalar A = a - 2 * b + c;
SkScalar B = 2 * (b - a);
@@ -1088,8 +1014,8 @@ static SkScalar quad_solve(SkScalar a, SkScalar b, SkScalar c, SkScalar d)
Should only return false if the computed pos is the start of the curve
(i.e. root == 0)
*/
-static bool truncate_last_curve(const SkPoint quad[3], SkScalar x, SkScalar y, SkPoint* dest)
-{
+static bool truncate_last_curve(const SkPoint quad[3], SkScalar x, SkScalar y,
+ SkPoint* dest) {
const SkScalar* base;
SkScalar value;
@@ -1105,8 +1031,7 @@ static bool truncate_last_curve(const SkPoint quad[3], SkScalar x, SkScalar y, S
// root might return something outside of [0, 1)
SkScalar t = quad_solve(base[0], base[2], base[4], value);
- if (t > 0)
- {
+ if (t > 0) {
SkPoint tmp[5];
SkChopQuadAt(quad, tmp, t);
dest[0] = tmp[1];
@@ -1167,8 +1092,7 @@ static const SkPoint gQuadCirclePts[kSkBuildQuadArcStorage] = {
int SkBuildQuadArc(const SkVector& uStart, const SkVector& uStop,
SkRotationDirection dir, const SkMatrix* userMatrix,
- SkPoint quadPoints[])
-{
+ SkPoint quadPoints[]) {
// rotate by x,y so that uStart is (1.0)
SkScalar x = SkPoint::DotProduct(uStart, uStop);
SkScalar y = SkPoint::CrossProduct(uStart, uStop);
@@ -1189,45 +1113,37 @@ int SkBuildQuadArc(const SkVector& uStart, const SkVector& uStop,
quadPoints[0].set(SK_Scalar1, 0);
pointCount = 1;
} else {
- if (dir == kCCW_SkRotationDirection)
+ if (dir == kCCW_SkRotationDirection) {
y = -y;
-
+ }
// what octant (quadratic curve) is [xy] in?
int oct = 0;
bool sameSign = true;
- if (0 == y)
- {
+ if (0 == y) {
oct = 4; // 180
SkASSERT(SkScalarAbs(x + SK_Scalar1) <= SK_ScalarNearlyZero);
- }
- else if (0 == x)
- {
+ } else if (0 == x) {
SkASSERT(absY - SK_Scalar1 <= SK_ScalarNearlyZero);
- if (y > 0)
- oct = 2; // 90
- else
- oct = 6; // 270
- }
- else
- {
- if (y < 0)
+ oct = y > 0 ? 2 : 6; // 90 : 270
+ } else {
+ if (y < 0) {
oct += 4;
- if ((x < 0) != (y < 0))
- {
+ }
+ if ((x < 0) != (y < 0)) {
oct += 2;
sameSign = false;
}
- if ((absX < absY) == sameSign)
+ if ((absX < absY) == sameSign) {
oct += 1;
+ }
}
int wholeCount = oct << 1;
memcpy(quadPoints, gQuadCirclePts, (wholeCount + 1) * sizeof(SkPoint));
const SkPoint* arc = &gQuadCirclePts[wholeCount];
- if (truncate_last_curve(arc, x, y, &quadPoints[wholeCount + 1]))
- {
+ if (truncate_last_curve(arc, x, y, &quadPoints[wholeCount + 1])) {
wholeCount += 2;
}
pointCount = wholeCount + 1;