diff options
35 files changed, 1641 insertions, 1497 deletions
diff --git a/cui/source/tabpages/chardlg.cxx b/cui/source/tabpages/chardlg.cxx index a7e3dda42bc9..6a35b45ba46f 100644 --- a/cui/source/tabpages/chardlg.cxx +++ b/cui/source/tabpages/chardlg.cxx @@ -59,6 +59,7 @@ #include <FontFeaturesDialog.hxx> #include <sal/log.hxx> #include <osl/diagnose.h> +#include <o3tl/unit_conversion.hxx> using namespace ::com::sun::star; @@ -441,7 +442,9 @@ namespace // old value, scaled tools::Long nHeight; if ( _pFontSizeLB->IsPtRelative() ) - nHeight = rOldItem.GetHeight() + PointToTwips( static_cast<tools::Long>(_pFontSizeLB->get_value() / 10) ); + nHeight = rOldItem.GetHeight() + + o3tl::convert(_pFontSizeLB->get_value(), o3tl::Length::pt, + o3tl::Length::twip) / 10; else nHeight = static_cast<tools::Long>(rOldItem.GetHeight() * _pFontSizeLB->get_value() / 100); @@ -450,7 +453,8 @@ namespace ItemToControl( nHeight, _pPage->GetItemSet().GetPool()->GetMetric( _nFontHeightWhich ), FieldUnit::TWIP ) ); } else if ( !_pFontSizeLB->get_active_text().isEmpty() ) - aSize.setHeight( PointToTwips( static_cast<tools::Long>(_pFontSizeLB->get_value() / 10) ) ); + aSize.setHeight(o3tl::convert(_pFontSizeLB->get_value(), o3tl::Length::pt, + o3tl::Length::twip) / 10); else aSize.setHeight( 200 ); // default 10pt aFontMetrics.SetFontSize( aSize ); diff --git a/cui/source/tabpages/grfpage.cxx b/cui/source/tabpages/grfpage.cxx index ddc47de404c2..569329e3a160 100644 --- a/cui/source/tabpages/grfpage.cxx +++ b/cui/source/tabpages/grfpage.cxx @@ -38,9 +38,9 @@ #include <svtools/optionsdrawinglayer.hxx> #include <basegfx/matrix/b2dhommatrix.hxx> #include <basegfx/polygon/b2dpolygontools.hxx> +#include <o3tl/unit_conversion.hxx> -#define CM_1_TO_TWIP 567 -#define TWIP_TO_INCH 1440 +constexpr auto CM_1_TO_TWIP = o3tl::convert(1, o3tl::Length::cm, o3tl::Length::twip); // 567 static int lcl_GetValue(const weld::MetricSpinButton& rMetric, FieldUnit eUnit) @@ -646,16 +646,17 @@ void SvxGrfCropPage::GraphicHasChanged( bool bFound ) } if ( aOrigPixelSize.Width() && aOrigPixelSize.Height() ) { - sal_Int32 ax = sal_Int32(floor(static_cast<float>(aOrigPixelSize.Width()) / - (static_cast<float>(aOrigSize.Width())/TWIP_TO_INCH)+0.5)); - sal_Int32 ay = sal_Int32(floor(static_cast<float>(aOrigPixelSize.Height()) / - (static_cast<float>(aOrigSize.Height())/TWIP_TO_INCH)+0.5)); - sTemp += " " + CuiResId( RID_SVXSTR_PPI ); + sal_Int32 ax = 0.5 + aOrigPixelSize.Width() / + o3tl::convert<double>(aOrigSize.Width(), o3tl::Length::twip, + o3tl::Length::in); + sal_Int32 ay = 0.5 + aOrigPixelSize.Height() / + o3tl::convert<double>(aOrigSize.Height(), o3tl::Length::twip, + o3tl::Length::in); OUString sPPI = OUString::number(ax); if (abs(ax - ay) > 1) { sPPI += u"\u00D7" + OUString::number(ay); } - sTemp = sTemp.replaceAll("%1", sPPI); + sTemp += " " + CuiResId(RID_SVXSTR_PPI).replaceAll("%1", sPPI); } m_xOrigSizeFT->set_label(sTemp); } diff --git a/emfio/source/reader/wmfreader.cxx b/emfio/source/reader/wmfreader.cxx index 78fee922ff35..999584b02294 100644 --- a/emfio/source/reader/wmfreader.cxx +++ b/emfio/source/reader/wmfreader.cxx @@ -24,6 +24,7 @@ #include <memory> #include <optional> #include <o3tl/safeint.hxx> +#include <o3tl/unit_conversion.hxx> #include <rtl/crc.h> #include <rtl/tencinfo.h> #include <sal/log.hxx> @@ -1291,8 +1292,8 @@ namespace emfio { // #n417818#: If we have an external header then overwrite the bounds! tools::Rectangle aExtRect(0, 0, - static_cast<double>(mpExternalHeader->xExt) * 567 * mnUnitsPerInch / 1440000, - static_cast<double>(mpExternalHeader->yExt) * 567 * mnUnitsPerInch / 1440000); + o3tl::convert(mpExternalHeader->xExt, o3tl::Length::mm100, o3tl::Length::px), + o3tl::convert(mpExternalHeader->yExt, o3tl::Length::mm100, o3tl::Length::px)); aPlaceableBound = aExtRect; SAL_INFO("vcl.wmf", "External header size " diff --git a/include/o3tl/unit_conversion.hxx b/include/o3tl/unit_conversion.hxx new file mode 100644 index 000000000000..17dd5ae12293 --- /dev/null +++ b/include/o3tl/unit_conversion.hxx @@ -0,0 +1,231 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include <o3tl/safeint.hxx> +#include <sal/macros.h> +#include <sal/types.h> + +#include <array> +#include <cassert> +#include <utility> +#include <type_traits> + +namespace o3tl +{ +// Length units +enum class Length +{ + mm100 = 0, // 1/100th mm + mm10, // 1/10 mm, corresponds to MapUnit::Map10thMM + mm, // millimeter + cm, // centimeter + m, // meter + km, // kilometer + emu, // English Metric Unit: 1/360000 cm, 1/914400 in + twip, // "Twentieth of a point" aka "dxa": 1/20 pt + pt, // Point: 1/72 in + pc, // Pica: 1/6 in, corresponds to FieldUnit::PICA and MeasureUnit::PICA + in1000, // 1/1000 in, corresponds to MapUnit::Map1000thInch + in100, // 1/100 in, corresponds to MapUnit::Map100thInch + in10, // 1/10 in, corresponds to MapUnit::Map10thInch + in, // inch + ft, // foot + mi, // mile + master, // PPT Master Unit: 1/576 in + px, // "pixel" unit: 15 twip (96 ppi), corresponds to MeasureUnit::PIXEL + ch, // "char" unit: 210 twip (14 px), corresponds to FieldUnit::CHAR + line, // "line" unit: 312 twip, corresponds to FieldUnit::LINE + count, // <== add new units above this last entry + invalid = -1 +}; + +// If other categories of units would be needed (like time), a separate scoped enum +// should be created, respective conversion array prepared in detail namespace, and +// respective md(NewUnit, NewUnit) overload introduced, which would allow using +// o3tl::convert() and o3tl::convertSanitize() with the new category in a type-safe +// way, without mixing unrelated units. + +namespace detail +{ +// Common utilities + +// A special function to avoid compiler warning comparing signed and unsigned values +template <typename I> constexpr bool isBetween(I n, sal_Int64 min, sal_Int64 max) +{ + assert(max > 0 && min < 0); + if constexpr (std::is_signed_v<I>) + return n >= min && n <= max; + else + return n <= sal_uInt64(max); +} + +// Ensure correct rounding for both positive and negative integers +template <typename I, std::enable_if_t<std::is_integral_v<I>, int> = 0> +constexpr sal_Int64 MulDiv(I n, sal_Int64 m, sal_Int64 d) +{ + assert(m > 0 && d > 0); + assert(isBetween(n, (SAL_MIN_INT64 + d / 2) / m, (SAL_MAX_INT64 - d / 2) / m)); + return (n >= 0 ? (n * m + d / 2) : (n * m - d / 2)) / d; +} +template <typename F, std::enable_if_t<std::is_floating_point_v<F>, int> = 0> +constexpr double MulDiv(F f, sal_Int64 m, sal_Int64 d) +{ + assert(m > 0 && d > 0); + return f * (double(m) / d); +} + +template <typename I, std::enable_if_t<std::is_integral_v<I>, int> = 0> +constexpr sal_Int64 MulDiv(I n, sal_Int64 m, sal_Int64 d, bool& bOverflow, sal_Int64 nDefault) +{ + if (!isBetween(n, (SAL_MIN_INT64 + d / 2) / m, (SAL_MAX_INT64 - d / 2) / m)) + { + bOverflow = true; + return nDefault; + } + bOverflow = false; + return MulDiv(n, m, d); +} + +template <typename I, std::enable_if_t<std::is_integral_v<I>, int> = 0> +constexpr sal_Int64 MulDivSaturate(I n, sal_Int64 m, sal_Int64 d) +{ + if (!isBetween(n, (SAL_MIN_INT64 + d / 2) / m, (SAL_MAX_INT64 - d / 2) / m)) + { + if (m > d && !isBetween(n, SAL_MIN_INT64 / m * d + d / 2, SAL_MAX_INT64 / m * d - d / 2)) + return n > 0 ? SAL_MAX_INT64 : SAL_MIN_INT64; // saturate + return (n >= 0 ? n + d / 2 : n - d / 2) / d * m; // divide before multiplication + } + return MulDiv(n, m, d); +} + +// Greatest common divisor +constexpr int gcd(sal_Int64 a, sal_Int64 b) { return b == 0 ? a : gcd(b, a % b); } + +// Packs integral multiplier and divisor for conversion from one unit to another +struct m_and_d +{ + sal_Int64 m; // multiplier + sal_Int64 d; // divisor + constexpr m_and_d(sal_Int64 _m, sal_Int64 _d) + : m(_m / gcd(_m, _d)) // make sure to use smallest quotients here because + , d(_d / gcd(_m, _d)) // they will be multiplied when building final table + { + assert(_m > 0 && _d > 0); + } +}; + +// Resulting static array N x N of all quotients to convert between all units. The +// quotients are minimal to allow largest range of converted numbers without overflow. +// Maybe o3tl::enumarray could be used here, but it's not constexpr yet. +template <int N> constexpr auto prepareMDArray(const m_and_d (&mdBase)[N]) +{ + std::array<std::array<sal_Int64, N>, N> a{}; + for (int i = 0; i < N; ++i) + { + for (int j = 0; j <= i; ++j) + { + if (i == j) + a[i][j] = 1; + else + { + assert(mdBase[i].m < SAL_MAX_INT64 / mdBase[j].d); + assert(mdBase[i].d < SAL_MAX_INT64 / mdBase[j].m); + const sal_Int64 m = mdBase[i].m * mdBase[j].d, d = mdBase[i].d * mdBase[j].m; + const sal_Int64 g = gcd(m, d); + a[i][j] = m / g; + a[j][i] = d / g; + } + } + } + return a; +} + +// Length units implementation + +// Array of conversion quotients for mm, used to build final conversion table. Entries +// are { multiplier, divider } to convert respective unit *to* mm. Order of elements +// corresponds to order in o3tl::Length enum (Length::count and Length::invalid omitted). +constexpr m_and_d mdBaseLen[] = { + { 1, 100 }, // mm100 => mm + { 1, 10 }, // mm10 => mm + { 1, 1 }, // mm => mm + { 10, 1 }, // cm => mm + { 1000, 1 }, // m => mm + { 1000000, 1 }, // km => mm + { 1, 36000 }, // emu => mm + { 254, 10 * 1440 }, // twip => mm + { 254, 10 * 72 }, // pt => mm + { 254, 10 * 6 }, // pc => mm + { 254, 10000 }, // in1000 => mm + { 254, 1000 }, // in100 => mm + { 254, 100 }, // in10 => mm + { 254, 10 }, // in => mm + { 254 * 12, 10 }, // ft => mm + { 254 * 12 * 5280, 10 }, // mi => mm + { 254, 10 * 576 }, // master => mm + { 254 * 15, 10 * 1440 }, // px => mm + { 254 * 210, 10 * 1440 }, // ch => mm + { 254 * 312, 10 * 1440 }, // line => mm +}; +static_assert(SAL_N_ELEMENTS(mdBaseLen) == static_cast<int>(Length::count), + "mdBaseL must have an entry for each unit in o3tl::Length"); + +// an overload taking Length +constexpr sal_Int64 md(Length i, Length j) +{ + // The resulting multipliers and divisors array + constexpr auto aMDArray = prepareMDArray(mdBaseLen); + + const int nI = static_cast<int>(i), nJ = static_cast<int>(j); + assert(nI >= 0 && o3tl::make_unsigned(nI) < aMDArray.size()); + assert(nJ >= 0 && o3tl::make_unsigned(nJ) < aMDArray.size()); + return aMDArray[nI][nJ]; +} + +// here might go overloads of md() taking other units ... +} + +// Unchecked conversion. Takes a number value, multiplier and divisor +template <typename N> constexpr auto convert(N n, sal_Int64 mul, sal_Int64 div) +{ + return detail::MulDiv(n, mul, div); +} + +// Unchecked conversion. Takes a number value and units defined in this header +template <typename N, typename U> constexpr auto convert(N n, U from, U to) +{ + return convert(n, detail::md(from, to), detail::md(to, from)); +} + +// Returns nDefault if intermediate multiplication overflows sal_Int64 (only for integral types). +// On return, bOverflow indicates if overflow happened. +template <typename N, typename U> +constexpr auto convert(N n, U from, U to, bool& bOverflow, sal_Int64 nDefault = 0) +{ + return detail::MulDiv(n, detail::md(from, to), detail::md(to, from), bOverflow, nDefault); +} + +// Conversion with saturation (only for integral types). For too large input returns SAL_MAX_INT64. +// When intermediate multiplication would overflow, but otherwise result in in sal_Int64 range, the +// precision is decreased because of inversion of multiplication and division. +template <typename N, typename U> constexpr auto convertSaturate(N n, U from, U to) +{ + return detail::MulDivSaturate(n, detail::md(from, to), detail::md(to, from)); +} + +// Return a pair { multiplier, divisor } for a given conversion +template <typename U> constexpr std::pair<sal_Int64, sal_Int64> getConversionMulDiv(U from, U to) +{ + return { detail::md(from, to), detail::md(to, from) }; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/oox/drawingml/drawingmltypes.hxx b/include/oox/drawingml/drawingmltypes.hxx index b8693c00fdeb..c24bff255a3e 100644 --- a/include/oox/drawingml/drawingmltypes.hxx +++ b/include/oox/drawingml/drawingmltypes.hxx @@ -31,6 +31,7 @@ #include <com/sun/star/style/TabAlign.hpp> #include <com/sun/star/uno/Reference.hxx> #include <o3tl/safeint.hxx> +#include <o3tl/unit_conversion.hxx> #include <oox/dllapi.h> #include <oox/helper/helper.hxx> #include <rtl/ustring.hxx> @@ -171,33 +172,30 @@ inline OString calcRotationValue(sal_Int32 nRotation) return OString::number(nRotation); } -const sal_Int32 EMU_PER_HMM = 360; /// 360 EMUs per 1/100 mm. -const sal_Int32 EMU_PER_PT = 12700; - /** Converts the passed 32-bit integer value from 1/100 mm to EMUs. */ inline sal_Int64 convertHmmToEmu( sal_Int32 nValue ) { - return static_cast< sal_Int64 >( nValue ) * EMU_PER_HMM; + return o3tl::convert(nValue, o3tl::Length::mm100, o3tl::Length::emu); } /** Converts the passed 64-bit integer value from EMUs to 1/100 mm. */ inline sal_Int32 convertEmuToHmm( sal_Int64 nValue ) { - sal_Int32 nCorrection = (nValue > 0 ? 1 : -1) * EMU_PER_HMM / 2; // So that the implicit floor will round. - return getLimitedValue<sal_Int32, sal_Int64>(o3tl::saturating_add<sal_Int64>(nValue, nCorrection) / EMU_PER_HMM, SAL_MIN_INT32, SAL_MAX_INT32); + return getLimitedValue<sal_Int32, sal_Int64>( + o3tl::convert(nValue, o3tl::Length::emu, o3tl::Length::mm100), SAL_MIN_INT32, + SAL_MAX_INT32); } /** Converts the passed 64-bit integer value from EMUs to Points. */ inline float convertEmuToPoints( sal_Int64 nValue ) { - return static_cast<float>(nValue) / EMU_PER_PT; + return o3tl::convert<double>(nValue, o3tl::Length::emu, o3tl::Length::pt); } /** Converts the passed double value from points to mm. */ inline double convertPointToMms(double fValue) { - constexpr double fFactor = static_cast<double>(EMU_PER_PT) / (EMU_PER_HMM * 100); - return fValue * fFactor; + return o3tl::convert(fValue, o3tl::Length::pt, o3tl::Length::mm); } /** A structure for a point with 64-bit integer components. */ diff --git a/include/svtools/unitconv.hxx b/include/svtools/unitconv.hxx index 34025261e46c..88bbffc146e5 100644 --- a/include/svtools/unitconv.hxx +++ b/include/svtools/unitconv.hxx @@ -46,8 +46,6 @@ SVT_DLLPUBLIC FieldUnit MapToFieldUnit( const MapUnit eUnit ); SVT_DLLPUBLIC void SetMetricValue(weld::MetricSpinButton& rField, int lCoreValue, MapUnit eUnit); SVT_DLLPUBLIC int GetCoreValue(const weld::MetricSpinButton& rField, MapUnit eUnit); -SVT_DLLPUBLIC tools::Long PointToTwips( tools::Long nIn ); - SVT_DLLPUBLIC tools::Long TransformMetric( tools::Long nVal, FieldUnit aOld, FieldUnit aNew ); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/UnitConversion.hxx b/include/tools/UnitConversion.hxx index 802a372a546d..7d3bdf565c1d 100644 --- a/include/tools/UnitConversion.hxx +++ b/include/tools/UnitConversion.hxx @@ -10,61 +10,117 @@ #pragma once +#include <o3tl/unit_conversion.hxx> #include <sal/types.h> -#include <cassert> -#include <type_traits> +#include <tools/fldunit.hxx> +#include <tools/fract.hxx> +#include <tools/mapunit.hxx> -template <typename I> constexpr bool isBetween(I n, sal_Int64 min, sal_Int64 max) +constexpr o3tl::Length FieldToO3tlLength(FieldUnit eU, o3tl::Length ePixelValue = o3tl::Length::px) { - assert(max > 0 && min < 0); - if constexpr (std::is_signed_v<I>) - return n >= min && n <= max; - else - return n <= sal_uInt64(max); + switch (eU) + { + case FieldUnit::MM: + return o3tl::Length::mm; + case FieldUnit::CM: + return o3tl::Length::cm; + case FieldUnit::M: + return o3tl::Length::m; + case FieldUnit::KM: + return o3tl::Length::km; + case FieldUnit::TWIP: + return o3tl::Length::twip; + case FieldUnit::POINT: + return o3tl::Length::pt; + case FieldUnit::PICA: + return o3tl::Length::pc; + case FieldUnit::INCH: + return o3tl::Length::in; + case FieldUnit::FOOT: + return o3tl::Length::ft; + case FieldUnit::MILE: + return o3tl::Length::mi; + case FieldUnit::CHAR: + return o3tl::Length::ch; + case FieldUnit::LINE: + return o3tl::Length::line; + case FieldUnit::MM_100TH: + return o3tl::Length::mm100; + case FieldUnit::PIXEL: + return ePixelValue; + default: + return o3tl::Length::invalid; + } } -constexpr int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); } - -// Ensure correct rounding for both positive and negative integers -template <int mul, int div, typename I, std::enable_if_t<std::is_integral_v<I>, int> = 0> -constexpr sal_Int64 MulDiv(I n) +constexpr o3tl::Length MapToO3tlLength(MapUnit eU, o3tl::Length ePixelValue = o3tl::Length::px) { - static_assert(mul > 0 && div > 0); - constexpr int m = mul / gcd(mul, div), d = div / gcd(mul, div); - assert(isBetween(n, (SAL_MIN_INT64 + d / 2) / m, (SAL_MAX_INT64 - d / 2) / m)); - return (n >= 0 ? (sal_Int64(n) * m + d / 2) : (sal_Int64(n) * m - d / 2)) / d; + switch (eU) + { + case MapUnit::Map100thMM: + return o3tl::Length::mm100; + case MapUnit::Map10thMM: + return o3tl::Length::mm10; + case MapUnit::MapMM: + return o3tl::Length::mm; + case MapUnit::MapCM: + return o3tl::Length::cm; + case MapUnit::Map1000thInch: + return o3tl::Length::in1000; + case MapUnit::Map100thInch: + return o3tl::Length::in100; + case MapUnit::Map10thInch: + return o3tl::Length::in10; + case MapUnit::MapInch: + return o3tl::Length::in; + case MapUnit::MapPoint: + return o3tl::Length::pt; + case MapUnit::MapTwip: + return o3tl::Length::twip; + case MapUnit::MapPixel: + return ePixelValue; + default: + return o3tl::Length::invalid; + } } -template <int mul, int div, typename F, std::enable_if_t<std::is_floating_point_v<F>, int> = 0> -constexpr double MulDiv(F f) + +inline Fraction conversionFract(o3tl::Length from, o3tl::Length to) { - static_assert(mul > 0 && div > 0); - return f * (double(mul) / div); + const auto & [ mul, div ] = o3tl::getConversionMulDiv(from, to); + return { mul, div }; } -template <int mul, int div, typename I, std::enable_if_t<std::is_integral_v<I>, int> = 0> -constexpr sal_Int64 sanitizeMulDiv(I n) +template <typename N> constexpr auto convertTwipToMm100(N n) { - constexpr int m = mul / gcd(mul, div), d = div / gcd(mul, div); - if constexpr (m > d) - if (!isBetween(n, SAL_MIN_INT64 / m * d + d / 2, SAL_MAX_INT64 / m * d - d / 2)) - return n > 0 ? SAL_MAX_INT64 : SAL_MIN_INT64; // saturate - if (!isBetween(n, (SAL_MIN_INT64 + d / 2) / m, (SAL_MAX_INT64 - d / 2) / m)) - return (n >= 0 ? n + d / 2 : n - d / 2) / d * m; // divide before multiplication - return MulDiv<mul, div>(n); + return o3tl::convert(n, o3tl::Length::twip, o3tl::Length::mm100); +} +template <typename N> constexpr auto convertMm100ToTwip(N n) +{ + return o3tl::convert(n, o3tl::Length::mm100, o3tl::Length::twip); } -template <typename N> constexpr auto convertTwipToMm100(N n) { return MulDiv<127, 72>(n); } -template <typename N> constexpr auto convertMm100ToTwip(N n) { return MulDiv<72, 127>(n); } - -constexpr sal_Int64 sanitiseMm100ToTwip(sal_Int64 n) { return sanitizeMulDiv<72, 127>(n); } - -template <typename N> constexpr auto convertPointToTwip(N n) { return MulDiv<20, 1>(n); } +constexpr sal_Int64 sanitiseMm100ToTwip(sal_Int64 n) +{ + return o3tl::convertSaturate(n, o3tl::Length::mm100, o3tl::Length::twip); +} -template <typename N> constexpr auto convertPointToMm100(N n) { return MulDiv<2540, 72>(n); } -template <typename N> constexpr auto convertMm100ToPoint(N n) { return MulDiv<72, 2540>(n); } +template <typename N> constexpr auto convertPointToMm100(N n) +{ + return o3tl::convert(n, o3tl::Length::pt, o3tl::Length::mm100); +} +template <typename N> constexpr auto convertMm100ToPoint(N n) +{ + return o3tl::convert(n, o3tl::Length::mm100, o3tl::Length::pt); +} // PPT's "master unit" (1/576 inch) <=> mm/100 -template <typename N> constexpr auto convertMasterUnitToMm100(N n) { return MulDiv<2540, 576>(n); } -template <typename N> constexpr auto convertMm100ToMasterUnit(N n) { return MulDiv<576, 2540>(n); } +template <typename N> constexpr auto convertMasterUnitToMm100(N n) +{ + return o3tl::convert(n, o3tl::Length::master, o3tl::Length::mm100); +} +template <typename N> constexpr auto convertMm100ToMasterUnit(N n) +{ + return o3tl::convert(n, o3tl::Length::mm100, o3tl::Length::master); +} /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/o3tl/CppunitTest_o3tl_tests.mk b/o3tl/CppunitTest_o3tl_tests.mk index 07229a9384b1..6866778f6c1a 100644 --- a/o3tl/CppunitTest_o3tl_tests.mk +++ b/o3tl/CppunitTest_o3tl_tests.mk @@ -35,6 +35,7 @@ $(eval $(call gb_CppunitTest_add_exception_objects,o3tl_tests,\ o3tl/qa/test-span \ o3tl/qa/test-temporary \ o3tl/qa/test-typed_flags \ + o3tl/qa/test-unit_conversion \ o3tl/qa/test-vector_pool \ )) diff --git a/o3tl/qa/test-unit_conversion.cxx b/o3tl/qa/test-unit_conversion.cxx new file mode 100644 index 000000000000..72a0e9b1f43c --- /dev/null +++ b/o3tl/qa/test-unit_conversion.cxx @@ -0,0 +1,872 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <sal/config.h> + +#include <o3tl/unit_conversion.hxx> + +// Just some static asserts + +namespace +{ +constexpr double const_abs(double f) { return f >= 0 ? f : -f; } +constexpr bool eq(double a, double b) { return const_abs(a - b) < 1E-6; } +bool eq(sal_Int64, double) = delete; +} + +// testing floating-point conversion + +static_assert(eq(o3tl::convert(1.0, o3tl::Length::mm100, o3tl::Length::mm100), 1)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::mm10, o3tl::Length::mm100), 10)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::mm, o3tl::Length::mm100), 100)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::cm, o3tl::Length::mm100), 1000)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::m, o3tl::Length::mm100), 100000)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::km, o3tl::Length::mm100), 100E6)); +static_assert(eq(o3tl::convert(360.0, o3tl::Length::emu, o3tl::Length::mm100), 1)); +static_assert(eq(o3tl::convert(72.0, o3tl::Length::twip, o3tl::Length::mm100), 127)); +static_assert(eq(o3tl::convert(18.0, o3tl::Length::pt, o3tl::Length::mm100), 635)); +static_assert(eq(o3tl::convert(3.0, o3tl::Length::pc, o3tl::Length::mm100), 1270)); +static_assert(eq(o3tl::convert(50.0, o3tl::Length::in1000, o3tl::Length::mm100), 127)); +static_assert(eq(o3tl::convert(5.0, o3tl::Length::in100, o3tl::Length::mm100), 127)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::in10, o3tl::Length::mm100), 254)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::in, o3tl::Length::mm100), 2540)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::ft, o3tl::Length::mm100), 30480)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::mi, o3tl::Length::mm100), 160934400)); +static_assert(eq(o3tl::convert(144.0, o3tl::Length::master, o3tl::Length::mm100), 635)); +static_assert(eq(o3tl::convert(24.0, o3tl::Length::px, o3tl::Length::mm100), 635)); +static_assert(eq(o3tl::convert(12.0, o3tl::Length::ch, o3tl::Length::mm100), 4445)); +static_assert(eq(o3tl::convert(3.0, o3tl::Length::line, o3tl::Length::mm100), 1651)); + +static_assert(eq(o3tl::convert(10.0, o3tl::Length::mm100, o3tl::Length::mm10), 1)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::mm10, o3tl::Length::mm10), 1)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::mm, o3tl::Length::mm10), 10)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::cm, o3tl::Length::mm10), 100)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::m, o3tl::Length::mm10), 10000)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::km, o3tl::Length::mm10), 10E6)); +static_assert(eq(o3tl::convert(3600.0, o3tl::Length::emu, o3tl::Length::mm10), 1)); +static_assert(eq(o3tl::convert(720.0, o3tl::Length::twip, o3tl::Length::mm10), 127)); +static_assert(eq(o3tl::convert(36.0, o3tl::Length::pt, o3tl::Length::mm10), 127)); +static_assert(eq(o3tl::convert(3.0, o3tl::Length::pc, o3tl::Length::mm10), 127)); +static_assert(eq(o3tl::convert(500.0, o3tl::Length::in1000, o3tl::Length::mm10), 127)); +static_assert(eq(o3tl::convert(50.0, o3tl::Length::in100, o3tl::Length::mm10), 127)); +static_assert(eq(o3tl::convert(5.0, o3tl::Length::in10, o3tl::Length::mm10), 127)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::in, o3tl::Length::mm10), 254)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::ft, o3tl::Length::mm10), 3048)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::mi, o3tl::Length::mm10), 16093440)); +static_assert(eq(o3tl::convert(288.0, o3tl::Length::master, o3tl::Length::mm10), 127)); +static_assert(eq(o3tl::convert(48.0, o3tl::Length::px, o3tl::Length::mm10), 127)); +static_assert(eq(o3tl::convert(24.0, o3tl::Length::ch, o3tl::Length::mm10), 889)); +static_assert(eq(o3tl::convert(30.0, o3tl::Length::line, o3tl::Length::mm10), 1651)); + +static_assert(eq(o3tl::convert(100.0, o3tl::Length::mm100, o3tl::Length::mm), 1)); +static_assert(eq(o3tl::convert(10.0, o3tl::Length::mm10, o3tl::Length::mm), 1)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::mm, o3tl::Length::mm), 1)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::cm, o3tl::Length::mm), 10)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::m, o3tl::Length::mm), 1000)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::km, o3tl::Length::mm), 1E6)); +static_assert(eq(o3tl::convert(36000.0, o3tl::Length::emu, o3tl::Length::mm), 1)); +static_assert(eq(o3tl::convert(7200.0, o3tl::Length::twip, o3tl::Length::mm), 127)); +static_assert(eq(o3tl::convert(360.0, o3tl::Length::pt, o3tl::Length::mm), 127)); +static_assert(eq(o3tl::convert(30.0, o3tl::Length::pc, o3tl::Length::mm), 127)); +static_assert(eq(o3tl::convert(5000.0, o3tl::Length::in1000, o3tl::Length::mm), 127)); +static_assert(eq(o3tl::convert(500.0, o3tl::Length::in100, o3tl::Length::mm), 127)); +static_assert(eq(o3tl::convert(50.0, o3tl::Length::in10, o3tl::Length::mm), 127)); +static_assert(eq(o3tl::convert(5.0, o3tl::Length::in, o3tl::Length::mm), 127)); +static_assert(eq(o3tl::convert(5.0, o3tl::Length::ft, o3tl::Length::mm), 1524)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::mi, o3tl::Length::mm), 1609344)); +static_assert(eq(o3tl::convert(2880.0, o3tl::Length::master, o3tl::Length::mm), 127)); +static_assert(eq(o3tl::convert(480.0, o3tl::Length::px, o3tl::Length::mm), 127)); +static_assert(eq(o3tl::convert(240.0, o3tl::Length::ch, o3tl::Length::mm), 889)); +static_assert(eq(o3tl::convert(300.0, o3tl::Length::line, o3tl::Length::mm), 1651)); + +static_assert(eq(o3tl::convert(1000.0, o3tl::Length::mm100, o3tl::Length::cm), 1)); +static_assert(eq(o3tl::convert(100.0, o3tl::Length::mm10, o3tl::Length::cm), 1)); +static_assert(eq(o3tl::convert(10.0, o3tl::Length::mm, o3tl::Length::cm), 1)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::cm, o3tl::Length::cm), 1)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::m, o3tl::Length::cm), 100)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::km, o3tl::Length::cm), 100000)); +static_assert(eq(o3tl::convert(360000.0, o3tl::Length::emu, o3tl::Length::cm), 1)); +static_assert(eq(o3tl::convert(72000.0, o3tl::Length::twip, o3tl::Length::cm), 127)); +static_assert(eq(o3tl::convert(3600.0, o3tl::Length::pt, o3tl::Length::cm), 127)); +static_assert(eq(o3tl::convert(300.0, o3tl::Length::pc, o3tl::Length::cm), 127)); +static_assert(eq(o3tl::convert(50000.0, o3tl::Length::in1000, o3tl::Length::cm), 127)); +static_assert(eq(o3tl::convert(5000.0, o3tl::Length::in100, o3tl::Length::cm), 127)); +static_assert(eq(o3tl::convert(500.0, o3tl::Length::in10, o3tl::Length::cm), 127)); +static_assert(eq(o3tl::convert(50.0, o3tl::Length::in, o3tl::Length::cm), 127)); +static_assert(eq(o3tl::convert(25.0, o3tl::Length::ft, o3tl::Length::cm), 762)); +static_assert(eq(o3tl::convert(5.0, o3tl::Length::mi, o3tl::Length::cm), 804672)); +static_assert(eq(o3tl::convert(28800.0, o3tl::Length::master, o3tl::Length::cm), 127)); +static_assert(eq(o3tl::convert(4800.0, o3tl::Length::px, o3tl::Length::cm), 127)); +static_assert(eq(o3tl::convert(2400.0, o3tl::Length::ch, o3tl::Length::cm), 889)); +static_assert(eq(o3tl::convert(3000.0, o3tl::Length::line, o3tl::Length::cm), 1651)); + +static_assert(eq(o3tl::convert(100000.0, o3tl::Length::mm100, o3tl::Length::m), 1)); +static_assert(eq(o3tl::convert(10000.0, o3tl::Length::mm10, o3tl::Length::m), 1)); +static_assert(eq(o3tl::convert(1000.0, o3tl::Length::mm, o3tl::Length::m), 1)); +static_assert(eq(o3tl::convert(100.0, o3tl::Length::cm, o3tl::Length::m), 1)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::m, o3tl::Length::m), 1)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::km, o3tl::Length::m), 1000)); +static_assert(eq(o3tl::convert(36E6, o3tl::Length::emu, o3tl::Length::m), 1)); +static_assert(eq(o3tl::convert(7200000.0, o3tl::Length::twip, o3tl::Length::m), 127)); +static_assert(eq(o3tl::convert(360000.0, o3tl::Length::pt, o3tl::Length::m), 127)); +static_assert(eq(o3tl::convert(30000.0, o3tl::Length::pc, o3tl::Length::m), 127)); +static_assert(eq(o3tl::convert(5000000.0, o3tl::Length::in1000, o3tl::Length::m), 127)); +static_assert(eq(o3tl::convert(500000.0, o3tl::Length::in100, o3tl::Length::m), 127)); +static_assert(eq(o3tl::convert(50000.0, o3tl::Length::in10, o3tl::Length::m), 127)); +static_assert(eq(o3tl::convert(5000.0, o3tl::Length::in, o3tl::Length::m), 127)); +static_assert(eq(o3tl::convert(1250.0, o3tl::Length::ft, o3tl::Length::m), 381)); +static_assert(eq(o3tl::convert(125.0, o3tl::Length::mi, o3tl::Length::m), 201168)); +static_assert(eq(o3tl::convert(2880000.0, o3tl::Length::master, o3tl::Length::m), 127)); +static_assert(eq(o3tl::convert(480000.0, o3tl::Length::px, o3tl::Length::m), 127)); +static_assert(eq(o3tl::convert(240000.0, o3tl::Length::ch, o3tl::Length::m), 889)); +static_assert(eq(o3tl::convert(300000.0, o3tl::Length::line, o3tl::Length::m), 1651)); + +static_assert(eq(o3tl::convert(100E6, o3tl::Length::mm100, o3tl::Length::km), 1)); +static_assert(eq(o3tl::convert(10E6, o3tl::Length::mm10, o3tl::Length::km), 1)); +static_assert(eq(o3tl::convert(1E6, o3tl::Length::mm, o3tl::Length::km), 1)); +static_assert(eq(o3tl::convert(100000.0, o3tl::Length::cm, o3tl::Length::km), 1)); +static_assert(eq(o3tl::convert(1000.0, o3tl::Length::m, o3tl::Length::km), 1)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::km, o3tl::Length::km), 1)); +static_assert(eq(o3tl::convert(36E9, o3tl::Length::emu, o3tl::Length::km), 1)); +static_assert(eq(o3tl::convert(7200E6, o3tl::Length::twip, o3tl::Length::km), 127)); +static_assert(eq(o3tl::convert(360E6, o3tl::Length::pt, o3tl::Length::km), 127)); +static_assert(eq(o3tl::convert(30E6, o3tl::Length::pc, o3tl::Length::km), 127)); +static_assert(eq(o3tl::convert(5E9, o3tl::Length::in1000, o3tl::Length::km), 127)); +static_assert(eq(o3tl::convert(500E6, o3tl::Length::in100, o3tl::Length::km), 127)); +static_assert(eq(o3tl::convert(50E6, o3tl::Length::in10, o3tl::Length::km), 127)); +static_assert(eq(o3tl::convert(5E6, o3tl::Length::in, o3tl::Length::km), 127)); +static_assert(eq(o3tl::convert(1250000.0, o3tl::Length::ft, o3tl::Length::km), 381)); +static_assert(eq(o3tl::convert(15625.0, o3tl::Length::mi, o3tl::Length::km), 25146)); +static_assert(eq(o3tl::convert(2880E6, o3tl::Length::master, o3tl::Length::km), 127)); +static_assert(eq(o3tl::convert(480E6, o3tl::Length::px, o3tl::Length::km), 127)); +static_assert(eq(o3tl::convert(240E6, o3tl::Length::ch, o3tl::Length::km), 889)); +static_assert(eq(o3tl::convert(300E6, o3tl::Length::line, o3tl::Length::km), 1651)); + +static_assert(eq(o3tl::convert(1.0, o3tl::Length::mm100, o3tl::Length::emu), 360)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::mm10, o3tl::Length::emu), 3600)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::mm, o3tl::Length::emu), 36000)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::cm, o3tl::Length::emu), 360000)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::m, o3tl::Length::emu), 36E6)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::km, o3tl::Length::emu), 36E9)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::emu, o3tl::Length::emu), 1)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::twip, o3tl::Length::emu), 635)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::pt, o3tl::Length::emu), 12700)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::pc, o3tl::Length::emu), 152400)); +static_assert(eq(o3tl::convert(5.0, o3tl::Length::in1000, o3tl::Length::emu), 4572)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::in100, o3tl::Length::emu), 9144)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::in10, o3tl::Length::emu), 91440)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::in, o3tl::Length::emu), 914400)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::ft, o3tl::Length::emu), 10972800)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::mi, o3tl::Length::emu), 57936384000)); +static_assert(eq(o3tl::convert(2.0, o3tl::Length::master, o3tl::Length::emu), 3175)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::px, o3tl::Length::emu), 9525)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::ch, o3tl::Length::emu), 133350)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::line, o3tl::Length::emu), 198120)); + +static_assert(eq(o3tl::convert(127.0, o3tl::Length::mm100, o3tl::Length::twip), 72)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::mm10, o3tl::Length::twip), 720)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::mm, o3tl::Length::twip), 7200)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::cm, o3tl::Length::twip), 72000)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::m, o3tl::Length::twip), 7200000)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::km, o3tl::Length::twip), 7200E6)); +static_assert(eq(o3tl::convert(635.0, o3tl::Length::emu, o3tl::Length::twip), 1)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::twip, o3tl::Length::twip), 1)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::pt, o3tl::Length::twip), 20)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::pc, o3tl::Length::twip), 240)); +static_assert(eq(o3tl::convert(25.0, o3tl::Length::in1000, o3tl::Length::twip), 36)); +static_assert(eq(o3tl::convert(5.0, o3tl::Length::in100, o3tl::Length::twip), 72)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::in10, o3tl::Length::twip), 144)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::in, o3tl::Length::twip), 1440)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::ft, o3tl::Length::twip), 17280)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::mi, o3tl::Length::twip), 91238400)); +static_assert(eq(o3tl::convert(2.0, o3tl::Length::master, o3tl::Length::twip), 5)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::px, o3tl::Length::twip), 15)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::ch, o3tl::Length::twip), 210)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::line, o3tl::Length::twip), 312)); + +static_assert(eq(o3tl::convert(635.0, o3tl::Length::mm100, o3tl::Length::pt), 18)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::mm10, o3tl::Length::pt), 36)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::mm, o3tl::Length::pt), 360)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::cm, o3tl::Length::pt), 3600)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::m, o3tl::Length::pt), 360000)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::km, o3tl::Length::pt), 360E6)); +static_assert(eq(o3tl::convert(12700.0, o3tl::Length::emu, o3tl::Length::pt), 1)); +static_assert(eq(o3tl::convert(20.0, o3tl::Length::twip, o3tl::Length::pt), 1)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::pt, o3tl::Length::pt), 1)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::pc, o3tl::Length::pt), 12)); +static_assert(eq(o3tl::convert(125.0, o3tl::Length::in1000, o3tl::Length::pt), 9)); +static_assert(eq(o3tl::convert(25.0, o3tl::Length::in100, o3tl::Length::pt), 18)); +static_assert(eq(o3tl::convert(5.0, o3tl::Length::in10, o3tl::Length::pt), 36)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::in, o3tl::Length::pt), 72)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::ft, o3tl::Length::pt), 864)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::mi, o3tl::Length::pt), 4561920)); +static_assert(eq(o3tl::convert(8.0, o3tl::Length::master, o3tl::Length::pt), 1)); +static_assert(eq(o3tl::convert(4.0, o3tl::Length::px, o3tl::Length::pt), 3)); +static_assert(eq(o3tl::convert(2.0, o3tl::Length::ch, o3tl::Length::pt), 21)); +static_assert(eq(o3tl::convert(5.0, o3tl::Length::line, o3tl::Length::pt), 78)); + +static_assert(eq(o3tl::convert(1270.0, o3tl::Length::mm100, o3tl::Length::pc), 3)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::mm10, o3tl::Length::pc), 3)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::mm, o3tl::Length::pc), 30)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::cm, o3tl::Length::pc), 300)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::m, o3tl::Length::pc), 30000)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::km, o3tl::Length::pc), 30E6)); +static_assert(eq(o3tl::convert(152400.0, o3tl::Length::emu, o3tl::Length::pc), 1)); +static_assert(eq(o3tl::convert(240.0, o3tl::Length::twip, o3tl::Length::pc), 1)); +static_assert(eq(o3tl::convert(12.0, o3tl::Length::pt, o3tl::Length::pc), 1)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::pc, o3tl::Length::pc), 1)); +static_assert(eq(o3tl::convert(500.0, o3tl::Length::in1000, o3tl::Length::pc), 3)); +static_assert(eq(o3tl::convert(50.0, o3tl::Length::in100, o3tl::Length::pc), 3)); +static_assert(eq(o3tl::convert(5.0, o3tl::Length::in10, o3tl::Length::pc), 3)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::in, o3tl::Length::pc), 6)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::ft, o3tl::Length::pc), 72)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::mi, o3tl::Length::pc), 380160)); +static_assert(eq(o3tl::convert(96.0, o3tl::Length::master, o3tl::Length::pc), 1)); +static_assert(eq(o3tl::convert(16.0, o3tl::Length::px, o3tl::Length::pc), 1)); +static_assert(eq(o3tl::convert(8.0, o3tl::Length::ch, o3tl::Length::pc), 7)); +static_assert(eq(o3tl::convert(10.0, o3tl::Length::line, o3tl::Length::pc), 13)); + +static_assert(eq(o3tl::convert(127.0, o3tl::Length::mm100, o3tl::Length::in1000), 50)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::mm10, o3tl::Length::in1000), 500)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::mm, o3tl::Length::in1000), 5000)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::cm, o3tl::Length::in1000), 50000)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::m, o3tl::Length::in1000), 5E6)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::km, o3tl::Length::in1000), 5E9)); +static_assert(eq(o3tl::convert(4572.0, o3tl::Length::emu, o3tl::Length::in1000), 5)); +static_assert(eq(o3tl::convert(36.0, o3tl::Length::twip, o3tl::Length::in1000), 25)); +static_assert(eq(o3tl::convert(9.0, o3tl::Length::pt, o3tl::Length::in1000), 125)); +static_assert(eq(o3tl::convert(3.0, o3tl::Length::pc, o3tl::Length::in1000), 500)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::in1000, o3tl::Length::in1000), 1)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::in100, o3tl::Length::in1000), 10)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::in10, o3tl::Length::in1000), 100)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::in, o3tl::Length::in1000), 1000)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::ft, o3tl::Length::in1000), 12000)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::mi, o3tl::Length::in1000), 63360000)); +static_assert(eq(o3tl::convert(72.0, o3tl::Length::master, o3tl::Length::in1000), 125)); +static_assert(eq(o3tl::convert(12.0, o3tl::Length::px, o3tl::Length::in1000), 125)); +static_assert(eq(o3tl::convert(6.0, o3tl::Length::ch, o3tl::Length::in1000), 875)); +static_assert(eq(o3tl::convert(3.0, o3tl::Length::line, o3tl::Length::in1000), 650)); + +static_assert(eq(o3tl::convert(127.0, o3tl::Length::mm100, o3tl::Length::in100), 5)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::mm10, o3tl::Length::in100), 50)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::mm, o3tl::Length::in100), 500)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::cm, o3tl::Length::in100), 5000)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::m, o3tl::Length::in100), 500000)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::km, o3tl::Length::in100), 500E6)); +static_assert(eq(o3tl::convert(9144.0, o3tl::Length::emu, o3tl::Length::in100), 1)); +static_assert(eq(o3tl::convert(72.0, o3tl::Length::twip, o3tl::Length::in100), 5)); +static_assert(eq(o3tl::convert(18.0, o3tl::Length::pt, o3tl::Length::in100), 25)); +static_assert(eq(o3tl::convert(3.0, o3tl::Length::pc, o3tl::Length::in100), 50)); +static_assert(eq(o3tl::convert(10.0, o3tl::Length::in1000, o3tl::Length::in100), 1)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::in100, o3tl::Length::in100), 1)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::in10, o3tl::Length::in100), 10)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::in, o3tl::Length::in100), 100)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::ft, o3tl::Length::in100), 1200)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::mi, o3tl::Length::in100), 6336000)); +static_assert(eq(o3tl::convert(144.0, o3tl::Length::master, o3tl::Length::in100), 25)); +static_assert(eq(o3tl::convert(24.0, o3tl::Length::px, o3tl::Length::in100), 25)); +static_assert(eq(o3tl::convert(12.0, o3tl::Length::ch, o3tl::Length::in100), 175)); +static_assert(eq(o3tl::convert(3.0, o3tl::Length::line, o3tl::Length::in100), 65)); + +static_assert(eq(o3tl::convert(254.0, o3tl::Length::mm100, o3tl::Length::in10), 1)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::mm10, o3tl::Length::in10), 5)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::mm, o3tl::Length::in10), 50)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::cm, o3tl::Length::in10), 500)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::m, o3tl::Length::in10), 50000)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::km, o3tl::Length::in10), 50E6)); +static_assert(eq(o3tl::convert(91440.0, o3tl::Length::emu, o3tl::Length::in10), 1)); +static_assert(eq(o3tl::convert(144.0, o3tl::Length::twip, o3tl::Length::in10), 1)); +static_assert(eq(o3tl::convert(36.0, o3tl::Length::pt, o3tl::Length::in10), 5)); +static_assert(eq(o3tl::convert(3.0, o3tl::Length::pc, o3tl::Length::in10), 5)); +static_assert(eq(o3tl::convert(100.0, o3tl::Length::in1000, o3tl::Length::in10), 1)); +static_assert(eq(o3tl::convert(10.0, o3tl::Length::in100, o3tl::Length::in10), 1)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::in10, o3tl::Length::in10), 1)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::in, o3tl::Length::in10), 10)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::ft, o3tl::Length::in10), 120)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::mi, o3tl::Length::in10), 633600)); +static_assert(eq(o3tl::convert(288.0, o3tl::Length::master, o3tl::Length::in10), 5)); +static_assert(eq(o3tl::convert(48.0, o3tl::Length::px, o3tl::Length::in10), 5)); +static_assert(eq(o3tl::convert(24.0, o3tl::Length::ch, o3tl::Length::in10), 35)); +static_assert(eq(o3tl::convert(6.0, o3tl::Length::line, o3tl::Length::in10), 13)); + +static_assert(eq(o3tl::convert(2540.0, o3tl::Length::mm100, o3tl::Length::in), 1)); +static_assert(eq(o3tl::convert(254.0, o3tl::Length::mm10, o3tl::Length::in), 1)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::mm, o3tl::Length::in), 5)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::cm, o3tl::Length::in), 50)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::m, o3tl::Length::in), 5000)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::km, o3tl::Length::in), 5E6)); +static_assert(eq(o3tl::convert(914400.0, o3tl::Length::emu, o3tl::Length::in), 1)); +static_assert(eq(o3tl::convert(1440.0, o3tl::Length::twip, o3tl::Length::in), 1)); +static_assert(eq(o3tl::convert(72.0, o3tl::Length::pt, o3tl::Length::in), 1)); +static_assert(eq(o3tl::convert(6.0, o3tl::Length::pc, o3tl::Length::in), 1)); +static_assert(eq(o3tl::convert(1000.0, o3tl::Length::in1000, o3tl::Length::in), 1)); +static_assert(eq(o3tl::convert(100.0, o3tl::Length::in100, o3tl::Length::in), 1)); +static_assert(eq(o3tl::convert(10.0, o3tl::Length::in10, o3tl::Length::in), 1)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::in, o3tl::Length::in), 1)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::ft, o3tl::Length::in), 12)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::mi, o3tl::Length::in), 63360)); +static_assert(eq(o3tl::convert(576.0, o3tl::Length::master, o3tl::Length::in), 1)); +static_assert(eq(o3tl::convert(96.0, o3tl::Length::px, o3tl::Length::in), 1)); +static_assert(eq(o3tl::convert(48.0, o3tl::Length::ch, o3tl::Length::in), 7)); +static_assert(eq(o3tl::convert(60.0, o3tl::Length::line, o3tl::Length::in), 13)); + +static_assert(eq(o3tl::convert(30480.0, o3tl::Length::mm100, o3tl::Length::ft), 1)); +static_assert(eq(o3tl::convert(3048.0, o3tl::Length::mm10, o3tl::Length::ft), 1)); +static_assert(eq(o3tl::convert(1524.0, o3tl::Length::mm, o3tl::Length::ft), 5)); +static_assert(eq(o3tl::convert(762.0, o3tl::Length::cm, o3tl::Length::ft), 25)); +static_assert(eq(o3tl::convert(381.0, o3tl::Length::m, o3tl::Length::ft), 1250)); +static_assert(eq(o3tl::convert(381.0, o3tl::Length::km, o3tl::Length::ft), 1250000)); +static_assert(eq(o3tl::convert(10972800.0, o3tl::Length::emu, o3tl::Length::ft), 1)); +static_assert(eq(o3tl::convert(17280.0, o3tl::Length::twip, o3tl::Length::ft), 1)); +static_assert(eq(o3tl::convert(864.0, o3tl::Length::pt, o3tl::Length::ft), 1)); +static_assert(eq(o3tl::convert(72.0, o3tl::Length::pc, o3tl::Length::ft), 1)); +static_assert(eq(o3tl::convert(12000.0, o3tl::Length::in1000, o3tl::Length::ft), 1)); +static_assert(eq(o3tl::convert(1200.0, o3tl::Length::in100, o3tl::Length::ft), 1)); +static_assert(eq(o3tl::convert(120.0, o3tl::Length::in10, o3tl::Length::ft), 1)); +static_assert(eq(o3tl::convert(12.0, o3tl::Length::in, o3tl::Length::ft), 1)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::ft, o3tl::Length::ft), 1)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::mi, o3tl::Length::ft), 5280)); +static_assert(eq(o3tl::convert(6912.0, o3tl::Length::master, o3tl::Length::ft), 1)); +static_assert(eq(o3tl::convert(1152.0, o3tl::Length::px, o3tl::Length::ft), 1)); +static_assert(eq(o3tl::convert(576.0, o3tl::Length::ch, o3tl::Length::ft), 7)); +static_assert(eq(o3tl::convert(720.0, o3tl::Length::line, o3tl::Length::ft), 13)); + +static_assert(eq(o3tl::convert(160934400.0, o3tl::Length::mm100, o3tl::Length::mi), 1)); +static_assert(eq(o3tl::convert(16093440.0, o3tl::Length::mm10, o3tl::Length::mi), 1)); +static_assert(eq(o3tl::convert(1609344.0, o3tl::Length::mm, o3tl::Length::mi), 1)); +static_assert(eq(o3tl::convert(804672.0, o3tl::Length::cm, o3tl::Length::mi), 5)); +static_assert(eq(o3tl::convert(201168.0, o3tl::Length::m, o3tl::Length::mi), 125)); +static_assert(eq(o3tl::convert(25146.0, o3tl::Length::km, o3tl::Length::mi), 15625)); +static_assert(eq(o3tl::convert(57936384000.0, o3tl::Length::emu, o3tl::Length::mi), 1)); +static_assert(eq(o3tl::convert(91238400.0, o3tl::Length::twip, o3tl::Length::mi), 1)); +static_assert(eq(o3tl::convert(4561920.0, o3tl::Length::pt, o3tl::Length::mi), 1)); +static_assert(eq(o3tl::convert(380160.0, o3tl::Length::pc, o3tl::Length::mi), 1)); +static_assert(eq(o3tl::convert(63360000.0, o3tl::Length::in1000, o3tl::Length::mi), 1)); +static_assert(eq(o3tl::convert(6336000.0, o3tl::Length::in100, o3tl::Length::mi), 1)); +static_assert(eq(o3tl::convert(633600.0, o3tl::Length::in10, o3tl::Length::mi), 1)); +static_assert(eq(o3tl::convert(63360.0, o3tl::Length::in, o3tl::Length::mi), 1)); +static_assert(eq(o3tl::convert(5280.0, o3tl::Length::ft, o3tl::Length::mi), 1)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::mi, o3tl::Length::mi), 1)); +static_assert(eq(o3tl::convert(36495360.0, o3tl::Length::master, o3tl::Length::mi), 1)); +static_assert(eq(o3tl::convert(6082560.0, o3tl::Length::px, o3tl::Length::mi), 1)); +static_assert(eq(o3tl::convert(3041280.0, o3tl::Length::ch, o3tl::Length::mi), 7)); +static_assert(eq(o3tl::convert(3801600.0, o3tl::Length::line, o3tl::Length::mi), 13)); + +static_assert(eq(o3tl::convert(635.0, o3tl::Length::mm100, o3tl::Length::master), 144)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::mm10, o3tl::Length::master), 288)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::mm, o3tl::Length::master), 2880)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::cm, o3tl::Length::master), 28800)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::m, o3tl::Length::master), 2880000)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::km, o3tl::Length::master), 2880E6)); +static_assert(eq(o3tl::convert(3175.0, o3tl::Length::emu, o3tl::Length::master), 2)); +static_assert(eq(o3tl::convert(5.0, o3tl::Length::twip, o3tl::Length::master), 2)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::pt, o3tl::Length::master), 8)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::pc, o3tl::Length::master), 96)); +static_assert(eq(o3tl::convert(125.0, o3tl::Length::in1000, o3tl::Length::master), 72)); +static_assert(eq(o3tl::convert(25.0, o3tl::Length::in100, o3tl::Length::master), 144)); +static_assert(eq(o3tl::convert(5.0, o3tl::Length::in10, o3tl::Length::master), 288)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::in, o3tl::Length::master), 576)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::ft, o3tl::Length::master), 6912)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::mi, o3tl::Length::master), 36495360)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::master, o3tl::Length::master), 1)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::px, o3tl::Length::master), 6)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::ch, o3tl::Length::master), 84)); +static_assert(eq(o3tl::convert(5.0, o3tl::Length::line, o3tl::Length::master), 624)); + +static_assert(eq(o3tl::convert(635.0, o3tl::Length::mm100, o3tl::Length::px), 24)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::mm10, o3tl::Length::px), 48)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::mm, o3tl::Length::px), 480)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::cm, o3tl::Length::px), 4800)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::m, o3tl::Length::px), 480000)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::km, o3tl::Length::px), 480E6)); +static_assert(eq(o3tl::convert(9525.0, o3tl::Length::emu, o3tl::Length::px), 1)); +static_assert(eq(o3tl::convert(15.0, o3tl::Length::twip, o3tl::Length::px), 1)); +static_assert(eq(o3tl::convert(3.0, o3tl::Length::pt, o3tl::Length::px), 4)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::pc, o3tl::Length::px), 16)); +static_assert(eq(o3tl::convert(125.0, o3tl::Length::in1000, o3tl::Length::px), 12)); +static_assert(eq(o3tl::convert(25.0, o3tl::Length::in100, o3tl::Length::px), 24)); +static_assert(eq(o3tl::convert(5.0, o3tl::Length::in10, o3tl::Length::px), 48)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::in, o3tl::Length::px), 96)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::ft, o3tl::Length::px), 1152)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::mi, o3tl::Length::px), 6082560)); +static_assert(eq(o3tl::convert(6.0, o3tl::Length::master, o3tl::Length::px), 1)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::px, o3tl::Length::px), 1)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::ch, o3tl::Length::px), 14)); +static_assert(eq(o3tl::convert(5.0, o3tl::Length::line, o3tl::Length::px), 104)); + +static_assert(eq(o3tl::convert(4445.0, o3tl::Length::mm100, o3tl::Length::ch), 12)); +static_assert(eq(o3tl::convert(889.0, o3tl::Length::mm10, o3tl::Length::ch), 24)); +static_assert(eq(o3tl::convert(889.0, o3tl::Length::mm, o3tl::Length::ch), 240)); +static_assert(eq(o3tl::convert(889.0, o3tl::Length::cm, o3tl::Length::ch), 2400)); +static_assert(eq(o3tl::convert(889.0, o3tl::Length::m, o3tl::Length::ch), 240000)); +static_assert(eq(o3tl::convert(889.0, o3tl::Length::km, o3tl::Length::ch), 240E6)); +static_assert(eq(o3tl::convert(133350.0, o3tl::Length::emu, o3tl::Length::ch), 1)); +static_assert(eq(o3tl::convert(210.0, o3tl::Length::twip, o3tl::Length::ch), 1)); +static_assert(eq(o3tl::convert(21.0, o3tl::Length::pt, o3tl::Length::ch), 2)); +static_assert(eq(o3tl::convert(7.0, o3tl::Length::pc, o3tl::Length::ch), 8)); +static_assert(eq(o3tl::convert(875.0, o3tl::Length::in1000, o3tl::Length::ch), 6)); +static_assert(eq(o3tl::convert(175.0, o3tl::Length::in100, o3tl::Length::ch), 12)); +static_assert(eq(o3tl::convert(35.0, o3tl::Length::in10, o3tl::Length::ch), 24)); +static_assert(eq(o3tl::convert(7.0, o3tl::Length::in, o3tl::Length::ch), 48)); +static_assert(eq(o3tl::convert(7.0, o3tl::Length::ft, o3tl::Length::ch), 576)); +static_assert(eq(o3tl::convert(7.0, o3tl::Length::mi, o3tl::Length::ch), 3041280)); +static_assert(eq(o3tl::convert(84.0, o3tl::Length::master, o3tl::Length::ch), 1)); +static_assert(eq(o3tl::convert(14.0, o3tl::Length::px, o3tl::Length::ch), 1)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::ch, o3tl::Length::ch), 1)); +static_assert(eq(o3tl::convert(35.0, o3tl::Length::line, o3tl::Length::ch), 52)); + +static_assert(eq(o3tl::convert(1651.0, o3tl::Length::mm100, o3tl::Length::line), 3)); +static_assert(eq(o3tl::convert(1651.0, o3tl::Length::mm10, o3tl::Length::line), 30)); +static_assert(eq(o3tl::convert(1651.0, o3tl::Length::mm, o3tl::Length::line), 300)); +static_assert(eq(o3tl::convert(1651.0, o3tl::Length::cm, o3tl::Length::line), 3000)); +static_assert(eq(o3tl::convert(1651.0, o3tl::Length::m, o3tl::Length::line), 300000)); +static_assert(eq(o3tl::convert(1651.0, o3tl::Length::km, o3tl::Length::line), 300E6)); +static_assert(eq(o3tl::convert(198120.0, o3tl::Length::emu, o3tl::Length::line), 1)); +static_assert(eq(o3tl::convert(312.0, o3tl::Length::twip, o3tl::Length::line), 1)); +static_assert(eq(o3tl::convert(78.0, o3tl::Length::pt, o3tl::Length::line), 5)); +static_assert(eq(o3tl::convert(13.0, o3tl::Length::pc, o3tl::Length::line), 10)); +static_assert(eq(o3tl::convert(650.0, o3tl::Length::in1000, o3tl::Length::line), 3)); +static_assert(eq(o3tl::convert(65.0, o3tl::Length::in100, o3tl::Length::line), 3)); +static_assert(eq(o3tl::convert(13.0, o3tl::Length::in10, o3tl::Length::line), 6)); +static_assert(eq(o3tl::convert(13.0, o3tl::Length::in, o3tl::Length::line), 60)); +static_assert(eq(o3tl::convert(13.0, o3tl::Length::ft, o3tl::Length::line), 720)); +static_assert(eq(o3tl::convert(13.0, o3tl::Length::mi, o3tl::Length::line), 3801600)); +static_assert(eq(o3tl::convert(624.0, o3tl::Length::master, o3tl::Length::line), 5)); +static_assert(eq(o3tl::convert(104.0, o3tl::Length::px, o3tl::Length::line), 5)); +static_assert(eq(o3tl::convert(52.0, o3tl::Length::ch, o3tl::Length::line), 35)); +static_assert(eq(o3tl::convert(1.0, o3tl::Length::line, o3tl::Length::line), 1)); + +// testing integral conversion + +static_assert(o3tl::convert(100, o3tl::Length::mm100, o3tl::Length::mm100) == 100); +static_assert(o3tl::convert(100, o3tl::Length::mm10, o3tl::Length::mm100) == 1000); +static_assert(o3tl::convert(100, o3tl::Length::mm, o3tl::Length::mm100) == 10000); +static_assert(o3tl::convert(100, o3tl::Length::cm, o3tl::Length::mm100) == 100000); +static_assert(o3tl::convert(100, o3tl::Length::m, o3tl::Length::mm100) == 10000000); +static_assert(o3tl::convert(100, o3tl::Length::km, o3tl::Length::mm100) == 10000000000); +static_assert(o3tl::convert(36000, o3tl::Length::emu, o3tl::Length::mm100) == 100); +static_assert(o3tl::convert(7200, o3tl::Length::twip, o3tl::Length::mm100) == 12700); +static_assert(o3tl::convert(1800, o3tl::Length::pt, o3tl::Length::mm100) == 63500); +static_assert(o3tl::convert(300, o3tl::Length::pc, o3tl::Length::mm100) == 127000); +static_assert(o3tl::convert(5000, o3tl::Length::in1000, o3tl::Length::mm100) == 12700); +static_assert(o3tl::convert(500, o3tl::Length::in100, o3tl::Length::mm100) == 12700); +static_assert(o3tl::convert(100, o3tl::Length::in10, o3tl::Length::mm100) == 25400); +static_assert(o3tl::convert(100, o3tl::Length::in, o3tl::Length::mm100) == 254000); +static_assert(o3tl::convert(100, o3tl::Length::ft, o3tl::Length::mm100) == 3048000); +static_assert(o3tl::convert(100, o3tl::Length::mi, o3tl::Length::mm100) == 16093440000); +static_assert(o3tl::convert(14400, o3tl::Length::master, o3tl::Length::mm100) == 63500); +static_assert(o3tl::convert(2400, o3tl::Length::px, o3tl::Length::mm100) == 63500); +static_assert(o3tl::convert(1200, o3tl::Length::ch, o3tl::Length::mm100) == 444500); +static_assert(o3tl::convert(300, o3tl::Length::line, o3tl::Length::mm100) == 165100); + +static_assert(o3tl::convert(1000, o3tl::Length::mm100, o3tl::Length::mm10) == 100); +static_assert(o3tl::convert(100, o3tl::Length::mm10, o3tl::Length::mm10) == 100); +static_assert(o3tl::convert(100, o3tl::Length::mm, o3tl::Length::mm10) == 1000); +static_assert(o3tl::convert(100, o3tl::Length::cm, o3tl::Length::mm10) == 10000); +static_assert(o3tl::convert(100, o3tl::Length::m, o3tl::Length::mm10) == 1000000); +static_assert(o3tl::convert(100, o3tl::Length::km, o3tl::Length::mm10) == 1000000000); +static_assert(o3tl::convert(360000, o3tl::Length::emu, o3tl::Length::mm10) == 100); +static_assert(o3tl::convert(72000, o3tl::Length::twip, o3tl::Length::mm10) == 12700); +static_assert(o3tl::convert(3600, o3tl::Length::pt, o3tl::Length::mm10) == 12700); +static_assert(o3tl::convert(300, o3tl::Length::pc, o3tl::Length::mm10) == 12700); +static_assert(o3tl::convert(50000, o3tl::Length::in1000, o3tl::Length::mm10) == 12700); +static_assert(o3tl::convert(5000, o3tl::Length::in100, o3tl::Length::mm10) == 12700); +static_assert(o3tl::convert(500, o3tl::Length::in10, o3tl::Length::mm10) == 12700); +static_assert(o3tl::convert(100, o3tl::Length::in, o3tl::Length::mm10) == 25400); +static_assert(o3tl::convert(100, o3tl::Length::ft, o3tl::Length::mm10) == 304800); +static_assert(o3tl::convert(100, o3tl::Length::mi, o3tl::Length::mm10) == 1609344000); +static_assert(o3tl::convert(28800, o3tl::Length::master, o3tl::Length::mm10) == 12700); +static_assert(o3tl::convert(4800, o3tl::Length::px, o3tl::Length::mm10) == 12700); +static_assert(o3tl::convert(2400, o3tl::Length::ch, o3tl::Length::mm10) == 88900); +static_assert(o3tl::convert(3000, o3tl::Length::line, o3tl::Length::mm10) == 165100); + +static_assert(o3tl::convert(10000, o3tl::Length::mm100, o3tl::Length::mm) == 100); +static_assert(o3tl::convert(1000, o3tl::Length::mm10, o3tl::Length::mm) == 100); +static_assert(o3tl::convert(100, o3tl::Length::mm, o3tl::Length::mm) == 100); +static_assert(o3tl::convert(100, o3tl::Length::cm, o3tl::Length::mm) == 1000); +static_assert(o3tl::convert(100, o3tl::Length::m, o3tl::Length::mm) == 100000); +static_assert(o3tl::convert(100, o3tl::Length::km, o3tl::Length::mm) == 100000000); +static_assert(o3tl::convert(3600000, o3tl::Length::emu, o3tl::Length::mm) == 100); +static_assert(o3tl::convert(720000, o3tl::Length::twip, o3tl::Length::mm) == 12700); +static_assert(o3tl::convert(36000, o3tl::Length::pt, o3tl::Length::mm) == 12700); +static_assert(o3tl::convert(3000, o3tl::Length::pc, o3tl::Length::mm) == 12700); +static_assert(o3tl::convert(500000, o3tl::Length::in1000, o3tl::Length::mm) == 12700); +static_assert(o3tl::convert(50000, o3tl::Length::in100, o3tl::Length::mm) == 12700); +static_assert(o3tl::convert(5000, o3tl::Length::in10, o3tl::Length::mm) == 12700); +static_assert(o3tl::convert(500, o3tl::Length::in, o3tl::Length::mm) == 12700); +static_assert(o3tl::convert(500, o3tl::Length::ft, o3tl::Length::mm) == 152400); +static_assert(o3tl::convert(100, o3tl::Length::mi, o3tl::Length::mm) == 160934400); +static_assert(o3tl::convert(288000, o3tl::Length::master, o3tl::Length::mm) == 12700); +static_assert(o3tl::convert(48000, o3tl::Length::px, o3tl::Length::mm) == 12700); +static_assert(o3tl::convert(24000, o3tl::Length::ch, o3tl::Length::mm) == 88900); +static_assert(o3tl::convert(30000, o3tl::Length::line, o3tl::Length::mm) == 165100); + +static_assert(o3tl::convert(100000, o3tl::Length::mm100, o3tl::Length::cm) == 100); +static_assert(o3tl::convert(10000, o3tl::Length::mm10, o3tl::Length::cm) == 100); +static_assert(o3tl::convert(1000, o3tl::Length::mm, o3tl::Length::cm) == 100); +static_assert(o3tl::convert(100, o3tl::Length::cm, o3tl::Length::cm) == 100); +static_assert(o3tl::convert(100, o3tl::Length::m, o3tl::Length::cm) == 10000); +static_assert(o3tl::convert(100, o3tl::Length::km, o3tl::Length::cm) == 10000000); +static_assert(o3tl::convert(36000000, o3tl::Length::emu, o3tl::Length::cm) == 100); +static_assert(o3tl::convert(7200000, o3tl::Length::twip, o3tl::Length::cm) == 12700); +static_assert(o3tl::convert(360000, o3tl::Length::pt, o3tl::Length::cm) == 12700); +static_assert(o3tl::convert(30000, o3tl::Length::pc, o3tl::Length::cm) == 12700); +static_assert(o3tl::convert(5000000, o3tl::Length::in1000, o3tl::Length::cm) == 12700); +static_assert(o3tl::convert(500000, o3tl::Length::in100, o3tl::Length::cm) == 12700); +static_assert(o3tl::convert(50000, o3tl::Length::in10, o3tl::Length::cm) == 12700); +static_assert(o3tl::convert(5000, o3tl::Length::in, o3tl::Length::cm) == 12700); +static_assert(o3tl::convert(2500, o3tl::Length::ft, o3tl::Length::cm) == 76200); +static_assert(o3tl::convert(500, o3tl::Length::mi, o3tl::Length::cm) == 80467200); +static_assert(o3tl::convert(2880000, o3tl::Length::master, o3tl::Length::cm) == 12700); +static_assert(o3tl::convert(480000, o3tl::Length::px, o3tl::Length::cm) == 12700); +static_assert(o3tl::convert(240000, o3tl::Length::ch, o3tl::Length::cm) == 88900); +static_assert(o3tl::convert(300000, o3tl::Length::line, o3tl::Length::cm) == 165100); + +static_assert(o3tl::convert(10000000, o3tl::Length::mm100, o3tl::Length::m) == 100); +static_assert(o3tl::convert(1000000, o3tl::Length::mm10, o3tl::Length::m) == 100); +static_assert(o3tl::convert(100000, o3tl::Length::mm, o3tl::Length::m) == 100); +static_assert(o3tl::convert(10000, o3tl::Length::cm, o3tl::Length::m) == 100); +static_assert(o3tl::convert(100, o3tl::Length::m, o3tl::Length::m) == 100); +static_assert(o3tl::convert(100, o3tl::Length::km, o3tl::Length::m) == 100000); +static_assert(o3tl::convert(3600000000, o3tl::Length::emu, o3tl::Length::m) == 100); +static_assert(o3tl::convert(720000000, o3tl::Length::twip, o3tl::Length::m) == 12700); +static_assert(o3tl::convert(36000000, o3tl::Length::pt, o3tl::Length::m) == 12700); +static_assert(o3tl::convert(3000000, o3tl::Length::pc, o3tl::Length::m) == 12700); +static_assert(o3tl::convert(500000000, o3tl::Length::in1000, o3tl::Length::m) == 12700); +static_assert(o3tl::convert(50000000, o3tl::Length::in100, o3tl::Length::m) == 12700); +static_assert(o3tl::convert(5000000, o3tl::Length::in10, o3tl::Length::m) == 12700); +static_assert(o3tl::convert(500000, o3tl::Length::in, o3tl::Length::m) == 12700); +static_assert(o3tl::convert(125000, o3tl::Length::ft, o3tl::Length::m) == 38100); +static_assert(o3tl::convert(12500, o3tl::Length::mi, o3tl::Length::m) == 20116800); +static_assert(o3tl::convert(288000000, o3tl::Length::master, o3tl::Length::m) == 12700); +static_assert(o3tl::convert(48000000, o3tl::Length::px, o3tl::Length::m) == 12700); +static_assert(o3tl::convert(24000000, o3tl::Length::ch, o3tl::Length::m) == 88900); +static_assert(o3tl::convert(30000000, o3tl::Length::line, o3tl::Length::m) == 165100); + +static_assert(o3tl::convert(10000000000, o3tl::Length::mm100, o3tl::Length::km) == 100); +static_assert(o3tl::convert(1000000000, o3tl::Length::mm10, o3tl::Length::km) == 100); +static_assert(o3tl::convert(100000000, o3tl::Length::mm, o3tl::Length::km) == 100); +static_assert(o3tl::convert(10000000, o3tl::Length::cm, o3tl::Length::km) == 100); +static_assert(o3tl::convert(100000, o3tl::Length::m, o3tl::Length::km) == 100); +static_assert(o3tl::convert(100, o3tl::Length::km, o3tl::Length::km) == 100); +static_assert(o3tl::convert(3600000000000, o3tl::Length::emu, o3tl::Length::km) == 100); +static_assert(o3tl::convert(720000000000, o3tl::Length::twip, o3tl::Length::km) == 12700); +static_assert(o3tl::convert(36000000000, o3tl::Length::pt, o3tl::Length::km) == 12700); +static_assert(o3tl::convert(3000000000, o3tl::Length::pc, o3tl::Length::km) == 12700); +static_assert(o3tl::convert(500000000000, o3tl::Length::in1000, o3tl::Length::km) == 12700); +static_assert(o3tl::convert(50000000000, o3tl::Length::in100, o3tl::Length::km) == 12700); +static_assert(o3tl::convert(5000000000, o3tl::Length::in10, o3tl::Length::km) == 12700); +static_assert(o3tl::convert(500000000, o3tl::Length::in, o3tl::Length::km) == 12700); +static_assert(o3tl::convert(125000000, o3tl::Length::ft, o3tl::Length::km) == 38100); +static_assert(o3tl::convert(1562500, o3tl::Length::mi, o3tl::Length::km) == 2514600); +static_assert(o3tl::convert(288000000000, o3tl::Length::master, o3tl::Length::km) == 12700); +static_assert(o3tl::convert(48000000000, o3tl::Length::px, o3tl::Length::km) == 12700); +static_assert(o3tl::convert(24000000000, o3tl::Length::ch, o3tl::Length::km) == 88900); +static_assert(o3tl::convert(30000000000, o3tl::Length::line, o3tl::Length::km) == 165100); + +static_assert(o3tl::convert(100, o3tl::Length::mm100, o3tl::Length::emu) == 36000); +static_assert(o3tl::convert(100, o3tl::Length::mm10, o3tl::Length::emu) == 360000); +static_assert(o3tl::convert(100, o3tl::Length::mm, o3tl::Length::emu) == 3600000); +static_assert(o3tl::convert(100, o3tl::Length::cm, o3tl::Length::emu) == 36000000); +static_assert(o3tl::convert(100, o3tl::Length::m, o3tl::Length::emu) == 3600000000); +static_assert(o3tl::convert(100, o3tl::Length::km, o3tl::Length::emu) == 3600000000000); +static_assert(o3tl::convert(100, o3tl::Length::emu, o3tl::Length::emu) == 100); +static_assert(o3tl::convert(100, o3tl::Length::twip, o3tl::Length::emu) == 63500); +static_assert(o3tl::convert(100, o3tl::Length::pt, o3tl::Length::emu) == 1270000); +static_assert(o3tl::convert(100, o3tl::Length::pc, o3tl::Length::emu) == 15240000); +static_assert(o3tl::convert(500, o3tl::Length::in1000, o3tl::Length::emu) == 457200); +static_assert(o3tl::convert(100, o3tl::Length::in100, o3tl::Length::emu) == 914400); +static_assert(o3tl::convert(100, o3tl::Length::in10, o3tl::Length::emu) == 9144000); +static_assert(o3tl::convert(100, o3tl::Length::in, o3tl::Length::emu) == 91440000); +static_assert(o3tl::convert(100, o3tl::Length::ft, o3tl::Length::emu) == 1097280000); +static_assert(o3tl::convert(100, o3tl::Length::mi, o3tl::Length::emu) == 5793638400000); +static_assert(o3tl::convert(200, o3tl::Length::master, o3tl::Length::emu) == 317500); +static_assert(o3tl::convert(100, o3tl::Length::px, o3tl::Length::emu) == 952500); +static_assert(o3tl::convert(100, o3tl::Length::ch, o3tl::Length::emu) == 13335000); +static_assert(o3tl::convert(100, o3tl::Length::line, o3tl::Length::emu) == 19812000); + +static_assert(o3tl::convert(12700, o3tl::Length::mm100, o3tl::Length::twip) == 7200); +static_assert(o3tl::convert(12700, o3tl::Length::mm10, o3tl::Length::twip) == 72000); +static_assert(o3tl::convert(12700, o3tl::Length::mm, o3tl::Length::twip) == 720000); +static_assert(o3tl::convert(12700, o3tl::Length::cm, o3tl::Length::twip) == 7200000); +static_assert(o3tl::convert(12700, o3tl::Length::m, o3tl::Length::twip) == 720000000); +static_assert(o3tl::convert(12700, o3tl::Length::km, o3tl::Length::twip) == 720000000000); +static_assert(o3tl::convert(63500, o3tl::Length::emu, o3tl::Length::twip) == 100); +static_assert(o3tl::convert(100, o3tl::Length::twip, o3tl::Length::twip) == 100); +static_assert(o3tl::convert(100, o3tl::Length::pt, o3tl::Length::twip) == 2000); +static_assert(o3tl::convert(100, o3tl::Length::pc, o3tl::Length::twip) == 24000); +static_assert(o3tl::convert(2500, o3tl::Length::in1000, o3tl::Length::twip) == 3600); +static_assert(o3tl::convert(500, o3tl::Length::in100, o3tl::Length::twip) == 7200); +static_assert(o3tl::convert(100, o3tl::Length::in10, o3tl::Length::twip) == 14400); +static_assert(o3tl::convert(100, o3tl::Length::in, o3tl::Length::twip) == 144000); +static_assert(o3tl::convert(100, o3tl::Length::ft, o3tl::Length::twip) == 1728000); +static_assert(o3tl::convert(100, o3tl::Length::mi, o3tl::Length::twip) == 9123840000); +static_assert(o3tl::convert(200, o3tl::Length::master, o3tl::Length::twip) == 500); +static_assert(o3tl::convert(100, o3tl::Length::px, o3tl::Length::twip) == 1500); +static_assert(o3tl::convert(100, o3tl::Length::ch, o3tl::Length::twip) == 21000); +static_assert(o3tl::convert(100, o3tl::Length::line, o3tl::Length::twip) == 31200); + +static_assert(o3tl::convert(63500, o3tl::Length::mm100, o3tl::Length::pt) == 1800); +static_assert(o3tl::convert(12700, o3tl::Length::mm10, o3tl::Length::pt) == 3600); +static_assert(o3tl::convert(12700, o3tl::Length::mm, o3tl::Length::pt) == 36000); +static_assert(o3tl::convert(12700, o3tl::Length::cm, o3tl::Length::pt) == 360000); +static_assert(o3tl::convert(12700, o3tl::Length::m, o3tl::Length::pt) == 36000000); +static_assert(o3tl::convert(12700, o3tl::Length::km, o3tl::Length::pt) == 36000000000); +static_assert(o3tl::convert(1270000, o3tl::Length::emu, o3tl::Length::pt) == 100); +static_assert(o3tl::convert(2000, o3tl::Length::twip, o3tl::Length::pt) == 100); +static_assert(o3tl::convert(100, o3tl::Length::pt, o3tl::Length::pt) == 100); +static_assert(o3tl::convert(100, o3tl::Length::pc, o3tl::Length::pt) == 1200); +static_assert(o3tl::convert(12500, o3tl::Length::in1000, o3tl::Length::pt) == 900); +static_assert(o3tl::convert(2500, o3tl::Length::in100, o3tl::Length::pt) == 1800); +static_assert(o3tl::convert(500, o3tl::Length::in10, o3tl::Length::pt) == 3600); +static_assert(o3tl::convert(100, o3tl::Length::in, o3tl::Length::pt) == 7200); +static_assert(o3tl::convert(100, o3tl::Length::ft, o3tl::Length::pt) == 86400); +static_assert(o3tl::convert(100, o3tl::Length::mi, o3tl::Length::pt) == 456192000); +static_assert(o3tl::convert(800, o3tl::Length::master, o3tl::Length::pt) == 100); +static_assert(o3tl::convert(400, o3tl::Length::px, o3tl::Length::pt) == 300); +static_assert(o3tl::convert(200, o3tl::Length::ch, o3tl::Length::pt) == 2100); +static_assert(o3tl::convert(500, o3tl::Length::line, o3tl::Length::pt) == 7800); + +static_assert(o3tl::convert(127000, o3tl::Length::mm100, o3tl::Length::pc) == 300); +static_assert(o3tl::convert(12700, o3tl::Length::mm10, o3tl::Length::pc) == 300); +static_assert(o3tl::convert(12700, o3tl::Length::mm, o3tl::Length::pc) == 3000); +static_assert(o3tl::convert(12700, o3tl::Length::cm, o3tl::Length::pc) == 30000); +static_assert(o3tl::convert(12700, o3tl::Length::m, o3tl::Length::pc) == 3000000); +static_assert(o3tl::convert(12700, o3tl::Length::km, o3tl::Length::pc) == 3000000000); +static_assert(o3tl::convert(15240000, o3tl::Length::emu, o3tl::Length::pc) == 100); +static_assert(o3tl::convert(24000, o3tl::Length::twip, o3tl::Length::pc) == 100); +static_assert(o3tl::convert(1200, o3tl::Length::pt, o3tl::Length::pc) == 100); +static_assert(o3tl::convert(100, o3tl::Length::pc, o3tl::Length::pc) == 100); +static_assert(o3tl::convert(50000, o3tl::Length::in1000, o3tl::Length::pc) == 300); +static_assert(o3tl::convert(5000, o3tl::Length::in100, o3tl::Length::pc) == 300); +static_assert(o3tl::convert(500, o3tl::Length::in10, o3tl::Length::pc) == 300); +static_assert(o3tl::convert(100, o3tl::Length::in, o3tl::Length::pc) == 600); +static_assert(o3tl::convert(100, o3tl::Length::ft, o3tl::Length::pc) == 7200); +static_assert(o3tl::convert(100, o3tl::Length::mi, o3tl::Length::pc) == 38016000); +static_assert(o3tl::convert(9600, o3tl::Length::master, o3tl::Length::pc) == 100); +static_assert(o3tl::convert(1600, o3tl::Length::px, o3tl::Length::pc) == 100); +static_assert(o3tl::convert(800, o3tl::Length::ch, o3tl::Length::pc) == 700); +static_assert(o3tl::convert(1000, o3tl::Length::line, o3tl::Length::pc) == 1300); + +static_assert(o3tl::convert(12700, o3tl::Length::mm100, o3tl::Length::in1000) == 5000); +static_assert(o3tl::convert(12700, o3tl::Length::mm10, o3tl::Length::in1000) == 50000); +static_assert(o3tl::convert(12700, o3tl::Length::mm, o3tl::Length::in1000) == 500000); +static_assert(o3tl::convert(12700, o3tl::Length::cm, o3tl::Length::in1000) == 5000000); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::m, o3tl::Length::in1000), 5E6)); +static_assert(eq(o3tl::convert(127.0, o3tl::Length::km, o3tl::Length::in1000), 5E9)); +static_assert(o3tl::convert(457200, o3tl::Length::emu, o3tl::Length::in1000) == 500); +static_assert(o3tl::convert(3600, o3tl::Length::twip, o3tl::Length::in1000) == 2500); +static_assert(o3tl::convert(900, o3tl::Length::pt, o3tl::Length::in1000) == 12500); +static_assert(o3tl::convert(300, o3tl::Length::pc, o3tl::Length::in1000) == 50000); +static_assert(o3tl::convert(100, o3tl::Length::in1000, o3tl::Length::in1000) == 100); +static_assert(o3tl::convert(100, o3tl::Length::in100, o3tl::Length::in1000) == 1000); +static_assert(o3tl::convert(100, o3tl::Length::in10, o3tl::Length::in1000) == 10000); +static_assert(o3tl::convert(100, o3tl::Length::in, o3tl::Length::in1000) == 100000); +static_assert(o3tl::convert(100, o3tl::Length::ft, o3tl::Length::in1000) == 1200000); +static_assert(o3tl::convert(100, o3tl::Length::mi, o3tl::Length::in1000) == 6336000000); +static_assert(o3tl::convert(7200, o3tl::Length::master, o3tl::Length::in1000) == 12500); +static_assert(o3tl::convert(1200, o3tl::Length::px, o3tl::Length::in1000) == 12500); +static_assert(o3tl::convert(600, o3tl::Length::ch, o3tl::Length::in1000) == 87500); +static_assert(o3tl::convert(300, o3tl::Length::line, o3tl::Length::in1000) == 65000); + +static_assert(o3tl::convert(12700, o3tl::Length::mm100, o3tl::Length::in100) == 500); +static_assert(o3tl::convert(12700, o3tl::Length::mm10, o3tl::Length::in100) == 5000); +static_assert(o3tl::convert(12700, o3tl::Length::mm, o3tl::Length::in100) == 50000); +static_assert(o3tl::convert(12700, o3tl::Length::cm, o3tl::Length::in100) == 500000); +static_assert(o3tl::convert(12700, o3tl::Length::m, o3tl::Length::in100) == 50000000); +static_assert(o3tl::convert(12700, o3tl::Length::km, o3tl::Length::in100) == 50000000000); +static_assert(o3tl::convert(914400, o3tl::Length::emu, o3tl::Length::in100) == 100); +static_assert(o3tl::convert(7200, o3tl::Length::twip, o3tl::Length::in100) == 500); +static_assert(o3tl::convert(1800, o3tl::Length::pt, o3tl::Length::in100) == 2500); +static_assert(o3tl::convert(300, o3tl::Length::pc, o3tl::Length::in100) == 5000); +static_assert(o3tl::convert(1000, o3tl::Length::in1000, o3tl::Length::in100) == 100); +static_assert(o3tl::convert(100, o3tl::Length::in100, o3tl::Length::in100) == 100); +static_assert(o3tl::convert(100, o3tl::Length::in10, o3tl::Length::in100) == 1000); +static_assert(o3tl::convert(100, o3tl::Length::in, o3tl::Length::in100) == 10000); +static_assert(o3tl::convert(100, o3tl::Length::ft, o3tl::Length::in100) == 120000); +static_assert(o3tl::convert(100, o3tl::Length::mi, o3tl::Length::in100) == 633600000); +static_assert(o3tl::convert(14400, o3tl::Length::master, o3tl::Length::in100) == 2500); +static_assert(o3tl::convert(2400, o3tl::Length::px, o3tl::Length::in100) == 2500); +static_assert(o3tl::convert(1200, o3tl::Length::ch, o3tl::Length::in100) == 17500); +static_assert(o3tl::convert(300, o3tl::Length::line, o3tl::Length::in100) == 6500); + +static_assert(o3tl::convert(25400, o3tl::Length::mm100, o3tl::Length::in10) == 100); +static_assert(o3tl::convert(12700, o3tl::Length::mm10, o3tl::Length::in10) == 500); +static_assert(o3tl::convert(12700, o3tl::Length::mm, o3tl::Length::in10) == 5000); +static_assert(o3tl::convert(12700, o3tl::Length::cm, o3tl::Length::in10) == 50000); +static_assert(o3tl::convert(12700, o3tl::Length::m, o3tl::Length::in10) == 5000000); +static_assert(o3tl::convert(12700, o3tl::Length::km, o3tl::Length::in10) == 5000000000); +static_assert(o3tl::convert(9144000, o3tl::Length::emu, o3tl::Length::in10) == 100); +static_assert(o3tl::convert(14400, o3tl::Length::twip, o3tl::Length::in10) == 100); +static_assert(o3tl::convert(3600, o3tl::Length::pt, o3tl::Length::in10) == 500); +static_assert(o3tl::convert(300, o3tl::Length::pc, o3tl::Length::in10) == 500); +static_assert(o3tl::convert(10000, o3tl::Length::in1000, o3tl::Length::in10) == 100); +static_assert(o3tl::convert(1000, o3tl::Length::in100, o3tl::Length::in10) == 100); +static_assert(o3tl::convert(100, o3tl::Length::in10, o3tl::Length::in10) == 100); +static_assert(o3tl::convert(100, o3tl::Length::in, o3tl::Length::in10) == 1000); +static_assert(o3tl::convert(100, o3tl::Length::ft, o3tl::Length::in10) == 12000); +static_assert(o3tl::convert(100, o3tl::Length::mi, o3tl::Length::in10) == 63360000); +static_assert(o3tl::convert(28800, o3tl::Length::master, o3tl::Length::in10) == 500); +static_assert(o3tl::convert(4800, o3tl::Length::px, o3tl::Length::in10) == 500); +static_assert(o3tl::convert(2400, o3tl::Length::ch, o3tl::Length::in10) == 3500); +static_assert(o3tl::convert(600, o3tl::Length::line, o3tl::Length::in10) == 1300); + +static_assert(o3tl::convert(254000, o3tl::Length::mm100, o3tl::Length::in) == 100); +static_assert(o3tl::convert(25400, o3tl::Length::mm10, o3tl::Length::in) == 100); +static_assert(o3tl::convert(12700, o3tl::Length::mm, o3tl::Length::in) == 500); +static_assert(o3tl::convert(12700, o3tl::Length::cm, o3tl::Length::in) == 5000); +static_assert(o3tl::convert(12700, o3tl::Length::m, o3tl::Length::in) == 500000); +static_assert(o3tl::convert(12700, o3tl::Length::km, o3tl::Length::in) == 500000000); +static_assert(o3tl::convert(91440000, o3tl::Length::emu, o3tl::Length::in) == 100); +static_assert(o3tl::convert(144000, o3tl::Length::twip, o3tl::Length::in) == 100); +static_assert(o3tl::convert(7200, o3tl::Length::pt, o3tl::Length::in) == 100); +static_assert(o3tl::convert(600, o3tl::Length::pc, o3tl::Length::in) == 100); +static_assert(o3tl::convert(100000, o3tl::Length::in1000, o3tl::Length::in) == 100); +static_assert(o3tl::convert(10000, o3tl::Length::in100, o3tl::Length::in) == 100); +static_assert(o3tl::convert(1000, o3tl::Length::in10, o3tl::Length::in) == 100); +static_assert(o3tl::convert(100, o3tl::Length::in, o3tl::Length::in) == 100); +static_assert(o3tl::convert(100, o3tl::Length::ft, o3tl::Length::in) == 1200); +static_assert(o3tl::convert(100, o3tl::Length::mi, o3tl::Length::in) == 6336000); +static_assert(o3tl::convert(57600, o3tl::Length::master, o3tl::Length::in) == 100); +static_assert(o3tl::convert(9600, o3tl::Length::px, o3tl::Length::in) == 100); +static_assert(o3tl::convert(4800, o3tl::Length::ch, o3tl::Length::in) == 700); +static_assert(o3tl::convert(6000, o3tl::Length::line, o3tl::Length::in) == 1300); + +static_assert(o3tl::convert(3048000, o3tl::Length::mm100, o3tl::Length::ft) == 100); +static_assert(o3tl::convert(304800, o3tl::Length::mm10, o3tl::Length::ft) == 100); +static_assert(o3tl::convert(152400, o3tl::Length::mm, o3tl::Length::ft) == 500); +static_assert(o3tl::convert(76200, o3tl::Length::cm, o3tl::Length::ft) == 2500); +static_assert(o3tl::convert(38100, o3tl::Length::m, o3tl::Length::ft) == 125000); +static_assert(o3tl::convert(38100, o3tl::Length::km, o3tl::Length::ft) == 125000000); +static_assert(o3tl::convert(1097280000, o3tl::Length::emu, o3tl::Length::ft) == 100); +static_assert(o3tl::convert(1728000, o3tl::Length::twip, o3tl::Length::ft) == 100); +static_assert(o3tl::convert(86400, o3tl::Length::pt, o3tl::Length::ft) == 100); +static_assert(o3tl::convert(7200, o3tl::Length::pc, o3tl::Length::ft) == 100); +static_assert(o3tl::convert(1200000, o3tl::Length::in1000, o3tl::Length::ft) == 100); +static_assert(o3tl::convert(120000, o3tl::Length::in100, o3tl::Length::ft) == 100); +static_assert(o3tl::convert(12000, o3tl::Length::in10, o3tl::Length::ft) == 100); +static_assert(o3tl::convert(1200, o3tl::Length::in, o3tl::Length::ft) == 100); +static_assert(o3tl::convert(100, o3tl::Length::ft, o3tl::Length::ft) == 100); +static_assert(o3tl::convert(100, o3tl::Length::mi, o3tl::Length::ft) == 528000); +static_assert(o3tl::convert(691200, o3tl::Length::master, o3tl::Length::ft) == 100); +static_assert(o3tl::convert(115200, o3tl::Length::px, o3tl::Length::ft) == 100); +static_assert(o3tl::convert(57600, o3tl::Length::ch, o3tl::Length::ft) == 700); +static_assert(o3tl::convert(72000, o3tl::Length::line, o3tl::Length::ft) == 1300); + +static_assert(o3tl::convert(16093440000, o3tl::Length::mm100, o3tl::Length::mi) == 100); +static_assert(o3tl::convert(1609344000, o3tl::Length::mm10, o3tl::Length::mi) == 100); +static_assert(o3tl::convert(160934400, o3tl::Length::mm, o3tl::Length::mi) == 100); +static_assert(o3tl::convert(80467200, o3tl::Length::cm, o3tl::Length::mi) == 500); +static_assert(o3tl::convert(20116800, o3tl::Length::m, o3tl::Length::mi) == 12500); +static_assert(o3tl::convert(2514600, o3tl::Length::km, o3tl::Length::mi) == 1562500); +static_assert(o3tl::convert(5793638400000, o3tl::Length::emu, o3tl::Length::mi) == 100); +static_assert(o3tl::convert(9123840000, o3tl::Length::twip, o3tl::Length::mi) == 100); +static_assert(o3tl::convert(456192000, o3tl::Length::pt, o3tl::Length::mi) == 100); +static_assert(o3tl::convert(38016000, o3tl::Length::pc, o3tl::Length::mi) == 100); +static_assert(o3tl::convert(6336000000, o3tl::Length::in1000, o3tl::Length::mi) == 100); +static_assert(o3tl::convert(633600000, o3tl::Length::in100, o3tl::Length::mi) == 100); +static_assert(o3tl::convert(63360000, o3tl::Length::in10, o3tl::Length::mi) == 100); +static_assert(o3tl::convert(6336000, o3tl::Length::in, o3tl::Length::mi) == 100); +static_assert(o3tl::convert(528000, o3tl::Length::ft, o3tl::Length::mi) == 100); +static_assert(o3tl::convert(100, o3tl::Length::mi, o3tl::Length::mi) == 100); +static_assert(o3tl::convert(3649536000, o3tl::Length::master, o3tl::Length::mi) == 100); +static_assert(o3tl::convert(608256000, o3tl::Length::px, o3tl::Length::mi) == 100); +static_assert(o3tl::convert(304128000, o3tl::Length::ch, o3tl::Length::mi) == 700); +static_assert(o3tl::convert(380160000, o3tl::Length::line, o3tl::Length::mi) == 1300); + +static_assert(o3tl::convert(63500, o3tl::Length::mm100, o3tl::Length::master) == 14400); +static_assert(o3tl::convert(12700, o3tl::Length::mm10, o3tl::Length::master) == 28800); +static_assert(o3tl::convert(12700, o3tl::Length::mm, o3tl::Length::master) == 288000); +static_assert(o3tl::convert(12700, o3tl::Length::cm, o3tl::Length::master) == 2880000); +static_assert(o3tl::convert(12700, o3tl::Length::m, o3tl::Length::master) == 288000000); +static_assert(o3tl::convert(12700, o3tl::Length::km, o3tl::Length::master) == 288000000000); +static_assert(o3tl::convert(317500, o3tl::Length::emu, o3tl::Length::master) == 200); +static_assert(o3tl::convert(500, o3tl::Length::twip, o3tl::Length::master) == 200); +static_assert(o3tl::convert(100, o3tl::Length::pt, o3tl::Length::master) == 800); +static_assert(o3tl::convert(100, o3tl::Length::pc, o3tl::Length::master) == 9600); +static_assert(o3tl::convert(12500, o3tl::Length::in1000, o3tl::Length::master) == 7200); +static_assert(o3tl::convert(2500, o3tl::Length::in100, o3tl::Length::master) == 14400); +static_assert(o3tl::convert(500, o3tl::Length::in10, o3tl::Length::master) == 28800); +static_assert(o3tl::convert(100, o3tl::Length::in, o3tl::Length::master) == 57600); +static_assert(o3tl::convert(100, o3tl::Length::ft, o3tl::Length::master) == 691200); +static_assert(o3tl::convert(100, o3tl::Length::mi, o3tl::Length::master) == 3649536000); +static_assert(o3tl::convert(100, o3tl::Length::master, o3tl::Length::master) == 100); +static_assert(o3tl::convert(100, o3tl::Length::px, o3tl::Length::master) == 600); +static_assert(o3tl::convert(100, o3tl::Length::ch, o3tl::Length::master) == 8400); +static_assert(o3tl::convert(500, o3tl::Length::line, o3tl::Length::master) == 62400); + +static_assert(o3tl::convert(63500, o3tl::Length::mm100, o3tl::Length::px) == 2400); +static_assert(o3tl::convert(12700, o3tl::Length::mm10, o3tl::Length::px) == 4800); +static_assert(o3tl::convert(12700, o3tl::Length::mm, o3tl::Length::px) == 48000); +static_assert(o3tl::convert(12700, o3tl::Length::cm, o3tl::Length::px) == 480000); +static_assert(o3tl::convert(12700, o3tl::Length::m, o3tl::Length::px) == 48000000); +static_assert(o3tl::convert(12700, o3tl::Length::km, o3tl::Length::px) == 48000000000); +static_assert(o3tl::convert(952500, o3tl::Length::emu, o3tl::Length::px) == 100); +static_assert(o3tl::convert(1500, o3tl::Length::twip, o3tl::Length::px) == 100); +static_assert(o3tl::convert(300, o3tl::Length::pt, o3tl::Length::px) == 400); +static_assert(o3tl::convert(100, o3tl::Length::pc, o3tl::Length::px) == 1600); +static_assert(o3tl::convert(12500, o3tl::Length::in1000, o3tl::Length::px) == 1200); +static_assert(o3tl::convert(2500, o3tl::Length::in100, o3tl::Length::px) == 2400); +static_assert(o3tl::convert(500, o3tl::Length::in10, o3tl::Length::px) == 4800); +static_assert(o3tl::convert(100, o3tl::Length::in, o3tl::Length::px) == 9600); +static_assert(o3tl::convert(100, o3tl::Length::ft, o3tl::Length::px) == 115200); +static_assert(o3tl::convert(100, o3tl::Length::mi, o3tl::Length::px) == 608256000); +static_assert(o3tl::convert(600, o3tl::Length::master, o3tl::Length::px) == 100); +static_assert(o3tl::convert(100, o3tl::Length::px, o3tl::Length::px) == 100); +static_assert(o3tl::convert(100, o3tl::Length::ch, o3tl::Length::px) == 1400); +static_assert(o3tl::convert(500, o3tl::Length::line, o3tl::Length::px) == 10400); + +static_assert(o3tl::convert(444500, o3tl::Length::mm100, o3tl::Length::ch) == 1200); +static_assert(o3tl::convert(88900, o3tl::Length::mm10, o3tl::Length::ch) == 2400); +static_assert(o3tl::convert(88900, o3tl::Length::mm, o3tl::Length::ch) == 24000); +static_assert(o3tl::convert(88900, o3tl::Length::cm, o3tl::Length::ch) == 240000); +static_assert(o3tl::convert(88900, o3tl::Length::m, o3tl::Length::ch) == 24000000); +static_assert(o3tl::convert(88900, o3tl::Length::km, o3tl::Length::ch) == 24000000000); +static_assert(o3tl::convert(13335000, o3tl::Length::emu, o3tl::Length::ch) == 100); +static_assert(o3tl::convert(21000, o3tl::Length::twip, o3tl::Length::ch) == 100); +static_assert(o3tl::convert(2100, o3tl::Length::pt, o3tl::Length::ch) == 200); +static_assert(o3tl::convert(700, o3tl::Length::pc, o3tl::Length::ch) == 800); +static_assert(o3tl::convert(87500, o3tl::Length::in1000, o3tl::Length::ch) == 600); +static_assert(o3tl::convert(17500, o3tl::Length::in100, o3tl::Length::ch) == 1200); +static_assert(o3tl::convert(3500, o3tl::Length::in10, o3tl::Length::ch) == 2400); +static_assert(o3tl::convert(700, o3tl::Length::in, o3tl::Length::ch) == 4800); +static_assert(o3tl::convert(700, o3tl::Length::ft, o3tl::Length::ch) == 57600); +static_assert(o3tl::convert(700, o3tl::Length::mi, o3tl::Length::ch) == 304128000); +static_assert(o3tl::convert(8400, o3tl::Length::master, o3tl::Length::ch) == 100); +static_assert(o3tl::convert(1400, o3tl::Length::px, o3tl::Length::ch) == 100); +static_assert(o3tl::convert(100, o3tl::Length::ch, o3tl::Length::ch) == 100); +static_assert(o3tl::convert(3500, o3tl::Length::line, o3tl::Length::ch) == 5200); + +static_assert(o3tl::convert(165100, o3tl::Length::mm100, o3tl::Length::line) == 300); +static_assert(o3tl::convert(165100, o3tl::Length::mm10, o3tl::Length::line) == 3000); +static_assert(o3tl::convert(165100, o3tl::Length::mm, o3tl::Length::line) == 30000); +static_assert(o3tl::convert(165100, o3tl::Length::cm, o3tl::Length::line) == 300000); +static_assert(o3tl::convert(165100, o3tl::Length::m, o3tl::Length::line) == 30000000); +static_assert(o3tl::convert(165100, o3tl::Length::km, o3tl::Length::line) == 30000000000); +static_assert(o3tl::convert(19812000, o3tl::Length::emu, o3tl::Length::line) == 100); +static_assert(o3tl::convert(31200, o3tl::Length::twip, o3tl::Length::line) == 100); +static_assert(o3tl::convert(7800, o3tl::Length::pt, o3tl::Length::line) == 500); +static_assert(o3tl::convert(1300, o3tl::Length::pc, o3tl::Length::line) == 1000); +static_assert(o3tl::convert(65000, o3tl::Length::in1000, o3tl::Length::line) == 300); +static_assert(o3tl::convert(6500, o3tl::Length::in100, o3tl::Length::line) == 300); +static_assert(o3tl::convert(1300, o3tl::Length::in10, o3tl::Length::line) == 600); +static_assert(o3tl::convert(1300, o3tl::Length::in, o3tl::Length::line) == 6000); +static_assert(o3tl::convert(1300, o3tl::Length::ft, o3tl::Length::line) == 72000); +static_assert(o3tl::convert(1300, o3tl::Length::mi, o3tl::Length::line) == 380160000); +static_assert(o3tl::convert(62400, o3tl::Length::master, o3tl::Length::line) == 500); +static_assert(o3tl::convert(10400, o3tl::Length::px, o3tl::Length::line) == 500); +static_assert(o3tl::convert(5200, o3tl::Length::ch, o3tl::Length::line) == 3500); +static_assert(o3tl::convert(100, o3tl::Length::line, o3tl::Length::line) == 100); + +// Integral rounding + +static_assert(o3tl::convert(49, o3tl::Length::mm100, o3tl::Length::mm) == 0); +static_assert(o3tl::convert(50, o3tl::Length::mm100, o3tl::Length::mm) == 1); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/oox/source/drawingml/diagram/diagram.cxx b/oox/source/drawingml/diagram/diagram.cxx index 9a8f727b9070..28c79e8cbd60 100644 --- a/oox/source/drawingml/diagram/diagram.cxx +++ b/oox/source/drawingml/diagram/diagram.cxx @@ -30,6 +30,7 @@ #include <editeng/unoprnms.hxx> #include <drawingml/fillproperties.hxx> #include <drawingml/customshapeproperties.hxx> +#include <o3tl/unit_conversion.hxx> #include <oox/token/namespaces.hxx> #include <basegfx/matrix/b2dhommatrix.hxx> #include <svx/svdpage.hxx> @@ -439,15 +440,17 @@ void reloadDiagram(SdrObject* pObj, core::XmlFilterBase& rFilter) ShapePtr pShape = std::make_shared<Shape>(); pShape->setDiagramType(); - pShape->setSize(awt::Size(xShape->getSize().Width * EMU_PER_HMM, - xShape->getSize().Height * EMU_PER_HMM)); + pShape->setSize( + awt::Size(o3tl::convert(xShape->getSize().Width, o3tl::Length::mm100, o3tl::Length::emu), + o3tl::convert(xShape->getSize().Height, o3tl::Length::mm100, o3tl::Length::emu))); loadDiagram(pShape, pDiagramData, layoutDom, styleDom, colorDom, rFilter); uno::Reference<drawing::XShapes> xShapes(xShape, uno::UNO_QUERY_THROW); basegfx::B2DHomMatrix aTransformation; - aTransformation.translate(xShape->getPosition().X * EMU_PER_HMM, - xShape->getPosition().Y * EMU_PER_HMM); + aTransformation.translate( + o3tl::convert(xShape->getPosition().X, o3tl::Length::mm100, o3tl::Length::emu), + o3tl::convert(xShape->getPosition().Y, o3tl::Length::mm100, o3tl::Length::emu)); for (auto const& child : pShape->getChildren()) child->addShape(rFilter, rFilter.getCurrentTheme(), xShapes, aTransformation, pShape->getFillProperties()); } diff --git a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx index 66df25d9ef4a..bc24b0322059 100644 --- a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx +++ b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx @@ -26,6 +26,7 @@ #include <basegfx/numeric/ftools.hxx> #include <sal/log.hxx> +#include <o3tl/unit_conversion.hxx> #include <oox/helper/attributelist.hxx> #include <oox/token/properties.hxx> #include <drawingml/fillproperties.hxx> @@ -538,14 +539,11 @@ void CompositeAlg::applyConstraintToLayout(const Constraint& rConstraint, // Reference not found, assume a fixed value. // Values are never in EMU, while oox::drawingml::Shape position and size are always in // EMU. - double fUnitFactor = 0; - if (isFontUnit(rConstraint.mnRefType)) - // Points -> EMU. - fUnitFactor = EMU_PER_PT; - else - // Millimeters -> EMU. - fUnitFactor = EMU_PER_HMM * 100; - rProperties[rConstraint.msForName][rConstraint.mnType] = rConstraint.mfValue * fUnitFactor; + const double fValue = o3tl::convert(rConstraint.mfValue, + isFontUnit(rConstraint.mnRefType) ? o3tl::Length::pt + : o3tl::Length::mm, + o3tl::Length::emu); + rProperties[rConstraint.msForName][rConstraint.mnType] = fValue; } } @@ -1709,7 +1707,8 @@ void AlgAtom::layoutShape(const ShapePtr& rShape, const std::vector<Constraint>& double fFactor = convertPointToMms(rConstr.mfFactor); // DrawingML works in EMUs, UNO API works in MM100s. - sal_Int32 nValue = rShape->getSize().Width * fFactor / EMU_PER_HMM; + sal_Int32 nValue = o3tl::convert(rShape->getSize().Width * fFactor, + o3tl::Length::emu, o3tl::Length::mm100); rShape->getShapeProperties().setProperty(nProperty, nValue); } @@ -1816,12 +1815,15 @@ void AlgAtom::layoutShape(const ShapePtr& rShape, const std::vector<Constraint>& { if (!aParagraph->getProperties().getParaLeftMargin().has_value()) { - sal_Int32 nLeftMargin = 285750 * (nLevel - nStartBulletsAtLevel + 1) / EMU_PER_HMM; + sal_Int32 nLeftMargin + = o3tl::convert(285750 * (nLevel - nStartBulletsAtLevel + 1), + o3tl::Length::emu, o3tl::Length::mm100); aParagraph->getProperties().getParaLeftMargin() = nLeftMargin; } if (!aParagraph->getProperties().getFirstLineIndentation().has_value()) - aParagraph->getProperties().getFirstLineIndentation() = -285750 / EMU_PER_HMM; + aParagraph->getProperties().getFirstLineIndentation() + = o3tl::convert(-285750, o3tl::Length::emu, o3tl::Length::mm100); // It is not possible to change the bullet style for text. aParagraph->getProperties().getBulletList().setBulletChar(u"•"); diff --git a/oox/source/drawingml/drawingmltypes.cxx b/oox/source/drawingml/drawingmltypes.cxx index 645fe9ec9221..3a94a449f317 100644 --- a/oox/source/drawingml/drawingmltypes.cxx +++ b/oox/source/drawingml/drawingmltypes.cxx @@ -40,8 +40,7 @@ namespace oox::drawingml { /** converts EMUs into 1/100th mmm */ sal_Int32 GetCoordinate( sal_Int32 nValue ) { - nValue = o3tl::saturating_add<sal_Int32>(nValue, 180); - return nValue / 360; + return o3tl::convert(nValue, o3tl::Length::emu, o3tl::Length::mm100); } /** converts an emu string into 1/100th mmm */ @@ -56,7 +55,7 @@ sal_Int32 GetCoordinate( std::u16string_view sValue ) /** converts 1/100mm to EMU */ sal_Int32 GetPointFromCoordinate( sal_Int32 nValue ) { - return nValue * 360; + return o3tl::convert(nValue, o3tl::Length::mm100, o3tl::Length::emu); } /** converts a ST_Percentage % string into 1/1000th of % */ diff --git a/oox/source/drawingml/shape.cxx b/oox/source/drawingml/shape.cxx index b4ce27ea4df4..22cacec6eaa6 100644 --- a/oox/source/drawingml/shape.cxx +++ b/oox/source/drawingml/shape.cxx @@ -35,6 +35,7 @@ #include <drawingml/chart/chartspacefragment.hxx> #include <drawingml/chart/chartspacemodel.hxx> #include <o3tl/safeint.hxx> +#include <o3tl/unit_conversion.hxx> #include <oox/ppt/pptimport.hxx> #include <oox/vml/vmldrawing.hxx> #include <oox/vml/vmlshape.hxx> @@ -699,7 +700,11 @@ Reference< XShape > const & Shape::createAndInsert( } } - awt::Rectangle aShapeRectHmm( maPosition.X / EMU_PER_HMM, maPosition.Y / EMU_PER_HMM, maSize.Width / EMU_PER_HMM, maSize.Height / EMU_PER_HMM ); + awt::Rectangle aShapeRectHmm( + o3tl::convert(maPosition.X, o3tl::Length::emu, o3tl::Length::mm100), + o3tl::convert(maPosition.Y, o3tl::Length::emu, o3tl::Length::mm100), + o3tl::convert(maSize.Width, o3tl::Length::emu, o3tl::Length::mm100), + o3tl::convert(maSize.Height, o3tl::Length::emu, o3tl::Length::mm100)); OUString aServiceName; if (pMathXml) @@ -804,14 +809,17 @@ Reference< XShape > const & Shape::createAndInsert( { // if global position is used, add it to transformation if (mbWps && !bInGroup) - aTransformation.translate( maPosition.X * EMU_PER_HMM, maPosition.Y * EMU_PER_HMM); + aTransformation.translate( + o3tl::convert(maPosition.X, o3tl::Length::mm100, o3tl::Length::emu), + o3tl::convert(maPosition.Y, o3tl::Length::mm100, o3tl::Length::emu)); else aTransformation.translate( maPosition.X, maPosition.Y ); } aTransformation = aParentTransformation*aTransformation; aParentTransformation = aTransformation; - aTransformation.scale(1/double(EMU_PER_HMM), 1/double(EMU_PER_HMM)); + constexpr double fEmuToMm100 = o3tl::convert(1.0, o3tl::Length::emu, o3tl::Length::mm100); + aTransformation.scale(fEmuToMm100, fEmuToMm100); if( bIsCustomShape && mbFlipH != mbFlipV ) { diff --git a/oox/source/vml/vmlformatting.cxx b/oox/source/vml/vmlformatting.cxx index 60ef7f900d15..96d26efe8ff8 100644 --- a/oox/source/vml/vmlformatting.cxx +++ b/oox/source/vml/vmlformatting.cxx @@ -29,6 +29,7 @@ #include <com/sun/star/drawing/EnhancedCustomShapeTextPathMode.hpp> #include <com/sun/star/table/ShadowFormat.hpp> #include <com/sun/star/text/XTextRange.hpp> +#include <o3tl/unit_conversion.hxx> #include <rtl/strbuf.hxx> #include <sal/log.hxx> #include <osl/diagnose.h> @@ -174,21 +175,20 @@ sal_Int64 ConversionHelper::decodeMeasureToEmu( const GraphicHelper& rGraphicHel { sal_Unicode cChar1 = aUnit[ 0 ]; sal_Unicode cChar2 = aUnit[ 1 ]; - if( (cChar1 == 'i') && (cChar2 == 'n') ) // 1 inch = 914,400 EMU - fValue *= 914400.0; - else if( (cChar1 == 'c') && (cChar2 == 'm') ) // 1 cm = 360,000 EMU - fValue *= 360000.0; - else if( (cChar1 == 'm') && (cChar2 == 'm') ) // 1 mm = 36,000 EMU - fValue *= 36000.0; - else if( (cChar1 == 'p') && (cChar2 == 't') ) // 1 point = 1/72 inch = 12,700 EMU - fValue *= 12700.0; - else if( (cChar1 == 'p') && (cChar2 == 'c') ) // 1 pica = 1/6 inch = 152,400 EMU - fValue *= 152400.0; + if ((cChar1 == 'i') && (cChar2 == 'n')) + fValue = o3tl::convert(fValue, o3tl::Length::in, o3tl::Length::emu); + else if ((cChar1 == 'c') && (cChar2 == 'm')) + fValue = o3tl::convert(fValue, o3tl::Length::cm, o3tl::Length::emu); + else if ((cChar1 == 'm') && (cChar2 == 'm')) + fValue = o3tl::convert(fValue, o3tl::Length::mm, o3tl::Length::emu); + else if ((cChar1 == 'p') && (cChar2 == 't')) + fValue = o3tl::convert(fValue, o3tl::Length::pt, o3tl::Length::emu); + else if ((cChar1 == 'p') && (cChar2 == 'c')) + fValue = o3tl::convert(fValue, o3tl::Length::pc, o3tl::Length::emu); else if( (cChar1 == 'p') && (cChar2 == 'x') ) // 1 pixel, dependent on output device - fValue = static_cast< double >( ::oox::drawingml::convertHmmToEmu( - bPixelX ? - rGraphicHelper.convertScreenPixelXToHmm( fValue ) : - rGraphicHelper.convertScreenPixelYToHmm( fValue ) ) ); + fValue = o3tl::convert(bPixelX ? rGraphicHelper.convertScreenPixelXToHmm(fValue) + : rGraphicHelper.convertScreenPixelYToHmm(fValue), + o3tl::Length::mm100, o3tl::Length::emu); } else if( (aUnit.getLength() == 1) && (aUnit[ 0 ] == '%') ) { diff --git a/sax/source/tools/converter.cxx b/sax/source/tools/converter.cxx index 4f7c686a1aba..18731b45ac77 100644 --- a/sax/source/tools/converter.cxx +++ b/sax/source/tools/converter.cxx @@ -28,7 +28,9 @@ #include <rtl/ustrbuf.hxx> #include <rtl/math.hxx> +#include <rtl/character.hxx> #include <sal/log.hxx> +#include <o3tl/unit_conversion.hxx> #include <osl/diagnose.h> #include <tools/long.hxx> @@ -43,11 +45,11 @@ using namespace ::com::sun::star::i18n; namespace sax { -const char* const gpsMM = "mm"; -const char* const gpsCM = "cm"; -const char* const gpsPT = "pt"; -const char* const gpsINCH = "in"; -const char* const gpsPC = "pc"; +const std::string_view gpsMM = "mm"; +const std::string_view gpsCM = "cm"; +const std::string_view gpsPT = "pt"; +const std::string_view gpsINCH = "in"; +const std::string_view gpsPC = "pc"; const sal_Int8 XML_MAXDIGITSCOUNT_TIME = 14; @@ -60,6 +62,62 @@ static sal_Int64 toInt64_WithLength(const char * str, sal_Int16 radix, sal_Int32 return rtl_str_toInt64_WithLength(str, radix, nStrLength); } +namespace +{ +o3tl::Length Measure2O3tlUnit(sal_Int16 nUnit) +{ + switch (nUnit) + { + case MeasureUnit::TWIP: + return o3tl::Length::twip; + case MeasureUnit::POINT: + return o3tl::Length::pt; + case MeasureUnit::MM_10TH: + return o3tl::Length::mm10; + case MeasureUnit::MM_100TH: + return o3tl::Length::mm100; + case MeasureUnit::MM: + return o3tl::Length::mm; + case MeasureUnit::CM: + return o3tl::Length::cm; + default: + SAL_WARN("sax", "unit not supported for length"); + [[fallthrough]]; + case MeasureUnit::INCH: + return o3tl::Length::in; + } +} + +std::string_view Measure2UnitString(sal_Int16 nUnit) +{ + switch (nUnit) + { + case MeasureUnit::TWIP: + return gpsPC; // ?? + case MeasureUnit::POINT: + return gpsPT; + case MeasureUnit::MM_10TH: + case MeasureUnit::MM_100TH: + return {}; + case MeasureUnit::MM: + return gpsMM; + case MeasureUnit::CM: + return gpsCM; + case MeasureUnit::INCH: + default: + return gpsINCH; + } +} + +template <typename V> bool wordEndsWith(V string, std::string_view expected) +{ + V substr = string.substr(0, expected.size()); + return std::equal(substr.begin(), substr.end(), expected.begin(), expected.end(), + [](sal_uInt32 c1, sal_uInt32 c2) { return rtl::toAsciiLowerCase(c1) == c2; }) + && (string.size() == expected.size() || string[expected.size()] == ' '); +} + +} /** convert string to measure using optional min and max values*/ template<typename V> @@ -137,127 +195,70 @@ static bool lcl_convertMeasure( sal_Int32& rValue, OSL_ENSURE( MeasureUnit::TWIP == nTargetUnit || MeasureUnit::POINT == nTargetUnit || MeasureUnit::MM_100TH == nTargetUnit || MeasureUnit::MM_10TH == nTargetUnit || MeasureUnit::PIXEL == nTargetUnit, "unit is not supported"); - const char *aCmpsL[3] = { nullptr, nullptr, nullptr }; - const char *aCmpsU[3] = { nullptr, nullptr, nullptr }; - double aScales[3] = { 1., 1., 1. }; + + o3tl::Length eFrom = o3tl::Length::invalid; if( MeasureUnit::TWIP == nTargetUnit ) { - switch( rString[nPos] ) + switch (rtl::toAsciiLowerCase<sal_uInt32>(rString[nPos])) { case u'c': - case u'C': - aCmpsL[0] = "cm"; - aCmpsU[0] = "CM"; - aScales[0] = (72.*20.)/2.54; // twip + if (wordEndsWith(rString.substr(nPos + 1), "m")) + eFrom = o3tl::Length::cm; break; case u'i': - case u'I': - aCmpsL[0] = "in"; - aCmpsU[0] = "IN"; - aScales[0] = 72.*20.; // twip + if (wordEndsWith(rString.substr(nPos + 1), "n")) + eFrom = o3tl::Length::in; break; case u'm': - case u'M': - aCmpsL[0] = "mm"; - aCmpsU[0] = "MM"; - aScales[0] = (72.*20.)/25.4; // twip + if (wordEndsWith(rString.substr(nPos + 1), "m")) + eFrom = o3tl::Length::mm; break; case u'p': - case u'P': - aCmpsL[0] = "pt"; - aCmpsU[0] = "PT"; - aScales[0] = 20.; // twip - - aCmpsL[1] = "pc"; - aCmpsU[1] = "PC"; - aScales[1] = 12.*20.; // twip + if (wordEndsWith(rString.substr(nPos + 1), "t")) + eFrom = o3tl::Length::pt; + else if (wordEndsWith(rString.substr(nPos + 1), "c")) + eFrom = o3tl::Length::pc; break; } } else if( MeasureUnit::MM_100TH == nTargetUnit || MeasureUnit::MM_10TH == nTargetUnit ) { - double nScaleFactor = (MeasureUnit::MM_100TH == nTargetUnit) ? 100.0 : 10.0; - switch( rString[nPos] ) + switch (rtl::toAsciiLowerCase<sal_uInt32>(rString[nPos])) { case u'c': - case u'C': - aCmpsL[0] = "cm"; - aCmpsU[0] = "CM"; - aScales[0] = 10.0 * nScaleFactor; // mm/100 + if (wordEndsWith(rString.substr(nPos + 1), "m")) + eFrom = o3tl::Length::cm; break; case u'i': - case u'I': - aCmpsL[0] = "in"; - aCmpsU[0] = "IN"; - aScales[0] = 1000.*2.54; // mm/100 + if (wordEndsWith(rString.substr(nPos + 1), "n")) + eFrom = o3tl::Length::in; break; case u'm': - case u'M': - aCmpsL[0] = "mm"; - aCmpsU[0] = "MM"; - aScales[0] = 1.0 * nScaleFactor; // mm/100 + if (wordEndsWith(rString.substr(nPos + 1), "m")) + eFrom = o3tl::Length::mm; break; case u'p': - case u'P': - aCmpsL[0] = "pt"; - aCmpsU[0] = "PT"; - aScales[0] = (10.0 * nScaleFactor*2.54)/72.; // mm/100 - - aCmpsL[1] = "pc"; - aCmpsU[1] = "PC"; - aScales[1] = (10.0 * nScaleFactor*2.54)/12.; // mm/100 - - aCmpsL[2] = "px"; - aCmpsU[2] = "PX"; - aScales[2] = 0.28 * nScaleFactor; // mm/100 + if (wordEndsWith(rString.substr(nPos + 1), "t")) + eFrom = o3tl::Length::pt; + else if (wordEndsWith(rString.substr(nPos + 1), "c")) + eFrom = o3tl::Length::pc; + else if (wordEndsWith(rString.substr(nPos + 1), "x")) + eFrom = o3tl::Length::px; break; } } else if( MeasureUnit::POINT == nTargetUnit ) { - if( rString[nPos] == 'p' || rString[nPos] == 'P' ) - { - aCmpsL[0] = "pt"; - aCmpsU[0] = "PT"; - aScales[0] = 1; - } - } - - if( aCmpsL[0] == nullptr ) - return false; - - double nScale = 0.; - for( sal_uInt16 i= 0; i < 3; i++ ) - { - sal_Int32 nTmp = nPos; // come back to the initial position before each iteration - const char *pL = aCmpsL[i]; - if( pL ) - { - const char *pU = aCmpsU[i]; - while( nTmp < nLen && *pL ) - { - sal_Unicode c = rString[nTmp]; - if( c != *pL && c != *pU ) - break; - pL++; - pU++; - nTmp++; - } - if( !*pL && (nTmp == nLen || ' ' == rString[nTmp]) ) - { - nScale = aScales[i]; - break; - } - } + if (wordEndsWith(rString.substr(nPos), "pt")) + eFrom = o3tl::Length::pt; } - if( 0. == nScale ) + if (eFrom == o3tl::Length::invalid) return false; // TODO: check overflow - if( nScale != 1. ) - nVal *= nScale; + nVal = o3tl::convert(nVal, eFrom, Measure2O3tlUnit(nTargetUnit)); } } @@ -320,14 +321,13 @@ void Converter::convertMeasure( OUStringBuffer& rBuffer, rBuffer.append( '-' ); } - // The new length is (nVal * nMul)/(nDiv*nFac*10) - tools::Long nMul = 1000; - tools::Long nDiv = 1; - tools::Long nFac = 100; - const char* psUnit = nullptr; + o3tl::Length eFrom = o3tl::Length::in, eTo = o3tl::Length::in; + int nFac = 100; // used to get specific number of decimals (2 by default) + std::string_view psUnit; switch( nSourceUnit ) { case MeasureUnit::TWIP: + eFrom = o3tl::Length::twip; switch( nTargetUnit ) { case MeasureUnit::MM_100TH: @@ -335,25 +335,19 @@ void Converter::convertMeasure( OUStringBuffer& rBuffer, OSL_ENSURE( MeasureUnit::INCH == nTargetUnit,"output unit not supported for twip values" ); [[fallthrough]]; case MeasureUnit::MM: - // 0.01mm = 0.57twip (exactly) - nMul = 25400; // 25.4 * 1000 - nDiv = 1440; // 72 * 20; + eTo = o3tl::Length::mm; nFac = 100; psUnit = gpsMM; break; case MeasureUnit::CM: - // 0.001cm = 0.57twip (exactly) - nMul = 25400; // 2.54 * 10000 - nDiv = 1440; // 72 * 20; + eTo = o3tl::Length::cm; nFac = 1000; psUnit = gpsCM; break; case MeasureUnit::POINT: - // 0.01pt = 0.2twip (exactly) - nMul = 1000; - nDiv = 20; + eTo = o3tl::Length::pt; nFac = 100; psUnit = gpsPT; break; @@ -362,9 +356,6 @@ void Converter::convertMeasure( OUStringBuffer& rBuffer, default: OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for twip values" ); - // 0.0001in = 0.144twip (exactly) - nMul = 100000; - nDiv = 1440; // 72 * 20; nFac = 10000; psUnit = gpsINCH; break; @@ -375,8 +366,7 @@ void Converter::convertMeasure( OUStringBuffer& rBuffer, // 1pt = 1pt (exactly) OSL_ENSURE( MeasureUnit::POINT == nTargetUnit, "output unit not supported for pt values" ); - nMul = 10; - nDiv = 1; + eFrom = eTo = o3tl::Length::pt; nFac = 1; psUnit = gpsPT; break; @@ -384,6 +374,7 @@ void Converter::convertMeasure( OUStringBuffer& rBuffer, case MeasureUnit::MM_100TH: { int nFac2 = (MeasureUnit::MM_100TH == nSourceUnit) ? 100 : 10; + eFrom = Measure2O3tlUnit(nSourceUnit); switch( nTargetUnit ) { case MeasureUnit::MM_100TH: @@ -392,25 +383,19 @@ void Converter::convertMeasure( OUStringBuffer& rBuffer, "output unit not supported for 1/100mm values" ); [[fallthrough]]; case MeasureUnit::MM: - // 0.01mm = 1 mm/100 (exactly) - nMul = 10; - nDiv = 1; + eTo = o3tl::Length::mm; nFac = nFac2; psUnit = gpsMM; break; case MeasureUnit::CM: - // 0.001mm = 1 mm/100 (exactly) - nMul = 10; - nDiv = 1; // 72 * 20; + eTo = o3tl::Length::cm; nFac = 10*nFac2; psUnit = gpsCM; break; case MeasureUnit::POINT: - // 0.01pt = 0.35 mm/100 (exactly) - nMul = 72000; - nDiv = 2540; + eTo = o3tl::Length::pt; nFac = nFac2; psUnit = gpsPT; break; @@ -419,9 +404,6 @@ void Converter::convertMeasure( OUStringBuffer& rBuffer, default: OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for 1/100mm values" ); - // 0.0001in = 0.254 mm/100 (exactly) - nMul = 100000; - nDiv = 2540; nFac = 100*nFac2; psUnit = gpsINCH; break; @@ -434,11 +416,7 @@ void Converter::convertMeasure( OUStringBuffer& rBuffer, break; } - OSL_ENSURE(nValue <= SAL_MAX_INT64 / nMul, "convertMeasure: overflow"); - nValue *= nMul; - nValue /= nDiv; - nValue += 5; - nValue /= 10; + nValue = o3tl::convert(nValue * nFac, eFrom, eTo); rBuffer.append( static_cast<sal_Int64>(nValue / nFac) ); if (nFac > 1 && (nValue % nFac) != 0) @@ -451,8 +429,8 @@ void Converter::convertMeasure( OUStringBuffer& rBuffer, } } - if( psUnit ) - rBuffer.appendAscii( psUnit ); + if (psUnit.length() > 0) + rBuffer.appendAscii(psUnit.data(), psUnit.length()); } /** convert string to boolean */ @@ -2240,349 +2218,12 @@ double Converter::GetConversionFactor(OUStringBuffer& rUnit, sal_Int16 nSourceUn if(nSourceUnit != nTargetUnit) { - const char* psUnit = nullptr; - - switch(nSourceUnit) - { - case MeasureUnit::TWIP: - { - switch(nTargetUnit) - { - case MeasureUnit::MM_100TH: - { - // 0.01mm = 0.57twip (exactly) - fRetval = ((25400.0 / 1440.0) / 10.0); - break; - } - case MeasureUnit::MM_10TH: - { - // 0.01mm = 0.57twip (exactly) - fRetval = ((25400.0 / 1440.0) / 100.0); - break; - } - case MeasureUnit::MM: - { - // 0.01mm = 0.57twip (exactly) - fRetval = ((25400.0 / 1440.0) / 1000.0); - psUnit = gpsMM; - break; - } - case MeasureUnit::CM: - { - // 0.001cm = 0.57twip (exactly) - fRetval = ((25400.0 / 1440.0) / 10000.0); - psUnit = gpsCM; - break; - } - case MeasureUnit::POINT: - { - // 0.01pt = 0.2twip (exactly) - fRetval = ((1000.0 / 20.0) / 1000.0); - psUnit = gpsPT; - break; - } - case MeasureUnit::INCH: - default: - { - OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for twip values"); - // 0.0001in = 0.144twip (exactly) - fRetval = ((100000.0 / 1440.0) / 100000.0); - psUnit = gpsINCH; - break; - } - } - break; - } - case MeasureUnit::POINT: - { - switch(nTargetUnit) - { - case MeasureUnit::MM_100TH: - { - // 1mm = 72 / 25.4 pt (exactly) - fRetval = ( 2540.0 / 72.0 ); - break; - } - case MeasureUnit::MM_10TH: - { - // 1mm = 72 / 25.4 pt (exactly) - fRetval = ( 254.0 / 72.0 ); - break; - } - case MeasureUnit::MM: - { - // 1mm = 72 / 25.4 pt (exactly) - fRetval = ( 25.4 / 72.0 ); - psUnit = gpsMM; - break; - - } - case MeasureUnit::CM: - { - // 1cm = 72 / 2.54 pt (exactly) - fRetval = ( 2.54 / 72.0 ); - psUnit = gpsCM; - break; - } - case MeasureUnit::TWIP: - { - // 1twip = 72 / 1440 pt (exactly) - fRetval = 20.0; // 1440.0 / 72.0 - psUnit = gpsPC; - break; - } - case MeasureUnit::INCH: - default: - { - OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for pt values"); - // 1in = 72 pt (exactly) - fRetval = ( 1.0 / 72.0 ); - psUnit = gpsINCH; - break; - } - } - break; - } - case MeasureUnit::MM_10TH: - { - switch(nTargetUnit) - { - case MeasureUnit::MM_100TH: - { - fRetval = 10.0; - break; - } - case MeasureUnit::MM: - { - // 0.01mm = 1 mm/100 (exactly) - fRetval = ((10.0 / 1.0) / 100.0); - psUnit = gpsMM; - break; - } - case MeasureUnit::CM: - { - fRetval = ((10.0 / 1.0) / 1000.0); - psUnit = gpsCM; - break; - } - case MeasureUnit::POINT: - { - // 0.01pt = 0.35 mm/100 (exactly) - fRetval = ((72000.0 / 2540.0) / 100.0); - psUnit = gpsPT; - break; - } - case MeasureUnit::TWIP: - { - fRetval = ((20.0 * 72000.0 / 2540.0) / 100.0); - psUnit = gpsPC; - break; - } - case MeasureUnit::INCH: - default: - { - OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for 1/10mm values"); - // 0.0001in = 0.254 mm/100 (exactly) - fRetval = ((100000.0 / 2540.0) / 10000.0); - psUnit = gpsINCH; - break; - } - } - break; - } - case MeasureUnit::MM_100TH: - { - switch(nTargetUnit) - { - case MeasureUnit::MM_10TH: - { - fRetval = ((10.0 / 1.0) / 100.0); - break; - } - case MeasureUnit::MM: - { - // 0.01mm = 1 mm/100 (exactly) - fRetval = ((10.0 / 1.0) / 1000.0); - psUnit = gpsMM; - break; - } - case MeasureUnit::CM: - { - fRetval = ((10.0 / 1.0) / 10000.0); - psUnit = gpsCM; - break; - } - case MeasureUnit::POINT: - { - // 0.01pt = 0.35 mm/100 (exactly) - fRetval = ((72000.0 / 2540.0) / 1000.0); - psUnit = gpsPT; - break; - } - case MeasureUnit::TWIP: - { - fRetval = ((20.0 * 72000.0 / 2540.0) / 1000.0); - psUnit = gpsPC; - break; - } - case MeasureUnit::INCH: - default: - { - OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for 1/100mm values"); - // 0.0001in = 0.254 mm/100 (exactly) - fRetval = ((100000.0 / 2540.0) / 100000.0); - psUnit = gpsINCH; - break; - } - } - break; - } - case MeasureUnit::MM: - { - switch(nTargetUnit) - { - case MeasureUnit::MM_100TH: - { - fRetval = 100.0; - break; - } - case MeasureUnit::MM_10TH: - { - fRetval = 10.0; - break; - } - case MeasureUnit::CM: - { - fRetval = 0.1; - psUnit = gpsCM; - break; - } - case MeasureUnit::POINT: - { - fRetval = 72.0 / (2.54 * 10); - psUnit = gpsPT; - break; - } - case MeasureUnit::TWIP: - { - fRetval = (20.0 * 72.0) / (2.54 * 10); - psUnit = gpsPC; - break; - } - case MeasureUnit::INCH: - default: - { - OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for cm values"); - fRetval = 1 / (2.54 * 10); - psUnit = gpsINCH; - break; - } - } - break; - } - case MeasureUnit::CM: - { - switch(nTargetUnit) - { - case MeasureUnit::MM_100TH: - { - fRetval = 1000.0; - break; - } - case MeasureUnit::MM_10TH: - { - fRetval = 100.0; - break; - } - case MeasureUnit::MM: - { - fRetval = 10.0; - psUnit = gpsMM; - break; - } - case MeasureUnit::CM: - { - break; - } - case MeasureUnit::POINT: - { - fRetval = 72.0 / 2.54; - psUnit = gpsPT; - break; - } - case MeasureUnit::TWIP: - { - fRetval = (20.0 * 72.0) / 2.54; - psUnit = gpsPC; - break; - } - case MeasureUnit::INCH: - default: - { - OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for cm values"); - fRetval = 1 / 2.54; - psUnit = gpsINCH; - break; - } - } - break; - } - case MeasureUnit::INCH: - { - switch (nTargetUnit) - { - case MeasureUnit::MM_100TH: - { - fRetval = 2540; - break; - } - case MeasureUnit::MM_10TH: - { - fRetval = 254; - break; - } - case MeasureUnit::MM: - { - fRetval = 25.4; - psUnit = gpsMM; - break; - } - case MeasureUnit::CM: - { - fRetval = 2.54; - psUnit = gpsCM; - break; - } - case MeasureUnit::POINT: - { - fRetval = 72.0; - psUnit = gpsPT; - break; - } - case MeasureUnit::TWIP: - { - fRetval = 72.0 * 20.0; - psUnit = gpsPC; - break; - } - default: - { - OSL_FAIL("output unit not supported for in values"); - fRetval = 1; - psUnit = gpsINCH; - break; - } - } - break; - } - default: - OSL_ENSURE(false, "sax::Converter::GetConversionFactor(): " - "source unit not supported"); - break; - } + const o3tl::Length eFrom = Measure2O3tlUnit(nSourceUnit); + const o3tl::Length eTo = Measure2O3tlUnit(nTargetUnit); + fRetval = o3tl::convert(1.0, eFrom, eTo); - if( psUnit ) - rUnit.appendAscii( psUnit ); + if (const auto sUnit = Measure2UnitString(nTargetUnit); sUnit.size() > 0) + rUnit.appendAscii(sUnit.data(), sUnit.size()); } return fRetval; diff --git a/sc/source/filter/oox/unitconverter.cxx b/sc/source/filter/oox/unitconverter.cxx index 088121286d9e..8ca79ce78d90 100644 --- a/sc/source/filter/oox/unitconverter.cxx +++ b/sc/source/filter/oox/unitconverter.cxx @@ -26,6 +26,7 @@ #include <com/sun/star/sheet/XSpreadsheetDocument.hpp> #include <com/sun/star/util/Date.hpp> #include <com/sun/star/util/DateTime.hpp> +#include <o3tl/unit_conversion.hxx> #include <osl/diagnose.h> #include <oox/core/filterbase.hxx> #include <oox/helper/propertyset.hxx> @@ -43,11 +44,6 @@ using namespace ::com::sun::star::uno; namespace { -const double MM100_PER_INCH = 2540.0; -const double MM100_PER_POINT = MM100_PER_INCH / 72.0; -const double MM100_PER_TWIP = MM100_PER_POINT / 20.0; -const double MM100_PER_EMU = 1.0 / 360.0; - /** Returns true, if the passed year is a leap year. */ bool lclIsLeapYear( sal_Int32 nYear ) { @@ -95,10 +91,10 @@ UnitConverter::UnitConverter( const WorkbookHelper& rHelper ) : { // initialize constant and default coefficients const DeviceInfo& rDeviceInfo = getBaseFilter().getGraphicHelper().getDeviceInfo(); - maCoeffs[ Unit::Inch ] = MM100_PER_INCH; - maCoeffs[ Unit::Point ] = MM100_PER_POINT; - maCoeffs[ Unit::Twip ] = MM100_PER_TWIP; - maCoeffs[ Unit::Emu ] = MM100_PER_EMU; + maCoeffs[Unit::Inch] = o3tl::convert(1.0, o3tl::Length::in, o3tl::Length::mm100); + maCoeffs[Unit::Point] = o3tl::convert(1.0, o3tl::Length::pt, o3tl::Length::mm100); + maCoeffs[Unit::Twip] = o3tl::convert(1.0, o3tl::Length::twip, o3tl::Length::mm100); + maCoeffs[Unit::Emu] = o3tl::convert(1.0, o3tl::Length::emu, o3tl::Length::mm100); maCoeffs[ Unit::ScreenX ] = (rDeviceInfo.PixelPerMeterX > 0) ? (100000.0 / rDeviceInfo.PixelPerMeterX) : 50.0; maCoeffs[ Unit::ScreenY ] = (rDeviceInfo.PixelPerMeterY > 0) ? (100000.0 / rDeviceInfo.PixelPerMeterY) : 50.0; maCoeffs[ Unit::Digit ] = 200.0; // default: 1 digit = 2 mm @@ -133,13 +129,16 @@ void UnitConverter::finalizeImport() return; // get maximum width of all digits - sal_Int32 nDigitWidth = 0; + sal_Int64 nDigitWidth = 0; for( sal_Unicode cChar = '0'; cChar <= '9'; ++cChar ) - nDigitWidth = ::std::max( nDigitWidth, scaleToMm100( xFont->getCharWidth( cChar ), Unit::Twip ) ); + nDigitWidth + = ::std::max(nDigitWidth, o3tl::convert(xFont->getCharWidth(cChar), o3tl::Length::twip, + o3tl::Length::mm100)); if( nDigitWidth > 0 ) maCoeffs[ Unit::Digit ] = nDigitWidth; // get width of space character - sal_Int32 nSpaceWidth = scaleToMm100( xFont->getCharWidth( ' ' ), Unit::Twip ); + sal_Int32 nSpaceWidth + = o3tl::convert(xFont->getCharWidth(' '), o3tl::Length::twip, o3tl::Length::mm100); if( nSpaceWidth > 0 ) maCoeffs[ Unit::Space ] = nSpaceWidth; } diff --git a/sc/source/ui/vba/vbarange.cxx b/sc/source/ui/vba/vbarange.cxx index 1dd212e61bb2..e78088facd52 100644 --- a/sc/source/ui/vba/vbarange.cxx +++ b/sc/source/ui/vba/vbarange.cxx @@ -22,6 +22,7 @@ #include <comphelper/types.hxx> #include <cppuhelper/exc_hlp.hxx> #include <o3tl/any.hxx> +#include <o3tl/unit_conversion.hxx> #include <tools/diagnose_ex.h> #include <com/sun/star/script/ArrayWrapper.hpp> @@ -163,11 +164,6 @@ using ::std::vector; // difference between VBA and file format width, in character units const double fExtraWidth = 182.0 / 256.0; -// * 1 point = 1/72 inch = 20 twips -// * 1 inch = 72 points = 1440 twips -// * 1 cm = 567 twips -static double lcl_hmmToPoints( double nVal ) { return nVal / 1000 * 567 / 20; } - const sal_Int16 supportedIndexTable[] = { excel::XlBordersIndex::xlEdgeLeft, excel::XlBordersIndex::xlEdgeTop, excel::XlBordersIndex::xlEdgeBottom, excel::XlBordersIndex::xlEdgeRight, excel::XlBordersIndex::xlDiagonalDown, excel::XlBordersIndex::xlDiagonalUp, excel::XlBordersIndex::xlInsideVertical, excel::XlBordersIndex::xlInsideHorizontal }; static sal_uInt16 lcl_pointsToTwips( double nVal ) @@ -3747,7 +3743,7 @@ static double getDefaultCharWidth( ScDocShell* pDocShell ) pAttr->GetFont( aDefFont, SC_AUTOCOL_BLACK, pRefDevice ); pRefDevice->SetFont( aDefFont ); tools::Long nCharWidth = pRefDevice->GetTextWidth( OUString( '0' ) ); // 1/100th mm - return lcl_hmmToPoints( nCharWidth ); + return o3tl::convert<double>(nCharWidth, o3tl::Length::mm100, o3tl::Length::pt); } uno::Any SAL_CALL @@ -4084,7 +4080,7 @@ ScVbaRange::getLeft() if ( m_Areas->getCount() > 1 ) return getArea( 0 )->getLeft(); awt::Point aPoint = getPosition(); - return uno::makeAny( lcl_hmmToPoints( aPoint.X ) ); + return uno::makeAny(o3tl::convert<double>(aPoint.X, o3tl::Length::mm100, o3tl::Length::pt)); } uno::Any SAL_CALL @@ -4094,7 +4090,7 @@ ScVbaRange::getTop() if ( m_Areas->getCount() > 1 ) return getArea( 0 )->getTop(); awt::Point aPoint= getPosition(); - return uno::makeAny( lcl_hmmToPoints( aPoint.Y ) ); + return uno::makeAny(o3tl::convert<double>(aPoint.Y, o3tl::Length::mm100, o3tl::Length::pt)); } static uno::Reference< sheet::XCellRangeReferrer > getNamedRange( const uno::Reference< uno::XInterface >& xIf, const uno::Reference< table::XCellRange >& thisRange ) diff --git a/sd/qa/unit/export-tests-ooxml1.cxx b/sd/qa/unit/export-tests-ooxml1.cxx index a740e2b2d69c..7c3739fa1a7d 100644 --- a/sd/qa/unit/export-tests-ooxml1.cxx +++ b/sd/qa/unit/export-tests-ooxml1.cxx @@ -746,7 +746,7 @@ void SdOOXMLExportTest1::testBulletMarginAndIndentation() CPPUNIT_ASSERT(pNumFmt); CPPUNIT_ASSERT_EQUAL_MESSAGE( "Bullet's left margin is wrong!", sal_Int32(1000),pNumFmt->GetNumRule()->GetLevel(0).GetAbsLSpace() ); // left margin is 0.79 cm - CPPUNIT_ASSERT_EQUAL_MESSAGE( "Bullet's indentation is wrong!", sal_Int32(-998),pNumFmt->GetNumRule()->GetLevel(0). GetFirstLineOffset()); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "Bullet's indentation is wrong!", sal_Int32(-1000),pNumFmt->GetNumRule()->GetLevel(0). GetFirstLineOffset()); xDocShRef->DoClose(); } @@ -768,7 +768,7 @@ void SdOOXMLExportTest1::testParaMarginAndindentation() sal_Int32 nParaFirstLineIndent = 0; xPropSet->getPropertyValue( "ParaFirstLineIndent" ) >>= nParaFirstLineIndent; - CPPUNIT_ASSERT_EQUAL(sal_Int32(-1268), nParaFirstLineIndent); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1270), nParaFirstLineIndent); xDocShRef->DoClose(); } diff --git a/sd/qa/unit/export-tests-ooxml2.cxx b/sd/qa/unit/export-tests-ooxml2.cxx index b38678f62a61..faaf35f71347 100644 --- a/sd/qa/unit/export-tests-ooxml2.cxx +++ b/sd/qa/unit/export-tests-ooxml2.cxx @@ -1772,9 +1772,9 @@ void SdOOXMLExportTest2::testTdf90626() xmlDocUniquePtr pXmlDocContent = parseExport(tempFile, "ppt/slides/slide1.xml"); assertXPath(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:sp[2]/p:txBody/a:p[1]/a:pPr/a:buSzPct", "val", "100000"); - assertXPath(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:sp[2]/p:txBody/a:p[2]/a:pPr/a:buSzPct", "val", "150568"); + assertXPath(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:sp[2]/p:txBody/a:p[2]/a:pPr/a:buSzPct", "val", "150142"); assertXPath(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:sp[2]/p:txBody/a:p[3]/a:pPr/a:buSzPct", "val", "100000"); - assertXPath(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:sp[2]/p:txBody/a:p[4]/a:pPr/a:buSzPct", "val", "150568"); + assertXPath(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:sp[2]/p:txBody/a:p[4]/a:pPr/a:buSzPct", "val", "150142"); } void SdOOXMLExportTest2::testTdf107608() diff --git a/sd/qa/unit/import-tests.cxx b/sd/qa/unit/import-tests.cxx index dc270a38da7d..12560e90d586 100644 --- a/sd/qa/unit/import-tests.cxx +++ b/sd/qa/unit/import-tests.cxx @@ -2696,7 +2696,7 @@ void SdImportTest::testTdf90626() { const SvxNumBulletItem *pNumFmt = aEdit.GetParaAttribs(i).GetItem(EE_PARA_NUMBULLET); CPPUNIT_ASSERT(pNumFmt); - CPPUNIT_ASSERT_DOUBLES_EQUAL(tools::Long(371), pNumFmt->GetNumRule()->GetLevel(0).GetGraphicSize().getHeight(), tools::Long(1)); + CPPUNIT_ASSERT_DOUBLES_EQUAL(tools::Long(372), pNumFmt->GetNumRule()->GetLevel(0).GetGraphicSize().getHeight(), tools::Long(1)); } xDocShRef->DoClose(); @@ -2780,7 +2780,7 @@ void SdImportTest::testTdf114913() CPPUNIT_ASSERT_MESSAGE("No text object", pTxtObj != nullptr); const SvxNumBulletItem *pItem = pTxtObj->GetOutlinerParaObject()->GetTextObject().GetParaAttribs(0).GetItem(EE_PARA_NUMBULLET); CPPUNIT_ASSERT(pItem); - CPPUNIT_ASSERT_EQUAL(tools::Long(691), pItem->GetNumRule()->GetLevel(0).GetGraphicSize().getHeight()); + CPPUNIT_ASSERT_EQUAL(tools::Long(692), pItem->GetNumRule()->GetLevel(0).GetGraphicSize().getHeight()); xDocShRef->DoClose(); } diff --git a/sd/source/ui/unoidl/unomodel.cxx b/sd/source/ui/unoidl/unomodel.cxx index 230eeefeb420..35b1c376940c 100644 --- a/sd/source/ui/unoidl/unomodel.cxx +++ b/sd/source/ui/unoidl/unomodel.cxx @@ -2216,10 +2216,9 @@ void SdXImpressDocument::paintTile( VirtualDevice& rDevice, // that VirtualDevices use a DPI of 96. // We specifically calculate these scales first as we're still // in TWIPs, and might as well minimize the number of conversions. - Fraction scaleX = Fraction( nOutputWidth, 96 ) * Fraction(1440) / - Fraction( nTileWidth); - Fraction scaleY = Fraction( nOutputHeight, 96 ) * Fraction(1440) / - Fraction( nTileHeight); + const Fraction scale = conversionFract(o3tl::Length::px, o3tl::Length::twip); + Fraction scaleX = Fraction(nOutputWidth, nTileWidth) * scale; + Fraction scaleY = Fraction(nOutputHeight, nTileHeight) * scale; // svx seems to be the only component that works natively in // 100th mm rather than TWIP. It makes most sense just to diff --git a/sfx2/source/view/lokcharthelper.cxx b/sfx2/source/view/lokcharthelper.cxx index a27fc70271bb..f80637133744 100644 --- a/sfx2/source/view/lokcharthelper.cxx +++ b/sfx2/source/view/lokcharthelper.cxx @@ -248,8 +248,9 @@ void LokChartHelper::PaintAllChartsOnTile(VirtualDevice& rDevice, // Scaling. Must convert from pixels to twips. We know // that VirtualDevices use a DPI of 96. - Fraction scaleX = Fraction(nOutputWidth, 96) * Fraction(1440) / Fraction(nTileWidth); - Fraction scaleY = Fraction(nOutputHeight, 96) * Fraction(1440) / Fraction(nTileHeight); + const Fraction scale = conversionFract(o3tl::Length::px, o3tl::Length::twip); + Fraction scaleX = Fraction(nOutputWidth, nTileWidth) * scale; + Fraction scaleY = Fraction(nOutputHeight, nTileHeight) * scale; aMapMode.SetScaleX(scaleX); aMapMode.SetScaleY(scaleY); rDevice.SetMapMode(aMapMode); diff --git a/svtools/source/misc/unitconv.cxx b/svtools/source/misc/unitconv.cxx index 361570163063..bdff583182b5 100644 --- a/svtools/source/misc/unitconv.cxx +++ b/svtools/source/misc/unitconv.cxx @@ -17,8 +17,10 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include <o3tl/temporary.hxx> #include <svtools/unitconv.hxx> #include <tools/debug.hxx> +#include <tools/UnitConversion.hxx> #include <vcl/outdev.hxx> #include <vcl/weld.hxx> @@ -125,80 +127,19 @@ tools::Long CalcToUnit( float nIn, MapUnit eUnit ) eUnit == MapUnit::MapMM || eUnit == MapUnit::MapCM, "this unit is not implemented" ); - float nTmp = nIn; + if (const auto eTo = MapToO3tlLength(eUnit); eTo != o3tl::Length::invalid) + return o3tl::convert(nIn, o3tl::Length::pt, eTo); - if ( MapUnit::MapTwip != eUnit ) - nTmp = nIn * 10 / 567; - - switch ( eUnit ) - { - case MapUnit::Map100thMM: nTmp *= 100; break; - case MapUnit::Map10thMM: nTmp *= 10; break; - case MapUnit::MapMM: break; - case MapUnit::MapCM: nTmp /= 10; break; - default: ;//prevent warning - } - - nTmp *= 20; - tools::Long nRet = static_cast<tools::Long>(nTmp); - return nRet; -//! return (long)(nTmp * 20); + return 0; } tools::Long ItemToControl( tools::Long nIn, MapUnit eItem, FieldUnit eCtrl ) { - tools::Long nOut = 0; - - switch ( eItem ) - { - case MapUnit::Map100thMM: - case MapUnit::Map10thMM: - case MapUnit::MapMM: - { - if ( eItem == MapUnit::Map10thMM ) - nIn /= 10; - else if ( eItem == MapUnit::Map100thMM ) - nIn /= 100; - nOut = TransformMetric( nIn, FieldUnit::MM, eCtrl ); - } - break; - - case MapUnit::MapCM: - { - nOut = TransformMetric( nIn, FieldUnit::CM, eCtrl ); - } - break; - - case MapUnit::Map1000thInch: - case MapUnit::Map100thInch: - case MapUnit::Map10thInch: - case MapUnit::MapInch: - { - if ( eItem == MapUnit::Map10thInch ) - nIn /= 10; - else if ( eItem == MapUnit::Map100thInch ) - nIn /= 100; - else if ( eItem == MapUnit::Map1000thInch ) - nIn /= 1000; - nOut = TransformMetric( nIn, FieldUnit::INCH, eCtrl ); - } - break; - - case MapUnit::MapPoint: - { - nOut = TransformMetric( nIn, FieldUnit::POINT, eCtrl ); - } - break; - - case MapUnit::MapTwip: - { - nOut = TransformMetric( nIn, FieldUnit::TWIP, eCtrl ); - } - break; - default: ;//prevent warning - } - return nOut; + const auto eFrom = MapToO3tlLength(eItem), eTo = FieldToO3tlLength(eCtrl); + if (eFrom != o3tl::Length::invalid && eTo != o3tl::Length::invalid) + return o3tl::convert(nIn, eFrom, eTo); + return 0; } @@ -245,374 +186,18 @@ tools::Long CalcToPoint( tools::Long nIn, MapUnit eUnit, sal_uInt16 nFactor ) eUnit == MapUnit::MapMM || eUnit == MapUnit::MapCM, "this unit is not implemented" ); - tools::Long nRet = 0; - - if ( MapUnit::MapTwip == eUnit ) - nRet = nIn; - else - nRet = nIn * 567; - - switch ( eUnit ) - { - case MapUnit::Map100thMM: nRet /= 100; break; - case MapUnit::Map10thMM: nRet /= 10; break; - case MapUnit::MapMM: break; - case MapUnit::MapCM: nRet *= 10; break; - default: ;//prevent warning - } - - // round up if necessary - if ( MapUnit::MapTwip != eUnit ) - { - tools::Long nTmp = nRet % 10; - - if ( nTmp >= 4 ) - nRet += 10 - nTmp; - nRet /= 10; - } - return nRet * nFactor / 20; -} - - -static tools::Long CMToTwips( tools::Long nIn ) -{ - tools::Long nRet = 0; - - if ( nIn <= ( LONG_MAX / 567 ) && nIn >= ( LONG_MIN / 567 ) ) - nRet = nIn * 567; - return nRet; -} - - -static tools::Long MMToTwips( tools::Long nIn ) -{ - tools::Long nRet = 0; - - if ( nIn <= ( LONG_MAX / 567 ) && nIn >= ( LONG_MIN / 567 ) ) - nRet = nIn * 567 / 10; - return nRet; -} - - -static tools::Long InchToTwips( tools::Long nIn ) -{ - tools::Long nRet = 0; - - if ( nIn <= ( LONG_MAX / 1440 ) && nIn >= ( LONG_MIN / 1440 ) ) - nRet = nIn * 1440; - return nRet; -} - - -tools::Long PointToTwips( tools::Long nIn ) -{ - tools::Long nRet = 0; - - if ( nIn <= ( LONG_MAX / 20 ) && nIn >= ( LONG_MIN / 20 ) ) - nRet = nIn * 20; - return nRet; -} - - -static tools::Long PicaToTwips( tools::Long nIn ) -{ - tools::Long nRet = 0; - - if ( nIn <= ( LONG_MAX / 240 ) && nIn >= ( LONG_MIN / 240 ) ) - nRet = nIn * 240; - return nRet; -} - - -static tools::Long TwipsToCM( tools::Long nIn ) -{ - tools::Long nRet = nIn / 567; - return nRet; -} - - -static tools::Long InchToCM( tools::Long nIn ) -{ - tools::Long nRet = 0; - - if ( nIn <= ( LONG_MAX / 254 ) && nIn >= ( LONG_MIN / 254 ) ) - nRet = nIn * 254 / 100; - return nRet; -} - - -static tools::Long MMToCM( tools::Long nIn ) -{ - tools::Long nRet = nIn / 10; - return nRet; -} - - -static tools::Long PointToCM( tools::Long nIn ) -{ - tools::Long nRet = 0; - - if ( nIn <= ( LONG_MAX / 20 ) && nIn >= ( LONG_MIN / 20 ) ) - nRet = nIn * 20 / 567; - return nRet; -} - - -static tools::Long PicaToCM( tools::Long nIn) -{ - tools::Long nRet = 0; - - if ( nIn <= ( LONG_MAX / 12 / 20 ) && nIn >= ( LONG_MIN / 12 / 20 ) ) - nRet = nIn * 12 * 20 / 567; - return nRet; -} - - -static tools::Long TwipsToMM( tools::Long nIn ) -{ - tools::Long nRet = 0; - - if ( nIn <= ( LONG_MAX / 10 ) && nIn >= ( LONG_MIN / 10 ) ) - nRet = nIn * 10 / 566; - return nRet; -} - - -static tools::Long CMToMM( tools::Long nIn ) -{ - tools::Long nRet = 0; - - if ( nIn <= ( LONG_MAX / 10 ) && nIn >= ( LONG_MIN / 10 ) ) - nRet = nIn * 10; - return nRet; -} - - -static tools::Long InchToMM( tools::Long nIn ) -{ - tools::Long nRet = 0; - - if ( nIn <= ( LONG_MAX / 254 ) && nIn >= ( LONG_MIN / 254 ) ) - nRet = nIn * 254 / 10; - return nRet; -} - - -static tools::Long PointToMM( tools::Long nIn ) -{ - tools::Long nRet = 0; - - if ( nIn <= ( LONG_MAX / 200 ) && nIn >= ( LONG_MIN / 200 ) ) - nRet = nIn * 200 / 567; - return nRet; -} - - -static tools::Long PicaToMM( tools::Long nIn ) -{ - tools::Long nRet = 0; - - if ( nIn <= ( LONG_MAX / 12 / 200 ) && nIn >= ( LONG_MIN / 12 / 200 ) ) - nRet = nIn * 12 * 200 / 567; - return nRet; -} - - -static tools::Long TwipsToInch( tools::Long nIn ) -{ - tools::Long nRet = nIn / 1440; - return nRet; -} - - -static tools::Long CMToInch( tools::Long nIn ) -{ - tools::Long nRet = 0; - - if ( nIn <= ( LONG_MAX / 100 ) && nIn >= ( LONG_MIN / 100 ) ) - nRet = nIn * 100 / 254; - return nRet; -} - - -static tools::Long MMToInch( tools::Long nIn ) -{ - tools::Long nRet = 0; - - if ( nIn <= ( LONG_MAX / 10 ) && nIn >= ( LONG_MIN / 10 ) ) - nRet = nIn * 10 / 254; - return nRet; -} - - -static tools::Long PointToInch( tools::Long nIn ) -{ - tools::Long nRet = nIn / 72; - return nRet; -} - - -static tools::Long PicaToInch( tools::Long nIn ) -{ - tools::Long nRet = nIn / 6; - return nRet; -} - - -static tools::Long TwipsToPoint( tools::Long nIn ) -{ - tools::Long nRet = nIn / 20; - return nRet; -} - - -static tools::Long InchToPoint( tools::Long nIn ) -{ - tools::Long nRet = 0; - - if ( nIn <= ( LONG_MAX / 72 ) && nIn >= ( LONG_MIN / 72 ) ) - nRet = nIn * 72; - return nRet; -} - - -static tools::Long CMToPoint( tools::Long nIn ) -{ - tools::Long nRet = 0; - - if ( nIn <= ( LONG_MAX / 567 ) && nIn >= ( LONG_MIN / 567 ) ) - nRet = nIn * 567 / 20; - return nRet; -} - - -static tools::Long MMToPoint( tools::Long nIn ) -{ - tools::Long nRet = 0; - - if ( nIn <= ( LONG_MAX / 567 ) && nIn >= ( LONG_MIN / 567 ) ) - nRet = nIn * 567 / 200; - return nRet; -} - - -static tools::Long PicaToPoint( tools::Long nIn ) -{ - tools::Long nRet = nIn / 12; - return nRet; -} - - -static tools::Long TwipsToPica( tools::Long nIn ) -{ - tools::Long nRet = nIn / 240; - return nRet; -} - - -static tools::Long InchToPica( tools::Long nIn ) -{ - tools::Long nRet = 0; - - if ( nIn <= ( LONG_MAX / 6 ) && nIn >= ( LONG_MIN / 6 ) ) - nRet = nIn * 6; - return nRet; -} - - -static tools::Long PointToPica( tools::Long nIn ) -{ - tools::Long nRet = 0; - - if ( nIn <= ( LONG_MAX / 12 ) && nIn >= ( LONG_MIN / 12 ) ) - nRet = nIn * 12; - return nRet; -} - - -static tools::Long CMToPica( tools::Long nIn ) -{ - tools::Long nRet = 0; - - if ( nIn <= ( LONG_MAX / 567 ) && nIn >= ( LONG_MIN / 567 ) ) - nRet = nIn * 567 / 20 / 12; - return nRet; + if (const auto eTo = MapToO3tlLength(eUnit); eTo != o3tl::Length::invalid) + return o3tl::convert(nIn, eTo, o3tl::Length::pt) * nFactor; + return 0; } -static tools::Long MMToPica( tools::Long nIn ) -{ - tools::Long nRet = 0; - - if ( nIn <= ( LONG_MAX / 567 ) && nIn >= ( LONG_MIN / 567 ) ) - nRet = nIn * 567 / 200 / 12; - return nRet; -} - - -static tools::Long Nothing( tools::Long nIn ) -{ - tools::Long nRet = nIn; - return nRet; -} - -FUNC_CONVERT const ConvertTable[6][6] = -{ -// CM, MM INCH POINT PICAS=32 TWIPS - { Nothing, CMToMM, CMToInch, CMToPoint, CMToPica, CMToTwips }, - { MMToCM, Nothing, MMToInch, MMToPoint, MMToPica, MMToTwips }, - { InchToCM, InchToMM, Nothing, InchToPoint, InchToPica, InchToTwips }, - { PointToCM, PointToMM, PointToInch, Nothing, PointToPica, PointToTwips }, - { PicaToCM, PicaToMM, PicaToInch, PicaToPoint, Nothing, PicaToTwips }, - { TwipsToCM, TwipsToMM, TwipsToInch, TwipsToPoint,TwipsToPica, Nothing } -}; - - tools::Long TransformMetric( tools::Long nVal, FieldUnit aOld, FieldUnit aNew ) { - if ( aOld == FieldUnit::NONE || aNew == FieldUnit::NONE || - aOld == FieldUnit::CUSTOM || aNew == FieldUnit::CUSTOM ) - { + const auto eFrom = FieldToO3tlLength(aOld), eTo = FieldToO3tlLength(aNew); + if (eFrom == o3tl::Length::invalid || eTo == o3tl::Length::invalid) return nVal; - } - - sal_uInt16 nOld = 0; - sal_uInt16 nNew = 0; - - switch ( aOld ) - { - case FieldUnit::CM: - nOld = 0; break; - case FieldUnit::MM: - nOld = 1; break; - case FieldUnit::INCH: - nOld = 2; break; - case FieldUnit::POINT: - nOld = 3; break; - case FieldUnit::PICA: - nOld = 4; break; - case FieldUnit::TWIP: - nOld = 5; break; - default: ;//prevent warning - } - - switch ( aNew ) - { - case FieldUnit::CM: - nNew = 0; break; - case FieldUnit::MM: - nNew = 1; break; - case FieldUnit::INCH: - nNew = 2; break; - case FieldUnit::POINT: - nNew = 3; break; - case FieldUnit::PICA: - nNew = 4; break; - case FieldUnit::TWIP: - nNew = 5; break; - default: ;//prevent warning - } - return ConvertTable[nOld][nNew]( nVal ); + return o3tl::convert(nVal, eFrom, eTo, o3tl::temporary(bool())); // Just 0 when overflown } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/customshapes/EnhancedCustomShape3d.cxx b/svx/source/customshapes/EnhancedCustomShape3d.cxx index 651d176f6076..9c933ef9313e 100644 --- a/svx/source/customshapes/EnhancedCustomShape3d.cxx +++ b/svx/source/customshapes/EnhancedCustomShape3d.cxx @@ -18,6 +18,7 @@ */ #include "EnhancedCustomShape3d.hxx" +#include <o3tl/unit_conversion.hxx> #include <svx/deflt3d.hxx> #include <svx/svdmodel.hxx> #include <tools/poly.hxx> @@ -262,7 +263,8 @@ SdrObject* EnhancedCustomShape3d::Create3DObject( if ( rSdrObjCustomShape.getSdrModelFromSdrObject().GetScaleUnit() != MapUnit::Map100thMM ) { DBG_ASSERT( rSdrObjCustomShape.getSdrModelFromSdrObject().GetScaleUnit() == MapUnit::MapTwip, "EnhancedCustomShape3d::Current MapMode is Unsupported" ); - fMap *= 1440.0 / 2540.0; + // But we could use MapToO3tlUnit from <tools/UnitConversion> ... ? + fMap *= o3tl::convert(1.0, o3tl::Length::mm100, o3tl::Length::twip); pMap = &fMap; } diff --git a/svx/source/svdraw/svdmodel.cxx b/svx/source/svdraw/svdmodel.cxx index f6f2f8797d72..d5add2eb33b4 100644 --- a/svx/source/svdraw/svdmodel.cxx +++ b/svx/source/svdraw/svdmodel.cxx @@ -71,6 +71,7 @@ #include <sfx2/viewsh.hxx> #include <o3tl/enumrange.hxx> #include <tools/diagnose_ex.h> +#include <tools/UnitConversion.hxx> using namespace ::com::sun::star; using namespace ::com::sun::star::uno; @@ -866,94 +867,31 @@ void SdrModel::ImpSetUIUnit() m_aUIScale = Fraction(1,1); } - // set start values m_nUIUnitDecimalMark = 0; - sal_Int64 nMul(1); - sal_Int64 nDiv(1); - - // normalize on meters resp. inch - switch (m_eObjUnit) - { - case MapUnit::Map100thMM : m_nUIUnitDecimalMark+=5; break; - case MapUnit::Map10thMM : m_nUIUnitDecimalMark+=4; break; - case MapUnit::MapMM : m_nUIUnitDecimalMark+=3; break; - case MapUnit::MapCM : m_nUIUnitDecimalMark+=2; break; - case MapUnit::Map1000thInch: m_nUIUnitDecimalMark+=3; break; - case MapUnit::Map100thInch : m_nUIUnitDecimalMark+=2; break; - case MapUnit::Map10thInch : m_nUIUnitDecimalMark+=1; break; - case MapUnit::MapInch : m_nUIUnitDecimalMark+=0; break; - case MapUnit::MapPoint : nDiv=72; break; // 1Pt = 1/72" - case MapUnit::MapTwip : nDiv=144; m_nUIUnitDecimalMark++; break; // 1Twip = 1/1440" - case MapUnit::MapPixel : break; - case MapUnit::MapSysFont : break; - case MapUnit::MapAppFont : break; - case MapUnit::MapRelative : break; - default: break; - } // switch - // 1 mile = 8 furlong = 63.360" = 1.609.344,0mm - // 1 furlong = 10 chains = 7.920" = 201.168,0mm - // 1 chain = 4 poles = 792" = 20.116,8mm - // 1 pole = 5 1/2 yd = 198" = 5.029,2mm - // 1 yd = 3 ft = 36" = 914,4mm - // 1 ft = 12 " = 1" = 304,8mm + o3tl::Length eFrom = MapToO3tlLength(m_eObjUnit, o3tl::Length::invalid); + o3tl::Length eTo; + switch (m_eUIUnit) { - case FieldUnit::NONE : break; - // metric - case FieldUnit::MM_100TH: m_nUIUnitDecimalMark-=5; break; - case FieldUnit::MM : m_nUIUnitDecimalMark-=3; break; - case FieldUnit::CM : m_nUIUnitDecimalMark-=2; break; - case FieldUnit::M : m_nUIUnitDecimalMark+=0; break; - case FieldUnit::KM : m_nUIUnitDecimalMark+=3; break; - // Inch - case FieldUnit::TWIP : nMul=144; m_nUIUnitDecimalMark--; break; // 1Twip = 1/1440" - case FieldUnit::POINT : nMul=72; break; // 1Pt = 1/72" - case FieldUnit::PICA : nMul=6; break; // 1Pica = 1/6" - case FieldUnit::INCH : break; // 1" = 1" - case FieldUnit::FOOT : nDiv*=12; break; // 1Ft = 12" - case FieldUnit::MILE : nDiv*=6336; m_nUIUnitDecimalMark++; break; // 1mile = 63360" - // other - case FieldUnit::CUSTOM : break; - case FieldUnit::PERCENT: m_nUIUnitDecimalMark+=2; break; - // TODO: Add code to handle the following if needed (added to remove warning) - case FieldUnit::CHAR : break; - case FieldUnit::LINE : break; - case FieldUnit::PIXEL : break; - case FieldUnit::DEGREE : break; - case FieldUnit::SECOND : break; - case FieldUnit::MILLISECOND : break; + case FieldUnit::CHAR: + case FieldUnit::LINE: + eTo = o3tl::Length::invalid; + break; + case FieldUnit::PERCENT: + m_nUIUnitDecimalMark += 2; + [[fallthrough]]; + default: + eTo = FieldToO3tlLength(m_eUIUnit, o3tl::Length::invalid); } // switch - // check if mapping is from metric to inch and adapt - const bool bMapInch(IsInch(m_eObjUnit)); - const bool bUIMetr(IsMetric(m_eUIUnit)); - - if (bMapInch && bUIMetr) + sal_Int32 nMul = 1, nDiv = 1; + if (eFrom != o3tl::Length::invalid && eTo != o3tl::Length::invalid) { - m_nUIUnitDecimalMark += 4; - nMul *= 254; + const auto& [mul, div] = o3tl::getConversionMulDiv(eFrom, eTo); + nMul = mul; + nDiv = div; } - - // check if mapping is from inch to metric and adapt - const bool bMapMetr(IsMetric(m_eObjUnit)); - const bool bUIInch(IsInch(m_eUIUnit)); - - if (bMapMetr && bUIInch) - { - m_nUIUnitDecimalMark -= 4; - nDiv *= 254; - } - - // use temporary fraction for reduction (fallback to 32bit here), - // may need to be changed in the future, too - if(1 != nMul || 1 != nDiv) - { - const Fraction aTemp(static_cast< tools::Long >(nMul), static_cast< tools::Long >(nDiv)); - nMul = aTemp.GetNumerator(); - nDiv = aTemp.GetDenominator(); - } - // #i89872# take Unit of Measurement into account if(1 != m_aUIScale.GetDenominator() || 1 != m_aUIScale.GetNumerator()) { diff --git a/svx/source/svdraw/svdtrans.cxx b/svx/source/svdraw/svdtrans.cxx index 5b02f994cc12..6af3a49ea873 100644 --- a/svx/source/svdraw/svdtrans.cxx +++ b/svx/source/svdraw/svdtrans.cxx @@ -25,6 +25,7 @@ #include <vcl/virdev.hxx> #include <tools/bigint.hxx> +#include <tools/UnitConversion.hxx> #include <unotools/syslocale.hxx> #include <unotools/localedatawrapper.hxx> #include <sal/log.hxx> @@ -564,22 +565,28 @@ tools::Long BigMulDiv(tools::Long nVal, tools::Long nMul, tools::Long nDiv) return BigInt::Scale(nVal, nMul, nDiv); } +static FrPair toPair(o3tl::Length eFrom, o3tl::Length eTo) +{ + const auto& [nNum, nDen] = o3tl::getConversionMulDiv(eFrom, eTo); + return FrPair(nNum, nDen); +} + // How many eU units fit into a mm, respectively an inch? // Or: How many mm, respectively inches, are there in an eU (and then give me the inverse) static FrPair GetInchOrMM(MapUnit eU) { switch (eU) { - case MapUnit::Map1000thInch: return FrPair(1000,1); - case MapUnit::Map100thInch : return FrPair( 100,1); - case MapUnit::Map10thInch : return FrPair( 10,1); - case MapUnit::MapInch : return FrPair( 1,1); - case MapUnit::MapPoint : return FrPair( 72,1); - case MapUnit::MapTwip : return FrPair(1440,1); - case MapUnit::Map100thMM : return FrPair( 100,1); - case MapUnit::Map10thMM : return FrPair( 10,1); - case MapUnit::MapMM : return FrPair( 1,1); - case MapUnit::MapCM : return FrPair( 1,10); + case MapUnit::Map1000thInch: return toPair(o3tl::Length::in, o3tl::Length::in1000); + case MapUnit::Map100thInch : return toPair(o3tl::Length::in, o3tl::Length::in100); + case MapUnit::Map10thInch : return toPair(o3tl::Length::in, o3tl::Length::in10); + case MapUnit::MapInch : return toPair(o3tl::Length::in, o3tl::Length::in); + case MapUnit::MapPoint : return toPair(o3tl::Length::in, o3tl::Length::pt); + case MapUnit::MapTwip : return toPair(o3tl::Length::in, o3tl::Length::twip); + case MapUnit::Map100thMM : return toPair(o3tl::Length::mm, o3tl::Length::mm100); + case MapUnit::Map10thMM : return toPair(o3tl::Length::mm, o3tl::Length::mm10); + case MapUnit::MapMM : return toPair(o3tl::Length::mm, o3tl::Length::mm); + case MapUnit::MapCM : return toPair(o3tl::Length::mm, o3tl::Length::cm); case MapUnit::MapPixel : { ScopedVclPtrInstance< VirtualDevice > pVD; pVD->SetMapMode(MapMode(MapUnit::Map100thMM)); @@ -599,31 +606,16 @@ static FrPair GetInchOrMM(MapUnit eU) return Fraction(1,1); } -static FrPair GetInchOrMM(FieldUnit eU) -{ - switch (eU) { - case FieldUnit::INCH : return FrPair( 1,1); - case FieldUnit::POINT : return FrPair( 72,1); - case FieldUnit::TWIP : return FrPair(1440,1); - case FieldUnit::MM_100TH : return FrPair( 100,1); - case FieldUnit::MM : return FrPair( 1,1); - case FieldUnit::CM : return FrPair( 1,10); - case FieldUnit::M : return FrPair( 1,1000); - case FieldUnit::KM : return FrPair( 1,1000000); - case FieldUnit::PICA : return FrPair( 6,1); - case FieldUnit::FOOT : return FrPair( 1,12); - case FieldUnit::MILE : return FrPair( 1,63360); - default: break; - } - return Fraction(1,1); -} - // Calculate the factor that we need to convert units from eS to eD. // e. g. GetMapFactor(UNIT_MM,UNIT_100TH_MM) => 100. FrPair GetMapFactor(MapUnit eS, MapUnit eD) { if (eS==eD) return FrPair(1,1,1,1); + const auto eFrom = MapToO3tlLength(eS, o3tl::Length::invalid); + const auto eTo = MapToO3tlLength(eD, o3tl::Length::invalid); + if (eFrom != o3tl::Length::invalid && eTo != o3tl::Length::invalid) + return toPair(eFrom, eTo); FrPair aS(GetInchOrMM(eS)); FrPair aD(GetInchOrMM(eD)); bool bSInch=IsInch(eS); @@ -637,84 +629,51 @@ FrPair GetMapFactor(MapUnit eS, MapUnit eD) FrPair GetMapFactor(FieldUnit eS, FieldUnit eD) { if (eS==eD) return FrPair(1,1,1,1); - FrPair aS(GetInchOrMM(eS)); - FrPair aD(GetInchOrMM(eD)); - bool bSInch=IsInch(eS); - bool bDInch=IsInch(eD); - FrPair aRet(aD.X()/aS.X(),aD.Y()/aS.Y()); - if (bSInch && !bDInch) { aRet.X()*=Fraction(127,5); aRet.Y()*=Fraction(127,5); } - if (!bSInch && bDInch) { aRet.X()*=Fraction(5,127); aRet.Y()*=Fraction(5,127); } - return aRet; + auto eFrom = FieldToO3tlLength(eS), eTo = FieldToO3tlLength(eD); + if (eFrom == o3tl::Length::invalid) + { + if (eTo == o3tl::Length::invalid) + return FrPair(1,1,1,1); + eFrom = IsInch(eD) ? o3tl::Length::in : o3tl::Length::mm; + } + else if (eTo == o3tl::Length::invalid) + eTo = IsInch(eS) ? o3tl::Length::in : o3tl::Length::mm; + return toPair(eFrom, eTo); }; - - // 1 mile = 8 furlong = 63.360" = 1.609.344,0mm - // 1 furlong = 10 chains = 7.920" = 201.168,0mm - // 1 chain = 4 poles = 792" = 20.116,8mm - // 1 pole = 5 1/2 yd = 198" = 5.029,2mm - // 1 yd = 3 ft = 36" = 914,4mm - // 1 ft = 12 " = 1" = 304,8mm - -static void GetMeterOrInch(MapUnit eMU, short& rnComma, tools::Long& rnMul, tools::Long& rnDiv, bool& rbMetr, bool& rbInch) -{ - rnMul=1; rnDiv=1; - short nComma=0; - bool bMetr = false, bInch = false; - switch (eMU) { - // Metrically - case MapUnit::Map100thMM : bMetr = true; nComma=5; break; - case MapUnit::Map10thMM : bMetr = true; nComma=4; break; - case MapUnit::MapMM : bMetr = true; nComma=3; break; - case MapUnit::MapCM : bMetr = true; nComma=2; break; - // Inch - case MapUnit::Map1000thInch: bInch = true; nComma=3; break; - case MapUnit::Map100thInch : bInch = true; nComma=2; break; - case MapUnit::Map10thInch : bInch = true; nComma=1; break; - case MapUnit::MapInch : bInch = true; nComma=0; break; - case MapUnit::MapPoint : bInch = true; rnDiv=72; break; // 1Pt = 1/72" - case MapUnit::MapTwip : bInch = true; rnDiv=144; nComma=1; break; // 1Twip = 1/1440" - // Others - case MapUnit::MapPixel : break; - case MapUnit::MapSysFont : break; - case MapUnit::MapAppFont : break; - case MapUnit::MapRelative : break; - default: break; - } // switch - rnComma=nComma; - rbMetr=bMetr; - rbInch=bInch; -} - - void SdrFormatter::Undirty() { - bool bSrcMetr,bSrcInch,bDstMetr,bDstInch; - tools::Long nMul1,nDiv1,nMul2,nDiv2; - short nComma1,nComma2; - // first: normalize to m or in - GetMeterOrInch(eSrcMU,nComma1,nMul1,nDiv1,bSrcMetr,bSrcInch); - GetMeterOrInch(eDstMU,nComma2,nMul2,nDiv2,bDstMetr,bDstInch); - nMul1*=nDiv2; - nDiv1*=nMul2; - nComma1=nComma1-nComma2; - - if (bSrcInch && bDstMetr) { - nComma1+=4; - nMul1*=254; - } - if (bSrcMetr && bDstInch) { - nComma1-=4; - nDiv1*=254; - } - - // temporary fraction for canceling - Fraction aTempFract(nMul1,nDiv1); - nMul1=aTempFract.GetNumerator(); - nDiv1=aTempFract.GetDenominator(); - - nMul_=nMul1; - nDiv_=nDiv1; - nComma_=nComma1; + const o3tl::Length eFrom = MapToO3tlLength(eSrcMU, o3tl::Length::invalid); + const o3tl::Length eTo = MapToO3tlLength(eDstMU, o3tl::Length::invalid); + if (eFrom != o3tl::Length::invalid && eTo != o3tl::Length::invalid) + { + const auto& [mul, div] = o3tl::getConversionMulDiv(eFrom, eTo); + sal_Int64 nMul = mul; + sal_Int64 nDiv = div; + short nComma = 0; + + // shorten trailing zeros for dividend + while (0 == (nMul % 10)) + { + nComma--; + nMul /= 10; + } + + // shorten trailing zeros for divisor + while (0 == (nDiv % 10)) + { + nComma++; + nDiv /= 10; + } + nMul_ = nMul; + nDiv_ = nDiv; + nComma_ = nComma; + } + else + { + nMul_ = nDiv_ = 1; + nComma_ = 0; + } bDirty=false; } diff --git a/sw/source/core/view/viewsh.cxx b/sw/source/core/view/viewsh.cxx index 5365b3399698..2c4ad8f2e8f4 100644 --- a/sw/source/core/view/viewsh.cxx +++ b/sw/source/core/view/viewsh.cxx @@ -77,6 +77,7 @@ #include <svx/svdpagv.hxx> #include <comphelper/lok.hxx> #include <sfx2/lokhelper.hxx> +#include <tools/UnitConversion.hxx> #if !HAVE_FEATURE_DESKTOP #include <vcl/sysdata.hxx> @@ -1903,8 +1904,9 @@ void SwViewShell::PaintTile(VirtualDevice &rDevice, int contextWidth, int contex // Scaling. Must convert from pixels to twips. We know // that VirtualDevices use a DPI of 96. - Fraction scaleX = Fraction(contextWidth, 96) * Fraction(1440) / Fraction(tileWidth); - Fraction scaleY = Fraction(contextHeight, 96) * Fraction(1440) / Fraction(tileHeight); + const Fraction scale = conversionFract(o3tl::Length::px, o3tl::Length::twip); + Fraction scaleX = Fraction(contextWidth, tileWidth) * scale; + Fraction scaleY = Fraction(contextHeight, tileHeight) * scale; aMapMode.SetScaleX(scaleX); aMapMode.SetScaleY(scaleY); rDevice.SetMapMode(aMapMode); diff --git a/sw/source/filter/html/css1atr.cxx b/sw/source/filter/html/css1atr.cxx index b2515833eba7..0b3721fe4caa 100644 --- a/sw/source/filter/html/css1atr.cxx +++ b/sw/source/filter/html/css1atr.cxx @@ -91,6 +91,7 @@ #include <IDocumentStylePoolAccess.hxx> #include <numrule.hxx> #include <o3tl/typed_flags_set.hxx> +#include <o3tl/unit_conversion.hxx> #include <rtl/strbuf.hxx> @@ -376,10 +377,8 @@ static void AddUnitPropertyValue(OStringBuffer &rOut, tools::Long nVal, rOut.append('-'); } - // the recalculated unit results from (x * nMul)/(nDiv*nFac*10) - tools::Long nMul = 1000; - tools::Long nDiv = 1; - tools::Long nFac = 100; + o3tl::Length eTo; + int nFac; // used to get specific number of decimals const char *pUnit; switch( eUnit ) { @@ -387,9 +386,7 @@ static void AddUnitPropertyValue(OStringBuffer &rOut, tools::Long nVal, OSL_ENSURE( FieldUnit::MM == eUnit, "Measuring unit not supported" ); [[fallthrough]]; case FieldUnit::MM: - // 0.01mm = 0.57twip - nMul = 25400; // 25.4 * 1000 - nDiv = 1440; // 72 * 20; + eTo = o3tl::Length::mm; nFac = 100; pUnit = sCSS1_UNIT_mm; break; @@ -399,9 +396,7 @@ static void AddUnitPropertyValue(OStringBuffer &rOut, tools::Long nVal, OSL_ENSURE( FieldUnit::CM == eUnit, "Measuring unit not supported" ); [[fallthrough]]; case FieldUnit::CM: - // 0.01cm = 5.7twip (not exact, but the UI is also not exact) - nMul = 2540; // 2.54 * 1000 - nDiv = 1440; // 72 * 20; + eTo = o3tl::Length::cm; nFac = 100; pUnit = sCSS1_UNIT_cm; break; @@ -410,17 +405,13 @@ static void AddUnitPropertyValue(OStringBuffer &rOut, tools::Long nVal, OSL_ENSURE( FieldUnit::POINT == eUnit, "Measuring unit not supported" ); [[fallthrough]]; case FieldUnit::POINT: - // 0.1pt = 2.0twip (not exact, but the UI is also not exact) - nMul = 100; - nDiv = 20; + eTo = o3tl::Length::pt; nFac = 10; pUnit = sCSS1_UNIT_pt; break; case FieldUnit::PICA: - // 0.01pc = 2.40twip (not exact, but the UI is also not exact) - nMul = 1000; - nDiv = 240; // 12 * 20; + eTo = o3tl::Length::pc; nFac = 100; pUnit = sCSS1_UNIT_pc; break; @@ -433,63 +424,21 @@ static void AddUnitPropertyValue(OStringBuffer &rOut, tools::Long nVal, case FieldUnit::INCH: default: OSL_ENSURE( FieldUnit::INCH == eUnit, "Measuring unit not supported" ); - // 0.01in = 14.4twip (not exact, but the UI is also not exact) - nMul = 1000; - nDiv = 1440; // 72 * 20; + eTo = o3tl::Length::in; nFac = 100; pUnit = sCSS1_UNIT_inch; break; } - tools::Long nLongVal = 0; - bool bOutLongVal = true; - if( nVal > LONG_MAX / nMul ) + sal_Int64 nResult = o3tl::convert(nVal * nFac, o3tl::Length::twip, eTo); + rOut.append(OString::number(nResult/nFac)); + if ((nResult % nFac) != 0) { - sal_Int64 nBigVal( nVal ); - nBigVal *= nMul; - nBigVal /= nDiv; - nBigVal += 5; - nBigVal /= 10; - - if( nBigVal <= LONG_MAX ) - { - // a long is sufficient - nLongVal = static_cast<tools::Long>(nBigVal); - } - else - { - rOut.append(nBigVal / static_cast<sal_Int64>(nFac)); - if( (nBigVal % static_cast<sal_Int64>(nFac)) != 0 ) - { - rOut.append('.'); - while( nFac > 1 && (nBigVal % static_cast<sal_Int64>(nFac)) != 0 ) - { - nFac /= 10; - rOut.append((nBigVal / static_cast<sal_Int64>(nFac)) % sal_Int64(10)); - } - } - bOutLongVal = false; - } - } - else - { - nLongVal = nVal * nMul; - nLongVal /= nDiv; - nLongVal += 5; - nLongVal /= 10; - } - - if( bOutLongVal ) - { - rOut.append(OString::number(nLongVal/nFac)); - if( (nLongVal % nFac) != 0 ) + rOut.append('.'); + while (nFac > 1 && (nResult % nFac) != 0) { - rOut.append('.'); - while( nFac > 1 && (nLongVal % nFac) != 0 ) - { - nFac /= 10; - rOut.append(OString::number((nLongVal / nFac) % 10)); - } + nFac /= 10; + rOut.append(OString::number((nResult / nFac) % 10)); } } diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index c9f78fd2c446..ddc26f1a3be4 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -133,6 +133,7 @@ #include <txtatr.hxx> #include <frameformats.hxx> +#include <o3tl/unit_conversion.hxx> #include <osl/file.hxx> #include <utility> #include <vcl/embeddedfontshelper.hxx> @@ -9271,10 +9272,10 @@ void DocxAttributeOutput::FormatBox( const SvxBoxItem& rBox ) double fDistanceBottomTwips = double(rBox.GetDistance(SvxBoxItemLine::BOTTOM)); // Convert 'TWIPS' to 'INCH' (because in Word the default values are in Inches) - double fDistanceLeftInch = fDistanceLeftTwips / 1440; - double fDistanceTopInch = fDistanceTopTwips / 1440; - double fDistanceRightInch = fDistanceRightTwips / 1440; - double fDistanceBottomInch = fDistanceBottomTwips / 1440; + double fDistanceLeftInch = o3tl::convert(fDistanceLeftTwips, o3tl::Length::twip, o3tl::Length::in); + double fDistanceTopInch = o3tl::convert(fDistanceTopTwips, o3tl::Length::twip, o3tl::Length::in); + double fDistanceRightInch = o3tl::convert(fDistanceRightTwips, o3tl::Length::twip, o3tl::Length::in); + double fDistanceBottomInch = o3tl::convert(fDistanceBottomTwips, o3tl::Length::twip, o3tl::Length::in); // This code will write ONLY the non-default values. The values are in 'left','top','right','bottom' order. // so 'bottom' is checked if it is default and if it is non-default - all the values will be written diff --git a/sw/source/filter/ww8/wrtw8esh.cxx b/sw/source/filter/ww8/wrtw8esh.cxx index bee858964b4e..a964516780db 100644 --- a/sw/source/filter/ww8/wrtw8esh.cxx +++ b/sw/source/filter/ww8/wrtw8esh.cxx @@ -2145,11 +2145,8 @@ void SwBasicEscherEx::Init() } // MS-DFF-Properties mostly are in EMU (English Metric Units) - // 1mm=36000emu, 1twip=635emu - Fraction aFact(360, 1); + Fraction aFact = conversionFract(o3tl::Length::mm100, o3tl::Length::emu); aFact /= GetMapFactor(MapUnit::Map100thMM, eMap).X(); - // create little values - aFact = Fraction(aFact.GetNumerator(), aFact.GetDenominator()); mnEmuMul = aFact.GetNumerator(); mnEmuDiv = aFact.GetDenominator(); diff --git a/sw/source/filter/ww8/ww8par6.cxx b/sw/source/filter/ww8/ww8par6.cxx index 44acfec4b3fb..9cffb20357fe 100644 --- a/sw/source/filter/ww8/ww8par6.cxx +++ b/sw/source/filter/ww8/ww8par6.cxx @@ -19,6 +19,7 @@ #include <stdlib.h> #include <o3tl/safeint.hxx> +#include <o3tl/unit_conversion.hxx> #include <svl/itemiter.hxx> #include <svl/grabbagitem.hxx> #include <rtl/tencinfo.h> @@ -106,8 +107,10 @@ using namespace nsHdFtFlags; // various -#define MM_250 1417 // WW default for horizontal borders: 2.5 cm -#define MM_200 1134 // WW default for lower border: 2.0 cm +// WW default for horizontal borders: 2.5 cm +constexpr auto MM_250 = o3tl::convert(25, o3tl::Length::mm, o3tl::Length::twip); // 1417 +// WW default for lower border: 2.0 cm +constexpr auto MM_200 = o3tl::convert(20, o3tl::Length::mm, o3tl::Length::twip); // 1134 static sal_uInt8 lcl_ReadBorders(bool bVer67, WW8_BRCVer9* brc, WW8PLCFx_Cp_FKP* pPap, diff --git a/vcl/source/control/field.cxx b/vcl/source/control/field.cxx index f232e50a7c7a..9a42dcb2d8a5 100644 --- a/vcl/source/control/field.cxx +++ b/vcl/source/control/field.cxx @@ -19,12 +19,14 @@ #include <sal/config.h> +#include <cmath> #include <string_view> #include <sal/log.hxx> #include <osl/diagnose.h> #include <comphelper/string.hxx> +#include <tools/UnitConversion.hxx> #include <vcl/builder.hxx> #include <vcl/fieldvalues.hxx> @@ -972,35 +974,6 @@ static FieldUnit ImplMetricGetUnit(const OUString& rStr) return vcl::StringToMetric(aStr); } -#define K *1000L -#define M *1000000LL -#define X *5280L - -// twip in km = 254 / 14 400 000 000 -// expressions too big for default size 32 bit need LL to avoid overflow - -const sal_Int64 aImplFactor[sal_uInt16(FieldUnit::LINE) + 1] - [sal_uInt16(FieldUnit::LINE) + 1] = -{ /* -mm/100 mm cm m km twip point pica inch foot mile char line */ -{ 1, 100, 1 K, 100 K, 100 M, 2540, 2540, 2540, 2540,2540*12,2540*12 X , 53340, 396240}, -{ 1, 1, 10, 1 K, 1 M, 2540, 2540, 2540, 2540,2540*12,2540*12 X , 5334, 396240}, -{ 1, 1, 1, 100, 100 K, 254, 254, 254, 254, 254*12, 254*12 X , 5334, 39624}, -{ 1, 1, 1, 1, 1 K, 254, 254, 254, 254, 254*12, 254*12 X , 533400, 39624}, -{ 1, 1, 1, 1, 1, 254, 254, 254, 254, 254*12, 254*12 X ,533400 K, 39624}, -{ 1440,144 K,144 K,14400 K,14400LL M, 1, 20, 240, 1440,1440*12,1440*12 X , 210, 3120}, -{ 72, 7200, 7200, 720 K, 720 M, 1, 1, 12, 72, 72*12, 72*12 X , 210, 156}, -{ 6, 600, 600, 60 K, 60 M, 1, 1, 1, 6, 6*12, 6*12 X , 210, 10}, -{ 1, 100, 100, 10 K, 10 M, 1, 1, 1, 1, 12, 12 X , 210, 45}, -{ 1, 100, 100, 10 K, 10 M, 1, 1, 1, 1, 1, 1 X , 210, 45}, -{ 1, 100, 100, 10 K, 10 M, 1, 1, 1, 1, 1, 1 , 210, 45}, -{ 144, 1440,14400, 14400, 14400, 1, 20, 240, 1440,1440*12, 1440*12 X, 1, 156 }, -{ 720,72000,72000, 7200 K,7200LL M, 20, 10, 13, 11, 11*12, 11*12 X, 105, 1 } -}; -#undef X -#undef M -#undef K - static FieldUnit ImplMap2FieldUnit( MapUnit meUnit, tools::Long& nDecDigits ) { switch( meUnit ) @@ -1057,7 +1030,7 @@ namespace vcl else if ( nDouble >= double(SAL_MAX_INT64) ) nLong = SAL_MAX_INT64; else - nLong = static_cast<sal_Int64>( nDouble ); + nLong = static_cast<sal_Int64>( std::round(nDouble) ); return nLong; } @@ -1094,20 +1067,11 @@ double convertValue( double nValue, tools::Long nDigits, FieldUnit eInUnit, Fiel if ( eInUnit != eOutUnit ) { - sal_Int64 nDiv = aImplFactor[sal_uInt16(eInUnit)][sal_uInt16(eOutUnit)]; - sal_Int64 nMult = aImplFactor[sal_uInt16(eOutUnit)][sal_uInt16(eInUnit)]; - - SAL_WARN_IF( nMult <= 0, "vcl", "illegal *" ); - SAL_WARN_IF( nDiv <= 0, "vcl", "illegal /" ); - - if ( nMult != 1 && nMult > 0) - nValue *= nMult; - if ( nDiv != 1 && nDiv > 0 ) - { - nValue += (nValue < 0) ? (-nDiv/2) : (nDiv/2); - nValue /= nDiv; - } + const o3tl::Length eFrom = FieldToO3tlLength(eInUnit), eTo = FieldToO3tlLength(eOutUnit); + if (eFrom != o3tl::Length::invalid && eTo != o3tl::Length::invalid) + nValue = o3tl::convert(nValue, eFrom, eTo); } + return nValue; } @@ -1143,49 +1107,22 @@ namespace vcl { if ( eInUnit != eOutUnit ) { - sal_Int64 nMult = 1, nDiv = 1; - - if (eInUnit == FieldUnit::PERCENT) + if (eInUnit == FieldUnit::PERCENT && mnBaseValue > 0 && nValue > 0) { - if ( (mnBaseValue <= 0) || (nValue <= 0) ) - return nValue; - nDiv = 100 * ImplPower10(nDecDigits); + sal_Int64 nDiv = 100 * ImplPower10(nDecDigits); - nMult = mnBaseValue; - } - else if ( eOutUnit == FieldUnit::PERCENT || - eOutUnit == FieldUnit::CUSTOM || - eOutUnit == FieldUnit::NONE || - eOutUnit == FieldUnit::DEGREE || - eOutUnit == FieldUnit::SECOND || - eOutUnit == FieldUnit::MILLISECOND || - eOutUnit == FieldUnit::PIXEL || - eInUnit == FieldUnit::CUSTOM || - eInUnit == FieldUnit::NONE || - eInUnit == FieldUnit::DEGREE || - eInUnit == FieldUnit::MILLISECOND || - eInUnit == FieldUnit::PIXEL ) - return nValue; - else - { - if (eOutUnit == FieldUnit::MM_100TH) - eOutUnit = FieldUnit::NONE; - if (eInUnit == FieldUnit::MM_100TH) - eInUnit = FieldUnit::NONE; + if (mnBaseValue != 1) + nValue *= mnBaseValue; - nDiv = aImplFactor[sal_uInt16(eInUnit)][sal_uInt16(eOutUnit)]; - nMult = aImplFactor[sal_uInt16(eOutUnit)][sal_uInt16(eInUnit)]; - - SAL_WARN_IF( nMult <= 0, "vcl", "illegal *" ); - SAL_WARN_IF( nDiv <= 0, "vcl", "illegal /" ); + nValue += nDiv / 2; + nValue /= nDiv; } - - if ( nMult != 1 && nMult > 0 ) - nValue *= nMult; - if ( nDiv != 1 && nDiv > 0 ) + else { - nValue += ( nValue < 0 ) ? (-nDiv/2) : (nDiv/2); - nValue /= nDiv; + const o3tl::Length eFrom = FieldToO3tlLength(eInUnit, o3tl::Length::invalid); + const o3tl::Length eTo = FieldToO3tlLength(eOutUnit, o3tl::Length::invalid); + if (eFrom != o3tl::Length::invalid && eTo != o3tl::Length::invalid) + nValue = o3tl::convert(nValue, eFrom, eTo); } } @@ -1240,19 +1177,10 @@ namespace vcl if ( eFieldUnit != eInUnit ) { - sal_Int64 nDiv = aImplFactor[sal_uInt16(eInUnit)][sal_uInt16(eFieldUnit)]; - sal_Int64 nMult = aImplFactor[sal_uInt16(eFieldUnit)][sal_uInt16(eInUnit)]; - - SAL_WARN_IF( nMult <= 0, "vcl", "illegal *" ); - SAL_WARN_IF( nDiv <= 0, "vcl", "illegal /" ); - - if( nMult != 1 && nMult > 0 ) - nValue *= nMult; - if( nDiv != 1 && nDiv > 0 ) - { - nValue += (nValue < 0) ? (-nDiv/2) : (nDiv/2); - nValue /= nDiv; - } + const o3tl::Length eFrom = FieldToO3tlLength(eInUnit, o3tl::Length::invalid); + const o3tl::Length eTo = FieldToO3tlLength(eFieldUnit, o3tl::Length::invalid); + if (eFrom != o3tl::Length::invalid && eTo != o3tl::Length::invalid) + nValue = o3tl::convert(nValue, eFrom, eTo); } return nValue; } diff --git a/vcl/source/gdi/pdfwriter_impl2.cxx b/vcl/source/gdi/pdfwriter_impl2.cxx index e349d8e837f9..304647aa1233 100644 --- a/vcl/source/gdi/pdfwriter_impl2.cxx +++ b/vcl/source/gdi/pdfwriter_impl2.cxx @@ -43,6 +43,7 @@ #include <com/sun/star/beans/XMaterialHolder.hpp> #include <cppuhelper/implbase.hxx> +#include <o3tl/unit_conversion.hxx> #include <sal/log.hxx> #include <memory> @@ -116,8 +117,12 @@ void PDFWriterImpl::implWriteBitmapEx( const Point& i_rPoint, const Size& i_rSiz const Size aDstSizeTwip( i_pDummyVDev->PixelToLogic(i_pDummyVDev->LogicToPixel(aSize), MapMode(MapUnit::MapTwip)) ); const double fBmpPixelX = aBmpSize.Width(); const double fBmpPixelY = aBmpSize.Height(); - const double fMaxPixelX = aDstSizeTwip.Width() * i_rContext.m_nMaxImageResolution / 1440.0; - const double fMaxPixelY = aDstSizeTwip.Height() * i_rContext.m_nMaxImageResolution / 1440.0; + const double fMaxPixelX + = o3tl::convert<double>(aDstSizeTwip.Width(), o3tl::Length::twip, o3tl::Length::in) + * i_rContext.m_nMaxImageResolution; + const double fMaxPixelY + = o3tl::convert<double>(aDstSizeTwip.Height(), o3tl::Length::twip, o3tl::Length::in) + * i_rContext.m_nMaxImageResolution; // check, if the bitmap DPI exceeds the maximum DPI (allow 4 pixel rounding tolerance) if( ( ( fBmpPixelX > ( fMaxPixelX + 4 ) ) || @@ -460,8 +465,8 @@ void PDFWriterImpl::playMetafile( const GDIMetaFile& i_rMtf, vcl::PDFExtOutDevDa if ( nMaxBmpDPI > i_rContext.m_nMaxImageResolution ) nMaxBmpDPI = i_rContext.m_nMaxImageResolution; } - const sal_Int32 nPixelX = static_cast<sal_Int32>(static_cast<double>(aDstSizeTwip.Width()) * static_cast<double>(nMaxBmpDPI) / 1440.0); - const sal_Int32 nPixelY = static_cast<sal_Int32>(static_cast<double>(aDstSizeTwip.Height()) * static_cast<double>(nMaxBmpDPI) / 1440.0); + const sal_Int32 nPixelX = o3tl::convert<double>(aDstSizeTwip.Width(), o3tl::Length::twip, o3tl::Length::in) * nMaxBmpDPI; + const sal_Int32 nPixelY = o3tl::convert<double>(aDstSizeTwip.Height(), o3tl::Length::twip, o3tl::Length::in) * nMaxBmpDPI; if ( nPixelX && nPixelY ) { Size aDstSizePixel( nPixelX, nPixelY ); diff --git a/vcl/source/outdev/bitmap.cxx b/vcl/source/outdev/bitmap.cxx index c69938b11878..6c93084f0062 100644 --- a/vcl/source/outdev/bitmap.cxx +++ b/vcl/source/outdev/bitmap.cxx @@ -46,6 +46,7 @@ #include <tools/helpers.hxx> #include <tools/debug.hxx> #include <rtl/math.hxx> +#include <o3tl/unit_conversion.hxx> #include <vcl/dibtools.hxx> #include <tools/stream.hxx> @@ -216,8 +217,12 @@ Bitmap OutputDevice::GetDownsampledBitmap( const Size& rDstSz, const Size aBmpSize( aBmp.GetSizePixel() ); const double fBmpPixelX = aBmpSize.Width(); const double fBmpPixelY = aBmpSize.Height(); - const double fMaxPixelX = aDstSizeTwip.Width() * nMaxBmpDPIX / 1440.0; - const double fMaxPixelY = aDstSizeTwip.Height() * nMaxBmpDPIY / 1440.0; + const double fMaxPixelX + = o3tl::convert<double>(aDstSizeTwip.Width(), o3tl::Length::twip, o3tl::Length::in) + * nMaxBmpDPIX; + const double fMaxPixelY + = o3tl::convert<double>(aDstSizeTwip.Height(), o3tl::Length::twip, o3tl::Length::in) + * nMaxBmpDPIY; // check, if the bitmap DPI exceeds the maximum DPI (allow 4 pixel rounding tolerance) if( ( ( fBmpPixelX > ( fMaxPixelX + 4 ) ) || diff --git a/vcl/source/outdev/map.cxx b/vcl/source/outdev/map.cxx index 09ae63b0174d..e899fdc96fa4 100644 --- a/vcl/source/outdev/map.cxx +++ b/vcl/source/outdev/map.cxx @@ -33,14 +33,7 @@ #include <outdev.h> #include <basegfx/matrix/b2dhommatrix.hxx> -#include <o3tl/enumarray.hxx> - -// we don't actually handle units beyond, hence the zeros in the arrays -const MapUnit s_MaxValidUnit = MapUnit::MapPixel; -const o3tl::enumarray<MapUnit,tools::Long> aImplNumeratorAry = - { 1, 1, 5, 50, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 }; -const o3tl::enumarray<MapUnit,tools::Long> aImplDenominatorAry = - { 2540, 254, 127, 127, 1000, 100, 10, 1, 72, 1440, 1, 0, 0, 0 }; +#include <tools/UnitConversion.hxx> /* Reduces accuracy until it is a fraction (should become @@ -82,6 +75,13 @@ static Fraction ImplMakeFraction( tools::Long nN1, tools::Long nN2, tools::Long return aF; } +static auto setMapRes(ImplMapRes& rMapRes, const o3tl::Length eUnit) +{ + const auto [nNum, nDen] = o3tl::getConversionMulDiv(eUnit, o3tl::Length::in); + rMapRes.mnMapScNumX = rMapRes.mnMapScNumY = nNum; + rMapRes.mnMapScDenomX = rMapRes.mnMapScDenomY = nDen; +}; + static void ImplCalcMapResolution( const MapMode& rMapMode, tools::Long nDPIX, tools::Long nDPIY, ImplMapRes& rMapRes ) { @@ -90,64 +90,34 @@ static void ImplCalcMapResolution( const MapMode& rMapMode, case MapUnit::MapRelative: break; case MapUnit::Map100thMM: - rMapRes.mnMapScNumX = 1; - rMapRes.mnMapScDenomX = 2540; - rMapRes.mnMapScNumY = 1; - rMapRes.mnMapScDenomY = 2540; + setMapRes(rMapRes, o3tl::Length::mm100); break; case MapUnit::Map10thMM: - rMapRes.mnMapScNumX = 1; - rMapRes.mnMapScDenomX = 254; - rMapRes.mnMapScNumY = 1; - rMapRes.mnMapScDenomY = 254; + setMapRes(rMapRes, o3tl::Length::mm10); break; case MapUnit::MapMM: - rMapRes.mnMapScNumX = 5; // 10 - rMapRes.mnMapScDenomX = 127; // 254 - rMapRes.mnMapScNumY = 5; // 10 - rMapRes.mnMapScDenomY = 127; // 254 + setMapRes(rMapRes, o3tl::Length::mm); break; case MapUnit::MapCM: - rMapRes.mnMapScNumX = 50; // 100 - rMapRes.mnMapScDenomX = 127; // 254 - rMapRes.mnMapScNumY = 50; // 100 - rMapRes.mnMapScDenomY = 127; // 254 + setMapRes(rMapRes, o3tl::Length::cm); break; case MapUnit::Map1000thInch: - rMapRes.mnMapScNumX = 1; - rMapRes.mnMapScDenomX = 1000; - rMapRes.mnMapScNumY = 1; - rMapRes.mnMapScDenomY = 1000; + setMapRes(rMapRes, o3tl::Length::in1000); break; case MapUnit::Map100thInch: - rMapRes.mnMapScNumX = 1; - rMapRes.mnMapScDenomX = 100; - rMapRes.mnMapScNumY = 1; - rMapRes.mnMapScDenomY = 100; + setMapRes(rMapRes, o3tl::Length::in100); break; case MapUnit::Map10thInch: - rMapRes.mnMapScNumX = 1; - rMapRes.mnMapScDenomX = 10; - rMapRes.mnMapScNumY = 1; - rMapRes.mnMapScDenomY = 10; + setMapRes(rMapRes, o3tl::Length::in10); break; case MapUnit::MapInch: - rMapRes.mnMapScNumX = 1; - rMapRes.mnMapScDenomX = 1; - rMapRes.mnMapScNumY = 1; - rMapRes.mnMapScDenomY = 1; + setMapRes(rMapRes, o3tl::Length::in); break; case MapUnit::MapPoint: - rMapRes.mnMapScNumX = 1; - rMapRes.mnMapScDenomX = 72; - rMapRes.mnMapScNumY = 1; - rMapRes.mnMapScDenomY = 72; + setMapRes(rMapRes, o3tl::Length::pt); break; case MapUnit::MapTwip: - rMapRes.mnMapScNumX = 1; - rMapRes.mnMapScDenomX = 1440; - rMapRes.mnMapScNumY = 1; - rMapRes.mnMapScDenomY = 1440; + setMapRes(rMapRes, o3tl::Length::twip); break; case MapUnit::MapPixel: rMapRes.mnMapScNumX = 1; @@ -701,8 +671,10 @@ void OutputDevice::SetRelativeMapMode( const MapMode& rNewMapMode ) } else { - Fraction aF( aImplNumeratorAry[eNew] * aImplDenominatorAry[eOld], - aImplNumeratorAry[eOld] * aImplDenominatorAry[eNew] ); + const auto eFrom = MapToO3tlLength(eOld, o3tl::Length::in); + const auto eTo = MapToO3tlLength(eNew, o3tl::Length::in); + const auto& [nNum, nDen] = o3tl::getConversionMulDiv(eFrom, eTo); + Fraction aF(nNum, nDen); // a?F = a?F * aF aXF = ImplMakeFraction( aXF.GetNumerator(), aF.GetNumerator(), @@ -1322,22 +1294,25 @@ static void verifyUnitSourceDest( MapUnit eUnitSource, MapUnit eUnitDest ) "Destination MapUnit is not permitted" ); } -#define ENTER3( eUnitSource, eUnitDest ) \ - tools::Long nNumerator = 1; \ - tools::Long nDenominator = 1; \ - SAL_WARN_IF( eUnitSource > s_MaxValidUnit, "vcl.gdi", "Invalid source map unit"); \ - SAL_WARN_IF( eUnitDest > s_MaxValidUnit, "vcl.gdi", "Invalid destination map unit"); \ - if( (eUnitSource <= s_MaxValidUnit) && (eUnitDest <= s_MaxValidUnit) ) \ - { \ - nNumerator = aImplNumeratorAry[eUnitSource] * \ - aImplDenominatorAry[eUnitDest]; \ - nDenominator = aImplNumeratorAry[eUnitDest] * \ - aImplDenominatorAry[eUnitSource]; \ - } \ - if ( eUnitSource == MapUnit::MapPixel ) \ - nDenominator *= 72; \ - else if( eUnitDest == MapUnit::MapPixel ) \ - nNumerator *= 72 +namespace +{ +auto getCorrectedUnit(MapUnit eMapSrc, MapUnit eMapDst) +{ + o3tl::Length eSrc = o3tl::Length::invalid; + o3tl::Length eDst = o3tl::Length::invalid; + if (eMapSrc > MapUnit::MapPixel) + SAL_WARN("vcl.gdi", "Invalid source map unit"); + else if (eMapDst > MapUnit::MapPixel) + SAL_WARN("vcl.gdi", "Invalid destination map unit"); + else if (eMapSrc != eMapDst) + { + // Here 72 PPI is assumed for MapPixel + eSrc = MapToO3tlLength(eMapSrc, o3tl::Length::pt); + eDst = MapToO3tlLength(eMapDst, o3tl::Length::pt); + } + return std::make_pair(eSrc, eDst); +} +} #define ENTER4( rMapModeSource, rMapModeDest ) \ ImplMapRes aMapResSource; \ @@ -1464,13 +1439,15 @@ static tools::Long fn5( const tools::Long n1, } // of else } -// return (n1 * n2) / n3 -static tools::Long fn3( const tools::Long n1, const tools::Long n2, const tools::Long n3 ) +static tools::Long fn3(const tools::Long n1, const o3tl::Length eFrom, const o3tl::Length eTo) { - if ( n1 == 0 || n2 == 0 || n3 == 0 ) + if (n1 == 0 || eFrom == o3tl::Length::invalid || eTo == o3tl::Length::invalid) return 0; - if (std::numeric_limits<tools::Long>::max() / std::abs(n1) < std::abs(n2)) + bool bOverflow; + const auto nResult = o3tl::convert(n1, eFrom, eTo, bOverflow); + if (bOverflow) { + const auto& [n2, n3] = o3tl::getConversionMulDiv(eFrom, eTo); BigInt a4 = n1; a4 *= n2; @@ -1483,20 +1460,7 @@ static tools::Long fn3( const tools::Long n1, const tools::Long n2, const tools: return static_cast<tools::Long>(a4); } // of if else - { - tools::Long n4 = n1 * n2; - const tools::Long n3_2 = n3 / 2; - - if( n4 < 0 ) - { - if ((n4 - std::numeric_limits<tools::Long>::min()) >= n3_2) - n4 -= n3_2; - } - else if ((std::numeric_limits<tools::Long>::max() - n4) >= n3_2) - n4 += n3_2; - - return n4 / n3; - } // of else + return nResult; } Point OutputDevice::LogicToLogic( const Point& rPtSource, @@ -1566,10 +1530,8 @@ Point OutputDevice::LogicToLogic( const Point& rPtSource, if (rMapModeSource.IsSimple() && rMapModeDest.IsSimple()) { - ENTER3( eUnitSource, eUnitDest ); - - return Point( fn3( rPtSource.X(), nNumerator, nDenominator ), - fn3( rPtSource.Y(), nNumerator, nDenominator ) ); + const auto& [eFrom, eTo] = getCorrectedUnit(eUnitSource, eUnitDest); + return Point(fn3(rPtSource.X(), eFrom, eTo), fn3(rPtSource.Y(), eFrom, eTo)); } else { @@ -1599,10 +1561,8 @@ Size OutputDevice::LogicToLogic( const Size& rSzSource, if (rMapModeSource.IsSimple() && rMapModeDest.IsSimple()) { - ENTER3( eUnitSource, eUnitDest ); - - return Size( fn3( rSzSource.Width(), nNumerator, nDenominator ), - fn3( rSzSource.Height(), nNumerator, nDenominator ) ); + const auto& [eFrom, eTo] = getCorrectedUnit(eUnitSource, eUnitDest); + return Size(fn3(rSzSource.Width(), eFrom, eTo), fn3(rSzSource.Height(), eFrom, eTo)); } else { @@ -1648,9 +1608,10 @@ basegfx::B2DHomMatrix OutputDevice::LogicToLogic(const MapMode& rMapModeSource, if (rMapModeSource.IsSimple() && rMapModeDest.IsSimple()) { - ENTER3(eUnitSource, eUnitDest); - - const double fScaleFactor(static_cast<double>(nNumerator) / static_cast<double>(nDenominator)); + const auto& [eFrom, eTo] = getCorrectedUnit(eUnitSource, eUnitDest); + const double fScaleFactor(eFrom == o3tl::Length::invalid || eTo == o3tl::Length::invalid + ? std::numeric_limits<double>::quiet_NaN() + : o3tl::convert(1.0, eFrom, eTo)); aTransform.set(0, 0, fScaleFactor); aTransform.set(1, 1, fScaleFactor); } @@ -1685,15 +1646,15 @@ tools::Rectangle OutputDevice::LogicToLogic( const tools::Rectangle& rRectSource if (rMapModeSource.IsSimple() && rMapModeDest.IsSimple()) { - ENTER3( eUnitSource, eUnitDest ); + const auto& [eFrom, eTo] = getCorrectedUnit(eUnitSource, eUnitDest); - auto left = fn3( rRectSource.Left(), nNumerator, nDenominator ); - auto top = fn3( rRectSource.Top(), nNumerator, nDenominator ); + auto left = fn3(rRectSource.Left(), eFrom, eTo); + auto top = fn3(rRectSource.Top(), eFrom, eTo); if (rRectSource.IsEmpty()) return tools::Rectangle( left, top ); - auto right = fn3( rRectSource.Right(), nNumerator, nDenominator ); - auto bottom = fn3( rRectSource.Bottom(), nNumerator, nDenominator ); + auto right = fn3(rRectSource.Right(), eFrom, eTo); + auto bottom = fn3(rRectSource.Bottom(), eFrom, eTo); return tools::Rectangle(left, top, right, bottom); } else @@ -1730,9 +1691,8 @@ tools::Long OutputDevice::LogicToLogic( tools::Long nLongSource, return nLongSource; verifyUnitSourceDest( eUnitSource, eUnitDest ); - ENTER3( eUnitSource, eUnitDest ); - - return fn3( nLongSource, nNumerator, nDenominator ); + const auto& [eFrom, eTo] = getCorrectedUnit(eUnitSource, eUnitDest); + return fn3(nLongSource, eFrom, eTo); } void OutputDevice::SetPixelOffset( const Size& rOffset ) |