sw/source/core/text/itrform2.cxx |   10 +++++++---
 sw/source/core/text/portxt.cxx   |    6 ++++++
 vcl/source/gdi/impglyphitem.cxx  |    9 ++++++++-
 3 files changed, 21 insertions(+), 4 deletions(-)

New commits:
commit 4c8f88bef948b18f3d810c29a7f83496367758a9
Author:     Jonathan Clark <jonat...@libreoffice.org>
AuthorDate: Fri Jul 12 13:40:34 2024 -0600
Commit:     Jonathan Clark <jonat...@libreoffice.org>
CommitDate: Sat Jul 13 04:22:05 2024 +0200

    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 <jonat...@libreoffice.org>

diff --git a/sw/source/core/text/itrform2.cxx b/sw/source/core/text/itrform2.cxx
index b4256d85888f..893666e1108d 100644
--- a/sw/source/core/text/itrform2.cxx
+++ b/sw/source/core/text/itrform2.cxx
@@ -1419,8 +1419,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
@@ -1445,7 +1448,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 476dbf7aac77..d7c376de35ce 100644
--- a/sw/source/core/text/portxt.cxx
+++ b/sw/source/core/text/portxt.cxx
@@ -438,6 +438,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 300127de6b7a..184e9f819b5a 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 && pos > 0 && text[pos - 1] 
== nbSpace)

Reply via email to