sw/qa/extras/layout/data/tdf166181.fodt | 58 ++++++++++++++++++++++++++++++++ sw/qa/extras/layout/layout5.cxx | 22 ++++++++++++ sw/source/core/layout/tabfrm.cxx | 12 ++++-- 3 files changed, 89 insertions(+), 3 deletions(-)
New commits: commit 6a074bd78322d8a8ca3eddd5ea4d4edf8f796a80 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Sun Jul 13 22:38:40 2025 +0500 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Mon Jul 14 11:40:05 2025 +0200 tdf#166181: partial revert of 223a51801f0b75ae5036a8bcecc6eb81d99b113e A newly created follow row frame for a split row would be passed into lcl_GetHeightOfRows with Y position of 0, while the next row frames would have Y positions from their previous placement (below the last row frame kept on the previous page). Thus we can't use a difference between top ot first row and bottom of last row to get sum of heights. Change-Id: Ia96cd3ec488a6c3e6fb768fb1346bc8d61696118 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/187818 Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> Tested-by: Jenkins diff --git a/sw/qa/extras/layout/data/tdf166181.fodt b/sw/qa/extras/layout/data/tdf166181.fodt new file mode 100644 index 000000000000..2da431f4918f --- /dev/null +++ b/sw/qa/extras/layout/data/tdf166181.fodt @@ -0,0 +1,58 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" office:version="1.4" office:mimetype="application/vnd.oasis.opendocument.text"> + <office:styles> + <style:default-style style:family="table"> + <style:table-properties table:border-model="collapsing"/> + </style:default-style> + <style:default-style style:family="table-row"> + <style:table-row-properties fo:keep-together="auto"/> + </style:default-style> + </office:styles> + <office:automatic-styles> + <style:style style:name="Table1" style:family="table"> + <style:table-properties style:width="170mm" table:align="margins"/> + </style:style> + <style:style style:name="Table1.1" style:family="table-row"> + <style:table-row-properties style:min-row-height="248mm"/> + </style:style> + <style:style style:name="Table1.A1" style:family="table-cell"> + <style:table-cell-properties fo:padding="1mm" fo:border="0.5pt solid #000000"/> + </style:style> + <style:page-layout style:name="pm1"> + <style:page-layout-properties fo:page-width="210mm" fo:page-height="297mm" style:print-orientation="portrait" fo:margin-top="2cm" fo:margin-bottom="2cm" fo:margin-left="2cm" fo:margin-right="2cm"/> + </style:page-layout> + </office:automatic-styles> + <office:master-styles> + <style:master-page style:name="Standard" style:page-layout-name="pm1"/> + </office:master-styles> + <office:body> + <office:text> + <table:table table:name="Table1" table:style-name="Table1"> + <table:table-column/> + <table:table-column/> + <table:table-row table:style-name="Table1.1"> + <table:table-cell table:style-name="Table1.A1" table:number-columns-spanned="2" office:value-type="string"> + <text:p>A1</text:p> + </table:table-cell> + <table:covered-table-cell/> + </table:table-row> + <table:table-row> + <table:table-cell table:style-name="Table1.A1" table:number-rows-spanned="2" office:value-type="string"> + <text:p>A2 (merged cell)</text:p> + </table:table-cell> + <table:table-cell table:style-name="Table1.A1" office:value-type="string"> + <text:p>B2</text:p> + </table:table-cell> + </table:table-row> + <table:table-row> + <table:covered-table-cell table:style-name="Table1.A1"/> + <table:table-cell table:style-name="Table1.A1" office:value-type="string"> + <text:p>B3</text:p> + </table:table-cell> + </table:table-row> + </table:table> + <text:p/> + </office:text> + </office:body> +</office:document> \ No newline at end of file diff --git a/sw/qa/extras/layout/layout5.cxx b/sw/qa/extras/layout/layout5.cxx index de3df0d3b1d7..f103796a9cdd 100644 --- a/sw/qa/extras/layout/layout5.cxx +++ b/sw/qa/extras/layout/layout5.cxx @@ -1809,6 +1809,28 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter5, testTdf166978) u"A2: this row suddenly jumps to the next page"); } +CPPUNIT_TEST_FIXTURE(SwLayoutWriter5, testTdf166181) +{ + // Given a document with a table with a merged cell, which gets split across pages: + createSwDoc("tdf166181.fodt"); + CPPUNIT_ASSERT_EQUAL(2, getPages()); + + // Make sure that the follow cell has the correct height + auto pXmlDoc = parseLayoutDump(); + assertXPath(pXmlDoc, "//page", 2); + assertXPath(pXmlDoc, "//page[2]/body/tab", 1); + assertXPath(pXmlDoc, "//page[2]/body/tab/row", 2); + assertXPath(pXmlDoc, "//page[2]/body/tab/row[1]/infos/bounds", "height", u"0"); + // Check that the first cell of the row is a follow (it has a precede) + (void)getXPath(pXmlDoc, "//page[2]/body/tab/row[1]/cell[1]", "precede"); + // Check that it is merged + assertXPath(pXmlDoc, "//page[2]/body/tab/row[1]/cell[1]", "rowspan", u"2"); + // Get cell height + OUString height = getXPath(pXmlDoc, "//page[2]/body/tab/row[1]/cell[1]/infos/bounds", "height"); + // Without a fix, this was greater than 16000; it is expected around 400 + CPPUNIT_ASSERT_LESS(sal_Int32(500), height.toInt32()); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/layout/tabfrm.cxx b/sw/source/core/layout/tabfrm.cxx index 31d778f06692..003b528dcbd7 100644 --- a/sw/source/core/layout/tabfrm.cxx +++ b/sw/source/core/layout/tabfrm.cxx @@ -227,15 +227,21 @@ static SwTwips lcl_GetHeightOfRows( const SwFrame* pStart, tools::Long nCount ) if ( !nCount || !pStart) return 0; + // There are moments when some rows have correct size, but wrong position: e.g., when a merged + // cell is split, the 0-height follow of the previous row is inserted, and arrives here with a + // correct height, but positioned at [0, 0]; the following rows have correct position (offset + // to the new page's starting Y coordinate). This disallows to simplify the height calculation + // to just difference between top row's top and bottom row's bottom. + SwTwips nRet = 0; SwRectFnSet aRectFnSet(pStart); - SwTwips nTop = aRectFnSet.GetTop(pStart->getFrameArea()); - while (pStart->GetNext() && nCount > 1) + while (pStart && nCount > 0) { + nRet += aRectFnSet.GetHeight(pStart->getFrameArea()); pStart = pStart->GetNext(); --nCount; } - return -aRectFnSet.BottomDist(pStart->getFrameArea(), nTop); + return nRet; } // Local helper function to insert a new follow flow line