sw/qa/extras/layout/data/fdo48718-1.docx |binary
 sw/qa/extras/layout/data/tdf161718.docx  |binary
 sw/qa/extras/layout/layout2.cxx          |   29 +++++++++++++
 sw/source/core/inc/tabfrm.hxx            |    2 
 sw/source/core/layout/layact.cxx         |    5 --
 sw/source/core/layout/tabfrm.cxx         |   67 ++++++++++++++++++++++++++++---
 sw/source/core/text/txtftn.cxx           |    7 +++
 7 files changed, 100 insertions(+), 10 deletions(-)

New commits:
commit 306cdedb6ba3b7e63f9d3369ae9f18814292de55
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Wed Jun 26 15:44:44 2024 +0200
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Wed Aug 7 11:08:33 2024 +0500

    tdf#156724 sw: layout: ignore footnotes when splitting float table row
    
    (regression from commit 534d3818aedfa95ad73935235462f5ec2817f5da)
    
    Change-Id: I169d88375a93c288604a89ef89f7e895830446c8
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/169570
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>

diff --git a/sw/qa/extras/layout/data/fdo48718-1.docx 
b/sw/qa/extras/layout/data/fdo48718-1.docx
new file mode 100644
index 000000000000..373aa357fd5c
Binary files /dev/null and b/sw/qa/extras/layout/data/fdo48718-1.docx differ
diff --git a/sw/qa/extras/layout/layout2.cxx b/sw/qa/extras/layout/layout2.cxx
index 7d7eb0f73f87..1cfb586d74bc 100644
--- a/sw/qa/extras/layout/layout2.cxx
+++ b/sw/qa/extras/layout/layout2.cxx
@@ -2977,6 +2977,18 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf161718)
     assertXPath(pXmlDoc, "/root/page", 1);
 }
 
+CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, TestTdf161348)
+{
+    createSwDoc("fdo48718-1.docx");
+
+    xmlDocUniquePtr pXml = parseLayoutDump();
+
+    // the floating table is on page 1
+    // apparently both parts of the split table are on this text frame
+    assertXPath(pXml, "/root/page[1]/body/txt[2]/anchored/fly", 2);
+    assertXPath(pXml, "/root/page[1]/body/txt[2]/anchored/fly/tab", 2);
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/tabfrm.cxx b/sw/source/core/layout/tabfrm.cxx
index 61f08c6bc848..98e39b254671 100644
--- a/sw/source/core/layout/tabfrm.cxx
+++ b/sw/source/core/layout/tabfrm.cxx
@@ -807,7 +807,8 @@ static bool lcl_RecalcSplitLine( SwRowFrame& rLastLine, 
SwRowFrame& rFollowLine,
         bRet = false;
 
     // apparently checking nFootnoteHeight here does *not* guarantee that it 
fits into the body
-    if (bRet && nDistanceToFootnoteBodyPrtBottom + nFollowFootnotes < 0)
+    if (bRet && rTab.IsInDocBody()
+        && nDistanceToFootnoteBodyPrtBottom + nFollowFootnotes < 0)
     {
         assert(rTab.GetUpper() != 
rTab.FindFootnoteBossFrame()->FindBodyCont());
         SAL_INFO("sw.layout", "SwTabFrame Split failed because of footnote 
growth");
commit c8ab4dc01252741a1d9055efb7bfc6caa31f78b9
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Tue Jun 25 18:47:15 2024 +0200
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Wed Aug 7 11:08:23 2024 +0500

    tdf#161718 sw: fix background flys blocking footnotes
    
    The problem is that the document has an unwanted page break on the
    paragraph with the footnote.
    
    The reason is that lcl_GetFootnoteLower() tries to evade flys, but
    doesn't take into account that background flys (Wrap Through) should be
    ignored.
    
    (somehow regression from commit c303981cfd95ce1c3881366023d5495ae2edce97)
    
    Change-Id: I02578f14644e232fac127142fe12801101f87f86
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/169530
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>

diff --git a/sw/qa/extras/layout/data/tdf161718.docx 
b/sw/qa/extras/layout/data/tdf161718.docx
new file mode 100644
index 000000000000..240192e07a71
Binary files /dev/null and b/sw/qa/extras/layout/data/tdf161718.docx differ
diff --git a/sw/qa/extras/layout/layout2.cxx b/sw/qa/extras/layout/layout2.cxx
index 2c1e197fd95e..7d7eb0f73f87 100644
--- a/sw/qa/extras/layout/layout2.cxx
+++ b/sw/qa/extras/layout/layout2.cxx
@@ -2960,6 +2960,23 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf156724)
     assertXPath(pXmlDoc, "/root/page", 2);
 }
 
+CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf161718)
+{
+    createSwDoc("tdf161718.docx");
+
+    xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+
+    // everything on one page
+    assertXPath(pXmlDoc, "/root/page/header", 1);
+    assertXPath(pXmlDoc, "/root/page/header/txt/anchored", 1);
+    assertXPath(pXmlDoc, "/root/page/footer", 1);
+    assertXPath(pXmlDoc, "/root/page/ftncont/ftn", 1);
+    assertXPath(pXmlDoc, "/root/page/ftncont/ftn/txt", 1);
+    assertXPath(pXmlDoc, "/root/page/body/txt", 27);
+    assertXPath(pXmlDoc, "/root/page/body/txt/anchored", 1);
+    assertXPath(pXmlDoc, "/root/page", 1);
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/txtftn.cxx b/sw/source/core/text/txtftn.cxx
index 035158e2bd25..cefc6239a0ba 100644
--- a/sw/source/core/text/txtftn.cxx
+++ b/sw/source/core/text/txtftn.cxx
@@ -32,6 +32,7 @@
 #include <txtftn.hxx>
 #include <flyfrm.hxx>
 #include <fmtftn.hxx>
+#include <fmtsrnd.hxx>
 #include <ftninfo.hxx>
 #include <charfmt.hxx>
 #include <rowfrm.hxx>
@@ -246,6 +247,12 @@ static SwTwips lcl_GetFootnoteLower( const SwTextFrame* 
pFrame, SwTwips nLower )
             const SwSortedObjs &rObjs = *pStartFrame->GetDrawObjs();
             for (SwAnchoredObject* pAnchoredObj : rObjs)
             {
+                if (pAnchoredObj->GetFrameFormat().GetSurround().GetSurround()
+                        == text::WrapTextMode_THROUGH)
+                {
+                    continue; // tdf#161718 no effect on text flow, skip
+                }
+
                 SwRect aRect( pAnchoredObj->GetObjRect() );
 
                 auto pFlyFrame = pAnchoredObj->DynCastFlyFrame();
commit 82cb612befff3da47772918bb1a3d188092a7165
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Wed May 15 14:43:10 2024 +0200
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Wed Aug 7 10:57:26 2024 +0500

    tdf#160897 sw: layout: fail SwTabFrame::Split on footnote overlap
    
    The bugdoc has a table in a section, and the cells contain many
    footnotes.
    
    Somehow commit c303981cfd95ce1c3881366023d5495ae2edce97 introduced some
    layout looping, and it also looks worse than in 7.5.
    
    During lcl_RecalcRow(rLastLine) it may happen that first some footnotes
    are moved off the page, then the table/section grow during text
    formatting, then the footnotes are moved back onto the page, so the
    footnote container is the same size as before, the body is the same size
    as before (because it shrinks whenever the footnote container grows),
    but the section and table don't fit into the body any more.
    
    This fixes the layout loops, and also there are no visible overlaps of
    body(table) and footnotes any more; however, the layout is obviously not
    perfect, many footnotes are on the wrong page and there are some gaps of
    empty space on some pages, but at least none of the footnotes are
    numbered "0" any more.
    
    In 7.5, there was overlap of the body and the footnotes on page 1 and 3,
    and also the irritating effect that moving the mouse over
    the bottom of page 3 would relayout the document multiple times...
    
    Some other ideas that don't work:
    
    * it doesn't help to call Shrink() on the section frame, because it has
      ToMaximize() and does not actually shrink.
    * one aspect of the loop is that the section is always size-invalidated
      even when it doesn't change its size during SwTabFormat::MakeAll()
      and the idea was to detect this (invalidation flag set on upper but
      same area as before) and reset the flag, but this prevents shrinking
      the section to fit on the page
    
    Change-Id: I6074b5c2615a0d7f613edebe92b5350efdd7fe02
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167693
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>

diff --git a/sw/source/core/layout/tabfrm.cxx b/sw/source/core/layout/tabfrm.cxx
index efcca2c6aa41..61f08c6bc848 100644
--- a/sw/source/core/layout/tabfrm.cxx
+++ b/sw/source/core/layout/tabfrm.cxx
@@ -760,6 +760,9 @@ static bool lcl_RecalcSplitLine( SwRowFrame& rLastLine, 
SwRowFrame& rFollowLine,
     // #i26945# - include check, if objects fit
     const SwTwips nDistanceToUpperPrtBottom =
         aRectFnSet.BottomDist(rTab.getFrameArea(), 
aRectFnSet.GetPrtBottom(*rTab.GetUpper()));
+    // also check the footnote boss - it *may* be smaller than the upper now!
+    const SwTwips nDistanceToFootnoteBodyPrtBottom =
+        aRectFnSet.BottomDist(rTab.getFrameArea(), 
aRectFnSet.GetPrtBottom(*rTab.FindFootnoteBossFrame()->FindBodyCont()));
     // tdf#125685 ignore footnotes that are anchored in follow-table of this
     // table - if split is successful they move to the next page/column anyway
     assert(rTab.GetFollow() == rFollowLine.GetUpper());
@@ -803,6 +806,14 @@ static bool lcl_RecalcSplitLine( SwRowFrame& rLastLine, 
SwRowFrame& rFollowLine,
     if (nDistanceToUpperPrtBottom + nFollowFootnotes < 0 || 
!rTab.DoesObjsFit())
         bRet = false;
 
+    // apparently checking nFootnoteHeight here does *not* guarantee that it 
fits into the body
+    if (bRet && nDistanceToFootnoteBodyPrtBottom + nFollowFootnotes < 0)
+    {
+        assert(rTab.GetUpper() != 
rTab.FindFootnoteBossFrame()->FindBodyCont());
+        SAL_INFO("sw.layout", "SwTabFrame Split failed because of footnote 
growth");
+        bRet = false; // tdf#160897
+    }
+
     // 2. Check if each cell in the last line has at least one content frame.
 
     // Note: a FollowFlowRow may contains empty cells!
commit f83390ba4e0ae20d8256ddbe0e995c4fcd37aafa
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Wed Aug 23 15:50:59 2023 +0200
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Wed Aug 7 09:18:04 2024 +0500

    tdf#156724 sw: layout: fix tables not splitting due to footnotes differently
    
    Revert commit 610c6f02b11b4b4c555a78b0feb2a1eb35159e39 and
    and 61a78a523a6131ff98b5d846368e5626fe58d99c instead do the
    opposite: never calc content frames in FormatLayout().
    
    There were a few cases where documents looked worse with the fix, such
    as the somewhat pathological tdf120139-1.odt and tdf124474-1.odt, but
    typically these went from a bad layout to a worse layout, e.g.
    --convert-to pdf tdf120139-1.odt went from 11 minutes to 33 minutes
    (dbgutil) with twice as many more half-empty pages.
    
    Worse is that the previous fix appears to prevent tdf#128437 from
    working.
    
    It should also be less risky to never calc content frames in
    FormatLayout(), because with IsPaintLocked() check that used to be done
    led to doing it only for pages which were visible when loading the
    document, so any regressions with this new approach would appear on few
    pages at the start of the document, instead of many pages at the end.
    
    Note that without the previous commit, this would cause
    * CppunitTest_sw_core_layout CPPUNIT_TEST_NAME="testTablePrintAreaLeft"
      to fail
    * tdf#137523 SwLayoutWriter3 testTdf137523 to fail,
      *only* on the last text frame
    
    This also appears to fix tdf#125749.
    
    Change-Id: I3d72f8e9d2b89aa3738e554308fd9dce12e92238
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/155988
    Tested-by: Michael Stahl <michael.st...@allotropia.de>
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>

diff --git a/sw/source/core/inc/tabfrm.hxx b/sw/source/core/inc/tabfrm.hxx
index 6360405e4407..9b7baf171dfc 100644
--- a/sw/source/core/inc/tabfrm.hxx
+++ b/sw/source/core/inc/tabfrm.hxx
@@ -106,7 +106,7 @@ class SAL_DLLPUBLIC_RTTI SwTabFrame final: public 
SwLayoutFrame, public SwFlowFr
      * created and constructed and inserted directly after this.
      * Join() gets the Follow's content and destroys it.
      */
-    bool Split( const SwTwips nCutPos, bool bTryToSplit, bool bTableRowKeep );
+    bool Split(const SwTwips nCutPos, bool bTryToSplit, bool bTableRowKeep, 
bool & rIsFootnoteGrowth);
     void Join();
 
     void UpdateAttr_(
diff --git a/sw/source/core/layout/layact.cxx b/sw/source/core/layout/layact.cxx
index 6c85d2d223d5..5afa15fd0772 100644
--- a/sw/source/core/layout/layact.cxx
+++ b/sw/source/core/layout/layact.cxx
@@ -1423,10 +1423,7 @@ bool SwLayAction::FormatLayout( OutputDevice 
*pRenderContext, SwLayoutFrame *pLa
                 PopFormatLayout();
             }
         }
-        else if (!pLay->IsColBodyFrame())
-        {   // tdf#156724 unconditionally for frames in tables, so their 
footnotes exist before trying to split
-            pLow->OptCalc();
-        }
+        // else: don't calc content frames any more
 
         if ( IsAgain() )
             return false;
diff --git a/sw/source/core/layout/tabfrm.cxx b/sw/source/core/layout/tabfrm.cxx
index 2c6e7edc979a..efcca2c6aa41 100644
--- a/sw/source/core/layout/tabfrm.cxx
+++ b/sw/source/core/layout/tabfrm.cxx
@@ -646,7 +646,8 @@ inline void TableSplitRecalcLock( SwFlowFrame *pTab ) { 
pTab->LockJoin(); }
 inline void TableSplitRecalcUnlock( SwFlowFrame *pTab ) { pTab->UnlockJoin(); }
 
 static bool lcl_RecalcSplitLine( SwRowFrame& rLastLine, SwRowFrame& 
rFollowLine,
-                          SwTwips nRemainingSpaceForLastRow, SwTwips 
nAlreadyFree )
+                          SwTwips nRemainingSpaceForLastRow, SwTwips 
nAlreadyFree,
+                          bool & rIsFootnoteGrowth)
 {
     bool bRet = true;
 
@@ -655,6 +656,34 @@ static bool lcl_RecalcSplitLine( SwRowFrame& rLastLine, 
SwRowFrame& rFollowLine,
     SwRectFnSet aRectFnSet(rTab.GetUpper());
     SwTwips nCurLastLineHeight = 
aRectFnSet.GetHeight(rLastLine.getFrameArea());
 
+    SwTwips nFootnoteHeight(0);
+    if (SwFootnoteBossFrame const*const pBoss = rTab.FindFootnoteBossFrame())
+    {
+        if (SwFootnoteContFrame const*const pCont = pBoss->FindFootnoteCont())
+        {
+            for (SwFootnoteFrame const* pFootnote = 
static_cast<SwFootnoteFrame const*>(pCont->Lower());
+                 pFootnote != nullptr;
+                 pFootnote = static_cast<SwFootnoteFrame 
const*>(pFootnote->GetNext()))
+            {
+                SwContentFrame const*const pAnchor = pFootnote->GetRef();
+                SwTabFrame const* pTab = pAnchor->FindTabFrame();
+                if (pTab == &rTab)
+                {
+                    while (pTab->GetUpper()->IsInTab())
+                    {
+                        pTab = pTab->GetUpper()->FindTabFrame();
+                    }
+                    // TODO currently do this only for top-level tables?
+                    // otherwise would need to check rTab's follow and any 
upper table's follow?
+                    if (pTab == &rTab)
+                    {
+                        nFootnoteHeight += 
aRectFnSet.GetHeight(pFootnote->getFrameArea());
+                    }
+                }
+            }
+        }
+    }
+
     // If there are nested cells in rLastLine, the recalculation of the last
     // line needs some preprocessing.
     lcl_PreprocessRowsInCells( rTab, rLastLine, rFollowLine, 
nRemainingSpaceForLastRow );
@@ -759,8 +788,16 @@ static bool lcl_RecalcSplitLine( SwRowFrame& rLastLine, 
SwRowFrame& rFollowLine,
                     {
                         nFollowFootnotes += 
aRectFnSet.GetHeight(pFootnote->getFrameArea());
                     }
+                    if (pTab == &rTab)
+                    {
+                        nFootnoteHeight -= 
aRectFnSet.GetHeight(pFootnote->getFrameArea());
+                    }
                 }
             }
+            if (nFootnoteHeight < 0)
+            {   // tdf#156724 footnotes have grown, try to split again
+                rIsFootnoteGrowth = true;
+            }
         }
     }
     if (nDistanceToUpperPrtBottom + nFollowFootnotes < 0 || 
!rTab.DoesObjsFit())
@@ -1020,7 +1057,8 @@ static bool lcl_FindSectionsInRow( const SwRowFrame& rRow 
)
     return bRet;
 }
 
-bool SwTabFrame::Split( const SwTwips nCutPos, bool bTryToSplit, bool 
bTableRowKeep )
+bool SwTabFrame::Split(const SwTwips nCutPos, bool bTryToSplit,
+        bool bTableRowKeep, bool & rIsFootnoteGrowth)
 {
     bool bRet = true;
 
@@ -1358,7 +1396,7 @@ bool SwTabFrame::Split( const SwTwips nCutPos, bool 
bTryToSplit, bool bTableRowK
         // we also don't shrink here, because we will be doing that in 
lcl_RecalcSplitLine
 
         // recalculate the split line
-        bRet = lcl_RecalcSplitLine( *pLastRow, *pFollowRow, 
nRemainingSpaceForLastRow, nShrink );
+        bRet = lcl_RecalcSplitLine(*pLastRow, *pFollowRow, 
nRemainingSpaceForLastRow, nShrink, rIsFootnoteGrowth);
 
         // RecalcSplitLine did not work. In this case we conceal the split 
error:
         if (!bRet && !bSplitRowAllowed)
@@ -2590,7 +2628,10 @@ void SwTabFrame::MakeAll(vcl::RenderContext* 
pRenderContext)
                     }
 
                     oAccess.reset();
-                    const bool bSplitError = !Split( nDeadLine, bTryToSplit, ( 
bTableRowKeep && !(bAllowSplitOfRow || bEmulateTableKeepSplitAllowed) ) );
+                    bool isFootnoteGrowth(false);
+                    const bool bSplitError = !Split(nDeadLine, bTryToSplit,
+                        (bTableRowKeep && !(bAllowSplitOfRow || 
bEmulateTableKeepSplitAllowed)),
+                        isFootnoteGrowth);
 
                     // tdf#130639 don't start table on a new page after the 
fallback "switch off repeating header"
                     if (bSplitError && nRepeat > GetTable()->GetRowsToRepeat())
@@ -2625,7 +2666,11 @@ void SwTabFrame::MakeAll(vcl::RenderContext* 
pRenderContext)
                     {
                         lcl_RecalcRow(*static_cast<SwRowFrame*>(Lower()), 
LONG_MAX);
                         setFrameAreaPositionValid(false);
-                        bTryToSplit = false;
+                        // tdf#156724 if the table added footnotes, try to 
split *again*
+                        if (!isFootnoteGrowth)
+                        {
+                            bTryToSplit = false;
+                        }
                         continue;
                     }
 
commit b6c5f64252b00d4f050cbf1d041a672621d784a5
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Mon Aug 14 17:27:52 2023 +0200
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Wed Aug 7 09:18:04 2024 +0500

    tdf#156724 tdf#156722 sw: layout: remove IsPaintLocked() check
    
    Get rid of the problematic IsPaintLocked() and only check for a column
    parent; effectively this prevents formatting frames in columns even when
    loaded from the UI, so the layout will hopefully be the same regardless
    of how it is invoked.
    
    Change-Id: Ib4cc2efdb68ef4db73dcad01c7e1bd4be35de071
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/155673
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>

diff --git a/sw/source/core/layout/layact.cxx b/sw/source/core/layout/layact.cxx
index b044bbe358af..6c85d2d223d5 100644
--- a/sw/source/core/layout/layact.cxx
+++ b/sw/source/core/layout/layact.cxx
@@ -1423,7 +1423,7 @@ bool SwLayAction::FormatLayout( OutputDevice 
*pRenderContext, SwLayoutFrame *pLa
                 PopFormatLayout();
             }
         }
-        else if (m_pImp->GetShell()->IsPaintLocked() || 
!pLay->IsColBodyFrame())
+        else if (!pLay->IsColBodyFrame())
         {   // tdf#156724 unconditionally for frames in tables, so their 
footnotes exist before trying to split
             pLow->OptCalc();
         }

Reply via email to