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

Side by Side Diff: src/pathops/SkPathOpsCubic.cpp

Issue 265453009: remove inverse_paths from ignored tests (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: experiment with 128 bit floats Created 6 years, 7 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/pathops/SkPathOpsCubic.h ('k') | src/pathops/SkPathOpsDebug.h » ('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 2012 Google Inc. 2 * Copyright 2012 Google Inc.
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 #include "SkLineParameters.h" 7 #include "SkLineParameters.h"
8 #include "SkPathOpsCubic.h" 8 #include "SkPathOpsCubic.h"
9 #include "SkPathOpsLine.h" 9 #include "SkPathOpsLine.h"
10 #include "SkPathOpsQuad.h" 10 #include "SkPathOpsQuad.h"
11 #include "SkPathOpsRect.h" 11 #include "SkPathOpsRect.h"
12 12
13 const int SkDCubic::gPrecisionUnit = 256; // FIXME: test different values in te st framework 13 const int SkDCubic::gPrecisionUnit = 256; // FIXME: test different values in te st framework
14 14
15 int SkDCubic::AddValidTs(double allRoots[3], int realRoots, double validRoots[3] ) {
16 int valid = SkDQuad::AddValidTs(allRoots, realRoots, validRoots);
17 if (valid != 1) {
18 return valid;
19 }
20 if (realRoots == 1) {
21 return valid;
22 }
23 return -1;
24 }
25
26 double SkDCubic::binarySearch(double step, double t, double axisIntercept, bool yAxis) const {
27 do {
28 SkDPoint cubicAtT = ptAtT(t);
29 double calcDist = yAxis ? cubicAtT.fX : cubicAtT.fY;
30 if (approximately_equal(calcDist, axisIntercept)) {
31 break;
32 }
33 if (step == 0) {
34 return -1; // binary search with this step failed
35 }
36 calcDist = fabs(calcDist - axisIntercept);
37 double lastStep = step;
38 step /= 2;
39 SkDPoint lessPt = ptAtT(t - lastStep);
40 double lessDist = fabs((yAxis ? lessPt.fX : lessPt.fY) - axisIntercept);
41 if (calcDist > lessDist) {
42 t -= step;
43 t = SkTMax(0., t);
44 } else {
45 SkDPoint morePt = ptAtT(t + lastStep);
46 double moreDist = fabs((yAxis ? morePt.fX : morePt.fY) - axisInterce pt);
47 if (calcDist <= moreDist) {
48 continue;
49 }
50 t += step;
51 t = SkTMin(1., t);
52 }
53 } while (true);
54 return t;
55 }
56
15 // FIXME: cache keep the bounds and/or precision with the caller? 57 // FIXME: cache keep the bounds and/or precision with the caller?
16 double SkDCubic::calcPrecision() const { 58 double SkDCubic::calcPrecision() const {
17 SkDRect dRect; 59 SkDRect dRect;
18 dRect.setBounds(*this); // OPTIMIZATION: just use setRawBounds ? 60 dRect.setBounds(*this); // OPTIMIZATION: just use setRawBounds ?
19 double width = dRect.fRight - dRect.fLeft; 61 double width = dRect.fRight - dRect.fLeft;
20 double height = dRect.fBottom - dRect.fTop; 62 double height = dRect.fBottom - dRect.fTop;
21 return (width > height ? width : height) / gPrecisionUnit; 63 return (width > height ? width : height) / gPrecisionUnit;
22 } 64 }
23 65
24 bool SkDCubic::clockwise() const { 66 bool SkDCubic::clockwise() const {
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 } 128 }
87 distance = lineParameters.controlPtDistance(*this, 2); 129 distance = lineParameters.controlPtDistance(*this, 2);
88 return approximately_zero(distance); 130 return approximately_zero(distance);
89 } 131 }
90 132
91 bool SkDCubic::monotonicInY() const { 133 bool SkDCubic::monotonicInY() const {
92 return between(fPts[0].fY, fPts[1].fY, fPts[3].fY) 134 return between(fPts[0].fY, fPts[1].fY, fPts[3].fY)
93 && between(fPts[0].fY, fPts[2].fY, fPts[3].fY); 135 && between(fPts[0].fY, fPts[2].fY, fPts[3].fY);
94 } 136 }
95 137
138 void SkDCubic::searchRoots(double allRoots[3], int realRoots, double* tPtr, doub le axisIntercept,
139 bool yAxis) const {
140 double largest = SkTMax(fabs(allRoots[0]), fabs(allRoots[1]));
141 if (realRoots == 3) {
142 largest = SkTMax(largest, fabs(allRoots[2]));
143 }
144 int largeBits;
145 if (largest <= 1) {
146 double smallest = SkTMin(allRoots[0], allRoots[1]);
147 if (realRoots == 3) {
148 smallest = SkTMin(smallest, allRoots[2]);
149 }
150 SkASSERT(smallest < 0);
151 SkASSERT(smallest >= -1);
152 largeBits = 0;
153 } else {
154 (void) frexp(largest, &largeBits);
155 SkASSERT(largeBits >= 0);
156 SkASSERT(largeBits < 256);
157 }
158 double step = 1e-6;
159 if (largeBits > 21) {
160 step = 1e-1;
161 } else if (largeBits > 18) {
162 step = 1e-2;
163 } else if (largeBits > 15) {
164 step = 1e-3;
165 } else if (largeBits > 12) {
166 step = 1e-4;
167 } else if (largeBits > 9) {
168 step = 1e-5;
169 }
170 do {
171 double newT = binarySearch(step, *tPtr, axisIntercept, yAxis);
172 if (newT >= 0) {
173 *tPtr = newT;
174 return;
175 }
176 step *= 1.5;
177 SkASSERT(step < 1);
178 } while (true);
179 }
180
96 bool SkDCubic::serpentine() const { 181 bool SkDCubic::serpentine() const {
97 #if 0 // FIXME: enabling this fixes cubicOp114 but breaks cubicOp58d and cubicO p53d 182 #if 0 // FIXME: enabling this fixes cubicOp114 but breaks cubicOp58d and cubicO p53d
98 double tValues[2]; 183 double tValues[2];
99 // OPTIMIZATION : another case where caching the present of cubic inflection s would be useful 184 // OPTIMIZATION : another case where caching the present of cubic inflection s would be useful
100 return findInflections(tValues) > 1; 185 return findInflections(tValues) > 1;
101 #endif 186 #endif
102 if (!controlsContainedByEnds()) { 187 if (!controlsContainedByEnds()) {
103 return false; 188 return false;
104 } 189 }
105 double wiggle = (fPts[0].fX - fPts[2].fX) * (fPts[0].fY + fPts[2].fY); 190 double wiggle = (fPts[0].fX - fPts[2].fX) * (fPts[0].fY + fPts[2].fY);
106 for (int idx = 0; idx < 2; ++idx) { 191 for (int idx = 0; idx < 2; ++idx) {
107 wiggle += (fPts[idx + 1].fX - fPts[idx].fX) * (fPts[idx + 1].fY + fPts[i dx].fY); 192 wiggle += (fPts[idx + 1].fX - fPts[idx].fX) * (fPts[idx + 1].fY + fPts[i dx].fY);
108 } 193 }
109 double waggle = (fPts[1].fX - fPts[3].fX) * (fPts[1].fY + fPts[3].fY); 194 double waggle = (fPts[1].fX - fPts[3].fX) * (fPts[1].fY + fPts[3].fY);
110 for (int idx = 1; idx < 3; ++idx) { 195 for (int idx = 1; idx < 3; ++idx) {
111 waggle += (fPts[idx + 1].fX - fPts[idx].fX) * (fPts[idx + 1].fY + fPts[i dx].fY); 196 waggle += (fPts[idx + 1].fX - fPts[idx].fX) * (fPts[idx + 1].fY + fPts[i dx].fY);
112 } 197 }
113 return wiggle * waggle < 0; 198 return wiggle * waggle < 0;
114 } 199 }
115 200
116 // cubic roots 201 // cubic roots
117 202
118 static const double PI = 3.141592653589793; 203 static const double PI = 3.141592653589793;
119 204
120 // from SkGeometry.cpp (and Numeric Solutions, 5.6) 205 // from SkGeometry.cpp (and Numeric Solutions, 5.6)
206 int SkDCubic::RootsValidT(double A, double B, double C, double D, double s[3], i nt* sCount,
207 double t[3]) {
208 *sCount = RootsReal(A, B, C, D, s);
209 int foundRoots = SkDCubic::AddValidTs(s, *sCount, t);
210 return foundRoots;
211 }
212
121 int SkDCubic::RootsValidT(double A, double B, double C, double D, double t[3]) { 213 int SkDCubic::RootsValidT(double A, double B, double C, double D, double t[3]) {
122 double s[3]; 214 double s[3];
123 int realRoots = RootsReal(A, B, C, D, s); 215 int realRoots = RootsReal(A, B, C, D, s);
124 int foundRoots = SkDQuad::AddValidTs(s, realRoots, t); 216 int foundRoots = SkDQuad::AddValidTs(s, realRoots, t);
125 return foundRoots; 217 return foundRoots;
126 } 218 }
127 219
128 int SkDCubic::RootsReal(double A, double B, double C, double D, double s[3]) { 220 int SkDCubic::RootsReal(double A, double B, double C, double D, double s[3]) {
129 #ifdef SK_DEBUG 221 #ifdef SK_DEBUG
130 // create a string mathematica understands 222 // create a string mathematica understands
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
173 a = B * invA; 265 a = B * invA;
174 b = C * invA; 266 b = C * invA;
175 c = D * invA; 267 c = D * invA;
176 } 268 }
177 double a2 = a * a; 269 double a2 = a * a;
178 double Q = (a2 - b * 3) / 9; 270 double Q = (a2 - b * 3) / 9;
179 double R = (2 * a2 * a - 9 * a * b + 27 * c) / 54; 271 double R = (2 * a2 * a - 9 * a * b + 27 * c) / 54;
180 double R2 = R * R; 272 double R2 = R * R;
181 double Q3 = Q * Q * Q; 273 double Q3 = Q * Q * Q;
182 double R2MinusQ3 = R2 - Q3; 274 double R2MinusQ3 = R2 - Q3;
275 double R2Q3Max = SkTMax(R2, fabs(Q3));
276 if (R2Q3Max * FLT_EPSILON > fabs(R2MinusQ3)) {
277 #if defined(__clang__) || defined(__GNUC__)
278 __float128 R2_128 = (__float128) R * (__float128) R;
279 __float128 Q3_128 = (__float128) Q * (__float128) Q * (__float128) Q;
280 __float128 R2MinusQ3_128 = R2_128 - Q3_128;
281 R2MinusQ3 = (double) R2MinusQ3_128;
282 #else
283 SkFloat128 R2_128 = SkFloat128Mul(R, R);
284 SkFloat128 Q3_128 = SkFloat128Mul(Q, Q);
285 Q3_128 = SkFloat128Mul(Q3_128, Q);
286 R2MinusQ3 = SkFloat128Sub(R2_128, Q3_128);
287 #endif
288 }
183 double adiv3 = a / 3; 289 double adiv3 = a / 3;
184 double r; 290 double r;
185 double* roots = s; 291 double* roots = s;
186 if (R2MinusQ3 < 0) { // we have 3 real roots 292 if (R2MinusQ3 < 0) { // we have 3 real roots
187 double theta = acos(R / sqrt(Q3)); 293 double theta = acos(R / sqrt(Q3));
188 double neg2RootQ = -2 * sqrt(Q); 294 double neg2RootQ = -2 * sqrt(Q);
189 295
190 r = neg2RootQ * cos(theta / 3) - adiv3; 296 r = neg2RootQ * cos(theta / 3) - adiv3;
191 *roots++ = r; 297 *roots++ = r;
192 298
(...skipping 10 matching lines...) Expand all
203 double A = fabs(R) + sqrtR2MinusQ3; 309 double A = fabs(R) + sqrtR2MinusQ3;
204 A = SkDCubeRoot(A); 310 A = SkDCubeRoot(A);
205 if (R > 0) { 311 if (R > 0) {
206 A = -A; 312 A = -A;
207 } 313 }
208 if (A != 0) { 314 if (A != 0) {
209 A += Q / A; 315 A += Q / A;
210 } 316 }
211 r = A - adiv3; 317 r = A - adiv3;
212 *roots++ = r; 318 *roots++ = r;
213 if (AlmostDequalUlps(R2, Q3)) { 319 if (AlmostDequalUlps((double) R2, (double) Q3)) {
214 r = -A / 2 - adiv3; 320 r = -A / 2 - adiv3;
215 if (!AlmostDequalUlps(s[0], r)) { 321 if (!AlmostDequalUlps(s[0], r)) {
216 *roots++ = r; 322 *roots++ = r;
217 } 323 }
218 } 324 }
219 } 325 }
220 return static_cast<int>(roots - s); 326 return static_cast<int>(roots - s);
221 } 327 }
222 328
223 // from http://www.cs.sunysb.edu/~qin/courses/geometry/4.pdf 329 // from http://www.cs.sunysb.edu/~qin/courses/geometry/4.pdf
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after
506 dst.pts[4].fY = (fPts[1].fY + 2 * fPts[2].fY + fPts[3].fY) / 4; 612 dst.pts[4].fY = (fPts[1].fY + 2 * fPts[2].fY + fPts[3].fY) / 4;
507 dst.pts[5].fX = (fPts[2].fX + fPts[3].fX) / 2; 613 dst.pts[5].fX = (fPts[2].fX + fPts[3].fX) / 2;
508 dst.pts[5].fY = (fPts[2].fY + fPts[3].fY) / 2; 614 dst.pts[5].fY = (fPts[2].fY + fPts[3].fY) / 2;
509 dst.pts[6] = fPts[3]; 615 dst.pts[6] = fPts[3];
510 return dst; 616 return dst;
511 } 617 }
512 interp_cubic_coords(&fPts[0].fX, &dst.pts[0].fX, t); 618 interp_cubic_coords(&fPts[0].fX, &dst.pts[0].fX, t);
513 interp_cubic_coords(&fPts[0].fY, &dst.pts[0].fY, t); 619 interp_cubic_coords(&fPts[0].fY, &dst.pts[0].fY, t);
514 return dst; 620 return dst;
515 } 621 }
OLDNEW
« no previous file with comments | « src/pathops/SkPathOpsCubic.h ('k') | src/pathops/SkPathOpsDebug.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698