[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-6.4' - 4 commits - include/svx svx/source sw/CppunitTest_sw_core_layout.mk sw/Module_sw.mk sw/qa sw/source writerfilter/qa writerfilter/source

Miklos Vajna (via logerrit) logerrit at kemper.freedesktop.org
Thu May 7 08:25:14 UTC 2020


 include/svx/framelink.hxx                                                     |    7 
 svx/source/dialog/framelink.cxx                                               |  117 ++++++++++
 sw/CppunitTest_sw_core_layout.mk                                              |   72 ++++++
 sw/Module_sw.mk                                                               |    1 
 sw/qa/core/layout/data/border-collapse-compat.docx                            |binary
 sw/qa/core/layout/data/table-fly-overlap.docx                                 |binary
 sw/qa/core/layout/layout.cxx                                                  |   68 +++++
 sw/qa/extras/ooxmlexport/ooxmlexport10.cxx                                    |    4 
 sw/qa/extras/ooxmlexport/ooxmlexport13.cxx                                    |    4 
 sw/qa/extras/ooxmlexport/ooxmlexport4.cxx                                     |    4 
 sw/qa/extras/ooxmlexport/ooxmlexport9.cxx                                     |    2 
 sw/source/core/layout/paintfrm.cxx                                            |   12 +
 sw/source/core/layout/tabfrm.cxx                                              |   30 ++
 writerfilter/qa/cppunittests/dmapper/GraphicImport.cxx                        |   34 ++
 writerfilter/qa/cppunittests/dmapper/data/inline-anchored-zorder.docx         |binary
 writerfilter/qa/cppunittests/dmapper/data/inline-inshape-anchored-zorder.docx |binary
 writerfilter/source/dmapper/DomainMapper.cxx                                  |    2 
 writerfilter/source/dmapper/DomainMapper.hxx                                  |    1 
 writerfilter/source/dmapper/GraphicImport.cxx                                 |   12 -
 19 files changed, 357 insertions(+), 13 deletions(-)

New commits:
commit fa77419c66544e050a612baf027a9f927c4fe0a4
Author:     Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Wed Feb 19 18:03:59 2020 +0100
Commit:     Miklos Vajna <vmiklos at collabora.com>
CommitDate: Thu May 7 10:14:24 2020 +0200

    sw table cell borders: add optional Word-compatible border collapsing
    
    We always compared border width and other aspects only after that, Word
    works with border weight according to their implementer notes.
    
    So extend svx::frame::Style to be able to collapse borders using weights
    and opt in for that from sw/ in case a compat mode (which is related to
    tables, off by default and is set by the DOC/DOCX import) is set.
    
    (cherry picked from commit e6fa52c2c371c7adc9c2c2cb18c3a8cf782cfa4b)
    
    Change-Id: I1f682789302c88a0d326c6c0263ad3007441cb24

diff --git a/include/svx/framelink.hxx b/include/svx/framelink.hxx
index 4c662700bec6..ee84176ce9fc 100644
--- a/include/svx/framelink.hxx
+++ b/include/svx/framelink.hxx
@@ -116,6 +116,7 @@ private:
         double              mfSecn;     /// Width of secondary (right or bottom) line.
         double              mfPatternScale; /// Scale used for line pattern spacing.
         SvxBorderLineStyle  mnType;
+        bool mbWordTableCell;
 
     public:
         /** Constructs an invisible frame style. */
@@ -129,7 +130,8 @@ private:
             mfDist(0.0),
             mfSecn(0.0),
             mfPatternScale(1.0),
-            mnType(SvxBorderLineStyle::SOLID)
+            mnType(SvxBorderLineStyle::SOLID),
+            mbWordTableCell(false)
         {}
     };
 
@@ -187,6 +189,9 @@ public:
     /** Mirrors this style (exchanges primary and secondary), if it is a double frame style. */
     Style& MirrorSelf();
 
+    /** Enables the Word-compatible Style comparison code. */
+    void SetWordTableCell(bool bWordTableCell);
+
     bool operator==( const Style& rOther) const;
     bool operator<( const Style& rOther) const;
 };
diff --git a/svx/source/dialog/framelink.cxx b/svx/source/dialog/framelink.cxx
index b4548c6ebed9..c8696b063e0b 100644
--- a/svx/source/dialog/framelink.cxx
+++ b/svx/source/dialog/framelink.cxx
@@ -267,6 +267,16 @@ Style& Style::MirrorSelf()
     return *this;
 }
 
+void Style::SetWordTableCell(bool bWordTableCell)
+{
+    if (!maImplStyle)
+    {
+        implEnsureImplStyle();
+    }
+
+    maImplStyle->mbWordTableCell = bWordTableCell;
+}
+
 bool Style::operator==( const Style& rOther) const
 {
     if(!maImplStyle && !rOther.maImplStyle)
@@ -290,6 +300,101 @@ bool Style::operator==( const Style& rOther) const
         && Type() == rOther.Type());
 }
 
+namespace
+{
+/**
+ * Gets the weight of rStyle, according to [MS-OI29500] v20171130, 2.1.168 Part 1 Section 17.4.66,
+ * tcBorders (Table Cell Borders).
+ */
+double GetWordTableCellBorderWeight(const Style& rStyle)
+{
+    double fWidth = rStyle.GetWidth();
+    int nBorderNumber = 0;
+
+    // See lcl_convertBorderStyleFromToken() in writerfilter/ and ConvertBorderStyleFromWord() in
+    // editeng/, this is the opposite of the combination of those functions.
+    switch (rStyle.Type())
+    {
+        case SvxBorderLineStyle::NONE:
+            return 0.0;
+        case SvxBorderLineStyle::DOTTED:
+        case SvxBorderLineStyle::DASHED:
+            return 1.0;
+        case SvxBorderLineStyle::SOLID:
+            // single = 1
+            // thick = 2
+            // wave = 20
+            nBorderNumber = 1;
+            break;
+        case SvxBorderLineStyle::DOUBLE:
+        case SvxBorderLineStyle::DOUBLE_THIN:
+            // double = 3
+            // triple = 10
+            // doubleWave = 21
+            // dashDotStroked = 23
+            nBorderNumber = 3;
+            break;
+        case SvxBorderLineStyle::DASH_DOT:
+            // dotDash = 8
+            nBorderNumber = 8;
+            break;
+        case SvxBorderLineStyle::DASH_DOT_DOT:
+            // dotDotDash = 9
+            nBorderNumber = 9;
+            break;
+        case SvxBorderLineStyle::THINTHICK_SMALLGAP:
+            // thinThickSmallGap = 11
+            nBorderNumber = 11;
+            break;
+        case SvxBorderLineStyle::THICKTHIN_SMALLGAP:
+            // thickThinSmallGap = 12
+            // thinThickThinSmallGap = 13
+            nBorderNumber = 12;
+            break;
+        case SvxBorderLineStyle::THINTHICK_MEDIUMGAP:
+            // thinThickMediumGap = 14
+            nBorderNumber = 14;
+            break;
+        case SvxBorderLineStyle::THICKTHIN_MEDIUMGAP:
+            // thickThinMediumGap = 15
+            // thinThickThinMediumGap = 16
+            nBorderNumber = 15;
+            break;
+        case SvxBorderLineStyle::THINTHICK_LARGEGAP:
+            // thinThickLargeGap = 17
+            nBorderNumber = 17;
+            break;
+        case SvxBorderLineStyle::THICKTHIN_LARGEGAP:
+            // thickThinLargeGap = 18
+            // thinThickThinLargeGap = 19
+            nBorderNumber = 18;
+            break;
+        case SvxBorderLineStyle::FINE_DASHED:
+            // dashSmallGap = 22
+            nBorderNumber = 22;
+            break;
+        case SvxBorderLineStyle::EMBOSSED:
+            // threeDEmboss = 24
+            nBorderNumber = 24;
+            break;
+        case SvxBorderLineStyle::ENGRAVED:
+            // threeDEngrave = 25
+            nBorderNumber = 25;
+            break;
+        case SvxBorderLineStyle::OUTSET:
+            // outset = 26
+            nBorderNumber = 25;
+            break;
+        case SvxBorderLineStyle::INSET:
+            // inset = 27
+            nBorderNumber = 27;
+            break;
+    }
+
+    return nBorderNumber * fWidth;
+}
+}
+
 bool Style::operator<( const Style& rOther) const
 {
     if(!maImplStyle && !rOther.maImplStyle)
@@ -298,6 +403,18 @@ bool Style::operator<( const Style& rOther) const
         return false;
     }
 
+    if (maImplStyle && maImplStyle->mbWordTableCell)
+    {
+        // The below code would first compare based on the border width, Word compares based on its
+        // calculated weight, do that in the compat case.
+        double fLW = GetWordTableCellBorderWeight(*this);
+        double fRW = GetWordTableCellBorderWeight(rOther);
+        if (!rtl::math::approxEqual(fLW, fRW))
+        {
+            return fLW < fRW;
+        }
+    }
+
     // different total widths -> this<rOther, if this is thinner
     double nLW = GetWidth();
     double nRW = rOther.GetWidth();
diff --git a/sw/qa/core/layout/data/border-collapse-compat.docx b/sw/qa/core/layout/data/border-collapse-compat.docx
new file mode 100644
index 000000000000..a3f29cbe8d1c
Binary files /dev/null and b/sw/qa/core/layout/data/border-collapse-compat.docx differ
diff --git a/sw/qa/core/layout/layout.cxx b/sw/qa/core/layout/layout.cxx
index cbea578be4cc..4c16a3bbcd97 100644
--- a/sw/qa/core/layout/layout.cxx
+++ b/sw/qa/core/layout/layout.cxx
@@ -43,6 +43,26 @@ CPPUNIT_TEST_FIXTURE(SwCoreLayoutTest, testTableFlyOverlap)
     CPPUNIT_ASSERT_GREATEREQUAL(nFlyBottom, nTableTop);
 }
 
+CPPUNIT_TEST_FIXTURE(SwCoreLayoutTest, testBorderCollapseCompat)
+{
+    // Load a document with a border conflict: top cell has a dotted bottom border, bottom cell has
+    // a solid upper border.
+    load(DATA_DIRECTORY, "border-collapse-compat.docx");
+    SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
+    SwDocShell* pShell = pTextDoc->GetDocShell();
+    std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
+    MetafileXmlDump aDumper;
+    xmlDocPtr pXmlDoc = dumpAndParse(aDumper, *xMetaFile);
+
+    // Make sure the solid border has priority.
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: 1
+    // - Actual  : 48
+    // i.e. there was no single cell border with width=20, rather there were 48 border parts
+    // (forming a dotted border), all with width=40.
+    assertXPath(pXmlDoc, "//polyline[@style='solid']", "width", "20");
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/paintfrm.cxx b/sw/source/core/layout/paintfrm.cxx
index 60b25866d073..a53e7b249dba 100644
--- a/sw/source/core/layout/paintfrm.cxx
+++ b/sw/source/core/layout/paintfrm.cxx
@@ -2717,11 +2717,23 @@ void SwTabFramePainter::Insert(const SwFrame& rFrame, const SvxBoxItem& rBoxItem
     bool const bVert = mrTabFrame.IsVertical();
     bool const bR2L  = mrTabFrame.IsRightToLeft();
 
+    bool bWordTableCell = false;
+    SwViewShell* pShell = rFrame.getRootFrame()->GetCurrShell();
+    if (pShell)
+    {
+        const IDocumentSettingAccess& rIDSA = pShell->GetDoc()->getIDocumentSettingAccess();
+        bWordTableCell = rIDSA.get(DocumentSettingId::TABLE_ROW_KEEP);
+    }
+
     // no scaling needed, it's all in the primitives and the target device
     svx::frame::Style aL(rBoxItem.GetLeft(), 1.0);
+    aL.SetWordTableCell(bWordTableCell);
     svx::frame::Style aR(rBoxItem.GetRight(), 1.0);
+    aR.SetWordTableCell(bWordTableCell);
     svx::frame::Style aT(rBoxItem.GetTop(), 1.0);
+    aT.SetWordTableCell(bWordTableCell);
     svx::frame::Style aB(rBoxItem.GetBottom(), 1.0);
+    aB.SetWordTableCell(bWordTableCell);
 
     aR.MirrorSelf();
     aB.MirrorSelf();
commit 50d93ff6ea05bd49d68c34664529ec66262b14b0
Author:     Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Mon Feb 17 14:35:54 2020 +0100
Commit:     Miklos Vajna <vmiklos at collabora.com>
CommitDate: Thu May 7 10:12:53 2020 +0200

    DOCX import: don't touch the ZOrder of inline, in-shape objects
    
    1) This is not needed: Word only supports inline "anchoring" in
    textboxes.
    
    2) If the textbox has a certain ZOrder, we don't want the inline shapes
    to be behind the textbox.
    
    3) This allows restoring the old assert in sw_ooxmlexport7 that was
    changed in commit 99847d6b3005c5444ed5a46ca578c0e40149d77c (DOCX import:
    fix ZOrder of inline vs anchored shapes, 2020-02-12).
    
    (cherry picked from commit 70ae12fe0b9e33633fc62cf805c261ef51fb4b59)
    
    Conflicts:
            sw/qa/extras/ooxmlexport/ooxmlexport7.cxx
    
    Change-Id: I817e4fb70cb789e8eb116219050fc1aeaec76667

diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport7.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport7.cxx
index 860d6927e505..b673c06a3d2a 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport7.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport7.cxx
@@ -586,7 +586,7 @@ DECLARE_OOXMLEXPORT_TEST(fdo76591, "fdo76591.docx")
     xmlDocPtr pXmlDoc = parseExport("word/document.xml");
     if (!pXmlDoc)
         return;
-    assertXPath(pXmlDoc, "/w:document[1]/w:body[1]/w:p[1]/w:r[3]/mc:AlternateContent[1]/mc:Choice[1]/w:drawing[1]/wp:anchor[1]", "relativeHeight", "4");
+    assertXPath(pXmlDoc, "/w:document[1]/w:body[1]/w:p[1]/w:r[3]/mc:AlternateContent[1]/mc:Choice[1]/w:drawing[1]/wp:anchor[1]", "relativeHeight", "3");
 }
 
 DECLARE_OOXMLEXPORT_TEST(test76317_2K10, "test76317_2K10.docx")
diff --git a/writerfilter/qa/cppunittests/dmapper/GraphicImport.cxx b/writerfilter/qa/cppunittests/dmapper/GraphicImport.cxx
index d5140f134cb3..01dd3d6ca602 100644
--- a/writerfilter/qa/cppunittests/dmapper/GraphicImport.cxx
+++ b/writerfilter/qa/cppunittests/dmapper/GraphicImport.cxx
@@ -124,6 +124,23 @@ CPPUNIT_TEST_FIXTURE(Test, testInlineAnchoredZOrder)
     // i.e. the rectangle (with no name) was on top of the oval one, not the other way around.
     CPPUNIT_ASSERT_EQUAL(OUString("Oval 2"), xOval->getName());
 }
+
+CPPUNIT_TEST_FIXTURE(Test, testInlineInShapeAnchoredZOrder)
+{
+    // This document has a textbox shape and then an inline shape inside that.
+    // The ZOrder of the inline shape is larger than the hosting textbox, so the image is visible.
+    OUString aURL
+        = m_directories.getURLFromSrc(DATA_DIRECTORY) + "inline-inshape-anchored-zorder.docx";
+    getComponent() = loadFromDesktop(aURL);
+    uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(getComponent(), uno::UNO_QUERY);
+    uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage();
+    uno::Reference<container::XNamed> xOval(xDrawPage->getByIndex(1), uno::UNO_QUERY);
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: Picture 1
+    // - Actual  : Text Box 2
+    // i.e. the image was behind the textbox that was hosting it.
+    CPPUNIT_ASSERT_EQUAL(OUString("Picture 1"), xOval->getName());
+}
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerfilter/qa/cppunittests/dmapper/data/inline-inshape-anchored-zorder.docx b/writerfilter/qa/cppunittests/dmapper/data/inline-inshape-anchored-zorder.docx
new file mode 100644
index 000000000000..3792285f4849
Binary files /dev/null and b/writerfilter/qa/cppunittests/dmapper/data/inline-inshape-anchored-zorder.docx differ
diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx
index 938cc59be726..97e34afb7926 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -3867,6 +3867,8 @@ bool DomainMapper::IsInHeaderFooter() const
     return m_pImpl->IsInHeaderFooter();
 }
 
+bool DomainMapper::IsInShape() const { return m_pImpl->IsInShape(); }
+
 bool DomainMapper::IsInTable() const
 {
     return m_pImpl->hasTableManager() && m_pImpl->getTableManager().isInCell();
diff --git a/writerfilter/source/dmapper/DomainMapper.hxx b/writerfilter/source/dmapper/DomainMapper.hxx
index 0913dd125814..55f9a20e0373 100644
--- a/writerfilter/source/dmapper/DomainMapper.hxx
+++ b/writerfilter/source/dmapper/DomainMapper.hxx
@@ -112,6 +112,7 @@ public:
     bool IsInHeaderFooter() const;
     bool IsInTable() const;
     bool IsStyleSheetImport() const;
+    bool IsInShape() const;
 
     void hasControls( const bool bSet ) { mbHasControls = bSet; }
 
diff --git a/writerfilter/source/dmapper/GraphicImport.cxx b/writerfilter/source/dmapper/GraphicImport.cxx
index df5f644e34ba..33540be2ff72 100644
--- a/writerfilter/source/dmapper/GraphicImport.cxx
+++ b/writerfilter/source/dmapper/GraphicImport.cxx
@@ -288,7 +288,8 @@ public:
         ,m_rAligns(rAligns)
         ,m_rPositivePercentages(rPositivePercentages)
     {
-        if (eGraphicImportType == GraphicImportType::IMPORT_AS_DETECTED_INLINE)
+        if (eGraphicImportType == GraphicImportType::IMPORT_AS_DETECTED_INLINE
+            && !rDMapper.IsInShape())
         {
             zOrder = 0;
         }
commit 506ef593207a4ce7a463df4a7f4600b542c5cdda
Author:     Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Fri Feb 14 16:29:44 2020 +0100
Commit:     Miklos Vajna <vmiklos at collabora.com>
CommitDate: Thu May 7 10:10:55 2020 +0200

    sw: fix handling of table vs fly overlaps in the AddVerticalFlyOffsets case
    
    When a table overlaps with a fly frame, Writer creates a fly portion
    inside the relevant cell frame (increasing its height), and Word shifts
    the table down. Both are valid approaches, but the rendering result is
    different in case the table has a border.
    
    So keep the default unchanged, but in case the AddVerticalFlyOffsets
    compat flag (set by the Word importers) is set, avoid the overlap the
    Word way.
    
    Note that the table frame uses the full width (available in the body)
    even for e.g. 50% width tables, so check for the overlap using the print
    area, which does not always overlap.
    
    Finally, don't always require a valid frame area definition from the fly
    frame:
    
    - the mentioned i#46807 bugdoc currently doesn't need that check
    
    - the fly frame area definition becomes valid only after already
      positioning the table, leading to an overlap
    
    Keep that check for the non-compat case, though.
    
    (cherry picked from commit fd7749fddc5a767461dfced55369af48e5a6d561)
    
    Conflicts:
            sw/Module_sw.mk
    
    Change-Id: I9202050befebf2efdbb5395ded6fcb52b378d8e7

diff --git a/sw/CppunitTest_sw_core_layout.mk b/sw/CppunitTest_sw_core_layout.mk
new file mode 100644
index 000000000000..1801e66a713d
--- /dev/null
+++ b/sw/CppunitTest_sw_core_layout.mk
@@ -0,0 +1,72 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#*************************************************************************
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+#*************************************************************************
+
+$(eval $(call gb_CppunitTest_CppunitTest,sw_core_layout))
+
+$(eval $(call gb_CppunitTest_use_common_precompiled_header,sw_core_layout))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,sw_core_layout, \
+    sw/qa/core/layout/layout \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,sw_core_layout, \
+    comphelper \
+    cppu \
+    cppuhelper \
+    sal \
+    sfx \
+    sw \
+    test \
+    unotest \
+    utl \
+    vcl \
+    svt \
+    tl \
+    svl \
+))
+
+$(eval $(call gb_CppunitTest_use_externals,sw_core_layout,\
+    boost_headers \
+    libxml2 \
+))
+
+$(eval $(call gb_CppunitTest_set_include,sw_core_layout,\
+    -I$(SRCDIR)/sw/inc \
+    -I$(SRCDIR)/sw/source/core/inc \
+    -I$(SRCDIR)/sw/source/uibase/inc \
+    -I$(SRCDIR)/sw/qa/inc \
+    $$(INCLUDE) \
+))
+
+$(eval $(call gb_CppunitTest_use_api,sw_core_layout,\
+	udkapi \
+	offapi \
+	oovbaapi \
+))
+
+$(eval $(call gb_CppunitTest_use_ure,sw_core_layout))
+$(eval $(call gb_CppunitTest_use_vcl,sw_core_layout))
+
+$(eval $(call gb_CppunitTest_use_rdb,sw_core_layout,services))
+
+$(eval $(call gb_CppunitTest_use_custom_headers,sw_core_layout,\
+    officecfg/registry \
+))
+
+$(eval $(call gb_CppunitTest_use_configuration,sw_core_layout))
+
+$(eval $(call gb_CppunitTest_use_uiconfigs,sw_core_layout, \
+    modules/swriter \
+))
+
+$(eval $(call gb_CppunitTest_use_more_fonts,sw_core_layout))
+
+# vim: set noet sw=4 ts=4:
diff --git a/sw/Module_sw.mk b/sw/Module_sw.mk
index dc4f303d7a3b..ae5459d8bf89 100644
--- a/sw/Module_sw.mk
+++ b/sw/Module_sw.mk
@@ -110,6 +110,7 @@ $(eval $(call gb_Module_add_slowcheck_targets,sw,\
     CppunitTest_sw_core_frmedt \
     CppunitTest_sw_core_txtnode \
     CppunitTest_sw_core_objectpositioning \
+    CppunitTest_sw_core_layout \
 ))
 
 ifneq ($(DISABLE_GUI),TRUE)
diff --git a/sw/qa/core/layout/data/table-fly-overlap.docx b/sw/qa/core/layout/data/table-fly-overlap.docx
new file mode 100644
index 000000000000..a819e855b2eb
Binary files /dev/null and b/sw/qa/core/layout/data/table-fly-overlap.docx differ
diff --git a/sw/qa/core/layout/layout.cxx b/sw/qa/core/layout/layout.cxx
new file mode 100644
index 000000000000..cbea578be4cc
--- /dev/null
+++ b/sw/qa/core/layout/layout.cxx
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <swmodeltestbase.hxx>
+
+#include <vcl/gdimtf.hxx>
+#include <comphelper/classids.hxx>
+#include <tools/globname.hxx>
+#include <svtools/embedhlp.hxx>
+
+#include <wrtsh.hxx>
+#include <fmtanchr.hxx>
+
+static char const DATA_DIRECTORY[] = "/sw/qa/core/layout/data/";
+
+/// Covers sw/source/core/layout/ fixes.
+class SwCoreLayoutTest : public SwModelTestBase
+{
+};
+
+CPPUNIT_TEST_FIXTURE(SwCoreLayoutTest, testTableFlyOverlap)
+{
+    // Load a document that has an image anchored in the header.
+    // It also has a table which has the wrap around the image.
+    load(DATA_DIRECTORY, "table-fly-overlap.docx");
+    SwTwips nFlyTop = parseDump("//header/txt/anchored/fly/infos/bounds", "top").toInt32();
+    SwTwips nFlyHeight = parseDump("//header/txt/anchored/fly/infos/bounds", "height").toInt32();
+    SwTwips nFlyBottom = nFlyTop + nFlyHeight;
+    SwTwips nTableFrameTop = parseDump("//tab/infos/bounds", "top").toInt32();
+    SwTwips nTablePrintTop = parseDump("//tab/infos/prtBounds", "top").toInt32();
+    SwTwips nTableTop = nTableFrameTop + nTablePrintTop;
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected greater or equal than: 3579
+    // - Actual  : 2210
+    // i.e. the table's top border overlapped with the image, even if the image's wrap mode was set
+    // to parallel.
+    CPPUNIT_ASSERT_GREATEREQUAL(nFlyBottom, nTableTop);
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/tabfrm.cxx b/sw/source/core/layout/tabfrm.cxx
index 42150626aa10..1674ed1a08ba 100644
--- a/sw/source/core/layout/tabfrm.cxx
+++ b/sw/source/core/layout/tabfrm.cxx
@@ -35,6 +35,7 @@
 #include <editeng/ulspitem.hxx>
 #include <editeng/brushitem.hxx>
 #include <editeng/boxitem.hxx>
+#include <basegfx/range/b1drange.hxx>
 #include <fmtlsplt.hxx>
 #include <fmtrowsplt.hxx>
 #include <fmtsrnd.hxx>
@@ -2695,6 +2696,9 @@ bool SwTabFrame::CalcFlyOffsets( SwTwips& rUpper,
         long nYDiff = aRectFnSet.YDiff( aRectFnSet.GetTop(getFramePrintArea()), rUpper );
         if( nYDiff > 0 )
             aRectFnSet.AddBottom( aRect, -nYDiff );
+
+        bool bAddVerticalFlyOffsets = rIDSA.get(DocumentSettingId::ADD_VERTICAL_FLY_OFFSETS);
+
         for ( size_t i = 0; i < pPage->GetSortedObjs()->size(); ++i )
         {
             SwAnchoredObject* pAnchoredObj = (*pPage->GetSortedObjs())[i];
@@ -2722,7 +2726,7 @@ bool SwTabFrame::CalcFlyOffsets( SwTwips& rUpper,
                 bool bConsiderFly =
                     // #i46807# - do not consider invalid
                     // Writer fly frames.
-                    pFly->isFrameAreaDefinitionValid() &&
+                    (pFly->isFrameAreaDefinitionValid() || bAddVerticalFlyOffsets) &&
                     // fly anchored at character
                     pFly->IsFlyAtContentFrame() &&
                     // fly overlaps with corresponding table rectangle
@@ -2766,7 +2770,29 @@ bool SwTabFrame::CalcFlyOffsets( SwTwips& rUpper,
                 {
                     const SwFormatSurround   &rSur = pFly->GetFormat()->GetSurround();
                     const SwFormatHoriOrient &rHori= pFly->GetFormat()->GetHoriOrient();
-                    if ( css::text::WrapTextMode_NONE == rSur.GetSurround() )
+                    bool bShiftDown = css::text::WrapTextMode_NONE == rSur.GetSurround();
+                    if (!bShiftDown && bAddVerticalFlyOffsets)
+                    {
+                        if (rSur.GetSurround() == text::WrapTextMode_PARALLEL
+                            && rHori.GetHoriOrient() == text::HoriOrientation::NONE)
+                        {
+                            // We know that wrapping was requested and the table frame overlaps with
+                            // the fly frame. Check if the print area overlaps with the fly frame as
+                            // well (in case the table does not use all the available width).
+                            basegfx::B1DRange aTabRange(
+                                aRectFnSet.GetLeft(aRect) + aRectFnSet.GetLeft(getFramePrintArea()),
+                                aRectFnSet.GetLeft(aRect) + aRectFnSet.GetLeft(getFramePrintArea())
+                                    + aRectFnSet.GetWidth(getFramePrintArea()));
+                            basegfx::B1DRange aFlyRange(aRectFnSet.GetLeft(aFlyRect),
+                                                        aRectFnSet.GetRight(aFlyRect));
+                            // If it does, shift the table down. Do this only in the compat case,
+                            // normally an SwFlyPortion is created instead that increases the height
+                            // of the first table row.
+                            bShiftDown = aTabRange.overlaps(aFlyRange);
+                        }
+                    }
+
+                    if (bShiftDown)
                     {
                         long nBottom = aRectFnSet.GetBottom(aFlyRect);
                         if( aRectFnSet.YDiff( nPrtPos, nBottom ) < 0 )
commit 32750c8a1121177ea48d3e7b237a9ddc834fde38
Author:     Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Wed Feb 12 15:02:18 2020 +0100
Commit:     Miklos Vajna <vmiklos at collabora.com>
CommitDate: Thu May 7 09:38:21 2020 +0200

    DOCX import: fix ZOrder of inline vs anchored shapes
    
    Shapes which are anchored but are not in the background should be always
    on top of as-char anchored shapes in OOXML terms. Writer supports a
    custom ZOrder even for as-char shapes, so make sure that they are
    always behind anchored shapes.
    
    To avoid unnecessary work, make sure that when there are multiple inline
    shapes, we don't pointlessly reorder them (the old vs new style of the
    sorting controls exactly this, what happens when two shapes have the
    same ZOrder, and all inline shapes have a 0 ZOrder).
    
    Adapt a few tests that used ZOrder indexes to access shapes, but the
    intention was to just refer to a shape: fix the index and migrate to
    shape names where possible.
    
    (cherry picked from commit 99847d6b3005c5444ed5a46ca578c0e40149d77c)
    
    Conflicts:
            sw/qa/extras/ooxmlexport/ooxmlexport7.cxx
            writerfilter/qa/cppunittests/dmapper/GraphicImport.cxx
    
    Change-Id: I670e4dc2acbd2a0c6d47fe964cb5e3f2300e6848

diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport10.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport10.cxx
index 92d7d63aa80d..9b086540f9dd 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport10.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport10.cxx
@@ -487,11 +487,11 @@ DECLARE_OOXMLEXPORT_TEST(testStrict, "strict.docx")
     getParagraphOfText(1, xHeaderText, "This is a header.");
 
     // Picture was missing.
-    uno::Reference<lang::XServiceInfo> xServiceInfo(getShape(1), uno::UNO_QUERY);
+    uno::Reference<lang::XServiceInfo> xServiceInfo(getShapeByName("Picture 2"), uno::UNO_QUERY);
     CPPUNIT_ASSERT(xServiceInfo->supportsService("com.sun.star.text.TextGraphicObject"));
 
     // SmartArt was missing.
-    xServiceInfo.set(getShape(2), uno::UNO_QUERY);
+    xServiceInfo.set(getShape(1), uno::UNO_QUERY);
     CPPUNIT_ASSERT(xServiceInfo->supportsService("com.sun.star.drawing.GroupShape"));
 
     // Chart was missing.
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx
index e586a666dff4..d2765488b797 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx
@@ -556,10 +556,10 @@ DECLARE_OOXMLEXPORT_TEST(testTdf119201, "tdf119201.docx")
     auto xShape(getShape(1));
     CPPUNIT_ASSERT_MESSAGE("First shape should be visible.", getProperty<bool>(xShape, "Visible"));
     CPPUNIT_ASSERT_MESSAGE("First shape should be printable.", getProperty<bool>(xShape, "Printable"));
-    xShape = getShape(2);
+    xShape = getShapeByName("Rectangle 1");
     CPPUNIT_ASSERT_MESSAGE("Second shape should not be visible.", !getProperty<bool>(xShape, "Visible"));
     CPPUNIT_ASSERT_MESSAGE("Second shape should not be printable.", !getProperty<bool>(xShape, "Printable"));
-    xShape = getShape(3);
+    xShape = getShapeByName("Oval 2");
     CPPUNIT_ASSERT_MESSAGE("Third shape should be visible.", getProperty<bool>(xShape, "Visible"));
     CPPUNIT_ASSERT_MESSAGE("Third shape should be printable.", getProperty<bool>(xShape, "Printable"));
 }
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport4.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport4.cxx
index a7a1336dd480..f9c5997a42b1 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport4.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport4.cxx
@@ -1084,9 +1084,7 @@ DECLARE_OOXMLEXPORT_TEST(testTdf102466, "tdf102466.docx")
 
     // check content of the first page
     {
-        uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(mxComponent, uno::UNO_QUERY);
-        uno::Reference<container::XIndexAccess> xIndexAccess = xDrawPageSupplier->getDrawPage();
-        uno::Reference<beans::XPropertySet> xFrame(xIndexAccess->getByIndex(0), uno::UNO_QUERY);
+        uno::Reference<beans::XPropertySet> xFrame(getShapeByName("Marco1"), uno::UNO_QUERY);
 
         // no border
         CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(xFrame, "LineWidth"));
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport7.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport7.cxx
index b673c06a3d2a..860d6927e505 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport7.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport7.cxx
@@ -586,7 +586,7 @@ DECLARE_OOXMLEXPORT_TEST(fdo76591, "fdo76591.docx")
     xmlDocPtr pXmlDoc = parseExport("word/document.xml");
     if (!pXmlDoc)
         return;
-    assertXPath(pXmlDoc, "/w:document[1]/w:body[1]/w:p[1]/w:r[3]/mc:AlternateContent[1]/mc:Choice[1]/w:drawing[1]/wp:anchor[1]", "relativeHeight", "3");
+    assertXPath(pXmlDoc, "/w:document[1]/w:body[1]/w:p[1]/w:r[3]/mc:AlternateContent[1]/mc:Choice[1]/w:drawing[1]/wp:anchor[1]", "relativeHeight", "4");
 }
 
 DECLARE_OOXMLEXPORT_TEST(test76317_2K10, "test76317_2K10.docx")
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx
index ece282f437aa..f9959d21886a 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx
@@ -569,7 +569,7 @@ DECLARE_OOXMLEXPORT_TEST(testTdf103573, "tdf103573.docx")
 
 DECLARE_OOXMLEXPORT_TEST(testTdf106132, "tdf106132.docx")
 {
-    uno::Reference<beans::XPropertySet> xShape(getShape(1), uno::UNO_QUERY);
+    uno::Reference<beans::XPropertySet> xShape(getShapeByName("Frame1"), uno::UNO_QUERY);
     // This was 250, <wps:bodyPr ... rIns="0" ...> was ignored for an outer shape.
     CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), getProperty<sal_Int32>(xShape, "TextRightDistance"));
 }
diff --git a/writerfilter/qa/cppunittests/dmapper/GraphicImport.cxx b/writerfilter/qa/cppunittests/dmapper/GraphicImport.cxx
index f20694b828cc..d5140f134cb3 100644
--- a/writerfilter/qa/cppunittests/dmapper/GraphicImport.cxx
+++ b/writerfilter/qa/cppunittests/dmapper/GraphicImport.cxx
@@ -17,6 +17,7 @@
 #include <com/sun/star/text/XTextTable.hpp>
 #include <com/sun/star/text/XTextTablesSupplier.hpp>
 #include <com/sun/star/text/RelOrientation.hpp>
+#include <com/sun/star/container/XNamed.hpp>
 
 #include <comphelper/processfactory.hxx>
 
@@ -107,6 +108,22 @@ CPPUNIT_TEST_FIXTURE(Test, testDrawShapeInlineEffect)
     // i.e. the layout result had less pages than expected (compared to Word).
     CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(273), nBottomMargin);
 }
+
+CPPUNIT_TEST_FIXTURE(Test, testInlineAnchoredZOrder)
+{
+    // Load a document which has two shapes: an inline one and an anchored one. The inline has no
+    // explicit ZOrder, the anchored one has, and it's set to a value so it's visible.
+    OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "inline-anchored-zorder.docx";
+    getComponent() = loadFromDesktop(aURL);
+    uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(getComponent(), uno::UNO_QUERY);
+    uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage();
+    uno::Reference<container::XNamed> xOval(xDrawPage->getByIndex(1), uno::UNO_QUERY);
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: Oval 2
+    // - Actual  :
+    // i.e. the rectangle (with no name) was on top of the oval one, not the other way around.
+    CPPUNIT_ASSERT_EQUAL(OUString("Oval 2"), xOval->getName());
+}
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerfilter/qa/cppunittests/dmapper/data/inline-anchored-zorder.docx b/writerfilter/qa/cppunittests/dmapper/data/inline-anchored-zorder.docx
new file mode 100644
index 000000000000..93932c4703b7
Binary files /dev/null and b/writerfilter/qa/cppunittests/dmapper/data/inline-anchored-zorder.docx differ
diff --git a/writerfilter/source/dmapper/GraphicImport.cxx b/writerfilter/source/dmapper/GraphicImport.cxx
index b69f4565fb13..df5f644e34ba 100644
--- a/writerfilter/source/dmapper/GraphicImport.cxx
+++ b/writerfilter/source/dmapper/GraphicImport.cxx
@@ -287,7 +287,12 @@ public:
         ,m_rPositionOffsets(rPositionOffsets)
         ,m_rAligns(rAligns)
         ,m_rPositivePercentages(rPositivePercentages)
-    {}
+    {
+        if (eGraphicImportType == GraphicImportType::IMPORT_AS_DETECTED_INLINE)
+        {
+            zOrder = 0;
+        }
+    }
 
     void setXSize(sal_Int32 _nXSize)
     {
@@ -358,7 +363,8 @@ public:
         if (zOrder >= 0)
         {
             GraphicZOrderHelper* pZOrderHelper = rDomainMapper.graphicZOrderHelper();
-            xGraphicObjectProperties->setPropertyValue(getPropertyName(PROP_Z_ORDER), uno::makeAny(pZOrderHelper->findZOrder(zOrder)));
+            bool bOldStyle = eGraphicImportType == GraphicImportType::IMPORT_AS_DETECTED_INLINE;
+            xGraphicObjectProperties->setPropertyValue(getPropertyName(PROP_Z_ORDER), uno::makeAny(pZOrderHelper->findZOrder(zOrder, bOldStyle)));
             pZOrderHelper->addItem(xGraphicObjectProperties, zOrder);
         }
     }
@@ -898,6 +904,7 @@ void GraphicImport::lcl_attribute(Id nName, Value& rValue)
                     {
                         uno::Reference< beans::XPropertySet > xShapeProps(m_xShape, uno::UNO_QUERY_THROW);
                         m_pImpl->applyMargins(xShapeProps);
+                        m_pImpl->applyZOrder(xShapeProps);
                         comphelper::SequenceAsHashMap aInteropGrabBag(xShapeProps->getPropertyValue("InteropGrabBag"));
                         aInteropGrabBag.update(m_pImpl->getInteropGrabBag());
                         xShapeProps->setPropertyValue("InteropGrabBag", uno::makeAny(aInteropGrabBag.getAsConstPropertyValueList()));


More information about the Libreoffice-commits mailing list