[Libreoffice-commits] core.git: sw/source

Michael Stahl (via logerrit) logerrit at kemper.freedesktop.org
Mon Jun 21 12:51:19 UTC 2021


 sw/source/core/doc/htmltbl.cxx   |    2 -
 sw/source/core/inc/tabfrm.hxx    |    3 +-
 sw/source/core/layout/tabfrm.cxx |   49 +++++++++++++++++++++++++++++++++------
 3 files changed, 45 insertions(+), 9 deletions(-)

New commits:
commit f1439db62eb36ef5fbc9111b87dc4e0f24b3cb86
Author:     Michael Stahl <michael.stahl at allotropia.de>
AuthorDate: Fri Jun 18 19:49:46 2021 +0200
Commit:     Michael Stahl <michael.stahl at allotropia.de>
CommitDate: Mon Jun 21 14:50:41 2021 +0200

    tdf#116501 sw: layout: check for flys in SwTabFrame::ShouldBwdMoved()
    
    On loading, this hits loop control
    
    warn:legacy.osl:580715:580715:sw/source/core/layout/layact.cxx:543: LoopControl_1 in SwLayAction::InternalAction
    
    This is because there's a fly frame 404 anchored at the last text
    frame 353 on page 2 inside the nested table 347.
    
    ShouldBwdMoved() sees that there is space on the bottom of page 2 and
    hence the follow flow row joined, but then it immediately splits again
    in the same way as before due to the fly with WrapTextMode_NONE.
    
    But then the outer table's cell 273 (upper of 347) is invalidated
    again, hence the loop.
    
    Try to check for overlapping flys in SwTabFrame::ShouldBwdMoved()
    by reusing CalcFlyOffsets(), which is ... not quite ideal, but perhaps
    better than copy-pasting half of it to a new function.
    
    This should have less side effects than the previous fix, but a problem
    remains that clicking on the shape on bottom of page 2 causes the layout
    to go wonky, but that was also the case with previous fix.
    
    Note there's a check of SwLayouter::DoesRowContainMovedFwdFrame() there
    already, but that doesn't help because it will only detect when the fly
    itself was moved forward, but in this case the fly remains on the page.
    
    Also likely it wouldn't be a good idea to move a text frame forward if
    the only thing of it that fits on a page is an anchored fly (i.e. its
    follow has mnOffset=0) because that can be intentional.
    
    Change-Id: I0376f7dcb784c006990336233c97f5093aaccb77
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/117473
    Tested-by: Jenkins
    Tested-by: László Németh <nemeth at numbertext.org>
    Reviewed-by: László Németh <nemeth at numbertext.org>

diff --git a/sw/source/core/doc/htmltbl.cxx b/sw/source/core/doc/htmltbl.cxx
index 41a10d34c10b..8aba28a8b806 100644
--- a/sw/source/core/doc/htmltbl.cxx
+++ b/sw/source/core/doc/htmltbl.cxx
@@ -364,7 +364,7 @@ sal_uInt16 SwHTMLTableLayout::GetBrowseWidthByTabFrame(
     SwTwips nUpperDummy = 0;
     tools::Long nRightOffset = 0,
          nLeftOffset  = 0;
-    rTabFrame.CalcFlyOffsets( nUpperDummy, nLeftOffset, nRightOffset );
+    rTabFrame.CalcFlyOffsets(nUpperDummy, nLeftOffset, nRightOffset, nullptr);
     nWidth -= (nLeftOffset + nRightOffset);
 
     return o3tl::narrowing<sal_uInt16>(std::min(nWidth, SwTwips(SAL_MAX_UINT16)));
diff --git a/sw/source/core/inc/tabfrm.hxx b/sw/source/core/inc/tabfrm.hxx
index 460c42d92434..11e61f7c5b31 100644
--- a/sw/source/core/inc/tabfrm.hxx
+++ b/sw/source/core/inc/tabfrm.hxx
@@ -218,7 +218,8 @@ public:
     bool CalcFlyOffsets(
         SwTwips& rUpper,
         tools::Long& rLeftOffset,
-        tools::Long& rRightOffset ) const;
+        tools::Long& rRightOffset,
+        SwTwips * pSpaceBelowBottom) const;
 
     SwTwips CalcHeightOfFirstContentLine() const;
 
diff --git a/sw/source/core/layout/tabfrm.cxx b/sw/source/core/layout/tabfrm.cxx
index 241827898a67..1626e4eac315 100644
--- a/sw/source/core/layout/tabfrm.cxx
+++ b/sw/source/core/layout/tabfrm.cxx
@@ -2732,7 +2732,8 @@ static bool IsNextOnSamePage(SwPageFrame const& rPage,
 /// Calculate the offsets arising because of FlyFrames
 bool SwTabFrame::CalcFlyOffsets( SwTwips& rUpper,
                                tools::Long& rLeftOffset,
-                               tools::Long& rRightOffset ) const
+                               tools::Long& rRightOffset,
+                               SwTwips *const pSpaceBelowBottom) const
 {
     bool bInvalidatePrtArea = false;
     const SwPageFrame *pPage = FindPageFrame();
@@ -2752,9 +2753,16 @@ bool SwTabFrame::CalcFlyOffsets( SwTwips& rUpper,
         tools::Long nPrtPos = aRectFnSet.GetTop(getFrameArea());
         nPrtPos = aRectFnSet.YInc( nPrtPos, rUpper );
         SwRect aRect( getFrameArea() );
-        tools::Long nYDiff = aRectFnSet.YDiff( aRectFnSet.GetTop(getFramePrintArea()), rUpper );
-        if( nYDiff > 0 )
-            aRectFnSet.AddBottom( aRect, -nYDiff );
+        if (pSpaceBelowBottom)
+        {   // set to space below table frame
+            aRectFnSet.SetTopAndHeight(aRect, aRectFnSet.GetBottom(aRect), *pSpaceBelowBottom);
+        }
+        else
+        {
+            tools::Long nYDiff = aRectFnSet.YDiff( aRectFnSet.GetTop(getFramePrintArea()), rUpper );
+            if (nYDiff > 0)
+                aRectFnSet.AddBottom( aRect, -nYDiff );
+        }
 
         bool bAddVerticalFlyOffsets = rIDSA.get(DocumentSettingId::ADD_VERTICAL_FLY_OFFSETS);
 
@@ -2791,8 +2799,9 @@ bool SwTabFrame::CalcFlyOffsets( SwTwips& rUpper,
                     aFlyRect.IsOver( aRect ) &&
                     // fly isn't lower of table and
                     // anchor character frame of fly isn't lower of table
-                    ( !IsAnLower( pFly ) &&
-                      ( !pAnchorCharFrame || !IsAnLower( pAnchorCharFrame ) ) ) &&
+                    (pSpaceBelowBottom // not if in ShouldBwdMoved
+                     || (!IsAnLower( pFly ) &&
+                          (!pAnchorCharFrame || !IsAnLower(pAnchorCharFrame)))) &&
                     // table isn't lower of fly
                     !pFly->IsAnLower( this ) &&
                     // fly is lower of fly, the table is in
@@ -2874,6 +2883,20 @@ bool SwTabFrame::CalcFlyOffsets( SwTwips& rUpper,
                         {
                             if (aRectFnSet.YDiff( nPrtPos, nBottom ) < 0)
                                 nPrtPos = nBottom;
+                            // tdf#116501 subtract flys blocking space from below
+                            // TODO this may not work ideally for multiple flys
+                            if (pSpaceBelowBottom
+                                && aRectFnSet.YDiff(aRectFnSet.GetBottom(aRect), nBottom) < 0)
+                            {
+                                if (aRectFnSet.YDiff(aRectFnSet.GetTop(aRect), aRectFnSet.GetTop(aFlyRect)) < 0)
+                                {
+                                    aRectFnSet.SetBottom(aRect, aRectFnSet.GetTop(aFlyRect));
+                                }
+                                else
+                                {
+                                    aRectFnSet.SetHeight(aRect, 0);
+                                }
+                            }
                             bInvalidatePrtArea = true;
                         }
                     }
@@ -2901,6 +2924,10 @@ bool SwTabFrame::CalcFlyOffsets( SwTwips& rUpper,
             }
         }
         rUpper = aRectFnSet.YDiff( nPrtPos, aRectFnSet.GetTop(getFrameArea()) );
+        if (pSpaceBelowBottom)
+        {
+            *pSpaceBelowBottom = aRectFnSet.GetHeight(aRect);
+        }
     }
 
     return bInvalidatePrtArea;
@@ -2936,7 +2963,7 @@ void SwTabFrame::Format( vcl::RenderContext* /*pRenderContext*/, const SwBorderA
     //    those are right or left aligned, those set the minimum for the margins
     tools::Long nTmpRight = -1000000,
          nLeftOffset  = 0;
-    if( CalcFlyOffsets( nUpper, nLeftOffset, nTmpRight ) )
+    if (CalcFlyOffsets(nUpper, nLeftOffset, nTmpRight, nullptr))
     {
         setFramePrintAreaValid(false);
     }
@@ -3589,6 +3616,14 @@ bool SwTabFrame::ShouldBwdMoved( SwLayoutFrame *pNewUpper, bool &rReformat )
                     const SwViewShell *pSh = getRootFrame()->GetCurrShell();
                     if( pSh && pSh->GetViewOptions()->getBrowseMode() )
                         nSpace += pNewUpper->Grow( LONG_MAX, true );
+                    if (0 < nSpace && GetPrecede())
+                    {
+                        SwTwips nUpperDummy(0);
+                        tools::Long nLeftOffsetDummy(0), nRightOffsetDummy(0);
+                        // tdf#116501 check for no-wrap fly overlap
+                        static_cast<const SwTabFrame*>(GetPrecede())->CalcFlyOffsets(
+                            nUpperDummy, nLeftOffsetDummy, nRightOffsetDummy, &nSpace);
+                    }
                 }
             }
             else if (!m_bLockBackMove)


More information about the Libreoffice-commits mailing list