sw/source/core/inc/tabfrm.hxx    |    2 -
 sw/source/core/layout/layact.cxx |    5 ---
 sw/source/core/layout/tabfrm.cxx |   55 +++++++++++++++++++++++++++++++++++----
 3 files changed, 52 insertions(+), 10 deletions(-)

New commits:
commit 5b3fcbf23773ea8d039185dec2b9704981833473
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Wed Aug 23 15:50:59 2023 +0200
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Tue Sep 26 13:37:59 2023 +0200

    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>
    (cherry picked from commit c303981cfd95ce1c3881366023d5495ae2edce97)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/156965
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

diff --git a/sw/source/core/inc/tabfrm.hxx b/sw/source/core/inc/tabfrm.hxx
index a249f6c1f845..4eba886c2385 100644
--- a/sw/source/core/inc/tabfrm.hxx
+++ b/sw/source/core/inc/tabfrm.hxx
@@ -108,7 +108,7 @@ class SW_DLLPUBLIC SwTabFrame final: public SwLayoutFrame, 
public SwFlowFrame
      * 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 52774e52f0fa..ae8295b43903 100644
--- a/sw/source/core/layout/layact.cxx
+++ b/sw/source/core/layout/layact.cxx
@@ -1433,10 +1433,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 1c3a878b85d2..049893e2850d 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;
 
@@ -1381,7 +1419,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)
@@ -2645,7 +2683,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())
@@ -2678,7 +2719,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;
                     }
 

Reply via email to