Handle subnormal properly in close_to_linear
The old code just assumed that if both A and B were close
to zero that B would not dominate A forcing linear
behavior. This is not necessarily the case, so check to
make sure.
Change-Id: I0ff4098ece02abbb49b2ba0ae4f429b5dccb8558
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/705226
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Commit-Queue: Herb Derby <herb@google.com>
diff --git a/src/base/SkQuads.cpp b/src/base/SkQuads.cpp
index 41635aa..0997033 100644
--- a/src/base/SkQuads.cpp
+++ b/src/base/SkQuads.cpp
@@ -27,17 +27,18 @@
return 1;
}
-// When the A coefficient of a quadratic is close to 0, there can be floating point error
-// that arises from computing a very large root. In those cases, we would rather be
-// precise about the one smaller root, so we have this arbitrary cutoff for when A is
-// really small or small compared to B.
+// When B >> A, then the x^2 component doesn't contribute much to the output, so the second root
+// will be very large, but have massive round off error. Because of the round off error, the
+// second root will not evaluate to zero when substituted back into the quadratic equation. In
+// the situation when B >> A, then just treat the quadratic as a linear equation.
static bool close_to_linear(double A, double B) {
- if (sk_double_nearly_zero(B)) {
- return sk_double_nearly_zero(A);
+ if (A != 0) {
+ // Return if B is much bigger than A.
+ return std::abs(B / A) >= 1.0e+16;
}
- // This is a different threshold (tighter) than the close_to_a_quadratic in SkCubics.cpp
- // because the SkQuads::RootsReal gives better answers for longer as A/B -> 0.
- return std::abs(A / B) < 1.0e-16;
+
+ // Otherwise A is zero, and the quadratic is linear.
+ return true;
}
double SkQuads::Discriminant(const double a, const double b, const double c) {