summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Stahl <michael.stahl@allotropia.de>2021-06-18 19:49:46 +0200
committerXisco Fauli <xiscofauli@libreoffice.org>2021-06-22 09:35:29 +0200
commit35a0bfa7bf52ca713ea8e57cd982d16723be920d (patch)
treec65db8fc656c568de13f0cce143997723e96732e
parentRevert "tdf#116501 fix freezing at embedded text tables" (diff)
downloadcore-35a0bfa7bf52ca713ea8e57cd982d16723be920d.tar.gz
core-35a0bfa7bf52ca713ea8e57cd982d16723be920d.zip
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>
-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.cxx49
3 files changed, 45 insertions, 9 deletions
diff --git a/sw/source/core/doc/htmltbl.cxx b/sw/source/core/doc/htmltbl.cxx
index 31edb6dff0bc..dd0011bfacad 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;
tools::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 7e302473a421..34010d96a9c3 100644
--- a/sw/source/core/inc/tabfrm.hxx
+++ b/sw/source/core/inc/tabfrm.hxx
@@ -203,7 +203,8 @@ public:
bool CalcFlyOffsets(
SwTwips& rUpper,
tools::Long& rLeftOffset,
- tools::Long& rRightOffset ) const;
+ tools::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 05069534af8d..d639e4d18d74 100644
--- a/sw/source/core/layout/tabfrm.cxx
+++ b/sw/source/core/layout/tabfrm.cxx
@@ -2730,7 +2730,8 @@ static bool IsNextOnSamePage(SwPageFrame const& rPage,
/// Calculate the offsets arising because of FlyFrames
bool SwTabFrame::CalcFlyOffsets( SwTwips& rUpper,
tools::Long& rLeftOffset,
- tools::Long& rRightOffset ) const
+ tools::Long& rRightOffset,
+ SwTwips *const pSpaceBelowBottom) const
{
bool bInvalidatePrtArea = false;
const SwPageFrame *pPage = FindPageFrame();
@@ -2750,9 +2751,16 @@ bool SwTabFrame::CalcFlyOffsets( SwTwips& rUpper,
tools::Long nPrtPos = aRectFnSet.GetTop(getFrameArea());
nPrtPos = aRectFnSet.YInc( nPrtPos, rUpper );
SwRect aRect( getFrameArea() );
- tools::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
+ {
+ tools::Long nYDiff = aRectFnSet.YDiff( aRectFnSet.GetTop(getFramePrintArea()), rUpper );
+ if (nYDiff > 0)
+ aRectFnSet.AddBottom( aRect, -nYDiff );
+ }
bool bAddVerticalFlyOffsets = rIDSA.get(DocumentSettingId::ADD_VERTICAL_FLY_OFFSETS);
@@ -2789,8 +2797,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
@@ -2872,6 +2881,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;
}
}
@@ -2899,6 +2922,10 @@ bool SwTabFrame::CalcFlyOffsets( SwTwips& rUpper,
}
}
rUpper = aRectFnSet.YDiff( nPrtPos, aRectFnSet.GetTop(getFrameArea()) );
+ if (pSpaceBelowBottom)
+ {
+ *pSpaceBelowBottom = aRectFnSet.GetHeight(aRect);
+ }
}
return bInvalidatePrtArea;
@@ -2934,7 +2961,7 @@ void SwTabFrame::Format( vcl::RenderContext* /*pRenderContext*/, const SwBorderA
// those are right or left aligned, those set the minimum for the margins
tools::Long nTmpRight = -1000000,
nLeftOffset = 0;
- if( CalcFlyOffsets( nUpper, nLeftOffset, nTmpRight ) )
+ if (CalcFlyOffsets(nUpper, nLeftOffset, nTmpRight, nullptr))
{
setFramePrintAreaValid(false);
}
@@ -3579,6 +3606,14 @@ bool SwTabFrame::ShouldBwdMoved( SwLayoutFrame *pNewUpper, 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);
+ tools::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)