[Libreoffice-commits] core.git: Branch 'distro/collabora/co-2021' - sw/CppunitTest_sw_uwriter.mk sw/inc sw/qa sw/source
LuboÅ¡ LuÅák (via logerrit)
logerrit at kemper.freedesktop.org
Tue Sep 28 11:52:43 UTC 2021
sw/CppunitTest_sw_uwriter.mk | 1
sw/inc/swregion.hxx | 3 -
sw/qa/core/test_region.cxx | 108 +++++++++++++++++++++++++++++++++++++
sw/source/core/bastyp/swregion.cxx | 32 +++-------
sw/source/core/view/viewsh.cxx | 4 -
5 files changed, 124 insertions(+), 24 deletions(-)
New commits:
commit 6fef9f66f924a518b5e8290445d34536ed8c0678
Author: Luboš Luňák <l.lunak at collabora.com>
AuthorDate: Wed Sep 22 16:41:45 2021 +0200
Commit: Luboš Luňák <l.lunak at collabora.com>
CommitDate: Tue Sep 28 13:52:07 2021 +0200
add some unittests for SwRegionRects
And fix two small bugs in SwRegionRects::Compress().
Change-Id: I8df7cc2e9d4d6ca78e3af711639e3fbae2e471ae
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/122462
Tested-by: Jenkins
Reviewed-by: Luboš Luňák <l.lunak at collabora.com>
(cherry picked from commit 362d2271721dd19de7a7f6f2271a349272ce51d8)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/122639
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
diff --git a/sw/CppunitTest_sw_uwriter.mk b/sw/CppunitTest_sw_uwriter.mk
index e6a490c5dff1..6507224393dc 100644
--- a/sw/CppunitTest_sw_uwriter.mk
+++ b/sw/CppunitTest_sw_uwriter.mk
@@ -20,6 +20,7 @@ $(eval $(call gb_CppunitTest_add_exception_objects,sw_uwriter, \
sw/qa/core/test_ToxLinkProcessor \
sw/qa/core/test_ToxTextGenerator \
sw/qa/core/test_ToxMiscTest \
+ sw/qa/core/test_region \
))
$(eval $(call gb_CppunitTest_use_library_objects,sw_uwriter,sw))
diff --git a/sw/inc/swregion.hxx b/sw/inc/swregion.hxx
index 1aa190712a8f..338a30649c7a 100644
--- a/sw/inc/swregion.hxx
+++ b/sw/inc/swregion.hxx
@@ -55,8 +55,9 @@ public:
// Ensures all rectangles are within the origin area.
void LimitToOrigin();
+ enum CompressType { CompressExact, CompressFuzzy };
// Combine adjacent rectangles.
- void Compress();
+ void Compress( CompressType type );
const SwRect &GetOrigin() const { return m_aOrigin; }
void ChangeOrigin( const SwRect &rRect ) { m_aOrigin = rRect; }
diff --git a/sw/qa/core/test_region.cxx b/sw/qa/core/test_region.cxx
new file mode 100644
index 000000000000..15fa398c7e4a
--- /dev/null
+++ b/sw/qa/core/test_region.cxx
@@ -0,0 +1,108 @@
+/* -*- 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 <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <swregion.hxx>
+#include <vcl/region.hxx>
+
+class RegionUnittest : public CppUnit::TestFixture
+{
+public:
+ void testCompress();
+ void testInvert();
+
+ CPPUNIT_TEST_SUITE(RegionUnittest);
+ CPPUNIT_TEST(testCompress);
+ CPPUNIT_TEST(testInvert);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void RegionUnittest::testCompress()
+{
+ SwRegionRects region;
+
+ // All inside each other, check it'll compress them to the largest one.
+ region = SwRegionRects();
+ region += SwRect(Point(10, 10), Size(10, 10));
+ region += SwRect(Point(10, 10), Size(20, 20));
+ region += SwRect(Point(10, 10), Size(100, 100));
+ region += SwRect(Point(10, 10), Size(50, 50));
+ region.Compress(SwRegionRects::CompressExact);
+ CPPUNIT_ASSERT_EQUAL(size_t(1), region.size());
+ CPPUNIT_ASSERT_EQUAL(SwRect(Point(10, 10), Size(100, 100)), region[0]);
+
+ // Check merging of adjacent rectangles. This will merge first two groups
+ // and then those two merged rects only in the next iteration.
+ region = SwRegionRects();
+ region += SwRect(Point(10, 10), Size(10000, 10000));
+ region += SwRect(Point(10010, 10), Size(10000, 10000));
+ region += SwRect(Point(10, 10010), Size(10000, 10000));
+ region += SwRect(Point(10010, 10010), Size(10000, 10000));
+ region.Compress(SwRegionRects::CompressExact);
+ CPPUNIT_ASSERT_EQUAL(size_t(1), region.size());
+ CPPUNIT_ASSERT_EQUAL(SwRect(Point(10, 10), Size(20000, 20000)), region[0]);
+
+ // Check fuzzy compress, two almost aligned rects will be compressed to one.
+ region = SwRegionRects();
+ region += SwRect(Point(10, 10), Size(100, 100));
+ region += SwRect(Point(110, 10), Size(100, 90));
+ region.Compress(SwRegionRects::CompressExact);
+ CPPUNIT_ASSERT_EQUAL(size_t(2), region.size());
+ region.Compress(SwRegionRects::CompressFuzzy);
+ CPPUNIT_ASSERT_EQUAL(size_t(1), region.size());
+ CPPUNIT_ASSERT_EQUAL(SwRect(Point(10, 10), Size(200, 100)), region[0]);
+
+ // Check it doesn't crash because of empty size.
+ region = SwRegionRects();
+ region += SwRect(Point(0, 0), Size(0, 0));
+ region += SwRect(Point(10, 10), Size(0, 0));
+ region += SwRect(Point(100, 100), Size(0, 0));
+ region.Compress(SwRegionRects::CompressExact);
+ region.Compress(SwRegionRects::CompressFuzzy);
+}
+
+void RegionUnittest::testInvert()
+{
+ // Check that punching holes and inverting has the same result as adding up rects.
+ const SwRect fullRect(Point(100, 100), Size(1000, 1000));
+ const SwRect rects[]
+ = { { Point(200, 200), Size(200, 200) },
+ { Point(0, 0), Size(200, 200) }, // this one is intentionally partially out of bounds
+ { Point(700, 760), Size(20, 150) },
+ { Point(100, 300), Size(200, 200) },
+ { Point(100, 800), Size(10, 10) }, // these two partially overlap
+ { Point(105, 805), Size(10, 10) } };
+ SwRegionRects region1(fullRect);
+ for (const SwRect& rect : rects)
+ region1 -= rect;
+ region1.Invert();
+ region1.Compress(SwRegionRects::CompressExact);
+ SwRegionRects region2;
+ region2.ChangeOrigin(fullRect);
+ for (const SwRect& rect : rects)
+ region2 += rect;
+ region2.LimitToOrigin();
+ region2.Compress(SwRegionRects::CompressExact);
+ // The regions should be the same area, but not necessarily the same representation.
+ // SwRegionRects cannot compare those easily, but vcl::Region can.
+ vcl::Region vclRegion1, vclRegion2;
+ for (const SwRect& rect : region1)
+ vclRegion1.Union(tools::Rectangle(rect.Pos(), rect.SSize()));
+ for (const SwRect& rect : region2)
+ vclRegion2.Union(tools::Rectangle(rect.Pos(), rect.SSize()));
+ CPPUNIT_ASSERT_EQUAL(vclRegion1, vclRegion2);
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(RegionUnittest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/bastyp/swregion.cxx b/sw/source/core/bastyp/swregion.cxx
index 06b810c20664..814fab8e779c 100644
--- a/sw/source/core/bastyp/swregion.cxx
+++ b/sw/source/core/bastyp/swregion.cxx
@@ -153,7 +153,7 @@ void SwRegionRects::LimitToOrigin()
}
// combine all adjacent rectangles
-void SwRegionRects::Compress()
+void SwRegionRects::Compress( CompressType type )
{
bool bAgain;
do
@@ -168,8 +168,8 @@ void SwRegionRects::Compress()
// Rectangles are sorted by Y axis, so check only pairs of rectangles
// that are possibly overlapping or adjacent or close enough to be grouped by the fuzzy
// code below.
- const tools::Long nFuzzy = 1361513;
- const tools::Long yMax = (*this)[i].Bottom() + nFuzzy
+ const tools::Long nFuzzy = type == CompressFuzzy ? 1361513 : 0;
+ const tools::Long yMax = (*this)[i].Top() + (*this)[i].Height() + nFuzzy
/ std::max<tools::Long>( 1, (*this)[i].Width());
for(size_type j = i+1; j < size(); ++j)
{
@@ -193,21 +193,12 @@ void SwRegionRects::Compress()
}
else
{
- // TODO: I think the comment below and the code are partially incorrect.
- // An obvious mistake is the comment saying that one rectangle can be deleted,
- // while it's the union that gets used instead of the two rectangles.
- // I think this code is supposed to merge adjacent rectangles (possibly
- // overlapping), and such rectangles can be detected by their merged areas
- // being equal to the area of the union (which is obviously the case if they
- // share one side, and using the nFuzzy extra allow merging also rectangles
- // that do not quite cover the entire union but it's close enough).
- // So another mistake seems to be using '- CalcArea( aInter )',
- // it should be on the other side of the comparison to subtract shared area
- // counted twice. In practice it seems rectangles here do not share areas,
- // so the error is irrelevant.
-
- // If two rectangles have the same area of their union minus the
- // intersection then one of them can be deleted.
+ // Merge adjacent rectangles (possibly overlapping), such rectangles can be
+ // detected by their merged areas being equal to the area of the union
+ // (which is obviously the case if they share one side, and using
+ // the nFuzzy extra allows merging also rectangles that do not quite cover
+ // the entire union but it's close enough).
+
// For combining as much as possible (and for having less single
// paints), the area of the union can be a little bit larger:
// ( 9622 * 141.5 = 1361513 ~= a quarter (1/4) centimeter wider
@@ -216,9 +207,8 @@ void SwRegionRects::Compress()
aUnion.Union( (*this)[j] );
SwRect aInter( (*this)[i] );
aInter.Intersection( (*this)[j] );
- if ( (::CalcArea( (*this)[i] ) +
- ::CalcArea( (*this)[j] ) + nFuzzy) >=
- (::CalcArea( aUnion ) - CalcArea( aInter )) )
+ if ( CalcArea( (*this)[i] ) + CalcArea( (*this)[j] ) - CalcArea( aInter )
+ + nFuzzy >= CalcArea( aUnion ) )
{
(*this)[i] = aUnion;
(*this)[j].Width(0);
diff --git a/sw/source/core/view/viewsh.cxx b/sw/source/core/view/viewsh.cxx
index 7e0fe1980006..f981c2a193db 100644
--- a/sw/source/core/view/viewsh.cxx
+++ b/sw/source/core/view/viewsh.cxx
@@ -328,7 +328,7 @@ void SwViewShell::ImplEndAction( const bool bIdleEnd )
SwRootFrame* pCurrentLayout = GetLayout();
pRegion->LimitToOrigin();
- pRegion->Compress();
+ pRegion->Compress( SwRegionRects::CompressFuzzy );
ScopedVclPtr<VirtualDevice> pVout;
while ( !pRegion->empty() )
@@ -1664,7 +1664,7 @@ bool SwViewShell::CheckInvalidForPaint( const SwRect &rRect )
if ( pRegion )
{
pRegion->LimitToOrigin();
- pRegion->Compress();
+ pRegion->Compress( SwRegionRects::CompressFuzzy );
bRet = false;
if ( !pRegion->empty() )
{
More information about the Libreoffice-commits
mailing list