diff options
author | Michael Stahl <mstahl@redhat.com> | 2015-03-03 15:26:10 +0100 |
---|---|---|
committer | Michael Stahl <mstahl@redhat.com> | 2015-03-31 20:08:35 +0200 |
commit | b9782a2b59428e1bc398b5f3a895785a072c93b6 (patch) | |
tree | 11321664d97646020fb77cf161e89e20a11d68d6 /vcl/generic/glyphs | |
parent | b7fa07b07195799f385ccba0243611f71ffe0525 (diff) |
tdf#89666: vcl: speed up HbLayoutEngine with cache in SwTxtFormatInfo
When a SwTxtFormatInfo is created to format a paragraph, pre-compute the
result of vcl::ScriptRun::next() and cache it for future calls to
OutputDevice::GetTextBreak() and GetTextWidth().
This requires adapting a bunch of methods to pass the additional
parameter, and some classes to backup and restore the cache when they
replace the text of the SwTxtFormatInfo.
There is some code in vcl OutputDevice::ImplPrepareLayoutArgs()
to modify the passed string and replace digits depending on
"meTextLanguage" member; try to set it to the correct value when
creating the layout cache (unfortunately it's not possible if the user
sets the CTL Numerals config to the non-default "Context" value).
Another issue is the check in OutputDevice::ImplLayout() if there is
a mpConversion member on the font; apparently this is used to translate
between different Symbol fonts, so not very important; just ignore the
cache in this case.
This reduces vcl::ScriptRun::next() from 11 to 0.36 billion callgrind
cycles when built with GCC 4.9.2 -m32 -Os (which is still 16% of the
formatting).
Change-Id: I61fb8530333f2e7a9199f767c00cf2181ba49951
Reviewed-on: https://gerrit.libreoffice.org/14732
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
Diffstat (limited to 'vcl/generic/glyphs')
-rw-r--r-- | vcl/generic/glyphs/gcach_layout.cxx | 64 |
1 files changed, 56 insertions, 8 deletions
diff --git a/vcl/generic/glyphs/gcach_layout.cxx b/vcl/generic/glyphs/gcach_layout.cxx index debcbe79eb4c..94486a1a8813 100644 --- a/vcl/generic/glyphs/gcach_layout.cxx +++ b/vcl/generic/glyphs/gcach_layout.cxx @@ -349,6 +349,41 @@ struct HbScriptRun typedef std::vector<HbScriptRun> HbScriptRuns; +namespace vcl { + struct Run + { + int32_t nStart; + int32_t nEnd; + UScriptCode nCode; + Run(int32_t nStart_, int32_t nEnd_, UScriptCode nCode_) + : nStart(nStart_), nEnd(nEnd_), nCode(nCode_) + {} + }; + + class TextLayoutCache + { + public: + std::vector<vcl::Run> runs; + TextLayoutCache(OUString const& rString, sal_Int32 const nEnd) + { + vcl::ScriptRun aScriptRun( + reinterpret_cast<const UChar *>(rString.getStr()), + nEnd); + while (aScriptRun.next()) + { + runs.push_back(Run(aScriptRun.getScriptStart(), + aScriptRun.getScriptEnd(), aScriptRun.getScriptCode())); + } + } + }; +} + +std::shared_ptr<vcl::TextLayoutCache> ServerFontLayout::CreateTextLayoutCache( + OUString const& rString) const +{ + return std::make_shared<vcl::TextLayoutCache>(rString, rString.getLength()); +} + bool HbLayoutEngine::Layout(ServerFontLayout& rLayout, ImplLayoutArgs& rArgs) { ServerFont& rFont = rLayout.GetServerFont(); @@ -370,7 +405,18 @@ bool HbLayoutEngine::Layout(ServerFontLayout& rLayout, ImplLayoutArgs& rArgs) rLayout.Reserve(nGlyphCapacity); - vcl::ScriptRun aScriptRun(reinterpret_cast<const UChar *>(rArgs.mpStr), rArgs.mnEndCharPos); + std::unique_ptr<vcl::TextLayoutCache> pNewScriptRun; + vcl::TextLayoutCache const* pTextLayout; + if (rArgs.m_pTextLayoutCache) + { + pTextLayout = rArgs.m_pTextLayoutCache; // use cache! + } + else + { + pNewScriptRun.reset(new vcl::TextLayoutCache( + reinterpret_cast<const UChar *>(rArgs.mpStr), rArgs.mnEndCharPos)); + pTextLayout = pNewScriptRun.get(); + } Point aCurrPos(0, 0); while (true) @@ -383,21 +429,25 @@ bool HbLayoutEngine::Layout(ServerFontLayout& rLayout, ImplLayoutArgs& rArgs) // Find script subruns. int nCurrentPos = nBidiMinRunPos; HbScriptRuns aScriptSubRuns; - while (aScriptRun.next()) + size_t k = 0; + for (; k < pTextLayout->runs.size(); ++k) { - if (aScriptRun.getScriptStart() <= nCurrentPos && aScriptRun.getScriptEnd() > nCurrentPos) + vcl::Run const& rRun(pTextLayout->runs[k]); + if (rRun.nStart <= nCurrentPos && nCurrentPos < rRun.nEnd) + { break; + } } while (nCurrentPos < nBidiEndRunPos) { int32_t nMinRunPos = nCurrentPos; - int32_t nEndRunPos = std::min(aScriptRun.getScriptEnd(), nBidiEndRunPos); - HbScriptRun aRun(nMinRunPos, nEndRunPos, aScriptRun.getScriptCode()); + int32_t nEndRunPos = std::min(pTextLayout->runs[k].nEnd, nBidiEndRunPos); + HbScriptRun aRun(nMinRunPos, nEndRunPos, pTextLayout->runs[k].nCode); aScriptSubRuns.push_back(aRun); nCurrentPos = nEndRunPos; - aScriptRun.next(); + ++k; } // RTL subruns should be reversed to ensure that final glyph order is @@ -405,8 +455,6 @@ bool HbLayoutEngine::Layout(ServerFontLayout& rLayout, ImplLayoutArgs& rArgs) if (bRightToLeft) std::reverse(aScriptSubRuns.begin(), aScriptSubRuns.end()); - aScriptRun.reset(); - for (HbScriptRuns::iterator it = aScriptSubRuns.begin(); it != aScriptSubRuns.end(); ++it) { int nMinRunPos = it->mnMin; |