sw/CppunitTest_sw_core_text.mk                       |    1 
 sw/qa/core/text/data/floattable-wrap-empty-para.docx |binary
 sw/qa/core/text/itrform2.cxx                         |   59 +++++++++++++++++++
 sw/source/core/text/itrform2.cxx                     |   13 +++-
 4 files changed, 70 insertions(+), 3 deletions(-)

New commits:
commit 8bd30999098567b3bdb84a6ca65c071952192932
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Fri Jul 14 08:28:32 2023 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Fri Jul 14 11:00:30 2023 +0200

    tdf#120262 sw floattable: don't wrap text around fly when no content would 
fit
    
    The document has 2 pages with 2 floating tables, but instead Writer had
    a single page with 2 overlapping floating tables.
    
    What happened is that most of the horizontal space on page 1 was used by
    the floating table, but out of the 10466 twips body width, 11 remained
    (after accounting for the floating table and its margin. Considering
    that the empty paragraph needs no space, the paragraph marker was
    shifted up, next to the floating table, leading to losing page 2 and
    overlapping floating tables.
    
    Fix the problem by checking if the remaining space has some minimal
    size: if it has no space to host any actual content, then shift the
    paragraph marker down (in compat mode), similar to what Word >= 2013
    does.
    
    Note this only fixes the "DOCX, Word >= 2013" version, the original
    bug DOC file still needs more work.
    
    Change-Id: I00864d9b3ae662cdf19fa63e004da1ee1cc7be7c
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/154409
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins

diff --git a/sw/CppunitTest_sw_core_text.mk b/sw/CppunitTest_sw_core_text.mk
index a04824e08e07..477e25b91612 100644
--- a/sw/CppunitTest_sw_core_text.mk
+++ b/sw/CppunitTest_sw_core_text.mk
@@ -16,6 +16,7 @@ $(eval $(call 
gb_CppunitTest_use_common_precompiled_header,sw_core_text))
 $(eval $(call gb_CppunitTest_add_exception_objects,sw_core_text, \
     sw/qa/core/text/frmform \
     sw/qa/core/text/itratr \
+    sw/qa/core/text/itrform2 \
     sw/qa/core/text/text \
 ))
 
diff --git a/sw/qa/core/text/data/floattable-wrap-empty-para.docx 
b/sw/qa/core/text/data/floattable-wrap-empty-para.docx
new file mode 100644
index 000000000000..91e8a141c15a
Binary files /dev/null and 
b/sw/qa/core/text/data/floattable-wrap-empty-para.docx differ
diff --git a/sw/qa/core/text/itrform2.cxx b/sw/qa/core/text/itrform2.cxx
new file mode 100644
index 000000000000..066a8fb331a6
--- /dev/null
+++ b/sw/qa/core/text/itrform2.cxx
@@ -0,0 +1,59 @@
+/* -*- 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 <swmodeltestbase.hxx>
+
+#include <memory>
+
+#include <IDocumentLayoutAccess.hxx>
+#include <rootfrm.hxx>
+#include <sortedobjs.hxx>
+#include <pagefrm.hxx>
+
+namespace
+{
+/// Covers sw/source/core/text/itrform2.cxx fixes.
+class Test : public SwModelTestBase
+{
+public:
+    Test()
+        : SwModelTestBase("/sw/qa/core/text/data/")
+    {
+    }
+};
+
+CPPUNIT_TEST_FIXTURE(Test, testFloattableWrapEmptyParagraph)
+{
+    // Given a document with 2 pages, a floating table on both pages:
+    createSwDoc("floattable-wrap-empty-para.docx");
+
+    // When calculating the layout:
+    calcLayout();
+
+    // Then make sure that each page has exactly 1 floating table:
+    SwDoc* pDoc = getSwDoc();
+    SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
+    auto pPage = dynamic_cast<SwPageFrame*>(pLayout->Lower());
+    CPPUNIT_ASSERT(pPage);
+    CPPUNIT_ASSERT(pPage->GetSortedObjs());
+    const SwSortedObjs& rPageObjs = *pPage->GetSortedObjs();
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: 1
+    // - Actual  : 2
+    // i.e. both tables were on page 1, leading to an overlap.
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPageObjs.size());
+    auto pPage2 = dynamic_cast<SwPageFrame*>(pPage->GetNext());
+    CPPUNIT_ASSERT(pPage2);
+    CPPUNIT_ASSERT(pPage2->GetSortedObjs());
+    const SwSortedObjs& rPageObjs2 = *pPage2->GetSortedObjs();
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPageObjs2.size());
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/itrform2.cxx b/sw/source/core/text/itrform2.cxx
index 51c3a49f2062..5895825bf668 100644
--- a/sw/source/core/text/itrform2.cxx
+++ b/sw/source/core/text/itrform2.cxx
@@ -2714,11 +2714,11 @@ void SwTextFormatter::CalcFlyWidth( SwTextFormatInfo 
&rInf )
     SwRect aLine( rInf.X() + nLeftMin, nTop, rInf.RealWidth() - rInf.X()
                   + nLeftMar - nLeftMin , nHeight );
 
+    bool bWordFlyWrap = 
GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(DocumentSettingId::ADD_VERTICAL_FLY_OFFSETS);
     // tdf#116486: consider also the upper margin from getFramePrintArea 
because intersections
     //             with this additional space should lead to repositioning of 
paragraphs
     //             For compatibility we grab a related compat flag:
-    if 
(GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(DocumentSettingId::ADD_VERTICAL_FLY_OFFSETS)
-        && IsFirstTextLine())
+    if (bWordFlyWrap && IsFirstTextLine())
     {
         tools::Long nUpper = m_pFrame->getFramePrintArea().Top();
         // Make sure that increase only happens in case the upper spacing 
comes from the upper
@@ -2800,8 +2800,15 @@ void SwTextFormatter::CalcFlyWidth( SwTextFormatInfo 
&rInf )
     if( !aInter.HasArea() )
         return;
 
-    const bool bFullLine =  aLine.Left()  == aInter.Left() &&
+    bool bFullLine =  aLine.Left()  == aInter.Left() &&
                             aLine.Right() == aInter.Right();
+    if (!bFullLine && bWordFlyWrap)
+    {
+        // Word >= 2013 style: if there is minimal space remaining, then 
handle that similar to a
+        // full line and put the actual empty paragraph below the fly.
+        bFullLine = std::abs(aLine.Left() - aInter.Left()) < MINLAY
+                    && std::abs(aLine.Right() - aInter.Right()) < MINLAY;
+    }
 
     // Although no text is left, we need to format another line,
     // because also empty lines need to avoid a Fly with no wrapping.

Reply via email to