[Libreoffice-commits] core.git: Branch 'private/tvajngerl/staging' - basegfx/CppunitTest_basegfx.mk basegfx/test include/basegfx

Tomaž Vajngerl (via logerrit) logerrit at kemper.freedesktop.org
Tue Dec 29 08:47:25 UTC 2020


Rebased ref, commits from common ancestor:
commit 2fa6311246b6b0c1cd6c006851de86fd2d7b65c6
Author:     Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
AuthorDate: Thu Nov 12 10:01:20 2020 +0100
Commit:     Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
CommitDate: Tue Dec 29 17:46:42 2020 +0900

    basegfx: added LengthUnit class as the base unit for length
    
    Change-Id: I1d4790b60dd784e8b2e2e438274f3ebd6db4b60c

diff --git a/basegfx/CppunitTest_basegfx.mk b/basegfx/CppunitTest_basegfx.mk
index 231854cdf057..2922934bc6be 100644
--- a/basegfx/CppunitTest_basegfx.mk
+++ b/basegfx/CppunitTest_basegfx.mk
@@ -41,6 +41,7 @@ $(eval $(call gb_CppunitTest_add_exception_objects,basegfx,\
     basegfx/test/basegfxtools \
     basegfx/test/clipstate \
     basegfx/test/genericclipper \
+    basegfx/test/LengthUnitTest \
 ))
 
 # vim: set noet sw=4 ts=4:
diff --git a/basegfx/test/LengthUnitTest.cxx b/basegfx/test/LengthUnitTest.cxx
new file mode 100644
index 000000000000..0b80c33da5b0
--- /dev/null
+++ b/basegfx/test/LengthUnitTest.cxx
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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 <basegfx/units/LengthUnit.hxx>
+
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+class LengthUnitTest : public CppUnit::TestFixture
+{
+public:
+    void test();
+
+    CPPUNIT_TEST_SUITE(LengthUnitTest);
+    CPPUNIT_TEST(test);
+    CPPUNIT_TEST_SUITE_END();
+};
+
+void LengthUnitTest::test()
+{
+    gfx::LengthUnit cm = 1_cm + 5_cm - 2_cm;
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(4.0, cm.as_cm(), 1e-4);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(0.04, cm.as_m(), 1e-4);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(40.0, cm.as_mm(), 1e-4);
+    CPPUNIT_ASSERT_EQUAL(sal_Int64(1440000), cm.raw());
+
+    gfx::LengthUnit cm2 = 5_cm * 2;
+    CPPUNIT_ASSERT_EQUAL(sal_Int64(3600000), cm2.raw());
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(10.0, cm2.as_cm(), 1e-4);
+
+    // 1 km - 50 m = 950 m = 95000 cm
+    gfx::LengthUnit cm3 = 100000_cm - 5000_cm;
+    CPPUNIT_ASSERT_EQUAL(sal_Int64(34200000000), cm3.raw());
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(95000.0, cm3.as_cm(), 1e-4);
+
+    gfx::LengthUnit cm4(1_cm);
+    cm4 /= 2;
+    CPPUNIT_ASSERT_EQUAL(sal_Int64(180000), cm4.raw());
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(0.5, cm4.as_cm(), 1e-4);
+
+    // (635 * 20) + 3 * (635 * 15) = 41275EMU
+    gfx::LengthUnit pt = 1_pt + 3_px;
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(3.25, pt.as_pt(), 1e-4);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(65.0, pt.as_twip(), 1e-4);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0451, pt.as_in(), 1e-4);
+    CPPUNIT_ASSERT_EQUAL(sal_Int64(41275), pt.raw());
+
+    gfx::LengthUnit inch = 1_in; // 1440 * 635
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(1440.0, inch.as_twip(), 1e-4);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(96.0, inch.as_px(), 1e-4);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, inch.as_in(), 1e-4);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(914400.0, inch.as_emu(), 1e-4);
+    CPPUNIT_ASSERT_EQUAL(sal_Int64(914400), inch.raw());
+
+    // Conversion
+    sal_Int64 asNumber(17_pt);
+    asNumber += sal_Int64(1_pt);
+    gfx::LengthUnit asLength = gfx::LengthUnit::emu(asNumber);
+    CPPUNIT_ASSERT_EQUAL(sal_Int64(18 * 635 * 20), asLength.raw());
+
+    gfx::LengthUnit maximum = gfx::LengthUnit::emu(SAL_MAX_INT64);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(256204778801.5, maximum.as_m(), 1e-1);
+    // 256204778 km
+    CPPUNIT_ASSERT_EQUAL(sal_Int64(SAL_MAX_INT64), maximum.raw());
+
+    gfx::LengthUnit minimum = gfx::LengthUnit::emu(SAL_MIN_INT64);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(-256204778801.5, minimum.as_m(), 1e-1);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(double(SAL_MIN_INT64), minimum.as_emu(), 1e-1);
+    CPPUNIT_ASSERT_EQUAL(sal_Int64(SAL_MIN_INT64), minimum.raw());
+
+    // 27 emu + 33 emu + 360 emu = 420
+    gfx::LengthUnit emus = 27_emu + 33_emu + 1_hmm;
+    CPPUNIT_ASSERT_EQUAL(sal_Int64(420), emus.raw());
+
+    //  Creation from number
+    int number = 10;
+    auto asCm = gfx::LengthUnit::cm(number);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(10.0, asCm.as_cm(), 1e-4);
+    CPPUNIT_ASSERT_EQUAL(sal_Int64(3600000), asCm.raw());
+
+    auto asMm = gfx::LengthUnit::mm(number);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(10.0, asMm.as_mm(), 1e-4);
+    CPPUNIT_ASSERT_EQUAL(sal_Int64(360000), asMm.raw());
+
+    auto asInch = gfx::LengthUnit::in(number);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(10.0, asInch.as_in(), 1e-4);
+    CPPUNIT_ASSERT_EQUAL(sal_Int64(9144000), asInch.raw());
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(LengthUnitTest);
diff --git a/include/basegfx/units/LengthUnit.hxx b/include/basegfx/units/LengthUnit.hxx
new file mode 100644
index 000000000000..4edd1cc4704f
--- /dev/null
+++ b/include/basegfx/units/LengthUnit.hxx
@@ -0,0 +1,194 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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 <sal/types.h>
+
+namespace gfx
+{
+namespace
+{
+constexpr sal_Int64 constFactor_hmm_to_EMU = 360ll;
+constexpr sal_Int64 constFactor_mm_to_EMU = constFactor_hmm_to_EMU * 100ll;
+constexpr sal_Int64 constFactor_cm_to_EMU = constFactor_hmm_to_EMU * 1000ll;
+constexpr sal_Int64 constFactor_m_to_EMU = constFactor_hmm_to_EMU * 100000ll;
+
+constexpr sal_Int64 constFactor_twip_to_EMU = 635ll;
+constexpr sal_Int64 constFactor_in_to_EMU = constFactor_twip_to_EMU * 1440ll;
+constexpr sal_Int64 constFactor_pt_to_EMU = constFactor_twip_to_EMU * 20ll;
+constexpr sal_Int64 constFactor_px_to_EMU = constFactor_twip_to_EMU * 15ll;
+
+} // end anonymous namespace
+
+template <typename T> class LengthUnitBase
+{
+private:
+    // value in EMU units
+    T m_nValue;
+
+    constexpr explicit LengthUnitBase(T nValue)
+        : m_nValue(nValue)
+    {
+    }
+
+public:
+    static constexpr LengthUnitBase cm(T nValue)
+    {
+        return LengthUnitBase(gfx::constFactor_cm_to_EMU * nValue);
+    }
+
+    static constexpr LengthUnitBase mm(T nValue)
+    {
+        return LengthUnitBase(gfx::constFactor_mm_to_EMU * nValue);
+    }
+
+    static constexpr LengthUnitBase hmm(T nValue)
+    {
+        return LengthUnitBase(gfx::constFactor_hmm_to_EMU * nValue);
+    }
+
+    static constexpr LengthUnitBase in(T nValue)
+    {
+        return LengthUnitBase(gfx::constFactor_in_to_EMU * nValue);
+    }
+
+    static constexpr LengthUnitBase twip(T nValue)
+    {
+        return LengthUnitBase(gfx::constFactor_twip_to_EMU * nValue);
+    }
+
+    static constexpr LengthUnitBase pt(T nValue)
+    {
+        return LengthUnitBase(gfx::constFactor_pt_to_EMU * nValue);
+    }
+
+    static constexpr LengthUnitBase px(T nValue)
+    {
+        return LengthUnitBase(gfx::constFactor_px_to_EMU * nValue);
+    }
+
+    static constexpr LengthUnitBase emu(T nValue) { return LengthUnitBase(nValue); }
+
+    constexpr explicit LengthUnitBase()
+        : m_nValue(0)
+    {
+    }
+
+    constexpr explicit operator T() const { return m_nValue; }
+
+    constexpr LengthUnitBase& operator+=(LengthUnitBase const& rhs)
+    {
+        m_nValue += rhs.m_nValue;
+        return *this;
+    }
+
+    constexpr LengthUnitBase& operator-=(LengthUnitBase const& rhs)
+    {
+        m_nValue -= rhs.m_nValue;
+        return *this;
+    }
+
+    constexpr LengthUnitBase& operator*=(T const& rhs)
+    {
+        m_nValue *= rhs;
+        return *this;
+    }
+
+    constexpr LengthUnitBase& operator/=(T const& rhs)
+    {
+        m_nValue /= rhs;
+        return *this;
+    }
+
+    constexpr LengthUnitBase& operator-()
+    {
+        m_nValue = -m_nValue;
+        return *this;
+    }
+
+    T raw() const { return m_nValue; }
+
+    double as_hmm() const { return m_nValue / double(constFactor_hmm_to_EMU); }
+    double as_mm() const { return m_nValue / double(constFactor_mm_to_EMU); }
+    double as_cm() const { return m_nValue / double(constFactor_cm_to_EMU); }
+    double as_m() const { return m_nValue / double(constFactor_m_to_EMU); }
+    double as_twip() const { return m_nValue / double(constFactor_twip_to_EMU); }
+    double as_in() const { return m_nValue / double(constFactor_in_to_EMU); }
+    double as_pt() const { return m_nValue / double(constFactor_pt_to_EMU); }
+    double as_px() const { return m_nValue / double(constFactor_px_to_EMU); }
+    double as_emu() const { return double(m_nValue); }
+};
+
+template <typename T>
+inline LengthUnitBase<T> operator+(LengthUnitBase<T> lhs, const LengthUnitBase<T>& rhs)
+{
+    return lhs += rhs;
+}
+
+template <typename T>
+inline LengthUnitBase<T> operator-(LengthUnitBase<T> lhs, const LengthUnitBase<T>& rhs)
+{
+    return lhs -= rhs;
+}
+
+template <typename T> inline LengthUnitBase<T> operator*(LengthUnitBase<T> lhs, const long rhs)
+{
+    return lhs *= rhs;
+}
+
+template <typename T> inline LengthUnitBase<T> operator/(LengthUnitBase<T> lhs, const long rhs)
+{
+    return lhs /= rhs;
+}
+
+typedef LengthUnitBase<sal_Int64> LengthUnit;
+typedef LengthUnitBase<double> LengthUnitD;
+
+} // end namespace gfx
+
+constexpr gfx::LengthUnit operator"" _emu(unsigned long long value)
+{
+    return gfx::LengthUnit::emu(value);
+}
+
+constexpr gfx::LengthUnit operator"" _in(unsigned long long value)
+{
+    return gfx::LengthUnit::in(value);
+}
+
+constexpr gfx::LengthUnit operator"" _cm(unsigned long long value)
+{
+    return gfx::LengthUnit::cm(value);
+}
+
+constexpr gfx::LengthUnit operator"" _mm(unsigned long long value)
+{
+    return gfx::LengthUnit::mm(value);
+}
+
+constexpr gfx::LengthUnit operator"" _hmm(unsigned long long value)
+{
+    return gfx::LengthUnit::hmm(value);
+}
+
+constexpr gfx::LengthUnit operator"" _twip(unsigned long long value)
+{
+    return gfx::LengthUnit::twip(value);
+}
+
+constexpr gfx::LengthUnit operator"" _pt(unsigned long long value)
+{
+    return gfx::LengthUnit::pt(value);
+}
+
+constexpr gfx::LengthUnit operator"" _px(unsigned long long value)
+{
+    return gfx::LengthUnit::px(value);
+}


More information about the Libreoffice-commits mailing list