summaryrefslogtreecommitdiffstats
path: root/sw/source/core/layout/calcmove.cxx
diff options
context:
space:
mode:
authorMichael Stahl <michael.stahl@allotropia.de>2022-10-14 16:59:42 +0200
committerXisco Fauli <xiscofauli@libreoffice.org>2023-02-15 11:40:56 +0000
commitd31b30a6bb044bedd4e296c4cbb3e0fc9c2cb7b6 (patch)
treecc54c295fc52022059560705443718f189f98069 /sw/source/core/layout/calcmove.cxx
parentdisable script dump (diff)
downloadcore-d31b30a6bb044bedd4e296c4cbb3e0fc9c2cb7b6.tar.gz
core-d31b30a6bb044bedd4e296c4cbb3e0fc9c2cb7b6.zip
tdf#146500 sw: try to fix some layout loops caused by fly in table cell
Reportedly regression from commit 1cb7e4899b5ada902e99a0c964ee047950c07044 but reverting that on master doesn't seem to help. Inserting paragraphs with single letters into the first cell on page 2, once we get to "s" and press Enter, the infinite loop happens as text frame 56 is split at index 0 (where a fly is anchored), the new follow moves to page 3, and very quickly frame 56 is formatted again and all text in the follow moves back to page 2, where it doesn't fit with its anchored fly. The problem here is that the (Word format) file sets the ConsiderObjWrapInfluenceOnObjPos mode, which disables any use of the SwLayouter::FrameMovedFwdByObjPos() etc. functions. Oddly enough the spec obj-pos-without-wrapping.sxw claims that in this mode, "If a paragraph respectively one of the anchor characters moves to the next page during its format in step (2) or (4), the process is re-started with this paragraph, the complete paragraph is moved to the next page and it is assured that the paragraph doesn't move back again." What happens instead is that when a fly position is changed, its mbRestartLayoutProcess flag is set. So let's try to check this flag during SwTextFrame::Format(): stop at a position where a fly is anchored in a follow frame that has the flag set, via rInf.SetStop(true). This is similar to a check in SwFlowFrame::MoveBwd() that prevents a frame from moving back if it has an anchored fly with this flag set. Now we get a different loop, where the text frame moves forward, then back and then splits again. This is because ShouldBwdMoved() sees that the first line of the text frame fits into the cell of the previous page - but the first line consists only of a SwFlyPortion and a SwMarginPortion, for the fly anchored in the same text frame. So change WidowsAndOrphans::WouldFit() to continue until the first line that doesn't consist entirely of flys. Then there's another loop where the follow flow row is joined and then splits again - this is very similar to the previous problem, change SwTextFrame::FirstLineHeight() (which is only called from table code) to continue until a non-fly line as well. Unforunately this is all not so clear because we can't actually tell which text frame contains the anchor of a SwFlyPortion, so let's see what's going to break with these changes. Change-Id: Ia6e80f86f6ca3d2e3d91651b6a403c050d74ebfa Reviewed-on: https://gerrit.libreoffice.org/c/core/+/141383 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.stahl@allotropia.de> (cherry picked from commit 8c32cc17ce914188ea6783b0f79e19c5ddbf0b8d) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/146698 Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
Diffstat (limited to 'sw/source/core/layout/calcmove.cxx')
-rw-r--r--sw/source/core/layout/calcmove.cxx8
1 files changed, 4 insertions, 4 deletions
diff --git a/sw/source/core/layout/calcmove.cxx b/sw/source/core/layout/calcmove.cxx
index c9d5622ba02d..184373585928 100644
--- a/sw/source/core/layout/calcmove.cxx
+++ b/sw/source/core/layout/calcmove.cxx
@@ -1761,7 +1761,7 @@ void SwContentFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/)
SwTwips nTmp = aRectFnSet.GetHeight(GetUpper()->getFramePrintArea()) -
aRectFnSet.GetTop(getFramePrintArea());
bool bSplit = !IsFwdMoveAllowed();
- if ( nTmp > 0 && WouldFit( nTmp, bSplit, false ) )
+ if (nTmp > 0 && WouldFit(nTmp, bSplit, false, false))
{
Prepare( PrepareHint::WidowsOrphans, nullptr, false );
setFrameAreaSizeValid(false);
@@ -2046,7 +2046,7 @@ bool SwContentFrame::WouldFit_( SwTwips nSpace,
bRet = static_cast<SwTextFrame*>(pFrame)->TestFormat( pTmpPrev, nSpace, bSplit );
}
else
- bRet = pFrame->WouldFit( nSpace, bSplit, false );
+ bRet = pFrame->WouldFit(nSpace, bSplit, false, true);
pTmpFrame->RemoveFromLayout();
pTmpFrame->InsertBefore( pUp, pOldNext );
@@ -2054,7 +2054,7 @@ bool SwContentFrame::WouldFit_( SwTwips nSpace,
}
else
{
- bRet = pFrame->WouldFit( nSpace, bSplit, false );
+ bRet = pFrame->WouldFit(nSpace, bSplit, false, true);
nSecondCheck = !bSplit ? 1 : 0;
}
@@ -2123,7 +2123,7 @@ bool SwContentFrame::WouldFit_( SwTwips nSpace,
// We do a second check with the original remaining space
// reduced by the required upper space:
nOldSpace -= nSecondCheck;
- const bool bSecondRet = nOldSpace >= 0 && pFrame->WouldFit( nOldSpace, bOldSplit, false );
+ const bool bSecondRet = nOldSpace >= 0 && pFrame->WouldFit(nOldSpace, bOldSplit, false, true);
if ( bSecondRet && bOldSplit && nOldSpace >= 0 )
{
bRet = true;