diff options
author | Michael Stahl <michael.stahl@allotropia.de> | 2021-06-18 19:49:46 +0200 |
---|---|---|
committer | Samuel Mehrbrodt <samuel.mehrbrodt@allotropia.de> | 2022-01-17 16:16:06 +0100 |
commit | d148326ca8dfe8f152801eb341940c69a150c7ee (patch) | |
tree | 343872f3dbeb9030053d7769a430baa68e18190b | |
parent | 3857705b16a5cc2ae5c67a3b0501d922e6c70d6b (diff) |
tdf#116501 sw: layout: check for flys in SwTabFrame::ShouldBwdMoved()
On loading, this hits loop control
warn:legacy.osl:580715:580715:sw/source/core/layout/layact.cxx:543: LoopControl_1 in SwLayAction::InternalAction
This is because there's a fly frame 404 anchored at the last text
frame 353 on page 2 inside the nested table 347.
ShouldBwdMoved() sees that there is space on the bottom of page 2 and
hence the follow flow row joined, but then it immediately splits again
in the same way as before due to the fly with WrapTextMode_NONE.
But then the outer table's cell 273 (upper of 347) is invalidated
again, hence the loop.
Try to check for overlapping flys in SwTabFrame::ShouldBwdMoved()
by reusing CalcFlyOffsets(), which is ... not quite ideal, but perhaps
better than copy-pasting half of it to a new function.
This should have less side effects than the previous fix, but a problem
remains that clicking on the shape on bottom of page 2 causes the layout
to go wonky, but that was also the case with previous fix.
Note there's a check of SwLayouter::DoesRowContainMovedFwdFrame() there
already, but that doesn't help because it will only detect when the fly
itself was moved forward, but in this case the fly remains on the page.
Also likely it wouldn't be a good idea to move a text frame forward if
the only thing of it that fits on a page is an anchored fly (i.e. its
follow has mnOffset=0) because that can be intentional.
Change-Id: I0376f7dcb784c006990336233c97f5093aaccb77
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/117473
Tested-by: Jenkins
Tested-by: László Németh <nemeth@numbertext.org>
Reviewed-by: László Németh <nemeth@numbertext.org>
(cherry picked from commit f1439db62eb36ef5fbc9111b87dc4e0f24b3cb86)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/117602
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
(cherry picked from commit 35a0bfa7bf52ca713ea8e57cd982d16723be920d)
-rw-r--r-- | sw/source/core/doc/htmltbl.cxx | 2 | ||||
-rw-r--r-- | sw/source/core/inc/tabfrm.hxx | 3 | ||||
-rw-r--r-- | sw/source/core/layout/tabfrm.cxx | 50 |
3 files changed, 46 insertions, 9 deletions
diff --git a/sw/source/core/doc/htmltbl.cxx b/sw/source/core/doc/htmltbl.cxx index 346c67c552fe..5482a984238a 100644 --- a/sw/source/core/doc/htmltbl.cxx +++ b/sw/source/core/doc/htmltbl.cxx @@ -363,7 +363,7 @@ sal_uInt16 SwHTMLTableLayout::GetBrowseWidthByTabFrame( SwTwips nUpperDummy = 0; long nRightOffset = 0, nLeftOffset = 0; - rTabFrame.CalcFlyOffsets( nUpperDummy, nLeftOffset, nRightOffset ); + rTabFrame.CalcFlyOffsets(nUpperDummy, nLeftOffset, nRightOffset, nullptr); nWidth -= (nLeftOffset + nRightOffset); return static_cast<sal_uInt16>(std::min(nWidth, SwTwips(SAL_MAX_UINT16))); diff --git a/sw/source/core/inc/tabfrm.hxx b/sw/source/core/inc/tabfrm.hxx index 176396c6667a..73768558ac10 100644 --- a/sw/source/core/inc/tabfrm.hxx +++ b/sw/source/core/inc/tabfrm.hxx @@ -201,7 +201,8 @@ public: bool CalcFlyOffsets( SwTwips& rUpper, long& rLeftOffset, - long& rRightOffset ) const; + long& rRightOffset, + SwTwips * pSpaceBelowBottom) const; SwTwips CalcHeightOfFirstContentLine() const; diff --git a/sw/source/core/layout/tabfrm.cxx b/sw/source/core/layout/tabfrm.cxx index ba85082edcaf..c00a7294e8c3 100644 --- a/sw/source/core/layout/tabfrm.cxx +++ b/sw/source/core/layout/tabfrm.cxx @@ -2740,7 +2740,8 @@ static bool IsNextOnSamePage(SwPageFrame const& rPage, /// Calculate the offsets arising because of FlyFrames bool SwTabFrame::CalcFlyOffsets( SwTwips& rUpper, long& rLeftOffset, - long& rRightOffset ) const + long& rRightOffset, + SwTwips *const pSpaceBelowBottom) const { bool bInvalidatePrtArea = false; const SwPageFrame *pPage = FindPageFrame(); @@ -2760,9 +2761,17 @@ bool SwTabFrame::CalcFlyOffsets( SwTwips& rUpper, long nPrtPos = aRectFnSet.GetTop(getFrameArea()); nPrtPos = aRectFnSet.YInc( nPrtPos, rUpper ); SwRect aRect( getFrameArea() ); - long nYDiff = aRectFnSet.YDiff( aRectFnSet.GetTop(getFramePrintArea()), rUpper ); - if( nYDiff > 0 ) - aRectFnSet.AddBottom( aRect, -nYDiff ); + if (pSpaceBelowBottom) + { // set to space below table frame + aRectFnSet.SetTopAndHeight(aRect, aRectFnSet.GetBottom(aRect), *pSpaceBelowBottom); + } + else + { + long nYDiff = aRectFnSet.YDiff( aRectFnSet.GetTop(getFramePrintArea()), rUpper ); + if (nYDiff > 0) + aRectFnSet.AddBottom( aRect, -nYDiff ); + } + for ( size_t i = 0; i < pPage->GetSortedObjs()->size(); ++i ) { SwAnchoredObject* pAnchoredObj = (*pPage->GetSortedObjs())[i]; @@ -2797,8 +2806,9 @@ bool SwTabFrame::CalcFlyOffsets( SwTwips& rUpper, aFlyRect.IsOver( aRect ) && // fly isn't lower of table and // anchor character frame of fly isn't lower of table - ( !IsAnLower( pFly ) && - ( !pAnchorCharFrame || !IsAnLower( pAnchorCharFrame ) ) ) && + (pSpaceBelowBottom // not if in ShouldBwdMoved + || (!IsAnLower( pFly ) && + (!pAnchorCharFrame || !IsAnLower(pAnchorCharFrame)))) && // table isn't lower of fly !pFly->IsAnLower( this ) && // fly is lower of fly, the table is in @@ -2853,6 +2863,20 @@ bool SwTabFrame::CalcFlyOffsets( SwTwips& rUpper, { if (aRectFnSet.YDiff( nPrtPos, nBottom ) < 0) nPrtPos = nBottom; + // tdf#116501 subtract flys blocking space from below + // TODO this may not work ideally for multiple flys + if (pSpaceBelowBottom + && aRectFnSet.YDiff(aRectFnSet.GetBottom(aRect), nBottom) < 0) + { + if (aRectFnSet.YDiff(aRectFnSet.GetTop(aRect), aRectFnSet.GetTop(aFlyRect)) < 0) + { + aRectFnSet.SetBottom(aRect, aRectFnSet.GetTop(aFlyRect)); + } + else + { + aRectFnSet.SetHeight(aRect, 0); + } + } bInvalidatePrtArea = true; } } @@ -2880,6 +2904,10 @@ bool SwTabFrame::CalcFlyOffsets( SwTwips& rUpper, } } rUpper = aRectFnSet.YDiff( nPrtPos, aRectFnSet.GetTop(getFrameArea()) ); + if (pSpaceBelowBottom) + { + *pSpaceBelowBottom = aRectFnSet.GetHeight(aRect); + } } return bInvalidatePrtArea; @@ -2915,7 +2943,7 @@ void SwTabFrame::Format( vcl::RenderContext* /*pRenderContext*/, const SwBorderA // are right or left aligned, those set the minimum for the borders. long nTmpRight = -1000000, nLeftOffset = 0; - if( CalcFlyOffsets( nUpper, nLeftOffset, nTmpRight ) ) + if (CalcFlyOffsets(nUpper, nLeftOffset, nTmpRight, nullptr)) { setFramePrintAreaValid(false); } @@ -3549,6 +3577,14 @@ bool SwTabFrame::ShouldBwdMoved( SwLayoutFrame *pNewUpper, bool, bool &rReformat const SwViewShell *pSh = getRootFrame()->GetCurrShell(); if( pSh && pSh->GetViewOptions()->getBrowseMode() ) nSpace += pNewUpper->Grow( LONG_MAX, true ); + if (0 < nSpace && GetPrecede()) + { + SwTwips nUpperDummy(0); + long nLeftOffsetDummy(0), nRightOffsetDummy(0); + // tdf#116501 check for no-wrap fly overlap + static_cast<const SwTabFrame*>(GetPrecede())->CalcFlyOffsets( + nUpperDummy, nLeftOffsetDummy, nRightOffsetDummy, &nSpace); + } } } else if (!m_bLockBackMove) |