summaryrefslogtreecommitdiff
path: root/writerfilter
diff options
context:
space:
mode:
authorCaolán McNamara <caolanm@redhat.com>2012-05-30 13:12:15 +0100
committerCaolán McNamara <caolanm@redhat.com>2012-05-30 13:16:27 +0100
commit651d045cddf8fd238999cb3442e87410f1a8e1df (patch)
tree4052f1769c242478c50c067d9859bdd57db4702f /writerfilter
parent48e74fb6d384aa47fd57d97e781ea8857c81bf18 (diff)
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
Diffstat (limited to 'writerfilter')
-rw-r--r--writerfilter/source/rtftok/rtfdocumentimpl.cxx62
-rw-r--r--writerfilter/source/rtftok/rtfsprm.hxx3
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<RTFSprms> Pointer_t;
typedef std::pair<Id, RTFValue::Pointer_t> 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: