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

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

Issue 1025033002: use Sk2s for conics (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years, 9 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 | « src/core/SkGeometry.h ('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 "Sk2x.h" 10 #include "Sk2x.h"
11 11
12 static Sk2s from_point(const SkPoint& point) {
13 return Sk2s::Load(&point.fX);
14 }
15
16 static SkPoint to_point(const Sk2s& x) {
17 SkPoint point;
18 x.store(&point.fX);
19 return point;
20 }
21
22 static SkVector to_vector(const Sk2s& x) {
23 SkVector vector;
24 x.store(&vector.fX);
25 return vector;
26 }
27
28 #if 0
29 static Sk2s divide(const Sk2s& numer, const Sk2s& denom) {
30 SkScalar numerStorage[2], denomStorage[2];
31 numer.store(numerStorage);
32 denom.store(denomStorage);
33 numerStorage[0] /= denomStorage[0];
34 numerStorage[1] /= denomStorage[1];
35 return Sk2s::Load(numerStorage);
36 }
37 #endif
38
12 /** If defined, this makes eval_quad and eval_cubic do more setup (sometimes 39 /** If defined, this makes eval_quad and eval_cubic do more setup (sometimes
13 involving integer multiplies by 2 or 3, but fewer calls to SkScalarMul. 40 involving integer multiplies by 2 or 3, but fewer calls to SkScalarMul.
14 May also introduce overflow of fixed when we compute our setup. 41 May also introduce overflow of fixed when we compute our setup.
15 */ 42 */
16 // #define DIRECT_EVAL_OF_POLYNOMIALS 43 // #define DIRECT_EVAL_OF_POLYNOMIALS
17 44
18 //////////////////////////////////////////////////////////////////////// 45 ////////////////////////////////////////////////////////////////////////
19 46
20 static int is_not_monotonic(SkScalar a, SkScalar b, SkScalar c) { 47 static int is_not_monotonic(SkScalar a, SkScalar b, SkScalar c) {
21 SkScalar ab = a - b; 48 SkScalar ab = a - b;
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
85 SkTSwap<SkScalar>(roots[0], roots[1]); 112 SkTSwap<SkScalar>(roots[0], roots[1]);
86 else if (roots[0] == roots[1]) // nearly-equal? 113 else if (roots[0] == roots[1]) // nearly-equal?
87 r -= 1; // skip the double root 114 r -= 1; // skip the double root
88 } 115 }
89 return (int)(r - roots); 116 return (int)(r - roots);
90 } 117 }
91 118
92 /////////////////////////////////////////////////////////////////////////////// 119 ///////////////////////////////////////////////////////////////////////////////
93 /////////////////////////////////////////////////////////////////////////////// 120 ///////////////////////////////////////////////////////////////////////////////
94 121
122 static Sk2s quad_poly_eval(const Sk2s& A, const Sk2s& B, const Sk2s& C, const Sk 2s& t) {
123 return (A * t + B) * t + C;
124 }
125
95 static SkScalar eval_quad(const SkScalar src[], SkScalar t) { 126 static SkScalar eval_quad(const SkScalar src[], SkScalar t) {
96 SkASSERT(src); 127 SkASSERT(src);
97 SkASSERT(t >= 0 && t <= SK_Scalar1); 128 SkASSERT(t >= 0 && t <= SK_Scalar1);
98 129
99 #ifdef DIRECT_EVAL_OF_POLYNOMIALS 130 #ifdef DIRECT_EVAL_OF_POLYNOMIALS
100 SkScalar C = src[0]; 131 SkScalar C = src[0];
101 SkScalar A = src[4] - 2 * src[2] + C; 132 SkScalar A = src[4] - 2 * src[2] + C;
102 SkScalar B = 2 * (src[2] - C); 133 SkScalar B = 2 * (src[2] - C);
103 return SkScalarMulAdd(SkScalarMulAdd(A, t, B), t, C); 134 return SkScalarMulAdd(SkScalarMulAdd(A, t, B), t, C);
104 #else 135 #else
(...skipping 20 matching lines...) Expand all
125 if (tangent) { 156 if (tangent) {
126 tangent->set(eval_quad_derivative(&src[0].fX, t), 157 tangent->set(eval_quad_derivative(&src[0].fX, t),
127 eval_quad_derivative(&src[0].fY, t)); 158 eval_quad_derivative(&src[0].fY, t));
128 } 159 }
129 } 160 }
130 161
131 SkPoint SkEvalQuadAt(const SkPoint src[3], SkScalar t) { 162 SkPoint SkEvalQuadAt(const SkPoint src[3], SkScalar t) {
132 SkASSERT(src); 163 SkASSERT(src);
133 SkASSERT(t >= 0 && t <= SK_Scalar1); 164 SkASSERT(t >= 0 && t <= SK_Scalar1);
134 165
135 const Sk2f t2(t); 166 const Sk2s t2(t);
136 167
137 Sk2f P0 = Sk2f::Load(&src[0].fX); 168 Sk2s P0 = from_point(src[0]);
138 Sk2f P1 = Sk2f::Load(&src[1].fX); 169 Sk2s P1 = from_point(src[1]);
139 Sk2f P2 = Sk2f::Load(&src[2].fX); 170 Sk2s P2 = from_point(src[2]);
140 171
141 Sk2f B = P1 - P0; 172 Sk2s B = P1 - P0;
142 Sk2f A = P2 - P1 - B; 173 Sk2s A = P2 - P1 - B;
143 174
144 SkPoint result; 175 return to_point((A * t2 + B+B) * t2 + P0);
145 ((A * t2 + B+B) * t2 + P0).store(&result.fX);
146 return result;
147 } 176 }
148 177
149 SkVector SkEvalQuadTangentAt(const SkPoint src[3], SkScalar t) { 178 SkVector SkEvalQuadTangentAt(const SkPoint src[3], SkScalar t) {
150 SkASSERT(src); 179 SkASSERT(src);
151 SkASSERT(t >= 0 && t <= SK_Scalar1); 180 SkASSERT(t >= 0 && t <= SK_Scalar1);
152 181
153 Sk2f P0 = Sk2f::Load(&src[0].fX); 182 Sk2s P0 = from_point(src[0]);
154 Sk2f P1 = Sk2f::Load(&src[1].fX); 183 Sk2s P1 = from_point(src[1]);
155 Sk2f P2 = Sk2f::Load(&src[2].fX); 184 Sk2s P2 = from_point(src[2]);
156 185
157 Sk2f B = P1 - P0; 186 Sk2s B = P1 - P0;
158 Sk2f A = P2 - P1 - B; 187 Sk2s A = P2 - P1 - B;
159 Sk2f T = A * Sk2f(t) + B; 188 Sk2s T = A * Sk2s(t) + B;
160 189
161 SkVector result; 190 return to_vector(T + T);
162 (T + T).store(&result.fX);
163 return result;
164 } 191 }
165 192
166 static void interp_quad_coords(const SkScalar* src, SkScalar* dst, SkScalar t) { 193 static void interp_quad_coords(const SkScalar* src, SkScalar* dst, SkScalar t) {
167 SkScalar ab = SkScalarInterp(src[0], src[2], t); 194 SkScalar ab = SkScalarInterp(src[0], src[2], t);
168 SkScalar bc = SkScalarInterp(src[2], src[4], t); 195 SkScalar bc = SkScalarInterp(src[2], src[4], t);
169 196
170 dst[0] = src[0]; 197 dst[0] = src[0];
171 dst[2] = ab; 198 dst[2] = ab;
172 dst[4] = SkScalarInterp(ab, bc, t); 199 dst[4] = SkScalarInterp(ab, bc, t);
173 dst[6] = bc; 200 dst[6] = bc;
174 dst[8] = src[4]; 201 dst[8] = src[4];
175 } 202 }
176 203
177 void SkChopQuadAt(const SkPoint src[3], SkPoint dst[5], SkScalar t) { 204 void SkChopQuadAt(const SkPoint src[3], SkPoint dst[5], SkScalar t) {
178 SkASSERT(t > 0 && t < SK_Scalar1); 205 SkASSERT(t > 0 && t < SK_Scalar1);
179 206
180 interp_quad_coords(&src[0].fX, &dst[0].fX, t); 207 interp_quad_coords(&src[0].fX, &dst[0].fX, t);
181 interp_quad_coords(&src[0].fY, &dst[0].fY, t); 208 interp_quad_coords(&src[0].fY, &dst[0].fY, t);
182 } 209 }
183 210
184 static inline Sk2s interp(const Sk2s& v0, const Sk2s& v1, const Sk2s& t) { 211 static inline Sk2s interp(const Sk2s& v0, const Sk2s& v1, const Sk2s& t) {
185 return v0 + (v1 - v0) * t; 212 return v0 + (v1 - v0) * t;
186 } 213 }
187 214
188 void SkChopQuadAt2(const SkPoint src[3], SkPoint dst[5], SkScalar t) { 215 void SkChopQuadAt2(const SkPoint src[3], SkPoint dst[5], SkScalar t) {
189 SkASSERT(t > 0 && t < SK_Scalar1); 216 SkASSERT(t > 0 && t < SK_Scalar1);
190 217
191 Sk2s p0 = Sk2f::Load(&src[0].fX); 218 Sk2s p0 = from_point(src[0]);
192 Sk2s p1 = Sk2f::Load(&src[1].fX); 219 Sk2s p1 = from_point(src[1]);
193 Sk2s p2 = Sk2f::Load(&src[2].fX); 220 Sk2s p2 = from_point(src[2]);
194 Sk2s tt = Sk2s(t); 221 Sk2s tt = Sk2s(t);
195 222
196 Sk2s p01 = interp(p0, p1, tt); 223 Sk2s p01 = interp(p0, p1, tt);
197 Sk2s p12 = interp(p1, p2, tt); 224 Sk2s p12 = interp(p1, p2, tt);
198 225
199 p0.store(&dst[0].fX); 226 dst[0] = to_point(p0);
200 p01.store(&dst[1].fX); 227 dst[1] = to_point(p01);
201 interp(p01, p12, tt).store(&dst[2].fX); 228 dst[2] = to_point(interp(p01, p12, tt));
202 p12.store(&dst[3].fX); 229 dst[3] = to_point(p12);
203 p2.store(&dst[4].fX); 230 dst[4] = to_point(p2);
204 } 231 }
205 232
206 void SkChopQuadAtHalf(const SkPoint src[3], SkPoint dst[5]) { 233 void SkChopQuadAtHalf(const SkPoint src[3], SkPoint dst[5]) {
207 SkScalar x01 = SkScalarAve(src[0].fX, src[1].fX); 234 SkScalar x01 = SkScalarAve(src[0].fX, src[1].fX);
208 SkScalar y01 = SkScalarAve(src[0].fY, src[1].fY); 235 SkScalar y01 = SkScalarAve(src[0].fY, src[1].fY);
209 SkScalar x12 = SkScalarAve(src[1].fX, src[2].fX); 236 SkScalar x12 = SkScalarAve(src[1].fX, src[2].fX);
210 SkScalar y12 = SkScalarAve(src[1].fY, src[2].fY); 237 SkScalar y12 = SkScalarAve(src[1].fY, src[2].fY);
211 238
212 dst[0] = src[0]; 239 dst[0] = src[0];
213 dst[1].set(x01, y01); 240 dst[1].set(x01, y01);
(...skipping 1030 matching lines...) Expand 10 before | Expand all | Expand 10 after
1244 // w1 /= sqrt(w0*w2) 1271 // w1 /= sqrt(w0*w2)
1245 // 1272 //
1246 // However, in our case, we know that for dst[0]: 1273 // However, in our case, we know that for dst[0]:
1247 // w0 == 1, and for dst[1], w2 == 1 1274 // w0 == 1, and for dst[1], w2 == 1
1248 // 1275 //
1249 SkScalar root = SkScalarSqrt(tmp2[1].fZ); 1276 SkScalar root = SkScalarSqrt(tmp2[1].fZ);
1250 dst[0].fW = tmp2[0].fZ / root; 1277 dst[0].fW = tmp2[0].fZ / root;
1251 dst[1].fW = tmp2[2].fZ / root; 1278 dst[1].fW = tmp2[2].fZ / root;
1252 } 1279 }
1253 1280
1281 static Sk2s times_2(const Sk2s& value) {
1282 return value + value;
1283 }
1284
1285 SkPoint SkConic::evalAt(SkScalar t) const {
1286 Sk2s p0 = from_point(fPts[0]);
1287 Sk2s p1 = from_point(fPts[1]);
1288 Sk2s p2 = from_point(fPts[2]);
1289 Sk2s tt = Sk2s(t);
1290 Sk2s ww = Sk2s(fW);
1291 Sk2s one = Sk2s(1);
1292
1293 Sk2s p1w = p1 * ww;
1294 Sk2s C = p0;
1295 Sk2s A = p2 - times_2(p1w) + p0;
1296 Sk2s B = times_2(p1w - C);
1297 Sk2s numer = quad_poly_eval(A, B, C, tt);
1298
1299 B = times_2(ww - one);
1300 A = -B;
1301 Sk2s denom = quad_poly_eval(A, B, one, tt);
1302
1303 return to_point(numer / denom);
1304 }
1305
1306 SkVector SkConic::evalTangentAt(SkScalar t) const {
1307 Sk2s p0 = from_point(fPts[0]);
1308 Sk2s p1 = from_point(fPts[1]);
1309 Sk2s p2 = from_point(fPts[2]);
1310 Sk2s ww = Sk2s(fW);
1311
1312 Sk2s p20 = p2 - p0;
1313 Sk2s p10 = p1 - p0;
1314
1315 Sk2s C = ww * p10;
1316 Sk2s A = ww * p20 - p20;
1317 Sk2s B = p20 - C - C;
1318
1319 return to_vector(quad_poly_eval(A, B, C, Sk2s(t)));
1320 #if 0
1321 static void conic_deriv_coeff(const SkScalar src[],
1322 SkScalar w,
1323 SkScalar coeff[3]) {
1324 const SkScalar P20 = src[4] - src[0];
1325 const SkScalar P10 = src[2] - src[0];
1326 const SkScalar wP10 = w * P10;
1327 coeff[0] = w * P20 - P20;
1328 coeff[1] = P20 - 2 * wP10;
1329 coeff[2] = wP10;
1330 }
1331
1332 static SkScalar conic_eval_tan(const SkScalar coord[], SkScalar w, SkScalar t) {
1333 SkScalar coeff[3];
1334 conic_deriv_coeff(coord, w, coeff);
1335 return t * (t * coeff[0] + coeff[1]) + coeff[2];
1336 }
1337 #endif
1338 }
1339
1254 static SkScalar subdivide_w_value(SkScalar w) { 1340 static SkScalar subdivide_w_value(SkScalar w) {
1255 return SkScalarSqrt(SK_ScalarHalf + w * SK_ScalarHalf); 1341 return SkScalarSqrt(SK_ScalarHalf + w * SK_ScalarHalf);
1256 } 1342 }
1257 1343
1258 void SkConic::chop(SkConic dst[2]) const { 1344 void SkConic::chop(SkConic dst[2]) const {
1259 SkScalar scale = SkScalarInvert(SK_Scalar1 + fW); 1345 SkScalar scale = SkScalarInvert(SK_Scalar1 + fW);
1260 SkScalar p1x = fW * fPts[1].fX; 1346 SkScalar p1x = fW * fPts[1].fX;
1261 SkScalar p1y = fW * fPts[1].fY; 1347 SkScalar p1y = fW * fPts[1].fY;
1262 SkScalar mx = (fPts[0].fX + 2 * p1x + fPts[2].fX) * scale * SK_ScalarHalf; 1348 SkScalar mx = (fPts[0].fX + 2 * p1x + fPts[2].fX) * scale * SK_ScalarHalf;
1263 SkScalar my = (fPts[0].fY + 2 * p1y + fPts[2].fY) * scale * SK_ScalarHalf; 1349 SkScalar my = (fPts[0].fY + 2 * p1y + fPts[2].fY) * scale * SK_ScalarHalf;
1264 1350
1265 dst[0].fPts[0] = fPts[0]; 1351 dst[0].fPts[0] = fPts[0];
1266 dst[0].fPts[1].set((fPts[0].fX + p1x) * scale, 1352 dst[0].fPts[1].set((fPts[0].fX + p1x) * scale,
1267 (fPts[0].fY + p1y) * scale); 1353 (fPts[0].fY + p1y) * scale);
1268 dst[0].fPts[2].set(mx, my); 1354 dst[0].fPts[2].set(mx, my);
1269 1355
1270 dst[1].fPts[0].set(mx, my); 1356 dst[1].fPts[0].set(mx, my);
1271 dst[1].fPts[1].set((p1x + fPts[2].fX) * scale, 1357 dst[1].fPts[1].set((p1x + fPts[2].fX) * scale,
1272 (p1y + fPts[2].fY) * scale); 1358 (p1y + fPts[2].fY) * scale);
1273 dst[1].fPts[2] = fPts[2]; 1359 dst[1].fPts[2] = fPts[2];
1274 1360
1275 dst[0].fW = dst[1].fW = subdivide_w_value(fW); 1361 dst[0].fW = dst[1].fW = subdivide_w_value(fW);
1276 } 1362 }
1277 1363
1364 void SkConic::chop2(SkConic * SK_RESTRICT dst) const {
1365 Sk2s scale(SkScalarInvert(SK_Scalar1 + fW));
1366 // Sk2s scale = Sk2s(SK_Scalar1 + fW).invert();
1367 SkScalar newW = subdivide_w_value(fW);
1368
1369 Sk2s p0 = from_point(fPts[0]);
1370 Sk2s p1 = from_point(fPts[1]);
1371 Sk2s p2 = from_point(fPts[2]);
1372 Sk2s ww = Sk2s(fW);
1373 Sk2s half = Sk2s(0.5f);
1374
1375 Sk2s wp1 = ww * p1;
1376 Sk2s m = ((p0 + wp1 + wp1 + p2) * half) * scale;
1377
1378 dst[0].fPts[0] = fPts[0];
1379 dst[0].fPts[1] = to_point((p0 + wp1) * scale);
1380 dst[0].fPts[2] = dst[1].fPts[0] = to_point(m);
1381 dst[1].fPts[1] = to_point((wp1 + p2) * scale);
1382 dst[1].fPts[2] = fPts[2];
1383
1384 dst[0].fW = dst[1].fW = newW;
1385 }
1386
1278 /* 1387 /*
1279 * "High order approximation of conic sections by quadratic splines" 1388 * "High order approximation of conic sections by quadratic splines"
1280 * by Michael Floater, 1993 1389 * by Michael Floater, 1993
1281 */ 1390 */
1282 #define AS_QUAD_ERROR_SETUP \ 1391 #define AS_QUAD_ERROR_SETUP \
1283 SkScalar a = fW - 1; \ 1392 SkScalar a = fW - 1; \
1284 SkScalar k = a / (4 * (2 + a)); \ 1393 SkScalar k = a / (4 * (2 + a)); \
1285 SkScalar x = k * (fPts[0].fX - 2 * fPts[1].fX + fPts[2].fX); \ 1394 SkScalar x = k * (fPts[0].fX - 2 * fPts[1].fX + fPts[2].fX); \
1286 SkScalar y = k * (fPts[0].fY - 2 * fPts[1].fY + fPts[2].fY); 1395 SkScalar y = k * (fPts[0].fY - 2 * fPts[1].fY + fPts[2].fY);
1287 1396
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after
1517 matrix.preScale(SK_Scalar1, -SK_Scalar1); 1626 matrix.preScale(SK_Scalar1, -SK_Scalar1);
1518 } 1627 }
1519 if (userMatrix) { 1628 if (userMatrix) {
1520 matrix.postConcat(*userMatrix); 1629 matrix.postConcat(*userMatrix);
1521 } 1630 }
1522 for (int i = 0; i < conicCount; ++i) { 1631 for (int i = 0; i < conicCount; ++i) {
1523 matrix.mapPoints(dst[i].fPts, 3); 1632 matrix.mapPoints(dst[i].fPts, 3);
1524 } 1633 }
1525 return conicCount; 1634 return conicCount;
1526 } 1635 }
OLDNEW
« no previous file with comments | « src/core/SkGeometry.h ('k') | tests/GeometryTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698