include/vcl/glyphitemcache.hxx  |   69 ++++++++++++++++++++++++++++++++++++++++
 sc/source/ui/view/output2.cxx   |   55 +++----------------------------
 vcl/source/gdi/impglyphitem.cxx |   46 ++++++++++++++++++++++++++
 3 files changed, 121 insertions(+), 49 deletions(-)

New commits:
commit 89fb3f7e87fd7ab9312bc43dffea842ffc34b140
Author:     Luboš Luňák <l.lu...@collabora.com>
AuthorDate: Fri Mar 11 17:48:41 2022 +0100
Commit:     Luboš Luňák <l.lu...@collabora.com>
CommitDate: Mon Mar 14 08:38:09 2022 +0100

    cache also failures in SalLayoutGlyphsCache
    
    This is what 3f69ec9ab4236de13d229f675943123aeb42ea29 did in Writer.
    
    Change-Id: I40fb49ce83fd24f16050318c523d87603300b06d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131392
    Tested-by: Jenkins
    Reviewed-by: Luboš Luňák <l.lu...@collabora.com>

diff --git a/vcl/source/gdi/impglyphitem.cxx b/vcl/source/gdi/impglyphitem.cxx
index 0d8c2241a21e..1fefe68994d2 100644
--- a/vcl/source/gdi/impglyphitem.cxx
+++ b/vcl/source/gdi/impglyphitem.cxx
@@ -99,8 +99,15 @@ SalLayoutGlyphsCache::GetLayoutGlyphs(const OUString& text, 
VclPtr<OutputDevice>
 {
     const CachedGlyphsKey key(text, outputDevice);
     auto it = mCachedGlyphs.find(key);
-    if (it != mCachedGlyphs.end() && it->second.IsValid())
-        return &it->second;
+    if (it != mCachedGlyphs.end())
+    {
+        if (it->second.IsValid())
+            return &it->second;
+        // Do not try to create the layout here. If a cache item exists, it's 
already
+        // been attempted and the layout was invalid (this happens with 
MultiSalLayout).
+        // So in that case this is a cached failure.
+        return nullptr;
+    }
     std::unique_ptr<SalLayout> layout = outputDevice->ImplLayout(
         text, 0, text.getLength(), Point(0, 0), 0, {}, 
SalLayoutFlags::GlyphItemsOnly);
     if (layout)
commit 3e3ef58be1c27e0ac32b0b5694f673f603d23224
Author:     Luboš Luňák <l.lu...@collabora.com>
AuthorDate: Fri Mar 11 17:47:40 2022 +0100
Commit:     Luboš Luňák <l.lu...@collabora.com>
CommitDate: Mon Mar 14 08:37:53 2022 +0100

    move cache for SalLayoutGlyph's from Calc to VCL
    
    For reuse later.
    
    Change-Id: I43479148a8312a36e56f267435e77acc8bf9bd35
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131390
    Tested-by: Jenkins
    Reviewed-by: Luboš Luňák <l.lu...@collabora.com>

diff --git a/include/vcl/glyphitemcache.hxx b/include/vcl/glyphitemcache.hxx
new file mode 100644
index 000000000000..8afc8da0bae6
--- /dev/null
+++ b/include/vcl/glyphitemcache.hxx
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_VCL_GLYPHITEMCACHE_HXX
+#define INCLUDED_VCL_GLYPHITEMCACHE_HXX
+
+#include <sal/types.h>
+#include <vcl/dllapi.h>
+
+#include <o3tl/lru_map.hxx>
+#include <o3tl/hash_combine.hxx>
+#include <vcl/glyphitem.hxx>
+
+/**
+A cache for SalLayoutGlyphs objects.
+
+Allows caching for OutputDevice::DrawText() and similar calls. Pass the text 
and the output device
+for the call to OutputDevice::ImplLayout(). Items are cached per output device 
and its font.
+If something more changes, call clear().
+*/
+class VCL_DLLPUBLIC SalLayoutGlyphsCache final
+{
+public:
+    SalLayoutGlyphsCache(int size = 1000)
+        : mCachedGlyphs(size)
+    {
+    }
+    const SalLayoutGlyphs* GetLayoutGlyphs(const OUString& text,
+                                           VclPtr<OutputDevice> outputDevice) 
const;
+    void clear() { mCachedGlyphs.clear(); }
+
+private:
+    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;
+
+    SalLayoutGlyphsCache(const SalLayoutGlyphsCache&) = delete;
+    SalLayoutGlyphsCache& operator=(const SalLayoutGlyphsCache&) = delete;
+};
+
+#endif // INCLUDED_VCL_GLYPHITEMCACHE_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/view/output2.cxx b/sc/source/ui/view/output2.cxx
index ab8e08c9d06f..0c394b0f7945 100644
--- a/sc/source/ui/view/output2.cxx
+++ b/sc/source/ui/view/output2.cxx
@@ -54,6 +54,7 @@
 #include <vcl/settings.hxx>
 #include <vcl/glyphitem.hxx>
 #include <vcl/vcllayout.hxx>
+#include <vcl/glyphitemcache.hxx>
 #include <sal/log.hxx>
 #include <unotools/charclass.hxx>
 #include <osl/diagnose.h>
@@ -120,19 +121,7 @@ class ScDrawStringsVars
     tools::Long                nExpWidth;
 
     ScRefCellValue      maLastCell;
-    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;
+    mutable SalLayoutGlyphsCache mCachedGlyphs;
     sal_uLong           nValueFormat;
     bool                bLineBreak;
     bool                bRepeat;
@@ -198,7 +187,10 @@ public:
 
     // ScOutputData::LayoutStrings() usually triggers a number of calls that 
require
     // to lay out the text, which is relatively slow, so cache that operation.
-    const SalLayoutGlyphs*  GetLayoutGlyphs(const OUString& rString) const;
+    const SalLayoutGlyphs*  GetLayoutGlyphs(const OUString& rString) const
+    {
+        return mCachedGlyphs.GetLayoutGlyphs(rString, pOutput->pFmtDevice);
+    }
 
 private:
     tools::Long        GetMaxDigitWidth();     // in logic units
@@ -225,7 +217,6 @@ ScDrawStringsVars::ScDrawStringsVars(ScOutputData* pData, 
bool bPTL) :
     nSignWidth( 0 ),
     nDotWidth( 0 ),
     nExpWidth( 0 ),
-    mCachedGlyphs( 1000 ),
     nValueFormat( 0 ),
     bLineBreak  ( false ),
     bRepeat     ( false ),
@@ -787,40 +778,6 @@ 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
-{
-    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, {}, SalLayoutFlags::GlyphItemsOnly );
-    if( layout )
-    {
-        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;
-}
-
 tools::Long ScDrawStringsVars::GetFmtTextWidth( const OUString& rString )
 {
     return pOutput->pFmtDevice->GetTextWidth( rString, 0, -1, nullptr, 
GetLayoutGlyphs( rString ));
diff --git a/vcl/source/gdi/impglyphitem.cxx b/vcl/source/gdi/impglyphitem.cxx
index 5464754bab56..0d8c2241a21e 100644
--- a/vcl/source/gdi/impglyphitem.cxx
+++ b/vcl/source/gdi/impglyphitem.cxx
@@ -18,6 +18,9 @@
  */
 
 #include <impglyphitem.hxx>
+#include <vcl/glyphitemcache.hxx>
+#include <vcl/vcllayout.hxx>
+#include <tools/stream.hxx>
 
 SalLayoutGlyphs::SalLayoutGlyphs() {}
 
@@ -91,4 +94,40 @@ bool SalLayoutGlyphsImpl::IsValid() const
     return true;
 }
 
+const SalLayoutGlyphs*
+SalLayoutGlyphsCache::GetLayoutGlyphs(const OUString& text, 
VclPtr<OutputDevice> outputDevice) const
+{
+    const CachedGlyphsKey key(text, outputDevice);
+    auto it = mCachedGlyphs.find(key);
+    if (it != mCachedGlyphs.end() && it->second.IsValid())
+        return &it->second;
+    std::unique_ptr<SalLayout> layout = outputDevice->ImplLayout(
+        text, 0, text.getLength(), Point(0, 0), 0, {}, 
SalLayoutFlags::GlyphItemsOnly);
+    if (layout)
+    {
+        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;
+}
+
+SalLayoutGlyphsCache::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 SalLayoutGlyphsCache::CachedGlyphsKey::operator==(const 
CachedGlyphsKey& other) const
+{
+    return hashValue == other.hashValue && outputDevice == other.outputDevice 
&& text == other.text;
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Reply via email to