diff options
author | Michael Stahl <michael.stahl@allotropia.de> | 2023-08-01 19:45:58 +0200 |
---|---|---|
committer | Michael Stahl <michael.stahl@allotropia.de> | 2023-08-02 11:35:50 +0200 |
commit | 06bbcee6e367d1bc319c1f9cb0e749168e4d890c (patch) | |
tree | e5ce9639b2bca0319364fc50924c36e2a53ed94e /sw | |
parent | f8c6be45b5862eb073eba0b8c327e38e3ac0c33c (diff) |
tdf#152307 sw: layout: invalidate more frames when footer grows
While on page 12:
SwTabFrame::MakeAll() is called on 523 while it's on page 12; there is
one invalid pos text frame 492 with a fly somewhere before it;
PrepareMake() of 523 formats prevs 492 then 493 which MoveFwd() taking
523 with it.
While on page 13:
TabFrame 523 is valid, and the footer 6651 never formatted (0 height).
Formatting the footer in SwHeadFootFrame::FormatSize() invalidates the
body 1031, immediately calls Calc() from SwFrame::MakePos(), where
~SwLayNotify() -> SwLayoutFrame::ChgLowersProp() invalidates
SectionFrame 1034.
Then SectionFrame 1034 is formatted, which via
SwSectionFrame::CheckClipping() -> SwLayoutFrame::ChgLowersProp()
invalidates only the last lower frame, because it checks the position of
the frame and this frame still has a position on a previous page (it
moved from page 12) and isn't even invalid yet.
So in case there are invalid frames, the positions of the frames
following these cannot be trusted to be used to optimize invalidations
in SwLayoutFrame::ChgLowersProp().
(aside: it seems odd to format the body text before the footer text, but
in this case doing it differently wouldn't have helped because the
problem was already caused on a previous page)
(regression from commit b9ef71476fd70bc13f50ebe80390e0730d1b7afb)
Change-Id: I23b35c09af3a373d0913d931a2ba59d45fadf2c0
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/155196
Tested-by: Jenkins
Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
Diffstat (limited to 'sw')
-rw-r--r-- | sw/source/core/layout/wsfrm.cxx | 26 |
1 files changed, 24 insertions, 2 deletions
diff --git a/sw/source/core/layout/wsfrm.cxx b/sw/source/core/layout/wsfrm.cxx index caaed34e8b70..992c81325e88 100644 --- a/sw/source/core/layout/wsfrm.cxx +++ b/sw/source/core/layout/wsfrm.cxx @@ -3156,26 +3156,48 @@ void SwLayoutFrame::ChgLowersProp( const Size& rOldSize ) } else { + SwFrame const* pFirstInvalid(nullptr); + for (SwFrame const* pLow = Lower(); + pLow && pLow != pLowerFrame; pLow = pLow->GetNext()) + { + if (!pLow->isFrameAreaDefinitionValid()) + { + pFirstInvalid = pLow; + break; + } + } // variable size of body|section frame has shrunk. Thus, // invalidate all lowers not matching the new body|section size // and the dedicated new last lower. if( aRectFnSet.IsVert() ) { SwTwips nBot = getFrameArea().Left() + getFramePrintArea().Left(); - while ( pLowerFrame && pLowerFrame->GetPrev() && pLowerFrame->getFrameArea().Left() < nBot ) + while (pLowerFrame && pLowerFrame->GetPrev() + && (pFirstInvalid != nullptr // tdf#152307 trust nothing after invalid frame + || pLowerFrame->getFrameArea().Left() < nBot)) { pLowerFrame->InvalidateAll_(); pLowerFrame->InvalidatePage( pPage ); + if (pLowerFrame == pFirstInvalid) + { + pFirstInvalid = nullptr; // continue checking nBot + } pLowerFrame = pLowerFrame->GetPrev(); } } else { SwTwips nBot = getFrameArea().Top() + getFramePrintArea().Bottom(); - while ( pLowerFrame && pLowerFrame->GetPrev() && pLowerFrame->getFrameArea().Top() > nBot ) + while (pLowerFrame && pLowerFrame->GetPrev() + && (pFirstInvalid != nullptr // tdf#152307 trust nothing after invalid frame + || nBot < pLowerFrame->getFrameArea().Top())) { pLowerFrame->InvalidateAll_(); pLowerFrame->InvalidatePage( pPage ); + if (pLowerFrame == pFirstInvalid) + { + pFirstInvalid = nullptr; // continue checking nBot + } pLowerFrame = pLowerFrame->GetPrev(); } } |