sw/qa/core/text/data/floattable-bad-fly-pos.docx |binary
 sw/qa/core/text/frmform.cxx                      |   30 +++++++++++++++++++++++
 sw/source/core/text/frmform.cxx                  |   14 ++++++++--
 3 files changed, 41 insertions(+), 3 deletions(-)

New commits:
commit 8451b04506c88dc748a0a98177483f671625636b
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Fri Sep 29 09:01:29 2023 +0200
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Tue Oct 3 09:30:24 2023 +0200

    Related: tdf#126449 sw floattable: fix bad position of in-table follow fly
    
    The reduced bugdoc is of 4 pages, an inner floating table should be on
    pages 2 -> 4 but was only on 2 -> 3.
    
    The reason for this seems to be that we correctly split the inner table
    twice, but the 3rd fly frame in the chain is positioned on page 3, and
    once the anchor moves to page 4, we never re-position the fly frame. The
    fly frame is normally only positioned once, since the position of the
    anchor and the fly frame depend on each other, so the loop has to be
    broken, and this is normally done by locking the position of the fly
    after one positioning.
    
    Fix the problem by extending the condition when to unlock the position
    of anchored fly frames in SwTextFrame::MakePos(): similar to not yet
    positioned fly frames, do one more cycle in case the anchor and the fly
    frame are not on the same page.
    
    This just fixes a simplified DOCX bugdoc, the full document still needs
    more fixes.
    
    (cherry picked from commit 83abd141bf41c1c8a1d4e5a894b235c842da2a07)
    
    Conflicts:
            sw/source/core/text/frmform.cxx
    
    Change-Id: I066c64cf4e12bf31f22218f84f0f2425256ba63e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/157496
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

diff --git a/sw/qa/core/text/data/floattable-bad-fly-pos.docx 
b/sw/qa/core/text/data/floattable-bad-fly-pos.docx
new file mode 100644
index 000000000000..a0a8bb4dbdb9
Binary files /dev/null and b/sw/qa/core/text/data/floattable-bad-fly-pos.docx 
differ
diff --git a/sw/qa/core/text/frmform.cxx b/sw/qa/core/text/frmform.cxx
index f2f942bde324..ee791f325729 100644
--- a/sw/qa/core/text/frmform.cxx
+++ b/sw/qa/core/text/frmform.cxx
@@ -116,6 +116,36 @@ CPPUNIT_TEST_FIXTURE(Test, 
testFloattableAvoidLastManipOfst)
     CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0),
                          static_cast<sal_Int32>(pAnchorText->GetOffset()));
 }
+
+CPPUNIT_TEST_FIXTURE(Test, testFloattableBadFlyPos)
+{
+    // Given a document with an inner floating table on page 2 -> 4:
+    // When laying out that document:
+    createSwDoc("floattable-bad-fly-pos.docx");
+
+    // Then make sure that pages 2 -> 4 get the 3 fly frames:
+    SwDoc* pDoc = getSwDoc();
+    SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
+    auto pPage1 = pLayout->Lower()->DynCastPageFrame();
+    CPPUNIT_ASSERT(pPage1);
+    CPPUNIT_ASSERT(!pPage1->GetSortedObjs());
+    auto pPage2 = pPage1->GetNext()->DynCastPageFrame();
+    CPPUNIT_ASSERT(pPage2);
+    CPPUNIT_ASSERT(pPage2->GetSortedObjs());
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), 
pPage2->GetSortedObjs()->size());
+    auto pPage3 = pPage2->GetNext()->DynCastPageFrame();
+    CPPUNIT_ASSERT(pPage3);
+    CPPUNIT_ASSERT(pPage3->GetSortedObjs());
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: 1
+    // - Actual  : 2
+    // i.e. the fly on page 4 was still on page 3.
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), 
pPage3->GetSortedObjs()->size());
+    auto pPage4 = pPage3->GetNext()->DynCastPageFrame();
+    CPPUNIT_ASSERT(pPage4);
+    CPPUNIT_ASSERT(pPage4->GetSortedObjs());
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), 
pPage4->GetSortedObjs()->size());
+}
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/frmform.cxx b/sw/source/core/text/frmform.cxx
index 864a1d5c031f..a30a2eee633f 100644
--- a/sw/source/core/text/frmform.cxx
+++ b/sw/source/core/text/frmform.cxx
@@ -363,10 +363,18 @@ void SwTextFrame::MakePos()
             // Possibly this fly was positioned relative to us, invalidate its 
position now that our
             // position is changed.
             SwPageFrame* pPageFrame = pFly->FindPageFrame();
-            if (pPageFrame && pFly->getFrameArea().Pos() == 
pPageFrame->getFrameArea().Pos())
+            bool bFlyNeedsPositioning = false;
+            bool bFlyPageMismatch = false;
+            if (pPageFrame)
             {
-                // The position was just adjusted to be be inside the page 
frame, so not really
-                // positioned, unlock the position once to allow a recalc.
+                // Was the position just adjusted to be inside the page frame?
+                bFlyNeedsPositioning = pFly->getFrameArea().Pos() == 
pPageFrame->getFrameArea().Pos();
+                // Is the fly on a page different than the anchor frame?
+                bFlyPageMismatch = pPageFrame != FindPageFrame();
+            }
+            if (bFlyNeedsPositioning || bFlyPageMismatch)
+            {
+                // Not really positioned, unlock the position once to allow a 
recalc.
                 pFly->UnlockPosition();
             }
             pFly->InvalidatePos();

Reply via email to