summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Clark <jonathan@libreoffice.org>2024-07-12 13:40:34 -0600
committerAdolfo Jayme Barrientos <fitojb@ubuntu.com>2024-09-04 18:16:38 +0200
commitef40759390de4eba93d0a1e9369fc8ba5c1ea534 (patch)
tree0f6ed26ced36087726c6a3a1aa349923f3b70980
parent74a68f76bb116e348826bff912d52d8205ab92a3 (diff)
tdf#92064 sw: Improve Tibetan layout performance
This change includes the following scalability improvements for documents containing extremely long paragraphs: - Reduces the size of layout contexts to account for line breaks. - Disables a misbehaving glyph cache performance optimization for long strings. Change-Id: Ie9a3365076c0d112a7a655988d672a9f4609b42b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/170420 Tested-by: Jenkins Reviewed-by: Jonathan Clark <jonathan@libreoffice.org> Signed-off-by: Xisco Fauli <xiscofauli@libreoffice.org> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/172858 Reviewed-by: Adolfo Jayme Barrientos <fitojb@ubuntu.com> Reviewed-by: Ilmari Lauhakangas <ilmari.lauhakangas@libreoffice.org>
-rw-r--r--sw/source/core/text/itrform2.cxx10
-rw-r--r--sw/source/core/text/portxt.cxx6
-rw-r--r--vcl/source/gdi/impglyphitem.cxx9
3 files changed, 21 insertions, 4 deletions
diff --git a/sw/source/core/text/itrform2.cxx b/sw/source/core/text/itrform2.cxx
index 71b78bc0914d..3673b46ba247 100644
--- a/sw/source/core/text/itrform2.cxx
+++ b/sw/source/core/text/itrform2.cxx
@@ -1418,8 +1418,11 @@ SwTextPortion *SwTextFormatter::NewTextPortion( SwTextFormatInfo &rInf )
if (!nCharWidthGuess)
nCharWidthGuess = 1;
auto nExpect = rInf.GetIdx() + TextFrameIndex(rInf.GetLineWidth() / nCharWidthGuess);
- if (nExpect > rInf.GetIdx() && nNextChg > nExpect)
- nNextChg = nExpect;
+ if (nExpect > rInf.GetIdx())
+ {
+ nNextChg = std::min(nNextChg, nExpect);
+ nNextContext = std::min(nNextContext, nExpect);
+ }
// we keep an invariant during method calls:
// there are no portion ending characters like hard spaces
@@ -1444,7 +1447,8 @@ SwTextPortion *SwTextFormatter::NewTextPortion( SwTextFormatInfo &rInf )
// for the first text portion in a paragraph, or for any successive
// portions that are outside of the bounds of the previous context.
if (!rInf.GetLayoutContext().has_value()
- || rInf.GetLayoutContext()->m_nEnd <= rInf.GetIdx().get())
+ || rInf.GetLayoutContext()->m_nBegin < rInf.GetLineStart().get()
+ || rInf.GetLayoutContext()->m_nEnd < nNextChg.get())
{
// The layout context must terminate at special characters
sal_Int32 nEnd = rInf.GetIdx().get();
diff --git a/sw/source/core/text/portxt.cxx b/sw/source/core/text/portxt.cxx
index ee39f156c24a..ec0303c0665c 100644
--- a/sw/source/core/text/portxt.cxx
+++ b/sw/source/core/text/portxt.cxx
@@ -445,6 +445,12 @@ bool SwTextPortion::Format_( SwTextFormatInfo &rInf )
SetLen( pGuess->BreakPos() - rInf.GetIdx() );
+ // Clamp layout context to the end of the line
+ if(auto stClampedContext = GetLayoutContext(); stClampedContext.has_value()) {
+ stClampedContext->m_nEnd = pGuess->BreakPos().get();
+ SetLayoutContext(stClampedContext);
+ }
+
OSL_ENSURE( pGuess->BreakStart() >= pGuess->FieldDiff(),
"Trouble with expanded field portions during line break" );
TextFrameIndex const nRealStart = pGuess->BreakStart() - pGuess->FieldDiff();
diff --git a/vcl/source/gdi/impglyphitem.cxx b/vcl/source/gdi/impglyphitem.cxx
index 1b40291736b7..946230a51762 100644
--- a/vcl/source/gdi/impglyphitem.cxx
+++ b/vcl/source/gdi/impglyphitem.cxx
@@ -364,6 +364,13 @@ const SalLayoutGlyphs* SalLayoutGlyphsCache::GetLayoutGlyphs(
// part being underlined. Doing this for any two segments allows this optimization
// even when the prefix of the string would use a different font.
// TODO: Can those font differences be ignored?
+
+ // Shaping performance seems to scale poorly with respect to string length. Certain
+ // writing systems involve extremely long strings (for example, Tibetan: tdf#92064).
+ // In such cases, this optimization would be a net loss, and must be disabled.
+ constexpr sal_Int32 nOptLengthThreshold = 20000;
+ bool bEnableOptimization = (text.getLength() < nOptLengthThreshold);
+
// Writer layouts tests enable SAL_NON_APPLICATION_FONT_USE=abort in order
// to make PrintFontManager::Substitute() abort if font fallback happens. When
// laying out the entire string the chance this happens increases (e.g. testAbi11870
@@ -374,7 +381,7 @@ const SalLayoutGlyphs* SalLayoutGlyphsCache::GetLayoutGlyphs(
const char* pEnv = getenv("SAL_NON_APPLICATION_FONT_USE");
return pEnv && strcmp(pEnv, "abort") == 0;
}();
- if (mLastSubstringKey.has_value() && !bAbortOnFontSubstitute)
+ if (bEnableOptimization && mLastSubstringKey.has_value() && !bAbortOnFontSubstitute)
{
sal_Int32 pos = nIndex;
if (mLastSubstringKey->len < pos && text[pos - 1] == nbSpace)