sw/inc/fesh.hxx                                                                
            |    2 
 
sw/qa/extras/layout/data/2024-01-19_merged-cells-on-separate-pages-vertical-alignement.odt
 |binary
 sw/qa/extras/layout/layout5.cxx                                                
            |   61 ++++++++++
 sw/source/core/layout/tabfrm.cxx                                               
            |   18 ++
 4 files changed, 80 insertions(+), 1 deletion(-)

New commits:
commit ec69f07a178a1b6b3cbef309150704f7b236ab8e
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Tue Feb 4 10:36:50 2025 +0100
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Wed Feb 5 21:20:05 2025 +0100

    tdf#159029 sw: layout: fix cell vertical orientation after split
    
    The vertical alignment of cells is implemented in SwCellFrame::Format(),
    but it is disabled if IsRebuildLastLine() is true (apparently since the
    time when splitting table rows was first implemented in commit
    90b73c7b667b06d42f5e37196d25a85b6c787f33 "INTEGRATION: CWS cellbreak")
    which is in 2 different cases:
    
    1. when another line fits on the page, around a call to
       lcl_RecalcRow(pLastLine) after RemoveFollowFlowLine() - this is the
       relevant case when the paragraph is deleted
    
    This case used to work by accident before commit
    068c133ac41c97652909b88c432e3b73010efc3e, when after
    RemoveFollowFlowLine() of row 406 the text frame moved to the top, then
    a Split of the row after the one containing the last part of the merged
    cell with the problem was attempted and failed, and in lcl_RecalcRow()
    after the Split the alignment was fixed; this commit changed it so that
    the first row frame 6 had an invalid position, which caused an earlier
    correction of the position of all the cells and text frames during the
    lcl_RecalcRow() after joining the follow, where m_bIsRebuildLastLine was
    set.
    
    2. after a successful Split() with bTryToSplit=true, i.e., a row was
       split - this is the relevant case on Undo of the paragraph delete
    
    This actually was a problem already before the above mentioned commit,
    but then it could be "fixed" by clicking on the cell, which stopped to
    work.
    
    Here there is no RemoveFollowFlowLine() at the start, but then again a
    failed attempt to Split a row followed by a successful Split between
    rows; before the 2nd Split the text frame is correctly positioned and
    valid, but then lcl_RecalcSplitLine() calling
    lcl_ShrinkCellsAndAllContent() moves the text frame up.
    
    In both cases, explicitly invalidate the PrtArea of cells in the last
    row where a vertical orientation is set.
    
    (regression from commit 068c133ac41c97652909b88c432e3b73010efc3e)
    
    Change-Id: I7d2e85bb76a4b77c7871d759abbebd6abeb31282
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/181113
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    Tested-by: Jenkins
    (cherry picked from commit ee482e856143ee62b37869411a64c36a1d78c7cc)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/181119
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

diff --git a/sw/inc/fesh.hxx b/sw/inc/fesh.hxx
index 6e4466dc60d7..be98672f0f51 100644
--- a/sw/inc/fesh.hxx
+++ b/sw/inc/fesh.hxx
@@ -670,7 +670,7 @@ public:
     void SetRowSplit( const SwFormatRowSplit &rSz );
     std::unique_ptr<SwFormatRowSplit> GetRowSplit() const;
 
-    void   SetBoxAlign( sal_uInt16 nOrient );
+    SW_DLLPUBLIC void SetBoxAlign(sal_uInt16 nOrient);
     sal_uInt16 GetBoxAlign() const;         ///< USHRT_MAX if ambiguous.
 
     bool BalanceRowHeight( bool bTstOnly, const bool bOptimize = false );
diff --git 
a/sw/qa/extras/layout/data/2024-01-19_merged-cells-on-separate-pages-vertical-alignement.odt
 
b/sw/qa/extras/layout/data/2024-01-19_merged-cells-on-separate-pages-vertical-alignement.odt
new file mode 100644
index 000000000000..e316e93fe087
Binary files /dev/null and 
b/sw/qa/extras/layout/data/2024-01-19_merged-cells-on-separate-pages-vertical-alignement.odt
 differ
diff --git a/sw/qa/extras/layout/layout5.cxx b/sw/qa/extras/layout/layout5.cxx
index 64d7e33a8b23..eaefdcf69bbf 100644
--- a/sw/qa/extras/layout/layout5.cxx
+++ b/sw/qa/extras/layout/layout5.cxx
@@ -742,6 +742,67 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter5, testTdf117245)
     assertXPath(pXmlDoc, "/root/page/body/txt[2]/SwParaPortion/SwLineLayout", 
1);
 }
 
+CPPUNIT_TEST_FIXTURE(SwLayoutWriter5, testTdf159029)
+{
+    
createSwDoc("2024-01-19_merged-cells-on-separate-pages-vertical-alignement.odt");
+
+    {
+        xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+        assertXPath(pXmlDoc, 
"/root/page[1]/body/tab[1]/row[1]/cell[2]/infos/bounds", "top",
+                    u"1970");
+        assertXPath(pXmlDoc, 
"/root/page[1]/body/tab[1]/row[1]/cell[2]/txt[1]/infos/bounds", "top",
+                    u"1970");
+    }
+
+    // set vert orient
+    SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
+    pWrtShell->GotoTable("Table1");
+    pWrtShell->Right(SwCursorSkipMode::Cells, /*bSelect=*/false, 1, 
/*bBasicCall=*/false);
+    pWrtShell->SetBoxAlign(css::text::VertOrientation::BOTTOM);
+
+    {
+        xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+        assertXPath(pXmlDoc, 
"/root/page[1]/body/tab[1]/row[1]/cell[2]/infos/bounds", "top",
+                    u"1970");
+        assertXPath(pXmlDoc, 
"/root/page[1]/body/tab[1]/row[1]/cell[2]/txt[1]/infos/bounds", "top",
+                    u"15494");
+    }
+
+    // delete
+    pWrtShell->SttEndDoc(true);
+    pWrtShell->DelRight();
+
+    {
+        xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+        assertXPath(pXmlDoc, 
"/root/page[1]/body/tab[1]/row[1]/cell[2]/infos/bounds", "top",
+                    u"1694");
+        // the problem was that this moved to the top of the cell
+        assertXPath(pXmlDoc, 
"/root/page[1]/body/tab[1]/row[1]/cell[2]/txt[1]/infos/bounds", "top",
+                    u"15494");
+    }
+
+    pWrtShell->Undo();
+
+    {
+        xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+        assertXPath(pXmlDoc, 
"/root/page[1]/body/tab[1]/row[1]/cell[2]/infos/bounds", "top",
+                    u"1970");
+        // the problem was that this moved to the top of the cell
+        assertXPath(pXmlDoc, 
"/root/page[1]/body/tab[1]/row[1]/cell[2]/txt[1]/infos/bounds", "top",
+                    u"15494");
+    }
+
+    pWrtShell->Redo();
+
+    {
+        xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+        assertXPath(pXmlDoc, 
"/root/page[1]/body/tab[1]/row[1]/cell[2]/infos/bounds", "top",
+                    u"1694");
+        assertXPath(pXmlDoc, 
"/root/page[1]/body/tab[1]/row[1]/cell[2]/txt[1]/infos/bounds", "top",
+                    u"15494");
+    }
+}
+
 CPPUNIT_TEST_FIXTURE(SwLayoutWriter5, testTdf118672)
 {
     createSwDoc("tdf118672.odt");
diff --git a/sw/source/core/layout/tabfrm.cxx b/sw/source/core/layout/tabfrm.cxx
index eced2e301c8a..cfc8de996473 100644
--- a/sw/source/core/layout/tabfrm.cxx
+++ b/sw/source/core/layout/tabfrm.cxx
@@ -183,6 +183,22 @@ void SwTabFrame::RegistFlys()
     }
 }
 
+static void InvalidateVertOrientCells(SwRowFrame & rRow)
+{
+    for (SwFrame * pLower{rRow.Lower()}; pLower != nullptr; pLower = 
pLower->GetNext())
+    {
+        SwCellFrame * pCell{static_cast<SwCellFrame *>(pLower)};
+        if (pCell->GetLayoutRowSpan() != 1)
+        {
+            pCell = const_cast<SwCellFrame 
*>(&pCell->FindStartEndOfRowSpanCell(true));
+        }
+        if (pCell->GetFormat()->GetVertOrient().GetVertOrient() != 
text::VertOrientation::NONE)
+        {   // tdf#159029 force repositioning of content in cell because it
+            pCell->InvalidatePrt(); // was disabled by SetRebuildLastLine()
+        }
+    }
+}
+
 static void SwInvalidateAll( SwFrame *pFrame, tools::Long nBottom );
 static void lcl_RecalcRow( SwRowFrame& rRow, tools::Long nBottom );
 static bool lcl_ArrangeLowers( SwLayoutFrame *pLay, tools::Long lYStart, bool 
bInva );
@@ -860,6 +876,7 @@ static bool lcl_RecalcSplitLine( SwRowFrame& rLastLine, 
SwRowFrame& rFollowLine,
         // Everything looks fine. Splitting seems to be successful. We 
invalidate
         // rFollowLine to force a new formatting.
         ::SwInvalidateAll( &rFollowLine, LONG_MAX );
+        InvalidateVertOrientCells(rLastLine);
     }
     else
     {
@@ -2673,6 +2690,7 @@ void SwTabFrame::MakeAll(vcl::RenderContext* 
pRenderContext)
                                 ::SwInvalidateAll( pLastLine, LONG_MAX );
                                 SetRebuildLastLine( true );
                                 
lcl_RecalcRow(*static_cast<SwRowFrame*>(pLastLine), LONG_MAX);
+                                
InvalidateVertOrientCells(*static_cast<SwRowFrame *>(pLastLine));
                                 SetRebuildLastLine( false );
                             }
 

Reply via email to