sw/qa/extras/rtfexport/data/tdf118047.rtf      |   14 +++++++++++++
 sw/qa/extras/rtfexport/rtfexport5.cxx          |   15 ++++++++++++++
 writerfilter/source/rtftok/rtfdispatchflag.cxx |    6 -----
 writerfilter/source/rtftok/rtfdocumentimpl.cxx |   26 +++++++++++++------------
 writerfilter/source/rtftok/rtfdocumentimpl.hxx |    3 +-
 5 files changed, 46 insertions(+), 18 deletions(-)

New commits:
commit 79b5ff92b17fde902c2f9db3e806f1c77a387dff
Author:     Vasily Melenchuk <vasily.melenc...@cib.de>
AuthorDate: Mon Mar 21 13:54:28 2022 +0300
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Mon Mar 21 15:58:54 2022 +0100

    tdf#118047: RTF import: better deduplication for header/footer
    
    Here are two related fixes in one patch:
    
    1. By default current style index is 0, not -1. Due to this we
    can assume usage of default "Normal" style during deduplication.
    Seems there is no difference in case of no style mentioning in
    run or mentioning "Normal" one (\s0), so value -1 looks
    unnesesary.
    
    2. During header/footer "substreams" processing StyleTableEntires
    was not reused in new domain mapper impl instance. So deduplication
    did not work well.
    
    2a. To avoid copying of whole StyleTableEntries between instances
    it is stored as pointer in domain mapper impl.
    
    Change-Id: Id003d35554e9b43186238920d9a6373452095121
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131899
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/sw/qa/extras/rtfexport/data/tdf118047.rtf 
b/sw/qa/extras/rtfexport/data/tdf118047.rtf
new file mode 100644
index 000000000000..258d99de9bef
--- /dev/null
+++ b/sw/qa/extras/rtfexport/data/tdf118047.rtf
@@ -0,0 +1,14 @@
+{\rtf1\ansi
+
+{\stylesheet
+{\fs72\sa3200 Normal;}
+}
+
+\sectd 
+{
+\headerr 
+Header\par
+}
+
+Text\par
+}
diff --git a/sw/qa/extras/rtfexport/rtfexport5.cxx 
b/sw/qa/extras/rtfexport/rtfexport5.cxx
index 04c857ade582..c59448af2514 100644
--- a/sw/qa/extras/rtfexport/rtfexport5.cxx
+++ b/sw/qa/extras/rtfexport/rtfexport5.cxx
@@ -1348,6 +1348,21 @@ DECLARE_RTFEXPORT_TEST(testTdf131234, "tdf131234.rtf")
     CPPUNIT_ASSERT_EQUAL(awt::FontSlant_NONE, 
getProperty<awt::FontSlant>(xRun, "CharPosture"));
 }
 
+DECLARE_RTFEXPORT_TEST(testTdf118047, "tdf118047.rtf")
+{
+    uno::Reference<text::XTextRange> xPara = getParagraph(1);
+
+    // Ensure that default "Normal" style properties are not applied to text:
+    // text remains with fontsize 12pt and no huge margin below
+    CPPUNIT_ASSERT_EQUAL(12.f, getProperty<float>(getRun(xPara, 1), 
"CharHeight"));
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(1), 
"ParaBottomMargin"));
+
+    // Same for header, it should not derive props from "Normal" style
+    CPPUNIT_ASSERT_EQUAL(OUString("Header"), 
parseDump("/root/page[1]/header/txt/text()"));
+    sal_Int32 nHeight = parseDump("/root/page[1]/header/infos/bounds", 
"height").toInt32();
+    CPPUNIT_ASSERT_MESSAGE("Header is too large", 1000 > nHeight);
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerfilter/source/rtftok/rtfdispatchflag.cxx 
b/writerfilter/source/rtftok/rtfdispatchflag.cxx
index 6df2b588a016..fb91639a3316 100644
--- a/writerfilter/source/rtftok/rtfdispatchflag.cxx
+++ b/writerfilter/source/rtftok/rtfdispatchflag.cxx
@@ -520,12 +520,8 @@ RTFError RTFDocumentImpl::dispatchFlag(RTFKeyword nKeyword)
                 {
                     
m_aStates.top().getParagraphSprms().set(NS_ooxml::LN_CT_PPrBase_pStyle,
                                                             new 
RTFValue(aName));
-                    m_aStates.top().setCurrentStyleIndex(0);
-                }
-                else
-                {
-                    m_aStates.top().setCurrentStyleIndex(-1);
                 }
+                m_aStates.top().setCurrentStyleIndex(0);
             }
             // Need to send paragraph properties again, if there will be any.
             m_bNeedPap = true;
diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.cxx 
b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
index f0847e945ebe..75d6ae193ffc 100644
--- a/writerfilter/source/rtftok/rtfdocumentimpl.cxx
+++ b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
@@ -291,6 +291,7 @@ 
RTFDocumentImpl::RTFDocumentImpl(uno::Reference<uno::XComponentContext> const& x
     , m_nCurrentFontIndex(0)
     , m_nCurrentEncoding(-1)
     , m_nDefaultFontIndex(-1)
+    , m_pStyleTableEntries(new RTFReferenceTable::Entries_t)
     , m_nCurrentStyleIndex(0)
     , m_bFormField(false)
     , m_bMathNor(false)
@@ -363,6 +364,7 @@ void RTFDocumentImpl::resolveSubstream(std::size_t nPos, Id 
nId, OUString const&
         m_aAuthorInitials.clear();
     }
     pImpl->m_nDefaultFontIndex = m_nDefaultFontIndex;
+    pImpl->m_pStyleTableEntries = m_pStyleTableEntries;
     pImpl->Strm().Seek(nPos);
     SAL_INFO("writerfilter.rtf", "substream start");
     Mapper().substream(nId, pImpl);
@@ -497,16 +499,16 @@ RTFDocumentImpl::getProperties(const RTFSprms& 
rAttributes, RTFSprms const& rSpr
     int nStyle = 0;
     if (!m_aStates.empty())
         nStyle = m_aStates.top().getCurrentStyleIndex();
-    auto it = m_aStyleTableEntries.find(nStyle);
-    if (it != m_aStyleTableEntries.end())
+    auto it = m_pStyleTableEntries->find(nStyle);
+    if (it != m_pStyleTableEntries->end())
     {
         // cloneAndDeduplicate() wants to know about only a single "style", so
         // let's merge paragraph and character style properties here.
-        auto itChar = m_aStyleTableEntries.end();
+        auto itChar = m_pStyleTableEntries->end();
         if (!m_aStates.empty())
         {
             int nCharStyle = m_aStates.top().getCurrentCharacterStyleIndex();
-            itChar = m_aStyleTableEntries.find(nCharStyle);
+            itChar = m_pStyleTableEntries->find(nCharStyle);
         }
 
         RTFSprms aStyleSprms;
@@ -517,7 +519,7 @@ RTFDocumentImpl::getProperties(const RTFSprms& rAttributes, 
RTFSprms const& rSpr
         RTFReferenceProperties& rProps = 
*static_cast<RTFReferenceProperties*>(it->second.get());
         lcl_copyFlatten(rProps, aStyleAttributes, aStyleSprms);
 
-        if (itChar != m_aStyleTableEntries.end())
+        if (itChar != m_pStyleTableEntries->end())
         {
             // Found active character style, then update 
aStyleSprms/Attributes.
             if (!nStyleType || nStyleType == 
NS_ooxml::LN_Value_ST_StyleType_character)
@@ -1402,7 +1404,7 @@ void RTFDocumentImpl::text(OUString& rString)
 
                             writerfilter::Reference<Properties>::Pointer_t 
const pProp(
                                 createStyleProperties());
-                            m_aStyleTableEntries.insert(
+                            m_pStyleTableEntries->insert(
                                 std::make_pair(m_nCurrentStyleIndex, pProp));
                         }
                         else
@@ -2091,7 +2093,7 @@ writerfilter::Reference<Properties>::Pointer_t 
RTFDocumentImpl::createStylePrope
 /** 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
+       stored in m_pStyleTableEntries, 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
@@ -2100,7 +2102,7 @@ writerfilter::Reference<Properties>::Pointer_t 
RTFDocumentImpl::createStylePrope
 RTFReferenceTable::Entries_t RTFDocumentImpl::deduplicateStyleTable()
 {
     RTFReferenceTable::Entries_t ret;
-    for (auto const& it : m_aStyleTableEntries)
+    for (auto const& it : *m_pStyleTableEntries)
     {
         auto pStyle = it.second;
         ret[it.first] = pStyle;
@@ -2116,8 +2118,8 @@ RTFReferenceTable::Entries_t 
RTFDocumentImpl::deduplicateStyleTable()
             if (it.first == nBasedOn)
                 continue;
 
-            auto const itParent(m_aStyleTableEntries.find(nBasedOn)); // 
definition as read!
-            if (itParent != m_aStyleTableEntries.end())
+            auto const itParent(m_pStyleTableEntries->find(nBasedOn)); // 
definition as read!
+            if (itParent != m_pStyleTableEntries->end())
             {
                 auto const pStyleType(
                     
static_cast<RTFReferenceProperties&>(*pStyle).getAttributes().find(
@@ -2143,7 +2145,7 @@ RTFReferenceTable::Entries_t 
RTFDocumentImpl::deduplicateStyleTable()
             }
         }
     }
-    assert(ret.size() == m_aStyleTableEntries.size());
+    assert(ret.size() == m_pStyleTableEntries->size());
     return ret;
 }
 
@@ -3668,7 +3670,7 @@ RTFParserState::RTFParserState(RTFDocumentImpl* 
pDocumentImpl)
     , m_nHour(0)
     , m_nMinute(0)
     , m_pCurrentDestinationText(nullptr)
-    , m_nCurrentStyleIndex(-1)
+    , m_nCurrentStyleIndex(0)
     , m_nCurrentCharacterStyleIndex(-1)
     , m_pCurrentBuffer(nullptr)
     , m_bInListpicture(false)
diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.hxx 
b/writerfilter/source/rtftok/rtfdocumentimpl.hxx
index fc5c8802b5d7..66e27a509be5 100644
--- a/writerfilter/source/rtftok/rtfdocumentimpl.hxx
+++ b/writerfilter/source/rtftok/rtfdocumentimpl.hxx
@@ -933,7 +933,8 @@ private:
     /// Raw default font index, use getFont() on it to get a real one.
     int m_nDefaultFontIndex;
 
-    RTFReferenceTable::Entries_t m_aStyleTableEntries;
+    /// To avoid copying entries between DomainMapper instances it is stored 
as pointer
+    std::shared_ptr<RTFReferenceTable::Entries_t> m_pStyleTableEntries;
     int m_nCurrentStyleIndex;
     bool m_bFormField;
     /// For the INCLUDEPICTURE field's argument.

Reply via email to