+ 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") ) ;
+ }
+}
+
+
+#pragma mark -
+
+wxDC::wxDC()
+{
+ m_ok = false ;
+ m_colour = true;
+ m_mm_to_pix_x = mm2pt;
+ m_mm_to_pix_y = mm2pt;
+
+ m_externalDeviceOriginX = 0;
+ m_externalDeviceOriginY = 0;
+ m_logicalScaleX = 1.0;
+ m_logicalScaleY = 1.0;
+ m_userScaleX = 1.0;
+ m_userScaleY = 1.0;
+ m_scaleX = 1.0;
+ m_scaleY = 1.0;
+ m_needComputeScaleX =
+ m_needComputeScaleY = false;
+
+ m_macPort = 0 ;
+ m_macLocalOrigin.x =
+ m_macLocalOrigin.y = 0 ;
+
+ m_pen = *wxBLACK_PEN;
+ m_font = *wxNORMAL_FONT;
+ m_brush = *wxWHITE_BRUSH;
+
+ m_macATSUIStyle = NULL ;
+ m_graphicContext = NULL ;
+}
+
+wxDC::~wxDC()
+{
+ if ( m_macATSUIStyle )
+ {
+ ::ATSUDisposeStyle((ATSUStyle)m_macATSUIStyle);
+ m_macATSUIStyle = NULL ;
+ }
+
+ delete m_graphicContext ;
+}
+
+void wxDC::DoDrawBitmap( const wxBitmap &bmp, wxCoord x, wxCoord y, bool useMask )
+{
+ wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoDrawBitmap - invalid DC") );
+ wxCHECK_RET( bmp.Ok(), wxT("wxDC(cg)::DoDrawBitmap - invalid bitmap") );
+
+ wxCoord xx = XLOG2DEVMAC(x);
+ wxCoord yy = YLOG2DEVMAC(y);
+ wxCoord w = bmp.GetWidth();
+ wxCoord h = bmp.GetHeight();
+ wxCoord ww = XLOG2DEVREL(w);
+ wxCoord hh = YLOG2DEVREL(h);
+
+ if ( bmp.GetDepth()==1 )
+ {
+ wxGraphicPath* path = m_graphicContext->CreatePath() ;
+ path->AddRectangle( xx , yy , ww , hh ) ;
+ m_graphicContext->FillPath( path , m_textBackgroundColour, wxODDEVEN_RULE) ;
+ delete path;
+ m_graphicContext->DrawBitmap( bmp, xx , yy , ww , hh ) ;
+ }
+ else
+ {
+ m_graphicContext->DrawBitmap( bmp, xx , yy , ww , hh ) ;
+ }
+}
+
+void wxDC::DoDrawIcon( const wxIcon &icon, wxCoord x, wxCoord y )
+{
+ wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoDrawIcon - invalid DC") );
+ wxCHECK_RET( icon.Ok(), wxT("wxDC(cg)::DoDrawIcon - invalid icon") );
+
+ wxCoord xx = XLOG2DEVMAC(x);
+ wxCoord yy = YLOG2DEVMAC(y);
+ wxCoord w = icon.GetWidth();
+ wxCoord h = icon.GetHeight();
+ wxCoord ww = XLOG2DEVREL(w);
+ wxCoord hh = YLOG2DEVREL(h);
+
+ m_graphicContext->DrawIcon( icon , xx, yy, ww, hh ) ;
+}
+
+void wxDC::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
+{
+ wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoSetClippingRegion - invalid DC") );
+
+ wxCoord xx, yy, ww, hh;
+ xx = XLOG2DEVMAC(x);
+ yy = YLOG2DEVMAC(y);
+ ww = XLOG2DEVREL(width);
+ hh = YLOG2DEVREL(height);
+
+ CGContextRef cgContext = ((wxMacCGContext*)(m_graphicContext))->GetNativeContext() ;
+ CGRect clipRect = CGRectMake( xx , yy , ww, hh ) ;
+ CGContextClipToRect( cgContext , clipRect ) ;
+
+// SetRectRgn( (RgnHandle) m_macCurrentClipRgn , xx , yy , xx + ww , yy + hh ) ;
+// SectRgn( (RgnHandle) m_macCurrentClipRgn , (RgnHandle) m_macBoundaryClipRgn , (RgnHandle) m_macCurrentClipRgn ) ;
+
+ if ( m_clipping )
+ {
+ m_clipX1 = wxMax( m_clipX1, xx );
+ m_clipY1 = wxMax( m_clipY1, yy );
+ m_clipX2 = wxMin( m_clipX2, (xx + ww) );
+ m_clipY2 = wxMin( m_clipY2, (yy + hh) );
+ }
+ else
+ {
+ m_clipping = true;
+
+ m_clipX1 = xx;
+ m_clipY1 = yy;
+ m_clipX2 = xx + ww;
+ m_clipY2 = yy + hh;
+ }
+
+ // TODO: as soon as we don't reset the context for each operation anymore
+ // we have to update the context as well
+}
+
+void wxDC::DoSetClippingRegionAsRegion( const wxRegion ®ion )
+{
+ wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoSetClippingRegionAsRegion - invalid DC") );
+