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 |