summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorMike Kaganski <mike.kaganski@collabora.com>2021-11-22 09:08:46 +0300
committerMike Kaganski <mike.kaganski@collabora.com>2021-11-22 11:25:38 +0100
commitde4cb026b5fe3ecd1c9557817565cff4ca4e8408 (patch)
tree90072778d17ffc45e394760dc765f5e8d79bffd6 /include
parent003b2d0c36c62800257c688c65109bf2fc7d4f32 (diff)
Generalize DegreeN
This potentially allows to introduce other degree fractions easily, like Degree<sal_Int64, 60000>, with automatically defined conversion functions. Change-Id: Id1c32d9e029943844bdc833178c1f99387ff87fc Reviewed-on: https://gerrit.libreoffice.org/c/core/+/125640 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
Diffstat (limited to 'include')
-rw-r--r--include/tools/degree.hxx29
1 files changed, 21 insertions, 8 deletions
diff --git a/include/tools/degree.hxx b/include/tools/degree.hxx
index 74a27a2c2d35..1f2b2e2f8853 100644
--- a/include/tools/degree.hxx
+++ b/include/tools/degree.hxx
@@ -13,17 +13,28 @@
#include <basegfx/numeric/ftools.hxx>
#include <sal/types.h>
#include <o3tl/strong_int.hxx>
+#include <o3tl/unit_conversion.hxx>
#include <cstdlib>
#include <math.h>
+#include <numeric>
+#include <utility>
+
+template <int N> struct FractionTag;
+// 1/Nth fraction of a degree
+template <typename I, int N> using Degree = o3tl::strong_int<I, FractionTag<N>>;
+
+template <typename I, int N> char (&NofDegree(Degree<I, N>))[N]; // helper
+// Nof<DegreeN> gives compile-time constant N, needed in templates
+template <class D> constexpr int Nof = sizeof(NofDegree(std::declval<D>()));
/** tenths of a Degree, normally rotation */
-typedef o3tl::strong_int<sal_Int16, struct Degree10Tag> Degree10;
+typedef Degree<sal_Int16, 10> Degree10;
/** custom literal */
constexpr Degree10 operator""_deg10(unsigned long long n) { return Degree10{ n }; }
/** hundredths of a Degree, normally rotation */
-typedef o3tl::strong_int<sal_Int32, struct Degree100Tag> Degree100;
+typedef Degree<sal_Int32, 100> Degree100;
// Android has trouble calling the correct overload of std::abs
#ifdef ANDROID
@@ -37,12 +48,14 @@ constexpr Degree100 operator""_deg100(unsigned long long n) { return Degree100{
/** conversion functions */
-inline Degree100 toDegree100(Degree10 x) { return Degree100(x.get() * 10); }
-inline double toRadians(Degree10 x) { return basegfx::deg2rad<10>(x.get()); }
-inline double toDegrees(Degree10 x) { return x.get() / 10.0; }
+template <class To, typename IofFrom, int NofFrom> inline To to(Degree<IofFrom, NofFrom> x)
+{
+ constexpr sal_Int64 m = Nof<To> / std::gcd(Nof<To>, NofFrom);
+ constexpr sal_Int64 d = NofFrom / std::gcd(Nof<To>, NofFrom);
+ return To{ o3tl::convert(x.get(), m, d) };
+}
-inline Degree10 toDegree10(Degree100 x) { return Degree10((x.get() + 5) / 10); }
-inline double toRadians(Degree100 x) { return basegfx::deg2rad<100>(x.get()); }
-inline double toDegrees(Degree100 x) { return x.get() / 100.0; }
+template <class D> inline double toRadians(D x) { return basegfx::deg2rad<Nof<D>>(x.get()); }
+template <class D> inline double toDegrees(D x) { return x.get() / static_cast<double>(Nof<D>); }
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */