sw/qa/writerfilter/dmapper/DomainMapperTableHandler.cxx | 31 +++++++ sw/qa/writerfilter/dmapper/data/floattable-hidemark.docx |binary sw/source/writerfilter/dmapper/DomainMapperTableHandler.cxx | 53 ++++++++++++ 3 files changed, 84 insertions(+)
New commits: commit c14c8c7f275a351e16169aa01b5eff4e5be5ab2a Author: Miklos Vajna <[email protected]> AuthorDate: Thu Oct 16 09:07:25 2025 +0200 Commit: Caolán McNamara <[email protected]> CommitDate: Thu Oct 16 11:58:02 2025 +0200 tdf#162730 sw floattable: fix when inside an inline table, with hide mark Open the bugdoc, it has an outer inline table, then an inner floating table. The inner table is split, but both parts of it stay on page 1, leading to overlapping text. This document's outer table has a single row and a single cell, but the cell has a <w:hideMark> property. If that's missing, the inner floating table is split properly. Fix the problem by ignoring <w:hideMark> in case the cell's only content is a floating table: in this case setting the row's size type to "fix" would not be correct anyway. Regression from commit 2d43c34333076fad092f0cdc0f60f81580acdbee (Related: tdf#55160 sw floattable, nested DOCX imp: fix inner tbl at cell start, 2023-09-15). Change-Id: Ia9759a1c8ebaaa22b547a5ff250fa9dcf7ffbe4a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/192474 Tested-by: Caolán McNamara <[email protected]> Reviewed-by: Caolán McNamara <[email protected]> Tested-by: Jenkins CollaboraOffice <[email protected]> diff --git a/sw/qa/writerfilter/dmapper/DomainMapperTableHandler.cxx b/sw/qa/writerfilter/dmapper/DomainMapperTableHandler.cxx index e36ae88a7728..d023c30e08f1 100644 --- a/sw/qa/writerfilter/dmapper/DomainMapperTableHandler.cxx +++ b/sw/qa/writerfilter/dmapper/DomainMapperTableHandler.cxx @@ -23,6 +23,10 @@ #include <frmatr.hxx> #include <swtable.hxx> +#include <IDocumentLayoutAccess.hxx> +#include <rootfrm.hxx> +#include <pagefrm.hxx> +#include <sortedobjs.hxx> using namespace ::com::sun::star; @@ -302,6 +306,33 @@ CPPUNIT_TEST_FIXTURE(Test, testDOCXFloatingTableRedline) // i.e. the cell background was white, should be gray. CPPUNIT_ASSERT_EQUAL(Color(0xD0D8E8), rCellBackground.GetColor()); } + +CPPUNIT_TEST_FIXTURE(Test, testDOCXFloatingTableHidemark) +{ + // Given a document with an inline table, then a floating table inside, the outer table's cell + // has "hide mark" set to true: + // When loading the document: + createSwDoc("floattable-hidemark.docx"); + + // Then make sure the resulting layout is correct: + SwDoc* pDoc = getSwDoc(); + SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout(); + SwPageFrame* pPage1 = pLayout->Lower()->DynCastPageFrame(); + CPPUNIT_ASSERT(pPage1); + CPPUNIT_ASSERT(pPage1->GetSortedObjs()); + const SwSortedObjs& rPage1Objs = *pPage1->GetSortedObjs(); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 1 + // - Actual : 2 + // i.e. the follow fly was on page 1, not page 2. + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPage1Objs.size()); + SwPageFrame* pPage2 = pPage1->GetNext()->DynCastPageFrame(); + CPPUNIT_ASSERT(pPage2); + CPPUNIT_ASSERT(pPage2->GetSortedObjs()); + const SwSortedObjs& rPage2Objs = *pPage2->GetSortedObjs(); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPage2Objs.size()); + CPPUNIT_ASSERT(!pPage2->GetNext()); +} } CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sw/qa/writerfilter/dmapper/data/floattable-hidemark.docx b/sw/qa/writerfilter/dmapper/data/floattable-hidemark.docx new file mode 100644 index 000000000000..3fbb6450f707 Binary files /dev/null and b/sw/qa/writerfilter/dmapper/data/floattable-hidemark.docx differ diff --git a/sw/source/writerfilter/dmapper/DomainMapperTableHandler.cxx b/sw/source/writerfilter/dmapper/DomainMapperTableHandler.cxx index 7495442adac9..b4e2174f52dc 100644 --- a/sw/source/writerfilter/dmapper/DomainMapperTableHandler.cxx +++ b/sw/source/writerfilter/dmapper/DomainMapperTableHandler.cxx @@ -979,6 +979,51 @@ static bool lcl_hideMarks(PropertyMapVector1& rCellProperties) return true; } +namespace +{ +/// Assuming rRow has no text in it, checks if any of the empty cells is a floating table anchor. +bool EmptyRowContainsSplitFlysAnchor(const RowSequence_t& rRow) +{ + for (const CellSequence_t& rCell : rRow) + { + uno::Reference<beans::XPropertySet> xCellStart(rCell[0], uno::UNO_QUERY); + if (!xCellStart.is() + || !xCellStart->getPropertySetInfo()->hasPropertyByName(u"TextParagraph"_ustr)) + { + continue; + } + + uno::Reference<container::XContentEnumerationAccess> xCEA( + xCellStart->getPropertyValue(u"TextParagraph"_ustr), uno::UNO_QUERY); + if (!xCEA.is()) + { + continue; + } + + uno::Reference<container::XEnumeration> xEnumeration + = xCEA->createContentEnumeration(u"com.sun.star.text.TextContent"_ustr); + while (xEnumeration->hasMoreElements()) + { + uno::Reference<beans::XPropertySet> xPropertySet(xEnumeration->nextElement(), uno::UNO_QUERY); + if (!xPropertySet.is() + || !xPropertySet->getPropertySetInfo()->hasPropertyByName(u"IsSplitAllowed"_ustr)) + { + continue; + } + + bool bIsSplitAllowed{}; + xPropertySet->getPropertyValue(u"IsSplitAllowed"_ustr) >>= bIsSplitAllowed; + if (bIsSplitAllowed) + { + return true; + } + } + } + + return false; +} +} + /// Are all cells in this row empty? static bool lcl_emptyRow(std::vector<RowSequence_t>& rTableRanges, sal_Int32 nRow) { @@ -1020,6 +1065,14 @@ static bool lcl_emptyRow(std::vector<RowSequence_t>& rTableRanges, sal_Int32 nRo TOOLS_WARN_EXCEPTION( "writerfilter.dmapper", "compareRegionStarts() failed"); return false; } + + if (EmptyRowContainsSplitFlysAnchor(rRowSeq)) + { + // Not really empty: handle as if it would have text, otherwise the anchored floating table + // is not laid out correctly. + return false; + } + return true; }
