sc/source/filter/excel/xestyle.cxx | 79 +++++++++++++++++++++++++++---------- sc/source/filter/inc/xestyle.hxx | 27 ++++++++++++ 2 files changed, 85 insertions(+), 21 deletions(-)
New commits: commit c0b8be4d7eb9fa1a0d8abfb1d27c71ac34bffd1b Author: Noel Grandin <noel.gran...@collabora.co.uk> AuthorDate: Fri Oct 25 08:55:51 2019 +0200 Commit: Noel Grandin <noel.gran...@collabora.co.uk> CommitDate: Fri Oct 25 11:04:59 2019 +0200 tdf#126021 speed up saving xls with lots of styles extend the find-map so we can do partial-match searching. Makes it 10x faster for me. Change-Id: I1952a221a919707af078fac9fd1eb63781d9188d Reviewed-on: https://gerrit.libreoffice.org/81488 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk> diff --git a/sc/source/filter/excel/xestyle.cxx b/sc/source/filter/excel/xestyle.cxx index 7f3ac9c25b53..7b6a3b5a5665 100644 --- a/sc/source/filter/excel/xestyle.cxx +++ b/sc/source/filter/excel/xestyle.cxx @@ -2666,24 +2666,58 @@ void XclExpXFBuffer::SaveXFXml( XclExpXmlStream& rStrm, XclExpXF& rXF ) sal_uInt32 XclExpXFBuffer::FindXF( const ScPatternAttr& rPattern, sal_uInt32 nForceScNumFmt, sal_uInt16 nForceXclFont, bool bForceLineBreak ) const { - auto it = maXFFindMap.find(&rPattern.GetItemSet()); - if (it == maXFFindMap.end()) - return EXC_XFID_NOTFOUND; - for (auto const & nPos : it->second) - if( maXFList.GetRecord( nPos )->Equals( rPattern, nForceScNumFmt, nForceXclFont, bForceLineBreak ) ) - return nPos; + if (nForceScNumFmt != NUMBERFORMAT_ENTRY_NOT_FOUND && nForceXclFont == EXC_FONT_NOTFOUND) + { + FindKey key1 { /*mbCellXF*/true, &rPattern.GetItemSet(), nForceScNumFmt, 0 }; + FindKey key2 { /*mbCellXF*/true, &rPattern.GetItemSet(), nForceScNumFmt, EXC_FONT_NOTFOUND }; + auto it1 = maXFFindMap.lower_bound(key1); + if (it1 != maXFFindMap.end()) + { + auto it2 = maXFFindMap.upper_bound(key2); + for (auto it = it1; it != it2; ++it) + for (auto const & nPos : it->second) + if( maXFList.GetRecord( nPos )->Equals( rPattern, nForceScNumFmt, nForceXclFont, bForceLineBreak ) ) + return nPos; + } + } + else if (nForceScNumFmt == NUMBERFORMAT_ENTRY_NOT_FOUND || nForceXclFont == EXC_FONT_NOTFOUND) + { + FindKey key1 { /*mbCellXF*/true, &rPattern.GetItemSet(), 0, 0 }; + FindKey key2 { /*mbCellXF*/true, &rPattern.GetItemSet(), NUMBERFORMAT_ENTRY_NOT_FOUND, EXC_FONT_NOTFOUND }; + auto it1 = maXFFindMap.lower_bound(key1); + if (it1 != maXFFindMap.end()) + { + auto it2 = maXFFindMap.upper_bound(key2); + for (auto it = it1; it != it2; ++it) + for (auto const & nPos : it->second) + if( maXFList.GetRecord( nPos )->Equals( rPattern, nForceScNumFmt, nForceXclFont, bForceLineBreak ) ) + return nPos; + } + } + else + { + FindKey key { /*mbCellXF*/true, &rPattern.GetItemSet(), nForceScNumFmt, nForceXclFont }; + auto it = maXFFindMap.find(key); + if (it == maXFFindMap.end()) + return EXC_XFID_NOTFOUND; + for (auto const & nPos : it->second) + if( maXFList.GetRecord( nPos )->Equals( rPattern, nForceScNumFmt, nForceXclFont, bForceLineBreak ) ) + return nPos; + } return EXC_XFID_NOTFOUND; } sal_uInt32 XclExpXFBuffer::FindXF( const SfxStyleSheetBase& rStyleSheet ) const { const SfxItemSet* pItemSet = &const_cast< SfxStyleSheetBase& >( rStyleSheet ).GetItemSet(); - auto it = maXFFindMap.find(pItemSet); - if (it == maXFFindMap.end()) - return EXC_XFID_NOTFOUND; - for (auto const & nPos : it->second) - if( maXFList.GetRecord( nPos )->Equals( rStyleSheet ) ) - return nPos; + FindKey key1 { /*mbCellXF*/false, pItemSet, 0, 0 }; + FindKey key2 { /*mbCellXF*/false, pItemSet, NUMBERFORMAT_ENTRY_NOT_FOUND, EXC_FONT_NOTFOUND }; + auto it1 = maXFFindMap.lower_bound(key1); + auto it2 = maXFFindMap.upper_bound(key2); + for (auto it = it1; it != it2; ++it) + for (auto const & nPos : it->second) + if( maXFList.GetRecord( nPos )->Equals( rStyleSheet ) ) + return nPos; return EXC_XFID_NOTFOUND; } @@ -2698,6 +2732,11 @@ sal_uInt32 XclExpXFBuffer::FindBuiltInXF( sal_uInt8 nStyleId, sal_uInt8 nLevel ) return EXC_XFID_NOTFOUND; } +XclExpXFBuffer::FindKey XclExpXFBuffer::ToFindKey(XclExpXF const & rRec) +{ + return { rRec.IsCellXF(), rRec.GetItemSet(), rRec.GetScNumFmt(), rRec.GetXclFont() }; +} + sal_uInt32 XclExpXFBuffer::InsertCellXF( const ScPatternAttr* pPattern, sal_Int16 nScript, sal_uInt32 nForceScNumFmt, sal_uInt16 nForceXclFont, bool bForceLineBreak ) { @@ -2715,14 +2754,14 @@ sal_uInt32 XclExpXFBuffer::InsertCellXF( const ScPatternAttr* pPattern, sal_Int1 if( rbPredefined ) { // remove old entry in find-map - auto & rPositions = maXFFindMap[maXFList.GetRecord(EXC_XF_DEFAULTCELL)->GetItemSet()]; + auto & rPositions = maXFFindMap[ToFindKey(*maXFList.GetRecord(EXC_XF_DEFAULTCELL))]; auto it = std::find(rPositions.begin(), rPositions.end(), EXC_XF_DEFAULTCELL); rPositions.erase(it); // replace default cell pattern XclExpXFRef xNewXF( new XclExpXF( GetRoot(), *pPattern, nScript ) ); maXFList.ReplaceRecord( xNewXF, EXC_XF_DEFAULTCELL ); // and add new entry in find-map - maXFFindMap[xNewXF->GetItemSet()].push_back(EXC_XF_DEFAULTCELL); + maXFFindMap[ToFindKey(*xNewXF)].push_back(EXC_XF_DEFAULTCELL); rbPredefined = false; } return GetDefCellXFId(); @@ -2739,7 +2778,7 @@ sal_uInt32 XclExpXFBuffer::InsertCellXF( const ScPatternAttr* pPattern, sal_Int1 maXFList.AppendNewRecord( pNewExp ); // do not set nXFId before the AppendNewRecord() call - it may insert 2 XFs (style+cell) nXFId = static_cast< sal_uInt32 >( maXFList.GetSize() - 1 ); - maXFFindMap[pNewExp->GetItemSet()].push_back(nXFId); + maXFFindMap[ToFindKey(*pNewExp)].push_back(nXFId); } else { @@ -2775,14 +2814,14 @@ sal_uInt32 XclExpXFBuffer::InsertStyleXF( const SfxStyleSheetBase& rStyleSheet ) if( rbPredefined ) { // remove old entry in find-map - auto & rPositions = maXFFindMap[maXFList.GetRecord(nXFId)->GetItemSet()]; + auto & rPositions = maXFFindMap[ToFindKey(*maXFList.GetRecord(nXFId))]; auto it = std::find(rPositions.begin(), rPositions.end(), nXFId); rPositions.erase(it); // replace predefined built-in style (ReplaceRecord() deletes old record) auto pNewExp = std::make_shared<XclExpXF>( GetRoot(), rStyleSheet ); maXFList.ReplaceRecord( pNewExp, nXFId ); // and add new entry in find-map - maXFFindMap[pNewExp->GetItemSet()].push_back(nXFId); + maXFFindMap[ToFindKey(*pNewExp)].push_back(nXFId); rbPredefined = false; } } @@ -2812,7 +2851,7 @@ sal_uInt32 XclExpXFBuffer::InsertStyleXF( const SfxStyleSheetBase& rStyleSheet ) // create the STYLE record if( !rStyleSheet.GetName().isEmpty() ) maStyleList.AppendNewRecord( new XclExpStyle( nXFId, rStyleSheet.GetName() ) ); - maXFFindMap[pNewExp->GetItemSet()].push_back(nXFId); + maXFFindMap[ToFindKey(*pNewExp)].push_back(nXFId); } else // list full - fall back to default style XF @@ -2833,7 +2872,7 @@ sal_uInt32 XclExpXFBuffer::AppendBuiltInXF( XclExpXFRef const & xXF, sal_uInt8 n { sal_uInt32 nXFId = static_cast< sal_uInt32 >( maXFList.GetSize() ); maXFList.AppendRecord( xXF ); - maXFFindMap[xXF->GetItemSet()].push_back(nXFId); + maXFFindMap[ToFindKey(*xXF)].push_back(nXFId); XclExpBuiltInInfo& rInfo = maBuiltInMap[ nXFId ]; rInfo.mnStyleId = nStyleId; rInfo.mnLevel = nLevel; @@ -2906,7 +2945,7 @@ void XclExpXFBuffer::InsertDefaultRecords() // index 15: default hard cell format, placeholder to be able to add more built-in styles maXFList.AppendNewRecord( new XclExpDefaultXF( GetRoot(), true ) ); - maXFFindMap[maXFList.GetRecord(maXFList.GetSize()-1)->GetItemSet()].push_back(maXFList.GetSize()-1); + maXFFindMap[ToFindKey(*maXFList.GetRecord(maXFList.GetSize()-1))].push_back(maXFList.GetSize()-1); maBuiltInMap[ EXC_XF_DEFAULTCELL ].mbPredefined = true; // index 16-20: other built-in styles diff --git a/sc/source/filter/inc/xestyle.hxx b/sc/source/filter/inc/xestyle.hxx index 48b1e53f4fa2..ae960530e80c 100644 --- a/sc/source/filter/inc/xestyle.hxx +++ b/sc/source/filter/inc/xestyle.hxx @@ -30,6 +30,7 @@ #include <fonthelper.hxx> #include <memory> #include <vector> +#include <o3tl/sorted_vector.hxx> /* ============================================================================ - Buffers for style records (PALETTE, FONT, FORMAT, XF, STYLE). @@ -470,6 +471,9 @@ public: const SfxItemSet* GetItemSet() const { return mpItemSet; } + sal_uInt32 GetScNumFmt() const { return mnScNumFmt; } + sal_uInt16 GetXclFont() const { return mnXclFont; } + protected: explicit XclExpXF( const XclExpRoot& rRoot, bool bCellXF ); @@ -681,8 +685,29 @@ private: typedef ::std::vector< XclExpCellBorder > XclExpBorderList; typedef ::std::vector< XclExpCellArea > XclExpFillList; + /** composite key for the find-map, so we can do partial key searching */ + struct FindKey + { + bool mbCellXF; // is this a hard cell format, or a cell style + const SfxItemSet* mpItemSet; + sal_uInt32 mnScNumFmt; + sal_uInt16 mnXclFont; + + bool operator<(const FindKey& other) const + { + if (mbCellXF != other.mbCellXF) + return mbCellXF < other.mbCellXF; + if (mpItemSet != other.mpItemSet) + return mpItemSet < other.mpItemSet; + if (mnScNumFmt != other.mnScNumFmt) + return mnScNumFmt < other.mnScNumFmt; + return mnXclFont < other.mnXclFont; + } + }; + static FindKey ToFindKey(XclExpXF const &); + XclExpXFList maXFList; /// List of all XF records. - std::unordered_map<const SfxItemSet*, std::vector<sal_uInt32>> + std::map<FindKey, std::vector<sal_uInt32>> maXFFindMap; /// map of itemset to vector of positions, to speed up find XclExpStyleList maStyleList; /// List of all STYLE records. XclExpBuiltInMap maBuiltInMap; /// Contained elements describe built-in XFs. _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits