sw/qa/core/layout/paintfrm.cxx | 10 ++-- sw/source/core/layout/paintfrm.cxx | 80 ++++++++++++++++++++++++++++++++++++- 2 files changed, 85 insertions(+), 5 deletions(-)
New commits: commit 05ece1c965baff19a68e8be19711982256ab0d3d Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Mon Aug 21 08:33:14 2023 +0200 Commit: Caolán McNamara <caolan.mcnam...@collabora.com> CommitDate: Tue Aug 22 18:05:26 2023 +0200 tdf#156351 sw floattable: fix missing bottom border in master table The problem was that the bugdoc has a split floating table, and the bottom of the table on the first page was missing its border. The borders on the second page were correct. This happens because the cell itself has no bottom border and the layout did not extra effort to mirror the top table margin at the buttom, like Word does. Fix the problem similar to commit 53798fef2cc0b5b0b9706081a4af5ceca964a41b (Related: tdf#156351 sw floattable: fix missing top border in follow table, 2023-08-18), so we add a bottom border for master tables at a layout level, similar how a top border was already added for follow tables. Given that this kind of worked already in the past (just top borders, just the 1 row case), do this unconditionally; but if needed this could be limited to the "Word table cell" case. (cherry picked from commit 08aea5526c75ff4c5385e960bd940f10ffa19cd5) Change-Id: Iafdcd90226fdc425be597d36ad97fb69dca5a89a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/155934 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> diff --git a/sw/qa/core/layout/paintfrm.cxx b/sw/qa/core/layout/paintfrm.cxx index 15b9df6a4fb4..2416c6b95f8c 100644 --- a/sw/qa/core/layout/paintfrm.cxx +++ b/sw/qa/core/layout/paintfrm.cxx @@ -36,7 +36,8 @@ CPPUNIT_TEST_FIXTURE(Test, testSplitTableBorder) // When rendering that document: std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile(); - // Then make sure that the follow table has a top border: + // Then make sure that the master table has a bottom border and the follow table has a top + // border: MetafileXmlDump aDumper; xmlDocUniquePtr pXmlDoc = dumpAndParse(aDumper, *xMetaFile); xmlXPathObjectPtr pXmlObj = getXPathNode(pXmlDoc, "//polyline[@style='solid']/point"); @@ -61,10 +62,11 @@ CPPUNIT_TEST_FIXTURE(Test, testSplitTableBorder) } xmlXPathFreeObject(pXmlObj); // Without the accompanying fix in place, this test would have failed with: - // - Expected: 3 + // - Expected: 4 // - Actual : 2 - // i.e. the top border in the follow table was missing. - CPPUNIT_ASSERT_EQUAL(3, nHorizontalBorders); + // i.e. the bottom border in the master table and the top border in the follow table were + // missing. + CPPUNIT_ASSERT_EQUAL(4, nHorizontalBorders); } } diff --git a/sw/source/core/layout/paintfrm.cxx b/sw/source/core/layout/paintfrm.cxx index 211a539b8c8f..ac9389e03277 100644 --- a/sw/source/core/layout/paintfrm.cxx +++ b/sw/source/core/layout/paintfrm.cxx @@ -2394,6 +2394,9 @@ class SwTabFramePainter void InsertFollowTopBorder(const SwFrame& rFrame, const SvxBoxItem& rBoxItem, bool bWordTableCell, SwTwips nTop, SwTwips nLeft, SwTwips nRight, bool bTopIsOuter); + void InsertMasterBottomBorder(const SwFrame& rFrame, const SvxBoxItem& rBoxItem, + bool bWordTableCell, SwTwips nBottom, SwTwips nLeft, SwTwips nRight, + bool bBottomIsOuter); void HandleFrame(const SwLayoutFrame& rFrame, const SwRect& rPaintArea); void FindStylesForLine( Point&, @@ -2866,7 +2869,7 @@ void SwTabFramePainter::InsertFollowTopBorder(const SwFrame& rFrame, const SvxBo // This is then a first row in a follow table, without repeated headlines. auto pLastRow = dynamic_cast<const SwRowFrame*>(mrTabFrame.GetLastLower()); - if (!pLastRow && pLastRow == pThisRow) + if (!pLastRow || pLastRow == pThisRow) { return; } @@ -2902,6 +2905,79 @@ void SwTabFramePainter::InsertFollowTopBorder(const SwFrame& rFrame, const SvxBo Insert(aFollowTop, true); } +void SwTabFramePainter::InsertMasterBottomBorder(const SwFrame& rFrame, const SvxBoxItem& rBoxItem, + bool bWordTableCell, SwTwips nBottom, SwTwips nLeft, + SwTwips nRight, bool bBottomIsOuter) +{ + // Figure out which cell to copy. + int nCol = 0; + const SwFrame* pCell = &rFrame; + while (pCell) + { + if (!pCell->GetPrev()) + { + break; + } + + ++nCol; + pCell = pCell->GetPrev(); + } + + auto pThisRow = dynamic_cast<const SwRowFrame*>(rFrame.GetUpper()); + if (!pThisRow || pThisRow->GetUpper() != &mrTabFrame) + { + return; + } + + if (mrTabFrame.IsFollow() || !mrTabFrame.GetFollow()) + { + return; + } + + // This is a master table that is split. + if (pThisRow->GetNext() || rBoxItem.GetTop() || rBoxItem.GetBottom()) + { + return; + } + + // This is then a last row in a master table. + auto pFirstRow = dynamic_cast<const SwRowFrame*>(mrTabFrame.GetLower()); + if (!pFirstRow || pFirstRow == pThisRow) + { + return; + } + + const SwFrame* pFirstCell = pFirstRow->GetLower(); + for (int i = 0; i < nCol; ++i) + { + if (!pFirstCell) + { + break; + } + + pFirstCell = pFirstCell->GetNext(); + } + if (!pFirstCell) + { + return; + } + + SwBorderAttrAccess aAccess(SwFrame::GetCache(), pFirstCell); + const SwBorderAttrs& rAttrs = *aAccess.Get(); + const SvxBoxItem& rFirstBoxItem = rAttrs.GetBox(); + if (!rFirstBoxItem.GetTop()) + { + return; + } + + // The matching (same column) row in the first row has a top border for us. + svx::frame::Style aMasterT(rFirstBoxItem.GetTop(), 1.0); + aMasterT.SetWordTableCell(bWordTableCell); + SwLineEntry aMasterBottom(nBottom, nLeft, nRight, bBottomIsOuter, aMasterT); + aMasterT.SetRefMode(svx::frame::RefMode::Begin); + Insert(aMasterBottom, true); +} + void SwTabFramePainter::Insert(const SwFrame& rFrame, const SvxBoxItem& rBoxItem, const SwRect& rPaintArea) { // build 4 line entries for the 4 borders: @@ -2989,6 +3065,8 @@ void SwTabFramePainter::Insert(const SwFrame& rFrame, const SvxBoxItem& rBoxItem Insert( aTop, true ); Insert( aBottom, true ); + InsertMasterBottomBorder(rFrame, rBoxItem, bWordTableCell, nBottom, nLeft, nRight, + bBottomIsOuter); InsertFollowTopBorder(rFrame, rBoxItem, bWordTableCell, nTop, nLeft, nRight, bTopIsOuter); }