summaryrefslogtreecommitdiff
path: root/sw
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2023-08-18 11:21:25 +0200
committerMiklos Vajna <vmiklos@collabora.com>2023-08-18 14:52:56 +0200
commit53798fef2cc0b5b0b9706081a4af5ceca964a41b (patch)
tree45cbad82094101892fd6fd5b91cead262f8da416 /sw
parentc8bbabd64ca642b8e9dec5cc6479177315be1210 (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.mk1
-rw-r--r--sw/qa/core/layout/data/split-table-border.odtbin0 -> 13057 bytes
-rw-r--r--sw/qa/core/layout/paintfrm.cxx71
-rw-r--r--sw/source/core/layout/paintfrm.cxx80
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
new file mode 100644
index 000000000000..743d54bd38c5
--- /dev/null
+++ b/sw/qa/core/layout/data/split-table-border.odt
Binary files differ
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 )