vcl/source/gdi/sallayout.cxx |   11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

New commits:
commit 7cafd6648d991d9f25466766042416e0c686074b
Author:     Jonathan Clark <jonat...@libreoffice.org>
AuthorDate: Thu Jun 19 03:01:48 2025 -0600
Commit:     Jonathan Clark <jonat...@libreoffice.org>
CommitDate: Fri Jun 20 09:01:27 2025 +0200

    tdf#163761 Fix for tofu inside mixed-direction fallback runs in GUI text
    
    Fixed a bug inside MultiSalLayout::ImplAdjustMultiLayout() that caused
    tofu characters and improper position adjustment for certain UI text
    with bidi fallback runs. The root cause was an implementation error
    causing the current glyph index in the base layout to outpace the
    current fallback run.
    
    Regression from commit 9c2eb9c872bb10049fcb0217842b3bb849c27a22
    (tdf#373494: Correctly drop NotDef glyphs in mixed direction fallback runs)
    
    Change-Id: I7c16943866bdd465cc3c2c1f8540b38d2d4d529c
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/186720
    Tested-by: Jenkins
    Reviewed-by: Jonathan Clark <jonat...@libreoffice.org>

diff --git a/vcl/source/gdi/sallayout.cxx b/vcl/source/gdi/sallayout.cxx
index ced75edbc26b..0e4d1473c27d 100644
--- a/vcl/source/gdi/sallayout.cxx
+++ b/vcl/source/gdi/sallayout.cxx
@@ -886,10 +886,13 @@ void 
MultiSalLayout::ImplAdjustMultiLayout(vcl::text::ImplLayoutArgs& rArgs,
         if( n > 0 )
         {
             // drop the NotDef glyphs in the base layout run if a fallback run 
exists
-            while (
-                    
(maFallbackRuns[n-1].PosIsInAnyRun(pGlyphs[nFirstValid]->charPos())) &&
-                    
(!maFallbackRuns[n].PosIsInAnyRun(pGlyphs[nFirstValid]->charPos()))
-                  )
+            //
+            // tdf#163761: The whole algorithm in this outer loop works by 
advancing through
+            // all of the glyphs and runs in lock-step. The current glyph in 
the base layout
+            // must not outpace the fallback runs. The following loop does 
this by breaking
+            // at the end of the current fallback run (which comes from the 
previous level).
+            while ((maFallbackRuns[n - 
1].PosIsInRun(pGlyphs[nFirstValid]->charPos()))
+                   && 
(!maFallbackRuns[n].PosIsInAnyRun(pGlyphs[nFirstValid]->charPos())))
             {
                 mpLayouts[0]->DropGlyph( nStartOld[0] );
                 nStartOld[0] = nStartNew[0];

Reply via email to