[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-6.2' - include/svx svx/source sw/qa sw/source

Miklos Vajna (via logerrit) logerrit at kemper.freedesktop.org
Thu Feb 20 10:28:03 UTC 2020


 include/svx/framelink.hxx                          |    7 +
 svx/source/dialog/framelink.cxx                    |  117 +++++++++++++++++++++
 sw/qa/core/layout/data/border-collapse-compat.docx |binary
 sw/qa/core/layout/layout.cxx                       |   21 +++
 sw/source/core/layout/paintfrm.cxx                 |   12 ++
 5 files changed, 156 insertions(+), 1 deletion(-)

New commits:
commit 37bf72bac52ba98a29c1d29f3fe9e667c4222d06
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 Feb 20 11:27:32 2020 +0100

    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.
    
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/89052
    Reviewed-by: Miklos Vajna <vmiklos at collabora.com>
    Tested-by: Jenkins
    (cherry picked from commit e6fa52c2c371c7adc9c2c2cb18c3a8cf782cfa4b)
    
    Change-Id: I1f682789302c88a0d326c6c0263ad3007441cb24
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/89078
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
    Reviewed-by: Miklos Vajna <vmiklos at collabora.com>

diff --git a/include/svx/framelink.hxx b/include/svx/framelink.hxx
index fa629fc24ad2..cab0b59e371d 100644
--- a/include/svx/framelink.hxx
+++ b/include/svx/framelink.hxx
@@ -123,6 +123,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. */
@@ -136,7 +137,8 @@ private:
             mfDist(0.0),
             mfSecn(0.0),
             mfPatternScale(1.0),
-            mnType(SvxBorderLineStyle::SOLID)
+            mnType(SvxBorderLineStyle::SOLID),
+            mbWordTableCell(false)
         {}
     };
 
@@ -194,6 +196,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..9c19cbbfd2f9 100644
--- a/sw/qa/core/layout/layout.cxx
+++ b/sw/qa/core/layout/layout.cxx
@@ -13,6 +13,7 @@
 #include <comphelper/classids.hxx>
 #include <tools/globname.hxx>
 #include <svtools/embedhlp.hxx>
+#include <test/mtfxmldump.hxx>
 
 #include <wrtsh.hxx>
 #include <fmtanchr.hxx>
@@ -43,6 +44,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 = aDumper.dumpAndParse(*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 480cf8ea8613..b149802db1ba 100644
--- a/sw/source/core/layout/paintfrm.cxx
+++ b/sw/source/core/layout/paintfrm.cxx
@@ -2709,11 +2709,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();


More information about the Libreoffice-commits mailing list