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 ); }