include/svx/framelinkarray.hxx             |    8 -
 svx/CppunitTest_svx_unit.mk                |    1 
 svx/qa/unit/framelinkarray.cxx             |  196 +++++++++++++++++++++++++++++
 svx/source/dialog/framelinkarray.cxx       |   45 +++---
 svx/source/table/viewcontactoftableobj.cxx |   24 ++-
 vcl/qa/cppunit/pdfexport/pdfexport2.cxx    |    4 
 6 files changed, 248 insertions(+), 30 deletions(-)

New commits:
commit 209eb64b6c45e5301fbef73bfa71fed88171e5df
Author:     Jonathan Clark <jonat...@libreoffice.org>
AuthorDate: Tue Jan 14 11:26:56 2025 -0700
Commit:     Adolfo Jayme Barrientos <fit...@ubuntu.com>
CommitDate: Sat Jan 18 10:27:08 2025 +0100

    tdf#34837 sc: Use border from correct cell for merged cells in RTL
    
    This change fixes a bug causing borders to fail to render for merged
    cells in RTL spreadsheets.
    
    The root cause for this bug was framelinkarray utility code using the
    top-left cell as the source for border styles of merged cells. This use
    was correct for LTR spreadsheets. However, this framelinkarray data is
    mirrored for RTL documents. After mirroring, the correct cell containing
    border styles is the top-right one.
    
    This change also reverts and reimplements a prior fix for tdf#135843
    (commit 586a0f149f332c0b0e53c0bb30568d4bd411b0e3), which violated the
    framelinkarray contract that edge styles for merged cells must be added
    to the top-left underlying cell of a merged cell.
    
    Change-Id: I27eec416d54f9f99cd5df1151a12c758f350c789
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180256
    Tested-by: Jenkins
    Reviewed-by: Jonathan Clark <jonat...@libreoffice.org>
    (cherry picked from commit bf54efbe21d6c6fcb910f7fa3d9f43978dc555c9)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180291
    Reviewed-by: Adolfo Jayme Barrientos <fit...@ubuntu.com>

diff --git a/include/svx/framelinkarray.hxx b/include/svx/framelinkarray.hxx
index 1ddb9b76cbd0..47aa7ec1b9b9 100644
--- a/include/svx/framelinkarray.hxx
+++ b/include/svx/framelinkarray.hxx
@@ -131,28 +131,28 @@ public:
         Returns the style only if visible (i.e. at left border of a merged 
range).
         @return
             The left frame style or an invisible style for invalid cell 
addresses. */
-    SAL_DLLPRIVATE const Style& GetCellStyleLeft( sal_Int32 nCol, sal_Int32 
nRow ) const;
+    const Style& GetCellStyleLeft(sal_Int32 nCol, sal_Int32 nRow) const;
 
     /** Returns the right frame style of the cell (nCol,nRow).
         Returns thicker of own right style or left style of the cell to the 
right.
         Returns the style only if visible (i.e. at right border of a merged 
range).
         @return
             The left frame style or an invisible style for invalid cell 
addresses. */
-    SAL_DLLPRIVATE const Style& GetCellStyleRight( sal_Int32 nCol, sal_Int32 
nRow ) const;
+    const Style& GetCellStyleRight(sal_Int32 nCol, sal_Int32 nRow) const;
 
     /** Returns the top frame style of the cell (nCol,nRow).
         Returns thicker of own top style or bottom style of the cell above.
         Returns the style only if visible (i.e. at top border of a merged 
range).
         @return
             The top frame style or an invisible style for invalid cell 
addresses. */
-    SAL_DLLPRIVATE const Style& GetCellStyleTop( sal_Int32 nCol, sal_Int32 
nRow ) const;
+    const Style& GetCellStyleTop(sal_Int32 nCol, sal_Int32 nRow) const;
 
     /** Returns the top frame style of the cell (nCol,nRow).
         Returns thicker of own top style or bottom style of the cell above.
         Returns the style only if visible (i.e. at top border of a merged 
range).
         @return
             The top frame style or an invisible style for invalid cell 
addresses. */
-    SAL_DLLPRIVATE const Style& GetCellStyleBottom( sal_Int32 nCol, sal_Int32 
nRow ) const;
+    const Style& GetCellStyleBottom(sal_Int32 nCol, sal_Int32 nRow) const;
 
     /** Returns the top-left to bottom-right frame style of the cell 
(nCol,nRow).
         Ignores merged ranges;
diff --git a/svx/CppunitTest_svx_unit.mk b/svx/CppunitTest_svx_unit.mk
index 95c76b2d0733..0cad5af02c26 100644
--- a/svx/CppunitTest_svx_unit.mk
+++ b/svx/CppunitTest_svx_unit.mk
@@ -26,6 +26,7 @@ $(eval $(call gb_CppunitTest_add_exception_objects,svx_unit, \
        svx/qa/unit/svdraw/test_SdrTextObject \
        svx/qa/unit/customshapes \
     svx/qa/unit/classicshapes \
+       svx/qa/unit/framelinkarray \
     svx/qa/unit/gluepointTest \
        svx/qa/unit/sdr \
        svx/qa/unit/svdraw \
diff --git a/svx/qa/unit/framelinkarray.cxx b/svx/qa/unit/framelinkarray.cxx
new file mode 100644
index 000000000000..f94077a702b1
--- /dev/null
+++ b/svx/qa/unit/framelinkarray.cxx
@@ -0,0 +1,196 @@
+/* -*- 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 <test/unoapi_test.hxx>
+
+#include <svx/framelinkarray.hxx>
+#include <svx/framelink.hxx>
+
+using namespace com::sun::star;
+
+class FrameLinkArrayTest : public UnoApiTest
+{
+public:
+    FrameLinkArrayTest()
+        : UnoApiTest(u"svx/qa/unit/data/"_ustr)
+    {
+    }
+};
+
+CPPUNIT_TEST_FIXTURE(FrameLinkArrayTest, testSingleCell)
+{
+    svx::frame::Array stArr;
+    stArr.Initialize(10, 10);
+
+    stArr.SetCellStyleLeft(/*col*/ 2, /*row*/ 4,
+                           svx::frame::Style{ 1.0, 1.0, 1.0, 
SvxBorderLineStyle::ENGRAVED, 1.0 });
+    stArr.SetCellStyleRight(/*col*/ 2, /*row*/ 4,
+                            svx::frame::Style{ 1.0, 1.0, 1.0, 
SvxBorderLineStyle::DOTTED, 1.0 });
+    stArr.SetCellStyleTop(/*col*/ 2, /*row*/ 4,
+                          svx::frame::Style{ 1.0, 1.0, 1.0, 
SvxBorderLineStyle::DASHED, 1.0 });
+    stArr.SetCellStyleBottom(/*col*/ 2, /*row*/ 4,
+                             svx::frame::Style{ 1.0, 1.0, 1.0, 
SvxBorderLineStyle::DOUBLE, 1.0 });
+
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::ENGRAVED, 
stArr.GetCellStyleLeft(2, 4).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::DOTTED, 
stArr.GetCellStyleRight(2, 4).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::DASHED, stArr.GetCellStyleTop(2, 
4).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::DOUBLE, 
stArr.GetCellStyleBottom(2, 4).Type());
+}
+
+CPPUNIT_TEST_FIXTURE(FrameLinkArrayTest, testSingleCellRtl)
+{
+    svx::frame::Array stArr;
+    stArr.Initialize(10, 10);
+
+    stArr.SetCellStyleLeft(/*col*/ 2, /*row*/ 4,
+                           svx::frame::Style{ 1.0, 1.0, 1.0, 
SvxBorderLineStyle::ENGRAVED, 1.0 });
+    stArr.SetCellStyleRight(/*col*/ 2, /*row*/ 4,
+                            svx::frame::Style{ 1.0, 1.0, 1.0, 
SvxBorderLineStyle::DOTTED, 1.0 });
+    stArr.SetCellStyleTop(/*col*/ 2, /*row*/ 4,
+                          svx::frame::Style{ 1.0, 1.0, 1.0, 
SvxBorderLineStyle::DASHED, 1.0 });
+    stArr.SetCellStyleBottom(/*col*/ 2, /*row*/ 4,
+                             svx::frame::Style{ 1.0, 1.0, 1.0, 
SvxBorderLineStyle::DOUBLE, 1.0 });
+
+    stArr.MirrorSelfX();
+
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, stArr.GetCellStyleLeft(2, 
4).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, stArr.GetCellStyleRight(2, 
4).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, stArr.GetCellStyleTop(2, 
4).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, 
stArr.GetCellStyleBottom(2, 4).Type());
+
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::DOTTED, stArr.GetCellStyleLeft(7, 
4).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::ENGRAVED, 
stArr.GetCellStyleRight(7, 4).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::DASHED, stArr.GetCellStyleTop(7, 
4).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::DOUBLE, 
stArr.GetCellStyleBottom(7, 4).Type());
+}
+
+CPPUNIT_TEST_FIXTURE(FrameLinkArrayTest, testMergedCell)
+{
+    svx::frame::Array stArr;
+    stArr.Initialize(10, 10);
+
+    stArr.SetCellStyleLeft(/*col*/ 2, /*row*/ 4,
+                           svx::frame::Style{ 1.0, 1.0, 1.0, 
SvxBorderLineStyle::ENGRAVED, 1.0 });
+    stArr.SetCellStyleRight(/*col*/ 2, /*row*/ 4,
+                            svx::frame::Style{ 1.0, 1.0, 1.0, 
SvxBorderLineStyle::DOTTED, 1.0 });
+    stArr.SetCellStyleTop(/*col*/ 2, /*row*/ 4,
+                          svx::frame::Style{ 1.0, 1.0, 1.0, 
SvxBorderLineStyle::DASHED, 1.0 });
+    stArr.SetCellStyleBottom(/*col*/ 2, /*row*/ 4,
+                             svx::frame::Style{ 1.0, 1.0, 1.0, 
SvxBorderLineStyle::DOUBLE, 1.0 });
+    stArr.SetMergedRange(/*first col*/ 2, /*first row*/ 4, /*last col*/ 4, 
/*last row*/ 6);
+
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::ENGRAVED, 
stArr.GetCellStyleLeft(2, 4).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, stArr.GetCellStyleRight(2, 
4).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::DASHED, stArr.GetCellStyleTop(2, 
4).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, 
stArr.GetCellStyleBottom(2, 4).Type());
+
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, stArr.GetCellStyleLeft(3, 
4).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, stArr.GetCellStyleRight(3, 
4).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::DASHED, stArr.GetCellStyleTop(3, 
4).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, 
stArr.GetCellStyleBottom(3, 4).Type());
+
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, stArr.GetCellStyleLeft(4, 
4).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::DOTTED, 
stArr.GetCellStyleRight(4, 4).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::DASHED, stArr.GetCellStyleTop(4, 
4).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, 
stArr.GetCellStyleBottom(4, 4).Type());
+
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::ENGRAVED, 
stArr.GetCellStyleLeft(2, 5).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, stArr.GetCellStyleRight(2, 
5).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, stArr.GetCellStyleTop(2, 
5).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, 
stArr.GetCellStyleBottom(2, 5).Type());
+
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, stArr.GetCellStyleLeft(3, 
5).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, stArr.GetCellStyleRight(3, 
5).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, stArr.GetCellStyleTop(3, 
5).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, 
stArr.GetCellStyleBottom(3, 5).Type());
+
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, stArr.GetCellStyleLeft(4, 
5).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::DOTTED, 
stArr.GetCellStyleRight(4, 5).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, stArr.GetCellStyleTop(4, 
5).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, 
stArr.GetCellStyleBottom(4, 5).Type());
+
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::ENGRAVED, 
stArr.GetCellStyleLeft(2, 6).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, stArr.GetCellStyleRight(2, 
6).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, stArr.GetCellStyleTop(2, 
6).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::DOUBLE, 
stArr.GetCellStyleBottom(2, 6).Type());
+
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, stArr.GetCellStyleLeft(3, 
6).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, stArr.GetCellStyleRight(3, 
6).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, stArr.GetCellStyleTop(3, 
6).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::DOUBLE, 
stArr.GetCellStyleBottom(3, 6).Type());
+
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, stArr.GetCellStyleLeft(4, 
6).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::DOTTED, 
stArr.GetCellStyleRight(4, 6).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, stArr.GetCellStyleTop(4, 
6).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::DOUBLE, 
stArr.GetCellStyleBottom(4, 6).Type());
+}
+
+CPPUNIT_TEST_FIXTURE(FrameLinkArrayTest, testMergedCellRtl)
+{
+    svx::frame::Array stArr;
+    stArr.Initialize(10, 10);
+
+    stArr.SetCellStyleLeft(/*col*/ 2, /*row*/ 4,
+                           svx::frame::Style{ 1.0, 1.0, 1.0, 
SvxBorderLineStyle::ENGRAVED, 1.0 });
+    stArr.SetCellStyleRight(/*col*/ 2, /*row*/ 4,
+                            svx::frame::Style{ 1.0, 1.0, 1.0, 
SvxBorderLineStyle::DOTTED, 1.0 });
+    stArr.SetCellStyleTop(/*col*/ 2, /*row*/ 4,
+                          svx::frame::Style{ 1.0, 1.0, 1.0, 
SvxBorderLineStyle::DASHED, 1.0 });
+    stArr.SetCellStyleBottom(/*col*/ 2, /*row*/ 4,
+                             svx::frame::Style{ 1.0, 1.0, 1.0, 
SvxBorderLineStyle::DOUBLE, 1.0 });
+    stArr.SetMergedRange(/*first col*/ 2, /*first row*/ 4, /*last col*/ 4, 
/*last row*/ 6);
+    stArr.MirrorSelfX();
+
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::DOTTED, stArr.GetCellStyleLeft(5, 
4).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, stArr.GetCellStyleRight(5, 
4).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::DASHED, stArr.GetCellStyleTop(5, 
4).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, 
stArr.GetCellStyleBottom(5, 4).Type());
+
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, stArr.GetCellStyleLeft(6, 
4).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, stArr.GetCellStyleRight(6, 
4).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::DASHED, stArr.GetCellStyleTop(6, 
4).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, 
stArr.GetCellStyleBottom(6, 4).Type());
+
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, stArr.GetCellStyleLeft(7, 
4).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::ENGRAVED, 
stArr.GetCellStyleRight(7, 4).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::DASHED, stArr.GetCellStyleTop(7, 
4).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, 
stArr.GetCellStyleBottom(7, 4).Type());
+
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::DOTTED, stArr.GetCellStyleLeft(5, 
5).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, stArr.GetCellStyleRight(5, 
5).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, stArr.GetCellStyleTop(5, 
5).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, 
stArr.GetCellStyleBottom(5, 5).Type());
+
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, stArr.GetCellStyleLeft(6, 
5).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, stArr.GetCellStyleRight(6, 
5).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, stArr.GetCellStyleTop(6, 
5).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, 
stArr.GetCellStyleBottom(6, 5).Type());
+
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, stArr.GetCellStyleLeft(7, 
5).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::ENGRAVED, 
stArr.GetCellStyleRight(7, 5).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, stArr.GetCellStyleTop(7, 
5).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, 
stArr.GetCellStyleBottom(7, 5).Type());
+
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::DOTTED, stArr.GetCellStyleLeft(5, 
6).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, stArr.GetCellStyleRight(5, 
6).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, stArr.GetCellStyleTop(5, 
6).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::DOUBLE, 
stArr.GetCellStyleBottom(5, 6).Type());
+
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, stArr.GetCellStyleLeft(6, 
6).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, stArr.GetCellStyleRight(6, 
6).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, stArr.GetCellStyleTop(6, 
6).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::DOUBLE, 
stArr.GetCellStyleBottom(6, 6).Type());
+
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, stArr.GetCellStyleLeft(7, 
6).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::ENGRAVED, 
stArr.GetCellStyleRight(7, 6).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::SOLID, stArr.GetCellStyleTop(7, 
6).Type());
+    CPPUNIT_ASSERT_EQUAL(SvxBorderLineStyle::DOUBLE, 
stArr.GetCellStyleBottom(7, 6).Type());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/dialog/framelinkarray.cxx 
b/svx/source/dialog/framelinkarray.cxx
index 02332d5e6de8..e1b420762f3b 100644
--- a/svx/source/dialog/framelinkarray.cxx
+++ b/svx/source/dialog/framelinkarray.cxx
@@ -317,6 +317,7 @@ struct ArrayImpl
     mutable bool        mbXCoordsDirty;
     mutable bool        mbYCoordsDirty;
     bool                mbMayHaveCellRotation;
+    bool mbXMirrored = false;
 
     explicit            ArrayImpl( sal_Int32 nWidth, sal_Int32 nHeight );
     ~ArrayImpl();
@@ -334,8 +335,7 @@ struct ArrayImpl
     sal_Int32              GetMergedLastCol( sal_Int32 nCol, sal_Int32 nRow ) 
const;
     sal_Int32              GetMergedLastRow( sal_Int32 nCol, sal_Int32 nRow ) 
const;
 
-    const Cell*         GetMergedOriginCell( sal_Int32 nCol, sal_Int32 nRow ) 
const;
-    const Cell*         GetMergedLastCell( sal_Int32 nCol, sal_Int32 nRow ) 
const;
+    const Cell* GetMergedStyleSourceCell(sal_Int32 nCol, sal_Int32 nRow) const;
 
     bool                IsMergedOverlappedLeft( sal_Int32 nCol, sal_Int32 nRow 
) const;
     bool                IsMergedOverlappedRight( sal_Int32 nCol, sal_Int32 
nRow ) const;
@@ -454,14 +454,14 @@ sal_Int32 ArrayImpl::GetMergedLastRow( sal_Int32 nCol, 
sal_Int32 nRow ) const
     return nLastRow - 1;
 }
 
-const Cell* ArrayImpl::GetMergedOriginCell( sal_Int32 nCol, sal_Int32 nRow ) 
const
+const Cell* ArrayImpl::GetMergedStyleSourceCell(sal_Int32 nCol, sal_Int32 
nRow) const
 {
-    return GetCell( GetMergedFirstCol( nCol, nRow ), GetMergedFirstRow( nCol, 
nRow ) );
-}
+    if (mbXMirrored)
+    {
+        return GetCell(GetMergedLastCol(nCol, nRow), GetMergedFirstRow(nCol, 
nRow));
+    }
 
-const Cell* ArrayImpl::GetMergedLastCell( sal_Int32 nCol, sal_Int32 nRow ) 
const
-{
-    return GetCell( GetMergedLastCol( nCol, nRow ), GetMergedLastRow( nCol, 
nRow ) );
+    return GetCell(GetMergedFirstCol(nCol, nRow), GetMergedFirstRow(nCol, 
nRow));
 }
 
 bool ArrayImpl::IsMergedOverlappedLeft( sal_Int32 nCol, sal_Int32 nRow ) const
@@ -783,15 +783,16 @@ const Style& Array::GetCellStyleLeft( sal_Int32 nCol, 
sal_Int32 nRow ) const
         return OBJ_STYLE_NONE;
     // left clipping border: always own left style
     if( nCol == mxImpl->mnFirstClipCol )
-        return mxImpl->GetMergedOriginCell( nCol, nRow )->GetStyleLeft();
+        return mxImpl->GetMergedStyleSourceCell(nCol, nRow)->GetStyleLeft();
     // right clipping border: always right style of left neighbor cell
     if( nCol == mxImpl->mnLastClipCol + 1 )
-        return mxImpl->GetMergedOriginCell( nCol - 1, nRow )->GetStyleRight();
+        return mxImpl->GetMergedStyleSourceCell(nCol - 1, 
nRow)->GetStyleRight();
     // outside clipping columns: invisible
     if( !mxImpl->IsColInClipRange( nCol ) )
         return OBJ_STYLE_NONE;
     // inside clipping range: maximum of own left style and right style of 
left neighbor cell
-    return std::max( mxImpl->GetMergedOriginCell( nCol, nRow 
)->GetStyleLeft(), mxImpl->GetMergedOriginCell( nCol - 1, nRow 
)->GetStyleRight() );
+    return std::max(mxImpl->GetMergedStyleSourceCell(nCol, 
nRow)->GetStyleLeft(),
+                    mxImpl->GetMergedStyleSourceCell(nCol - 1, 
nRow)->GetStyleRight());
 }
 
 const Style& Array::GetCellStyleRight( sal_Int32 nCol, sal_Int32 nRow ) const
@@ -801,15 +802,16 @@ const Style& Array::GetCellStyleRight( sal_Int32 nCol, 
sal_Int32 nRow ) const
         return OBJ_STYLE_NONE;
     // left clipping border: always left style of right neighbor cell
     if( nCol + 1 == mxImpl->mnFirstClipCol )
-        return mxImpl->GetMergedOriginCell( nCol + 1, nRow )->GetStyleLeft();
+        return mxImpl->GetMergedStyleSourceCell(nCol + 1, 
nRow)->GetStyleLeft();
     // right clipping border: always own right style
     if( nCol == mxImpl->mnLastClipCol )
-        return mxImpl->GetMergedLastCell( nCol, nRow )->GetStyleRight();
+        return mxImpl->GetMergedStyleSourceCell(nCol, nRow)->GetStyleRight();
     // outside clipping columns: invisible
     if( !mxImpl->IsColInClipRange( nCol ) )
         return OBJ_STYLE_NONE;
     // inside clipping range: maximum of own right style and left style of 
right neighbor cell
-    return std::max( mxImpl->GetMergedOriginCell( nCol, nRow 
)->GetStyleRight(), mxImpl->GetMergedOriginCell( nCol + 1, nRow 
)->GetStyleLeft() );
+    return std::max(mxImpl->GetMergedStyleSourceCell(nCol, 
nRow)->GetStyleRight(),
+                    mxImpl->GetMergedStyleSourceCell(nCol + 1, 
nRow)->GetStyleLeft());
 }
 
 const Style& Array::GetCellStyleTop( sal_Int32 nCol, sal_Int32 nRow ) const
@@ -819,15 +821,16 @@ const Style& Array::GetCellStyleTop( sal_Int32 nCol, 
sal_Int32 nRow ) const
         return OBJ_STYLE_NONE;
     // top clipping border: always own top style
     if( nRow == mxImpl->mnFirstClipRow )
-        return mxImpl->GetMergedOriginCell( nCol, nRow )->GetStyleTop();
+        return mxImpl->GetMergedStyleSourceCell(nCol, nRow)->GetStyleTop();
     // bottom clipping border: always bottom style of top neighbor cell
     if( nRow == mxImpl->mnLastClipRow + 1 )
-        return mxImpl->GetMergedOriginCell( nCol, nRow - 1 )->GetStyleBottom();
+        return mxImpl->GetMergedStyleSourceCell(nCol, nRow - 
1)->GetStyleBottom();
     // outside clipping rows: invisible
     if( !mxImpl->IsRowInClipRange( nRow ) )
         return OBJ_STYLE_NONE;
     // inside clipping range: maximum of own top style and bottom style of top 
neighbor cell
-    return std::max( mxImpl->GetMergedOriginCell( nCol, nRow )->GetStyleTop(), 
mxImpl->GetMergedOriginCell( nCol, nRow - 1 )->GetStyleBottom() );
+    return std::max(mxImpl->GetMergedStyleSourceCell(nCol, 
nRow)->GetStyleTop(),
+                    mxImpl->GetMergedStyleSourceCell(nCol, nRow - 
1)->GetStyleBottom());
 }
 
 const Style& Array::GetCellStyleBottom( sal_Int32 nCol, sal_Int32 nRow ) const
@@ -837,15 +840,16 @@ const Style& Array::GetCellStyleBottom( sal_Int32 nCol, 
sal_Int32 nRow ) const
         return OBJ_STYLE_NONE;
     // top clipping border: always top style of bottom neighbor cell
     if( nRow + 1 == mxImpl->mnFirstClipRow )
-        return mxImpl->GetMergedOriginCell( nCol, nRow + 1 )->GetStyleTop();
+        return mxImpl->GetMergedStyleSourceCell(nCol, nRow + 1)->GetStyleTop();
     // bottom clipping border: always own bottom style
     if( nRow == mxImpl->mnLastClipRow )
-        return mxImpl->GetMergedLastCell( nCol, nRow )->GetStyleBottom();
+        return mxImpl->GetMergedStyleSourceCell(nCol, nRow)->GetStyleBottom();
     // outside clipping rows: invisible
     if( !mxImpl->IsRowInClipRange( nRow ) )
         return OBJ_STYLE_NONE;
     // inside clipping range: maximum of own bottom style and top style of 
bottom neighbor cell
-    return std::max( mxImpl->GetMergedOriginCell( nCol, nRow 
)->GetStyleBottom(), mxImpl->GetMergedOriginCell( nCol, nRow + 1 
)->GetStyleTop() );
+    return std::max(mxImpl->GetMergedStyleSourceCell(nCol, 
nRow)->GetStyleBottom(),
+                    mxImpl->GetMergedStyleSourceCell(nCol, nRow + 
1)->GetStyleTop());
 }
 
 const Style& Array::GetCellStyleTLBR( sal_Int32 nCol, sal_Int32 nRow ) const
@@ -1165,6 +1169,7 @@ void Array::MirrorSelfX()
 
     std::reverse( mxImpl->maWidths.begin(), mxImpl->maWidths.end() );
     mxImpl->mbXCoordsDirty = true;
+    mxImpl->mbXMirrored = !mxImpl->mbXMirrored;
 }
 
 // drawing
diff --git a/svx/source/table/viewcontactoftableobj.cxx 
b/svx/source/table/viewcontactoftableobj.cxx
index 8daf466983ea..c9d230292c39 100644
--- a/svx/source/table/viewcontactoftableobj.cxx
+++ b/svx/source/table/viewcontactoftableobj.cxx
@@ -249,11 +249,27 @@ namespace sdr::contact
 
                             if(xCurrentCell.is())
                             {
+                                // tdf#135843: Find correct neighbor cell 
index for merged cells
+                                auto nNextCol = aCellPos.mnCol + 
xCurrentCell->getColumnSpan();
+                                auto nNextRow = aCellPos.mnRow + 
xCurrentCell->getRowSpan();
+
                                 // copy styles for current cell to 
CellBorderArray for primitive creation
-                                aArray.SetCellStyleLeft(aCellPos.mnCol, 
aCellPos.mnRow, impGetLineStyle(rTableLayouter, aCellPos.mnCol, aCellPos.mnRow, 
false, nColCount, nRowCount, bIsRTL));
-                                aArray.SetCellStyleRight(aCellPos.mnCol, 
aCellPos.mnRow, impGetLineStyle(rTableLayouter, aCellPos.mnCol + 1, 
aCellPos.mnRow, false, nColCount, nRowCount, bIsRTL));
-                                aArray.SetCellStyleTop(aCellPos.mnCol, 
aCellPos.mnRow, impGetLineStyle(rTableLayouter, aCellPos.mnCol, aCellPos.mnRow, 
true, nColCount, nRowCount, bIsRTL));
-                                aArray.SetCellStyleBottom(aCellPos.mnCol, 
aCellPos.mnRow, impGetLineStyle(rTableLayouter, aCellPos.mnCol, aCellPos.mnRow 
+ 1, true, nColCount, nRowCount, bIsRTL));
+                                aArray.SetCellStyleLeft(
+                                    aCellPos.mnCol, aCellPos.mnRow,
+                                    impGetLineStyle(rTableLayouter, 
aCellPos.mnCol, aCellPos.mnRow,
+                                                    false, nColCount, 
nRowCount, bIsRTL));
+                                aArray.SetCellStyleRight(
+                                    aCellPos.mnCol, aCellPos.mnRow,
+                                    impGetLineStyle(rTableLayouter, nNextCol, 
aCellPos.mnRow, false,
+                                                    nColCount, nRowCount, 
bIsRTL));
+                                aArray.SetCellStyleTop(
+                                    aCellPos.mnCol, aCellPos.mnRow,
+                                    impGetLineStyle(rTableLayouter, 
aCellPos.mnCol, aCellPos.mnRow,
+                                                    true, nColCount, 
nRowCount, bIsRTL));
+                                aArray.SetCellStyleBottom(
+                                    aCellPos.mnCol, aCellPos.mnRow,
+                                    impGetLineStyle(rTableLayouter, 
aCellPos.mnCol, nNextRow, true,
+                                                    nColCount, nRowCount, 
bIsRTL));
 
                                 // ignore merged cells (all except the 
top-left of a merged cell)
                                 if(!xCurrentCell->isMerged())
diff --git a/vcl/qa/cppunit/pdfexport/pdfexport2.cxx 
b/vcl/qa/cppunit/pdfexport/pdfexport2.cxx
index 20acdc856aeb..09e934eabe9f 100644
--- a/vcl/qa/cppunit/pdfexport/pdfexport2.cxx
+++ b/vcl/qa/cppunit/pdfexport/pdfexport2.cxx
@@ -486,9 +486,9 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf135346)
     CPPUNIT_ASSERT(pPdfPage);
 
     // Without the fix in place, this test would have failed with
-    // - Expected: 56
+    // - Expected: 55
     // - Actual  : 0
-    CPPUNIT_ASSERT_EQUAL(56, pPdfPage->getObjectCount());
+    CPPUNIT_ASSERT_EQUAL(55, pPdfPage->getObjectCount());
 }
 
 CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf147164)

Reply via email to