summaryrefslogtreecommitdiff
path: root/vcl/aqua/source/gdi/ctlayout.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/aqua/source/gdi/ctlayout.cxx')
-rw-r--r--vcl/aqua/source/gdi/ctlayout.cxx86
1 files changed, 63 insertions, 23 deletions
diff --git a/vcl/aqua/source/gdi/ctlayout.cxx b/vcl/aqua/source/gdi/ctlayout.cxx
index 88b912f74fc0..aac5e77f8d52 100644
--- a/vcl/aqua/source/gdi/ctlayout.cxx
+++ b/vcl/aqua/source/gdi/ctlayout.cxx
@@ -52,9 +52,8 @@ public:
virtual void Simplify( bool bIsBase );
private:
- const CTTextStyle* const mpTextStyle;
-
// CoreText specific objects
+ CFMutableDictionaryRef mpStyleDict;
CFAttributedStringRef mpAttrString;
CTLineRef mpCTLine;
@@ -67,6 +66,9 @@ private:
// in these cases the font scale becomes something bigger than 1.0
float mfFontScale; // TODO: does CoreText have a font size limit?
+ CGFloat mfFontRotation; // text direction angle (in radians)
+ CGFloat mfFontStretch; // <1.0: font gets squeezed, >1.0: font gets stretched
+
// cached details about the resulting layout
// mutable members since these details are all lazy initialized
mutable double mfCachedWidth; // cached value of resulting typographical width
@@ -79,17 +81,19 @@ private:
// =======================================================================
CTLayout::CTLayout( const CTTextStyle* pTextStyle )
-: mpTextStyle( pTextStyle )
+: mpStyleDict( pTextStyle->GetStyleDict() )
, mpAttrString( NULL )
, mpCTLine( NULL )
, mnCharCount( 0 )
, mnTrailingSpaceCount( 0 )
, mfTrailingSpaceWidth( 0.0 )
, mfFontScale( pTextStyle->mfFontScale )
+, mfFontRotation( pTextStyle->mfFontRotation )
+, mfFontStretch( pTextStyle->mfFontStretch )
, mfCachedWidth( -1 )
, mnBaseAdv( 0 )
{
- CFRetain( mpTextStyle->GetStyleDict() );
+ CFRetain( mpStyleDict );
}
// -----------------------------------------------------------------------
@@ -100,13 +104,14 @@ CTLayout::~CTLayout()
CFRelease( mpCTLine );
if( mpAttrString )
CFRelease( mpAttrString );
- CFRelease( mpTextStyle->GetStyleDict() );
+ CFRelease( mpStyleDict );
}
// -----------------------------------------------------------------------
bool CTLayout::LayoutText( ImplLayoutArgs& rArgs )
{
+ // release an eventual older layout
if( mpAttrString )
CFRelease( mpAttrString );
mpAttrString = NULL;
@@ -114,6 +119,7 @@ bool CTLayout::LayoutText( ImplLayoutArgs& rArgs )
CFRelease( mpCTLine );
mpCTLine = NULL;
+ // initialize the new layout
SalLayout::AdjustLayout( rArgs );
mnCharCount = mnEndCharPos - mnMinCharPos;
@@ -121,9 +127,17 @@ bool CTLayout::LayoutText( ImplLayoutArgs& rArgs )
if( mnCharCount <= 0 )
return false;
- // create the CoreText line layout
+ // prepare the string to be layouted by CoreText
CFStringRef aCFText = CFStringCreateWithCharactersNoCopy( NULL, rArgs.mpStr + mnMinCharPos, mnCharCount, kCFAllocatorNull );
- mpAttrString = CFAttributedStringCreate( NULL, aCFText, mpTextStyle->GetStyleDict() );
+ // #i124375# force soft-hyphen visibility to meet the expectations of Writer+EditEngine
+ if( CFStringFind( aCFText, (CFStringRef)@"\u00AD", 0).length > 0 )
+ {
+ NSString* pDashStr = [(NSString*)aCFText stringByReplacingOccurrencesOfString: @"\u00AD" withString: @"-"];
+ aCFText = CFStringCreateCopy( NULL, (CFStringRef)pDashStr );
+ }
+
+ // create the CoreText line layout using the requested text style
+ mpAttrString = CFAttributedStringCreate( NULL, aCFText, mpStyleDict );
mpCTLine = CTLineCreateWithAttributedString( mpAttrString );
CFRelease( aCFText);
@@ -193,7 +207,7 @@ void CTLayout::AdjustLayout( ImplLayoutArgs& rArgs )
CFRelease( mpCTLine );
CFStringRef aCFText = CFStringCreateWithCharactersNoCopy( NULL, rArgs.mpStr + mnMinCharPos,
mnCharCount - mnTrailingSpaceCount, kCFAllocatorNull );
- CFAttributedStringRef pAttrStr = CFAttributedStringCreate( NULL, aCFText, mpTextStyle->GetStyleDict() );
+ CFAttributedStringRef pAttrStr = CFAttributedStringCreate( NULL, aCFText, mpStyleDict );
mpCTLine = CTLineCreateWithAttributedString( pAttrStr );
CFRelease( aCFText);
CFRelease( pAttrStr );
@@ -237,23 +251,21 @@ void CTLayout::DrawText( SalGraphics& rGraphics ) const
CGContextScaleCTM( rAquaGraphics.mrContext, +mfFontScale, -mfFontScale );
CGContextSetShouldAntialias( rAquaGraphics.mrContext, !rAquaGraphics.mbNonAntialiasedText );
- // Draw the text
+ // set the text transformation (e.g. position)
const Point aVclPos = GetDrawPosition( Point(mnBaseAdv,0) );
CGPoint aTextPos = { +aVclPos.X()/mfFontScale, -aVclPos.Y()/mfFontScale };
- if( mpTextStyle->mfFontRotation != 0.0 )
+ if( mfFontRotation != 0.0 )
{
- const CGFloat fRadians = mpTextStyle->mfFontRotation;
- CGContextRotateCTM( rAquaGraphics.mrContext, +fRadians );
+ CGContextRotateCTM( rAquaGraphics.mrContext, +mfFontRotation );
- const CGAffineTransform aInvMatrix = CGAffineTransformMakeRotation( -fRadians );
+ const CGAffineTransform aInvMatrix = CGAffineTransformMakeRotation( -mfFontRotation );
aTextPos = CGPointApplyAffineTransform( aTextPos, aInvMatrix );
}
CGContextSetTextPosition( rAquaGraphics.mrContext, aTextPos.x, aTextPos.y );
- CTLineDraw( mpCTLine, rAquaGraphics.mrContext );
- // request an update of the changed window area
+ // request an update of the to-be-changed window area
if( rAquaGraphics.IsWindowGraphics() )
{
const CGRect aInkRect = CTLineGetImageBounds( mpCTLine, rAquaGraphics.mrContext );
@@ -261,6 +273,12 @@ void CTLayout::DrawText( SalGraphics& rGraphics ) const
rAquaGraphics.RefreshRect( aRefreshRect );
}
+ // set the text color as fill color (see kCTForegroundColorFromContextAttributeName)
+ CGContextSetFillColor( rAquaGraphics.mrContext, rAquaGraphics.maTextColor.AsArray() );
+
+ // draw the text
+ CTLineDraw( mpCTLine, rAquaGraphics.mrContext );
+
// restore the original graphic context transformations
CGContextRestoreGState( rAquaGraphics.mrContext );
}
@@ -345,12 +363,12 @@ int CTLayout::GetNextGlyphs( int nLen, sal_GlyphId* pOutGlyphIds, Point& rPos, i
// convert glyph details for VCL
*(pOutGlyphIds++) = pCGGlyphIdx[ nSubIndex ];
if( pGlyphAdvances )
- *(pGlyphAdvances++) = pCGGlyphAdvs[ nSubIndex ].width;
+ *(pGlyphAdvances++) = mfFontStretch * pCGGlyphAdvs[ nSubIndex ].width;
if( pCharIndexes )
*(pCharIndexes++) = pCGGlyphStrIdx[ nSubIndex] + mnMinCharPos;
if( !nCount++ ) {
const CGPoint& rCurPos = pCGGlyphPos[ nSubIndex ];
- rPos = GetDrawPosition( Point( mfFontScale * rCurPos.x, mfFontScale * rCurPos.y) );
+ rPos = GetDrawPosition( Point( mfFontScale * mfFontStretch * rCurPos.x, mfFontScale * rCurPos.y) );
}
}
nSubIndex = 0; // prepare for the next glyph run
@@ -433,13 +451,35 @@ int CTLayout::GetTextBreak( long nMaxWidth, long nCharExtra, int nFactor ) const
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;
}
// -----------------------------------------------------------------------