summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cui/source/tabpages/chardlg.cxx8
-rw-r--r--cui/source/tabpages/grfpage.cxx17
-rw-r--r--emfio/source/reader/wmfreader.cxx5
-rw-r--r--include/o3tl/unit_conversion.hxx231
-rw-r--r--include/oox/drawingml/drawingmltypes.hxx16
-rw-r--r--include/svtools/unitconv.hxx2
-rw-r--r--include/tools/UnitConversion.hxx136
-rw-r--r--o3tl/CppunitTest_o3tl_tests.mk1
-rw-r--r--o3tl/qa/test-unit_conversion.cxx872
-rw-r--r--oox/source/drawingml/diagram/diagram.cxx11
-rw-r--r--oox/source/drawingml/diagram/diagramlayoutatoms.cxx24
-rw-r--r--oox/source/drawingml/drawingmltypes.cxx5
-rw-r--r--oox/source/drawingml/shape.cxx14
-rw-r--r--oox/source/vml/vmlformatting.cxx28
-rw-r--r--sax/source/tools/converter.cxx585
-rw-r--r--sc/source/filter/oox/unitconverter.cxx23
-rw-r--r--sc/source/ui/vba/vbarange.cxx12
-rw-r--r--sd/qa/unit/export-tests-ooxml1.cxx4
-rw-r--r--sd/qa/unit/export-tests-ooxml2.cxx4
-rw-r--r--sd/qa/unit/import-tests.cxx4
-rw-r--r--sd/source/ui/unoidl/unomodel.cxx7
-rw-r--r--sfx2/source/view/lokcharthelper.cxx5
-rw-r--r--svtools/source/misc/unitconv.cxx445
-rw-r--r--svx/source/customshapes/EnhancedCustomShape3d.cxx4
-rw-r--r--svx/source/svdraw/svdmodel.cxx98
-rw-r--r--svx/source/svdraw/svdtrans.cxx165
-rw-r--r--sw/source/core/view/viewsh.cxx6
-rw-r--r--sw/source/filter/html/css1atr.cxx81
-rw-r--r--sw/source/filter/ww8/docxattributeoutput.cxx9
-rw-r--r--sw/source/filter/ww8/wrtw8esh.cxx5
-rw-r--r--sw/source/filter/ww8/ww8par6.cxx7
-rw-r--r--vcl/source/control/field.cxx116
-rw-r--r--vcl/source/gdi/pdfwriter_impl2.cxx13
-rw-r--r--vcl/source/outdev/bitmap.cxx9
-rw-r--r--vcl/source/outdev/map.cxx166
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 )