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;