| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2006 The Android Open Source Project | 2 * Copyright 2006 The Android Open Source Project |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkGeometry.h" | 8 #include "SkGeometry.h" |
| 9 #include "SkMatrix.h" | 9 #include "SkMatrix.h" |
| 10 #include "SkNx.h" | 10 #include "SkNx.h" |
| (...skipping 957 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 968 dst[3] = SkScalarInterp(ab, bc, t); | 968 dst[3] = SkScalarInterp(ab, bc, t); |
| 969 dst[6] = bc; | 969 dst[6] = bc; |
| 970 } | 970 } |
| 971 | 971 |
| 972 static void ratquad_mapTo3D(const SkPoint src[3], SkScalar w, SkP3D dst[]) { | 972 static void ratquad_mapTo3D(const SkPoint src[3], SkScalar w, SkP3D dst[]) { |
| 973 dst[0].set(src[0].fX * 1, src[0].fY * 1, 1); | 973 dst[0].set(src[0].fX * 1, src[0].fY * 1, 1); |
| 974 dst[1].set(src[1].fX * w, src[1].fY * w, w); | 974 dst[1].set(src[1].fX * w, src[1].fY * w, w); |
| 975 dst[2].set(src[2].fX * 1, src[2].fY * 1, 1); | 975 dst[2].set(src[2].fX * 1, src[2].fY * 1, 1); |
| 976 } | 976 } |
| 977 | 977 |
| 978 void SkConic::chopAt(SkScalar t, SkConic dst[2]) const { | 978 // return false if infinity or NaN is generated; caller must check |
| 979 bool SkConic::chopAt(SkScalar t, SkConic dst[2]) const { |
| 979 SkP3D tmp[3], tmp2[3]; | 980 SkP3D tmp[3], tmp2[3]; |
| 980 | 981 |
| 981 ratquad_mapTo3D(fPts, fW, tmp); | 982 ratquad_mapTo3D(fPts, fW, tmp); |
| 982 | 983 |
| 983 p3d_interp(&tmp[0].fX, &tmp2[0].fX, t); | 984 p3d_interp(&tmp[0].fX, &tmp2[0].fX, t); |
| 984 p3d_interp(&tmp[0].fY, &tmp2[0].fY, t); | 985 p3d_interp(&tmp[0].fY, &tmp2[0].fY, t); |
| 985 p3d_interp(&tmp[0].fZ, &tmp2[0].fZ, t); | 986 p3d_interp(&tmp[0].fZ, &tmp2[0].fZ, t); |
| 986 | 987 |
| 987 dst[0].fPts[0] = fPts[0]; | 988 dst[0].fPts[0] = fPts[0]; |
| 988 tmp2[0].projectDown(&dst[0].fPts[1]); | 989 tmp2[0].projectDown(&dst[0].fPts[1]); |
| 989 tmp2[1].projectDown(&dst[0].fPts[2]); dst[1].fPts[0] = dst[0].fPts[2]; | 990 tmp2[1].projectDown(&dst[0].fPts[2]); dst[1].fPts[0] = dst[0].fPts[2]; |
| 990 tmp2[2].projectDown(&dst[1].fPts[1]); | 991 tmp2[2].projectDown(&dst[1].fPts[1]); |
| 991 dst[1].fPts[2] = fPts[2]; | 992 dst[1].fPts[2] = fPts[2]; |
| 992 | 993 |
| 993 // to put in "standard form", where w0 and w2 are both 1, we compute the | 994 // to put in "standard form", where w0 and w2 are both 1, we compute the |
| 994 // new w1 as sqrt(w1*w1/w0*w2) | 995 // new w1 as sqrt(w1*w1/w0*w2) |
| 995 // or | 996 // or |
| 996 // w1 /= sqrt(w0*w2) | 997 // w1 /= sqrt(w0*w2) |
| 997 // | 998 // |
| 998 // However, in our case, we know that for dst[0]: | 999 // However, in our case, we know that for dst[0]: |
| 999 // w0 == 1, and for dst[1], w2 == 1 | 1000 // w0 == 1, and for dst[1], w2 == 1 |
| 1000 // | 1001 // |
| 1001 SkScalar root = SkScalarSqrt(tmp2[1].fZ); | 1002 SkScalar root = SkScalarSqrt(tmp2[1].fZ); |
| 1002 dst[0].fW = tmp2[0].fZ / root; | 1003 dst[0].fW = tmp2[0].fZ / root; |
| 1003 dst[1].fW = tmp2[2].fZ / root; | 1004 dst[1].fW = tmp2[2].fZ / root; |
| 1005 SkASSERT(sizeof(dst[0]) == sizeof(SkScalar) * 7); |
| 1006 SkASSERT(0 == offsetof(SkConic, fPts[0].fX)); |
| 1007 return SkScalarsAreFinite(&dst[0].fPts[0].fX, 7 * 2); |
| 1004 } | 1008 } |
| 1005 | 1009 |
| 1006 void SkConic::chopAt(SkScalar t1, SkScalar t2, SkConic* dst) const { | 1010 void SkConic::chopAt(SkScalar t1, SkScalar t2, SkConic* dst) const { |
| 1007 if (0 == t1 || 1 == t2) { | 1011 if (0 == t1 || 1 == t2) { |
| 1008 if (0 == t1 && 1 == t2) { | 1012 if (0 == t1 && 1 == t2) { |
| 1009 *dst = *this; | 1013 *dst = *this; |
| 1014 return; |
| 1010 } else { | 1015 } else { |
| 1011 SkConic pair[2]; | 1016 SkConic pair[2]; |
| 1012 this->chopAt(t1 ? t1 : t2, pair); | 1017 if (this->chopAt(t1 ? t1 : t2, pair)) { |
| 1013 *dst = pair[SkToBool(t1)]; | 1018 *dst = pair[SkToBool(t1)]; |
| 1019 return; |
| 1020 } |
| 1014 } | 1021 } |
| 1015 return; | |
| 1016 } | 1022 } |
| 1017 SkConicCoeff coeff(*this); | 1023 SkConicCoeff coeff(*this); |
| 1018 Sk2s tt1(t1); | 1024 Sk2s tt1(t1); |
| 1019 Sk2s aXY = coeff.fNumer.eval(tt1); | 1025 Sk2s aXY = coeff.fNumer.eval(tt1); |
| 1020 Sk2s aZZ = coeff.fDenom.eval(tt1); | 1026 Sk2s aZZ = coeff.fDenom.eval(tt1); |
| 1021 Sk2s midTT((t1 + t2) / 2); | 1027 Sk2s midTT((t1 + t2) / 2); |
| 1022 Sk2s dXY = coeff.fNumer.eval(midTT); | 1028 Sk2s dXY = coeff.fNumer.eval(midTT); |
| 1023 Sk2s dZZ = coeff.fDenom.eval(midTT); | 1029 Sk2s dZZ = coeff.fDenom.eval(midTT); |
| 1024 Sk2s tt2(t2); | 1030 Sk2s tt2(t2); |
| 1025 Sk2s cXY = coeff.fNumer.eval(tt2); | 1031 Sk2s cXY = coeff.fNumer.eval(tt2); |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1236 return conic_find_extrema(&fPts[0].fX, fW, t); | 1242 return conic_find_extrema(&fPts[0].fX, fW, t); |
| 1237 } | 1243 } |
| 1238 | 1244 |
| 1239 bool SkConic::findYExtrema(SkScalar* t) const { | 1245 bool SkConic::findYExtrema(SkScalar* t) const { |
| 1240 return conic_find_extrema(&fPts[0].fY, fW, t); | 1246 return conic_find_extrema(&fPts[0].fY, fW, t); |
| 1241 } | 1247 } |
| 1242 | 1248 |
| 1243 bool SkConic::chopAtXExtrema(SkConic dst[2]) const { | 1249 bool SkConic::chopAtXExtrema(SkConic dst[2]) const { |
| 1244 SkScalar t; | 1250 SkScalar t; |
| 1245 if (this->findXExtrema(&t)) { | 1251 if (this->findXExtrema(&t)) { |
| 1246 this->chopAt(t, dst); | 1252 if (!this->chopAt(t, dst)) { |
| 1253 // if chop can't return finite values, don't chop |
| 1254 return false; |
| 1255 } |
| 1247 // now clean-up the middle, since we know t was meant to be at | 1256 // now clean-up the middle, since we know t was meant to be at |
| 1248 // an X-extrema | 1257 // an X-extrema |
| 1249 SkScalar value = dst[0].fPts[2].fX; | 1258 SkScalar value = dst[0].fPts[2].fX; |
| 1250 dst[0].fPts[1].fX = value; | 1259 dst[0].fPts[1].fX = value; |
| 1251 dst[1].fPts[0].fX = value; | 1260 dst[1].fPts[0].fX = value; |
| 1252 dst[1].fPts[1].fX = value; | 1261 dst[1].fPts[1].fX = value; |
| 1253 return true; | 1262 return true; |
| 1254 } | 1263 } |
| 1255 return false; | 1264 return false; |
| 1256 } | 1265 } |
| 1257 | 1266 |
| 1258 bool SkConic::chopAtYExtrema(SkConic dst[2]) const { | 1267 bool SkConic::chopAtYExtrema(SkConic dst[2]) const { |
| 1259 SkScalar t; | 1268 SkScalar t; |
| 1260 if (this->findYExtrema(&t)) { | 1269 if (this->findYExtrema(&t)) { |
| 1261 this->chopAt(t, dst); | 1270 if (!this->chopAt(t, dst)) { |
| 1271 // if chop can't return finite values, don't chop |
| 1272 return false; |
| 1273 } |
| 1262 // now clean-up the middle, since we know t was meant to be at | 1274 // now clean-up the middle, since we know t was meant to be at |
| 1263 // an Y-extrema | 1275 // an Y-extrema |
| 1264 SkScalar value = dst[0].fPts[2].fY; | 1276 SkScalar value = dst[0].fPts[2].fY; |
| 1265 dst[0].fPts[1].fY = value; | 1277 dst[0].fPts[1].fY = value; |
| 1266 dst[1].fPts[0].fY = value; | 1278 dst[1].fPts[0].fY = value; |
| 1267 dst[1].fPts[1].fY = value; | 1279 dst[1].fPts[1].fY = value; |
| 1268 return true; | 1280 return true; |
| 1269 } | 1281 } |
| 1270 return false; | 1282 return false; |
| 1271 } | 1283 } |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1397 matrix.preScale(SK_Scalar1, -SK_Scalar1); | 1409 matrix.preScale(SK_Scalar1, -SK_Scalar1); |
| 1398 } | 1410 } |
| 1399 if (userMatrix) { | 1411 if (userMatrix) { |
| 1400 matrix.postConcat(*userMatrix); | 1412 matrix.postConcat(*userMatrix); |
| 1401 } | 1413 } |
| 1402 for (int i = 0; i < conicCount; ++i) { | 1414 for (int i = 0; i < conicCount; ++i) { |
| 1403 matrix.mapPoints(dst[i].fPts, 3); | 1415 matrix.mapPoints(dst[i].fPts, 3); |
| 1404 } | 1416 } |
| 1405 return conicCount; | 1417 return conicCount; |
| 1406 } | 1418 } |
| OLD | NEW |