[Libreoffice-commits] core.git: cui/source emfio/source include/o3tl include/oox include/svtools include/tools o3tl/CppunitTest_o3tl_tests.mk o3tl/qa oox/source sax/source sc/source sd/qa sd/source sfx2/source svtools/source svx/source sw/source vcl/source
Mike Kaganski (via logerrit)
logerrit at kemper.freedesktop.org
Sun Feb 14 11:50:45 UTC 2021
cui/source/tabpages/chardlg.cxx | 8
cui/source/tabpages/grfpage.cxx | 17
emfio/source/reader/wmfreader.cxx | 5
include/o3tl/unit_conversion.hxx | 231 +++++
include/oox/drawingml/drawingmltypes.hxx | 16
include/svtools/unitconv.hxx | 2
include/tools/UnitConversion.hxx | 136 ++-
o3tl/CppunitTest_o3tl_tests.mk | 1
o3tl/qa/test-unit_conversion.cxx | 872 ++++++++++++++++++++
oox/source/drawingml/diagram/diagram.cxx | 11
oox/source/drawingml/diagram/diagramlayoutatoms.cxx | 24
oox/source/drawingml/drawingmltypes.cxx | 5
oox/source/drawingml/shape.cxx | 14
oox/source/vml/vmlformatting.cxx | 28
sax/source/tools/converter.cxx | 585 ++-----------
sc/source/filter/oox/unitconverter.cxx | 23
sc/source/ui/vba/vbarange.cxx | 12
sd/qa/unit/export-tests-ooxml1.cxx | 4
sd/qa/unit/export-tests-ooxml2.cxx | 4
sd/qa/unit/import-tests.cxx | 4
sd/source/ui/unoidl/unomodel.cxx | 7
sfx2/source/view/lokcharthelper.cxx | 5
svtools/source/misc/unitconv.cxx | 445 ----------
svx/source/customshapes/EnhancedCustomShape3d.cxx | 4
svx/source/svdraw/svdmodel.cxx | 98 --
svx/source/svdraw/svdtrans.cxx | 165 +--
sw/source/core/view/viewsh.cxx | 6
sw/source/filter/html/css1atr.cxx | 81 -
sw/source/filter/ww8/docxattributeoutput.cxx | 9
sw/source/filter/ww8/wrtw8esh.cxx | 5
sw/source/filter/ww8/ww8par6.cxx | 7
vcl/source/control/field.cxx | 116 --
vcl/source/gdi/pdfwriter_impl2.cxx | 13
vcl/source/outdev/bitmap.cxx | 9
vcl/source/outdev/map.cxx | 166 +--
35 files changed, 1641 insertions(+), 1497 deletions(-)
New commits:
commit cfff893b9c82843a90aac4ecdb3a3936721b74a0
Author: Mike Kaganski <mike.kaganski at collabora.com>
AuthorDate: Sat Feb 13 13:55:22 2021 +0300
Commit: Mike Kaganski <mike.kaganski at collabora.com>
CommitDate: Sun Feb 14 12:50:01 2021 +0100
Move unit conversion code to o3tl, and unify on that in more places
This also allows to easily add more units, both of length and for other
unit categories.
The conversion for "Line" unit (312 twip) is questionable. Corresponding
entries in aImplFactor in vcl/source/control/field.cxx were inconsistent
(45/11 in; 10/13 pc; 156/10 pt). They were added without explanation in
commit c85db626029fd8a5e0dfcb312937279df32339a0. I haven't found a spec
of the unit (https://en.wikipedia.org/wiki/Line_(unit) is not specific).
I used the definition based on "by pt", "by mm/100", "by char" (they all
were consistent); "by pc" seems inverted; "by twip" was half as much.
This accepted conversion makes unit test for tdf#79236 pass.
Change-Id: Iae5a21d915fa8e934a1f47f8ba9f6df03b79a9fd
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/110839
Tested-by: Mike Kaganski <mike.kaganski at collabora.com>
Reviewed-by: Mike Kaganski <mike.kaganski at collabora.com>
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(
}
}
... etc. - the rest is truncated
More information about the Libreoffice-commits
mailing list