sw/qa/core/layout/data/split-table-merged-border.odt |binary sw/qa/core/layout/paintfrm.cxx | 49 +++++++++++++++++++ sw/source/core/layout/paintfrm.cxx | 24 +++++---- 3 files changed, 63 insertions(+), 10 deletions(-)
New commits: commit 7a1b3f58080b301929269c0b4a5310851a0ee2bb Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Wed Nov 15 08:24:39 2023 +0100 Commit: Xisco Fauli <xiscofa...@libreoffice.org> CommitDate: Thu Nov 30 10:25:18 2023 +0100 tdf#157911 sw floattable: fix inconsistent inferred bottom border on split The bugdoc has a split table between page 1 and page 2. The last row of page 1 has a half bottom border: it starts on the left of the table, but finishes earlier than the right of the table. This is since commit 08aea5526c75ff4c5385e960bd940f10ffa19cd5 (tdf#156351 sw floattable: fix missing bottom border in master table, 2023-08-21). The trouble is that Writer table borders are really at a cell-level (and not at row or table level), the current partial border happens because the first row has merged cells and the last row on page 1 doesn't have merged cells, so the layout can't do a 1:1 mapping between the first row and last row cells. It's also far from clear if the fixed result should be no bottom border or a table-width bottom border: - Word documents can have cell-level borders (where no inferred border is wanted) and table-level borders (where inferred borders are wanted), see the tdf#156351 bugdoc for a case where such inferring is wanted - In case only cell-level borders are defined, then Word doesn't do such inferring Fix the problem by always inferring such borders, because: - Writer already did this in some cases for a long time, see commit a4da71fb824f2d4ecc7c01f4deb2865ba52f5f4c (INTEGRATION: CWS fmebugs04 (1.115.46); FILE MERGED 2008/05/13 13:56:19 fme 1.115.46.2: #i9860# Top border for tables - correction 2008/05/13 13:49:23 fme 1.115.46.1: #i9860# Top border for tables, 2008-06-06) - The Word UI creates table borders by default, so the majority of the DOCX documents also want this inferring An alternative could be to only do such inferring for Word documents with a compat flag, but that looks poor, given that Word doesn't always do such inferring itself, either. Change-Id: I052e4591e99d066c3109e8ab8b590e97c8aebd36 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159429 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Jenkins (cherry picked from commit 47d824dd167eb34b08e5aec7141d2d9e6e996b34) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159588 Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org> diff --git a/sw/qa/core/layout/data/split-table-merged-border.odt b/sw/qa/core/layout/data/split-table-merged-border.odt new file mode 100644 index 000000000000..122bfd473c7c Binary files /dev/null and b/sw/qa/core/layout/data/split-table-merged-border.odt differ diff --git a/sw/qa/core/layout/paintfrm.cxx b/sw/qa/core/layout/paintfrm.cxx index ad09405fe3fb..baa858020acf 100644 --- a/sw/qa/core/layout/paintfrm.cxx +++ b/sw/qa/core/layout/paintfrm.cxx @@ -109,6 +109,55 @@ CPPUNIT_TEST_FIXTURE(Test, testRTLBorderMerge) // i.e. the 2nd and 5th vertical border was missing. CPPUNIT_ASSERT_EQUAL(6, nVerticalBorders); } + +CPPUNIT_TEST_FIXTURE(Test, testSplitTableMergedBorder) +{ + // Given a document with a split table, first row in frame 1 has merged cells: + createSwDoc("split-table-merged-border.odt"); + SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get()); + SwDocShell* pShell = pTextDoc->GetDocShell(); + + // When rendering that document: + std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile(); + + // Then make sure that the master table has a bottom border with the correct widths: + MetafileXmlDump aDumper; + xmlDocUniquePtr pXmlDoc = dumpAndParse(aDumper, *xMetaFile); + xmlXPathObjectPtr pXmlObj = getXPathNode(pXmlDoc, "//polyline[@style='solid']/point"); + xmlNodeSetPtr pXmlNodes = pXmlObj->nodesetval; + std::set<int> aHorizontalBorderStarts; + std::set<int> aHorizontalBorderEnds; + // Collect the horizontal borders: + for (int i = 0; i < xmlXPathNodeSetGetLength(pXmlNodes); i += 2) + { + xmlNodePtr pStart = pXmlNodes->nodeTab[i]; + xmlNodePtr pEnd = pXmlNodes->nodeTab[i + 1]; + xmlChar* pStartY = xmlGetProp(pStart, BAD_CAST("y")); + xmlChar* pEndY = xmlGetProp(pEnd, BAD_CAST("y")); + sal_Int32 nStartY = o3tl::toInt32(reinterpret_cast<char const*>(pStartY)); + sal_Int32 nEndY = o3tl::toInt32(reinterpret_cast<char const*>(pEndY)); + if (nStartY != nEndY) + { + // Vertical border. + continue; + } + + xmlChar* pStartX = xmlGetProp(pStart, BAD_CAST("x")); + xmlChar* pEndX = xmlGetProp(pEnd, BAD_CAST("x")); + sal_Int32 nStartX = o3tl::toInt32(reinterpret_cast<char const*>(pStartX)); + sal_Int32 nEndX = o3tl::toInt32(reinterpret_cast<char const*>(pEndX)); + aHorizontalBorderStarts.insert(nStartX); + aHorizontalBorderEnds.insert(nEndX); + } + xmlXPathFreeObject(pXmlObj); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), aHorizontalBorderStarts.size()); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 2 + // - Actual : 3 + // i.e. the frame 1 bottom border ended sooner than expected, resulting in a buggy, partial + // bottom border. + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), aHorizontalBorderEnds.size()); +} } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/layout/paintfrm.cxx b/sw/source/core/layout/paintfrm.cxx index 8242a99634f2..a23d86d1181c 100644 --- a/sw/source/core/layout/paintfrm.cxx +++ b/sw/source/core/layout/paintfrm.cxx @@ -2902,19 +2902,21 @@ void SwTabFramePainter::InsertFollowTopBorder(const SwFrame& rFrame, const SvxBo } const SwFrame* pLastCell = pLastRow->GetLower(); + if (!pLastCell) + { + return; + } + for (int i = 0; i < nCol; ++i) { - if (!pLastCell) + if (!pLastCell->GetNext()) { + // Reference row has merged cells, work with the last possible one. break; } pLastCell = pLastCell->GetNext(); } - if (!pLastCell) - { - return; - } SwBorderAttrAccess aAccess(SwFrame::GetCache(), pLastCell); const SwBorderAttrs& rAttrs = *aAccess.Get(); @@ -2975,19 +2977,21 @@ void SwTabFramePainter::InsertMasterBottomBorder(const SwFrame& rFrame, const Sv } const SwFrame* pFirstCell = pFirstRow->GetLower(); + if (!pFirstCell) + { + return; + } + for (int i = 0; i < nCol; ++i) { - if (!pFirstCell) + if (!pFirstCell->GetNext()) { + // Reference row has merged cells, work with the last possible one. break; } pFirstCell = pFirstCell->GetNext(); } - if (!pFirstCell) - { - return; - } SwBorderAttrAccess aAccess(SwFrame::GetCache(), pFirstCell); const SwBorderAttrs& rAttrs = *aAccess.Get();