diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2023-07-14 08:28:32 +0200 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2023-07-14 11:00:30 +0200 |
commit | 8bd30999098567b3bdb84a6ca65c071952192932 (patch) | |
tree | a50f28fd9ab4cb4a37ffb3de3b8e3d4fdd91770b /sw | |
parent | 46d7119b8be03968017e59d882e5671350304e15 (diff) |
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 <vmiklos@collabora.com>
Tested-by: Jenkins
Diffstat (limited to 'sw')
-rw-r--r-- | sw/CppunitTest_sw_core_text.mk | 1 | ||||
-rw-r--r-- | sw/qa/core/text/data/floattable-wrap-empty-para.docx | bin | 0 -> 16195 bytes | |||
-rw-r--r-- | sw/qa/core/text/itrform2.cxx | 59 | ||||
-rw-r--r-- | sw/source/core/text/itrform2.cxx | 13 |
4 files changed, 70 insertions, 3 deletions
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 Binary files differnew file mode 100644 index 000000000000..91e8a141c15a --- /dev/null +++ b/sw/qa/core/text/data/floattable-wrap-empty-para.docx 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. |