include/o3tl/hash_combine.hxx |   22 ++++++++++++++++++++++
 sc/source/ui/view/output2.cxx |   40 ++++++++++++++++++++++++++++++++++++----
 2 files changed, 58 insertions(+), 4 deletions(-)

New commits:
commit c9f688d64ae8e33f46e35f185b9a402f489bf911
Author:     Luboš Luňák <l.lu...@collabora.com>
AuthorDate: Tue Oct 19 11:56:15 2021 +0200
Commit:     Adolfo Jayme Barrientos <fit...@ubuntu.com>
CommitDate: Wed Oct 20 07:33:31 2021 +0200

    consider font when caching SalLayoutGlyphs in calc (tdf#143978)
    
    d62ad3efe3c8778cfd added the caching, but did not consider that
    the used OutputDevice (its font) may change.
    
    Backport to 7.2 includes o3tl::hash_combine() from bb5425ed3d8cc04.
    
    Change-Id: I291999d3613b7ba161e3d82348f621aa84a93067
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/123809
    Tested-by: Jenkins
    Reviewed-by: Luboš Luňák <l.lu...@collabora.com>
    (cherry picked from commit 6ee4ce119b55d6e415696b23432fe65eabc94c17)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/123783
    Reviewed-by: Adolfo Jayme Barrientos <fit...@ubuntu.com>

diff --git a/include/o3tl/hash_combine.hxx b/include/o3tl/hash_combine.hxx
index 17419b3e2c0f..f1dba031f5a1 100644
--- a/include/o3tl/hash_combine.hxx
+++ b/include/o3tl/hash_combine.hxx
@@ -24,6 +24,28 @@ inline void hash_combine(N& nSeed, T const& nValue)
     static_assert(sizeof(nSeed) == 8);
     nSeed ^= std::hash<T>{}(nValue) + 0x9E3779B97F4A7C15llu + (nSeed << 12) + 
(nSeed >> 4);
 }
+
+template <typename T, typename N>
+inline std::enable_if_t<(sizeof(N) == 4)> hash_combine(N& nSeed, T const* 
pValue, size_t nCount)
+{
+    static_assert(sizeof(nSeed) == 4);
+    for (size_t i = 0; i < nCount; ++i)
+    {
+        nSeed ^= std::hash<T>{}(*pValue) + 0x9E3779B9u + (nSeed << 6) + (nSeed 
>> 2);
+        ++pValue;
+    }
+}
+
+template <typename T, typename N>
+inline std::enable_if_t<(sizeof(N) == 8)> hash_combine(N& nSeed, T const* 
pValue, size_t nCount)
+{
+    static_assert(sizeof(nSeed) == 8);
+    for (size_t i = 0; i < nCount; ++i)
+    {
+        nSeed ^= std::hash<T>{}(*pValue) + 0x9E3779B97F4A7C15llu + (nSeed << 
12) + (nSeed >> 4);
+        ++pValue;
+    }
+}
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/sc/source/ui/view/output2.cxx b/sc/source/ui/view/output2.cxx
index 2d45fa62eaa7..2685cfe10fb6 100644
--- a/sc/source/ui/view/output2.cxx
+++ b/sc/source/ui/view/output2.cxx
@@ -56,6 +56,7 @@
 #include <sal/log.hxx>
 #include <unotools/charclass.hxx>
 #include <osl/diagnose.h>
+#include <tools/stream.hxx>
 
 #include <output.hxx>
 #include <document.hxx>
@@ -77,6 +78,7 @@
 #include <memory>
 #include <vector>
 #include <o3tl/lru_map.hxx>
+#include <o3tl/hash_combine.hxx>
 
 #include <math.h>
 
@@ -116,7 +118,19 @@ class ScDrawStringsVars
     tools::Long                nExpWidth;
 
     ScRefCellValue      maLastCell;
-    mutable o3tl::lru_map<OUString, SalLayoutGlyphs> mCachedGlyphs;
+    struct CachedGlyphsKey
+    {
+        OUString text;
+        VclPtr<OutputDevice> outputDevice;
+        size_t hashValue;
+        CachedGlyphsKey( const OUString& t, const VclPtr<OutputDevice>& dev );
+        bool operator==( const CachedGlyphsKey& other ) const;
+    };
+    struct CachedGlyphsHash
+    {
+        size_t operator()( const CachedGlyphsKey& key ) const { return 
key.hashValue; }
+    };
+    mutable o3tl::lru_map<CachedGlyphsKey, SalLayoutGlyphs, CachedGlyphsHash> 
mCachedGlyphs;
     sal_uLong           nValueFormat;
     bool                bLineBreak;
     bool                bRepeat;
@@ -772,17 +786,35 @@ tools::Long ScDrawStringsVars::GetExpWidth()
     return nExpWidth;
 }
 
+inline ScDrawStringsVars::CachedGlyphsKey::CachedGlyphsKey( const OUString& t, 
const VclPtr<OutputDevice>& d )
+    : text( t )
+    , outputDevice( d )
+{
+    hashValue = 0;
+    o3tl::hash_combine( hashValue, outputDevice.get());
+    SvMemoryStream stream;
+    WriteFont( stream, outputDevice->GetFont());
+    o3tl::hash_combine( hashValue, static_cast<const char*>(stream.GetData()), 
stream.GetSize());
+    o3tl::hash_combine( hashValue, text );
+}
+
+inline bool ScDrawStringsVars::CachedGlyphsKey::operator==( const 
CachedGlyphsKey& other ) const
+{
+    return hashValue == other.hashValue && outputDevice == other.outputDevice 
&& text == other.text;
+}
+
 const SalLayoutGlyphs* ScDrawStringsVars::GetLayoutGlyphs(const OUString& 
rString) const
 {
-    auto it = mCachedGlyphs.find( rString );
+    const CachedGlyphsKey key( rString, pOutput->pFmtDevice );
+    auto it = mCachedGlyphs.find( key );
     if( it != mCachedGlyphs.end() && it->second.IsValid())
         return &it->second;
     std::unique_ptr<SalLayout> layout = pOutput->pFmtDevice->ImplLayout( 
rString, 0, rString.getLength(),
         Point( 0, 0 ), 0, nullptr, SalLayoutFlags::GlyphItemsOnly );
     if( layout )
     {
-        mCachedGlyphs.insert( std::make_pair( rString, layout->GetGlyphs()));
-        assert(mCachedGlyphs.find( rString ) == mCachedGlyphs.begin()); // 
newly inserted item is first
+        mCachedGlyphs.insert( std::make_pair( key, layout->GetGlyphs()));
+        assert(mCachedGlyphs.find( key ) == mCachedGlyphs.begin()); // newly 
inserted item is first
         return &mCachedGlyphs.begin()->second;
     }
     return nullptr;

Reply via email to