summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Stahl <michael.stahl@allotropia.de>2021-06-18 19:49:46 +0200
committerSamuel Mehrbrodt <samuel.mehrbrodt@allotropia.de>2022-01-17 16:16:06 +0100
commitd148326ca8dfe8f152801eb341940c69a150c7ee (patch)
tree343872f3dbeb9030053d7769a430baa68e18190b
parent3857705b16a5cc2ae5c67a3b0501d922e6c70d6b (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.cxx2
-rw-r--r--sw/source/core/inc/tabfrm.hxx3
-rw-r--r--sw/source/core/layout/tabfrm.cxx50
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)