diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2023-08-18 11:21:25 +0200 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2023-08-18 14:52:56 +0200 |
commit | 53798fef2cc0b5b0b9706081a4af5ceca964a41b (patch) | |
tree | 45cbad82094101892fd6fd5b91cead262f8da416 /sw | |
parent | c8bbabd64ca642b8e9dec5cc6479177315be1210 (diff) |
Related: tdf#156351 sw floattable: fix missing top border in follow table
The problem was that in case a table has a table border but no cell
border, then the follow table was missing a top border in case the
follow table had multiple rows.
This was already working for single-row follow tables since 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:
i#9860 Top border for tables, 2008-06-06).
Fix the problem by checking for the case when the first row in a follow
table has no own bottom border and then take that bottom border from the
last row instead, if that has a bottom border.
The reported case around the missing bottom border in the master table
still needs work.
Change-Id: Ib418da99067a42efcf3bd0e2d6a9467797de619a
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/155824
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Tested-by: Jenkins
Diffstat (limited to 'sw')
-rw-r--r-- | sw/CppunitTest_sw_core_layout.mk | 1 | ||||
-rw-r--r-- | sw/qa/core/layout/data/split-table-border.odt | bin | 0 -> 13057 bytes | |||
-rw-r--r-- | sw/qa/core/layout/paintfrm.cxx | 71 | ||||
-rw-r--r-- | sw/source/core/layout/paintfrm.cxx | 80 |
4 files changed, 152 insertions, 0 deletions
diff --git a/sw/CppunitTest_sw_core_layout.mk b/sw/CppunitTest_sw_core_layout.mk index be208df04165..9431b6b83526 100644 --- a/sw/CppunitTest_sw_core_layout.mk +++ b/sw/CppunitTest_sw_core_layout.mk @@ -16,6 +16,7 @@ $(eval $(call gb_CppunitTest_use_common_precompiled_header,sw_core_layout)) $(eval $(call gb_CppunitTest_add_exception_objects,sw_core_layout, \ sw/qa/core/layout/flycnt \ sw/qa/core/layout/layout \ + sw/qa/core/layout/paintfrm \ sw/qa/core/layout/tabfrm \ )) diff --git a/sw/qa/core/layout/data/split-table-border.odt b/sw/qa/core/layout/data/split-table-border.odt Binary files differnew file mode 100644 index 000000000000..743d54bd38c5 --- /dev/null +++ b/sw/qa/core/layout/data/split-table-border.odt diff --git a/sw/qa/core/layout/paintfrm.cxx b/sw/qa/core/layout/paintfrm.cxx new file mode 100644 index 000000000000..15b9df6a4fb4 --- /dev/null +++ b/sw/qa/core/layout/paintfrm.cxx @@ -0,0 +1,71 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <swmodeltestbase.hxx> + +#include <o3tl/string_view.hxx> + +#include <docsh.hxx> +#include <unotxdoc.hxx> + +namespace +{ +/// Covers sw/source/core/layout/paintfrm.cxx fixes. +class Test : public SwModelTestBase +{ +public: + Test() + : SwModelTestBase("/sw/qa/core/layout/data/") + { + } +}; + +CPPUNIT_TEST_FIXTURE(Test, testSplitTableBorder) +{ + // Given a document with a split table, table borders are defined, but cell borders are not: + createSwDoc("split-table-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 follow table has a top border: + MetafileXmlDump aDumper; + xmlDocUniquePtr pXmlDoc = dumpAndParse(aDumper, *xMetaFile); + xmlXPathObjectPtr pXmlObj = getXPathNode(pXmlDoc, "//polyline[@style='solid']/point"); + xmlNodeSetPtr pXmlNodes = pXmlObj->nodesetval; + int nHorizontalBorders = 0; + // Count 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; + } + + ++nHorizontalBorders; + } + xmlXPathFreeObject(pXmlObj); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 3 + // - Actual : 2 + // i.e. the top border in the follow table was missing. + CPPUNIT_ASSERT_EQUAL(3, nHorizontalBorders); +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/layout/paintfrm.cxx b/sw/source/core/layout/paintfrm.cxx index e1f6e12827fe..51dabd080b01 100644 --- a/sw/source/core/layout/paintfrm.cxx +++ b/sw/source/core/layout/paintfrm.cxx @@ -2395,6 +2395,12 @@ class SwTabFramePainter void Insert( SwLineEntry&, bool bHori ); void Insert(const SwFrame& rFrame, const SvxBoxItem& rBoxItem, const SwRect &rPaintArea); + + /// Inserts top border at the top of a follow table. + void InsertFollowTopBorder(const SwFrame& rFrame, const SvxBoxItem& rBoxItem, + bool bWordTableCell, SwTwips nTop, SwTwips nLeft, SwTwips nRight, + bool bTopIsOuter); + void HandleFrame(const SwLayoutFrame& rFrame, const SwRect& rPaintArea); void FindStylesForLine( Point&, Point&, @@ -2852,6 +2858,78 @@ static bool lcl_IsLastVisibleCellBeforeHiddenCellAtTheEndOfRow( && pThisRowFrame->GetTabLine()->GetTabBoxes().back() != pThisCell->GetTabBox(); } +void SwTabFramePainter::InsertFollowTopBorder(const SwFrame& rFrame, const SvxBoxItem& rBoxItem, + bool bWordTableCell, SwTwips nTop, SwTwips nLeft, + SwTwips nRight, bool bTopIsOuter) +{ + // 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.GetTable()->GetRowsToRepeat()) + { + return; + } + + if (pThisRow->GetPrev() || rBoxItem.GetTop() || rBoxItem.GetBottom()) + { + return; + } + + // 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) + { + return; + } + + const SwFrame* pLastCell = pLastRow->GetLower(); + for (int i = 0; i < nCol; ++i) + { + if (!pLastCell) + { + break; + } + + pLastCell = pLastCell->GetNext(); + } + if (!pLastCell) + { + return; + } + + SwBorderAttrAccess aAccess(SwFrame::GetCache(), pLastCell); + const SwBorderAttrs& rAttrs = *aAccess.Get(); + const SvxBoxItem& rLastBoxItem = rAttrs.GetBox(); + if (!rLastBoxItem.GetBottom()) + { + return; + } + + // The matching (same column) row in the last row has a bottom border for us. + svx::frame::Style aFollowB(rLastBoxItem.GetBottom(), 1.0); + aFollowB.SetWordTableCell(bWordTableCell); + SwLineEntry aFollowTop(nTop, nLeft, nRight, bTopIsOuter, aFollowB); + aFollowB.SetRefMode(svx::frame::RefMode::Begin); + Insert(aFollowTop, true); +} + void SwTabFramePainter::Insert(const SwFrame& rFrame, const SvxBoxItem& rBoxItem, const SwRect& rPaintArea) { // build 4 line entries for the 4 borders: @@ -2941,6 +3019,8 @@ void SwTabFramePainter::Insert(const SwFrame& rFrame, const SvxBoxItem& rBoxItem Insert( aRight, false ); Insert( aTop, true ); Insert( aBottom, true ); + + InsertFollowTopBorder(rFrame, rBoxItem, bWordTableCell, nTop, nLeft, nRight, bTopIsOuter); } void SwTabFramePainter::Insert( SwLineEntry& rNew, bool bHori ) |