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