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

Reply via email to