sw/qa/extras/layout/data/tdf152298.docx |binary
 sw/qa/extras/layout/layout3.cxx         |   23 +++++++++++
 sw/source/core/layout/tabfrm.cxx        |   62 +++++++++++++++++++++++++++++---
 3 files changed, 80 insertions(+), 5 deletions(-)

New commits:
commit f0baab027df46d4e74b7808ff5d976b8efb1ea33
Author:     Mike Kaganski <[email protected]>
AuthorDate: Wed Sep 18 18:07:25 2024 +0500
Commit:     Mike Kaganski <[email protected]>
CommitDate: Fri Sep 20 04:05:44 2024 +0200

    tdf#152298: Handle "keep with next, allow split, span some rows" case
    
    All the rows on the table in bugdoc require to be kept with next
    (their first cells' first paragraphs have that flag). The layout
    finds the table break position after row 39;  but then it checks
    that that row should be kept with row 38,  that with row 37, and
    so on.  The layout loop happens because the search for the break
    position can't find a row.
    
    But cell A38 spans over four rows;  in this case, Word checks if
    this row can split, and splits the spanning cells, apparently as
    keeping "part" of the row with next.
    
    This change implements that algorithm.
    
    Change-Id: I234694138ac6b660781ad773cef20151daf874eb
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/173675
    Reviewed-by: Mike Kaganski <[email protected]>
    Tested-by: Jenkins

diff --git a/sw/qa/extras/layout/data/tdf152298.docx 
b/sw/qa/extras/layout/data/tdf152298.docx
new file mode 100644
index 000000000000..22c3de81a038
Binary files /dev/null and b/sw/qa/extras/layout/data/tdf152298.docx differ
diff --git a/sw/qa/extras/layout/layout3.cxx b/sw/qa/extras/layout/layout3.cxx
index cc27f66e3127..1f9358147e9f 100644
--- a/sw/qa/extras/layout/layout3.cxx
+++ b/sw/qa/extras/layout/layout3.cxx
@@ -3670,6 +3670,29 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, 
TestTdf152142DoNotMirrorRtlDrawObjs)
     CPPUNIT_ASSERT_LESS(nShapeEnd, nTextBoxEnd);
 }
 
+CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf152298)
+{
+    createSwDoc("tdf152298.docx");
+    auto pDump = parseLayoutDump();
+
+    assertXPath(pDump, "//page"_ostr, 2);
+    // Without the fix, this was 39
+    assertXPath(pDump, "//page[1]/body/tab/row"_ostr, 38);
+    assertXPath(pDump, "//page[1]/body/tab/row[38]/cell[1]"_ostr, 
"rowspan"_ostr, u"4"_ustr);
+    OUString a38_id = getXPath(pDump, 
"//page[1]/body/tab/row[38]/cell[1]"_ostr, "id"_ostr);
+    OUString follow_id = getXPath(pDump, 
"//page[1]/body/tab/row[38]/cell[1]"_ostr, "follow"_ostr);
+    // The text of A38, that spans four rows, must be split: empty paragraph 
here
+    assertXPathContent(pDump, "//page[1]/body/tab/row[38]/cell[1]/txt"_ostr, 
u""_ustr);
+    // First row is the repeating line
+    assertXPathContent(pDump, "//page[2]/body/tab/row[1]/cell[1]/txt"_ostr, 
u"1"_ustr);
+    assertXPathContent(pDump, "//page[2]/body/tab/row[1]/cell[2]/txt"_ostr, 
u"2"_ustr);
+    assertXPathContent(pDump, "//page[2]/body/tab/row[1]/cell[3]/txt"_ostr, 
u"3"_ustr);
+    // The text in the follow row's first cell is the second paragraph of A38, 
"10"
+    assertXPath(pDump, "//page[2]/body/tab/row[2]/cell[1]"_ostr, "id"_ostr, 
follow_id);
+    assertXPath(pDump, "//page[2]/body/tab/row[2]/cell[1]"_ostr, 
"precede"_ostr, a38_id);
+    assertXPathContent(pDump, "//page[2]/body/tab/row[2]/cell[1]/txt"_ostr, 
u"10"_ustr);
+}
+
 } // end of anonymous namespace
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/source/core/layout/tabfrm.cxx b/sw/source/core/layout/tabfrm.cxx
index fea11a76497f..9948b1be0c5c 100644
--- a/sw/source/core/layout/tabfrm.cxx
+++ b/sw/source/core/layout/tabfrm.cxx
@@ -1254,6 +1254,26 @@ bool SwTabFrame::Split(const SwTwips nCutPos, bool 
bTryToSplit,
         while ( pTmpRow && pTmpRow->ShouldRowKeepWithNext() &&
                 nRowCount > nRepeat )
         {
+            // Special case: pTmpRow wants to keep with pRow, but allows 
splitting, and some its
+            // cells span several rows, including pRow. In this case, the 
"split" of the spanning
+            // cells of the pTmpRow may still happen by moving pRow to the 
next page, even here
+            // with !bSplitRowAllowed.
+            if (pTmpRow->IsRowSplitAllowed())
+            {
+                bool bCellSpanCanSplit = false;
+                for (auto pCellFrame = static_cast<const 
SwCellFrame*>(pTmpRow->GetLower());
+                     pCellFrame;
+                     pCellFrame = static_cast<const 
SwCellFrame*>(pCellFrame->GetNext()))
+                {
+                    if (pCellFrame->GetTabBox()->getRowSpan() > 1) // Master 
cell
+                    {
+                        bCellSpanCanSplit = true;
+                        break;
+                    }
+                }
+                if (bCellSpanCanSplit)
+                    break;
+            }
             pRow = pTmpRow;
             --nRowCount;
             pTmpRow = static_cast<SwRowFrame*>(pTmpRow->GetPrev());
@@ -2255,9 +2275,31 @@ void SwTabFrame::MakeAll(vcl::RenderContext* 
pRenderContext)
         const SwRowFrame* pTmpRow = static_cast<const 
SwRowFrame*>(GetLastLower());
         if ( pTmpRow && pTmpRow->ShouldRowKeepWithNext() )
         {
-            if ( HasFollowFlowLine() )
-                RemoveFollowFlowLine();
-            Join();
+            // Special case: pTmpRow wants to keep with next, but allows 
splitting, and some its
+            // cells span several rows - i.e., also the next row. In this 
case, the "split" of the
+            // spanning cells of the pTmpRow may still happen by moving next 
row to the next page,
+            // even here with bTableRowKeep.
+            bool bCellSpanCanSplit = false;
+            if (pTmpRow->IsRowSplitAllowed())
+            {
+                for (auto pCellFrame = static_cast<const 
SwCellFrame*>(pTmpRow->GetLower());
+                     pCellFrame;
+                     pCellFrame = static_cast<const 
SwCellFrame*>(pCellFrame->GetNext()))
+                {
+                    if (pCellFrame->GetTabBox()->getRowSpan() > 1) // Master 
cell
+                    {
+                        bCellSpanCanSplit = true;
+                        break;
+                    }
+                }
+            }
+
+            if (!bCellSpanCanSplit)
+            {
+                if (HasFollowFlowLine())
+                    RemoveFollowFlowLine();
+                Join();
+            }
         }
     }
 
@@ -2947,8 +2989,18 @@ void SwTabFrame::MakeAll(vcl::RenderContext* 
pRenderContext)
 
                     oAccess.reset();
                     bool isFootnoteGrowth(false);
+                    bool bEffectiveTableRowKeep;
+                    if (bTryToSplit == true)
+                    {
+                        bEffectiveTableRowKeep = bTableRowKeep && 
!(bAllowSplitOfRow || bEmulateTableKeepSplitAllowed);
+                    }
+                    else
+                    {
+                        // The second attempt; ignore all the flags allowing 
to split the row
+                        bEffectiveTableRowKeep = bTableRowKeep;
+                    }
                     const bool bSplitError = !Split(nDeadLine, bTryToSplit,
-                        (bTableRowKeep && !(bAllowSplitOfRow || 
bEmulateTableKeepSplitAllowed)),
+                        bEffectiveTableRowKeep,
                         isFootnoteGrowth);
 
                     // tdf#130639 don't start table on a new page after the 
fallback "switch off repeating header"
commit afb6671d669120f213da0aa9f3973a02905a4088
Author:     Mike Kaganski <[email protected]>
AuthorDate: Wed Sep 18 14:19:33 2024 +0500
Commit:     Mike Kaganski <[email protected]>
CommitDate: Fri Sep 20 04:05:35 2024 +0200

    Check if split is forced when calculating fixed-height row's min height
    
    Change-Id: Ib5780d229041823e9aa7ba1c086655eb7c8590eb
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/173601
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <[email protected]>

diff --git a/sw/source/core/layout/tabfrm.cxx b/sw/source/core/layout/tabfrm.cxx
index 0ebdd4cb17cc..fea11a76497f 100644
--- a/sw/source/core/layout/tabfrm.cxx
+++ b/sw/source/core/layout/tabfrm.cxx
@@ -4826,7 +4826,7 @@ static SwTwips lcl_CalcMinRowHeight( const SwRowFrame* 
_pRow,
     if ( !_pRow->IsRowSpanLine() )
     {
         const SwFormatFrameSize &rSz = _pRow->GetFormat()->GetFrameSize();
-        if ( _pRow->HasFixSize() )
+        if (_pRow->HasFixSize() && !_pRow->IsForceRowSplitAllowed())
         {
             OSL_ENSURE(SwFrameSize::Fixed == rSz.GetHeightSizeType(), "pRow 
claims to have fixed size");
             return rSz.GetHeight();

Reply via email to