[Libreoffice-commits] core.git: Branch 'distro/lhm/libreoffice-6-1+backports' - sw/qa sw/source

Michael Stahl (via logerrit) logerrit at kemper.freedesktop.org
Tue Nov 17 10:41:08 UTC 2020


 sw/qa/extras/layout/data/tdf138039.odt |binary
 sw/qa/extras/layout/layout.cxx         |   26 +++++++++++++++++++++++
 sw/source/core/layout/tabfrm.cxx       |   36 ++++++++++++++++++++++++++++++---
 3 files changed, 59 insertions(+), 3 deletions(-)

New commits:
commit d9d27b82246fbc92b0a82356c7f80fa4f3c8cc7f
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Fri Nov 13 20:51:42 2020 +0100
Commit:     Michael Stahl <michael.stahl at cib.de>
CommitDate: Tue Nov 17 11:40:35 2020 +0100

    tdf#138039 tdf#134298 sw: layout: fix overlap of fly and table
    
    The layout is horribly borked, the fly anchored in the body-level
    paragraph messed with the preceding table:
    
    page id="1" top="284" width="11905" height="16837" bottom="17120"
        tab id="3" top="794"
            row id="4" top="17121"
                fly id="8" top="16725"
        txt id="7" top="1394"
            fly ptr="0x6ce5510" id="10" top="1302"
    
    SwTabFrame::CalcFlyOffsets() detects an overlap with the large fly, and
    since it has wrap NONE it resizes to below the large image.
    
    Then the SwTabFrame doesn't fit on the page, so it is split, but the split
    fails because nDistanceToUpperPrtBottom is -720 (negative); hence it is
    joined again.
    
    Meanwhile the fly was invalidated, so now CalcFlyOffsets() ignores it and
    the table shrinks again.
    
    Once the fly is positioned again, the process repeats from the start.
    
    Fix this in SwTabFrame::CalcFlyOffsets() by ignoring flys with wrap NONE that
    extend below the body of the document and are anchored in a frame in the
    next-chain of the table frame: these must move to the next page with their
    anchor frame.
    
    For the bugdoc this gives the same layout as LO 5.2.
    
    Reportedly this problem started to happen since commit
    6f5024de2e1a5cc533527e45b33d9a415467c48d, but it's not obvious why.
    
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/105809
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.stahl at cib.de>
    (cherry picked from commit 6b92d2e8522ecc98d2c5532f5076c20ae295168e)
    
    Change-Id: Iafb8a6afcba634f11c5db73869313ded0fe13bbd
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/105950
    Tested-by: Michael Stahl <michael.stahl at cib.de>
    Reviewed-by: Michael Stahl <michael.stahl at cib.de>

diff --git a/sw/qa/extras/layout/data/tdf138039.odt b/sw/qa/extras/layout/data/tdf138039.odt
new file mode 100644
index 000000000000..f355fd1349a6
Binary files /dev/null and b/sw/qa/extras/layout/data/tdf138039.odt differ
diff --git a/sw/qa/extras/layout/layout.cxx b/sw/qa/extras/layout/layout.cxx
index 50ec4ac5c427..fb934cad2aec 100755
--- a/sw/qa/extras/layout/layout.cxx
+++ b/sw/qa/extras/layout/layout.cxx
@@ -38,6 +38,7 @@ public:
     void testRedlineTables();
     void testRedlineCharAttributes();
     void testRedlineShowHideFootnotePagination();
+    void testTdf138039();
     void testTdf116830();
     void testTdf116925();
     void testTdf117028();
@@ -66,6 +67,7 @@ public:
     CPPUNIT_TEST(testRedlineTables);
     CPPUNIT_TEST(testRedlineCharAttributes);
     CPPUNIT_TEST(testRedlineShowHideFootnotePagination);
+    CPPUNIT_TEST(testTdf138039);
     CPPUNIT_TEST(testTdf116830);
     CPPUNIT_TEST(testTdf116925);
     CPPUNIT_TEST(testTdf117028);
@@ -2305,6 +2307,30 @@ void SwLayoutWriter::testRedlineShowHideFootnotePagination()
                 "zzz. zzz zzzz zzzz7 zzz zzz zzzzzzz zzz zzzz zzzzzzzzzzzzzz zzzzzzzzzzzz ");
 }
 
+void SwLayoutWriter::testTdf138039()
+{
+    createDoc("tdf138039.odt");
+
+    xmlDocPtr pXmlDoc = parseLayoutDump();
+
+    // there are 3 pages
+    assertXPath(pXmlDoc, "/root/page", 3);
+    // table on first page
+    assertXPath(pXmlDoc, "/root/page[1]/body/tab", 1);
+    assertXPath(pXmlDoc, "/root/page[1]/body/txt", 0);
+    // paragraph with large fly on second page
+    assertXPath(pXmlDoc, "/root/page[2]/body/tab", 0);
+    assertXPath(pXmlDoc, "/root/page[2]/body/txt", 1);
+    assertXPath(pXmlDoc, "/root/page[2]/body/txt[1]/anchored/fly", 1);
+    assertXPath(pXmlDoc, "/root/page[2]/body/txt[1]/anchored/fly[1]/infos/bounds", "top", "17915");
+    assertXPath(pXmlDoc, "/root/page[2]/body/txt[1]/anchored/fly[1]/infos/bounds", "height",
+                "15819");
+    // paragraph on third page
+    assertXPath(pXmlDoc, "/root/page[3]/body/tab", 0);
+    assertXPath(pXmlDoc, "/root/page[3]/body/txt", 1);
+    assertXPath(pXmlDoc, "/root/page[3]/body/txt[1]/anchored", 0);
+}
+
 void SwLayoutWriter::testTdf116830()
 {
     SwDoc* pDoc = createDoc("tdf116830.odt");
diff --git a/sw/source/core/layout/tabfrm.cxx b/sw/source/core/layout/tabfrm.cxx
index 8fd3ec659376..5f71f21ea116 100644
--- a/sw/source/core/layout/tabfrm.cxx
+++ b/sw/source/core/layout/tabfrm.cxx
@@ -2687,6 +2687,21 @@ void SwTabFrame::MakeAll(vcl::RenderContext* pRenderContext)
         aNotify.SetInvaKeep();
 }
 
+static bool IsNextOnSamePage(SwPageFrame const& rPage,
+        SwTabFrame const& rTabFrame, SwTextFrame const& rAnchorFrame)
+{
+    for (SwContentFrame const* pContentFrame = rTabFrame.FindNextCnt();
+        pContentFrame && pContentFrame->FindPageFrame() == &rPage;
+        pContentFrame = pContentFrame->FindNextCnt())
+    {
+        if (pContentFrame == &rAnchorFrame)
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
 /// Calculate the offsets arising because of FlyFrames
 bool SwTabFrame::CalcFlyOffsets( SwTwips& rUpper,
                                long& rLeftOffset,
@@ -2786,10 +2801,25 @@ bool SwTabFrame::CalcFlyOffsets( SwTwips& rUpper,
                     const SwFormatHoriOrient &rHori= pFly->GetFormat()->GetHoriOrient();
                     if ( css::text::WrapTextMode_NONE == rSur.GetSurround() )
                     {
+                        // possible cases:
+                        //        both in body
+                        //        both in same fly
+                        //        any comb. of body, footnote, header/footer
+                        // to keep it safe, check only in doc body vs page margin for now
                         long nBottom = aRectFnSet.GetBottom(aFlyRect);
-                        if( aRectFnSet.YDiff( nPrtPos, nBottom ) < 0 )
-                            nPrtPos = nBottom;
-                        bInvalidatePrtArea = true;
+                        // tdf#138039 don't grow beyond the page body
+                        // if the fly is anchored below the table; the fly
+                        // must move with its anchor frame to the next page
+                        SwRectFnSet fnPage(pPage);
+                        if (!IsInDocBody() // TODO
+                            || fnPage.YDiff(fnPage.GetBottom(aFlyRect), fnPage.GetPrtBottom(*pPage)) <= 0
+                            || !IsNextOnSamePage(*pPage, *this,
+                                *static_cast<SwTextFrame*>(pFly->GetAnchorFrameContainingAnchPos())))
+                        {
+                            if (aRectFnSet.YDiff( nPrtPos, nBottom ) < 0)
+                                nPrtPos = nBottom;
+                            bInvalidatePrtArea = true;
+                        }
                     }
                     if ( (css::text::WrapTextMode_RIGHT    == rSur.GetSurround() ||
                           css::text::WrapTextMode_PARALLEL == rSur.GetSurround())&&


More information about the Libreoffice-commits mailing list