+ Fixed atsuAngle = IntToFixed( iAngle ) ;
+ ATSUAttributeTag atsuTags[] =
+ {
+ kATSULineRotationTag ,
+ } ;
+ ByteCount atsuSizes[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
+ {
+ sizeof( Fixed ) ,
+ } ;
+ ATSUAttributeValuePtr atsuValues[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
+ {
+ &atsuAngle ,
+ } ;
+ status = ::ATSUSetLayoutControls(atsuLayout , sizeof(atsuTags) / sizeof(ATSUAttributeTag),
+ atsuTags, atsuSizes, atsuValues ) ;
+ }
+
+ {
+ ATSUAttributeTag atsuTags[] =
+ {
+ kATSUCGContextTag ,
+ } ;
+ ByteCount atsuSizes[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
+ {
+ sizeof( CGContextRef ) ,
+ } ;
+ ATSUAttributeValuePtr atsuValues[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
+ {
+ &m_cgContext ,
+ } ;
+ status = ::ATSUSetLayoutControls(atsuLayout , sizeof(atsuTags) / sizeof(ATSUAttributeTag),
+ atsuTags, atsuSizes, atsuValues ) ;
+ }
+
+ ATSUTextMeasurement textBefore, textAfter ;
+ ATSUTextMeasurement ascent, descent ;
+
+ status = ::ATSUGetUnjustifiedBounds( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd,
+ &textBefore , &textAfter, &ascent , &descent );
+
+ wxASSERT_MSG( status == noErr , wxT("couldn't measure the rotated text") );
+
+ Rect rect ;
+/*
+ // TODO
+ if ( m_backgroundMode == wxSOLID )
+ {
+ wxGraphicPath* path = m_graphicContext->CreatePath() ;
+ path->MoveToPoint( drawX , drawY ) ;
+ path->AddLineToPoint(
+ (int) (drawX + sin(angle / RAD2DEG) * FixedToInt(ascent + descent)) ,
+ (int) (drawY + cos(angle / RAD2DEG) * FixedToInt(ascent + descent)) ) ;
+ path->AddLineToPoint(
+ (int) (drawX + sin(angle / RAD2DEG) * FixedToInt(ascent + descent ) + cos(angle / RAD2DEG) * FixedToInt(textAfter)) ,
+ (int) (drawY + cos(angle / RAD2DEG) * FixedToInt(ascent + descent) - sin(angle / RAD2DEG) * FixedToInt(textAfter)) ) ;
+ path->AddLineToPoint(
+ (int) (drawX + cos(angle / RAD2DEG) * FixedToInt(textAfter)) ,
+ (int) (drawY - sin(angle / RAD2DEG) * FixedToInt(textAfter)) ) ;
+
+ m_graphicContext->FillPath( path , m_textBackgroundColour ) ;
+ delete path ;
+ }
+*/
+ x += (int)(sin(angle / RAD2DEG) * FixedToInt(ascent));
+ y += (int)(cos(angle / RAD2DEG) * FixedToInt(ascent));
+
+ status = ::ATSUMeasureTextImage( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd,
+ IntToFixed(x) , IntToFixed(y) , &rect );
+ wxASSERT_MSG( status == noErr , wxT("couldn't measure the rotated text") );
+
+ CGContextSaveGState(m_cgContext);
+ CGContextTranslateCTM(m_cgContext, x, y);
+ CGContextScaleCTM(m_cgContext, 1, -1);
+ status = ::ATSUDrawText( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd,
+ IntToFixed(0) , IntToFixed(0) );
+
+ wxASSERT_MSG( status == noErr , wxT("couldn't draw the rotated text") );
+
+ CGContextRestoreGState(m_cgContext) ;
+
+ ::ATSUDisposeTextLayout(atsuLayout);
+
+#if SIZEOF_WCHAR_T == 4
+ free( ubuf ) ;
+#endif
+}
+
+void wxMacCGContext::GetTextExtent( const wxString &str, wxCoord *width, wxCoord *height,
+ wxCoord *descent, wxCoord *externalLeading ) const
+{
+ wxCHECK_RET( m_macATSUIStyle != NULL, wxT("wxDC(cg)::DoGetTextExtent - no valid font set") ) ;
+
+ OSStatus status = noErr ;
+
+ ATSUTextLayout atsuLayout ;
+ UniCharCount chars = str.length() ;
+ UniChar* ubuf = NULL ;
+
+#if SIZEOF_WCHAR_T == 4
+ wxMBConvUTF16 converter ;
+#if wxUSE_UNICODE
+ size_t unicharlen = converter.WC2MB( NULL , str.wc_str() , 0 ) ;
+ ubuf = (UniChar*) malloc( unicharlen + 2 ) ;
+ converter.WC2MB( (char*) ubuf , str.wc_str(), unicharlen + 2 ) ;
+#else
+ const wxWCharBuffer wchar = str.wc_str( wxConvLocal ) ;
+ size_t unicharlen = converter.WC2MB( NULL , wchar.data() , 0 ) ;
+ ubuf = (UniChar*) malloc( unicharlen + 2 ) ;
+ converter.WC2MB( (char*) ubuf , wchar.data() , unicharlen + 2 ) ;
+#endif
+ chars = unicharlen / 2 ;
+#else
+#if wxUSE_UNICODE
+ ubuf = (UniChar*) str.wc_str() ;
+#else
+ wxWCharBuffer wchar = str.wc_str( wxConvLocal ) ;
+ chars = wxWcslen( wchar.data() ) ;
+ ubuf = (UniChar*) wchar.data() ;
+#endif
+#endif
+
+ status = ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr) ubuf , 0 , chars , chars , 1 ,
+ &chars , (ATSUStyle*) &m_macATSUIStyle , &atsuLayout ) ;
+
+ wxASSERT_MSG( status == noErr , wxT("couldn't create the layout of the text") );
+
+ ATSUTextMeasurement textBefore, textAfter ;
+ ATSUTextMeasurement textAscent, textDescent ;
+
+ status = ::ATSUGetUnjustifiedBounds( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd,
+ &textBefore , &textAfter, &textAscent , &textDescent );
+
+ if ( height )
+ *height = FixedToInt(textAscent + textDescent) ;
+ if ( descent )
+ *descent = FixedToInt(textDescent) ;
+ if ( externalLeading )
+ *externalLeading = 0 ;
+ if ( width )
+ *width = FixedToInt(textAfter - textBefore) ;
+
+ ::ATSUDisposeTextLayout(atsuLayout);
+}
+
+void wxMacCGContext::GetPartialTextExtents(const wxString& text, wxArrayInt& widths) const
+{
+ widths.Empty();
+ widths.Add(0, text.length());
+
+ if (text.empty())
+ return ;
+
+ ATSUTextLayout atsuLayout ;
+ UniCharCount chars = text.length() ;
+ UniChar* ubuf = NULL ;
+
+#if SIZEOF_WCHAR_T == 4
+ wxMBConvUTF16 converter ;
+#if wxUSE_UNICODE
+ size_t unicharlen = converter.WC2MB( NULL , text.wc_str() , 0 ) ;
+ ubuf = (UniChar*) malloc( unicharlen + 2 ) ;
+ converter.WC2MB( (char*) ubuf , text.wc_str(), unicharlen + 2 ) ;
+#else
+ const wxWCharBuffer wchar = text.wc_str( wxConvLocal ) ;
+ size_t unicharlen = converter.WC2MB( NULL , wchar.data() , 0 ) ;
+ ubuf = (UniChar*) malloc( unicharlen + 2 ) ;
+ converter.WC2MB( (char*) ubuf , wchar.data() , unicharlen + 2 ) ;
+#endif
+ chars = unicharlen / 2 ;
+#else
+#if wxUSE_UNICODE
+ ubuf = (UniChar*) text.wc_str() ;
+#else
+ wxWCharBuffer wchar = text.wc_str( wxConvLocal ) ;
+ chars = wxWcslen( wchar.data() ) ;
+ ubuf = (UniChar*) wchar.data() ;
+#endif
+#endif
+
+ ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr) ubuf , 0 , chars , chars , 1 ,
+ &chars , (ATSUStyle*) &m_macATSUIStyle , &atsuLayout ) ;
+
+ for ( int pos = 0; pos < (int)chars; pos ++ )
+ {
+ unsigned long actualNumberOfBounds = 0;
+ ATSTrapezoid glyphBounds;
+
+ // We get a single bound, since the text should only require one. If it requires more, there is an issue
+ OSStatus result;
+ result = ATSUGetGlyphBounds( atsuLayout, 0, 0, kATSUFromTextBeginning, pos + 1,
+ kATSUseDeviceOrigins, 1, &glyphBounds, &actualNumberOfBounds );
+ if (result != noErr || actualNumberOfBounds != 1 )
+ return ;
+
+ widths[pos] = FixedToInt( glyphBounds.upperRight.x - glyphBounds.upperLeft.x );
+ //unsigned char uch = s[i];
+ }
+
+ ::ATSUDisposeTextLayout(atsuLayout);
+}
+
+void wxMacCGContext::SetFont( const wxFont &font )
+{
+ if ( m_macATSUIStyle )
+ {
+ ::ATSUDisposeStyle((ATSUStyle)m_macATSUIStyle);
+ m_macATSUIStyle = NULL ;
+ }
+
+ if ( font.Ok() )
+ {
+ OSStatus status ;
+
+ status = ATSUCreateAndCopyStyle( (ATSUStyle) font.MacGetATSUStyle() , (ATSUStyle*) &m_macATSUIStyle ) ;
+
+ wxASSERT_MSG( status == noErr, wxT("couldn't create ATSU style") ) ;
+
+ // we need the scale here ...
+
+ Fixed atsuSize = IntToFixed( int( /*m_scaleY*/ 1 * font.MacGetFontSize()) ) ;
+ RGBColor atsuColor = MAC_WXCOLORREF( m_textForegroundColor.GetPixel() ) ;
+ ATSUAttributeTag atsuTags[] =
+ {
+ kATSUSizeTag ,
+ kATSUColorTag ,
+ } ;
+ ByteCount atsuSizes[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
+ {
+ sizeof( Fixed ) ,
+ sizeof( RGBColor ) ,
+ } ;
+ ATSUAttributeValuePtr atsuValues[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
+ {
+ &atsuSize ,
+ &atsuColor ,
+ } ;
+
+ status = ::ATSUSetAttributes(
+ (ATSUStyle)m_macATSUIStyle, sizeof(atsuTags) / sizeof(ATSUAttributeTag) ,
+ atsuTags, atsuSizes, atsuValues);
+
+ wxASSERT_MSG( status == noErr , wxT("couldn't modify ATSU style") ) ;