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

Reply via email to