Index: gsl/vcl/source/gdi/sallayout.cxx
diff -u gsl/vcl/source/gdi/sallayout.cxx:1.80 gsl/vcl/source/gdi/sallayout.cxx:1.78.42.5
--- vcl/source/gdi/sallayout.cxx:1.80	Mon Jun 19 12:31:39 2006
+++ vcl/source/gdi/sallayout.cxx	Fri Jul  7 03:28:33 2006
@@ -77,6 +77,8 @@
 #pragma warning(pop)
 #endif 
 
+#include <algorithm>
+
 // =======================================================================
 
 int GetVerticalFlags( sal_Unicode nChar )
@@ -635,48 +637,48 @@
 
 bool ImplLayoutArgs::PrepareFallback()
 {
-    // return early if a fallback is not needed
+    // short circuit if no fallback is needed
     if( maReruns.IsEmpty() )
     {
         maRuns.Clear();
         return false;
     }
 
-    // convert the fallback request to a layout request
-
-    // sort out chars that were not requested anyway
-    ImplLayoutRuns aOrigRuns = maRuns;
-    maRuns.Clear();
+    // convert the fallback requests to layout requests
     bool bRTL;
-    int nMin1, nEnd1;
+    int nMin, nEnd;
+
+    // get the individual fallback requests
+    typedef std::vector<int> IntVector;
+    IntVector aPosVector;
+    aPosVector.reserve( mnLength );
     maReruns.ResetPos();
-    for(; maReruns.GetRun( &nMin1, &nEnd1, &bRTL ); maReruns.NextRun() )
+    for(; maReruns.GetRun( &nMin, &nEnd, &bRTL ); maReruns.NextRun() )
+        for( int i = nMin; i < nEnd; ++i )
+            aPosVector.push_back( i );
+    maReruns.Clear();
+
+    // sort the individual fallback requests
+    std::sort( aPosVector.begin(), aPosVector.end() );
+
+    // adjust fallback runs to have the same order and limits of the original runs
+    ImplLayoutRuns aNewRuns;
+    maRuns.ResetPos();
+    for(; maRuns.GetRun( &nMin, &nEnd, &bRTL ); maRuns.NextRun() )
     {
-        // find a matching layout run and clip the fallback run to it
-        // TODO: improve O(n^2) algorithm
-        int nMin2, nEnd2;
-        aOrigRuns.ResetPos();
-        for(; aOrigRuns.GetRun( &nMin2, &nEnd2, &bRTL ); aOrigRuns.NextRun() )
-        {
-            // ignore runs that don't overlap
-            if( nMin1 >= nEnd2 )
-                continue;
-            if( nEnd1 <= nMin2 )
-                continue;
-            // clip the fallback run to the layout run
-            if( nMin1 < nMin2 )
-                nMin1 = nMin2;
-            if( nEnd1 > nEnd2 )
-                nEnd1 = nEnd2;
-            // if there is something left request the fallback
-            if( nMin1 < nEnd1 )
-                maRuns.AddRun( nMin1, nEnd1, bRTL );
-            break;
+        if( !bRTL) {
+            IntVector::const_iterator it = std::lower_bound( aPosVector.begin(), aPosVector.end(), nMin );
+            for(; (it != aPosVector.end()) && (*it < nEnd); ++it )
+                aNewRuns.AddPos( *it, bRTL );
+        } else {
+            IntVector::const_iterator it = std::upper_bound( aPosVector.begin(), aPosVector.end(), nEnd );
+            while( (it != aPosVector.begin()) && (*--it >= nMin) )
+                aNewRuns.AddPos( *it, bRTL );
         }
     }
 
+    maRuns = aNewRuns;  // TODO: use vector<>::swap()
     maRuns.ResetPos();
-    maReruns.Clear();
     return true;
 }
 
@@ -1063,7 +1065,8 @@
         n = pG->mnCharPos - rArgs.mnMinCharPos;
         if( (n < 0) || (nCharCount <= n) )
             continue;
-        pLogCluster[ n ] = i;
+        if( pLogCluster[ n ] < 0 )
+            pLogCluster[ n ] = i;
         if( nBasePointX < 0 )
             nBasePointX = pG->maLinearPos.X();
     }
@@ -1740,20 +1743,23 @@
             }
         }
 
-        // if a justification array is available => override the advance width
+        // if a justification array is available
+        // => use it directly to advance to the next x-position
         if( aMultiArgs.mpDXArray )
         {
             // the run advance is the width from the first char
             // in the run to the first char in the next run
             nRunAdvance = 0;
-            int nRelPos = nCharPos[0] - mnMinCharPos;
-            if( nRelPos > 0 )
-                nRunAdvance += aMultiArgs.mpDXArray[ nRelPos-1 ];
-            nRelPos = nActiveCharPos - mnMinCharPos;
-            if( nRelPos > 0 )
-                nRunAdvance -= aMultiArgs.mpDXArray[ nRelPos-1 ];
-            if( nRunAdvance < 0 )
+            const bool bLTR = (nActiveCharPos < nCharPos[0]);
+            int nDXIndex = nCharPos[0] - mnMinCharPos - bLTR;
+            if( nDXIndex >= 0 )
+                nRunAdvance += aMultiArgs.mpDXArray[ nDXIndex ];
+            nDXIndex = nActiveCharPos - mnMinCharPos - bLTR;
+            if( nDXIndex >= 0 )
+                nRunAdvance -= aMultiArgs.mpDXArray[ nDXIndex ];
+            if( !bLTR )
                 nRunAdvance = -nRunAdvance;
+
             // convert justification array units into fallback font units
             nRunAdvance *= mpLayouts[n]->GetUnitsPerPixel();
         }
Index: gsl/vcl/source/glyphs/gcach_layout.cxx
diff -u gsl/vcl/source/glyphs/gcach_layout.cxx:1.39 gsl/vcl/source/glyphs/gcach_layout.cxx:1.38.62.2
--- vcl/source/glyphs/gcach_layout.cxx:1.39	Mon Jun 19 12:32:50 2006
+++ vcl/source/glyphs/gcach_layout.cxx	Fri Jul  7 03:29:44 2006
@@ -390,7 +390,7 @@
 
     struct IcuPosition{ float fX, fY; };
     const int nAllocSize = sizeof(LEGlyphID) + sizeof(le_int32) + sizeof(IcuPosition);
-    LEGlyphID* pIcuGlyphs = (LEGlyphID*)alloca( nGlyphCapacity * nAllocSize + sizeof(IcuPosition) );
+    LEGlyphID* pIcuGlyphs = (LEGlyphID*)alloca( (nGlyphCapacity * nAllocSize) + sizeof(IcuPosition) );
     le_int32* pCharIndices = (le_int32*)((char*)pIcuGlyphs + nGlyphCapacity * sizeof(LEGlyphID) );
     IcuPosition* pGlyphPositions = (IcuPosition*)((char*)pCharIndices + nGlyphCapacity * sizeof(le_int32) );
 
@@ -466,11 +466,22 @@
             ||  (nGlyphIndex == ICU_DELETED_GLYPH) )
                 continue;  // ignore these glyphs
 
-            int nCharPos = pCharIndices[i] + nMinRunPos;
+            // adjust the relative char pos
+            int nCharPos = pCharIndices[i];
+            if( nCharPos >= 0 ) {
+                nCharPos += nMinRunPos;
+                // ICU seems to return bad pCharIndices
+                // for some combinations of ICU+font+text
+                // => better give up now than crash later
+                if( nCharPos >= nEndRunPos )
+                    continue;
+            }
+
             // when glyph fallback is needed update LayoutArgs
             if( !nGlyphIndex )
             {
-                rArgs.NeedFallback( nCharPos, bRightToLeft );
+                if( nCharPos >= 0 )
+                    rArgs.NeedFallback( nCharPos, bRightToLeft );
                 if( SAL_LAYOUT_FOR_FALLBACK & rArgs.mnFlags )
                     continue;
             }
@@ -484,14 +495,18 @@
                     nCharPos = nLastCharPos;
 
             // apply vertical flags, etc.
-            sal_Unicode aChar = rArgs.mpStr[ nCharPos ];
-            nGlyphIndex = rFont.FixupGlyphIndex( nGlyphIndex, aChar );
+            if( nCharPos >= 0 )
+            {
+                sal_Unicode aChar = rArgs.mpStr[ nCharPos ];
+                nGlyphIndex = rFont.FixupGlyphIndex( nGlyphIndex, aChar );
+            }
 
+            // get glyph position and its metrics
             aNewPos = Point( (int)(pPos->fX+0.5), (int)(pPos->fY+0.5) );
             const GlyphMetric& rGM = rFont.GetGlyphMetric( nGlyphIndex );
             int nGlyphWidth = rGM.GetCharWidth();
 
-            // heuristic to detect group clusters using the "smoothed" char positions
+            // heuristic to detect group clusters using "smoothed" char positions
             long nGlyphFlags = 0;
             if( nLastCharPos != -1 )
                 if( (nCharPos == nLastCharPos) || (nGlyphWidth <= 0) )
@@ -499,6 +514,7 @@
             if( bRightToLeft )
                 nGlyphFlags |= GlyphItem::IS_RTL_GLYPH;
 
+            // add resulting glyph item to layout
             GlyphItem aGI( nCharPos, nGlyphIndex, aNewPos, nGlyphFlags, nGlyphWidth );
             rLayout.AppendGlyph( aGI );
             ++nFilteredRunGlyphCount;
@@ -508,8 +524,9 @@
         nGlyphCount += nFilteredRunGlyphCount;
     }
 
+    // sort glyphs in visual order
     rLayout.SortGlyphItems();
-    
+
     // determine need for kashida justification
     if( (rArgs.mpDXArray || rArgs.mnLayoutWidth)
     &&  ((meScriptCode == arabScriptCode) || (meScriptCode == syrcScriptCode)) )
