[Libreoffice-commits] core.git: Branch 'libreoffice-5-3' - sw/qa sw/source

Mike Kaganski mike.kaganski at collabora.com
Mon Dec 12 20:25:04 UTC 2016


 sw/qa/extras/uiwriter/data/tdf104425.odt |binary
 sw/qa/extras/uiwriter/uiwriter.cxx       |   17 +++
 sw/source/core/inc/rowfrm.hxx            |   19 +++
 sw/source/core/layout/tabfrm.cxx         |  155 ++++++++++++++++++++++---------
 4 files changed, 146 insertions(+), 45 deletions(-)

New commits:
commit 8a800eea613c0f5ad3302136766791dc58880fb3
Author: Mike Kaganski <mike.kaganski at collabora.com>
Date:   Thu Dec 8 23:01:03 2016 +0300

    tdf#104425 sw: split rows w/large min height (fix layout loop)
    
    This solves the problem of rows with too big minimal height causing
    layout failure (the table just goes out of page, does not flow to
    next page).
    
    It does so with three steps:
    1. Currently, a row with a minimum height that flows to next page
    repeats whole min height on that (and possibly following) pages.
    If this behaviour continued, then that would cause layout loop:
    the row min height would be too high for the page, so it would
    keep flowing to next pages (actually just go beyond the botom
    because of layout failure). To mitigate this, the patch changes
    the behaviour to measure total height of all frames of the row:
    the function lcl_calcHeightOfRowBeforeThisFrame calculates the
    total height of previous row frames for the same row, then in
    places where we need to get min height, this value is subtracted
    from row min total height. On following pages the min height of
    frames will get less each time.
    
    2. When the row is split, the possibility to split depends on if
    the minimum height of the row fits into the vertical space left.
    The minimum height is found as maxinum of two values: minimal
    contents of the row (e.g., height of first line of text, or an
    object, or lower table cell), and the minimum height setting.
    As the minimum height setting should not prevent the cell to
    flow, (it only should ensure that total height is no less), we
    should not consider the setting when the split is performed
    (we should be able to keep on first page as little as required).
    To allow this, a new bool member introduced in SwRowFrame:
    m_bIsInSplit, with its setter and getter. When it is true,
    the routines that calculate min height ignore the min height
    setting. It is set in lcl_RecalcSplitLine around lcl_RecalcRow
    and SwRowFrame::Calc that decide if it's possible to keep part of
    row's content on first page, and update table's height to fit
    the rest of space.
    
    3. It turns out, that if contents of the splitted cell has less
    height than the min height setting, then following happens.
    In SwTabFrame::Split, all rows below splitted one are moved to
    follow flow table; then table frame's Shrink method used to shrink
    the freed height. At this moment, still, the height of splitted
    row is too high, and total height of table is too high. Then,
    lcl_RecalcSplitLine is called, where row is first shrunk, and then
    lcl_RecalcRow and SwRowFrame::Calc try to move contents and resize
    the splitted row. They get the minimum height of content (we already
    don't consider the min height setting), but then "last row will fill
    the space in its upper" (see SwRowFrame::Format). Row returns its
    previous size, table does not resize, it doesn't fit to page, and
    split fails.
    To try to fix that, I call SwTabFrame::Shrink in lcl_RecalcSplitLine
    after lcl_ShrinkCellsAndAllContent before lcl_RecalcRow.
    
    Unit test included.
    
    Change-Id: I37a6b3589abf287dd5efc991a6336fc378410df9
    Reviewed-on: https://gerrit.libreoffice.org/31774
    Reviewed-by: Mike Kaganski <mike.kaganski at collabora.com>
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>
    Reviewed-on: https://gerrit.libreoffice.org/31897
    Reviewed-by: Andras Timar <andras.timar at collabora.com>

diff --git a/sw/qa/extras/uiwriter/data/tdf104425.odt b/sw/qa/extras/uiwriter/data/tdf104425.odt
new file mode 100644
index 0000000..8bbf265
Binary files /dev/null and b/sw/qa/extras/uiwriter/data/tdf104425.odt differ
diff --git a/sw/qa/extras/uiwriter/uiwriter.cxx b/sw/qa/extras/uiwriter/uiwriter.cxx
index 46fd478..d609b99 100644
--- a/sw/qa/extras/uiwriter/uiwriter.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter.cxx
@@ -215,6 +215,7 @@ public:
     void testCursorWindows();
     void testLandscape();
     void testTdf95699();
+    void testTdf104425();
 
     CPPUNIT_TEST_SUITE(SwUiWriterTest);
     CPPUNIT_TEST(testReplaceForward);
@@ -326,6 +327,7 @@ public:
     CPPUNIT_TEST(testCursorWindows);
     CPPUNIT_TEST(testLandscape);
     CPPUNIT_TEST(testTdf95699);
+    CPPUNIT_TEST(testTdf104425);
     CPPUNIT_TEST_SUITE_END();
 
 private:
@@ -4067,6 +4069,21 @@ void SwUiWriterTest::testTdf95699()
     CPPUNIT_ASSERT_EQUAL(OUString("vnd.oasis.opendocument.field.FORMCHECKBOX"), pFieldMark->GetFieldname());
 }
 
+void SwUiWriterTest::testTdf104425()
+{
+    createDoc("tdf104425.odt");
+    xmlDocPtr pXmlDoc = parseLayoutDump();
+    // The document contains one top-level 1-cell table with minimum row height set to 70 cm,
+    // and the cell contents does not exceed the minimum row height.
+    // It should span over 3 pages.
+    assertXPath(pXmlDoc, "//page", 3);
+    sal_Int32 nHeight1 = getXPath(pXmlDoc, "//page[1]/body/tab/row/infos/bounds", "height").toInt32();
+    sal_Int32 nHeight2 = getXPath(pXmlDoc, "//page[2]/body/tab/row/infos/bounds", "height").toInt32();
+    sal_Int32 nHeight3 = getXPath(pXmlDoc, "//page[3]/body/tab/row/infos/bounds", "height").toInt32();
+    double fSumHeight_mm = (nHeight1 + nHeight2 + nHeight3) * 25.4 / 1440.0;
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(700.0, fSumHeight_mm, 0.05);
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(SwUiWriterTest);
 CPPUNIT_PLUGIN_IMPLEMENT();
 
diff --git a/sw/source/core/inc/rowfrm.hxx b/sw/source/core/inc/rowfrm.hxx
index 84bb857..6bc9c22 100644
--- a/sw/source/core/inc/rowfrm.hxx
+++ b/sw/source/core/inc/rowfrm.hxx
@@ -45,6 +45,8 @@ class SwRowFrame: public SwLayoutFrame
     bool m_bIsRepeatedHeadline;
     bool m_bIsRowSpanLine;
 
+    bool m_bIsInSplit;
+
     virtual void DestroyImpl() override;
     virtual ~SwRowFrame() override;
 
@@ -101,6 +103,23 @@ public:
     bool IsRowSpanLine() const { return m_bIsRowSpanLine; }
     void SetRowSpanLine( bool bNew ) { m_bIsRowSpanLine = bNew; }
 
+    // A row may only be split if the minimum height of the row frame
+    // fits into the vertical space left.
+    // The minimum height is found as maxinum of two values: minimal
+    // contents of the row (e.g., height of first line of text, or an
+    // object, or lower table cell), and the minimum height setting.
+    // As the minimum height setting should not prevent the row to
+    // flow, (it only should ensure that *total* height is no less), we
+    // should not consider the setting when the split is performed
+    // (we should be able to keep on first page as little as required).
+    // When IsInSplit is true, lcl_CalcMinRowHeight will ignore the
+    // mininum height setting. It is set in lcl_RecalcSplitLine around
+    // lcl_RecalcRow and SwRowFrame::Calc that decide if it's possible
+    // to keep part of row's content on first page, and update table's
+    // height to fit the rest of space.
+    bool IsInSplit() const { return m_bIsInSplit; }
+    void SetInSplit(bool bNew = true) { m_bIsInSplit = bNew; }
+
     DECL_FIXEDMEMPOOL_NEWDEL(SwRowFrame)
 };
 
diff --git a/sw/source/core/layout/tabfrm.cxx b/sw/source/core/layout/tabfrm.cxx
index e22b064..b2e56e8 100644
--- a/sw/source/core/layout/tabfrm.cxx
+++ b/sw/source/core/layout/tabfrm.cxx
@@ -194,6 +194,8 @@ static SwTwips lcl_CalcMinRowHeight( const SwRowFrame *pRow,
                                      const bool _bConsiderObjs );
 static SwTwips lcl_CalcTopAndBottomMargin( const SwLayoutFrame&, const SwBorderAttrs& );
 
+static SwTwips lcl_calcHeightOfRowBeforeThisFrame(const SwRowFrame& rRow);
+
 static SwTwips lcl_GetHeightOfRows( const SwFrame* pStart, long nCount )
 {
     if ( !nCount || !pStart)
@@ -516,8 +518,7 @@ static void lcl_PreprocessRowsInCells( SwTabFrame& rTab, SwRowFrame& rLastLine,
             // pTmpLastLineRow does not fit to the line or it is the last line
             // Check if we can move pTmpLastLineRow to the follow table,
             // or if we have to split the line:
-            SwFrame* pCell = pTmpLastLineRow->Lower();
-            bool bTableLayoutToComplex = false;
+            bool bTableLayoutTooComplex = false;
             long nMinHeight = 0;
 
             // We have to take into account:
@@ -528,12 +529,19 @@ static void lcl_PreprocessRowsInCells( SwTabFrame& rTab, SwRowFrame& rLastLine,
                 nMinHeight = (pTmpLastLineRow->Frame().*aRectFnSet->fnGetHeight)();
             else
             {
+                {
+                    const SwFormatFrameSize &rSz = pTmpLastLineRow->GetFormat()->GetFrameSize();
+                    if ( rSz.GetHeightSizeType() == ATT_MIN_SIZE )
+                        nMinHeight = rSz.GetHeight() - lcl_calcHeightOfRowBeforeThisFrame(*pTmpLastLineRow);
+                }
+
+                SwFrame* pCell = pTmpLastLineRow->Lower();
                 while ( pCell )
                 {
                     if ( static_cast<SwCellFrame*>(pCell)->Lower() &&
                          static_cast<SwCellFrame*>(pCell)->Lower()->IsRowFrame() )
                     {
-                        bTableLayoutToComplex = true;
+                        bTableLayoutTooComplex = true;
                         break;
                     }
 
@@ -542,10 +550,6 @@ static void lcl_PreprocessRowsInCells( SwTabFrame& rTab, SwRowFrame& rLastLine,
                     nMinHeight = std::max( nMinHeight, lcl_CalcTopAndBottomMargin( *static_cast<SwLayoutFrame*>(pCell), rAttrs ) );
                     pCell = pCell->GetNext();
                 }
-
-                const SwFormatFrameSize &rSz = pTmpLastLineRow->GetFormat()->GetFrameSize();
-                if ( rSz.GetHeightSizeType() == ATT_MIN_SIZE )
-                    nMinHeight = std::max( nMinHeight, rSz.GetHeight() );
             }
 
             // 1. Case:
@@ -558,7 +562,7 @@ static void lcl_PreprocessRowsInCells( SwTabFrame& rTab, SwRowFrame& rLastLine,
             // the master table, and the table structure is not to complex.
             if ( nTmpCut > nCurrentHeight ||
                  ( pTmpLastLineRow->IsRowSplitAllowed() &&
-                  !bTableLayoutToComplex && nMinHeight < nTmpCut ) )
+                  !bTableLayoutTooComplex && nMinHeight < nTmpCut ) )
             {
                 // The line has to be split:
                 SwRowFrame* pNewRow = new SwRowFrame( *pTmpLastLineRow->GetTabLine(), &rTab, false );
@@ -624,12 +628,14 @@ 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 nRemainingSpaceForLastRow, SwTwips nAlreadyFree )
 {
     bool bRet = true;
 
     vcl::RenderContext* pRenderContext = rLastLine.getRootFrame()->GetCurrShell()->GetOut();
     SwTabFrame& rTab = static_cast<SwTabFrame&>(*rLastLine.GetUpper());
+    SwRectFnSet aRectFnSet(rTab.GetUpper());
+    SwTwips nCurLastLineHeight = (rLastLine.Frame().*aRectFnSet->fnGetHeight)();
 
     // If there are nested cells in rLastLine, the recalculation of the last
     // line needs some preprocessing.
@@ -639,7 +645,6 @@ static bool lcl_RecalcSplitLine( SwRowFrame& rLastLine, SwRowFrame& rFollowLine,
     rTab.SetRebuildLastLine( true );
     // #i26945#
     rTab.SetDoesObjsFit( true );
-    SwRectFnSet aRectFnSet(rTab.GetUpper());
 
     // #i26945# - invalidate and move floating screen
     // objects 'out of range'
@@ -656,6 +661,11 @@ static bool lcl_RecalcSplitLine( SwRowFrame& rLastLine, SwRowFrame& rFollowLine,
     // invalidate last line
     ::SwInvalidateAll( &rLastLine, LONG_MAX );
 
+    // Shrink the table to account for the shrunk last row, as well as lower rows
+    // that had been moved to follow table in SwTabFrame::Split.
+    // It will grow later when last line will recalc its height.
+    rTab.Shrink(nAlreadyFree + nCurLastLineHeight - nRemainingSpaceForLastRow + 1);
+
     // Lock this tab frame and its follow
     bool bUnlockMaster = false;
     bool bUnlockFollow = false;
@@ -671,6 +681,9 @@ static bool lcl_RecalcSplitLine( SwRowFrame& rLastLine, SwRowFrame& rFollowLine,
         ::TableSplitRecalcLock( rTab.GetFollow() );
     }
 
+    bool bInSplit = rLastLine.IsInSplit();
+    rLastLine.SetInSplit();
+
     // Do the recalculation
     lcl_RecalcRow( rLastLine, LONG_MAX );
     // #115759# - force a format of the last line in order to
@@ -678,6 +691,8 @@ static bool lcl_RecalcSplitLine( SwRowFrame& rLastLine, SwRowFrame& rFollowLine,
     rLastLine.InvalidateSize();
     rLastLine.Calc(pRenderContext);
 
+    rLastLine.SetInSplit(bInSplit);
+
     // Unlock this tab frame and its follow
     if ( bUnlockFollow )
         ::TableSplitRecalcUnlock( rTab.GetFollow() );
@@ -933,7 +948,7 @@ bool SwTabFrame::Split( const SwTwips nCutPos, bool bTryToSplit, bool bTableRowK
         lcl_InnerCalcLayout( this->Lower(), LONG_MAX, true );
     }
 
-    //In order to be able to compare the positions of the cells whit CutPos,
+    //In order to be able to compare the positions of the cells whith CutPos,
     //they have to be calculated consecutively starting from the table.
     //They can definitely be invalid because of position changes of the table.
     SwRowFrame *pRow = static_cast<SwRowFrame*>(Lower());
@@ -965,7 +980,7 @@ bool SwTabFrame::Split( const SwTwips nCutPos, bool bTryToSplit, bool bTableRowK
     // bTryToSplit:      Row will never be split if bTryToSplit = false.
     //                   This can either be passed as a parameter, indicating
     //                   that we are currently doing the second try to split the
-    //                   table, or it will be set to falseunder certain
+    //                   table, or it will be set to false under certain
     //                   conditions that are not suitable for splitting
     //                   the row.
     bool bSplitRowAllowed = pRow->IsRowSplitAllowed();
@@ -1140,9 +1155,9 @@ bool SwTabFrame::Split( const SwTwips nCutPos, bool bTryToSplit, bool bTableRowK
         }
     }
 
-    SwRowFrame* pLastRow = nullptr;     // will point to the last remaining line in master
-    SwRowFrame* pFollowRow = nullptr;   // points to either the follow flow line of the
-                                // first regular line in the follow
+    SwRowFrame* pLastRow = nullptr;     // points to the last remaining line in master
+    SwRowFrame* pFollowRow = nullptr;   // points to either the follow flow line or the
+                                        // first regular line in the follow
 
     if ( bSplitRowAllowed )
     {
@@ -1178,7 +1193,7 @@ bool SwTabFrame::Split( const SwTwips nCutPos, bool bTryToSplit, bool bTableRowK
             pFollowRow = lcl_InsertNewFollowFlowLine( *this, *pLastRow, true );
     }
 
-    SwTwips nRet = 0;
+    SwTwips nShrink = 0;
 
     //Optimization: There is no paste needed for the new Follow and the
     //optimized insert can be used (big amounts of rows luckily only occurs in
@@ -1190,7 +1205,7 @@ bool SwTabFrame::Split( const SwTwips nCutPos, bool bTryToSplit, bool bTableRowK
         while ( pRow )
         {
             SwFrame* pNxt = pRow->GetNext();
-            nRet += (pRow->Frame().*aRectFnSet->fnGetHeight)();
+            nShrink += (pRow->Frame().*aRectFnSet->fnGetHeight)();
             // The footnotes do not have to be moved, this is done in the
             // MoveFwd of the follow table!!!
             pRow->RemoveFromLayout();
@@ -1209,7 +1224,7 @@ bool SwTabFrame::Split( const SwTwips nCutPos, bool bTryToSplit, bool bTableRowK
         while ( pRow )
         {
             SwFrame* pNxt = pRow->GetNext();
-            nRet += (pRow->Frame().*aRectFnSet->fnGetHeight)();
+            nShrink += (pRow->Frame().*aRectFnSet->fnGetHeight)();
 
             // The footnotes have to be moved:
             lcl_MoveFootnotes( *this, *GetFollow(), *pRow );
@@ -1222,13 +1237,15 @@ bool SwTabFrame::Split( const SwTwips nCutPos, bool bTryToSplit, bool bTableRowK
         }
     }
 
-    Shrink( nRet );
-
-    // we rebuild the last line to assure that it will be fully formatted
-    if ( pLastRow )
+    if ( !pLastRow )
+        Shrink( nShrink );
+    else
     {
+        // we rebuild the last line to assure that it will be fully formatted
+        // 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 );
+        bRet = lcl_RecalcSplitLine( *pLastRow, *pFollowRow, nRemainingSpaceForLastRow, nShrink );
 
         // NEW TABLES
         // check if each cell in the row span line has a good height
@@ -3539,6 +3556,7 @@ SwRowFrame::SwRowFrame(const SwTableLine &rLine, SwFrame* pSib, bool bInsertCont
     // <-- split table rows
     , m_bIsRepeatedHeadline( false )
     , m_bIsRowSpanLine( false )
+    , m_bIsInSplit( false )
 {
     mnFrameType = SwFrameType::Row;
 
@@ -3811,17 +3829,24 @@ static SwTwips lcl_CalcMinCellHeight( const SwLayoutFrame *_pCell,
 static SwTwips lcl_CalcMinRowHeight( const SwRowFrame* _pRow,
                                      const bool _bConsiderObjs )
 {
-    SwRectFnSet aRectFnSet(_pRow);
-
-    const SwFormatFrameSize &rSz = _pRow->GetFormat()->GetFrameSize();
-
-    if ( _pRow->HasFixSize() && !_pRow->IsRowSpanLine() )
+    SwTwips nHeight = 0;
+    if ( !_pRow->IsRowSpanLine() )
     {
-        OSL_ENSURE( ATT_FIX_SIZE == rSz.GetHeightSizeType(), "pRow claims to have fixed size" );
-        return rSz.GetHeight();
+        const SwFormatFrameSize &rSz = _pRow->GetFormat()->GetFrameSize();
+        if ( _pRow->HasFixSize() )
+        {
+            OSL_ENSURE(ATT_FIX_SIZE == rSz.GetHeightSizeType(), "pRow claims to have fixed size");
+            return rSz.GetHeight();
+        }
+        // If this row frame is being split, then row's minimal height shouldn't restrict
+        // this frame's minimal height, because the rest will go to follow frame.
+        else if ( !_pRow->IsInSplit() && rSz.GetHeightSizeType() == ATT_MIN_SIZE )
+        {
+            nHeight = rSz.GetHeight() - lcl_calcHeightOfRowBeforeThisFrame(*_pRow);
+        }
     }
 
-    SwTwips nHeight = 0;
+    SwRectFnSet aRectFnSet(_pRow);
     const SwCellFrame* pLow = static_cast<const SwCellFrame*>(_pRow->Lower());
     while ( pLow )
     {
@@ -3858,8 +3883,7 @@ static SwTwips lcl_CalcMinRowHeight( const SwRowFrame* _pRow,
 
         pLow = static_cast<const SwCellFrame*>(pLow->GetNext());
     }
-    if ( rSz.GetHeightSizeType() == ATT_MIN_SIZE && !_pRow->IsRowSpanLine() )
-        nHeight = std::max( nHeight, rSz.GetHeight() );
+
     return nHeight;
 }
 
@@ -3956,6 +3980,41 @@ static sal_uInt16 lcl_GetBottomLineDist( const SwRowFrame& rRow )
     return nBottomLineDist;
 }
 
+// tdf#104425: calculate the height of all row frames,
+// for which this frame is a follow.
+// When a row has fixed/minimum height, it may span over
+// several pages. The minimal height on this page should
+// take into account the sum of all the heights of previous
+// frames that constitute the table row on previous pages.
+// Otherwise, trying to split a too high row frame will
+// result in loop trying to create that too high row
+// on each following page
+static SwTwips lcl_calcHeightOfRowBeforeThisFrame(const SwRowFrame& rRow)
+{
+    SwRectFnSet aRectFnSet(&rRow);
+    const SwTableLine* pLine = rRow.GetTabLine();
+    const SwTabFrame* pTab = rRow.FindTabFrame();
+    if (!pLine || !pTab || !pTab->IsFollow())
+        return 0;
+    SwTwips nResult = 0;
+    SwIterator<SwRowFrame, SwFormat> aIter(*pLine->GetFrameFormat());
+    for (const SwRowFrame* pCurRow = aIter.First(); pCurRow; pCurRow = aIter.Next())
+    {
+        if (pCurRow != &rRow && pCurRow->GetTabLine() == pLine)
+        {
+            // We've found another row frame that is part of the same table row
+            const SwTabFrame* pCurTab = pCurRow->FindTabFrame();
+            if (pCurTab->IsAnFollow(pTab))
+            {
+                // The found row frame belongs to a table frame that preceedes
+                // (above) this one in chain. So, include it in the sum
+                nResult += (pCurRow->Frame().*aRectFnSet->fnGetHeight)();
+            }
+        }
+    }
+    return nResult;
+}
+
 void SwRowFrame::Format( vcl::RenderContext* /*pRenderContext*/, const SwBorderAttrs *pAttrs )
 {
     SwRectFnSet aRectFnSet(this);
@@ -4301,7 +4360,7 @@ SwTwips SwRowFrame::ShrinkFrame( SwTwips nDist, bool bTst, bool bInfo )
         return 0L;
     }
 
-    // bInfo may be set to true by SwRowFrame::Format; we need to hangle this
+    // bInfo may be set to true by SwRowFrame::Format; we need to handle this
     // here accordingly
     const bool bShrinkAnyway = bInfo;
 
@@ -4311,9 +4370,10 @@ SwTwips SwRowFrame::ShrinkFrame( SwTwips nDist, bool bTst, bool bInfo )
     if (pMod)
     {
         const SwFormatFrameSize &rSz = pMod->GetFrameSize();
-        SwTwips nMinHeight = rSz.GetHeightSizeType() == ATT_MIN_SIZE ?
-                             rSz.GetHeight() :
-                             0;
+        SwTwips nMinHeight = 0;
+        if (rSz.GetHeightSizeType() == ATT_MIN_SIZE)
+            nMinHeight = std::max(rSz.GetHeight() - lcl_calcHeightOfRowBeforeThisFrame(*this),
+                                  0L);
 
         // Only necessary to calculate minimal row height if height
         // of pRow is at least nMinHeight. Otherwise nMinHeight is the
@@ -5167,7 +5227,7 @@ static SwTwips lcl_CalcHeightOfFirstContentLine( const SwRowFrame& rSourceLine )
                 const SwRowFrame* pTmpSourceRow = static_cast<const SwRowFrame*>(pCurrSourceCell->Lower());
                 nTmpHeight = lcl_CalcHeightOfFirstContentLine( *pTmpSourceRow );
             }
-            if ( pTmp->IsTabFrame() )
+            else if ( pTmp->IsTabFrame() )
             {
                 nTmpHeight = static_cast<const SwTabFrame*>(pTmp)->CalcHeightOfFirstContentLine();
             }
@@ -5282,12 +5342,12 @@ SwTwips SwTabFrame::CalcHeightOfFirstContentLine() const
 
     SwTwips nTmpHeight = 0;
 
-    SwRowFrame* pFirstRow = GetFirstNonHeadlineRow();
+    const SwRowFrame* pFirstRow = GetFirstNonHeadlineRow();
     OSL_ENSURE( !IsFollow() || pFirstRow, "FollowTable without Lower" );
 
     // NEW TABLES
     if ( pFirstRow && pFirstRow->IsRowSpanLine() && pFirstRow->GetNext() )
-        pFirstRow = static_cast<SwRowFrame*>(pFirstRow->GetNext());
+        pFirstRow = static_cast<const SwRowFrame*>(pFirstRow->GetNext());
 
     // Calculate the height of the headlines:
     const sal_uInt16 nRepeat = GetTable()->GetRowsToRepeat();
@@ -5304,7 +5364,7 @@ SwTwips SwTabFrame::CalcHeightOfFirstContentLine() const
         while ( pFirstRow && pFirstRow->ShouldRowKeepWithNext() )
         {
             ++nKeepRows;
-            pFirstRow = static_cast<SwRowFrame*>(pFirstRow->GetNext());
+            pFirstRow = static_cast<const SwRowFrame*>(pFirstRow->GetNext());
         }
 
         if ( nKeepRows > nRepeat )
@@ -5338,7 +5398,7 @@ SwTwips SwTabFrame::CalcHeightOfFirstContentLine() const
             // line as it would be on the last page. Since this is quite complicated to calculate,
             // we only calculate the height of the first line.
             if ( pFirstRow->GetPrev() &&
-                 static_cast<SwRowFrame*>(pFirstRow->GetPrev())->IsRowSpanLine() )
+                 static_cast<const SwRowFrame*>(pFirstRow->GetPrev())->IsRowSpanLine() )
             {
                 // Calculate maximum height of all cells with rowspan = 1:
                 SwTwips nMaxHeight = 0;
@@ -5370,9 +5430,14 @@ SwTwips SwTabFrame::CalcHeightOfFirstContentLine() const
             const SwTwips nHeightOfFirstContentLine = lcl_CalcHeightOfFirstContentLine( *pFirstRow );
 
             // Consider minimum row height:
-            const SwFormatFrameSize &rSz = static_cast<const SwRowFrame*>(pFirstRow)->GetFormat()->GetFrameSize();
-            const SwTwips nMinRowHeight = rSz.GetHeightSizeType() == ATT_MIN_SIZE ?
-                                          rSz.GetHeight() : 0;
+            const SwFormatFrameSize &rSz = pFirstRow->GetFormat()->GetFrameSize();
+
+            SwTwips nMinRowHeight = 0;
+            if (rSz.GetHeightSizeType() == ATT_MIN_SIZE)
+            {
+                nMinRowHeight = std::max(rSz.GetHeight() - lcl_calcHeightOfRowBeforeThisFrame(*pFirstRow),
+                                         0L);
+            }
 
             nTmpHeight += std::max( nHeightOfFirstContentLine, nMinRowHeight );
 


More information about the Libreoffice-commits mailing list