editeng/source/editeng/impedit2.cxx |   17 ++++-----
 editeng/source/items/svxfont.cxx    |   66 ++++++++++++++++++++++++++++--------
 2 files changed, 61 insertions(+), 22 deletions(-)

New commits:
commit 88aeb649ed33a1a67547419f9b76c2c892dd2ee1
Author:     Mark Hung <mark...@gmail.com>
AuthorDate: Sun Apr 17 12:56:06 2022 +0800
Commit:     Mark Hung <mark...@gmail.com>
CommitDate: Wed Apr 20 13:07:31 2022 +0200

    tdf#148630 fix text layout and cursor position for IVS+spacing
    
    in Impress. This involves:
    
    1. SvxFont::QuickGetTextSize() and SvxFont::GetPhysTxtSize():
    insert space only when text array value changes. Same value indicates
    diffferent characters of the same glyph item (e.x. surrogate pairs,
    unicode IVS that is made of a base character and a selector. ).
    
    2. ImpEditEngine::GetChar(): fix a logical mistake that tried
    to increase the index by 1 than checking the value of character
    position. To advance the index we always need to check the position
    first.
    
    Change-Id: I4e3547413ce361ae7801c957e6d589776ebed114
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133102
    Tested-by: Jenkins
    Reviewed-by: Mark Hung <mark...@gmail.com>

diff --git a/editeng/source/editeng/impedit2.cxx 
b/editeng/source/editeng/impedit2.cxx
index 2f44eaf5468a..1471b4f291c1 100644
--- a/editeng/source/editeng/impedit2.cxx
+++ b/editeng/source/editeng/impedit2.cxx
@@ -4001,16 +4001,17 @@ sal_Int32 ImpEditEngine::GetChar(
                         tools::Long nDiffRight = nTmpPosMax - nXInPortion;
                         OSL_ENSURE( nDiffLeft >= 0, "DiffLeft negative" );
                         OSL_ENSURE( nDiffRight >= 0, "DiffRight negative" );
-                        nOffset = ( bSmart && ( nDiffRight < nDiffLeft ) ) ? 
x+1 : x;
-                        // I18N: If there are character position with the 
length of 0,
-                        // they belong to the same character, we can not use 
this position as an index.
-                        // Skip all 0-positions, cheaper than using 
XBreakIterator:
-                        if ( nOffset < nMax )
+
+                        if (bSmart && nDiffRight < nDiffLeft)
                         {
-                            const tools::Long nX = 
pLine->GetCharPosArray()[nOffset];
-                            while ( ( (nOffset+1) < nMax ) && ( 
pLine->GetCharPosArray()[nOffset+1] == nX ) )
-                                nOffset++;
+                            // I18N: If there are character position with the 
length of 0,
+                            // they belong to the same character, we can not 
use this position as an index.
+                            // Skip all 0-positions, cheaper than using 
XBreakIterator:
+                            tools::Long nX = 
pLine->GetCharPosArray()[nTmpCurIndex + x];
+                            while(x < nMax && 
pLine->GetCharPosArray()[nTmpCurIndex + x] == nX)
+                                ++x;
                         }
+                        nOffset = x;
                         break;
                     }
                 }
diff --git a/editeng/source/items/svxfont.cxx b/editeng/source/items/svxfont.cxx
index 4b549d49d711..839240f828df 100644
--- a/editeng/source/items/svxfont.cxx
+++ b/editeng/source/items/svxfont.cxx
@@ -30,6 +30,15 @@
 #include <com/sun/star/i18n/KCharacterType.hpp>
 #include <editeng/escapementitem.hxx>
 #include <sal/log.hxx>
+#include <limits>
+
+static tools::Long GetTextArray( const OutputDevice* pOut, const OUString& 
rStr, std::vector<sal_Int32>* pDXAry,
+                                 sal_Int32 nIndex, sal_Int32 nLen )
+
+{
+    const SalLayoutGlyphs* layoutGlyphs = 
SalLayoutGlyphsCache::self()->GetLayoutGlyphs(pOut, rStr, nIndex, nLen);
+    return pOut->GetTextArray( rStr, pDXAry, nIndex, nLen, nullptr, 
layoutGlyphs);
+}
 
 SvxFont::SvxFont()
 {
@@ -433,7 +442,21 @@ Size SvxFont::GetPhysTxtSize( const OutputDevice *pOut, 
const OUString &rTxt,
     }
 
     if( IsKern() && ( nLen > 1 ) )
-        aTxtSize.AdjustWidth( ( nLen-1 ) * tools::Long( nKern ) );
+    {
+        std::vector<sal_Int32> aDXArray(nLen);
+        GetTextArray(pOut, rTxt, &aDXArray, nIdx, nLen);
+        tools::Long nOldValue = aDXArray[0];
+        sal_Int32 nSpaceCount = 0;
+        for(sal_Int32 i = 1; i < nLen; ++i)
+        {
+            if (aDXArray[i] != nOldValue)
+            {
+                nOldValue = aDXArray[i];
+                ++nSpaceCount;
+            }
+        }
+        aTxtSize.AdjustWidth( nSpaceCount * tools::Long( nKern ) );
+    }
 
     return aTxtSize;
 }
@@ -453,13 +476,6 @@ Size SvxFont::GetPhysTxtSize( const OutputDevice *pOut )
     return aTxtSize;
 }
 
-static tools::Long GetTextArray( const OutputDevice* pOut, const OUString& 
rStr, std::vector<sal_Int32>* pDXAry,
-                                 sal_Int32 nIndex, sal_Int32 nLen )
-{
-    const SalLayoutGlyphs* layoutGlyphs = 
SalLayoutGlyphsCache::self()->GetLayoutGlyphs(pOut, rStr, nIndex, nLen);
-    return pOut->GetTextArray( rStr, pDXAry, nIndex, nLen, nullptr, 
layoutGlyphs);
-}
-
 Size SvxFont::QuickGetTextSize( const OutputDevice *pOut, const OUString &rTxt,
                          const sal_Int32 nIdx, const sal_Int32 nLen, 
std::vector<sal_Int32>* pDXArray ) const
 {
@@ -467,6 +483,15 @@ Size SvxFont::QuickGetTextSize( const OutputDevice *pOut, 
const OUString &rTxt,
         return Size( GetTextArray( pOut, rTxt, pDXArray, nIdx, nLen ),
                      pOut->GetTextHeight() );
 
+    std::vector<sal_Int32>  aDXArray;
+
+    // We always need pDXArray to count the number of kern spaces
+    if (!pDXArray && IsKern() && nLen > 1)
+    {
+        pDXArray = &aDXArray;
+        aDXArray.reserve(nLen);
+    }
+
     Size aTxtSize;
     aTxtSize.setHeight( pOut->GetTextHeight() );
     if ( !IsCaseMap() )
@@ -477,16 +502,29 @@ Size SvxFont::QuickGetTextSize( const OutputDevice *pOut, 
const OUString &rTxt,
 
     if( IsKern() && ( nLen > 1 ) )
     {
-        aTxtSize.AdjustWidth( ( nLen-1 ) * tools::Long( nKern ) );
+        tools::Long nOldValue = (*pDXArray)[0];
+        tools::Long nSpaceSum = nKern;
+        (*pDXArray)[0] += nSpaceSum;
 
-        if ( pDXArray )
+        for ( sal_Int32 i = 1; i < nLen; i++ )
         {
-            for ( sal_Int32 i = 0; i < nLen; i++ )
-                (*pDXArray)[i] += ( (i+1) * tools::Long( nKern ) );
-            // The last one is a nKern too big:
-            (*pDXArray)[nLen-1] -= nKern;
+            if ( (*pDXArray)[i] != nOldValue )
+            {
+                nOldValue = (*pDXArray)[i];
+                nSpaceSum += nKern;
+            }
+            (*pDXArray)[i] += nSpaceSum;
         }
+
+        // The last one is a nKern too big:
+        nOldValue = (*pDXArray)[nLen - 1];
+        tools::Long nNewValue = nOldValue - nKern;
+        for ( sal_Int32 i = nLen - 1; i >= 0 && (*pDXArray)[i] == nOldValue; 
--i)
+            (*pDXArray)[i] = nNewValue;
+
+        aTxtSize.AdjustWidth(nSpaceSum - nKern);
     }
+
     return aTxtSize;
 }
 

Reply via email to