sw/CppunitTest_sw_core_objectpositioning.mk                           |    4 
 sw/qa/core/objectpositioning/data/floattable-follow-on-wrong-page.odt |binary
 sw/qa/core/objectpositioning/objectpositioning.cxx                    |   56 
++++++++--
 sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx    |    7 +
 4 files changed, 56 insertions(+), 11 deletions(-)

New commits:
commit 51a16c241ed31de4012ed4d3d8569ed8eb64adfb
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Mon Sep 4 08:31:18 2023 +0200
Commit:     Xisco Fauli <xiscofa...@libreoffice.org>
CommitDate: Tue Sep 5 09:59:15 2023 +0200

    tdf#156318 sw floattable: fix follow text flow handling on interactive edit
    
    Once the bugdoc has 1 col for pages, setting the top and bottom margins
    to 2.5cm created a split fly, but the follow fly was on page 3, not on
    page 2.
    
    What happened is that the layout was already wrong before calling into
    SwFrame::GetNextFlyLeaf() (that does the split), the "follow text flow"
    feature shifted the fly down (top was originally 1341, then the
    increased margin means 2475, but an additional 4329 was set), and then
    the fly was created on the wrong page.
    
    Fix the problem by not calling GetAnchoredObj().SetObjTop() in
    SwToContentAnchoredObjectPosition::CalcPosition() when the fly doesn't
    fit anymore, this way the fly can shrink, a follow can be created and
    some of the content will be moved to the follow fly, leading to a
    correct split fly on pages 1 & 2.
    
    This also fixes the previously appearing "fly frame has negative height
    now" warnings on setting the page margin.
    
    Change-Id: I75bf9cfa19dc5c7ce9607417d6a4121b8e85ac47
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/156506
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins
    (cherry picked from commit 401c175d1bbe3c64e5dd96e3b23779999271cfb1)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/156531
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>

diff --git a/sw/CppunitTest_sw_core_objectpositioning.mk 
b/sw/CppunitTest_sw_core_objectpositioning.mk
index 0f1a9dcff0be..8edae42595c8 100644
--- a/sw/CppunitTest_sw_core_objectpositioning.mk
+++ b/sw/CppunitTest_sw_core_objectpositioning.mk
@@ -21,6 +21,7 @@ $(eval $(call 
gb_CppunitTest_use_libraries,sw_core_objectpositioning, \
     comphelper \
     cppu \
     cppuhelper \
+    editeng \
     sal \
     sfx \
     subsequenttest \
@@ -70,6 +71,9 @@ $(eval $(call 
gb_CppunitTest_use_uiconfigs,sw_core_objectpositioning, \
     modules/swriter \
 ))
 
+# assert if font/glyph fallback occurs
+$(eval $(call 
gb_CppunitTest_set_non_application_font_use,sw_core_objectpositioning,abort))
+
 $(eval $(call gb_CppunitTest_use_more_fonts,sw_core_objectpositioning))
 
 # vim: set noet sw=4 ts=4:
diff --git 
a/sw/qa/core/objectpositioning/data/floattable-follow-on-wrong-page.odt 
b/sw/qa/core/objectpositioning/data/floattable-follow-on-wrong-page.odt
new file mode 100644
index 000000000000..6401747fd9d3
Binary files /dev/null and 
b/sw/qa/core/objectpositioning/data/floattable-follow-on-wrong-page.odt differ
diff --git a/sw/qa/core/objectpositioning/objectpositioning.cxx 
b/sw/qa/core/objectpositioning/objectpositioning.cxx
index 611ce1294c22..4e0db43c475f 100644
--- a/sw/qa/core/objectpositioning/objectpositioning.cxx
+++ b/sw/qa/core/objectpositioning/objectpositioning.cxx
@@ -12,6 +12,8 @@
 #include <com/sun/star/text/VertOrientation.hpp>
 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
 
+#include <editeng/ulspitem.hxx>
+
 #include <wrtsh.hxx>
 #include <unotxdoc.hxx>
 #include <docsh.hxx>
@@ -21,18 +23,21 @@
 #include <sortedobjs.hxx>
 #include <anchoredobject.hxx>
 #include <flyfrm.hxx>
+#include <frmatr.hxx>
 
+namespace
+{
 /// Covers sw/source/core/objectpositioning/ fixes.
-class SwCoreObjectpositioningTest : public SwModelTestBase
+class Test : public SwModelTestBase
 {
 public:
-    SwCoreObjectpositioningTest()
+    Test()
         : SwModelTestBase("/sw/qa/core/objectpositioning/data/")
     {
     }
 };
 
-CPPUNIT_TEST_FIXTURE(SwCoreObjectpositioningTest, testOverlapCrash)
+CPPUNIT_TEST_FIXTURE(Test, testOverlapCrash)
 {
     // Load a document with 2 images.
     createSwDoc("overlap-crash.odt");
@@ -51,7 +56,7 @@ CPPUNIT_TEST_FIXTURE(SwCoreObjectpositioningTest, 
testOverlapCrash)
     pWrtShell->SplitNode();
 }
 
-CPPUNIT_TEST_FIXTURE(SwCoreObjectpositioningTest, testVertPosFromBottom)
+CPPUNIT_TEST_FIXTURE(Test, testVertPosFromBottom)
 {
     // Create a document, insert a shape and position it 1cm above the bottom 
of the body area.
     createSwDoc();
@@ -80,7 +85,7 @@ CPPUNIT_TEST_FIXTURE(SwCoreObjectpositioningTest, 
testVertPosFromBottom)
     CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(565), nBodyBottom - 
nAnchoredBottom);
 }
 
-CPPUNIT_TEST_FIXTURE(SwCoreObjectpositioningTest, testVertAlignBottomMargin)
+CPPUNIT_TEST_FIXTURE(Test, testVertAlignBottomMargin)
 {
     // Create a document, insert three shapes and align it the 
bottom,center,top of page print area bottom.
     // The size of shapes are 284 ~ 0.5cm
@@ -151,7 +156,7 @@ CPPUNIT_TEST_FIXTURE(SwCoreObjectpositioningTest, 
testVertAlignBottomMargin)
     CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), nThirdShapeTop - 
nBodyBottom);
 }
 
-CPPUNIT_TEST_FIXTURE(SwCoreObjectpositioningTest, 
testVertAlignBottomMarginWithFooter)
+CPPUNIT_TEST_FIXTURE(Test, testVertAlignBottomMarginWithFooter)
 {
     // Load an empty document with footer.
     createSwDoc("bottom-margin-with-footer.docx");
@@ -223,7 +228,7 @@ CPPUNIT_TEST_FIXTURE(SwCoreObjectpositioningTest, 
testVertAlignBottomMarginWithF
     CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), nThirdShapeTop - 
nBodyBottom);
 }
 
-CPPUNIT_TEST_FIXTURE(SwCoreObjectpositioningTest, 
testInsideOutsideVertAlignBottomMargin)
+CPPUNIT_TEST_FIXTURE(Test, testInsideOutsideVertAlignBottomMargin)
 {
     // Load a document, with two shapes.
     // The shapes align the outside and inside of page print area bottom.
@@ -244,7 +249,7 @@ CPPUNIT_TEST_FIXTURE(SwCoreObjectpositioningTest, 
testInsideOutsideVertAlignBott
     CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), nBodyBottom - 
nSecondShapeInside);
 }
 
-CPPUNIT_TEST_FIXTURE(SwCoreObjectpositioningTest, testVMLVertAlignBottomMargin)
+CPPUNIT_TEST_FIXTURE(Test, testVMLVertAlignBottomMargin)
 {
     // Load a document, with five shapes.
     // The shapes align the top,center,bottom,outside and inside of page print 
area bottom.
@@ -286,7 +291,7 @@ CPPUNIT_TEST_FIXTURE(SwCoreObjectpositioningTest, 
testVMLVertAlignBottomMargin)
     CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), nFifthVMLShapeOutside - 
nPageBottom);
 }
 
-CPPUNIT_TEST_FIXTURE(SwCoreObjectpositioningTest, 
testFloatingTableOverlapNever)
+CPPUNIT_TEST_FIXTURE(Test, testFloatingTableOverlapNever)
 {
     // Given a document with two floating tables, positioned in a way that 
normally these would
     // overlap, but SwFormatWrapInfluenceOnObjPos::mbAllowOverlap == false 
explicitly asks to avoid
@@ -313,7 +318,7 @@ CPPUNIT_TEST_FIXTURE(SwCoreObjectpositioningTest, 
testFloatingTableOverlapNever)
     CPPUNIT_ASSERT_GREATER(pFlyFrame1->getFrameArea().Bottom(), 
pFlyFrame2->getFrameArea().Top());
 }
 
-CPPUNIT_TEST_FIXTURE(SwCoreObjectpositioningTest, 
testFloatingTableVertOrientTop)
+CPPUNIT_TEST_FIXTURE(Test, testFloatingTableVertOrientTop)
 {
     // Given a document with a vert-orient=from-top anchored floating table:
     createSwDoc("floattable-vert-orient-top.odt");
@@ -337,6 +342,37 @@ CPPUNIT_TEST_FIXTURE(SwCoreObjectpositioningTest, 
testFloatingTableVertOrientTop
     CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPage2Objs.size());
 }
 
+CPPUNIT_TEST_FIXTURE(Test, testFloatingTableFollowWrongPage)
+{
+    // Given a document with text on 2 pages, the first page has a fly frame 
that can split:
+    createSwDoc("floattable-follow-on-wrong-page.odt");
+
+    // When increasing the top and bottom margins from 0.5cm to 2.5cm:
+    SwDoc* pDoc = getSwDoc();
+    SwPageDesc aStandard(pDoc->GetPageDesc(0));
+    SvxULSpaceItem aPageMargin(aStandard.GetMaster().GetULSpace());
+    aPageMargin.SetUpper(1417);
+    aPageMargin.SetLower(1417);
+    aStandard.GetMaster().SetFormatAttr(aPageMargin);
+    pDoc->ChgPageDesc(0, aStandard);
+
+    // Then make sure the first and second page has fly frames:
+    SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
+    auto pPage1 = pLayout->Lower()->DynCastPageFrame();
+    CPPUNIT_ASSERT(pPage1);
+    CPPUNIT_ASSERT(pPage1->GetSortedObjs());
+    const SwSortedObjs& rPage1Objs = *pPage1->GetSortedObjs();
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPage1Objs.size());
+    auto pPage2 = pPage1->GetNext()->DynCastPageFrame();
+    CPPUNIT_ASSERT(pPage2);
+    // Without the accompanying fix in place, this test would have failed, 
page 2 had no fly frame
+    // (page 3 had one).
+    CPPUNIT_ASSERT(pPage2->GetSortedObjs());
+    const SwSortedObjs& rPage2Objs = *pPage2->GetSortedObjs();
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPage2Objs.size());
+}
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx 
b/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx
index 561c16fd8115..73b8b088d1f7 100644
--- a/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx
+++ b/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx
@@ -193,6 +193,8 @@ void SwToContentAnchoredObjectPosition::CalcPosition()
     // If true, this means that the anchored object is a split fly frame and 
it's not a master but
     // one of the follows.
     bool bFollowSplitFly = false;
+    // The anchored object is a fly that is allowed to split.
+    bool bSplitFly = false;
     {
         // if object is at-character anchored, determine character-rectangle
         // and frame, position has to be oriented at.
@@ -257,6 +259,7 @@ void SwToContentAnchoredObjectPosition::CalcPosition()
                     // Anchored object has a precede, so it's a follow.
                     bFollowSplitFly = true;
                 }
+                bSplitFly = true;
             }
         }
     }
@@ -952,7 +955,9 @@ void SwToContentAnchoredObjectPosition::CalcPosition()
                     }
                 }
             }
-            else
+            // Don't move split flys around for follow text flow purposes; if 
they don't fit their
+            // parent anymore, they will shrink and part of the content will 
move to the follow fly.
+            else if (!bSplitFly)
             {
                 // follow text flow
                 const bool bInFootnote = rAnchorTextFrame.IsInFootnote();

Reply via email to