sw/qa/core/text/data/floattable-avoid-manip-ofst.docx |binary
 sw/qa/core/text/frmform.cxx                           |   20 ++++++++++++++++++
 sw/source/core/text/frmform.cxx                       |    8 +++++++
 3 files changed, 28 insertions(+)

New commits:
commit 4a4ab952a76646b78dee653b625c8ee26c2ebd3a
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Wed Jul 12 14:00:20 2023 +0200
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Wed Jul 19 11:07:04 2023 +0200

    cool#6857 sw floattable: try harder to keep anchor text in the last follow
    
    The bugdoc has a single floating table, spanning over 6 pages. Loading
    results in a layout loop, SwFrame::GetNextFlyLeaf() never finishes as
    the last follow fly has no anchor, which should never happen.
    
    The root of the problem seems to be already on page 3. The 6 fly frames
    are meant to have 6 matching anchor frames, where the offset of these
    text frames is all 0, i.e. the anchor frame's text goes to the last
    follow, since commit 73bada774ef37efd5a4498ccc083b1358314557d (sw
    floattable, crashtesting: fix PDF export of fdo72790-1.docx, part 3,
    2023-04-26).
    
    Fix the problem by improving SwTextFrame::FormatAdjust(), so it never
    sets the offset of a follow anchor frame to non-zero when the current
    frame has a non-last split fly. All the negative fly frame heights and
    the final layout loop was a result of this.
    
    Note that there are still calls to ManipOfst() on the follow frame after
    this, but all such calls are from SwTextFrame::RemoveFootnote(), and
    that always just sets a non-zero offset + restores it, so that is not a
    problem for us.
    
    Change-Id: If62a1e2690cffed2de0be047ffb741d524532dea
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/154343
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins
    (cherry picked from commit d59704b6b8c7e5395c0606fa01f37392afc4b2cd)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/154423
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/sw/qa/core/text/data/floattable-avoid-manip-ofst.docx 
b/sw/qa/core/text/data/floattable-avoid-manip-ofst.docx
new file mode 100644
index 000000000000..b4d85b5f8ac4
Binary files /dev/null and 
b/sw/qa/core/text/data/floattable-avoid-manip-ofst.docx differ
diff --git a/sw/qa/core/text/frmform.cxx b/sw/qa/core/text/frmform.cxx
index 3c1a16a99444..d23611a7eb05 100644
--- a/sw/qa/core/text/frmform.cxx
+++ b/sw/qa/core/text/frmform.cxx
@@ -16,6 +16,7 @@
 #include <sortedobjs.hxx>
 #include <anchoredobject.hxx>
 #include <pagefrm.hxx>
+#include <txtfrm.hxx>
 
 namespace
 {
@@ -59,6 +60,25 @@ CPPUNIT_TEST_FIXTURE(Test, testFloattableNegativeVertOffset)
     // 2nd paragraph.
     CPPUNIT_ASSERT_LESS(pPara2->getFrameArea().Top(), rFlyRect.Bottom());
 }
+
+CPPUNIT_TEST_FIXTURE(Test, testFloattableAvoidManipOfst)
+{
+    // Given a document with a 6-page floating table and some anchor text:
+    createSwDoc("floattable-avoid-manip-ofst.docx");
+
+    // When laying out that document:
+    calcLayout();
+
+    // Then make sure all anchor text is on the last page:
+    SwDoc* pDoc = getSwDoc();
+    SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
+    SwPageFrame* pLastPage = pLayout->GetLastPage();
+    SwLayoutFrame* pBodyFrame = pLastPage->FindBodyCont();
+    SwTextFrame* pAnchor = pBodyFrame->GetLower()->DynCastTextFrame();
+    // If this is not 0, that means some of the anchor text is shifted to a 
previous page, while
+    // anchors of non-last split fly frames should contain no text.
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), 
pAnchor->GetOffset().get());
+}
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/frmform.cxx b/sw/source/core/text/frmform.cxx
index 55f259f0bc96..cdf51563c0ae 100644
--- a/sw/source/core/text/frmform.cxx
+++ b/sw/source/core/text/frmform.cxx
@@ -1192,6 +1192,14 @@ void SwTextFrame::FormatAdjust( SwTextFormatter &rLine,
                 RemoveFootnote(nOld, nEnd - nOld);
             }
             ChangeOffset( GetFollow(), nEnd );
+
+            if (HasNonLastSplitFlyDrawObj())
+            {
+                // Make sure content from the last floating table anchor is 
not shifted to previous
+                // anchors.
+                nEnd = TextFrameIndex(0);
+            }
+
             GetFollow()->ManipOfst( nEnd );
         }
         else

Reply via email to