update SkTPin()
- Reword the comment to explain how it differs from std::clamp().
- Document and test an alternative form using std::{min,max}.
Change-Id: I3a97b98a15303478a5a7ff8d0536829f6d5f1586
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/327696
Reviewed-by: Chris Dalton <csmartdalton@google.com>
Commit-Queue: Mike Klein <mtklein@google.com>
diff --git a/include/core/SkTypes.h b/include/core/SkTypes.h
index 9f7c1d7..34938b9 100644
--- a/include/core/SkTypes.h
+++ b/include/core/SkTypes.h
@@ -581,13 +581,21 @@
return value;
}
-/** @return value pinned (clamped) between min and max, inclusively.
+/** @return x pinned (clamped) between lo and hi, inclusively.
- NOTE: Unlike std::clamp, SkTPin has well-defined behavior if 'value' is a
- floating point NaN. In that case, 'max' is returned.
+ Unlike std::clamp(), SkTPin() always returns a value between lo and hi.
+ If x is NaN, SkTPin() returns hi but std::clamp() returns NaN.
*/
-template <typename T> static constexpr const T& SkTPin(const T& value, const T& min, const T& max) {
- return value < min ? min : (value < max ? value : max);
+template <typename T>
+static constexpr const T& SkTPin(const T& x, const T& lo, const T& hi) {
+#if 0
+ return std::max(std::min(hi, x), lo);
+#else
+ // To avoid the need to #include <algorithm>, we use this equivalent logic:
+ return x < lo ? lo
+ : x < hi ? x
+ : /*else*/ hi;
+#endif
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/tests/MathTest.cpp b/tests/MathTest.cpp
index 8f68b92..64aff81 100644
--- a/tests/MathTest.cpp
+++ b/tests/MathTest.cpp
@@ -16,6 +16,7 @@
#include "src/core/SkMathPriv.h"
#include "tests/Test.h"
+#include <algorithm>
#include <cinttypes>
static void test_clz(skiatest::Reporter* reporter) {
@@ -685,6 +686,13 @@
// Ensure that SkTPin bounds even non-finite values (including NaN)
SkScalar p = SkTPin<SkScalar>(r.fFloat, 0, 100);
REPORTER_ASSERT(reporter, p >= 0 && p <= 100);
+
+ // SkTPin has a logical equivalent in terms of std::min and std::max that we don't use,
+ // I think only because we'd like to avoid pulling <algorithm> into SkTypes.h.
+ auto equiv = [](float x, float lo, float hi) {
+ return std::max(std::min(hi, x), lo);
+ };
+ REPORTER_ASSERT(reporter, p == equiv(r.fFloat, 0, 100));
}
}