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 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
123 SkScalar A = src[4] - 2 * src[2] + C; | 123 SkScalar A = src[4] - 2 * src[2] + C; |
124 SkScalar B = 2 * (src[2] - C); | 124 SkScalar B = 2 * (src[2] - C); |
125 return SkScalarMulAdd(SkScalarMulAdd(A, t, B), t, C); | 125 return SkScalarMulAdd(SkScalarMulAdd(A, t, B), t, C); |
126 #else | 126 #else |
127 SkScalar ab = SkScalarInterp(src[0], src[2], t); | 127 SkScalar ab = SkScalarInterp(src[0], src[2], t); |
128 SkScalar bc = SkScalarInterp(src[2], src[4], t); | 128 SkScalar bc = SkScalarInterp(src[2], src[4], t); |
129 return SkScalarInterp(ab, bc, t); | 129 return SkScalarInterp(ab, bc, t); |
130 #endif | 130 #endif |
131 } | 131 } |
132 | 132 |
| 133 static SkScalar eval_quad_derivative(const SkScalar src[], SkScalar t) { |
| 134 SkScalar A = src[4] - 2 * src[2] + src[0]; |
| 135 SkScalar B = src[2] - src[0]; |
| 136 |
| 137 return 2 * SkScalarMulAdd(A, t, B); |
| 138 } |
| 139 |
133 void SkQuadToCoeff(const SkPoint pts[3], SkPoint coeff[3]) { | 140 void SkQuadToCoeff(const SkPoint pts[3], SkPoint coeff[3]) { |
134 Sk2s p0 = from_point(pts[0]); | 141 Sk2s p0 = from_point(pts[0]); |
135 Sk2s p1 = from_point(pts[1]); | 142 Sk2s p1 = from_point(pts[1]); |
136 Sk2s p2 = from_point(pts[2]); | 143 Sk2s p2 = from_point(pts[2]); |
137 | 144 |
138 Sk2s p1minus2 = p1 - p0; | 145 Sk2s p1minus2 = p1 - p0; |
139 | 146 |
140 coeff[0] = to_point(p2 - p1 - p1 + p0); // A * t^2 | 147 coeff[0] = to_point(p2 - p1 - p1 + p0); // A * t^2 |
141 coeff[1] = to_point(p1minus2 + p1minus2); // B * t | 148 coeff[1] = to_point(p1minus2 + p1minus2); // B * t |
142 coeff[2] = pts[0]; // C | 149 coeff[2] = pts[0]; // C |
143 } | 150 } |
144 | 151 |
145 void SkEvalQuadAt(const SkPoint src[3], SkScalar t, SkPoint* pt, SkVector* tange
nt) { | 152 void SkEvalQuadAt(const SkPoint src[3], SkScalar t, SkPoint* pt, SkVector* tange
nt) { |
146 SkASSERT(src); | 153 SkASSERT(src); |
147 SkASSERT(t >= 0 && t <= SK_Scalar1); | 154 SkASSERT(t >= 0 && t <= SK_Scalar1); |
148 | 155 |
149 if (pt) { | 156 if (pt) { |
150 pt->set(eval_quad(&src[0].fX, t), eval_quad(&src[0].fY, t)); | 157 pt->set(eval_quad(&src[0].fX, t), eval_quad(&src[0].fY, t)); |
151 } | 158 } |
152 if (tangent) { | 159 if (tangent) { |
153 *tangent = SkEvalQuadTangentAt(src, t); | 160 tangent->set(eval_quad_derivative(&src[0].fX, t), |
| 161 eval_quad_derivative(&src[0].fY, t)); |
154 } | 162 } |
155 } | 163 } |
156 | 164 |
157 SkPoint SkEvalQuadAt(const SkPoint src[3], SkScalar t) { | 165 SkPoint SkEvalQuadAt(const SkPoint src[3], SkScalar t) { |
158 SkASSERT(src); | 166 SkASSERT(src); |
159 SkASSERT(t >= 0 && t <= SK_Scalar1); | 167 SkASSERT(t >= 0 && t <= SK_Scalar1); |
160 | 168 |
161 const Sk2s t2(t); | 169 const Sk2s t2(t); |
162 | 170 |
163 Sk2s P0 = from_point(src[0]); | 171 Sk2s P0 = from_point(src[0]); |
164 Sk2s P1 = from_point(src[1]); | 172 Sk2s P1 = from_point(src[1]); |
165 Sk2s P2 = from_point(src[2]); | 173 Sk2s P2 = from_point(src[2]); |
166 | 174 |
167 Sk2s B = P1 - P0; | 175 Sk2s B = P1 - P0; |
168 Sk2s A = P2 - P1 - B; | 176 Sk2s A = P2 - P1 - B; |
169 | 177 |
170 return to_point((A * t2 + B+B) * t2 + P0); | 178 return to_point((A * t2 + B+B) * t2 + P0); |
171 } | 179 } |
172 | 180 |
173 SkVector SkEvalQuadTangentAt(const SkPoint src[3], SkScalar t) { | 181 SkVector SkEvalQuadTangentAt(const SkPoint src[3], SkScalar t) { |
174 // The derivative equation is 2(b - a +(a - 2b +c)t). This returns a | |
175 // zero tangent vector when t is 0 or 1, and the control point is equal | |
176 // to the end point. In this case, use the quad end points to compute the ta
ngent. | |
177 if ((t == 0 && src[0] == src[1]) || (t == 1 && src[1] == src[2])) { | |
178 return src[2] - src[0]; | |
179 } | |
180 SkASSERT(src); | 182 SkASSERT(src); |
181 SkASSERT(t >= 0 && t <= SK_Scalar1); | 183 SkASSERT(t >= 0 && t <= SK_Scalar1); |
182 | 184 |
183 Sk2s P0 = from_point(src[0]); | 185 Sk2s P0 = from_point(src[0]); |
184 Sk2s P1 = from_point(src[1]); | 186 Sk2s P1 = from_point(src[1]); |
185 Sk2s P2 = from_point(src[2]); | 187 Sk2s P2 = from_point(src[2]); |
186 | 188 |
187 Sk2s B = P1 - P0; | 189 Sk2s B = P1 - P0; |
188 Sk2s A = P2 - P1 - B; | 190 Sk2s A = P2 - P1 - B; |
189 Sk2s T = A * Sk2s(t) + B; | 191 Sk2s T = A * Sk2s(t) + B; |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
389 | 391 |
390 void SkEvalCubicAt(const SkPoint src[4], SkScalar t, SkPoint* loc, | 392 void SkEvalCubicAt(const SkPoint src[4], SkScalar t, SkPoint* loc, |
391 SkVector* tangent, SkVector* curvature) { | 393 SkVector* tangent, SkVector* curvature) { |
392 SkASSERT(src); | 394 SkASSERT(src); |
393 SkASSERT(t >= 0 && t <= SK_Scalar1); | 395 SkASSERT(t >= 0 && t <= SK_Scalar1); |
394 | 396 |
395 if (loc) { | 397 if (loc) { |
396 loc->set(eval_cubic(&src[0].fX, t), eval_cubic(&src[0].fY, t)); | 398 loc->set(eval_cubic(&src[0].fX, t), eval_cubic(&src[0].fY, t)); |
397 } | 399 } |
398 if (tangent) { | 400 if (tangent) { |
399 // The derivative equation returns a zero tangent vector when t is 0 or
1, and the | 401 tangent->set(eval_cubic_derivative(&src[0].fX, t), |
400 // adjacent control point is equal to the end point. In this case, use t
he | 402 eval_cubic_derivative(&src[0].fY, t)); |
401 // next control point or the end points to compute the tangent. | |
402 if ((t == 0 && src[0] == src[1]) || (t == 1 && src[2] == src[3])) { | |
403 if (t == 0) { | |
404 *tangent = src[2] - src[0]; | |
405 } else { | |
406 *tangent = src[3] - src[1]; | |
407 } | |
408 if (!tangent->fX && !tangent->fY) { | |
409 *tangent = src[3] - src[0]; | |
410 } | |
411 } else { | |
412 tangent->set(eval_cubic_derivative(&src[0].fX, t), | |
413 eval_cubic_derivative(&src[0].fY, t)); | |
414 } | |
415 } | 403 } |
416 if (curvature) { | 404 if (curvature) { |
417 curvature->set(eval_cubic_2ndDerivative(&src[0].fX, t), | 405 curvature->set(eval_cubic_2ndDerivative(&src[0].fX, t), |
418 eval_cubic_2ndDerivative(&src[0].fY, t)); | 406 eval_cubic_2ndDerivative(&src[0].fY, t)); |
419 } | 407 } |
420 } | 408 } |
421 | 409 |
422 /** Cubic'(t) = At^2 + Bt + C, where | 410 /** Cubic'(t) = At^2 + Bt + C, where |
423 A = 3(-a + 3(b - c) + d) | 411 A = 3(-a + 3(b - c) + d) |
424 B = 6(a - 2b + c) | 412 B = 6(a - 2b + c) |
(...skipping 756 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1181 SkScalar w, | 1169 SkScalar w, |
1182 SkScalar coeff[3]) { | 1170 SkScalar coeff[3]) { |
1183 const SkScalar P20 = src[4] - src[0]; | 1171 const SkScalar P20 = src[4] - src[0]; |
1184 const SkScalar P10 = src[2] - src[0]; | 1172 const SkScalar P10 = src[2] - src[0]; |
1185 const SkScalar wP10 = w * P10; | 1173 const SkScalar wP10 = w * P10; |
1186 coeff[0] = w * P20 - P20; | 1174 coeff[0] = w * P20 - P20; |
1187 coeff[1] = P20 - 2 * wP10; | 1175 coeff[1] = P20 - 2 * wP10; |
1188 coeff[2] = wP10; | 1176 coeff[2] = wP10; |
1189 } | 1177 } |
1190 | 1178 |
| 1179 static SkScalar conic_eval_tan(const SkScalar coord[], SkScalar w, SkScalar t) { |
| 1180 SkScalar coeff[3]; |
| 1181 conic_deriv_coeff(coord, w, coeff); |
| 1182 return t * (t * coeff[0] + coeff[1]) + coeff[2]; |
| 1183 } |
| 1184 |
1191 static bool conic_find_extrema(const SkScalar src[], SkScalar w, SkScalar* t) { | 1185 static bool conic_find_extrema(const SkScalar src[], SkScalar w, SkScalar* t) { |
1192 SkScalar coeff[3]; | 1186 SkScalar coeff[3]; |
1193 conic_deriv_coeff(src, w, coeff); | 1187 conic_deriv_coeff(src, w, coeff); |
1194 | 1188 |
1195 SkScalar tValues[2]; | 1189 SkScalar tValues[2]; |
1196 int roots = SkFindUnitQuadRoots(coeff[0], coeff[1], coeff[2], tValues); | 1190 int roots = SkFindUnitQuadRoots(coeff[0], coeff[1], coeff[2], tValues); |
1197 SkASSERT(0 == roots || 1 == roots); | 1191 SkASSERT(0 == roots || 1 == roots); |
1198 | 1192 |
1199 if (1 == roots) { | 1193 if (1 == roots) { |
1200 *t = tValues[0]; | 1194 *t = tValues[0]; |
(...skipping 30 matching lines...) Expand all Loading... |
1231 } | 1225 } |
1232 | 1226 |
1233 void SkConic::evalAt(SkScalar t, SkPoint* pt, SkVector* tangent) const { | 1227 void SkConic::evalAt(SkScalar t, SkPoint* pt, SkVector* tangent) const { |
1234 SkASSERT(t >= 0 && t <= SK_Scalar1); | 1228 SkASSERT(t >= 0 && t <= SK_Scalar1); |
1235 | 1229 |
1236 if (pt) { | 1230 if (pt) { |
1237 pt->set(conic_eval_pos(&fPts[0].fX, fW, t), | 1231 pt->set(conic_eval_pos(&fPts[0].fX, fW, t), |
1238 conic_eval_pos(&fPts[0].fY, fW, t)); | 1232 conic_eval_pos(&fPts[0].fY, fW, t)); |
1239 } | 1233 } |
1240 if (tangent) { | 1234 if (tangent) { |
1241 *tangent = evalTangentAt(t); | 1235 tangent->set(conic_eval_tan(&fPts[0].fX, fW, t), |
| 1236 conic_eval_tan(&fPts[0].fY, fW, t)); |
1242 } | 1237 } |
1243 } | 1238 } |
1244 | 1239 |
1245 void SkConic::chopAt(SkScalar t, SkConic dst[2]) const { | 1240 void SkConic::chopAt(SkScalar t, SkConic dst[2]) const { |
1246 SkP3D tmp[3], tmp2[3]; | 1241 SkP3D tmp[3], tmp2[3]; |
1247 | 1242 |
1248 ratquad_mapTo3D(fPts, fW, tmp); | 1243 ratquad_mapTo3D(fPts, fW, tmp); |
1249 | 1244 |
1250 p3d_interp(&tmp[0].fX, &tmp2[0].fX, t); | 1245 p3d_interp(&tmp[0].fX, &tmp2[0].fX, t); |
1251 p3d_interp(&tmp[0].fY, &tmp2[0].fY, t); | 1246 p3d_interp(&tmp[0].fY, &tmp2[0].fY, t); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1289 Sk2s numer = quad_poly_eval(A, B, C, tt); | 1284 Sk2s numer = quad_poly_eval(A, B, C, tt); |
1290 | 1285 |
1291 B = times_2(ww - one); | 1286 B = times_2(ww - one); |
1292 A = Sk2s(0)-B; | 1287 A = Sk2s(0)-B; |
1293 Sk2s denom = quad_poly_eval(A, B, one, tt); | 1288 Sk2s denom = quad_poly_eval(A, B, one, tt); |
1294 | 1289 |
1295 return to_point(numer / denom); | 1290 return to_point(numer / denom); |
1296 } | 1291 } |
1297 | 1292 |
1298 SkVector SkConic::evalTangentAt(SkScalar t) const { | 1293 SkVector SkConic::evalTangentAt(SkScalar t) const { |
1299 // The derivative equation returns a zero tangent vector when t is 0 or 1, | |
1300 // and the control point is equal to the end point. | |
1301 // In this case, use the conic endpoints to compute the tangent. | |
1302 if ((t == 0 && fPts[0] == fPts[1]) || (t == 1 && fPts[1] == fPts[2])) { | |
1303 return fPts[2] - fPts[0]; | |
1304 } | |
1305 Sk2s p0 = from_point(fPts[0]); | 1294 Sk2s p0 = from_point(fPts[0]); |
1306 Sk2s p1 = from_point(fPts[1]); | 1295 Sk2s p1 = from_point(fPts[1]); |
1307 Sk2s p2 = from_point(fPts[2]); | 1296 Sk2s p2 = from_point(fPts[2]); |
1308 Sk2s ww(fW); | 1297 Sk2s ww(fW); |
1309 | 1298 |
1310 Sk2s p20 = p2 - p0; | 1299 Sk2s p20 = p2 - p0; |
1311 Sk2s p10 = p1 - p0; | 1300 Sk2s p10 = p1 - p0; |
1312 | 1301 |
1313 Sk2s C = ww * p10; | 1302 Sk2s C = ww * p10; |
1314 Sk2s A = ww * p20 - p20; | 1303 Sk2s A = ww * p20 - p20; |
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1590 matrix.preScale(SK_Scalar1, -SK_Scalar1); | 1579 matrix.preScale(SK_Scalar1, -SK_Scalar1); |
1591 } | 1580 } |
1592 if (userMatrix) { | 1581 if (userMatrix) { |
1593 matrix.postConcat(*userMatrix); | 1582 matrix.postConcat(*userMatrix); |
1594 } | 1583 } |
1595 for (int i = 0; i < conicCount; ++i) { | 1584 for (int i = 0; i < conicCount; ++i) { |
1596 matrix.mapPoints(dst[i].fPts, 3); | 1585 matrix.mapPoints(dst[i].fPts, 3); |
1597 } | 1586 } |
1598 return conicCount; | 1587 return conicCount; |
1599 } | 1588 } |
OLD | NEW |