svx/source/svdraw/svdotextdecomposition.cxx |    8 ++-
 sw/source/core/txtnode/fntcache.cxx         |   10 ++++
 vcl/inc/sallayout.hxx                       |    1 
 vcl/source/gdi/sallayout.cxx                |   66 +++++++++++++++-------------
 4 files changed, 54 insertions(+), 31 deletions(-)

New commits:
commit a84bf20b345ba016ab67217f5fd73eebb517dc6b
Author:     Khaled Hosny <kha...@libreoffice.org>
AuthorDate: Mon Jun 12 22:29:11 2023 +0300
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Fri Jun 23 22:52:56 2023 +0200

    tdf#152048: Fix measuring text width with font fallback
    
    This is a regression from:
    
    commit 43a5400063b17ed4ba4cbb38bdf5da4a991f60e2
    Author: Khaled Hosny <kha...@libreoffice.org>
    Date:   Thu May 25 10:59:18 2023 +0300
    
        tdf#152048: Fix underline width for Kashida-justified text
    
    It fixed measuring width when there is Kashida justification, but broke
    it for font fallback, because of the way MultiSalLayout measures the
    text width takes the maximum of the text widths for all its layouts, but
    layouts with missing glyphs are now giving wrong text width as they are
    measuring the width of .notdef (GID 0) glyph.
    
    This change makes MultiSalLayout measure the text width by iterating
    over all its valid glyphs.
    
    Change-Id: I8b19e0d44326c6f0afe6e504ab6d90c6fb3575f9
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/152933
    Tested-by: Jenkins
    Reviewed-by: خالد حسني <kha...@libreoffice.org>
    (cherry picked from commit 38b5e9bc7d45f52f11bad125a584ad2261383de6)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/152920
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

diff --git a/vcl/inc/sallayout.hxx b/vcl/inc/sallayout.hxx
index 35496750c286..d48edaaf67f2 100644
--- a/vcl/inc/sallayout.hxx
+++ b/vcl/inc/sallayout.hxx
@@ -62,6 +62,7 @@ class MultiSalLayout final : public SalLayout
 public:
     void            DrawText(SalGraphics&) const override;
     sal_Int32       GetTextBreak(DeviceCoordinate nMaxWidth, DeviceCoordinate 
nCharExtra, int nFactor) const override;
+    DeviceCoordinate GetTextWidth() const final override;
     DeviceCoordinate FillDXArray(std::vector<DeviceCoordinate>* pDXArray, 
const OUString& rStr) const override;
     void            GetCaretPositions(int nArraySize, sal_Int32* pCaretXArray) 
const override;
     bool            GetNextGlyph(const GlyphItem** pGlyph, DevicePoint& rPos, 
int& nStart,
diff --git a/vcl/source/gdi/sallayout.cxx b/vcl/source/gdi/sallayout.cxx
index 1ed2a37ad71b..3cdd71642b5b 100644
--- a/vcl/source/gdi/sallayout.cxx
+++ b/vcl/source/gdi/sallayout.cxx
@@ -1009,45 +1009,53 @@ sal_Int32 MultiSalLayout::GetTextBreak( 
DeviceCoordinate nMaxWidth, DeviceCoordi
     return -1;
 }
 
-DeviceCoordinate MultiSalLayout::FillDXArray( std::vector<DeviceCoordinate>* 
pCharWidths, const OUString& rStr ) const
+DeviceCoordinate MultiSalLayout::GetTextWidth() const
 {
-    DeviceCoordinate nMaxWidth = 0;
+    // Measure text width. There might be holes in each SalLayout due to
+    // missing chars, so we use GetNextGlyph() to get the glyphs across all
+    // layouts.
+    int nStart = 0;
+    DevicePoint aPos;
+    const GlyphItem* pGlyphItem;
 
-    // prepare merging of fallback levels
-    std::vector<DeviceCoordinate> aTempWidths;
-    const int nCharCount = mnEndCharPos - mnMinCharPos;
-    if( pCharWidths )
+    DeviceCoordinate nWidth = 0;
+    while (GetNextGlyph(&pGlyphItem, aPos, nStart))
+        nWidth += pGlyphItem->newWidth();
+
+    return nWidth;
+}
+
+DeviceCoordinate MultiSalLayout::FillDXArray( std::vector<DeviceCoordinate>* 
pCharWidths, const OUString& rStr ) const
+{
+    if (pCharWidths)
     {
+        // prepare merging of fallback levels
+        std::vector<DeviceCoordinate> aTempWidths;
+        const int nCharCount = mnEndCharPos - mnMinCharPos;
         pCharWidths->clear();
         pCharWidths->resize(nCharCount, 0);
-    }
 
-    for( int n = mnLevel; --n >= 0; )
-    {
-        // query every fallback level
-        DeviceCoordinate nTextWidth = mpLayouts[n]->FillDXArray( &aTempWidths, 
rStr );
-        if( !nTextWidth )
-            continue;
-        // merge results from current level
-        if( nMaxWidth < nTextWidth )
-            nMaxWidth = nTextWidth;
-        if( !pCharWidths )
-            continue;
-        // calculate virtual char widths using most probable fallback layout
-        for( int i = 0; i < nCharCount; ++i )
+        for (int n = mnLevel; --n >= 0;)
         {
-            // #i17359# restriction:
-            // one char cannot be resolved from different fallbacks
-            if( (*pCharWidths)[i] != 0 )
-                continue;
-            DeviceCoordinate nCharWidth = aTempWidths[i];
-            if( !nCharWidth )
-                continue;
-            (*pCharWidths)[i] = nCharWidth;
+            // query every fallback level
+            mpLayouts[n]->FillDXArray(&aTempWidths, rStr);
+
+            // calculate virtual char widths using most probable fallback 
layout
+            for (int i = 0; i < nCharCount; ++i)
+            {
+                // #i17359# restriction:
+                // one char cannot be resolved from different fallbacks
+                if ((*pCharWidths)[i] != 0)
+                    continue;
+                DeviceCoordinate nCharWidth = aTempWidths[i];
+                if (!nCharWidth)
+                    continue;
+                (*pCharWidths)[i] = nCharWidth;
+            }
         }
     }
 
-    return nMaxWidth;
+    return GetTextWidth();
 }
 
 void MultiSalLayout::GetCaretPositions( int nMaxIndex, sal_Int32* pCaretXArray 
) const
commit 04f4aaa36eab4cb7299e567d59b6e5de5c4f5bf6
Author:     Khaled Hosny <kha...@libreoffice.org>
AuthorDate: Thu Jun 8 16:41:18 2023 +0300
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Fri Jun 23 22:52:43 2023 +0200

    tdf#151968: Fix vertical position of RTL spelling wavy line
    
    Second try. This time making sure start > end even for RTL text.
    
    This also now works for horizontal, vertical and rotated Arabic text, in
    Writer and Edit Engine.
    
    Change-Id: I6fe1e9dbb9c071287054200a58d4ddddee073311
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/152820
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

diff --git a/svx/source/svdraw/svdotextdecomposition.cxx 
b/svx/source/svdraw/svdotextdecomposition.cxx
index e526c44edc68..6d9d5cd9d5f8 100644
--- a/svx/source/svdraw/svdotextdecomposition.cxx
+++ b/svx/source/svdraw/svdotextdecomposition.cxx
@@ -427,8 +427,12 @@ namespace
                         // full portion width
                         const double fTextWidth(aDXArray[aDXArray.size() - 1]);
 
-                        fStart = fTextWidth - fStart;
-                        fEnd = fTextWidth - fEnd;
+                        // tdf#151968
+                        // if start < end, OutputDevice::DrawWaveLine() will
+                        // think it is a rotated line, so we swap fStart and
+                        // fEnd to avoid this.
+                        fStart = fTextWidth - fEnd;
+                        fEnd = fTextWidth - fStart;
                     }
 
                     // need to take FontScaling out of values; it's already 
part of
diff --git a/sw/source/core/txtnode/fntcache.cxx 
b/sw/source/core/txtnode/fntcache.cxx
index 20ed476398d8..0da5658e1749 100644
--- a/sw/source/core/txtnode/fntcache.cxx
+++ b/sw/source/core/txtnode/fntcache.cxx
@@ -241,10 +241,20 @@ static void lcl_calcLinePos( const CalcLinePosData &rData,
         break;
     }
 
+    // tdf#151968
+    // if start < end, OutputDevice::DrawWaveLine() will think it is a rotated
+    // line, so we swap nStart and nEnd to avoid this.
+    if ( rData.bBidiPor )
+        std::swap(rStart, rEnd);
+
     if ( rData.bSwitchL2R )
     {
         rData.rInf.GetFrame()->SwitchLTRtoRTL( rStart );
         rData.rInf.GetFrame()->SwitchLTRtoRTL( rEnd );
+
+        // tdf#151968
+        // We need to do this here as well for LTR text in a RTL paragraph.
+        std::swap(rStart, rEnd);
     }
 
     if ( rData.bSwitchH2V )

Reply via email to