| 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 1187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1198 SkScalar B = 2 * (b - a); | 1198 SkScalar B = 2 * (b - a); |
| 1199 SkScalar C = a - d; | 1199 SkScalar C = a - d; |
| 1200 | 1200 |
| 1201 SkScalar roots[2]; | 1201 SkScalar roots[2]; |
| 1202 int count = SkFindUnitQuadRoots(A, B, C, roots); | 1202 int count = SkFindUnitQuadRoots(A, B, C, roots); |
| 1203 | 1203 |
| 1204 SkASSERT(count <= 1); | 1204 SkASSERT(count <= 1); |
| 1205 return count == 1 ? roots[0] : 0; | 1205 return count == 1 ? roots[0] : 0; |
| 1206 } | 1206 } |
| 1207 | 1207 |
| 1208 /* given a quad-curve and a point (x,y), chop the quad at that point and return | 1208 /* given a quad-curve and a point (x,y), chop the quad at that point and place |
| 1209 the new quad's offCurve point. Should only return false if the computed pos | 1209 the new off-curve point and endpoint into 'dest'. The new end point is used |
| 1210 is the start of the curve (i.e. root == 0) | 1210 (rather than (x,y)) to compensate for numerical inaccuracies. |
| 1211 Should only return false if the computed pos is the start of the curve |
| 1212 (i.e. root == 0) |
| 1211 */ | 1213 */ |
| 1212 static bool quad_pt2OffCurve(const SkPoint quad[3], SkScalar x, SkScalar y, SkPo
int* offCurve) | 1214 static bool truncate_last_curve(const SkPoint quad[3], SkScalar x, SkScalar y, S
kPoint* dest) |
| 1213 { | 1215 { |
| 1214 const SkScalar* base; | 1216 const SkScalar* base; |
| 1215 SkScalar value; | 1217 SkScalar value; |
| 1216 | 1218 |
| 1217 if (SkScalarAbs(x) < SkScalarAbs(y)) { | 1219 if (SkScalarAbs(x) < SkScalarAbs(y)) { |
| 1218 base = &quad[0].fX; | 1220 base = &quad[0].fX; |
| 1219 value = x; | 1221 value = x; |
| 1220 } else { | 1222 } else { |
| 1221 base = &quad[0].fY; | 1223 base = &quad[0].fY; |
| 1222 value = y; | 1224 value = y; |
| 1223 } | 1225 } |
| 1224 | 1226 |
| 1225 // note: this returns 0 if it thinks value is out of range, meaning the | 1227 // note: this returns 0 if it thinks value is out of range, meaning the |
| 1226 // root might return something outside of [0, 1) | 1228 // root might return something outside of [0, 1) |
| 1227 SkScalar t = quad_solve(base[0], base[2], base[4], value); | 1229 SkScalar t = quad_solve(base[0], base[2], base[4], value); |
| 1228 | 1230 |
| 1229 if (t > 0) | 1231 if (t > 0) |
| 1230 { | 1232 { |
| 1231 SkPoint tmp[5]; | 1233 SkPoint tmp[5]; |
| 1232 SkChopQuadAt(quad, tmp, t); | 1234 SkChopQuadAt(quad, tmp, t); |
| 1233 *offCurve = tmp[1]; | 1235 dest[0] = tmp[1]; |
| 1236 dest[1] = tmp[2]; |
| 1234 return true; | 1237 return true; |
| 1235 } else { | 1238 } else { |
| 1236 /* t == 0 means either the value triggered a root outside of [0, 1) | 1239 /* t == 0 means either the value triggered a root outside of [0, 1) |
| 1237 For our purposes, we can ignore the <= 0 roots, but we want to | 1240 For our purposes, we can ignore the <= 0 roots, but we want to |
| 1238 catch the >= 1 roots (which given our caller, will basically mean | 1241 catch the >= 1 roots (which given our caller, will basically mean |
| 1239 a root of 1, give-or-take numerical instability). If we are in the | 1242 a root of 1, give-or-take numerical instability). If we are in the |
| 1240 >= 1 case, return the existing offCurve point. | 1243 >= 1 case, return the existing offCurve point. |
| 1241 | 1244 |
| 1242 The test below checks to see if we are close to the "end" of the | 1245 The test below checks to see if we are close to the "end" of the |
| 1243 curve (near base[4]). Rather than specifying a tolerance, I just | 1246 curve (near base[4]). Rather than specifying a tolerance, I just |
| 1244 check to see if value is on to the right/left of the middle point | 1247 check to see if value is on to the right/left of the middle point |
| 1245 (depending on the direction/sign of the end points). | 1248 (depending on the direction/sign of the end points). |
| 1246 */ | 1249 */ |
| 1247 if ((base[0] < base[4] && value > base[2]) || | 1250 if ((base[0] < base[4] && value > base[2]) || |
| 1248 (base[0] > base[4] && value < base[2])) // should root have been 1 | 1251 (base[0] > base[4] && value < base[2])) // should root have been 1 |
| 1249 { | 1252 { |
| 1250 *offCurve = quad[1]; | 1253 dest[0] = quad[1]; |
| 1254 dest[1].set(x, y); |
| 1251 return true; | 1255 return true; |
| 1252 } | 1256 } |
| 1253 } | 1257 } |
| 1254 return false; | 1258 return false; |
| 1255 } | 1259 } |
| 1256 | 1260 |
| 1257 #ifdef SK_SCALAR_IS_FLOAT | 1261 #ifdef SK_SCALAR_IS_FLOAT |
| 1258 | 1262 |
| 1259 // Due to floating point issues (i.e., 1.0f - SK_ScalarRoot2Over2 != | 1263 // Due to floating point issues (i.e., 1.0f - SK_ScalarRoot2Over2 != |
| 1260 // SK_ScalarRoot2Over2 - SK_ScalarTanPIOver8) a cruder root2over2 | 1264 // SK_ScalarRoot2Over2 - SK_ScalarTanPIOver8) a cruder root2over2 |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1353 sameSign = false; | 1357 sameSign = false; |
| 1354 } | 1358 } |
| 1355 if ((absX < absY) == sameSign) | 1359 if ((absX < absY) == sameSign) |
| 1356 oct += 1; | 1360 oct += 1; |
| 1357 } | 1361 } |
| 1358 | 1362 |
| 1359 int wholeCount = oct << 1; | 1363 int wholeCount = oct << 1; |
| 1360 memcpy(quadPoints, gQuadCirclePts, (wholeCount + 1) * sizeof(SkPoint)); | 1364 memcpy(quadPoints, gQuadCirclePts, (wholeCount + 1) * sizeof(SkPoint)); |
| 1361 | 1365 |
| 1362 const SkPoint* arc = &gQuadCirclePts[wholeCount]; | 1366 const SkPoint* arc = &gQuadCirclePts[wholeCount]; |
| 1363 if (quad_pt2OffCurve(arc, x, y, &quadPoints[wholeCount + 1])) | 1367 if (truncate_last_curve(arc, x, y, &quadPoints[wholeCount + 1])) |
| 1364 { | 1368 { |
| 1365 quadPoints[wholeCount + 2].set(x, y); | |
| 1366 wholeCount += 2; | 1369 wholeCount += 2; |
| 1367 } | 1370 } |
| 1368 pointCount = wholeCount + 1; | 1371 pointCount = wholeCount + 1; |
| 1369 } | 1372 } |
| 1370 | 1373 |
| 1371 // now handle counter-clockwise and the initial unitStart rotation | 1374 // now handle counter-clockwise and the initial unitStart rotation |
| 1372 SkMatrix matrix; | 1375 SkMatrix matrix; |
| 1373 matrix.setSinCos(uStart.fY, uStart.fX); | 1376 matrix.setSinCos(uStart.fY, uStart.fX); |
| 1374 if (dir == kCCW_SkRotationDirection) { | 1377 if (dir == kCCW_SkRotationDirection) { |
| 1375 matrix.preScale(SK_Scalar1, -SK_Scalar1); | 1378 matrix.preScale(SK_Scalar1, -SK_Scalar1); |
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1655 } | 1658 } |
| 1656 if (this->findYExtrema(&t)) { | 1659 if (this->findYExtrema(&t)) { |
| 1657 this->evalAt(t, &pts[count++]); | 1660 this->evalAt(t, &pts[count++]); |
| 1658 } | 1661 } |
| 1659 bounds->set(pts, count); | 1662 bounds->set(pts, count); |
| 1660 } | 1663 } |
| 1661 | 1664 |
| 1662 void SkConic::computeFastBounds(SkRect* bounds) const { | 1665 void SkConic::computeFastBounds(SkRect* bounds) const { |
| 1663 bounds->set(fPts, 3); | 1666 bounds->set(fPts, 3); |
| 1664 } | 1667 } |
| OLD | NEW |