sw/source/core/inc/flowfrm.hxx | 3 ++ sw/source/core/layout/calcmove.cxx | 49 +++++++++++++++++++++++++--------- sw/source/core/layout/flowfrm.cxx | 52 +++++++++++++++++++++++++++++++++---- sw/source/core/layout/fly.cxx | 5 ++- sw/source/core/layout/frmtool.cxx | 2 - 5 files changed, 90 insertions(+), 21 deletions(-)
New commits: commit 75a0e9c5f8b364e194e087a6255f8174f55bbda6 Author: Michael Stahl <michael.st...@allotropia.de> AuthorDate: Fri Dec 6 14:20:22 2024 +0100 Commit: Adolfo Jayme Barrientos <fit...@ubuntu.com> CommitDate: Tue Dec 24 14:10:17 2024 +0100 sw: layout: ignore Keep-With-Next on hidden frames, part2 SwFrame::PrepareMake(), SwContentFrame::MakeAll(), SwContentFrame::WouldFit_() Change-Id: I2a909ac6d147668dddece97bd99e31fdddcf20eb Reviewed-on: https://gerrit.libreoffice.org/c/core/+/177976 Tested-by: Michael Stahl <michael.st...@allotropia.de> Reviewed-by: Michael Stahl <michael.st...@allotropia.de> (cherry picked from commit a08b8fa2d01e630ef876b7944c37f0b6de09d407) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/177996 Tested-by: Jenkins Reviewed-by: Adolfo Jayme Barrientos <fit...@ubuntu.com> diff --git a/sw/source/core/layout/calcmove.cxx b/sw/source/core/layout/calcmove.cxx index e04edcddd5a9..338030c7c03d 100644 --- a/sw/source/core/layout/calcmove.cxx +++ b/sw/source/core/layout/calcmove.cxx @@ -304,9 +304,17 @@ void SwFrame::PrepareMake(vcl::RenderContext* pRenderContext) // There is no format of previous frame, if current frame is a table // frame and its previous frame wants to keep with it. - const bool bFormatPrev = !bTab || - !GetPrev() || - !GetPrev()->GetAttrSet()->GetKeep().GetValue(); + bool bFormatPrev{!bTab}; + if (!bFormatPrev) + { + SwFrame const* pPrev{this}; + do + { + pPrev = pPrev->GetPrev(); + } + while (pPrev && pPrev->IsHiddenNow()); + bFormatPrev = pPrev && !pPrev->GetAttrSet()->GetKeep().GetValue(); + } if ( bFormatPrev ) { SwFrame *pFrame = GetUpper()->Lower(); @@ -1351,7 +1359,7 @@ void SwContentFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/) oNotify->SetBordersJoinedWithPrev(); } - const bool bKeep = IsKeep(rAttrs.GetAttrSet().GetKeep(), GetBreakItem()); + const bool bKeep{!isHiddenNow && IsKeep(rAttrs.GetAttrSet().GetKeep(), GetBreakItem())}; std::unique_ptr<SwSaveFootnoteHeight> pSaveFootnote; if ( bFootnote ) @@ -1767,7 +1775,7 @@ void SwContentFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/) if( nBottomDist >= 0 ) { - if ( bKeep && bMoveable ) + if (bKeep && bMoveable && !isHiddenNow) { // We make sure the successor will be formatted the same. // This way, we keep control until (almost) everything is stable, @@ -2094,8 +2102,18 @@ bool SwContentFrame::WouldFit_( SwTwips nSpace, const SwFrame *pTmpPrev = pNewUpper->Lower(); if( pTmpPrev && pTmpPrev->IsFootnoteFrame() ) pTmpPrev = static_cast<const SwFootnoteFrame*>(pTmpPrev)->Lower(); - while ( pTmpPrev && pTmpPrev->GetNext() ) - pTmpPrev = pTmpPrev->GetNext(); + { + SwFrame const* pTmpNonHidden{pTmpPrev && pTmpPrev->IsHiddenNow() ? nullptr : pTmpPrev}; + while (pTmpPrev && pTmpPrev->GetNext()) + { + pTmpPrev = pTmpPrev->GetNext(); + if (!pTmpPrev->IsHiddenNow()) + { + pTmpNonHidden = pTmpPrev; + } + } + pTmpPrev = pTmpNonHidden; + } // tdf#156727 if the previous one has keep-with-next, ignore it on this one! bool const isIgnoreKeep(pTmpPrev && pTmpPrev->IsFlowFrame() @@ -2104,6 +2122,14 @@ bool SwContentFrame::WouldFit_( SwTwips nSpace, do { + if (pFrame->IsHiddenNow()) + { // shortcut + assert(pFrame == this); + bRet = true; + pFrame = nullptr; + break; + } + // #i46181# SwTwips nSecondCheck = 0; SwTwips nOldSpace = nSpace; @@ -2269,8 +2295,8 @@ bool SwContentFrame::WouldFit_( SwTwips nSpace, return true; } } - SwFrame *pNxt; - if( nullptr != (pNxt = pFrame->FindNext()) && pNxt->IsContentFrame() && + SwFrame *const pNxt{pFrame->FindNextIgnoreHidden()}; + if (nullptr != pNxt && pNxt->IsContentFrame() && ( !pFootnoteFrame || ( pNxt->IsInFootnote() && pNxt->FindFootnoteFrame()->GetAttr() == pFootnoteFrame->GetAttr() ) ) ) { @@ -2296,10 +2322,7 @@ bool SwContentFrame::WouldFit_( SwTwips nSpace, pTmpPrev = nullptr; else { - if (pFrame->IsHiddenNow()) - pTmpPrev = lcl_NotHiddenPrev( pFrame ); - else - pTmpPrev = pFrame; + pTmpPrev = pFrame; } pFrame = static_cast<SwContentFrame*>(pNxt); } commit ea2d36e7cc290200609da2ab133e1f682dd4a22b Author: Michael Stahl <michael.st...@allotropia.de> AuthorDate: Fri Dec 6 14:10:32 2024 +0100 Commit: Adolfo Jayme Barrientos <fit...@ubuntu.com> CommitDate: Tue Dec 24 14:10:08 2024 +0100 sw: layout: ignore Keep-With-Next on hidden frames, part1 When a frame is hidden, don't consider it when evaluating keep-with-next attributes - this was the case for content in hidden sections before commit 0c96119895b347f8eb5bb89f393351bd3c02b9f1 ~SwFrameNotify() invalidating position of hidden frame with keep attribute causes layout loops. Also skip hidden frames in SwFlowFrame::IsKeepFwdMoveAllowed(), SwFlowFrame::CheckKeep(), SwFlowFrame::IsPrevObjMove(), SwFlowFrame::MoveBwd(), CalcContent(). Change-Id: I68556ba0a8e016d962399f3ce199e5eda0378867 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/177975 Tested-by: Michael Stahl <michael.st...@allotropia.de> Reviewed-by: Michael Stahl <michael.st...@allotropia.de> (cherry picked from commit cd8468bcba952ab9b0d6ca97152a63d7469a9209) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/177995 Tested-by: Jenkins Reviewed-by: Adolfo Jayme Barrientos <fit...@ubuntu.com> diff --git a/sw/source/core/inc/flowfrm.hxx b/sw/source/core/inc/flowfrm.hxx index 154fd37febf2..c8ca0b55cd06 100644 --- a/sw/source/core/inc/flowfrm.hxx +++ b/sw/source/core/inc/flowfrm.hxx @@ -184,6 +184,9 @@ public: SvxFormatBreakItem const& rBreak, bool bBreakCheck = false ) const; + SwFrame * FindPrevIgnoreHidden() const; + SwFrame * FindNextIgnoreHidden() const; + bool HasLockedFollow() const; bool HasParaSpaceAtPages( bool bSct ) const; diff --git a/sw/source/core/layout/flowfrm.cxx b/sw/source/core/layout/flowfrm.cxx index b45c8d100fcb..8a2bab2647bb 100644 --- a/sw/source/core/layout/flowfrm.cxx +++ b/sw/source/core/layout/flowfrm.cxx @@ -131,7 +131,9 @@ bool SwFlowFrame::IsKeepFwdMoveAllowed( bool bIgnoreMyOwnKeepValue ) if ( bIgnoreMyOwnKeepValue && pFrame->GetIndPrev() ) pFrame = pFrame->GetIndPrev(); do - { if ( pFrame->GetAttrSet()->GetKeep().GetValue() ) + { + if (pFrame->GetAttrSet()->GetKeep().GetValue() + || pFrame->IsHiddenNow()) pFrame = pFrame->GetIndPrev(); else return true; @@ -150,22 +152,42 @@ void SwFlowFrame::CheckKeep() // it's possible for the whole troop to move back. SwFrame *pPre = m_rThis.GetIndPrev(); assert(pPre); + while (pPre && pPre->IsHiddenNow()) + { + pPre = pPre->GetIndPrev(); + } + if (!pPre) + { + return; + } if( pPre->IsSctFrame() ) { SwFrame *pLast = static_cast<SwSectionFrame*>(pPre)->FindLastContent(); + while (pLast && pLast->IsHiddenNow()) + { + pLast = pLast->GetIndPrev(); + } if( pLast && pLast->FindSctFrame() == pPre ) pPre = pLast; else return; } - SwFrame* pTmp; + SwFrame* pTmp{pPre}; bool bKeep; while ( (bKeep = pPre->GetAttrSet()->GetKeep().GetValue()) && - nullptr != ( pTmp = pPre->GetIndPrev() ) ) + nullptr != (pTmp = pTmp->GetIndPrev()) ) { + if (pTmp->IsHiddenNow()) + { + continue; + } if( pTmp->IsSctFrame() ) { SwFrame *pLast = static_cast<SwSectionFrame*>(pTmp)->FindLastContent(); + while (pLast && pLast->IsHiddenNow()) + { + pLast = pLast->GetIndPrev(); + } if( pLast && pLast->FindSctFrame() == pTmp ) pTmp = pLast; else @@ -338,6 +360,26 @@ bool SwFlowFrame::IsKeep(SvxFormatKeepItem const& rKeep, return bKeep; } +SwFrame * SwFlowFrame::FindPrevIgnoreHidden() const +{ + SwFrame * pRet{m_rThis.FindPrev()}; + while (pRet && pRet->IsHiddenNow()) + { + pRet = pRet->FindPrev(); + } + return pRet; +} + +SwFrame * SwFlowFrame::FindNextIgnoreHidden() const +{ + SwFrame * pRet{m_rThis.FindNext()}; + while (pRet && pRet->IsHiddenNow()) + { + pRet = pRet->FindNext(); + } + return pRet; +} + sal_uInt8 SwFlowFrame::BwdMoveNecessary( const SwPageFrame *pPage, const SwRect &rRect ) { // The return value helps deciding whether we need to flow back (3), @@ -1188,7 +1230,7 @@ bool SwFlowFrame::IsPrevObjMove() const if( pSh && pSh->GetViewOptions()->getBrowseMode() ) return false; - SwFrame *pPre = m_rThis.FindPrev(); + SwFrame *const pPre{FindPrevIgnoreHidden()}; if ( pPre && pPre->GetDrawObjs() ) { @@ -2616,7 +2658,7 @@ bool SwFlowFrame::MoveBwd( bool &rbReformat ) // keep with next frame and next frame is locked. // i#38232 - If next frame is a table, do *not* check, // if it's locked. - if ( pNewUpper && !IsFollow() && + if ( pNewUpper && !IsFollow() && !m_rThis.IsHiddenNow() && m_rThis.GetAttrSet()->GetKeep().GetValue() && m_rThis.GetIndNext() ) { SwFrame* pIndNext = m_rThis.GetIndNext(); diff --git a/sw/source/core/layout/fly.cxx b/sw/source/core/layout/fly.cxx index 313f047ece98..f4cefef5ae29 100644 --- a/sw/source/core/layout/fly.cxx +++ b/sw/source/core/layout/fly.cxx @@ -1698,9 +1698,10 @@ void CalcContent( SwLayoutFrame *pLay, bool bNoColl ) // frame due to its keep-attribute, if it can't move forward. // #i57765# - do not consider invalid previous // frame, if current frame has a column/page break before attribute. - SwFrame* pTmpPrev = pFrame->FindPrev(); + assert(pFrame->IsFlowFrame()); + SwFlowFrame* pTmpFlowFrame = SwFlowFrame::CastFlowFrame(pFrame); + SwFrame* pTmpPrev = pTmpFlowFrame->FindPrevIgnoreHidden(); SwFlowFrame* pTmpPrevFlowFrame = pTmpPrev && pTmpPrev->IsFlowFrame() ? SwFlowFrame::CastFlowFrame(pTmpPrev) : nullptr; - SwFlowFrame* pTmpFlowFrame = pFrame->IsFlowFrame() ? SwFlowFrame::CastFlowFrame(pFrame) : nullptr; bool bPrevInvalid = pTmpPrevFlowFrame && pTmpFlowFrame && !pTmpFlowFrame->IsFollow() && diff --git a/sw/source/core/layout/frmtool.cxx b/sw/source/core/layout/frmtool.cxx index 05b968737cc3..95c008a8af42 100644 --- a/sw/source/core/layout/frmtool.cxx +++ b/sw/source/core/layout/frmtool.cxx @@ -155,7 +155,7 @@ void SwFrameNotify::ImplDestroy() { if ( mbInvaKeep ) { - SwFrame *pPre = mpFrame->FindPrev(); + SwFrame *pPre = pFlow->FindPrevIgnoreHidden(); if ( pPre && pPre->IsFlowFrame() ) { // 1. pPre wants to keep with me: