sw/qa/extras/ooxmlexport/data/tdf139948.docx      |binary
 sw/qa/extras/ooxmlexport/ooxmlexport17.cxx        |   26 +++++++++++++++++
 sw/qa/extras/rtfexport/data/tdf139948.rtf         |    8 +++++
 sw/qa/extras/rtfexport/rtfexport4.cxx             |   32 ++++++++++++++++++++++
 writerfilter/source/dmapper/DomainMapper.cxx      |   11 ++++++-
 writerfilter/source/dmapper/DomainMapper_Impl.cxx |   25 +++++++++++++++++
 writerfilter/source/dmapper/DomainMapper_Impl.hxx |    3 ++
 writerfilter/source/dmapper/PropertyIds.cxx       |    1 
 writerfilter/source/dmapper/PropertyIds.hxx       |    1 
 writerfilter/source/rtftok/rtfdispatchflag.cxx    |    4 ++
 writerfilter/source/rtftok/rtfdocumentimpl.cxx    |    5 ++-
 11 files changed, 113 insertions(+), 3 deletions(-)

New commits:
commit 537b2616b9c8639b2f1108047f39693ac6bd5500
Author:     Vasily Melenchuk <vasily.melenc...@cib.de>
AuthorDate: Fri Apr 1 16:35:40 2022 +0300
Commit:     Xisco Fauli <xiscofa...@libreoffice.org>
CommitDate: Tue Apr 26 14:20:42 2022 +0200

    tdf#139948: docx and rtf import: emulate border in between
    
    Writer does not support border in between available in all MS
    formats. Since this feature is missing in core it will be
    better to emulate it with top borders than to ignore it
    completely.
    
    Change-Id: I4e5a99cde5908066c4bb483136cfe9a1316df53c
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132429
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    (cherry picked from commit e3a996bf72a16f5b22e6ff021745af5cec70a632)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132594
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>

diff --git a/sw/qa/extras/ooxmlexport/data/tdf139948.docx 
b/sw/qa/extras/ooxmlexport/data/tdf139948.docx
new file mode 100644
index 000000000000..1b3f7df00031
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/tdf139948.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx 
b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx
index c0b693247828..41c188a3532e 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx
@@ -260,6 +260,32 @@ DECLARE_OOXMLEXPORT_TEST(testTdf81507, "tdf81507.docx")
     xmlXPathFreeObject(pXmlObj);
 }
 
+DECLARE_OOXMLEXPORT_TEST(testTdf139948, "tdf139948.docx")
+{
+    CPPUNIT_ASSERT_EQUAL(sal_uInt32(0),
+        getProperty<table::BorderLine2>(getParagraph(1, "No border"), 
"TopBorder").LineWidth);
+    CPPUNIT_ASSERT_EQUAL(sal_uInt32(0),
+        getProperty<table::BorderLine2>(getParagraph(2, "Border below"), 
"TopBorder").LineWidth);
+    CPPUNIT_ASSERT_EQUAL(sal_uInt32(88),
+        getProperty<table::BorderLine2>(getParagraph(3, "Borders below and 
above"), "TopBorder").LineWidth);
+    CPPUNIT_ASSERT_EQUAL(sal_uInt32(88),
+        getProperty<table::BorderLine2>(getParagraph(4, "Border above"), 
"TopBorder").LineWidth);
+    CPPUNIT_ASSERT_EQUAL(sal_uInt32(0),
+        getProperty<table::BorderLine2>(getParagraph(5, "No border"), 
"TopBorder").LineWidth);
+
+
+    CPPUNIT_ASSERT_EQUAL(sal_uInt32(0),
+        getProperty<table::BorderLine2>(getParagraph(1), 
"BottomBorder").LineWidth);
+    CPPUNIT_ASSERT_EQUAL(sal_uInt32(0),
+        getProperty<table::BorderLine2>(getParagraph(2), 
"BottomBorder").LineWidth);
+    CPPUNIT_ASSERT_EQUAL(sal_uInt32(0),
+        getProperty<table::BorderLine2>(getParagraph(3), 
"BottomBorder").LineWidth);
+    CPPUNIT_ASSERT_EQUAL(sal_uInt32(0),
+        getProperty<table::BorderLine2>(getParagraph(4), 
"BottomBorder").LineWidth);
+    CPPUNIT_ASSERT_EQUAL(sal_uInt32(0),
+        getProperty<table::BorderLine2>(getParagraph(5), 
"BottomBorder").LineWidth);
+}
+
 DECLARE_OOXMLEXPORT_TEST(testTdf144563, "tdf144563.docx")
 {
     uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, 
uno::UNO_QUERY);
diff --git a/sw/qa/extras/rtfexport/data/tdf139948.rtf 
b/sw/qa/extras/rtfexport/data/tdf139948.rtf
new file mode 100644
index 000000000000..0b601a764adf
--- /dev/null
+++ b/sw/qa/extras/rtfexport/data/tdf139948.rtf
@@ -0,0 +1,8 @@
+{\rtf1\ansi
+No border\par
+\pard\brdrbtw\brdrs\brdrw50 
+Border below\par
+Borders below and above\par
+Border above\par
+\pard No border\par
+}
\ No newline at end of file
diff --git a/sw/qa/extras/rtfexport/rtfexport4.cxx 
b/sw/qa/extras/rtfexport/rtfexport4.cxx
index 33a2a246a181..31469fc0ef02 100644
--- a/sw/qa/extras/rtfexport/rtfexport4.cxx
+++ b/sw/qa/extras/rtfexport/rtfexport4.cxx
@@ -570,6 +570,38 @@ DECLARE_RTFEXPORT_TEST(testTdf111851, "tdf111851.rtf")
     CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(xCell6, 
"BackColor"));
 }
 
+DECLARE_RTFEXPORT_TEST(testTdf139948, "tdf139948.rtf")
+{
+    CPPUNIT_ASSERT_EQUAL(
+        sal_uInt32(0),
+        getProperty<table::BorderLine2>(getParagraph(1, "No border"), 
"TopBorder").LineWidth);
+    CPPUNIT_ASSERT_EQUAL(
+        sal_uInt32(0),
+        getProperty<table::BorderLine2>(getParagraph(2, "Border below"), 
"TopBorder").LineWidth);
+    CPPUNIT_ASSERT_EQUAL(
+        sal_uInt32(88),
+        getProperty<table::BorderLine2>(getParagraph(3, "Borders below and 
above"), "TopBorder")
+            .LineWidth);
+    CPPUNIT_ASSERT_EQUAL(
+        sal_uInt32(88),
+        getProperty<table::BorderLine2>(getParagraph(4, "Border above"), 
"TopBorder").LineWidth);
+    CPPUNIT_ASSERT_EQUAL(
+        sal_uInt32(0),
+        getProperty<table::BorderLine2>(getParagraph(5, "No border"), 
"TopBorder").LineWidth);
+
+    // And let's ensure that there are no other horizontal borders
+    CPPUNIT_ASSERT_EQUAL(
+        sal_uInt32(0), getProperty<table::BorderLine2>(getParagraph(1), 
"BottomBorder").LineWidth);
+    CPPUNIT_ASSERT_EQUAL(
+        sal_uInt32(0), getProperty<table::BorderLine2>(getParagraph(2), 
"BottomBorder").LineWidth);
+    CPPUNIT_ASSERT_EQUAL(
+        sal_uInt32(0), getProperty<table::BorderLine2>(getParagraph(3), 
"BottomBorder").LineWidth);
+    CPPUNIT_ASSERT_EQUAL(
+        sal_uInt32(0), getProperty<table::BorderLine2>(getParagraph(4), 
"BottomBorder").LineWidth);
+    CPPUNIT_ASSERT_EQUAL(
+        sal_uInt32(0), getProperty<table::BorderLine2>(getParagraph(5), 
"BottomBorder").LineWidth);
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerfilter/source/dmapper/DomainMapper.cxx 
b/writerfilter/source/dmapper/DomainMapper.cxx
index 691e876d4859..7a4e47f812fe 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -1470,7 +1470,16 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const 
PropertyMapPtr& rContext )
                 eBorderDistId = PROP_RIGHT_BORDER_DISTANCE ;
                 break;
             case NS_ooxml::LN_CT_PBdr_between:
-                //not supported
+                if (m_pImpl->handlePreviousParagraphBorderInBetween())
+                {
+                    // If previous paragraph also had border in between 
property
+                    // then it is possible to emulate this border as top border
+                    // for current paragraph
+                    eBorderId = PROP_TOP_BORDER;
+                    eBorderDistId = PROP_TOP_BORDER_DISTANCE;
+                }
+                // Since there are borders in between, each paragraph will 
have own borders. No more joining
+                rContext->Insert(PROP_PARA_CONNECT_BORDERS, 
uno::makeAny(false));
                 break;
             default:;
             }
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx 
b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 7eb9964e36a4..8cd6f94e5b4c 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -8294,6 +8294,31 @@ void DomainMapper_Impl::commentProps(const OUString& 
sId, const CommentPropertie
     m_aCommentProps[sId] = rProps;
 }
 
+
+bool DomainMapper_Impl::handlePreviousParagraphBorderInBetween() const
+{
+    if (!m_xPreviousParagraph.is())
+        return false;
+
+    // Connected borders ("ParaIsConnectBorder") are always on by default
+    // and never changed by DomainMapper. Except one case when border in
+    // between is used. So this is not the best, but easiest way to check
+    // is previous paragraph has border in between.
+    bool bConnectBorders = true;
+    
m_xPreviousParagraph->getPropertyValue(getPropertyName(PROP_PARA_CONNECT_BORDERS))
 >>= bConnectBorders;
+
+    if (bConnectBorders)
+        return false;
+
+    // Previous paragraph has border in between. Current one also has (since 
this
+    // method is called). So current paragraph will get border above, but
+    // also need to ensure, that no unexpected bottom border are remaining in 
previous
+    // paragraph: since ParaIsConnectBorder=false it will be displayed in 
unexpected way.
+    
m_xPreviousParagraph->setPropertyValue(getPropertyName(PROP_BOTTOM_BORDER), 
uno::makeAny(table::BorderLine2()));
+
+    return true;
+}
+
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx 
b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
index bb37c556ebc6..5140436cabc2 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
@@ -1144,6 +1144,9 @@ public:
     /// start/end node.
     void ClearPreviousParagraph();
 
+    /// Check if previous paragraph has borders in between and do the border 
magic to it if so
+    bool handlePreviousParagraphBorderInBetween() const;
+
     /// Handle redline text portions in a frame, footnotes and redlines:
     /// store their data, and create them after frame creation or 
footnote/endnote copying
     bool m_bIsActualParagraphFramed;
diff --git a/writerfilter/source/dmapper/PropertyIds.cxx 
b/writerfilter/source/dmapper/PropertyIds.cxx
index b339a83f8ae6..1189bc0b1410 100644
--- a/writerfilter/source/dmapper/PropertyIds.cxx
+++ b/writerfilter/source/dmapper/PropertyIds.cxx
@@ -364,6 +364,7 @@ OUString getPropertyName( PropertyIds eId )
             sName = "RtlGutter";
             break;
         case PROP_CURSOR_NOT_IGNORE_TABLES_IN_HF: sName = 
"CursorNotIgnoreTables"; break;
+        case PROP_PARA_CONNECT_BORDERS: sName= "ParaIsConnectBorder"; break;
     }
     assert(sName.getLength()>0);
     return sName;
diff --git a/writerfilter/source/dmapper/PropertyIds.hxx 
b/writerfilter/source/dmapper/PropertyIds.hxx
index b09170d2da36..7b6fe9a05275 100644
--- a/writerfilter/source/dmapper/PropertyIds.hxx
+++ b/writerfilter/source/dmapper/PropertyIds.hxx
@@ -361,6 +361,7 @@ enum PropertyIds
         ,PROP_GUTTER_MARGIN
         ,PROP_RTL_GUTTER
         ,PROP_CURSOR_NOT_IGNORE_TABLES_IN_HF
+        ,PROP_PARA_CONNECT_BORDERS
     };
 
 //Returns the UNO string equivalent to eId.
diff --git a/writerfilter/source/rtftok/rtfdispatchflag.cxx 
b/writerfilter/source/rtftok/rtfdispatchflag.cxx
index 3aee1e1dda75..9d891384360c 100644
--- a/writerfilter/source/rtftok/rtfdispatchflag.cxx
+++ b/writerfilter/source/rtftok/rtfdispatchflag.cxx
@@ -672,6 +672,7 @@ RTFError RTFDocumentImpl::dispatchFlag(RTFKeyword nKeyword)
         case RTFKeyword::BRDRL:
         case RTFKeyword::BRDRB:
         case RTFKeyword::BRDRR:
+        case RTFKeyword::BRDRBTW:
         {
             RTFSprms aAttributes;
             RTFSprms aSprms;
@@ -690,6 +691,9 @@ RTFError RTFDocumentImpl::dispatchFlag(RTFKeyword nKeyword)
                 case RTFKeyword::BRDRR:
                     nParam = getParagraphBorder(3);
                     break;
+                case RTFKeyword::BRDRBTW:
+                    nParam = getParagraphBorder(4);
+                    break;
                 default:
                     break;
             }
diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.cxx 
b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
index 9e77cbf4602e..0aa22aa96f55 100644
--- a/writerfilter/source/rtftok/rtfdocumentimpl.cxx
+++ b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
@@ -81,8 +81,9 @@ namespace writerfilter::rtftok
 {
 Id getParagraphBorder(sal_uInt32 nIndex)
 {
-    static const Id aBorderIds[] = { NS_ooxml::LN_CT_PBdr_top, 
NS_ooxml::LN_CT_PBdr_left,
-                                     NS_ooxml::LN_CT_PBdr_bottom, 
NS_ooxml::LN_CT_PBdr_right };
+    static const Id aBorderIds[]
+        = { NS_ooxml::LN_CT_PBdr_top, NS_ooxml::LN_CT_PBdr_left, 
NS_ooxml::LN_CT_PBdr_bottom,
+            NS_ooxml::LN_CT_PBdr_right, NS_ooxml::LN_CT_PBdr_between };
 
     return aBorderIds[nIndex];
 }

Reply via email to