begin to wrap all float divides
Bug: skia:7607 skia:6134
Change-Id: Id126e92816bef1df1372bd531238cda9f3b36fab
Reviewed-on: https://skia-review.googlesource.com/106261
Reviewed-by: Mike Klein <mtklein@chromium.org>
Commit-Queue: Mike Reed <reed@google.com>
diff --git a/include/core/SkScalar.h b/include/core/SkScalar.h
index 936a006..9c015e5 100644
--- a/include/core/SkScalar.h
+++ b/include/core/SkScalar.h
@@ -134,10 +134,11 @@
static inline SkScalar SkScalarSquare(SkScalar x) { return x * x; }
-#define SkScalarInvert(x) (SK_Scalar1 / (x))
-#define SkScalarFastInvert(x) (SK_Scalar1 / (x))
-#define SkScalarAve(a, b) (((a) + (b)) * SK_ScalarHalf)
-#define SkScalarHalf(a) ((a) * SK_ScalarHalf)
+#define SkScalarDiv(numer, denom) sk_ieee_float_divide(numer, denom)
+#define SkScalarInvert(x) sk_ieee_float_divide(SK_Scalar1, (x))
+#define SkScalarFastInvert(x) sk_ieee_float_divide(SK_Scalar1, (x))
+#define SkScalarAve(a, b) (((a) + (b)) * SK_ScalarHalf)
+#define SkScalarHalf(a) ((a) * SK_ScalarHalf)
#define SkDegreesToRadians(degrees) ((degrees) * (SK_ScalarPI / 180))
#define SkRadiansToDegrees(radians) ((radians) * (180 / SK_ScalarPI))
diff --git a/include/private/SkFloatingPoint.h b/include/private/SkFloatingPoint.h
index bbb1179..a2e6ee5 100644
--- a/include/private/SkFloatingPoint.h
+++ b/include/private/SkFloatingPoint.h
@@ -190,4 +190,14 @@
#define SK_FLT_DECIMAL_DIG 9
#endif
+// IEEE defines how float divide behaves for non-finite values and zero-denoms, but C does not
+// so we have a helper that suppresses the possible undefined-behavior warnings.
+
+#ifdef __clang__
+__attribute__((no_sanitize("float-divide-by-zero")))
+#endif
+static inline float sk_ieee_float_divide(float numer, float denom) {
+ return numer / denom;
+}
+
#endif
diff --git a/src/core/SkMatrix.cpp b/src/core/SkMatrix.cpp
index 9a70fbb..778d77c 100644
--- a/src/core/SkMatrix.cpp
+++ b/src/core/SkMatrix.cpp
@@ -6,6 +6,7 @@
*/
#include "SkFloatBits.h"
+#include "SkMathPriv.h"
#include "SkMatrixPriv.h"
#include "SkNx.h"
#include "SkPaint.h"
@@ -1363,32 +1364,32 @@
/* check if abs(x2) > abs(y2) */
if ( x2 > 0 ? y2 > 0 ? x2 > y2 : x2 > -y2 : y2 > 0 ? -x2 > y2 : x2 < y2) {
- float denom = (x1 * y2 / x2) - y1;
+ float denom = sk_ieee_float_divide(x1 * y2, x2) - y1;
if (checkForZero(denom)) {
return false;
}
a1 = (((x0 - x1) * y2 / x2) - y0 + y1) / denom;
} else {
- float denom = x1 - (y1 * x2 / y2);
+ float denom = x1 - sk_ieee_float_divide(y1 * x2, y2);
if (checkForZero(denom)) {
return false;
}
- a1 = (x0 - x1 - ((y0 - y1) * x2 / y2)) / denom;
+ a1 = (x0 - x1 - sk_ieee_float_divide((y0 - y1) * x2, y2)) / denom;
}
/* check if abs(x1) > abs(y1) */
if ( x1 > 0 ? y1 > 0 ? x1 > y1 : x1 > -y1 : y1 > 0 ? -x1 > y1 : x1 < y1) {
- float denom = y2 - (x2 * y1 / x1);
+ float denom = y2 - sk_ieee_float_divide(x2 * y1, x1);
if (checkForZero(denom)) {
return false;
}
- a2 = (y0 - y2 - ((x0 - x2) * y1 / x1)) / denom;
+ a2 = (y0 - y2 - sk_ieee_float_divide((x0 - x2) * y1, x1)) / denom;
} else {
- float denom = (y2 * x1 / y1) - x2;
+ float denom = sk_ieee_float_divide(y2 * x1, y1) - x2;
if (checkForZero(denom)) {
return false;
}
- a2 = (((y0 - y2) * x1 / y1) - x0 + x2) / denom;
+ a2 = (sk_ieee_float_divide((y0 - y2) * x1, y1) - x0 + x2) / denom;
}
float invScale = SkScalarInvert(scale.fX);
diff --git a/src/effects/SkEmbossMaskFilter.cpp b/src/effects/SkEmbossMaskFilter.cpp
index 9fa26c5..9f4a54a8b 100644
--- a/src/effects/SkEmbossMaskFilter.cpp
+++ b/src/effects/SkEmbossMaskFilter.cpp
@@ -14,8 +14,27 @@
#include "SkWriteBuffer.h"
#include "SkString.h"
+static void normalize3(SkScalar dst[3], const SkScalar src[3]) {
+ SkScalar mag = SkScalarSquare(src[0]) + SkScalarSquare(src[1]) + SkScalarSquare(src[2]);
+ SkScalar scale = SkScalarInvert(SkScalarSqrt(mag));
+
+ for (int i = 0; i < 3; i++) {
+ dst[i] = src[i] * scale;
+ }
+}
+
sk_sp<SkMaskFilter> SkEmbossMaskFilter::Make(SkScalar blurSigma, const Light& light) {
- return sk_sp<SkMaskFilter>(new SkEmbossMaskFilter(blurSigma, light));
+ if (!SkScalarIsFinite(blurSigma) || blurSigma <= 0) {
+ return nullptr;
+ }
+
+ Light newLight = light;
+ normalize3(newLight.fDirection, light.fDirection);
+ if (SkScalarsAreFinite(newLight.fDirection, 3)) {
+ return nullptr;
+ }
+
+ return sk_sp<SkMaskFilter>(new SkEmbossMaskFilter(blurSigma, newLight));
}
#ifdef SK_SUPPORT_LEGACY_EMBOSSMASKFILTER
@@ -40,18 +59,11 @@
///////////////////////////////////////////////////////////////////////////////
-static void normalize(SkScalar v[3]) {
- SkScalar mag = SkScalarSquare(v[0]) + SkScalarSquare(v[1]) + SkScalarSquare(v[2]);
- mag = SkScalarSqrt(mag);
-
- for (int i = 0; i < 3; i++) {
- v[i] /= mag;
- }
-}
-
SkEmbossMaskFilter::SkEmbossMaskFilter(SkScalar blurSigma, const Light& light)
- : fLight(light), fBlurSigma(blurSigma) {
- normalize(fLight.fDirection);
+ : fLight(light), fBlurSigma(blurSigma)
+{
+ SkASSERT(fBlurSigma > 0);
+ SkASSERT(SkScalarsAreFinite(fLight.fDirection, 3));
}
SkMask::Format SkEmbossMaskFilter::getFormat() const {