sc/source/filter/inc/workbookhelper.hxx | 48 +++++++++++++++ sc/source/filter/oox/stylesbuffer.cxx | 97 +++++++++++++++++++------------- sc/source/filter/oox/workbookhelper.cxx | 8 ++ 3 files changed, 115 insertions(+), 38 deletions(-)
New commits: commit bf2734bbe3c35b0ecbf1a24a77824ffd61a71f3f Author: Caolán McNamara <caolan.mcnam...@collabora.com> AuthorDate: Thu Aug 10 21:49:59 2023 +0100 Commit: Noel Grandin <noel.gran...@collabora.co.uk> CommitDate: Sat Aug 12 22:00:09 2023 +0200 xlsx with a lot of comments repeatedly calls OutputDevice::HasGlyphs on the same font over and over again getting the same results Change-Id: I0c301e3fd4c1838645c25d4f6f7b330acc988135 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/155569 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> (cherry picked from commit e3caea16a9a1ac6749f38cfdbf463184f64e64df) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/155592 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk> diff --git a/sc/source/filter/inc/workbookhelper.hxx b/sc/source/filter/inc/workbookhelper.hxx index 0234c50252ff..ba046e40dab9 100644 --- a/sc/source/filter/inc/workbookhelper.hxx +++ b/sc/source/filter/inc/workbookhelper.hxx @@ -21,10 +21,14 @@ #include <memory> #include <string_view> +#include <unordered_map> +#include <o3tl/hash_combine.hxx> #include <oox/helper/storagebase.hxx> #include <address.hxx> +#include <com/sun/star/awt/FontDescriptor.hpp> + namespace oox::drawingml::chart { class ChartConverter; } namespace rtl { template <class reference_type> class Reference; } @@ -57,6 +61,22 @@ class ScRangeData; namespace oox::xls { +enum class FontClassification : sal_uInt8 +{ + None = 0x0000, + Asian = 0x0001, + Cmplx = 0x0002, + Latin = 0x0004 +}; + +} + +namespace o3tl { + template<> struct typed_flags<oox::xls::FontClassification> : is_typed_flags<oox::xls::FontClassification, 0x07> {}; +} + +namespace oox::xls { + class ExcelFilter; /** Functor for case-insensitive string comparison, usable in maps etc. */ @@ -87,6 +107,32 @@ class FormulaBuffer; class WorkbookGlobals; typedef std::shared_ptr< WorkbookGlobals > WorkbookGlobalsRef; +struct FontDescriptorHash +{ + size_t operator()( const css::awt::FontDescriptor& rKey) const + { + std::size_t seed = rKey.Name.hashCode(); + o3tl::hash_combine(seed, rKey.Height); + o3tl::hash_combine(seed, rKey.Width); + o3tl::hash_combine(seed, rKey.StyleName.hashCode()); + o3tl::hash_combine(seed, rKey.Family); + o3tl::hash_combine(seed, rKey.CharSet); + o3tl::hash_combine(seed, rKey.Pitch); + o3tl::hash_combine(seed, rKey.CharacterWidth); + o3tl::hash_combine(seed, rKey.Weight); + o3tl::hash_combine(seed, rKey.Slant); + o3tl::hash_combine(seed, rKey.Underline); + o3tl::hash_combine(seed, rKey.Strikeout); + o3tl::hash_combine(seed, rKey.Orientation); + o3tl::hash_combine(seed, rKey.Kerning); + o3tl::hash_combine(seed, rKey.WordLineMode); + o3tl::hash_combine(seed, rKey.Type); + return seed; + } +}; + +typedef std::unordered_map<css::awt::FontDescriptor, FontClassification, FontDescriptorHash> FontClassificationMap; + /** Helper class to provide access to global workbook data. All classes derived from this helper class will have access to a singleton @@ -233,6 +279,8 @@ public: PivotCacheBuffer& getPivotCaches() const; /** Returns the collection of pivot tables. */ PivotTableBuffer& getPivotTables() const; + /** Shared cache of Font Classifications to avoid repeated lookups */ + FontClassificationMap& getFontClassificationCache() const; // converters ------------------------------------------------------------- diff --git a/sc/source/filter/oox/stylesbuffer.cxx b/sc/source/filter/oox/stylesbuffer.cxx index e0c99ccb7a65..47dd75f34425 100644 --- a/sc/source/filter/oox/stylesbuffer.cxx +++ b/sc/source/filter/oox/stylesbuffer.cxx @@ -790,44 +790,65 @@ void Font::finalizeImport() if( !maUsedFlags.mbNameUsed ) return; - PropertySet aDocProps( getDocument() ); - Reference< XDevice > xDevice( aDocProps.getAnyProperty( PROP_ReferenceDevice ), UNO_QUERY ); - if( !xDevice.is() ) - return; - - Reference< XFont2 > xFont( xDevice->getFont( maApiData.maDesc ), UNO_QUERY ); - if( !xFont.is() ) - return; - - // #91658# CJK fonts - bool bHasAsian = - xFont->hasGlyphs( OUString( u'\x3041' ) ) || // 3040-309F: Hiragana - xFont->hasGlyphs( OUString( u'\x30A1' ) ) || // 30A0-30FF: Katakana - xFont->hasGlyphs( OUString( u'\x3111' ) ) || // 3100-312F: Bopomofo - xFont->hasGlyphs( OUString( u'\x3131' ) ) || // 3130-318F: Hangul Compatibility Jamo - xFont->hasGlyphs( OUString( u'\x3301' ) ) || // 3300-33FF: CJK Compatibility - xFont->hasGlyphs( OUString( u'\x3401' ) ) || // 3400-4DBF: CJK Unified Ideographs Extension A - xFont->hasGlyphs( OUString( u'\x4E01' ) ) || // 4E00-9FFF: CJK Unified Ideographs - xFont->hasGlyphs( OUString( u'\x7E01' ) ) || // 4E00-9FFF: CJK Unified Ideographs - xFont->hasGlyphs( OUString( u'\xA001' ) ) || // A001-A48F: Yi Syllables - xFont->hasGlyphs( OUString( u'\xAC01' ) ) || // AC00-D7AF: Hangul Syllables - xFont->hasGlyphs( OUString( u'\xCC01' ) ) || // AC00-D7AF: Hangul Syllables - xFont->hasGlyphs( OUString( u'\xF901' ) ) || // F900-FAFF: CJK Compatibility Ideographs - xFont->hasGlyphs( OUString( u'\xFF71' ) ); // FF00-FFEF: Halfwidth/Fullwidth Forms - // #113783# CTL fonts - bool bHasCmplx = - xFont->hasGlyphs( OUString( u'\x05D1' ) ) || // 0590-05FF: Hebrew - xFont->hasGlyphs( OUString( u'\x0631' ) ) || // 0600-06FF: Arabic - xFont->hasGlyphs( OUString( u'\x0721' ) ) || // 0700-074F: Syriac - xFont->hasGlyphs( OUString( u'\x0911' ) ) || // 0900-0DFF: Indic scripts - xFont->hasGlyphs( OUString( u'\x0E01' ) ) || // 0E00-0E7F: Thai - xFont->hasGlyphs( OUString( u'\xFB21' ) ) || // FB1D-FB4F: Hebrew Presentation Forms - xFont->hasGlyphs( OUString( u'\xFB51' ) ) || // FB50-FDFF: Arabic Presentation Forms-A - xFont->hasGlyphs( OUString( u'\xFE71' ) ); // FE70-FEFF: Arabic Presentation Forms-B - // Western fonts - bool bHasLatin = - (!bHasAsian && !bHasCmplx) || - xFont->hasGlyphs( OUString( 'A' ) ); + bool bHasAsian(false), bHasCmplx(false), bHasLatin(false); + FontClassificationMap& rFontClassificationCache = getFontClassificationCache(); + if (auto found = rFontClassificationCache.find(maApiData.maDesc); found != rFontClassificationCache.end()) + { + FontClassification eClassification = found->second; + bHasAsian = bool(eClassification & FontClassification::Asian); + bHasCmplx = bool(eClassification & FontClassification::Cmplx); + bHasLatin = bool(eClassification & FontClassification::Latin); + } + else + { + PropertySet aDocProps( getDocument() ); + Reference< XDevice > xDevice( aDocProps.getAnyProperty( PROP_ReferenceDevice ), UNO_QUERY ); + if( !xDevice.is() ) + return; + + Reference< XFont2 > xFont( xDevice->getFont( maApiData.maDesc ), UNO_QUERY ); + if( !xFont.is() ) + return; + + // #91658# CJK fonts + bHasAsian = + xFont->hasGlyphs( OUString( u'\x3041' ) ) || // 3040-309F: Hiragana + xFont->hasGlyphs( OUString( u'\x30A1' ) ) || // 30A0-30FF: Katakana + xFont->hasGlyphs( OUString( u'\x3111' ) ) || // 3100-312F: Bopomofo + xFont->hasGlyphs( OUString( u'\x3131' ) ) || // 3130-318F: Hangul Compatibility Jamo + xFont->hasGlyphs( OUString( u'\x3301' ) ) || // 3300-33FF: CJK Compatibility + xFont->hasGlyphs( OUString( u'\x3401' ) ) || // 3400-4DBF: CJK Unified Ideographs Extension A + xFont->hasGlyphs( OUString( u'\x4E01' ) ) || // 4E00-9FFF: CJK Unified Ideographs + xFont->hasGlyphs( OUString( u'\x7E01' ) ) || // 4E00-9FFF: CJK Unified Ideographs + xFont->hasGlyphs( OUString( u'\xA001' ) ) || // A001-A48F: Yi Syllables + xFont->hasGlyphs( OUString( u'\xAC01' ) ) || // AC00-D7AF: Hangul Syllables + xFont->hasGlyphs( OUString( u'\xCC01' ) ) || // AC00-D7AF: Hangul Syllables + xFont->hasGlyphs( OUString( u'\xF901' ) ) || // F900-FAFF: CJK Compatibility Ideographs + xFont->hasGlyphs( OUString( u'\xFF71' ) ); // FF00-FFEF: Halfwidth/Fullwidth Forms + // #113783# CTL fonts + bHasCmplx = + xFont->hasGlyphs( OUString( u'\x05D1' ) ) || // 0590-05FF: Hebrew + xFont->hasGlyphs( OUString( u'\x0631' ) ) || // 0600-06FF: Arabic + xFont->hasGlyphs( OUString( u'\x0721' ) ) || // 0700-074F: Syriac + xFont->hasGlyphs( OUString( u'\x0911' ) ) || // 0900-0DFF: Indic scripts + xFont->hasGlyphs( OUString( u'\x0E01' ) ) || // 0E00-0E7F: Thai + xFont->hasGlyphs( OUString( u'\xFB21' ) ) || // FB1D-FB4F: Hebrew Presentation Forms + xFont->hasGlyphs( OUString( u'\xFB51' ) ) || // FB50-FDFF: Arabic Presentation Forms-A + xFont->hasGlyphs( OUString( u'\xFE71' ) ); // FE70-FEFF: Arabic Presentation Forms-B + // Western fonts + bHasLatin = + (!bHasAsian && !bHasCmplx) || + xFont->hasGlyphs( OUString( 'A' ) ); + + FontClassification eClassification(FontClassification::None); + if (bHasAsian) + eClassification = eClassification | FontClassification::Asian; + if (bHasCmplx) + eClassification = eClassification | FontClassification::Cmplx; + if (bHasLatin) + eClassification = eClassification | FontClassification::Latin; + rFontClassificationCache.emplace(maApiData.maDesc, eClassification); + } lclSetFontName( maApiData.maLatinFont, maApiData.maDesc, bHasLatin ); lclSetFontName( maApiData.maAsianFont, maApiData.maDesc, bHasAsian ); diff --git a/sc/source/filter/oox/workbookhelper.cxx b/sc/source/filter/oox/workbookhelper.cxx index 5d9e80447bc7..c5552f9fb5a3 100644 --- a/sc/source/filter/oox/workbookhelper.cxx +++ b/sc/source/filter/oox/workbookhelper.cxx @@ -193,6 +193,8 @@ public: PivotCacheBuffer& getPivotCaches() const { return *mxPivotCaches; } /** Returns the collection of pivot tables. */ PivotTableBuffer& getPivotTables() { return *mxPivotTables; } + /** Shared cache of Font Classifications to avoid repeated lookups */ + FontClassificationMap& getFontClassificationCache() { return maFontClassificationMap; } // converters ------------------------------------------------------------- @@ -275,6 +277,7 @@ private: ConnectionsBfrPtr mxConnections; /// All external data connections. PivotCacheBfrPtr mxPivotCaches; /// All pivot caches in the document. PivotTableBfrPtr mxPivotTables; /// All pivot tables in the document. + FontClassificationMap maFontClassificationMap; /// Shared to avoid repeated lookups // converters FormulaParserPtr mxFmlaParser; /// Import formula parser. @@ -970,6 +973,11 @@ PivotTableBuffer& WorkbookHelper::getPivotTables() const return mrBookGlob.getPivotTables(); } +FontClassificationMap& WorkbookHelper::getFontClassificationCache() const +{ + return mrBookGlob.getFontClassificationCache(); +} + // converters ----------------------------------------------------------------- FormulaParser& WorkbookHelper::getFormulaParser() const