sw/qa/writerfilter/ooxml/data/table-wafter-row-height.docx |binary sw/qa/writerfilter/ooxml/ooxml.cxx | 24 ++++++++++ sw/source/writerfilter/ooxml/OOXMLFastContextHandler.cxx | 30 +++++++++++++ 3 files changed, 54 insertions(+)
New commits: commit d6e01cbebef37c713b5514022c9fa9f3f3c99abe Author: Miklos Vajna <[email protected]> AuthorDate: Fri Oct 31 09:50:41 2025 +0100 Commit: Caolán McNamara <[email protected]> CommitDate: Fri Oct 31 11:12:52 2025 +0100 tdf#168916 DOCX import, <w:wAfter>: make dummy paragraph less visible Load the bugdoc, Writer layout thinks there are floating tables here that need splitting, then layout fails to do that and it hangs: warn:legacy.osl:17593:17593:sw/source/core/layout/tabfrm.cxx:3365: debug assertion: <SwTabFrame::MakeAll()> - format of table lowers suppressed by fix i44910 Checking what would be the expected output here, it turns out no actual splitting is happening in Word, but Writer thinks the table won't fit the page. This happens because the table row has a "wAfter" (spacing after last cell), and Writer uses an empty paragraph in that cell, using the default paragraph style (non-zero paragraph spacing, larger font size); while Word simply has no content in such a "fake cell". Fix the problem similar to what we already do for floating table anchor paragraphs in commit 86b0957cf18ea6705c8afa09bf4aae1fbb7db22e (tdf#167379 sw floattable: make dummy paragraph from DOCX import less visible, 2025-07-10), where we have the same problem that we want the empty paragraph to take ~no layout space. Once the table row has the correct height, Writer doesn't attempt to split the floating table, so it can't go wrong. Change-Id: I7fb2b859e72e5ec1b4b54d46c191ebfc5e8fcaa0 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/193244 Tested-by: Jenkins CollaboraOffice <[email protected]> Tested-by: Caolán McNamara <[email protected]> Reviewed-by: Caolán McNamara <[email protected]> diff --git a/sw/qa/writerfilter/ooxml/data/table-wafter-row-height.docx b/sw/qa/writerfilter/ooxml/data/table-wafter-row-height.docx new file mode 100644 index 000000000000..98f7b218d6bd Binary files /dev/null and b/sw/qa/writerfilter/ooxml/data/table-wafter-row-height.docx differ diff --git a/sw/qa/writerfilter/ooxml/ooxml.cxx b/sw/qa/writerfilter/ooxml/ooxml.cxx index 9a9d2745ba7c..7ef1d48cbab1 100644 --- a/sw/qa/writerfilter/ooxml/ooxml.cxx +++ b/sw/qa/writerfilter/ooxml/ooxml.cxx @@ -25,6 +25,7 @@ #include <sortedobjs.hxx> #include <anchoredobject.hxx> #include <flyfrm.hxx> +#include <tabfrm.hxx> using namespace ::com::sun::star; @@ -146,6 +147,29 @@ CPPUNIT_TEST_FIXTURE(Test, testFloatingTableAnchorPos) // i.e. the vertical position of D was too big. CPPUNIT_ASSERT_LESSEQUAL(static_cast<SwTwips>(1), nDiff); } + +CPPUNIT_TEST_FIXTURE(Test, testTableWafterRowHeight) +{ + // Given a document with a table, 2 rows, 2nd row's height is 12pt: + // When laying out that document: + createSwDoc("table-wafter-row-height.docx"); + + // Then make sure that <w:gridAfter> / <w:wAfter> doesn't increase the row height: + SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell(); + SwRootFrame* pLayout = pWrtShell->GetLayout(); + SwPageFrame* pPage = pLayout->GetLower()->DynCastPageFrame(); + auto pBeforeTableFrame = pPage->FindFirstBodyContent()->DynCastTextFrame(); + auto pTabFrame = pBeforeTableFrame->GetNext()->DynCastTabFrame(); + const SwFrame* pRow1Frame = pTabFrame->Lower(); + const SwFrame* pRow2Frame = pRow1Frame->GetNext(); + SwTwips nRow2Height = pRow2Frame->getFrameArea().Height(); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 240 + // - Actual : 580 + // i.e. the row height was too large, should be exactly 12 points (11 points from line spacing, + // 1 point for the border). + CPPUNIT_ASSERT_EQUAL(static_cast<SwTwips>(240), nRow2Height); +} } CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sw/source/writerfilter/ooxml/OOXMLFastContextHandler.cxx b/sw/source/writerfilter/ooxml/OOXMLFastContextHandler.cxx index 0bd68b5d9049..10491799f703 100644 --- a/sw/source/writerfilter/ooxml/OOXMLFastContextHandler.cxx +++ b/sw/source/writerfilter/ooxml/OOXMLFastContextHandler.cxx @@ -1552,6 +1552,36 @@ void OOXMLFastContextHandlerTextTableRow::handleGridBefore( const OOXMLValue& va i < count; ++i ) { + if (isForwardEvents()) + { + // Forwarding events: not just looking through e.g. all footnotes, searching for a + // specific footnote. In this case wBefore/wAfter creates a cell to ensure correct width + // of the other cells in the row. Set the layout size of the empty paragraph to a + // minimum, to make sure this dummy paragraph doesn't increase the row height. + startParagraphGroup(); + { + // <w:spacing w:before="0" w:after="0" w:lineRule="atLeast" w:line="0"> + OOXMLPropertySet::Pointer_t pAttributes(new OOXMLPropertySet); + OOXMLValue pSBVal = OOXMLValue::createInteger(0); + pAttributes->add(NS_ooxml::LN_CT_Spacing_before, pSBVal, OOXMLProperty::ATTRIBUTE); + OOXMLValue pSAVal = OOXMLValue::createInteger(0); + pAttributes->add(NS_ooxml::LN_CT_Spacing_after, pSAVal, OOXMLProperty::ATTRIBUTE); + OOXMLValue pSLRVal = OOXMLValue::createInteger(NS_ooxml::LN_Value_doc_ST_LineSpacingRule_atLeast); + pAttributes->add(NS_ooxml::LN_CT_Spacing_lineRule, pSLRVal, OOXMLProperty::ATTRIBUTE); + OOXMLValue pSLVal = OOXMLValue::createInteger(0); + pAttributes->add(NS_ooxml::LN_CT_Spacing_line, pSLVal, OOXMLProperty::ATTRIBUTE); + OOXMLValue pSprm = OOXMLValue::createPropertySet(pAttributes); + OOXMLPropertySet::Pointer_t pProps(new OOXMLPropertySet); + pProps->add(NS_ooxml::LN_CT_PPrBase_spacing, pSprm, OOXMLProperty::SPRM); + mpStream->props(pProps.get()); + } + // Also set the font size to 1pt, unit is half-points. + OOXMLPropertySet::Pointer_t pProps(new OOXMLPropertySet); + OOXMLValue pSprm = OOXMLValue::createInteger(2); + pProps->add(NS_ooxml::LN_EG_RPrBase_sz, pSprm, OOXMLProperty::SPRM); + mpStream->props(pProps.get()); + } + endOfParagraph(); if (isForwardEvents())
