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
90b73c7b66 "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
068c133ac4, 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 068c133ac4)

Change-Id: I7d2e85bb76a4b77c7871d759abbebd6abeb31282
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/181113
Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
Tested-by: Jenkins
This commit is contained in:
Michael Stahl
2025-02-04 15:42:03 +01:00
parent 222ff8ce8e
commit ee482e8561
4 changed files with 80 additions and 1 deletions
+1 -1
View File
@@ -672,7 +672,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 );
+61
View File
@@ -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");
+18
View File
@@ -185,6 +185,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 );
@@ -865,6 +881,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
{
@@ -2680,6 +2697,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 );
}