[Libreoffice-commits] core.git: Branch 'libreoffice-5-0' - vcl/quartz

Thorsten Wagner thorsten.wagner.4 at gmail.com
Sun May 24 18:04:18 PDT 2015


 vcl/quartz/ctlayout.cxx |   60 +++++++++++++++++++++++++++++++++---------------
 1 file changed, 42 insertions(+), 18 deletions(-)

New commits:
commit 02fe9b00f9e779d69189dc011c82dce32c0446fc
Author: Thorsten Wagner <thorsten.wagner.4 at gmail.com>
Date:   Tue May 5 01:06:11 2015 +0200

    tdf#87373: Bad text spacing on OS X
    
    Adjustments to character positions less than one pixel are ignored.
    These adjustments are probably introduced by lossy conversions between
    integer based and float based coordinates.
    
    DXArray elements are adjusted to integers avoiding cummulated rounding
    differences.
    
    Change-Id: I65d476301247251a7d329b14adb70be367538c97
    Reviewed-on: https://gerrit.libreoffice.org/15633
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Khaled Hosny <khaledhosny at eglug.org>
    (cherry picked from commit 187af9b0c09f6ba57e994a25a756f0994beae7e5)
    Reviewed-on: https://gerrit.libreoffice.org/15887
    Tested-by: Norbert Thiebaud <nthiebaud at gmail.com>
    Reviewed-by: Norbert Thiebaud <nthiebaud at gmail.com>

diff --git a/vcl/quartz/ctlayout.cxx b/vcl/quartz/ctlayout.cxx
index 67733de..82d9c64 100644
--- a/vcl/quartz/ctlayout.cxx
+++ b/vcl/quartz/ctlayout.cxx
@@ -215,13 +215,17 @@ void CTLayout::AdjustLayout( ImplLayoutArgs& rArgs )
         return;
     }
 
-    DeviceCoordinate nPixelWidth = 0;
-
     if(rArgs.mpDXArray && !(rArgs.mnFlags & SalLayoutFlags::BiDiRtl) )
     {
-        nPixelWidth = rArgs.mpDXArray[ mnCharCount - 1 ];
-        if( nPixelWidth <= 0)
+        DeviceCoordinate nPixelWidth = rArgs.mpDXArray[ mnCharCount - 1 ];
+
+        // justification requests which change the width by just one pixel are probably
+        // introduced by lossy conversions between integer based coordinate system
+        DeviceCoordinate nOrigWidth = lrint( GetTextWidth() );
+        if( (nPixelWidth <= 0) || ((nOrigWidth >= rint( nPixelWidth - 1 )) && (nOrigWidth <= rint( nPixelWidth + 1 ))) )
+        {
             return;
+        }
         ApplyDXArray( rArgs );
         if( mnTrailingSpaceCount )
         {
@@ -230,13 +234,15 @@ void CTLayout::AdjustLayout( ImplLayoutArgs& rArgs )
                 rArgs.mpDXArray[ mnCharCount - mnTrailingSpaceCount - 1];
             mfTrailingSpaceWidth = nFullPixelWidth - nPixelWidth;
             if( nPixelWidth <= 0)
+            {
                 return;
+            }
         }
         mfCachedWidth = nPixelWidth;
     }
     else
     {
-        nPixelWidth = rArgs.mnLayoutWidth;
+        DeviceCoordinate nPixelWidth = rArgs.mnLayoutWidth;
 
         if( nPixelWidth <= 0 && rArgs.mnFlags & SalLayoutFlags::BiDiRtl)
         {
@@ -244,7 +250,9 @@ void CTLayout::AdjustLayout( ImplLayoutArgs& rArgs )
         }
 
         if( nPixelWidth <= 0)
+        {
             return;
+        }
 
         // if the text to be justified has whitespace in it then
         // - Writer goes crazy with its HalfSpace magic
@@ -721,21 +729,27 @@ DeviceCoordinate CTLayout::GetTextWidth() const
 
 DeviceCoordinate CTLayout::FillDXArray( DeviceCoordinate* pDXArray ) const
 {
-    DeviceCoordinate nPixWidth = GetTextWidth();
+    DeviceCoordinate nPixelWidth = GetTextWidth();
+
     // short circuit requests which don't need full details
     if( !pDXArray )
-        return nPixWidth;
+    {
+        return nPixelWidth;
+    }
 
     for(int i = 0; i < mnCharCount; i++)
     {
         pDXArray[i] = 0.0;
     }
+
+    // prepare the sub-pixel accurate logical-width array
+    ::std::vector<float> aWidthVector( mnCharCount );
     if( mnTrailingSpaceCount && (mfTrailingSpaceWidth > 0.0) )
     {
         const double fOneWidth = mfTrailingSpaceWidth / mnTrailingSpaceCount;
         for(int i = mnCharCount - mnTrailingSpaceCount; i < mnCharCount; i++)
         {
-            pDXArray[i] = fOneWidth;
+            aWidthVector[i] = fOneWidth;
         }
     }
 
@@ -743,9 +757,9 @@ DeviceCoordinate CTLayout::FillDXArray( DeviceCoordinate* pDXArray ) const
     CFArrayRef aGlyphRuns = CTLineGetGlyphRuns( mpCTLine );
     const int nRunCount = CFArrayGetCount( aGlyphRuns );
     typedef std::vector<CGSize> CGSizeVector;
-    CGSizeVector aSizeVec;
+    CGSizeVector aSizeVector;
     typedef std::vector<CFIndex> CFIndexVector;
-    CFIndexVector aIndexVec;
+    CFIndexVector aIndexVector;
 
     for( int nRunIndex = 0; nRunIndex < nRunCount; ++nRunIndex )
     {
@@ -753,19 +767,29 @@ DeviceCoordinate CTLayout::FillDXArray( DeviceCoordinate* pDXArray ) const
         const CFIndex nGlyphCount = CTRunGetGlyphCount( pGlyphRun );
         const CFRange aFullRange = CFRangeMake( 0, nGlyphCount );
 
-        aSizeVec.resize( nGlyphCount );
-        aIndexVec.resize( nGlyphCount );
-        CTRunGetAdvances( pGlyphRun, aFullRange, &aSizeVec[0] );
-        CTRunGetStringIndices( pGlyphRun, aFullRange, &aIndexVec[0] );
+        aSizeVector.resize( nGlyphCount );
+        aIndexVector.resize( nGlyphCount );
+        CTRunGetAdvances( pGlyphRun, aFullRange, &aSizeVector[0] );
+        CTRunGetStringIndices( pGlyphRun, aFullRange, &aIndexVector[0] );
 
         for( int i = 0; i != nGlyphCount; ++i )
         {
-            const int nRelIdx = aIndexVec[i];
-            SAL_INFO( "vcl.ct", "pDXArray[ g:" << i << "-> c:" << nRelIdx << " ] = " << pDXArray[nRelIdx] << " + " << aSizeVec[i].width << " = " << pDXArray[nRelIdx] + aSizeVec[i].width);
-            pDXArray[nRelIdx] += aSizeVec[i].width;
+            const int nRelIndex = aIndexVector[i];
+            SAL_INFO( "vcl.ct", "aWidthVector[ g:" << i << "-> c:" << nRelIndex << " ] = " << aWidthVector[nRelIndex] << " + " << aSizeVector[i].width << " = " << aWidthVector[nRelIndex] + aSizeVector[i].width);
+            aWidthVector[nRelIndex] += aSizeVector[i].width;
         }
     }
-    return nPixWidth;
+
+    // convert the sub-pixel accurate array into classic pDXArray integers
+    float fWidthSum = 0.0;
+    sal_Int32 nOldDX = 0;
+    for( int i = 0; i < mnCharCount; ++i)
+    {
+        const sal_Int32 nNewDX = rint( fWidthSum += aWidthVector[i]);
+        pDXArray[i] = nNewDX - nOldDX;
+        nOldDX = nNewDX;
+    }
+    return nPixelWidth;
 }
 
 sal_Int32 CTLayout::GetTextBreak( DeviceCoordinate nMaxWidth, DeviceCoordinate nCharExtra, int nFactor ) const


More information about the Libreoffice-commits mailing list