sw/qa/core/layout/flycnt.cxx | 15 +++++++++++++++ sw/source/core/layout/objectformatter.cxx | 7 ++++++- sw/source/core/layout/tabfrm.cxx | 4 +++- sw/source/core/text/txtfly.cxx | 17 +++++++++++++++++ 4 files changed, 41 insertions(+), 2 deletions(-)
New commits: commit f5ef52920dadcc6d4d4462078e7f272ebde46713 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Fri Sep 8 08:26:40 2023 +0200 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Thu Sep 14 08:10:00 2023 +0200 sw floattable, nesting: fix PDF export The problem was that the bugdoc rendered fine when opened interactively, but not when converted to PDF via 'soffice --convert-to pdf'. The direct cause was that the interactive case also enabled the navigator that did one more calculation for each fly, and that fixes the layout. The headless export to PDF has no navigator, so that didn't happen. The root of the problem seems to be that: 1) There is a bad left position for the inner follow fly (it's outside the page rectangle). 2) SwTabFrame::Split() for the outer tab normally calls lcl_RecalcSplitLine() which moves flys away + back. 3) Moving away happens in lcl_InvalidateLowerObjs() in the _bMoveObjsOutOfRange case, here we move away both fly 10 and 20 (both inner flys). 4) Moving back happens in SwToContentAnchoredObjectPosition::CalcPosition(), but that's not invoked for the inner follow fly. Fix the problem by extending SwObjectFormatter::FormatObjsAtFrame_() to be more consistent here and move back both flys. This is related to tdf#55160. (cherry picked from commit facdac2443d50339f81415d09c1869d19dded7bf) Change-Id: Ia264a828f36cf2bc1d67986ab3a97d57e9d167a7 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/156811 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> Reviewed-by: Miklos Vajna <vmik...@collabora.com> diff --git a/sw/qa/core/layout/flycnt.cxx b/sw/qa/core/layout/flycnt.cxx index 595d532df572..1f2fbeeb76bb 100644 --- a/sw/qa/core/layout/flycnt.cxx +++ b/sw/qa/core/layout/flycnt.cxx @@ -1068,6 +1068,13 @@ CPPUNIT_TEST_FIXTURE(Test, testSplitFlyNested) // rendered and this way the inner anchor had no fly portion, either. CPPUNIT_ASSERT_GREATER(pPage2->getFrameArea().Top(), pPage2Fly1->getFrameArea().Top()); + // Without the accompanying fix in place, this test would have failed with: + // - Expected less than: 12523 + // - Actual : 15312 + // i.e. the inner follow fly was not "moved back" to its place to have the wanted 4400 position, + // which makes the "Inner A2" text visible. + CPPUNIT_ASSERT_LESS(pPage2->getFrameArea().Right(), pPage2Fly1->getFrameArea().Right()); + auto pPage2Fly2 = rPage2Objs[1]->DynCastFlyFrame()->DynCastFlyAtContentFrame(); CPPUNIT_ASSERT(pPage2Fly2); CPPUNIT_ASSERT(!pPage2Fly2->GetAnchorFrameContainingAnchPos()->IsInFly()); diff --git a/sw/source/core/layout/objectformatter.cxx b/sw/source/core/layout/objectformatter.cxx index 15ca544a2d9c..b99da6a0fe4b 100644 --- a/sw/source/core/layout/objectformatter.cxx +++ b/sw/source/core/layout/objectformatter.cxx @@ -390,7 +390,12 @@ bool SwObjectFormatter::FormatObjsAtFrame_( SwTextFrame* _pMasterTextFrame ) pAnchorCharFrame != pAnchoredObj->GetAnchorFrame() && pAnchorCharFrame->FindBodyFrame() == static_cast<SwTextFrame*>(pAnchoredObj->AnchorFrame())->FindBodyFrame(); - if ( bAnchoredAtFollowInSameBodyAsMaster ) + // Make sure that in case nested split flys are moved "out of range" in + // lcl_InvalidateLowerObjs(), then we moved them back here. + SwFlyFrame* pFly = pAnchoredObj->DynCastFlyFrame(); + bool bSplitFly = pFly && pFly->IsFlySplitAllowed(); + bool bNestedSplitFly = bSplitFly && pAnchorCharFrame && pAnchorCharFrame->IsInFly(); + if (bAnchoredAtFollowInSameBodyAsMaster && !bNestedSplitFly) { continue; } commit f7dbc9f9572474224bd81c5f2588c6ab5fcd97d9 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Thu Sep 7 08:25:18 2023 +0200 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Thu Sep 14 08:09:51 2023 +0200 sw floattable, nesting: fix position of the inner follow table The bugdoc was no longer crashing, but the inner table's follow part on page 2 was not visible. The problem was that lcl_ArrangeLowers() didn't try to update the fly's position when the cell's position changed, now we do this for split flys. The other problem was that as SwTextFly::GetTop() is called by SwTextFly::InitAnchoredObjList(), the inner flys were ignored while collecting the intersecting fly frames for a paragraph, leading to an overlap between the inner follow fly and the inner anchor text. This is now fixed by explicitly checking for the splitfly-in-splitfly case. With this, the ODT bugdoc now renders correctly when opened. (This is related to tdf#55160.) (cherry picked from commit 3aa3f0a1638a8d8006955b62bb647526768be3d8) Change-Id: I60997e7913984872319250b0fb1cb91e02512800 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/156696 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> Reviewed-by: Miklos Vajna <vmik...@collabora.com> diff --git a/sw/qa/core/layout/flycnt.cxx b/sw/qa/core/layout/flycnt.cxx index bebef2eb63c2..595d532df572 100644 --- a/sw/qa/core/layout/flycnt.cxx +++ b/sw/qa/core/layout/flycnt.cxx @@ -1060,6 +1060,14 @@ CPPUNIT_TEST_FIXTURE(Test, testSplitFlyNested) CPPUNIT_ASSERT(pPage2Fly1); CPPUNIT_ASSERT(pPage2Fly1->GetAnchorFrameContainingAnchPos()->IsInFly()); CPPUNIT_ASSERT(pPage2Fly1->GetPrecede()); + + // Without the accompanying fix in place, this test would have failed with: + // - Expected greater than: 6204 + // - Actual : 1725 + // i.e. the inner follow fly had a bad position, it was outside the page rectangle, it was not + // rendered and this way the inner anchor had no fly portion, either. + CPPUNIT_ASSERT_GREATER(pPage2->getFrameArea().Top(), pPage2Fly1->getFrameArea().Top()); + auto pPage2Fly2 = rPage2Objs[1]->DynCastFlyFrame()->DynCastFlyAtContentFrame(); CPPUNIT_ASSERT(pPage2Fly2); CPPUNIT_ASSERT(!pPage2Fly2->GetAnchorFrameContainingAnchPos()->IsInFly()); diff --git a/sw/source/core/layout/tabfrm.cxx b/sw/source/core/layout/tabfrm.cxx index 211bd6b6a68e..67e60cea9c1d 100644 --- a/sw/source/core/layout/tabfrm.cxx +++ b/sw/source/core/layout/tabfrm.cxx @@ -5268,10 +5268,12 @@ static bool lcl_ArrangeLowers( SwLayoutFrame *pLay, tools::Long lYStart, bool bI // on the object positioning. // #i52904# - no direct move of objects, // whose vertical position doesn't depend on anchor frame. + // Also move split flys directly, otherwise the follows would not be moved + // at all. const bool bDirectMove = FAR_AWAY != pFly->getFrameArea().Top() && bVertPosDepOnAnchor && - !pFly->ConsiderObjWrapInfluenceOnObjPos(); + (!pFly->ConsiderObjWrapInfluenceOnObjPos() || pFly->IsFlySplitAllowed()); if ( bDirectMove ) { { diff --git a/sw/source/core/text/txtfly.cxx b/sw/source/core/text/txtfly.cxx index 4b1c0695af35..a4f625651f1e 100644 --- a/sw/source/core/text/txtfly.cxx +++ b/sw/source/core/text/txtfly.cxx @@ -679,6 +679,23 @@ bool SwTextFly::GetTop( const SwAnchoredObject* _pAnchoredObj, bool bEvade = !mpCurrAnchoredObj || Is_Lower_Of( mpCurrAnchoredObj->DynCastFlyFrame(), pNew); + auto pFly = _pAnchoredObj->DynCastFlyFrame(); + if (pFly && pFly->IsFlySplitAllowed()) + { + // Check if _pAnchoredObj is a split fly inside an other split fly. Always collect such + // flys, otherwise the inner anchor text will overlap with the inner fly. + SwFrame* pFlyAnchor = const_cast<SwAnchoredObject*>(_pAnchoredObj) + ->GetAnchorFrameContainingAnchPos(); + if (pFlyAnchor && pFlyAnchor->IsInFly()) + { + auto pOuterFly = pFlyAnchor->FindFlyFrame(); + if (pOuterFly && pOuterFly->IsFlySplitAllowed()) + { + return true; + } + } + } + if ( !bEvade ) { // We are currently inside a fly frame and pNew is not