summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuboš Luňák <l.lunak@collabora.com>2022-03-14 15:55:00 +0100
committerLuboš Luňák <l.lunak@collabora.com>2022-03-15 14:35:54 +0100
commitb2f0da51e36ae65d304881967605700ecee59575 (patch)
treed0bab1befdfc83b174d8d0318fe5e400eb04152b
parent3cc41346f5529026d7d38f2863ae3d84948e6ab7 (diff)
make CreateTextLayoutCache() cached (tdf#116400)
The result depends only on the string, so it's possible to cache it easily, and caching this for text drawing calls can have a good hit rate. Change-Id: I56c6e254cc176ab07afe0df24ed37b19579fe64d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131556 Tested-by: Jenkins Reviewed-by: Luboš Luňák <l.lunak@collabora.com>
-rw-r--r--include/vcl/outdev.hxx2
-rw-r--r--sw/source/core/text/inftxt.hxx8
-rw-r--r--sw/source/core/text/porfld.cxx2
-rw-r--r--sw/source/core/text/pormulti.cxx2
-rw-r--r--vcl/inc/sallayout.hxx2
-rw-r--r--vcl/source/gdi/CommonSalLayout.cxx31
-rw-r--r--vcl/source/outdev/text.cxx2
7 files changed, 38 insertions, 11 deletions
diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx
index fe1d9583e2ba..e1f85ad16fc7 100644
--- a/include/vcl/outdev.hxx
+++ b/include/vcl/outdev.hxx
@@ -1075,7 +1075,7 @@ public:
sal_Int32 nIndex, sal_Int32 nLen,
tools::Long nCharExtra,
vcl::text::TextLayoutCache const* = nullptr) const;
- static std::shared_ptr<vcl::text::TextLayoutCache> CreateTextLayoutCache(OUString const&);
+ static std::shared_ptr<const vcl::text::TextLayoutCache> CreateTextLayoutCache(OUString const&);
protected:
SAL_DLLPRIVATE void ImplInitTextLineSize();
diff --git a/sw/source/core/text/inftxt.hxx b/sw/source/core/text/inftxt.hxx
index 9ee658364355..7c7bf57afa56 100644
--- a/sw/source/core/text/inftxt.hxx
+++ b/sw/source/core/text/inftxt.hxx
@@ -145,7 +145,7 @@ protected:
// performance hack - this is only used by SwTextFormatInfo but
// because it's not even possible to dynamic_cast these things
// currently it has to be stored here
- std::shared_ptr<vcl::text::TextLayoutCache> m_pCachedVclData;
+ std::shared_ptr<const vcl::text::TextLayoutCache> m_pCachedVclData;
SwFont *m_pFnt;
SwUnderlineFont *m_pUnderFnt; // Font for underlining
@@ -325,11 +325,11 @@ public:
{ return ( m_pKanaComp && m_nKanaIdx < m_pKanaComp->size() )
? (*m_pKanaComp)[m_nKanaIdx] : 0; }
- const std::shared_ptr<vcl::text::TextLayoutCache>& GetCachedVclData() const
+ const std::shared_ptr<const vcl::text::TextLayoutCache>& GetCachedVclData() const
{
return m_pCachedVclData;
}
- void SetCachedVclData(std::shared_ptr<vcl::text::TextLayoutCache> const& pCachedVclData)
+ void SetCachedVclData(std::shared_ptr<const vcl::text::TextLayoutCache> const& pCachedVclData)
{
m_pCachedVclData = pCachedVclData;
}
@@ -673,7 +673,7 @@ public:
class SwTextSlot final
{
OUString aText;
- std::shared_ptr<vcl::text::TextLayoutCache> m_pOldCachedVclData;
+ std::shared_ptr<const vcl::text::TextLayoutCache> m_pOldCachedVclData;
const OUString *pOldText;
sw::WrongListIterator * m_pOldSmartTagList;
sw::WrongListIterator * m_pOldGrammarCheckList;
diff --git a/sw/source/core/text/porfld.cxx b/sw/source/core/text/porfld.cxx
index 47a55150ab3f..8c586530eff8 100644
--- a/sw/source/core/text/porfld.cxx
+++ b/sw/source/core/text/porfld.cxx
@@ -137,7 +137,7 @@ namespace {
*/
class SwFieldSlot
{
- std::shared_ptr<vcl::text::TextLayoutCache> m_pOldCachedVclData;
+ std::shared_ptr<const vcl::text::TextLayoutCache> m_pOldCachedVclData;
const OUString *pOldText;
OUString aText;
TextFrameIndex nIdx;
diff --git a/sw/source/core/text/pormulti.cxx b/sw/source/core/text/pormulti.cxx
index 2e4831065537..d47b281ac9a9 100644
--- a/sw/source/core/text/pormulti.cxx
+++ b/sw/source/core/text/pormulti.cxx
@@ -2000,7 +2000,7 @@ bool SwTextFormatter::BuildMultiPortion( SwTextFormatInfo &rInf,
// save some values
const OUString* pOldText = &(rInf.GetText());
const SwTwips nOldPaintOfst = rInf.GetPaintOfst();
- std::shared_ptr<vcl::text::TextLayoutCache> const pOldCachedVclData(rInf.GetCachedVclData());
+ std::shared_ptr<const vcl::text::TextLayoutCache> const pOldCachedVclData(rInf.GetCachedVclData());
rInf.SetCachedVclData(nullptr);
OUString const aMultiStr( rInf.GetText().copy(0, sal_Int32(nMultiLen + rInf.GetIdx())) );
diff --git a/vcl/inc/sallayout.hxx b/vcl/inc/sallayout.hxx
index 847c22ace091..75110158dc53 100644
--- a/vcl/inc/sallayout.hxx
+++ b/vcl/inc/sallayout.hxx
@@ -113,7 +113,7 @@ public:
void AdjustLayout(vcl::text::ImplLayoutArgs&) final override;
bool LayoutText(vcl::text::ImplLayoutArgs&, const SalLayoutGlyphsImpl*) final override;
void DrawText(SalGraphics&) const final override;
- static std::shared_ptr<vcl::text::TextLayoutCache> CreateTextLayoutCache(OUString const&);
+ static std::shared_ptr<const vcl::text::TextLayoutCache> CreateTextLayoutCache(OUString const&);
SalLayoutGlyphs GetGlyphs() const final override;
bool IsKashidaPosValid(int nCharPos) const final override;
diff --git a/vcl/source/gdi/CommonSalLayout.cxx b/vcl/source/gdi/CommonSalLayout.cxx
index 811849309d67..e26dc68692bf 100644
--- a/vcl/source/gdi/CommonSalLayout.cxx
+++ b/vcl/source/gdi/CommonSalLayout.cxx
@@ -21,8 +21,11 @@
#include <sal/log.hxx>
#include <unotools/configmgr.hxx>
+#include <o3tl/hash_combine.hxx>
+#include <o3tl/lru_map.hxx>
#include <o3tl/temporary.hxx>
+#include <vcl/lazydelete.hxx>
#include <vcl/unohelp.hxx>
#include <vcl/font/Feature.hxx>
#include <vcl/font/FeatureParser.hxx>
@@ -151,11 +154,35 @@ namespace {
return VerticalOrientation(nRet);
}
+struct FirstCharsStringHash
+{
+ size_t operator()( const OUString& str ) const
+ {
+ // Strings passed to GenericSalLayout::CreateTextLayoutCache() may be very long,
+ // and computing an entire hash could almost negate the gain of hashing. Hash just first
+ // characters, that should be good enough.
+ size_t hash = rtl_ustr_hashCode_WithLength( str.getStr(), std::min<size_t>( 100, str.getLength()));
+ o3tl::hash_combine(hash, str.getLength());
+ return hash;
+ }
+};
+
} // namespace
-std::shared_ptr<vcl::text::TextLayoutCache> GenericSalLayout::CreateTextLayoutCache(OUString const& rString)
+std::shared_ptr<const vcl::text::TextLayoutCache> GenericSalLayout::CreateTextLayoutCache(OUString const& rString)
{
- return std::make_shared<vcl::text::TextLayoutCache>(rString.getStr(), rString.getLength());
+ typedef o3tl::lru_map<OUString, std::shared_ptr<const vcl::text::TextLayoutCache>, FirstCharsStringHash> Cache;
+ static vcl::DeleteOnDeinit< Cache > cache( 1000 );
+ if( Cache* map = cache.get())
+ {
+ auto it = map->find(rString);
+ if( it != map->end())
+ return it->second;
+ auto ret = std::make_shared<const vcl::text::TextLayoutCache>(rString.getStr(), rString.getLength());
+ map->insert( { rString, ret } );
+ return ret;
+ }
+ return std::make_shared<const vcl::text::TextLayoutCache>(rString.getStr(), rString.getLength());
}
SalLayoutGlyphs GenericSalLayout::GetGlyphs() const
diff --git a/vcl/source/outdev/text.cxx b/vcl/source/outdev/text.cxx
index e9c9ff59d414..8ac3cc379073 100644
--- a/vcl/source/outdev/text.cxx
+++ b/vcl/source/outdev/text.cxx
@@ -1456,7 +1456,7 @@ std::unique_ptr<SalLayout> OutputDevice::ImplLayout(const OUString& rOrigStr,
return pSalLayout;
}
-std::shared_ptr<vcl::text::TextLayoutCache> OutputDevice::CreateTextLayoutCache(
+std::shared_ptr<const vcl::text::TextLayoutCache> OutputDevice::CreateTextLayoutCache(
OUString const& rString)
{
return GenericSalLayout::CreateTextLayoutCache(rString);