diff options
author | Armin Le Grand <alg@apache.org> | 2014-07-14 19:09:11 +0000 |
---|---|---|
committer | Armin Le Grand <alg@apache.org> | 2014-07-14 19:09:11 +0000 |
commit | 3c1d4742e649fe9c8aed8c2817fe3e1f3364f298 (patch) | |
tree | e0c6e02c89aa9227726c9469da1001b3e29c41df /vcl/aqua/source/gdi/ctlayout.cxx | |
parent | c5c31e2aeaedbdf76e1f38d3c385e34f5ed875ca (diff) |
Resync to trunk, windows non-pro buildaoo/aw080
Diffstat (limited to 'vcl/aqua/source/gdi/ctlayout.cxx')
-rw-r--r-- | vcl/aqua/source/gdi/ctlayout.cxx | 86 |
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; } // ----------------------------------------------------------------------- |