sw/qa/core/layout/data/floattable-wrapped-by-table.docx |binary
 sw/qa/core/layout/tabfrm.cxx                            |   30 ++++++++++++++++
 sw/source/core/layout/tabfrm.cxx                        |   22 +++++++++++
 3 files changed, 51 insertions(+), 1 deletion(-)

New commits:
commit 2c181a09bc76cf57aedce42c182b568d2087c3c8
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Tue Dec 5 08:39:10 2023 +0100
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Mon Dec 11 15:58:35 2023 +0100

    tdf#60558 sw floattable: allow wrap of table on the right of a floattable
    
    The bugdoc shows that Word wraps inline tables around floating tables if
    they have enough space, but Writer didn't do this.
    
    Table frames may wrap fly frames by adding some top, left or right
    margin to the table at a layout level, this is calculated in
    SwTabFrame::CalcFlyOffsets(). There we currently decide the give a top
    margin to such tables, which fixes the overlap problem, but the bugdoc
    is now of 2 pages instead of 1 page, since we don't wrap.
    
    Fix the problem by improving the "shift down" case by checking if
    shifting to the right would also work (has enough space). If so, do that
    in case the fly frame is a split fly.
    
    Note that this could be done for all flys as well, but that would have
    to be conditional on some Word compat flag and that's not needed to fix
    the bugdoc, so leave that for later.
    
    (cherry picked from commit 868140fcc1311259b9d5f666637b33d226511a53)
    
    Conflicts:
            sw/source/core/layout/tabfrm.cxx
    
    Change-Id: Idb45413257758fd0334b17ef348ba28010a52316
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/160380
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

diff --git a/sw/qa/core/layout/data/floattable-wrapped-by-table.docx 
b/sw/qa/core/layout/data/floattable-wrapped-by-table.docx
new file mode 100644
index 000000000000..a53f652183ea
Binary files /dev/null and 
b/sw/qa/core/layout/data/floattable-wrapped-by-table.docx differ
diff --git a/sw/qa/core/layout/tabfrm.cxx b/sw/qa/core/layout/tabfrm.cxx
index 84f7ba48c572..68c0821d46df 100644
--- a/sw/qa/core/layout/tabfrm.cxx
+++ b/sw/qa/core/layout/tabfrm.cxx
@@ -169,6 +169,36 @@ CPPUNIT_TEST_FIXTURE(Test, testSplitFlyTableJoin)
     CPPUNIT_ASSERT(pFly->GetPrecede());
     CPPUNIT_ASSERT(!pFly->HasFollow());
 }
+
+CPPUNIT_TEST_FIXTURE(Test, testSplitFlyWrappedByTable)
+{
+    // Given a document with a floating table, wrapped by an inline table:
+    // When laying out the document:
+    createSwDoc("floattable-wrapped-by-table.docx");
+
+    // Then make sure the inline table wraps around the floating table:
+    SwDoc* pDoc = getSwDoc();
+    SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
+    auto pPage = pLayout->Lower()->DynCastPageFrame();
+    CPPUNIT_ASSERT(pPage);
+    // Get the top of the inline table, ignoring margins:
+    CPPUNIT_ASSERT(pPage->GetSortedObjs());
+    SwSortedObjs& rPageObjs = *pPage->GetSortedObjs();
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPageObjs.size());
+    auto pFly = rPageObjs[0]->DynCastFlyFrame()->DynCastFlyAtContentFrame();
+    CPPUNIT_ASSERT(pFly);
+    // Get the bottom of of the floating table, ignoring margins:
+    SwTwips nFloatingBottom = pFly->getFrameArea().Top() + 
pFly->getFramePrintArea().Height();
+    SwFrame* pBody = pPage->FindBodyCont();
+    auto pTab = pBody->GetLower()->GetNext()->DynCastTabFrame();
+    SwTwips nInlineTop = pTab->getFrameArea().Top() + 
pTab->getFramePrintArea().Top();
+    // Make sure the inline table is on the right of the floating one, not 
below it:
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected less than: 7287
+    // - Actual  : 7287
+    // i.e. the inline table was under the floating one, not on the right of 
it.
+    CPPUNIT_ASSERT_LESS(nFloatingBottom, nInlineTop);
+}
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/tabfrm.cxx b/sw/source/core/layout/tabfrm.cxx
index 23d53350fc55..fb0ebaa13425 100644
--- a/sw/source/core/layout/tabfrm.cxx
+++ b/sw/source/core/layout/tabfrm.cxx
@@ -3135,6 +3135,7 @@ bool SwTabFrame::CalcFlyOffsets( SwTwips& rUpper,
                         nSurround = text::WrapTextMode_PARALLEL;
 
                     bool bShiftDown = css::text::WrapTextMode_NONE == 
nSurround;
+                    bool bSplitFly = pFly->IsFlySplitAllowed();
                     if (!bShiftDown && bAddVerticalFlyOffsets)
                     {
                         if (nSurround == text::WrapTextMode_PARALLEL && 
isHoriOrientShiftDown)
@@ -3157,6 +3158,18 @@ bool SwTabFrame::CalcFlyOffsets( SwTwips& rUpper,
                             // normally an SwFlyPortion is created instead 
that increases the height
                             // of the first table row.
                             bShiftDown = aTabRange.overlaps(aFlyRange);
+
+                            if (bSplitFly && 
pFly->GetAnchorFrame()->GetUpper() == GetUpper())
+                            {
+                                // Split fly followed by an inline table. 
Check if we have enough space to shift
+                                // to the right instead.
+                                SwTwips nShiftedTabRight = 
aFlyRectWithoutSpaces.Right() + getFramePrintArea().Width();
+                                SwTwips nRightShiftDeadline = 
pFly->GetAnchorFrame()->GetUpper()->getFrameArea().Right();
+                                if (aRectFnSet.XDiff(nRightShiftDeadline, 
nShiftedTabRight) >= 0)
+                                {
+                                    bShiftDown = false;
+                                }
+                            }
                         }
                     }
 
@@ -3196,9 +3209,16 @@ bool SwTabFrame::CalcFlyOffsets( SwTwips& rUpper,
                             bInvalidatePrtArea = true;
                         }
                     }
+                    bool bFlyHoriOrientLeft = text::HoriOrientation::LEFT == 
rHori.GetHoriOrient();
+                    if (bSplitFly && !bFlyHoriOrientLeft)
+                    {
+                        // If a split fly is oriented "from left", we already 
checked if it has enough space on
+                        // the right, so from-left and left means the same 
here.
+                        bFlyHoriOrientLeft = rHori.GetHoriOrient() == 
text::HoriOrientation::NONE;
+                    }
                     if ((css::text::WrapTextMode_RIGHT == nSurround
                          || css::text::WrapTextMode_PARALLEL == nSurround) &&
-                         text::HoriOrientation::LEFT == rHori.GetHoriOrient() 
&&
+                         bFlyHoriOrientLeft &&
                          !bShiftDown )
                     {
                         const tools::Long nWidth = aRectFnSet.XDiff(

Reply via email to