summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2023-09-04 08:31:18 +0200
committerMiklos Vajna <vmiklos@collabora.com>2023-09-04 11:51:53 +0200
commit401c175d1bbe3c64e5dd96e3b23779999271cfb1 (patch)
treebd12121c7c66df43418628a98b1616d523621829
parent1761680a8f8f4a4dfa50e5be4c9a94ffa2aa46b2 (diff)
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 <vmiklos@collabora.com> Tested-by: Jenkins
-rw-r--r--sw/CppunitTest_sw_core_objectpositioning.mk4
-rw-r--r--sw/qa/core/objectpositioning/data/floattable-follow-on-wrong-page.odtbin0 -> 38658 bytes
-rw-r--r--sw/qa/core/objectpositioning/objectpositioning.cxx56
-rw-r--r--sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx7
4 files changed, 56 insertions, 11 deletions
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
--- /dev/null
+++ b/sw/qa/core/objectpositioning/data/floattable-follow-on-wrong-page.odt
Binary files 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();