include/o3tl/unit_conversion.hxx | 20 ++++++++++++++++++++ include/oox/drawingml/drawingmltypes.hxx | 4 +--- 2 files changed, 21 insertions(+), 3 deletions(-)
New commits: commit ae04cfdbad1f4c09b06cd2cee9d89e9909181acc Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Mon Aug 23 16:28:10 2021 +0200 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Tue Aug 24 10:37:21 2021 +0200 Introduce convertNarrowing to return smaller integer types It will use compile-type constants to clamp input value, instead of clamping more expensive pre-sanitized output value. Change-Id: If78f8b1b4c99bd2f16b1d8a71872e89a0dddd8d0 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/120874 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> diff --git a/include/o3tl/unit_conversion.hxx b/include/o3tl/unit_conversion.hxx index cf293662e7b2..7bee0ed397e5 100644 --- a/include/o3tl/unit_conversion.hxx +++ b/include/o3tl/unit_conversion.hxx @@ -221,6 +221,26 @@ template <typename N, typename U> constexpr auto convertSaturate(N n, U from, U return detail::MulDivSaturate(n, detail::md(from, to), detail::md(to, from)); } +// Conversion with saturation (only for integral types), optimized for return types smaller than +// sal_Int64. In this case, it's easier to clamp input values to known bounds, than to do some +// preprocessing to handle too large input values, just to clamp the result anyway. Use it like: +// +// sal_Int32 n = convertNarrowing<sal_Int32, o3tl::Length::mm100, o3tl::Length::emu>(m); +template <typename Out, auto from, auto to, typename N, + std::enable_if_t< + std::is_integral_v<N> && std::is_integral_v<Out> && sizeof(Out) < sizeof(sal_Int64), + int> = 0> +constexpr Out convertNarrowing(N n) +{ + constexpr sal_Int64 nMin = convertSaturate(std::numeric_limits<Out>::min(), to, from); + constexpr sal_Int64 nMax = convertSaturate(std::numeric_limits<Out>::max(), to, from); + if (static_cast<sal_Int64>(n) > nMax) + return std::numeric_limits<Out>::max(); + if (static_cast<sal_Int64>(n) < nMin) + return std::numeric_limits<Out>::min(); + return convert(n, from, to); +} + // Return a pair { multiplier, divisor } for a given conversion template <typename U> constexpr std::pair<sal_Int64, sal_Int64> getConversionMulDiv(U from, U to) { diff --git a/include/oox/drawingml/drawingmltypes.hxx b/include/oox/drawingml/drawingmltypes.hxx index 05d218fa882e..4350b8d033a7 100644 --- a/include/oox/drawingml/drawingmltypes.hxx +++ b/include/oox/drawingml/drawingmltypes.hxx @@ -180,9 +180,7 @@ inline sal_Int64 convertHmmToEmu( sal_Int32 nValue ) /** Converts the passed 64-bit integer value from EMUs to 1/100 mm. */ inline sal_Int32 convertEmuToHmm( sal_Int64 nValue ) { - return getLimitedValue<sal_Int32, sal_Int64>( - o3tl::convertSaturate(nValue, o3tl::Length::emu, o3tl::Length::mm100), SAL_MIN_INT32, - SAL_MAX_INT32); + return o3tl::convertNarrowing<sal_Int32, o3tl::Length::emu, o3tl::Length::mm100>(nValue); } /** Converts the passed 64-bit integer value from EMUs to Points. */