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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/pathops/SkPathOpsCubic.h ('k') | src/pathops/SkPathOpsDebug.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/pathops/SkPathOpsCubic.cpp
diff --git a/src/pathops/SkPathOpsCubic.cpp b/src/pathops/SkPathOpsCubic.cpp
index a89604f94cafa98ae9617868cf36bf86014151aa..59e829643b612c2061158255a641dd34e610e850 100644
--- a/src/pathops/SkPathOpsCubic.cpp
+++ b/src/pathops/SkPathOpsCubic.cpp
@@ -12,6 +12,48 @@
const int SkDCubic::gPrecisionUnit = 256; // FIXME: test different values in test framework
+int SkDCubic::AddValidTs(double allRoots[3], int realRoots, double validRoots[3]) {
+ int valid = SkDQuad::AddValidTs(allRoots, realRoots, validRoots);
+ if (valid != 1) {
+ return valid;
+ }
+ if (realRoots == 1) {
+ return valid;
+ }
+ return -1;
+}
+
+double SkDCubic::binarySearch(double step, double t, double axisIntercept, bool yAxis) const {
+ do {
+ SkDPoint cubicAtT = ptAtT(t);
+ double calcDist = yAxis ? cubicAtT.fX : cubicAtT.fY;
+ if (approximately_equal(calcDist, axisIntercept)) {
+ break;
+ }
+ if (step == 0) {
+ return -1; // binary search with this step failed
+ }
+ calcDist = fabs(calcDist - axisIntercept);
+ double lastStep = step;
+ step /= 2;
+ SkDPoint lessPt = ptAtT(t - lastStep);
+ double lessDist = fabs((yAxis ? lessPt.fX : lessPt.fY) - axisIntercept);
+ if (calcDist > lessDist) {
+ t -= step;
+ t = SkTMax(0., t);
+ } else {
+ SkDPoint morePt = ptAtT(t + lastStep);
+ double moreDist = fabs((yAxis ? morePt.fX : morePt.fY) - axisIntercept);
+ if (calcDist <= moreDist) {
+ continue;
+ }
+ t += step;
+ t = SkTMin(1., t);
+ }
+ } while (true);
+ return t;
+}
+
// FIXME: cache keep the bounds and/or precision with the caller?
double SkDCubic::calcPrecision() const {
SkDRect dRect;
@@ -93,6 +135,49 @@ bool SkDCubic::monotonicInY() const {
&& between(fPts[0].fY, fPts[2].fY, fPts[3].fY);
}
+void SkDCubic::searchRoots(double allRoots[3], int realRoots, double* tPtr, double axisIntercept,
+ bool yAxis) const {
+ double largest = SkTMax(fabs(allRoots[0]), fabs(allRoots[1]));
+ if (realRoots == 3) {
+ largest = SkTMax(largest, fabs(allRoots[2]));
+ }
+ int largeBits;
+ if (largest <= 1) {
+ double smallest = SkTMin(allRoots[0], allRoots[1]);
+ if (realRoots == 3) {
+ smallest = SkTMin(smallest, allRoots[2]);
+ }
+ SkASSERT(smallest < 0);
+ SkASSERT(smallest >= -1);
+ largeBits = 0;
+ } else {
+ (void) frexp(largest, &largeBits);
+ SkASSERT(largeBits >= 0);
+ SkASSERT(largeBits < 256);
+ }
+ double step = 1e-6;
+ if (largeBits > 21) {
+ step = 1e-1;
+ } else if (largeBits > 18) {
+ step = 1e-2;
+ } else if (largeBits > 15) {
+ step = 1e-3;
+ } else if (largeBits > 12) {
+ step = 1e-4;
+ } else if (largeBits > 9) {
+ step = 1e-5;
+ }
+ do {
+ double newT = binarySearch(step, *tPtr, axisIntercept, yAxis);
+ if (newT >= 0) {
+ *tPtr = newT;
+ return;
+ }
+ step *= 1.5;
+ SkASSERT(step < 1);
+ } while (true);
+}
+
bool SkDCubic::serpentine() const {
#if 0 // FIXME: enabling this fixes cubicOp114 but breaks cubicOp58d and cubicOp53d
double tValues[2];
@@ -118,6 +203,13 @@ bool SkDCubic::serpentine() const {
static const double PI = 3.141592653589793;
// from SkGeometry.cpp (and Numeric Solutions, 5.6)
+int SkDCubic::RootsValidT(double A, double B, double C, double D, double s[3], int* sCount,
+ double t[3]) {
+ *sCount = RootsReal(A, B, C, D, s);
+ int foundRoots = SkDCubic::AddValidTs(s, *sCount, t);
+ return foundRoots;
+}
+
int SkDCubic::RootsValidT(double A, double B, double C, double D, double t[3]) {
double s[3];
int realRoots = RootsReal(A, B, C, D, s);
@@ -180,6 +272,20 @@ int SkDCubic::RootsReal(double A, double B, double C, double D, double s[3]) {
double R2 = R * R;
double Q3 = Q * Q * Q;
double R2MinusQ3 = R2 - Q3;
+ double R2Q3Max = SkTMax(R2, fabs(Q3));
+ if (R2Q3Max * FLT_EPSILON > fabs(R2MinusQ3)) {
+#if defined(__clang__) || defined(__GNUC__)
+ __float128 R2_128 = (__float128) R * (__float128) R;
+ __float128 Q3_128 = (__float128) Q * (__float128) Q * (__float128) Q;
+ __float128 R2MinusQ3_128 = R2_128 - Q3_128;
+ R2MinusQ3 = (double) R2MinusQ3_128;
+#else
+ SkFloat128 R2_128 = SkFloat128Mul(R, R);
+ SkFloat128 Q3_128 = SkFloat128Mul(Q, Q);
+ Q3_128 = SkFloat128Mul(Q3_128, Q);
+ R2MinusQ3 = SkFloat128Sub(R2_128, Q3_128);
+#endif
+ }
double adiv3 = a / 3;
double r;
double* roots = s;
@@ -210,7 +316,7 @@ int SkDCubic::RootsReal(double A, double B, double C, double D, double s[3]) {
}
r = A - adiv3;
*roots++ = r;
- if (AlmostDequalUlps(R2, Q3)) {
+ if (AlmostDequalUlps((double) R2, (double) Q3)) {
r = -A / 2 - adiv3;
if (!AlmostDequalUlps(s[0], r)) {
*roots++ = r;
« 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