Author: hdu
Date: Tue May 20 12:00:50 2014
New Revision: 1596218

URL: http://svn.apache.org/r1596218
Log:
#i124935# fix expanded/condensed text breaking in the CoreText engine

the concept of an extra-width per code-unit was obsolete at least since apps
supported unicode with its different normalization forms, diacritical marks,
surrogate-pairs, non-printing characters such as ZWJ/ZWNJ/RLM, etc.  so of
course modern engines like CoreText don't aid this typographical crime.

The fix here extends the CTLayout::GetTextBreak() method to handle the obsolete
semantic of per code-unit extra-widths by successively approximating the number
of involved code-units.

Modified:
    openoffice/trunk/main/vcl/aqua/source/gdi/ctlayout.cxx

Modified: openoffice/trunk/main/vcl/aqua/source/gdi/ctlayout.cxx
URL: 
http://svn.apache.org/viewvc/openoffice/trunk/main/vcl/aqua/source/gdi/ctlayout.cxx?rev=1596218&r1=1596217&r2=1596218&view=diff
==============================================================================
--- openoffice/trunk/main/vcl/aqua/source/gdi/ctlayout.cxx (original)
+++ openoffice/trunk/main/vcl/aqua/source/gdi/ctlayout.cxx Tue May 20 12:00:50 
2014
@@ -451,13 +451,35 @@ int CTLayout::GetTextBreak( long nMaxWid
                return STRING_LEN;
 
        CTTypesetterRef aCTTypeSetter = CTTypesetterCreateWithAttributedString( 
mpAttrString );
-       const double fCTMaxWidth = (double)nMaxWidth / (nFactor * mfFontScale);
-       CFIndex nIndex = CTTypesetterSuggestClusterBreak( aCTTypeSetter, 0, 
fCTMaxWidth );
-       if( nIndex >= mnCharCount )
-               return STRING_LEN;
 
-       nIndex += mnMinCharPos;
-       return (int)nIndex;
+       CFIndex nBestGuess = (nCharExtra >= 0) ? 0 : mnCharCount;
+       for( int i = 1; i <= mnCharCount; i *= 2 )
+       {
+               // guess the target width considering char-extra 
expansion/condensation
+               const long nTargetWidth = nMaxWidth - nBestGuess * nCharExtra;
+               const double fCTMaxWidth = nTargetWidth / (nFactor * 
mfFontScale);
+               // calculate the breaking index for the guessed target width
+               const CFIndex nNewIndex = CTTypesetterSuggestClusterBreak( 
aCTTypeSetter, 0, fCTMaxWidth );
+               if( nNewIndex >= mnCharCount ) {
+                       CFRelease( aCTTypeSetter );
+                       return STRING_LEN;
+               }
+               // check if the original extra-width guess was good
+               if( !nCharExtra )
+                       nBestGuess = nNewIndex;
+               if( nBestGuess == nNewIndex )
+                       break;
+               // prepare another round for a different number of characters
+               CFIndex nNewGuess = (nNewIndex + nBestGuess + 1) / 2;
+               if( nNewGuess == nBestGuess )
+                       nNewGuess += (nNewIndex > nBestGuess) ? +1 : -1;
+               nBestGuess = nNewGuess;
+       }
+
+       // suggest the best fitting cluster break as breaking position
+       CFRelease( aCTTypeSetter );
+       const int nIndex = nBestGuess + mnMinCharPos;
+       return nIndex;
 }
 
 // -----------------------------------------------------------------------


Reply via email to