From 651d045cddf8fd238999cb3442e87410f1a8e1df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= Date: Wed, 30 May 2012 13:12:15 +0100 Subject: [PATCH] Resolves: rhbz#825548 some rtf documents take vast amounts of time to load rtf documents with vast sequences of replicated properties without any pard resets to defaults create huge vectors of properties that eat time and memory So if we are adding a property which already exists and there are no intermediate properties which would cause side effects to the property then update the existing one instead Only implemented this optimization for some selected character properties This takes my load time down to 7 seconds from effectively some "infinite" hour+ load time. Change-Id: I520779233180f4d9faf9fb0989d546e08fc6cabd --- .../source/rtftok/rtfdocumentimpl.cxx | 62 ++++++++++++++++++- writerfilter/source/rtftok/rtfsprm.hxx | 3 + 2 files changed, 62 insertions(+), 3 deletions(-) diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.cxx b/writerfilter/source/rtftok/rtfdocumentimpl.cxx index d57f96f188c8..84461831f424 100644 --- a/writerfilter/source/rtftok/rtfdocumentimpl.cxx +++ b/writerfilter/source/rtftok/rtfdocumentimpl.cxx @@ -84,6 +84,57 @@ static Id lcl_getParagraphBorder(sal_uInt32 nIndex) return aBorderIds[nIndex]; } +namespace +{ + bool isTrivialCharSprm(Id nSprm) + { + bool bRet = false; + switch (nSprm) + { + case NS_sprm::LN_CRgFtc0: + case NS_sprm::LN_CRgFtc1: + case NS_sprm::LN_CRgFtc2: + case NS_sprm::LN_CHps: + case NS_sprm::LN_CHpsBi: + case NS_sprm::LN_CSfxText: + case NS_sprm::LN_CDxaSpace: + case NS_sprm::LN_CHpsKern: + case NS_sprm::LN_CCharScale: + case NS_sprm::LN_CRgLid0: + case NS_sprm::LN_CRgLid1: + case NS_sprm::LN_CLidBi: + bRet = true; + break; + default: + break; + } + return bRet; + } + + //rhbz#825548. rtf documents with vast sequences of replicated properties without + //any resets to defaults create a huge vector of properties and eat time and memory + // + //So if we are adding a property which already exists and there are no intermediate + //properties which would cause side effects to the property then update the existing + //one instead + bool tryToSafelyUpdateAnExistingProp(RTFSprms &rSprms, Id nSprm, RTFValue::Pointer_t xArg) + { + if (!isTrivialCharSprm(nSprm)) + return false; + + for (RTFSprms::ReverseIterator_t i = rSprms.rbegin(); i != rSprms.rend() && isTrivialCharSprm(i->first); ++i) + { + if (i->first == nSprm) + { + i->second = xArg; + return true; + } + } + + return false; + } +} + static void lcl_putNestedAttribute(RTFSprms& rSprms, Id nParent, Id nId, RTFValue::Pointer_t pValue, bool bOverwrite = false, bool bAttribute = true) { @@ -107,7 +158,8 @@ static void lcl_putNestedAttribute(RTFSprms& rSprms, Id nParent, Id nId, RTFValu } } } - rAttributes.push_back(make_pair(nId, pValue)); + if (!tryToSafelyUpdateAnExistingProp(rAttributes, nId, pValue)) + rAttributes.push_back(make_pair(nId, pValue)); } static void lcl_putNestedSprm(RTFSprms& rSprms, Id nParent, Id nId, RTFValue::Pointer_t pValue, bool bOverwrite = false) @@ -2227,7 +2279,9 @@ int RTFDocumentImpl::dispatchValue(RTFKeyword nKeyword, int nParam) } if (nSprm > 0) { - m_aStates.top().aCharacterSprms.push_back(make_pair(nSprm, pIntValue)); + RTFSprms &rSprms = m_aStates.top().aCharacterSprms; + if (!tryToSafelyUpdateAnExistingProp(rSprms, nSprm, pIntValue)) + rSprms.push_back(make_pair(nSprm, pIntValue)); // Language is a character property, but we should store it at a paragraph level as well for fields. if (nKeyword == RTF_LANG && m_bNeedPap) m_aStates.top().aParagraphSprms.push_back(make_pair(nSprm, pIntValue)); @@ -2310,7 +2364,9 @@ int RTFDocumentImpl::dispatchValue(RTFKeyword nKeyword, int nParam) { int nFontIndex = getFontIndex(nParam); RTFValue::Pointer_t pValue(new RTFValue(nFontIndex)); - m_aStates.top().aCharacterSprms.push_back(make_pair(NS_sprm::LN_CRgFtc0, pValue)); + RTFSprms &rSprms = m_aStates.top().aCharacterSprms; + if (!tryToSafelyUpdateAnExistingProp(rSprms, NS_sprm::LN_CRgFtc0, pValue)) + rSprms.push_back(make_pair(NS_sprm::LN_CRgFtc0, pValue)); m_aStates.top().nCurrentEncoding = getEncoding(nFontIndex); } break; diff --git a/writerfilter/source/rtftok/rtfsprm.hxx b/writerfilter/source/rtftok/rtfsprm.hxx index d126b728f05f..1004b596d3e6 100644 --- a/writerfilter/source/rtftok/rtfsprm.hxx +++ b/writerfilter/source/rtftok/rtfsprm.hxx @@ -40,6 +40,7 @@ namespace writerfilter { typedef ::boost::shared_ptr Pointer_t; typedef std::pair id_val; typedef std::vector< id_val >::iterator Iterator_t; + typedef std::vector< id_val >::reverse_iterator ReverseIterator_t; RTFSprms(); RTFSprms(const RTFSprms& rSprms); RTFSprms& operator=(const RTFSprms& rOther); @@ -51,6 +52,8 @@ namespace writerfilter { id_val& back() { return m_aSprms.back(); } Iterator_t begin() { return m_aSprms.begin(); } Iterator_t end() { return m_aSprms.end(); } + ReverseIterator_t rbegin() { return m_aSprms.rbegin(); } + ReverseIterator_t rend() { return m_aSprms.rend(); } void push_back(id_val aVal) { m_aSprms.push_back(aVal); } void clear() { return m_aSprms.clear(); } private: