[Libreoffice-commits] core.git: Branch 'libreoffice-6-2' - sw/qa writerfilter/source

Michael Stahl (via logerrit) logerrit at kemper.freedesktop.org
Sat Apr 13 18:29:12 UTC 2019


 sw/qa/extras/rtfexport/data/para-style-bottom-margin-2.rtf |   12 ++
 sw/qa/extras/rtfexport/rtfexport2.cxx                      |   27 +++++
 sw/qa/extras/rtfimport/data/para-style-bottom-margin.rtf   |   14 ++
 sw/qa/extras/rtfimport/rtfimport.cxx                       |   31 ++++++
 writerfilter/source/rtftok/rtfdocumentimpl.cxx             |   63 ++++++++++++-
 writerfilter/source/rtftok/rtfdocumentimpl.hxx             |    2 
 writerfilter/source/rtftok/rtfsprm.cxx                     |   11 +-
 writerfilter/source/rtftok/rtfsprm.hxx                     |    4 
 8 files changed, 158 insertions(+), 6 deletions(-)

New commits:
commit 9dbff5b4e1dabb715ed146827f69f8fbaba8644a
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Fri Apr 5 19:30:45 2019 +0200
Commit:     Caolán McNamara <caolanm at redhat.com>
CommitDate: Sat Apr 13 20:28:39 2019 +0200

    writerfilter: implement RTF derived styles defaulting
    
    It turns out that the situation fixed in commit
    1be0a3fa9ebb22b607c54b47739d4467acfed259 also applies to the definition
    of the styles themselves.
    
    To implement the same style import as Word, the style definitions need
    to be stored twice: once as read from the file, and another time with
    attributes defaulted and deduplicated vs. the parent style; the second
    representation is then sent to the domain mapper.
    
    To make this easier, add a bool parameter to cloneAndDeduplicate()
    to disable the implicit pPr dereferencing that happens when creating the
    hard formatted paragraph properties (this could potentially be cleaned
    up further if those paragraph properties would use pPr wrapper
    themselves).
    
    Also implement defaulting of line spacing in getDefaultSPRM().
    
    Reviewed-on: https://gerrit.libreoffice.org/70320
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmiklos at collabora.com>
    (cherry picked from commit 3d74ddd190a5087e0a54ef7b14d0a43006745ec3)
    
    Change-Id: I4810e917697b3af244e5dbdd7f5a45b4767c93fc
    Reviewed-on: https://gerrit.libreoffice.org/70508
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    Tested-by: Caolán McNamara <caolanm at redhat.com>

diff --git a/sw/qa/extras/rtfexport/data/para-style-bottom-margin-2.rtf b/sw/qa/extras/rtfexport/data/para-style-bottom-margin-2.rtf
new file mode 100644
index 000000000000..b4261e717070
--- /dev/null
+++ b/sw/qa/extras/rtfexport/data/para-style-bottom-margin-2.rtf
@@ -0,0 +1,12 @@
+{\rtf1
+\ansi\ansicpg1252\deff0
+{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2 Times New Roman;}}
+{\stylesheet
+{\ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \snext0 Normal;}
+{\s15\ql \li720\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin720\itap0\contextualspace \sbasedon0 \snext15 List Paragraph;}
+}
+\pard\plain \ltrpar\s15\ql \li720\ri0\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin720\itap0\contextualspace
+\par
+\pard\plain
+\par
+}
diff --git a/sw/qa/extras/rtfexport/rtfexport2.cxx b/sw/qa/extras/rtfexport/rtfexport2.cxx
index 307b6465ecad..1607d1754b05 100644
--- a/sw/qa/extras/rtfexport/rtfexport2.cxx
+++ b/sw/qa/extras/rtfexport/rtfexport2.cxx
@@ -1105,6 +1105,33 @@ DECLARE_RTFEXPORT_TEST(testParaBottomMargin, "para-bottom-margin.rtf")
     CPPUNIT_ASSERT_EQUAL(sal_Int32(2), getProperty<sal_Int32>(getParagraph(1), "ParaTopMargin"));
 }
 
+DECLARE_RTFIMPORT_TEST(testParaStyleBottomMargin2, "para-style-bottom-margin-2.rtf")
+{
+    uno::Reference<beans::XPropertySet> xPropertySet(
+        getStyles("ParagraphStyles")->getByName("Standard"), uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(353), getProperty<sal_Int32>(xPropertySet, "ParaBottomMargin"));
+    CPPUNIT_ASSERT_EQUAL(style::LineSpacingMode::PROP,
+                         getProperty<style::LineSpacing>(xPropertySet, "ParaLineSpacing").Mode);
+    CPPUNIT_ASSERT_EQUAL(sal_Int16(115),
+                         getProperty<style::LineSpacing>(xPropertySet, "ParaLineSpacing").Height);
+
+    // the derived style contains \sa200, as does its parent
+    uno::Reference<beans::XPropertySet> xPropertySet1(
+        getStyles("ParagraphStyles")->getByName("List Paragraph"), uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(353), getProperty<sal_Int32>(xPropertySet1, "ParaBottomMargin"));
+    CPPUNIT_ASSERT_EQUAL(style::LineSpacingMode::PROP,
+                         getProperty<style::LineSpacing>(xPropertySet1, "ParaLineSpacing").Mode);
+    CPPUNIT_ASSERT_EQUAL(sal_Int16(115),
+                         getProperty<style::LineSpacing>(xPropertySet1, "ParaLineSpacing").Height);
+    // for the paragraph there is no \saN, so it should default to 0
+    auto const xPara(getParagraph(1));
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(xPara, "ParaBottomMargin"));
+    CPPUNIT_ASSERT_EQUAL(style::LineSpacingMode::PROP,
+                         getProperty<style::LineSpacing>(xPara, "ParaLineSpacing").Mode);
+    CPPUNIT_ASSERT_EQUAL(sal_Int16(115),
+                         getProperty<style::LineSpacing>(xPara, "ParaLineSpacing").Height);
+}
+
 DECLARE_RTFEXPORT_TEST(testFdo66040, "fdo66040.rtf")
 {
     uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(mxComponent, uno::UNO_QUERY);
diff --git a/sw/qa/extras/rtfimport/data/para-style-bottom-margin.rtf b/sw/qa/extras/rtfimport/data/para-style-bottom-margin.rtf
new file mode 100644
index 000000000000..d7ebc215f3fc
--- /dev/null
+++ b/sw/qa/extras/rtfimport/data/para-style-bottom-margin.rtf
@@ -0,0 +1,14 @@
+{\rtf1
+\ansi\ansicpg1252\deff0
+{\fonttbl
+{\f0 Times New Roman;}
+}
+{\stylesheet
+{\sa200\sl276\slmult1 \snext0 Normal;}
+{\s19 \sbasedon0 \snext0 toc 1;}
+}
+\pard\plain \s19
+foo
+\par
+\par
+}
diff --git a/sw/qa/extras/rtfimport/rtfimport.cxx b/sw/qa/extras/rtfimport/rtfimport.cxx
index 5d7e6f34db79..5db5dbc2792c 100644
--- a/sw/qa/extras/rtfimport/rtfimport.cxx
+++ b/sw/qa/extras/rtfimport/rtfimport.cxx
@@ -18,6 +18,8 @@
 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
 #include <com/sun/star/lang/XServiceInfo.hpp>
 #include <com/sun/star/style/BreakType.hpp>
+#include <com/sun/star/style/LineSpacing.hpp>
+#include <com/sun/star/style/LineSpacingMode.hpp>
 #include <com/sun/star/style/ParagraphAdjust.hpp>
 #include <com/sun/star/style/TabStop.hpp>
 #include <com/sun/star/table/BorderLine2.hpp>
@@ -1588,6 +1590,35 @@ DECLARE_RTFIMPORT_TEST(testDefaultValues, "default-values.rtf")
     CPPUNIT_ASSERT_EQUAL(sal_Int32(COL_AUTO), getProperty<sal_Int32>(run, "CharColor"));
 }
 
+DECLARE_RTFIMPORT_TEST(testParaStyleBottomMargin, "para-style-bottom-margin.rtf")
+{
+    uno::Reference<beans::XPropertySet> xPropertySet(
+        getStyles("ParagraphStyles")->getByName("Standard"), uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(353), getProperty<sal_Int32>(xPropertySet, "ParaBottomMargin"));
+    CPPUNIT_ASSERT_EQUAL(style::LineSpacingMode::PROP,
+                         getProperty<style::LineSpacing>(xPropertySet, "ParaLineSpacing").Mode);
+    CPPUNIT_ASSERT_EQUAL(sal_Int16(115),
+                         getProperty<style::LineSpacing>(xPropertySet, "ParaLineSpacing").Height);
+
+    // The reason why this is 0 despite the default style containing \sa200
+    // is that Word will actually interpret \basedonN
+    // as "set style N and for every attribute of that style,
+    // set an attribute with default value on the style"
+    uno::Reference<beans::XPropertySet> xPropertySet1(
+        getStyles("ParagraphStyles")->getByName("Contents 1"), uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(xPropertySet1, "ParaBottomMargin"));
+    CPPUNIT_ASSERT_EQUAL(style::LineSpacingMode::PROP,
+                         getProperty<style::LineSpacing>(xPropertySet1, "ParaLineSpacing").Mode);
+    CPPUNIT_ASSERT_EQUAL(sal_Int16(100),
+                         getProperty<style::LineSpacing>(xPropertySet1, "ParaLineSpacing").Height);
+    auto const xPara(getParagraph(1));
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(xPara, "ParaBottomMargin"));
+    CPPUNIT_ASSERT_EQUAL(style::LineSpacingMode::PROP, // 0 or 3 ???
+                         getProperty<style::LineSpacing>(xPara, "ParaLineSpacing").Mode);
+    CPPUNIT_ASSERT_EQUAL(sal_Int16(100),
+                         getProperty<style::LineSpacing>(xPara, "ParaLineSpacing").Height);
+}
+
 // tests should only be added to rtfIMPORT *if* they fail round-tripping in rtfEXPORT
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.cxx b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
index 104e0e004bf6..6c97111bed71 100644
--- a/writerfilter/source/rtftok/rtfdocumentimpl.cxx
+++ b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
@@ -517,8 +517,9 @@ RTFDocumentImpl::getProperties(RTFSprms& rAttributes, RTFSprms const& rSprms, Id
         }
 
         // Get rid of direct formatting what is already in the style.
-        RTFSprms const sprms(aSprms.cloneAndDeduplicate(aStyleSprms, nStyleType));
-        RTFSprms const attributes(rAttributes.cloneAndDeduplicate(aStyleAttributes, nStyleType));
+        RTFSprms const sprms(aSprms.cloneAndDeduplicate(aStyleSprms, nStyleType, true));
+        RTFSprms const attributes(
+            rAttributes.cloneAndDeduplicate(aStyleAttributes, nStyleType, true));
         return new RTFReferenceProperties(attributes, sprms);
     }
 
@@ -2026,6 +2027,61 @@ writerfilter::Reference<Properties>::Pointer_t RTFDocumentImpl::createStylePrope
     return pProps;
 }
 
+/** 2 different representations of the styles are needed:
+
+    1) flat content, as read from the input file:
+       stored in m_aStyleTableEntries, used as reference input for
+       deduplication both here and for hard formatting in getProperties()
+
+    2) real content, with proper override of sprms/attributes where it differs
+       from parent style; this is produced here and sent to domain mapper
+ */
+RTFReferenceTable::Entries_t RTFDocumentImpl::deduplicateStyleTable()
+{
+    RTFReferenceTable::Entries_t ret;
+    for (auto const& it : m_aStyleTableEntries)
+    {
+        auto pStyle = it.second;
+        // ugly downcasts here, but can't easily replace the members with
+        // RTFReferenceProperties because dmapper wants SvRef<Properties> anyway
+        RTFValue::Pointer_t const pBasedOn(
+            static_cast<RTFReferenceProperties&>(*pStyle).getSprms().find(
+                NS_ooxml::LN_CT_Style_basedOn));
+        if (pBasedOn)
+        {
+            int const nBasedOn(pBasedOn->getInt());
+            auto const itParent(m_aStyleTableEntries.find(nBasedOn)); // definition as read!
+            if (itParent != m_aStyleTableEntries.end())
+            {
+                auto const pStyleType(
+                    static_cast<RTFReferenceProperties&>(*pStyle).getAttributes().find(
+                        NS_ooxml::LN_CT_Style_type));
+                assert(pStyleType);
+                int const nStyleType(pStyleType->getInt());
+                RTFSprms const sprms(
+                    static_cast<RTFReferenceProperties&>(*pStyle).getSprms().cloneAndDeduplicate(
+                        static_cast<RTFReferenceProperties&>(*itParent->second).getSprms(),
+                        nStyleType));
+                RTFSprms const attributes(
+                    static_cast<RTFReferenceProperties&>(*pStyle)
+                        .getAttributes()
+                        .cloneAndDeduplicate(
+                            static_cast<RTFReferenceProperties&>(*itParent->second).getAttributes(),
+                            nStyleType));
+
+                pStyle = new RTFReferenceProperties(attributes, sprms);
+            }
+            else
+            {
+                SAL_WARN("writerfilter.rtf", "parent style not found: " << nBasedOn);
+            }
+        }
+        ret[it.first] = pStyle;
+    }
+    assert(ret.size() == m_aStyleTableEntries.size());
+    return ret;
+}
+
 void RTFDocumentImpl::resetSprms()
 {
     m_aStates.top().aTableSprms.clear();
@@ -2089,8 +2145,9 @@ RTFError RTFDocumentImpl::popState()
         break;
         case Destination::STYLESHEET:
         {
+            RTFReferenceTable::Entries_t const pStyleTableDeduplicated(deduplicateStyleTable());
             writerfilter::Reference<Table>::Pointer_t const pTable(
-                new RTFReferenceTable(m_aStyleTableEntries));
+                new RTFReferenceTable(pStyleTableDeduplicated));
             Mapper().table(NS_ooxml::LN_STYLESHEET, pTable);
         }
         break;
diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.hxx b/writerfilter/source/rtftok/rtfdocumentimpl.hxx
index d51512889d74..0ecf59aae42a 100644
--- a/writerfilter/source/rtftok/rtfdocumentimpl.hxx
+++ b/writerfilter/source/rtftok/rtfdocumentimpl.hxx
@@ -504,6 +504,8 @@ public:
     /// Buffers properties to be sent later.
     void bufferProperties(RTFBuffer_t& rBuffer, const RTFValue::Pointer_t& pValue,
                           const tools::SvRef<TableRowBuffer>& pTableProperties);
+    /// implement non-obvious RTF specific style inheritance
+    RTFReferenceTable::Entries_t deduplicateStyleTable();
 
 private:
     SvStream& Strm();
diff --git a/writerfilter/source/rtftok/rtfsprm.cxx b/writerfilter/source/rtftok/rtfsprm.cxx
index a4f3b81be211..9eab27298050 100644
--- a/writerfilter/source/rtftok/rtfsprm.cxx
+++ b/writerfilter/source/rtftok/rtfsprm.cxx
@@ -160,6 +160,12 @@ static RTFValue::Pointer_t getDefaultSPRM(Id const id, Id nStyleType)
             case NS_ooxml::LN_CT_Ind_firstLine:
                 return new RTFValue(0);
 
+            case NS_ooxml::LN_CT_Spacing_lineRule:
+                return new RTFValue(NS_ooxml::LN_Value_doc_ST_LineSpacingRule_auto);
+            case NS_ooxml::LN_CT_Spacing_line:
+                // presumably this means 100%, cf. static const int nSingleLineSpacing = 240;
+                return new RTFValue(240);
+
             default:
                 break;
         }
@@ -338,7 +344,8 @@ void RTFSprms::duplicateList(const RTFValue::Pointer_t& pAbstract)
     }
 }
 
-RTFSprms RTFSprms::cloneAndDeduplicate(RTFSprms& rReference, Id nStyleType) const
+RTFSprms RTFSprms::cloneAndDeduplicate(RTFSprms& rReference, Id const nStyleType,
+                                       bool const bImplicitPPr) const
 {
     RTFSprms ret(*this);
     ret.ensureCopyBeforeWrite();
@@ -351,7 +358,7 @@ RTFSprms RTFSprms::cloneAndDeduplicate(RTFSprms& rReference, Id nStyleType) cons
         // paragraphs, but they are below NS_ooxml::LN_CT_Style_pPr in case of
         // styles. So handle those children directly, to avoid unexpected
         // addition of direct formatting sprms at the paragraph level.
-        if (rSprm.first == NS_ooxml::LN_CT_Style_pPr)
+        if (bImplicitPPr && rSprm.first == NS_ooxml::LN_CT_Style_pPr)
         {
             for (auto& i : rSprm.second->getSprms())
                 cloneAndDeduplicateSprm(i, ret, nStyleType);
diff --git a/writerfilter/source/rtftok/rtfsprm.hxx b/writerfilter/source/rtftok/rtfsprm.hxx
index cc5fb73ff13f..24eb9d6e1da9 100644
--- a/writerfilter/source/rtftok/rtfsprm.hxx
+++ b/writerfilter/source/rtftok/rtfsprm.hxx
@@ -62,7 +62,9 @@ public:
     /// Removes elements which are already in the reference set.
     /// Also insert default values to override attributes of style
     /// (yes, really; that's what Word does).
-    RTFSprms cloneAndDeduplicate(RTFSprms& rReference, Id nStyleType) const;
+    /// @param bImplicitPPr implicit dereference of top-level pPr SPRM
+    RTFSprms cloneAndDeduplicate(RTFSprms& rReference, Id nStyleType,
+                                 bool bImplicitPPr = false) const;
     /// Inserts default values to override attributes of pAbstract.
     void duplicateList(const RTFValue::Pointer_t& pAbstract);
     /// Removes duplicated values based on in-list properties.


More information about the Libreoffice-commits mailing list