tdf#157571 sw floattable: fix incorrect blank space after table-in-shape

Regression from a4af5432753408c4eea8a8d56c2f48202160c5fe (tdf#120262 sw
floattable, legacy: fix text wrap around fly when no content fits,
2023-07-17), the bugdoc has a shape which contains a table, and lots of
empty paragraphs next to it wrap around the shape. Writer didn't wrap
these empty paragraphs, so some of the page 1 content was shifted to
page 2.

What happened here is that in case there is a really small space for the
wrapping text around a floating object, then Word has some minimal
limit. If the available horizontal space is smaller than the limit, we
don't even try to wrap, even if the content (an empty paragraph) would
fit. It was assumed that this limit is the shape for normal anchored
objects and floating tables, but the two bugdocs show that there are two
different limits here.

Fix the problem by going back to MINLAY as the default limit where we
start wrapping, and only increase that to TEXT_MIN_SMALL when wrapping
around floating tables. That fixes the bugdoc and keeps the older
floating table use-case working as well.

This also allows reverting changes to testParaUpperMarginFlyIntersect,
to assert the non-floating-table case again.

Change-Id: I8f8a776c6ad5bdfa0ee4f197b600463fef6431f0
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/157743
Reviewed-by: Miklos Vajna <[email protected]>
Tested-by: Jenkins
diff --git a/sw/qa/core/text/data/fly-minimal-wrap.docx b/sw/qa/core/text/data/fly-minimal-wrap.docx
new file mode 100644
index 0000000..f5955d2
--- /dev/null
+++ b/sw/qa/core/text/data/fly-minimal-wrap.docx
Binary files differ
diff --git a/sw/qa/core/text/itrform2.cxx b/sw/qa/core/text/itrform2.cxx
index e190bed..637396a 100644
--- a/sw/qa/core/text/itrform2.cxx
+++ b/sw/qa/core/text/itrform2.cxx
@@ -82,6 +82,36 @@ CPPUNIT_TEST_FIXTURE(Test, testFloattableLegacyWrapEmptyParagraph)
    const SwSortedObjs& rPageObjs2 = *pPage2->GetSortedObjs();
    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPageObjs2.size());
}

CPPUNIT_TEST_FIXTURE(Test, testFlyMinimalWrap)
{
    // Given a document with a first page that has a shape and a table in it (not floating table),
    // some empty paragraphs wrapping around the shape:
    createSwDoc("fly-minimal-wrap.docx");

    // When calculating the layout:
    calcLayout();

    // Then make sure the wrap happens, so the 2nd page only has 2 paragraphs:
    SwDoc* pDoc = getSwDoc();
    SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
    auto pPage = dynamic_cast<SwPageFrame*>(pLayout->Lower());
    CPPUNIT_ASSERT(pPage);
    CPPUNIT_ASSERT(pPage->GetSortedObjs());
    const SwSortedObjs& rPageObjs = *pPage->GetSortedObjs();
    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), rPageObjs.size());
    auto pPage2 = dynamic_cast<SwPageFrame*>(pPage->GetNext());
    CPPUNIT_ASSERT(pPage2);
    CPPUNIT_ASSERT(!pPage2->GetSortedObjs());
    SwLayoutFrame* pBody2 = pPage2->FindBodyCont();
    SwFrame* pPage2Para1 = pBody2->GetLower();
    CPPUNIT_ASSERT(pPage2Para1);
    SwFrame* pPage2Para2 = pPage2Para1->GetNext();
    CPPUNIT_ASSERT(pPage2Para2);
    // Without the accompanying fix in place, this test would have failed, the second page had 19
    // text frames in the body frame, not 2.
    CPPUNIT_ASSERT(!pPage2Para2->GetNext());
}
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/qa/core/text/text.cxx b/sw/qa/core/text/text.cxx
index 16aa73c..8a48b75 100644
--- a/sw/qa/core/text/text.cxx
+++ b/sw/qa/core/text/text.cxx
@@ -1419,10 +1419,10 @@ CPPUNIT_TEST_FIXTURE(SwCoreTextTest, testParaUpperMarginFlyIntersect)
        nHeight += getXPath(pXmlDoc, xPath, "height").toInt32();
    }
    // Without the accompanying fix in place, this test would have failed with:
    // - Expected: 542 (~500)
    // - Expected: 521 (~500)
    // - Actual  : 857 (~1000)
    // I.e. both upper and lower margin was taken into account.
    CPPUNIT_ASSERT_EQUAL(542, nHeight);
    CPPUNIT_ASSERT_EQUAL(521, nHeight);
}

CPPUNIT_TEST_FIXTURE(SwCoreTextTest, testTdf129810)
diff --git a/sw/source/core/text/itrform2.cxx b/sw/source/core/text/itrform2.cxx
index f8b2c3a4..36a8650 100644
--- a/sw/source/core/text/itrform2.cxx
+++ b/sw/source/core/text/itrform2.cxx
@@ -2806,8 +2806,27 @@ void SwTextFormatter::CalcFlyWidth( SwTextFormatInfo &rInf )
    {
        // Word style: if there is minimal space remaining, then handle that similar to a full line
        // and put the actual empty paragraph below the fly.
        bFullLine = std::abs(aLine.Left() - aInter.Left()) < TEXT_MIN_SMALL
                    && std::abs(aLine.Right() - aInter.Right()) < TEXT_MIN_SMALL;
        SwTwips nLimit = MINLAY;
        for (const auto& pObj : *rTextFly.GetAnchoredObjList())
        {
            auto pFlyFrame = pObj->DynCastFlyFrame();
            if (!pFlyFrame)
            {
                continue;
            }

            if (!pFlyFrame->IsFlySplitAllowed())
            {
                continue;
            }

            // We wrap around a floating table, that has a larger minimal wrap distance.
            nLimit = TEXT_MIN_SMALL;
            break;
        }

        bFullLine = std::abs(aLine.Left() - aInter.Left()) < nLimit
                    && std::abs(aLine.Right() - aInter.Right()) < nLimit;
    }

    // Although no text is left, we need to format another line,