summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Stahl <michael.stahl@allotropia.de>2024-11-28 14:28:58 +0100
committerMike Kaganski <mike.kaganski@collabora.com>2024-12-03 16:25:31 +0100
commit4b81278ac5e43f7d3e35485aebc7d57c4b760076 (patch)
treeb8576618f8faa9d8b3023c9788c1757c626b7131
parent379857ddce35cf20d489a05e7aed73fb61d6cbf6 (diff)
sw: layout: fix toggling Hidden Paragraphs resulting in bad layout
1. SwContentFrame::MakeAll() needs some more checks to ensure that it never Formats a hidden text frame. This fixes the reported problem that turning off "Hidden Paragraphs" in Tools->Options->Writer->View results in bad layout (extra completely empty page at the end). 3. This means HideAndShowObjects() must be called manually in that case as it was previously called inside Format(), see testHiddenSectionFlys. 2. SwTextFrame::Prepare() as called from calcing some upper (table cell) in the bugdoc needs to avoid invalidating a hidden frame so it isn't formatted (triggered new assert). 4. SwLayAction::IsShortCut() had what looks like an obvious and ancient mistake that was causing a crash in testTdf155011. 5. SwTabFrame::MakeAll() should not calc the next if it's hidden, that was causing a problem in testThemeCrash where a hidden frame moved back into an overfull body and immediately forward again, triggering the new asserts. 6. SwTextFrame::IsHiddenNow() caused interesting problem where some ancient (CVS import) check for a 0 width would skip the invalidating due to the 2. change when called from SwViewShell::Reformat() ... lcl_InvalidateContent() in testParagraphMarkInCell; unclear why this check exists, let's avoid it for the cases where we definitely know that only doc model should determine visibility. 7. JunitTest_sw_unoapi_1 triggers new asserts because MakePos() in a cell ends up invalidating the text frame; fix it up again. (presumably regression from commit 0c96119895b347f8eb5bb89f393351bd3c02b9f1 or one of its follow-ups) Change-Id: I619f4be852eca5124f49d9a91e1de658b7070074 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/177486 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.stahl@allotropia.de> (cherry picked from commit 0a3f5169acc6708c352cad0fa07fdb4af8c8b2dd) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/177557 Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
-rw-r--r--sw/source/core/inc/txtfrm.hxx3
-rw-r--r--sw/source/core/layout/calcmove.cxx28
-rw-r--r--sw/source/core/layout/layact.cxx2
-rw-r--r--sw/source/core/layout/tabfrm.cxx4
-rw-r--r--sw/source/core/text/txtfrm.cxx21
5 files changed, 47 insertions, 11 deletions
diff --git a/sw/source/core/inc/txtfrm.hxx b/sw/source/core/inc/txtfrm.hxx
index 2f61a9e1b853..a70a824374e7 100644
--- a/sw/source/core/inc/txtfrm.hxx
+++ b/sw/source/core/inc/txtfrm.hxx
@@ -561,7 +561,8 @@ public:
#endif
/// Hidden
- virtual bool IsHiddenNow() const override; // bHidden && pOut == pPrt
+ virtual bool IsHiddenNow() const override;
+ bool IsHiddenNowImpl() const;
void HideHidden(); // Remove appendage if Hidden
void HideFootnotes(TextFrameIndex nStart, TextFrameIndex nEnd);
diff --git a/sw/source/core/layout/calcmove.cxx b/sw/source/core/layout/calcmove.cxx
index 475420e32d78..168083f21d64 100644
--- a/sw/source/core/layout/calcmove.cxx
+++ b/sw/source/core/layout/calcmove.cxx
@@ -1284,8 +1284,12 @@ void SwContentFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/)
return;
}
- if (IsHiddenNow())
+ bool const isHiddenNow(static_cast<SwTextFrame*>(this)->IsHiddenNowImpl());
+ if (isHiddenNow)
+ {
MakeValidZeroHeight();
+ HideAndShowObjects();
+ }
std::optional<SwFrameDeleteGuard> oDeleteGuard(std::in_place, this);
LockJoin();
@@ -1456,11 +1460,18 @@ void SwContentFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/)
aOldPrtPos = aRectFnSet.GetPos(getFramePrintArea());
if ( !isFrameAreaPositionValid() )
+ {
MakePos();
+ if (isHiddenNow && !isFrameAreaSizeValid())
+ { // in a table cell, might be invalidated by ~SwLayNotify
+ MakeValidZeroHeight();
+ }
+ }
//Set FixSize. VarSize is being adjusted by Format().
if ( !isFrameAreaSizeValid() )
{
+ assert(!isHiddenNow); // hidden frame must not be formatted
// invalidate printing area flag, if the following conditions are hold:
// - current frame width is 0.
// - current printing area width is 0.
@@ -1497,6 +1508,7 @@ void SwContentFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/)
}
if ( !isFramePrintAreaValid() )
{
+ assert(!isHiddenNow); // hidden frame must not be formatted
const tools::Long nOldW = aRectFnSet.GetWidth(getFramePrintArea());
// #i34730# - keep current frame height
const SwTwips nOldH = aRectFnSet.GetHeight(getFrameArea());
@@ -1533,7 +1545,7 @@ void SwContentFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/)
// Criteria:
// - It needs to be movable (otherwise, splitting doesn't make sense)
// - It needs to overlap with the lower edge of the PrtArea of the Upper
- if ( !bMustFit )
+ if (!bMustFit && !isHiddenNow)
{
bool bWidow = true;
const SwTwips nDeadLine = aRectFnSet.GetPrtBottom(*GetUpper());
@@ -1559,6 +1571,7 @@ void SwContentFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/)
}
if ( !isFrameAreaSizeValid() )
{
+ assert(!isHiddenNow); // hidden frame must not be formatted
setFrameAreaSizeValid(true);
bFormatted = true;
++nFormatCount;
@@ -1597,8 +1610,15 @@ void SwContentFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/)
pMoveBwdPre = pTemp;
isMoveBwdPreValid = bTemp;
bMovedBwd = true;
- bFormatted = false;
- if ( bKeep && bMoveable )
+ if (isHiddenNow)
+ { // MoveBwd invalidated the size! Validate to prevent Format!
+ MakeValidZeroHeight();
+ }
+ else
+ {
+ bFormatted = false;
+ }
+ if (bKeep && bMoveable && !isHiddenNow)
{
if( CheckMoveFwd( bMakePage, false, bMovedBwd ) )
{
diff --git a/sw/source/core/layout/layact.cxx b/sw/source/core/layout/layact.cxx
index a7933214f5c7..034e8a5f01e9 100644
--- a/sw/source/core/layout/layact.cxx
+++ b/sw/source/core/layout/layact.cxx
@@ -1085,7 +1085,7 @@ bool SwLayAction::IsShortCut( SwPageFrame *&prPage )
if ( pLst->IsInTab() )
pLst = pContent->FindTabFrame();
if ( pLst->IsInSct() )
- pLst = pContent->FindSctFrame();
+ pLst = pLst->FindSctFrame();
pLst = pLst->FindPrev();
if ( pLst &&
(pLst->getFrameArea().Top() >= rVis.Bottom() ||
diff --git a/sw/source/core/layout/tabfrm.cxx b/sw/source/core/layout/tabfrm.cxx
index 857ed194efc3..05da0a6b2fcd 100644
--- a/sw/source/core/layout/tabfrm.cxx
+++ b/sw/source/core/layout/tabfrm.cxx
@@ -3152,6 +3152,10 @@ void SwTabFrame::MakeAll(vcl::RenderContext* pRenderContext)
bCalcNxt = false;
}
}
+ if (pNxt->IsHiddenNow())
+ { // e.g. "testThemeCrash"
+ bCalcNxt = false;
+ }
if ( bCalcNxt )
{
// tdf#119109 follow was just formatted,
diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx
index 6ed5ac1f0232..654a59b30a63 100644
--- a/sw/source/core/text/txtfrm.cxx
+++ b/sw/source/core/text/txtfrm.cxx
@@ -1498,6 +1498,12 @@ bool SwTextFrame::IsHiddenNow() const
return true;
}
+ // TODO: what is the above check good for and can it be removed?
+ return IsHiddenNowImpl();
+}
+
+bool SwTextFrame::IsHiddenNowImpl() const
+{
if (SwContentFrame::IsHiddenNow())
return true;
@@ -2988,12 +2994,17 @@ bool SwTextFrame::Prepare( const PrepareHint ePrep, const void* pVoid,
if( !HasPara() && !bSplitFlyAnchor && PrepareHint::MustFit != ePrep )
{
- SetInvalidVert( true ); // Test
OSL_ENSURE( !IsLocked(), "SwTextFrame::Prepare: three of a perfect pair" );
- if ( bNotify )
- InvalidateSize();
- else
- InvalidateSize_();
+ // check while ignoring frame width (testParagraphMarkInCell)
+ // because it's called from InvalidateAllContent()
+ if (!IsHiddenNowImpl())
+ {
+ SetInvalidVert( true ); // Test
+ if ( bNotify )
+ InvalidateSize();
+ else
+ InvalidateSize_();
+ }
return bParaPossiblyInvalid;
}