From 9f5263c477b82fef5aa9c3e79fb6af92aa049e24 Mon Sep 17 00:00:00 2001 From: Miklos Vajna Date: Sun, 25 Nov 2012 00:54:10 +0100 Subject: fdo#44736 RTF import: ignore direct formatting which equals to style Change-Id: Ie82f18381a95adbfedf7ea02d6844685e44b151d --- writerfilter/source/rtftok/rtfdocumentimpl.cxx | 27 +++++++++++++++++----- writerfilter/source/rtftok/rtfdocumentimpl.hxx | 4 ++++ .../source/rtftok/rtfreferenceproperties.cxx | 10 ++++++++ .../source/rtftok/rtfreferenceproperties.hxx | 2 ++ writerfilter/source/rtftok/rtfsprm.cxx | 20 ++++++++++++++++ writerfilter/source/rtftok/rtfsprm.hxx | 2 ++ writerfilter/source/rtftok/rtfvalue.cxx | 5 ++++ writerfilter/source/rtftok/rtfvalue.hxx | 1 + 8 files changed, 65 insertions(+), 6 deletions(-) diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.cxx b/writerfilter/source/rtftok/rtfdocumentimpl.cxx index c8992ecfb780..d1888dc60f3e 100644 --- a/writerfilter/source/rtftok/rtfdocumentimpl.cxx +++ b/writerfilter/source/rtftok/rtfdocumentimpl.cxx @@ -399,6 +399,21 @@ void RTFDocumentImpl::setNeedPar(bool bNeedPar) m_bNeedPar = bNeedPar; } +writerfilter::Reference::Pointer_t RTFDocumentImpl::getProperties(RTFSprms& rAttributes, RTFSprms& rSprms) +{ + int nStyle = m_aStates.top().nCurrentStyleIndex; + RTFReferenceTable::Entries_t::iterator it = m_aStyleTableEntries.find(nStyle); + if (it != m_aStyleTableEntries.end()) + { + RTFReferenceProperties& rProps = *(RTFReferenceProperties*)it->second.get(); + // Get rid of direct formatting what is already in the style. + rSprms.deduplicate(rProps.getSprms()); + rAttributes.deduplicate(rProps.getAttributes()); + } + writerfilter::Reference::Pointer_t pRet(new RTFReferenceProperties(rAttributes, rSprms)); + return pRet; +} + void RTFDocumentImpl::checkNeedPap() { if (m_bNeedPap) @@ -407,7 +422,7 @@ void RTFDocumentImpl::checkNeedPap() if (!m_pCurrentBuffer) { writerfilter::Reference::Pointer_t const pParagraphProperties( - new RTFReferenceProperties(m_aStates.top().aParagraphAttributes, m_aStates.top().aParagraphSprms) + getProperties(m_aStates.top().aParagraphAttributes, m_aStates.top().aParagraphSprms) ); // Writer will ignore a page break before a text frame, so guard it with empty paragraphs @@ -441,9 +456,7 @@ void RTFDocumentImpl::runProps() { if (!m_pCurrentBuffer) { - writerfilter::Reference::Pointer_t const pProperties( - new RTFReferenceProperties(m_aStates.top().aCharacterAttributes, m_aStates.top().aCharacterSprms) - ); + writerfilter::Reference::Pointer_t const pProperties = getProperties(m_aStates.top().aCharacterAttributes, m_aStates.top().aCharacterSprms); Mapper().props(pProperties); } else @@ -1677,7 +1690,7 @@ int RTFDocumentImpl::dispatchSymbol(RTFKeyword nKeyword) m_aStates.top().aTableCellAttributes = m_aDefaultState.aTableCellAttributes; writerfilter::Reference::Pointer_t const pParagraphProperties( - new RTFReferenceProperties(m_aStates.top().aParagraphAttributes, m_aStates.top().aParagraphSprms) + getProperties(m_aStates.top().aParagraphAttributes, m_aStates.top().aParagraphSprms) ); Mapper().props(pParagraphProperties); @@ -2623,6 +2636,7 @@ int RTFDocumentImpl::dispatchValue(RTFKeyword nKeyword, int nParam) } break; case RTF_S: + m_aStates.top().nCurrentStyleIndex = nParam; if (m_aStates.top().nDestinationState == DESTINATION_STYLESHEET || m_aStates.top().nDestinationState == DESTINATION_STYLEENTRY) { m_nCurrentStyleIndex = nParam; @@ -4206,7 +4220,8 @@ RTFParserState::RTFParserState(RTFDocumentImpl *pDocumentImpl) nMonth(0), nDay(0), nHour(0), - nMinute(0) + nMinute(0), + nCurrentStyleIndex(-1) { } diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.hxx b/writerfilter/source/rtftok/rtfdocumentimpl.hxx index 4942facc0d3e..98011640306f 100644 --- a/writerfilter/source/rtftok/rtfdocumentimpl.hxx +++ b/writerfilter/source/rtftok/rtfdocumentimpl.hxx @@ -399,6 +399,9 @@ namespace writerfilter { /// Text from special destinations. rtl::OUStringBuffer aDestinationText; + + /// Same as the int value of NS_rtf::LN_ISTD in aParagraphAttributes, for performance reasons. + int nCurrentStyleIndex; }; class RTFTokenizer; @@ -478,6 +481,7 @@ namespace writerfilter { void runBreak(); void parBreak(); void tableBreak(); + writerfilter::Reference::Pointer_t getProperties(RTFSprms& rAttributes, RTFSprms& rSprms); void checkNeedPap(); void sectBreak(bool bFinal); void replayBuffer(RTFBuffer_t& rBuffer); diff --git a/writerfilter/source/rtftok/rtfreferenceproperties.cxx b/writerfilter/source/rtftok/rtfreferenceproperties.cxx index 03cd0e97293c..50f76e3e3e6c 100644 --- a/writerfilter/source/rtftok/rtfreferenceproperties.cxx +++ b/writerfilter/source/rtftok/rtfreferenceproperties.cxx @@ -62,6 +62,16 @@ std::string RTFReferenceProperties::getType() const return "RTFReferenceProperties"; } +RTFSprms& RTFReferenceProperties::getAttributes() +{ + return m_aAttributes; +} + +RTFSprms& RTFReferenceProperties::getSprms() +{ + return m_aSprms; +} + } // namespace rtftok } // namespace writerfilter diff --git a/writerfilter/source/rtftok/rtfreferenceproperties.hxx b/writerfilter/source/rtftok/rtfreferenceproperties.hxx index d580de912ca8..369590b14cc2 100644 --- a/writerfilter/source/rtftok/rtfreferenceproperties.hxx +++ b/writerfilter/source/rtftok/rtfreferenceproperties.hxx @@ -42,6 +42,8 @@ namespace writerfilter { virtual ~RTFReferenceProperties(); virtual void resolve(Properties & rHandler); virtual std::string getType() const; + RTFSprms& getAttributes(); + RTFSprms& getSprms(); private: RTFSprms m_aAttributes; RTFSprms m_aSprms; diff --git a/writerfilter/source/rtftok/rtfsprm.cxx b/writerfilter/source/rtftok/rtfsprm.cxx index fb61d292a5b8..2958cde25cb8 100644 --- a/writerfilter/source/rtftok/rtfsprm.cxx +++ b/writerfilter/source/rtftok/rtfsprm.cxx @@ -29,6 +29,7 @@ #include #include +#include // NS_rtf namespace using rtl::OStringBuffer; @@ -130,6 +131,25 @@ bool RTFSprms::erase(Id nKeyword) return false; } +void RTFSprms::deduplicate(RTFSprms& rReference) +{ + RTFSprms::Iterator_t i = m_aSprms.begin(); + while (i != m_aSprms.end()) + { + bool bIgnore = false; + if (i->first != NS_rtf::LN_ISTD) + { + RTFValue::Pointer_t pValue(rReference.find(i->first)); + if (pValue.get() && i->second->equals(*pValue)) + bIgnore = true; + } + if (bIgnore) + i = m_aSprms.erase(i); + else + ++i; + } +} + RTFSprms::RTFSprms() : m_aSprms() { diff --git a/writerfilter/source/rtftok/rtfsprm.hxx b/writerfilter/source/rtftok/rtfsprm.hxx index df223fc697cd..80d41a3c0f69 100644 --- a/writerfilter/source/rtftok/rtfsprm.hxx +++ b/writerfilter/source/rtftok/rtfsprm.hxx @@ -47,6 +47,8 @@ namespace writerfilter { /// Does the same as ->push_back(), except that it can overwrite existing entries. void set(Id nKeyword, RTFValue::Pointer_t pValue, bool bOverwrite = true); bool erase(Id nKeyword); + /// Removes elements, which are already in the reference set. + void deduplicate(RTFSprms& rReference); void swap(RTFSprms& rOther); size_t size() const { return m_aSprms.size(); } bool empty() const { return m_aSprms.empty(); } diff --git a/writerfilter/source/rtftok/rtfvalue.cxx b/writerfilter/source/rtftok/rtfvalue.cxx index 488252209eea..eaacc2a8351e 100644 --- a/writerfilter/source/rtftok/rtfvalue.cxx +++ b/writerfilter/source/rtftok/rtfvalue.cxx @@ -200,6 +200,11 @@ RTFValue* RTFValue::Clone() return new RTFValue(m_nValue, m_sValue, *m_pAttributes, *m_pSprms, m_xShape, m_xStream, m_xObject, m_bForceString); } +bool RTFValue::equals(RTFValue& rOther) +{ + return m_nValue == rOther.m_nValue; +} + RTFSprms& RTFValue::getAttributes() { return *m_pAttributes; diff --git a/writerfilter/source/rtftok/rtfvalue.hxx b/writerfilter/source/rtftok/rtfvalue.hxx index 6751126ac3bc..3714d263fe78 100644 --- a/writerfilter/source/rtftok/rtfvalue.hxx +++ b/writerfilter/source/rtftok/rtfvalue.hxx @@ -62,6 +62,7 @@ namespace writerfilter { virtual RTFValue* Clone(); RTFSprms& getAttributes(); RTFSprms& getSprms(); + bool equals(RTFValue& rOther); private: RTFValue& operator=(RTFValue const& rOther); int m_nValue; -- cgit v1.2.3