Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(79)

Side by Side Diff: src/core/SkGeometry.cpp

Issue 1312243002: Revert of fix zero-length tangent (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « gm/strokes.cpp ('k') | tests/GeometryTest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « gm/strokes.cpp ('k') | tests/GeometryTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698