summaryrefslogtreecommitdiffstats
path: root/include/tools
diff options
context:
space:
mode:
authorMike Kaganski <mike.kaganski@collabora.com>2021-02-05 09:36:59 +0300
committerMike Kaganski <mike.kaganski@collabora.com>2021-02-05 17:04:00 +0100
commitd7e5fa3bd8f4240665f13994589f5e72d362c097 (patch)
tree5709b7600d9f3ee8bec08b87e9b52f475990e16e /include/tools
parentFix typo (diff)
downloadcore-d7e5fa3bd8f4240665f13994589f5e72d362c097.tar.gz
core-d7e5fa3bd8f4240665f13994589f5e72d362c097.zip
Make sanitiseMm100ToTwip simpler and more correct
The result's absolute value is always smaller than n. Returning an uncorrected value taken from reversing multiplication and division order when intermediate value would overflow is better than arbitrary constant. Also further deduplicate Twips <-> 100th-mm conversion, and make sure they all are in a single header. Using conversion implementation that handles negatives correctly improves accuracy, as seen in unit tests; e.g. in testPictureEffectPreservation (the original doc had "dir" equal to "8100000", while we tested that it was "8076614" after roundtrip). Change-Id: Icd027af6238a9f45f916f53f8684506cc959e696 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/110433 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
Diffstat (limited to 'include/tools')
-rw-r--r--include/tools/UnitConversion.hxx15
-rw-r--r--include/tools/helpers.hxx34
2 files changed, 15 insertions, 34 deletions
diff --git a/include/tools/UnitConversion.hxx b/include/tools/UnitConversion.hxx
index e78ef315b432..57f8e39119f0 100644
--- a/include/tools/UnitConversion.hxx
+++ b/include/tools/UnitConversion.hxx
@@ -11,17 +11,32 @@
#pragma once
#include <sal/types.h>
+#include <cassert>
+#include <limits>
constexpr sal_Int64 convertTwipToMm100(sal_Int64 n)
{
+ assert(n < std::numeric_limits<sal_Int64>::max() / 127
+ && n > std::numeric_limits<sal_Int64>::min() / 127);
return (n >= 0) ? (n * 127 + 36) / 72 : (n * 127 - 36) / 72;
}
constexpr sal_Int64 convertMm100ToTwip(sal_Int64 n)
{
+ assert(n < std::numeric_limits<sal_Int64>::max() / 72
+ && n > std::numeric_limits<sal_Int64>::min() / 72);
return (n >= 0) ? (n * 72 + 63) / 127 : (n * 72 - 63) / 127;
}
+constexpr sal_Int64 sanitiseMm100ToTwip(sal_Int64 n)
+{
+ if (n >= std::numeric_limits<sal_Int64>::max() / 72
+ || n <= std::numeric_limits<sal_Int64>::min() / 72)
+ return n / 127 * 72; // do without correction; can not overflow here
+ else
+ return convertMm100ToTwip(n);
+}
+
constexpr sal_Int64 convertPointToTwip(sal_Int64 nNumber) { return nNumber * 20; }
constexpr sal_Int64 convertPointToMm100(sal_Int64 nNumber)
diff --git a/include/tools/helpers.hxx b/include/tools/helpers.hxx
index 381ecb206d18..abce49b3d469 100644
--- a/include/tools/helpers.hxx
+++ b/include/tools/helpers.hxx
@@ -98,38 +98,4 @@ template <typename T> [[nodiscard]] inline T NormAngle360(T angle)
return angle;
}
-/** Convert 100th-mm to twips
-
- A twip is 1/20 of a point, one inch is equal to 72 points, and
- one inch is 2,540 100th-mm.
-
- Thus:
- twips = n * 72 / 2,540 / 20
- = n * 72 / 127
-
- Adding 63 (half of 127) fixes truncation issues in int arithmetic.
-
- This formula is (n>=0) ? (n*72+63) / 127 : (n*72-63) / 127
- */
-inline sal_Int64 sanitiseMm100ToTwip(sal_Int64 n)
-{
- if (n >= 0)
- {
- if (o3tl::checked_multiply<sal_Int64>(n, 72, n) || o3tl::checked_add<sal_Int64>(n, 63, n))
- n = SAL_MAX_INT64;
- }
- else
- {
- if (o3tl::checked_multiply<sal_Int64>(n, 72, n) || o3tl::checked_sub<sal_Int64>(n, 63, n))
- n = SAL_MIN_INT64;
- }
- return n / 127; // 127 is 2,540 100th-mm divided by 20pts
-}
-
-/**
-* Convert Twips <-> 100th-mm
-*/
-inline constexpr sal_Int64 TwipsToHMM(sal_Int64 nTwips) { return (nTwips * 127 + 36) / 72; }
-inline constexpr sal_Int64 HMMToTwips(sal_Int64 nHMM) { return (nHMM * 72 + 63) / 127; }
-
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */