sw/CppunitTest_sw_core_layout.mk              |    1 
 sw/qa/core/layout/data/split-table-border.odt |binary
 sw/qa/core/layout/paintfrm.cxx                |   71 +++++++++++++++++++++++
 sw/source/core/layout/paintfrm.cxx            |   80 ++++++++++++++++++++++++++
 4 files changed, 152 insertions(+)

New commits:
commit 4650100548eae49978a40200313182ca7d2706f1
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Fri Aug 18 11:21:25 2023 +0200
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Tue Aug 22 18:04:46 2023 +0200

    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.
    
    (cherry picked from commit 53798fef2cc0b5b0b9706081a4af5ceca964a41b)
    
    Conflicts:
            sw/CppunitTest_sw_core_layout.mk
            sw/source/core/layout/paintfrm.cxx
    
    Change-Id: Ib418da99067a42efcf3bd0e2d6a9467797de619a
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/155885
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Tested-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

diff --git a/sw/CppunitTest_sw_core_layout.mk b/sw/CppunitTest_sw_core_layout.mk
index 1a7aeb649887..f360033d3378 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 \
 ))
 
 $(eval $(call gb_CppunitTest_use_libraries,sw_core_layout, \
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
Binary files /dev/null and b/sw/qa/core/layout/data/split-table-border.odt 
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 405f3888d3eb..211a539b8c8f 100644
--- a/sw/source/core/layout/paintfrm.cxx
+++ b/sw/source/core/layout/paintfrm.cxx
@@ -2389,6 +2389,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&,
@@ -2824,6 +2830,78 @@ static bool 
lcl_IsFirstRowInFollowTableWithoutRepeatedHeadlines(
         && rBoxItem.GetBottom());
 }
 
+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:
@@ -2910,6 +2988,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 )

Reply via email to