optimize repeated calls for the same string in SalLayoutGlyphsCache

It often happens that the entire text will be laid out in parts,
so if the first call is a prefix and another one follows that,
lay out the entire string and then use the glyph subset optimization.
Doing this only for the second segment instead immediately for
the prefix is more efficient, as sometimes there is only the prefix
call and there's no call for the rest of the string. This also
avoids failures in CppunitTest_sw_layoutwriter, as a number of tests
such as testAbi11870 lay out only a prefix and doing a layout
for the entire string leads to font fallback, on which
CppunitTest_sw_layoutwriter aborts in PrintFontManager::Substitute().

Change-Id: I76554868ec7e8a79dd09709a247ad1d839291c06
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133495
Tested-by: Jenkins
Reviewed-by: Luboš Luňák <l.lunak@collabora.com>
This commit is contained in:
Luboš Luňák
2022-05-03 09:08:44 +02:00
parent 6ba14f83ad
commit 0a6d946694
2 changed files with 32 additions and 0 deletions
+2
View File
@@ -96,6 +96,8 @@ private:
// Last temporary glyphs returned (pointer is returned, so the object needs to be kept somewhere).
std::optional<CachedGlyphsKey> mLastTemporaryKey;
SalLayoutGlyphs mLastTemporaryGlyphs;
// If set, info about the last call which wanted a prefix of the full text.
std::optional<CachedGlyphsKey> mLastPrefixKey;
SalLayoutGlyphsCache(const SalLayoutGlyphsCache&) = delete;
SalLayoutGlyphsCache& operator=(const SalLayoutGlyphsCache&) = delete;
+30
View File
@@ -301,6 +301,7 @@ SalLayoutGlyphsCache::GetLayoutGlyphs(VclPtr<const OutputDevice> outputDevice, c
const SalLayoutFlags glyphItemsOnlyLayout
= SalLayoutFlags::GlyphItemsOnly | SalLayoutFlags::BiDiStrong;
#endif
bool resetLastPrefixKey = true;
if (nIndex != 0 || nLen != text.getLength())
{
// The glyphs functions are often called first for an entire string
@@ -311,8 +312,34 @@ SalLayoutGlyphsCache::GetLayoutGlyphs(VclPtr<const OutputDevice> outputDevice, c
return &mLastTemporaryGlyphs;
const CachedGlyphsKey keyWhole(outputDevice, text, 0, text.getLength(), nLogicWidth);
GlyphsCache::const_iterator itWhole = mCachedGlyphs.find(keyWhole);
if (itWhole == mCachedGlyphs.end())
{
// This function may often be called repeatedly for segments of the same string,
// in which case it is more efficient to cache glyphs for the entire string
// and then return subsets of them. So if the first call is for a prefix of the string,
// remember that, and if the next call follows the previous part of the string,
// cache the entire string.
if (nIndex == 0)
{
mLastPrefixKey = key;
resetLastPrefixKey = false;
}
else if (mLastPrefixKey.has_value() && mLastPrefixKey->len == nIndex
&& mLastPrefixKey
== CachedGlyphsKey(outputDevice, text, mLastPrefixKey->index,
mLastPrefixKey->len, nLogicWidth))
{
assert(mLastPrefixKey->index == 0);
std::unique_ptr<SalLayout> layout
= outputDevice->ImplLayout(text, nIndex, nLen, Point(0, 0), nLogicWidth, {},
glyphItemsOnlyLayout, layoutCache);
GetLayoutGlyphs(outputDevice, text, 0, text.getLength(), nLogicWidth, layoutCache);
itWhole = mCachedGlyphs.find(keyWhole);
}
}
if (itWhole != mCachedGlyphs.end() && itWhole->second.IsValid())
{
mLastPrefixKey.reset();
mLastTemporaryGlyphs
= makeGlyphsSubset(itWhole->second, outputDevice, text, nIndex, nLen);
if (mLastTemporaryGlyphs.IsValid())
@@ -337,6 +364,9 @@ SalLayoutGlyphsCache::GetLayoutGlyphs(VclPtr<const OutputDevice> outputDevice, c
}
}
}
if (resetLastPrefixKey)
mLastPrefixKey.reset();
std::shared_ptr<const vcl::text::TextLayoutCache> tmpLayoutCache;
if (layoutCache == nullptr)
{