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:
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user