sw/qa/core/layout/data/floattable-nested-overlap.odt               |binary
 sw/qa/core/layout/flycnt.cxx                                       |   23 
+++++++++
 sw/source/core/layout/tabfrm.cxx                                   |   23 
+--------
 sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx |   24 
++++++++--
 4 files changed, 48 insertions(+), 22 deletions(-)

New commits:
commit e20bacc209a8e8483209cb4ec51c9e0b55423cdb
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Mon Sep 11 08:26:43 2023 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Mon Sep 11 09:22:37 2023 +0200

    sw floattable, nesting: fix overlap support
    
    The bugdoc had a nested, split floating table with overlap=never and
    that lead to a layout loop.
    
    The root of the trouble seems to be that the inner fly will obviously
    overlap with its outer fly but we tried to prevent that and we failed.
    
    Fix the problem by ignoring inner flys in
    SwToContentAnchoredObjectPosition::CalcOverlap().
    
    This also allows removing special handling of nested split flys in
    lcl_ArrangeLowers() and special handling of split flys at an other place
    in the same function, because now the non-bDirectMove case works out of
    the box.
    
    Change-Id: Icf3a8f776aa758ef4ae2c2994a7216c5a6142a62
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/156810
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins

diff --git a/sw/qa/core/layout/data/floattable-nested-overlap.odt 
b/sw/qa/core/layout/data/floattable-nested-overlap.odt
new file mode 100644
index 000000000000..b90ae9a7b01e
Binary files /dev/null and 
b/sw/qa/core/layout/data/floattable-nested-overlap.odt differ
diff --git a/sw/qa/core/layout/flycnt.cxx b/sw/qa/core/layout/flycnt.cxx
index 1c69606c8a24..73a107c4bc5e 100644
--- a/sw/qa/core/layout/flycnt.cxx
+++ b/sw/qa/core/layout/flycnt.cxx
@@ -1080,6 +1080,29 @@ CPPUNIT_TEST_FIXTURE(Test, testSplitFlyNested)
     CPPUNIT_ASSERT(!pPage2Fly2->GetAnchorFrameContainingAnchPos()->IsInFly());
     CPPUNIT_ASSERT(pPage2Fly2->GetPrecede());
 }
+
+CPPUNIT_TEST_FIXTURE(Test, testSplitFlyNestedOverlap)
+{
+    // Given a document with a nested, multi-page floating table, enabling the 
"don't overlap" logic:
+    // When calculating the layout:
+    createSwDoc("floattable-nested-overlap.odt");
+    calcLayout();
+
+    // Then make sure we get 2 pages (2 flys on each page):
+    // Without the accompanying fix in place, this test would have failed with 
a layout loop.
+    SwDoc* pDoc = getSwDoc();
+    SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
+    auto pPage1 = pLayout->Lower()->DynCastPageFrame();
+    CPPUNIT_ASSERT(pPage1);
+    CPPUNIT_ASSERT(pPage1->GetSortedObjs());
+    SwSortedObjs& rPage1Objs = *pPage1->GetSortedObjs();
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), rPage1Objs.size());
+    auto pPage2 = pPage1->GetNext()->DynCastPageFrame();
+    CPPUNIT_ASSERT(pPage2);
+    CPPUNIT_ASSERT(pPage2->GetSortedObjs());
+    SwSortedObjs& rPage2Objs = *pPage2->GetSortedObjs();
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), rPage2Objs.size());
+}
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/tabfrm.cxx b/sw/source/core/layout/tabfrm.cxx
index bbd7ebece6d8..68bb19b7f39d 100644
--- a/sw/source/core/layout/tabfrm.cxx
+++ b/sw/source/core/layout/tabfrm.cxx
@@ -5287,24 +5287,11 @@ static bool lcl_ArrangeLowers( SwLayoutFrame *pLay, 
tools::Long lYStart, bool bI
                 lcl_ArrangeLowers( static_cast<SwLayoutFrame*>(pFrame),
                     
aRectFnSet.GetTop(static_cast<SwLayoutFrame*>(pFrame)->Lower()->getFrameArea())
                     + lDiffX, bInva );
-            SwSortedObjs* pDrawObjs = pFrame->GetDrawObjs();
-            auto pTextFrame = pFrame->DynCastTextFrame();
-            if (pTextFrame && pTextFrame->IsInFly())
+            if ( pFrame->GetDrawObjs() )
             {
-                // See if this is a follow anchor. If so, we want the flys 
anchored in the master
-                // which are also lowers of pFrame.
-                SwTextFrame* pMaster = pTextFrame;
-                while (pMaster->IsFollow())
+                for ( size_t i = 0; i < pFrame->GetDrawObjs()->size(); ++i )
                 {
-                    pMaster = pMaster->FindMaster();
-                }
-                pDrawObjs = pMaster->GetDrawObjs();
-            }
-            if (pDrawObjs)
-            {
-                for (size_t i = 0; i < pDrawObjs->size(); ++i)
-                {
-                    SwAnchoredObject* pAnchoredObj = (*pDrawObjs)[i];
+                    SwAnchoredObject* pAnchoredObj = 
(*pFrame->GetDrawObjs())[i];
                     // #i26945# - check, if anchored object
                     // is lower of layout frame by checking, if the anchor
                     // frame, which contains the anchor position, is a lower
@@ -5338,12 +5325,10 @@ 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->IsFlySplitAllowed());
+                                !pFly->ConsiderObjWrapInfluenceOnObjPos();
                         if ( bDirectMove )
                         {
                             {
diff --git a/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx 
b/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx
index 9c1c491b24c9..b83d979d31b7 100644
--- a/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx
+++ b/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx
@@ -1212,6 +1212,14 @@ void 
SwToContentAnchoredObjectPosition::CalcOverlap(const SwTextFrame* pAnchorFr
         // At least for split flys we need to consider objects on the same 
page, but anchored in
         // different text frames.
         bSplitFly = true;
+
+        SwFrame* pFlyFrameAnchor = 
pFlyFrame->GetAnchorFrameContainingAnchPos();
+        if (pFlyFrameAnchor && pFlyFrameAnchor->IsInFly())
+        {
+            // An inner fly overlapping with its outer fly is fine.
+            return;
+        }
+
         const SwPageFrame* pPageFrame = 
pAnchorFrameForVertPos->FindPageFrame();
         if (pPageFrame)
         {
@@ -1239,10 +1247,20 @@ void 
SwToContentAnchoredObjectPosition::CalcOverlap(const SwTextFrame* pAnchorFr
         }
 
         SwFlyFrame* pAnchoredObjFly = pAnchoredObj->DynCastFlyFrame();
-        if (bSplitFly && !pAnchoredObjFly)
+        if (bSplitFly)
         {
-            // This is a split fly, then overlap is only checked against other 
split flys.
-            continue;
+            if (!pAnchoredObjFly)
+            {
+                // This is a split fly, then overlap is only checked against 
other split flys.
+                continue;
+            }
+
+            SwFrame* pAnchoredObjFlyAnchor = 
pAnchoredObjFly->GetAnchorFrameContainingAnchPos();
+            if (pAnchoredObjFlyAnchor && pAnchoredObjFlyAnchor->IsInFly())
+            {
+                // An inner fly overlapping with its outer fly is fine.
+                continue;
+            }
         }
 
         css::text::WrapTextMode eWrap = 
pAnchoredObj->GetFrameFormat().GetSurround().GetSurround();

Reply via email to