OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2006 The Android Open Source Project | 3 * Copyright 2006 The Android Open Source Project |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 | 9 |
10 #include "SkGeometry.h" | 10 #include "SkGeometry.h" |
(...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
387 // F''(t) = 2 (a - 2b + c) | 387 // F''(t) = 2 (a - 2b + c) |
388 // | 388 // |
389 // A = 2 (b - a) | 389 // A = 2 (b - a) |
390 // B = 2 (a - 2b + c) | 390 // B = 2 (a - 2b + c) |
391 // | 391 // |
392 // Maximum curvature for a quadratic means solving | 392 // Maximum curvature for a quadratic means solving |
393 // Fx' Fx'' + Fy' Fy'' = 0 | 393 // Fx' Fx'' + Fy' Fy'' = 0 |
394 // | 394 // |
395 // t = - (Ax Bx + Ay By) / (Bx ^ 2 + By ^ 2) | 395 // t = - (Ax Bx + Ay By) / (Bx ^ 2 + By ^ 2) |
396 // | 396 // |
397 int SkChopQuadAtMaxCurvature(const SkPoint src[3], SkPoint dst[5]) | 397 float SkFindQuadMaxCurvature(const SkPoint src[3]) { |
398 { | |
399 SkScalar Ax = src[1].fX - src[0].fX; | 398 SkScalar Ax = src[1].fX - src[0].fX; |
400 SkScalar Ay = src[1].fY - src[0].fY; | 399 SkScalar Ay = src[1].fY - src[0].fY; |
401 SkScalar Bx = src[0].fX - src[1].fX - src[1].fX + src[2].fX; | 400 SkScalar Bx = src[0].fX - src[1].fX - src[1].fX + src[2].fX; |
402 SkScalar By = src[0].fY - src[1].fY - src[1].fY + src[2].fY; | 401 SkScalar By = src[0].fY - src[1].fY - src[1].fY + src[2].fY; |
403 SkScalar t = 0; // 0 means don't chop | 402 SkScalar t = 0; // 0 means don't chop |
404 | 403 |
405 #ifdef SK_SCALAR_IS_FLOAT | 404 #ifdef SK_SCALAR_IS_FLOAT |
406 (void)valid_unit_divide(-(Ax * Bx + Ay * By), Bx * Bx + By * By, &t); | 405 (void)valid_unit_divide(-(Ax * Bx + Ay * By), Bx * Bx + By * By, &t); |
407 #else | 406 #else |
408 // !!! should I use SkFloat here? seems like it | 407 // !!! should I use SkFloat here? seems like it |
(...skipping 11 matching lines...) Expand all Loading... |
420 SkASSERT(!denom.isNeg()); | 419 SkASSERT(!denom.isNeg()); |
421 if (numer < denom) | 420 if (numer < denom) |
422 { | 421 { |
423 t = numer.getFixedDiv(denom); | 422 t = numer.getFixedDiv(denom); |
424 SkASSERT(t >= 0 && t <= SK_Fixed1); // assert that we're numeric
ally stable (ha!) | 423 SkASSERT(t >= 0 && t <= SK_Fixed1); // assert that we're numeric
ally stable (ha!) |
425 if ((unsigned)t >= SK_Fixed1) // runtime check for numeric
al stability | 424 if ((unsigned)t >= SK_Fixed1) // runtime check for numeric
al stability |
426 t = 0; // ignore the chop | 425 t = 0; // ignore the chop |
427 } | 426 } |
428 } | 427 } |
429 #endif | 428 #endif |
| 429 return t; |
| 430 } |
430 | 431 |
431 if (t == 0) | 432 int SkChopQuadAtMaxCurvature(const SkPoint src[3], SkPoint dst[5]) |
432 { | 433 { |
| 434 SkScalar t = SkFindQuadMaxCurvature(src); |
| 435 if (t == 0) { |
433 memcpy(dst, src, 3 * sizeof(SkPoint)); | 436 memcpy(dst, src, 3 * sizeof(SkPoint)); |
434 return 1; | 437 return 1; |
435 } | 438 } else { |
436 else | |
437 { | |
438 SkChopQuadAt(src, dst, t); | 439 SkChopQuadAt(src, dst, t); |
439 return 2; | 440 return 2; |
440 } | 441 } |
441 } | 442 } |
442 | 443 |
443 #ifdef SK_SCALAR_IS_FLOAT | 444 #ifdef SK_SCALAR_IS_FLOAT |
444 #define SK_ScalarTwoThirds (0.666666666f) | 445 #define SK_ScalarTwoThirds (0.666666666f) |
445 #else | 446 #else |
446 #define SK_ScalarTwoThirds ((SkFixed)(43691)) | 447 #define SK_ScalarTwoThirds ((SkFixed)(43691)) |
447 #endif | 448 #endif |
(...skipping 606 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1054 | 1055 |
1055 int SkChopCubicAtMaxCurvature(const SkPoint src[4], SkPoint dst[13], SkScalar tV
alues[3]) | 1056 int SkChopCubicAtMaxCurvature(const SkPoint src[4], SkPoint dst[13], SkScalar tV
alues[3]) |
1056 { | 1057 { |
1057 SkScalar t_storage[3]; | 1058 SkScalar t_storage[3]; |
1058 | 1059 |
1059 if (tValues == NULL) | 1060 if (tValues == NULL) |
1060 tValues = t_storage; | 1061 tValues = t_storage; |
1061 | 1062 |
1062 int count = SkFindCubicMaxCurvature(src, tValues); | 1063 int count = SkFindCubicMaxCurvature(src, tValues); |
1063 | 1064 |
1064 if (dst) | 1065 if (dst) { |
1065 { | |
1066 if (count == 0) | 1066 if (count == 0) |
1067 memcpy(dst, src, 4 * sizeof(SkPoint)); | 1067 memcpy(dst, src, 4 * sizeof(SkPoint)); |
1068 else | 1068 else |
1069 SkChopCubicAt(src, dst, tValues, count); | 1069 SkChopCubicAt(src, dst, tValues, count); |
1070 } | 1070 } |
1071 return count + 1; | 1071 return count + 1; |
1072 } | 1072 } |
1073 | 1073 |
1074 bool SkXRayCrossesMonotonicCubic(const SkXRay& pt, const SkPoint cubic[4], bool*
ambiguous) { | 1074 bool SkXRayCrossesMonotonicCubic(const SkXRay& pt, const SkPoint cubic[4], bool*
ambiguous) { |
1075 if (ambiguous) { | 1075 if (ambiguous) { |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1178 *ambiguous |= locally_ambiguous; | 1178 *ambiguous |= locally_ambiguous; |
1179 } | 1179 } |
1180 if (num_monotonic_cubics > 1) | 1180 if (num_monotonic_cubics > 1) |
1181 if (SkXRayCrossesMonotonicCubic(pt, &monotonic_cubics[6], &locally_ambig
uous)) | 1181 if (SkXRayCrossesMonotonicCubic(pt, &monotonic_cubics[6], &locally_ambig
uous)) |
1182 ++num_crossings; | 1182 ++num_crossings; |
1183 if (ambiguous) { | 1183 if (ambiguous) { |
1184 *ambiguous |= locally_ambiguous; | 1184 *ambiguous |= locally_ambiguous; |
1185 } | 1185 } |
1186 return num_crossings; | 1186 return num_crossings; |
1187 } | 1187 } |
1188 | |
1189 //////////////////////////////////////////////////////////////////////////////// | 1188 //////////////////////////////////////////////////////////////////////////////// |
1190 | 1189 |
1191 /* Find t value for quadratic [a, b, c] = d. | 1190 /* Find t value for quadratic [a, b, c] = d. |
1192 Return 0 if there is no solution within [0, 1) | 1191 Return 0 if there is no solution within [0, 1) |
1193 */ | 1192 */ |
1194 static SkScalar quad_solve(SkScalar a, SkScalar b, SkScalar c, SkScalar d) | 1193 static SkScalar quad_solve(SkScalar a, SkScalar b, SkScalar c, SkScalar d) |
1195 { | 1194 { |
1196 // At^2 + Bt + C = d | 1195 // At^2 + Bt + C = d |
1197 SkScalar A = a - 2 * b + c; | 1196 SkScalar A = a - 2 * b + c; |
1198 SkScalar B = 2 * (b - a); | 1197 SkScalar B = 2 * (b - a); |
(...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1658 } | 1657 } |
1659 if (this->findYExtrema(&t)) { | 1658 if (this->findYExtrema(&t)) { |
1660 this->evalAt(t, &pts[count++]); | 1659 this->evalAt(t, &pts[count++]); |
1661 } | 1660 } |
1662 bounds->set(pts, count); | 1661 bounds->set(pts, count); |
1663 } | 1662 } |
1664 | 1663 |
1665 void SkConic::computeFastBounds(SkRect* bounds) const { | 1664 void SkConic::computeFastBounds(SkRect* bounds) const { |
1666 bounds->set(fPts, 3); | 1665 bounds->set(fPts, 3); |
1667 } | 1666 } |
OLD | NEW |