]> git.saurik.com Git - wxWidgets.git/blobdiff - src/mac/carbon/dc.cpp
#include "wx/settings.h" wxSystemSettings is needed by non-OSX code.
[wxWidgets.git] / src / mac / carbon / dc.cpp
index 420d5dce829fc5a9f1df26b50f901f3c6d355874..4e570147ca74251bc009afe01c853ec9da7599f1 100644 (file)
@@ -28,9 +28,10 @@ using namespace std ;
 #endif
 
 #include "wx/mac/private.h"
-#include "ATSUnicode.h"
-#include "TextCommon.h"
-#include "TextEncodingConverter.h"
+#include <ATSUnicode.h>
+#include <TextCommon.h>
+#include <TextEncodingConverter.h>
+#include <FixMath.h>
 #if !USE_SHARED_LIBRARY
 IMPLEMENT_ABSTRACT_CLASS(wxDC, wxObject)
 #endif
@@ -54,6 +55,11 @@ const double RAD2DEG  = 180.0 / M_PI;
 const short kEmulatedMode = -1 ;
 const short kUnsupportedMode = -2 ;
 
+extern TECObjectRef s_TECNativeCToUnicode ;
+
+// set to 0 if problems arise
+#define wxMAC_EXPERIMENTAL_DC 1
+
 wxMacPortSetter::wxMacPortSetter( const wxDC* dc ) :
     m_ph( (GrafPtr) dc->m_macPort )
 {
@@ -61,53 +67,87 @@ wxMacPortSetter::wxMacPortSetter( const wxDC* dc ) :
     m_dc = dc ;
     dc->MacSetupPort(&m_ph) ;
 }
-
 wxMacPortSetter::~wxMacPortSetter()
 {
     m_dc->MacCleanupPort(&m_ph) ;
 }
 
-wxMacWindowClipper::wxMacWindowClipper( const wxWindow* win ) 
+#if wxMAC_EXPERIMENTAL_DC
+class wxMacFastPortSetter
 {
+public :
+    wxMacFastPortSetter( const wxDC *dc ) 
+    {
+           wxASSERT( dc->Ok() ) ;
+           m_swapped = QDSwapPort( (GrafPtr) dc->m_macPort , &m_oldPort ) ;
+           m_clipRgn = NewRgn() ;
+           GetClip( m_clipRgn ) ;
+           m_dc = dc ;
+           dc->MacSetupPort( NULL ) ;
+    }
+    ~wxMacFastPortSetter()
+    {
+        // SetPort( (GrafPtr) m_dc->m_macPort ) ;
+        SetClip( m_clipRgn ) ;
+        if ( m_swapped )
+               SetPort( m_oldPort ) ;
+           m_dc->MacCleanupPort( NULL ) ;
+           DisposeRgn( m_clipRgn ) ;
+    }
+private :
+    bool m_swapped ;
+    RgnHandle m_clipRgn ;
+    GrafPtr m_oldPort ;
+    const wxDC*   m_dc ;
+} ;
+
+#else
+typedef wxMacPortSetter wxMacFastPortSetter ;
+#endif
+
+wxMacWindowClipper::wxMacWindowClipper( const wxWindow* win ) :
+    wxMacPortSaver( (GrafPtr) GetWindowPort((WindowRef) win->MacGetTopLevelWindowRef()) )
+{
+    m_newPort =(GrafPtr) GetWindowPort((WindowRef) win->MacGetTopLevelWindowRef()) ;
     m_formerClip = NewRgn() ;
     m_newClip = NewRgn() ;
     GetClip( m_formerClip ) ;
     
     if ( win )
     {
-#if 0
-        // this clipping area was set to the parent window's drawing area, lead to problems
-        // with MacOSX controls drawing outside their wx' rectangle
-        RgnHandle insidergn = NewRgn() ;
-        int x = 0 , y = 0;
-        wxWindow *parent = win->GetParent() ;
-        parent->MacWindowToRootWindow( &x,&y ) ;
-        wxSize size = parent->GetSize() ;
-        SetRectRgn( insidergn , parent->MacGetLeftBorderSize() , parent->MacGetTopBorderSize() , 
-            size.x - parent->MacGetRightBorderSize(), 
-            size.y - parent->MacGetBottomBorderSize()) ;
-        CopyRgn( (RgnHandle) parent->MacGetVisibleRegion(false).GetWXHRGN() , m_newClip ) ;
-        SectRgn( m_newClip , insidergn , m_newClip ) ;
-        OffsetRgn( m_newClip , x , y ) ;
-        SetClip( m_newClip ) ;
-        DisposeRgn( insidergn ) ;
-#else
         int x = 0 , y = 0;
         win->MacWindowToRootWindow( &x,&y ) ;
-        CopyRgn( (RgnHandle) ((wxWindow*)win)->MacGetVisibleRegion().GetWXHRGN() , m_newClip ) ;
-        OffsetRgn( m_newClip , x , y ) ;
+        // get area including focus rect
+        CopyRgn( (RgnHandle) ((wxWindow*)win)->MacGetVisibleRegion(true).GetWXHRGN() , m_newClip ) ;
+        if ( !EmptyRgn( m_newClip ) )
+            OffsetRgn( m_newClip , x , y ) ;
+
         SetClip( m_newClip ) ;
-#endif  
     }
 }
 
 wxMacWindowClipper::~wxMacWindowClipper() 
 {
+    SetPort( m_newPort ) ;
     SetClip( m_formerClip ) ;
     DisposeRgn( m_newClip ) ;
     DisposeRgn( m_formerClip ) ;
 }
 
+wxMacWindowStateSaver::wxMacWindowStateSaver( const wxWindow* win ) :
+    wxMacWindowClipper( win )
+{
+    // the port is already set at this point
+    m_newPort =(GrafPtr) GetWindowPort((WindowRef) win->MacGetTopLevelWindowRef()) ;
+    GetThemeDrawingState( &m_themeDrawingState ) ;
+}
+
+wxMacWindowStateSaver::~wxMacWindowStateSaver() 
+{
+    SetPort( m_newPort ) ;
+    SetThemeDrawingState( m_themeDrawingState , true ) ;
+}
+
 //-----------------------------------------------------------------------------
 // Local functions
 //-----------------------------------------------------------------------------
@@ -262,11 +302,12 @@ void wxDC::MacSetupPort(wxMacPortStateHelper* help) const
     m_macCurrentPortStateHelper = help ;
 #endif
     SetClip( (RgnHandle) m_macCurrentClipRgn);
+#if ! wxMAC_EXPERIMENTAL_DC
     m_macFontInstalled = false ;
     m_macBrushInstalled = false ;
     m_macPenInstalled = false ;
+#endif
 }
-
 void wxDC::MacCleanupPort(wxMacPortStateHelper* help) const
 {
 #ifdef __WXDEBUG__
@@ -303,7 +344,7 @@ void wxDC::DoDrawBitmap( const wxBitmap &bmp, wxCoord x, wxCoord y, bool useMask
 {
      wxCHECK_RET( Ok(), wxT("invalid window dc") );
      wxCHECK_RET( bmp.Ok(), wxT("invalid bitmap") );
-     wxMacPortSetter helper(this) ;
+     wxMacFastPortSetter helper(this) ;
      wxCoord xx = XLOG2DEVMAC(x);
      wxCoord yy = YLOG2DEVMAC(y);
      wxCoord w = bmp.GetWidth();
@@ -422,12 +463,12 @@ void wxDC::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord hei
 void wxDC::DoSetClippingRegionAsRegion( const wxRegion &region  )
 {
     wxCHECK_RET( Ok(), wxT("invalid window dc") ) ;
-      wxMacPortSetter helper(this) ;
     if (region.Empty())
     {
         DestroyClippingRegion();
         return;
     }
+    wxMacFastPortSetter helper(this) ;
     wxCoord x, y, w, h;
     region.GetBox( x, y, w, h );
     wxCoord xx, yy, ww, hh;
@@ -469,9 +510,9 @@ void wxDC::DoSetClippingRegionAsRegion( const wxRegion &region  )
 
 void wxDC::DestroyClippingRegion()
 {
-    wxMacPortSetter helper(this) ;
+    wxMacFastPortSetter helper(this) ;
     CopyRgn( (RgnHandle) m_macBoundaryClipRgn , (RgnHandle) m_macCurrentClipRgn ) ;
-    m_clipping = FALSE;
+    ResetClipping();
 }
 
 void wxDC::DoGetSizeMM( int* width, int* height ) const
@@ -555,20 +596,6 @@ void wxDC::SetDeviceOrigin( wxCoord x, wxCoord y )
     ComputeScaleAndOrigin();
 }
 
-#if 0
-void wxDC::SetInternalDeviceOrigin( long x, long y )
-{
-    m_internalDeviceOriginX = x;
-    m_internalDeviceOriginY = y;
-    ComputeScaleAndOrigin();
-}
-void wxDC::GetInternalDeviceOrigin( long *x, long *y )
-{
-    if (x) *x = m_internalDeviceOriginX;
-    if (y) *y = m_internalDeviceOriginY;
-}
-#endif
-
 void wxDC::SetAxisOrientation( bool xLeftRight, bool yBottomUp )
 {
     m_signX = (xLeftRight ?  1 : -1);
@@ -604,10 +631,9 @@ void wxDC::ComputeScaleAndOrigin()
     {
         // this is a bit artificial, but we need to force wxDC to think
         // the pen has changed
-        wxPen* pen = & GetPen();
-        wxPen tempPen;
-        m_pen = tempPen;
-        SetPen(* pen);
+        wxPen pen(GetPen());
+        m_pen = wxNullPen;
+        SetPen(pen);
     }
 }
 
@@ -674,7 +700,7 @@ bool wxDC::DoFloodFill(wxCoord x, wxCoord y,
 bool  wxDC::DoGetPixel( wxCoord x, wxCoord y, wxColour *col ) const
 {
     wxCHECK_MSG( Ok(), false, wxT("wxDC::DoGetPixel  Invalid DC") );
-    wxMacPortSetter helper(this) ;
+    wxMacFastPortSetter helper(this) ;
     RGBColor colour;
     GetCPixel( XLOG2DEVMAC(x), YLOG2DEVMAC(y), &colour );
     // Convert from Mac colour to wx
@@ -687,7 +713,7 @@ bool  wxDC::DoGetPixel( wxCoord x, wxCoord y, wxColour *col ) const
 void  wxDC::DoDrawLine( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2 )
 {
     wxCHECK_RET(Ok(), wxT("Invalid DC"));
-    wxMacPortSetter helper(this) ;
+    wxMacFastPortSetter helper(this) ;
     if (m_pen.GetStyle() != wxTRANSPARENT)
     {
         MacInstallPen() ;
@@ -725,7 +751,7 @@ void  wxDC::DoDrawLine( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2 )
 void  wxDC::DoCrossHair( wxCoord x, wxCoord y )
 {
     wxCHECK_RET( Ok(), wxT("wxDC::DoCrossHair  Invalid window dc") );
-    wxMacPortSetter helper(this) ;
+    wxMacFastPortSetter helper(this) ;
     if (m_pen.GetStyle() != wxTRANSPARENT)
     {
         int w = 0;
@@ -755,8 +781,8 @@ void  wxDC::DoCrossHair( wxCoord x, wxCoord y )
 static double wxConvertWXangleToMACangle(double angle)
 {
     double newAngle = 90 - angle ;
-    if ( newAngle < 0 )
-        newAngle += 360 ;
+    while ( newAngle > 360 ) newAngle -= 360 ;
+    while ( newAngle < 0 ) newAngle += 360 ;
     return newAngle ;
 }
 
@@ -765,7 +791,7 @@ void  wxDC::DoDrawArc( wxCoord x1, wxCoord y1,
                       wxCoord xc, wxCoord yc )
 {
     wxCHECK_RET(Ok(), wxT("wxDC::DoDrawArc  Invalid DC"));
-    wxMacPortSetter helper(this) ;
+    wxMacFastPortSetter helper(this) ;
     wxCoord xx1 = XLOG2DEVMAC(x1);
     wxCoord yy1 = YLOG2DEVMAC(y1);
     wxCoord xx2 = XLOG2DEVMAC(x2);
@@ -797,9 +823,8 @@ void  wxDC::DoDrawArc( wxCoord x1, wxCoord y1,
     }
     wxCoord alpha2 = wxCoord(radius2 - radius1);
     wxCoord alpha1 = wxCoord(wxConvertWXangleToMACangle(radius1));
-    if( (xx1 > xx2) || (yy1 > yy2) ) {
-        alpha2 *= -1;
-    }
+    while( alpha2 < 0 ) alpha2 += 360 ;
+    alpha2 = -alpha2 ;
     Rect r = { yyc - rad, xxc - rad, yyc + rad, xxc + rad };
     if(m_brush.GetStyle() != wxTRANSPARENT) {
         MacInstallBrush();
@@ -815,7 +840,7 @@ void  wxDC::DoDrawEllipticArc( wxCoord x, wxCoord y, wxCoord w, wxCoord h,
                               double sa, double ea )
 {
     wxCHECK_RET(Ok(), wxT("wxDC::DoDrawEllepticArc  Invalid DC"));
-    wxMacPortSetter helper(this) ;
+    wxMacFastPortSetter helper(this) ;
     Rect r;
     double angle = sa - ea;  // Order important Mac in opposite direction to wx
     // we have to make sure that the filling is always counter-clockwise
@@ -846,7 +871,7 @@ void  wxDC::DoDrawEllipticArc( wxCoord x, wxCoord y, wxCoord w, wxCoord h,
 void  wxDC::DoDrawPoint( wxCoord x, wxCoord y )
 {
     wxCHECK_RET(Ok(), wxT("Invalid DC"));
-    wxMacPortSetter helper(this) ;
+    wxMacFastPortSetter helper(this) ;
     if (m_pen.GetStyle() != wxTRANSPARENT)
     {
         wxCoord xx1 = XLOG2DEVMAC(x);
@@ -861,7 +886,7 @@ void  wxDC::DoDrawLines(int n, wxPoint points[],
                         wxCoord xoffset, wxCoord yoffset)
 {
     wxCHECK_RET(Ok(), wxT("Invalid DC"));
-    wxMacPortSetter helper(this) ;
+    wxMacFastPortSetter helper(this) ;
     if (m_pen.GetStyle() == wxTRANSPARENT)
         return;
     MacInstallPen() ;
@@ -884,7 +909,7 @@ void  wxDC::DoDrawPolygon(int n, wxPoint points[],
                           int fillStyle )
 {
     wxCHECK_RET(Ok(), wxT("Invalid DC"));
-    wxMacPortSetter helper(this) ;
+    wxMacFastPortSetter helper(this) ;
     wxCoord x1, x2 , y1 , y2 ;
     if ( m_brush.GetStyle() == wxTRANSPARENT && m_pen.GetStyle() == wxTRANSPARENT )
         return ;
@@ -920,7 +945,7 @@ void  wxDC::DoDrawPolygon(int n, wxPoint points[],
 void wxDC::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
 {
     wxCHECK_RET(Ok(), wxT("Invalid DC"));
-    wxMacPortSetter helper(this) ;
+    wxMacFastPortSetter helper(this) ;
     wxCoord xx = XLOG2DEVMAC(x);
     wxCoord yy = YLOG2DEVMAC(y);
     wxCoord ww = m_signX * XLOG2DEVREL(width);
@@ -957,7 +982,7 @@ void  wxDC::DoDrawRoundedRectangle(wxCoord x, wxCoord y,
                                    double radius)
 {
     wxCHECK_RET(Ok(), wxT("Invalid DC"));
-    wxMacPortSetter helper(this) ;
+    wxMacFastPortSetter helper(this) ;
     if (radius < 0.0)
         radius = - radius * ((width < height) ? width : height);
     wxCoord xx = XLOG2DEVMAC(x);
@@ -994,7 +1019,7 @@ void  wxDC::DoDrawRoundedRectangle(wxCoord x, wxCoord y,
 void  wxDC::DoDrawEllipse(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
 {
     wxCHECK_RET(Ok(), wxT("Invalid DC"));
-    wxMacPortSetter helper(this) ;
+    wxMacFastPortSetter helper(this) ;
     wxCoord xx = XLOG2DEVMAC(x);
     wxCoord yy = YLOG2DEVMAC(y);
     wxCoord ww = m_signX * XLOG2DEVREL(width);
@@ -1123,7 +1148,7 @@ bool  wxDC::DoBlit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
     PixMapHandle    bmappixels =  GetGWorldPixMap( sourcePort ) ;
     if ( LockPixels(bmappixels) )
     {
-        wxMacPortSetter helper(this) ;
+        wxMacFastPortSetter helper(this) ;
         if ( source->GetDepth() == 1 )
         {
             RGBForeColor( &MAC_WXCOLORREF(m_textForegroundColour.GetPixel()) ) ;
@@ -1279,6 +1304,8 @@ bool  wxDC::DoBlit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
     return TRUE;
 }
 
+#ifndef FixedToInt
+// as macro in FixMath.h for 10.3
 inline Fixed    IntToFixed( int inInt )
 {
     return (((SInt32) inInt) << 16);
@@ -1288,58 +1315,56 @@ inline int    FixedToInt( Fixed inFixed )
 {
     return (((SInt32) inFixed) >> 16);
 }
+#endif
 
 void  wxDC::DoDrawRotatedText(const wxString& str, wxCoord x, wxCoord y,
                               double angle)
 {
+    // TODO support text background color (only possible by hand, ATSUI does not support it)
     wxCHECK_RET( Ok(), wxT("wxDC::DoDrawRotatedText  Invalid window dc") );
 
-    if (angle == 0.0 )
-    {
-        DrawText(str, x, y);
-        return;
-    }
-
     if ( str.Length() == 0 )
         return ;
-        
-    wxMacPortSetter helper(this) ;
+
+    wxMacFastPortSetter helper(this) ;
     MacInstallFont() ;
 
-    wxFontRefData * font = (wxFontRefData*) m_font.GetRefData() ;
     if ( 0 )
     {
         m_macFormerAliasState = IsAntiAliasedTextEnabled(&m_macFormerAliasSize);
-        SetAntiAliasedTextEnabled(true, SInt16(m_scaleY * font->m_macFontSize));
+        SetAntiAliasedTextEnabled(true, SInt16(m_scaleY * m_font.MacGetFontSize()));
         m_macAliasWasEnabled = true ;
     }
     OSStatus status = noErr ;
     ATSUTextLayout atsuLayout ;
     UniCharCount chars = str.Length() ;
+    UniChar* ubuf = NULL ;
+#if SIZEOF_WCHAR_T == 4
+       wxMBConvUTF16BE converter ;
 #if wxUSE_UNICODE
-    status = ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr) (const wxChar*) str , 0 , str.Length() , str.Length() , 1 ,
-        &chars , (ATSUStyle*) &m_macATSUIStyle , &atsuLayout ) ;
+       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
-    TECObjectRef ec;
-    status = TECCreateConverter(&ec,
-                                wxApp::s_macDefaultEncodingIsPC
-                                    ? (int)kTextEncodingWindowsLatin1
-                                    : (int)kTextEncodingMacRoman,
-                                kTextEncodingUnicodeDefault);
-       
-    wxASSERT_MSG( status == noErr , wxT("couldn't start converter") ) ;
-    ByteCount byteOutLen ;
-    ByteCount byteInLen = str.Length() ;
-    ByteCount byteBufferLen = byteInLen *2 ;
-    char* buf = new char[byteBufferLen] ;
-    status = TECConvertText(ec, (ConstTextPtr)str.c_str() , byteInLen, &byteInLen,
-        (TextPtr)buf, byteBufferLen, &byteOutLen);
-    wxASSERT_MSG( status == noErr , wxT("couldn't convert text") ) ;
-    status = TECDisposeConverter(ec);
-    wxASSERT_MSG( status == noErr , wxT("couldn't dispose converter") ) ;
-    status = ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr) buf , 0 , byteOutLen / 2 , byteOutLen / 2 , 1 ,
-        &chars , (ATSUStyle*) &m_macATSUIStyle , &atsuLayout ) ;
+    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 rotated text") );
     int iAngle = int( angle );
     int drawX = XLOG2DEVMAC(x) ;
@@ -1385,9 +1410,8 @@ void  wxDC::DoDrawRotatedText(const wxString& str, wxCoord x, wxCoord y,
     CalcBoundingBox(XDEV2LOG(rect.left), YDEV2LOG(rect.top) );
     CalcBoundingBox(XDEV2LOG(rect.right), YDEV2LOG(rect.bottom) );
     ::ATSUDisposeTextLayout(atsuLayout);
-#if wxUSE_UNICODE
-#else
-    delete[] buf ;
+#if SIZEOF_WCHAR_T == 4
+    free( ubuf ) ;
 #endif
 }
 
@@ -1395,22 +1419,16 @@ void  wxDC::DoDrawText(const wxString& strtext, wxCoord x, wxCoord y)
 {
     wxCHECK_RET(Ok(), wxT("wxDC::DoDrawText  Invalid DC"));
 
-    wxMacPortSetter helper(this) ;
+    wxMacFastPortSetter helper(this) ;
     long xx = XLOG2DEVMAC(x);
     long yy = YLOG2DEVMAC(y);
 #if TARGET_CARBON
-
     bool useDrawThemeText = ( DrawThemeTextBox != (void*) kUnresolvedCFragSymbolAddress ) ;
-    if ( IsKindOf(CLASSINFO( wxPrinterDC ) ) || m_font.GetNoAntiAliasing() )
+    if ( UMAGetSystemVersion() < 0x1000 || IsKindOf(CLASSINFO( wxPrinterDC ) ) || m_font.GetNoAntiAliasing() )
         useDrawThemeText = false ;
 #endif
     MacInstallFont() ;
-    if ( 0 )
-    {
-        m_macFormerAliasState = IsAntiAliasedTextEnabled(&m_macFormerAliasSize);
-        SetAntiAliasedTextEnabled(true, 8);
-        m_macAliasWasEnabled = true ;
-    }
+
     FontInfo fi ;
     ::GetFontInfo( &fi ) ;
 #if TARGET_CARBON
@@ -1426,64 +1444,14 @@ void  wxDC::DoDrawText(const wxString& strtext, wxCoord x, wxCoord y)
     {
         ::TextMode( srcCopy ) ;
     }
-    int length = strtext.Length() ;
-
-    int laststop = 0 ;
-    int i = 0 ;
     int line = 0 ;
     {
-        while( i < length )
-        {
-            if( strtext[i] == 13 || strtext[i] == 10)
-            {
-               wxString linetext = strtext.Mid( laststop , i - laststop ) ;
-#if TARGET_CARBON
-                if ( useDrawThemeText )
-                {
-                    Rect frame = { yy + line*(fi.descent + fi.ascent + fi.leading)  ,xx , yy + (line+1)*(fi.descent + fi.ascent + fi.leading) , xx + 10000 } ;
-                    wxMacCFStringHolder mString( linetext ) ;
-                    if ( m_backgroundMode != wxTRANSPARENT )
-                    {
-                        Point bounds={0,0} ;
-                        Rect background = frame ;
-                        SInt16 baseline ;
-                        ::GetThemeTextDimensions( mString,
-                            kThemeCurrentPortFont,
-                            kThemeStateActive,
-                            false,
-                            &bounds,
-                            &baseline );
-                        background.right = background.left + bounds.h ;
-                        background.bottom = background.top + bounds.v ;
-                        ::EraseRect( &background ) ;
-                    }
-                    ::DrawThemeTextBox( mString,
-                        kThemeCurrentPortFont,
-                        kThemeStateActive,
-                        false,
-                        &frame,
-                        teJustLeft,
-                        nil );
-                    line++ ;
-                }
-                else
-#endif
-                {
-                                       wxCharBuffer text = wxMacStringToCString(linetext) ; 
-                    ::DrawText( text , 0 , strlen(text) ) ;
-                    line++ ;
-                    ::MoveTo( xx , yy + line*(fi.descent + fi.ascent + fi.leading) );
-                }
-                laststop = i+1 ;
-            }
-            i++ ;
-        }
-        wxString linetext = strtext.Mid( laststop , i - laststop ) ;
+        wxString linetext = strtext ;
 #if TARGET_CARBON
         if ( useDrawThemeText )
         {
             Rect frame = { yy + line*(fi.descent + fi.ascent + fi.leading)  ,xx , yy + (line+1)*(fi.descent + fi.ascent + fi.leading) , xx + 10000 } ;
-            wxMacCFStringHolder mString( linetext ) ;
+            wxMacCFStringHolder mString( linetext , m_font.GetEncoding()) ;
 
             if ( m_backgroundMode != wxTRANSPARENT )
             {
@@ -1491,7 +1459,7 @@ void  wxDC::DoDrawText(const wxString& strtext, wxCoord x, wxCoord y)
                 Rect background = frame ;
                 SInt16 baseline ;
                 ::GetThemeTextDimensions( mString,
-                    kThemeCurrentPortFont,
+                    m_font.MacGetThemeFontID() ,
                     kThemeStateActive,
                     false,
                     &bounds,
@@ -1501,7 +1469,7 @@ void  wxDC::DoDrawText(const wxString& strtext, wxCoord x, wxCoord y)
                 ::EraseRect( &background ) ;
             }
             ::DrawThemeTextBox( mString,
-                kThemeCurrentPortFont,
+                m_font.MacGetThemeFontID() ,
                 kThemeStateActive,
                 false,
                 &frame,
@@ -1511,7 +1479,7 @@ void  wxDC::DoDrawText(const wxString& strtext, wxCoord x, wxCoord y)
         else
 #endif
         {
-                       wxCharBuffer text = wxMacStringToCString(linetext) ; 
+            wxCharBuffer text = linetext.mb_str(wxConvLocal) ; 
             ::DrawText( text , 0 , strlen(text) ) ;
          }
     }
@@ -1529,7 +1497,7 @@ void  wxDC::DoGetTextExtent( const wxString &strtext, wxCoord *width, wxCoord *h
                             wxFont *theFont ) const
 {
     wxCHECK_RET(Ok(), wxT("Invalid DC"));
-    wxMacPortSetter helper(this) ;
+    wxMacFastPortSetter helper(this) ;
     wxFont formerFont = m_font ;
     if ( theFont )
     {
@@ -1541,7 +1509,7 @@ void  wxDC::DoGetTextExtent( const wxString &strtext, wxCoord *width, wxCoord *h
     ::GetFontInfo( &fi ) ;
 #if TARGET_CARBON    
     bool useGetThemeText = ( GetThemeTextDimensions != (void*) kUnresolvedCFragSymbolAddress ) ;
-       if ( IsKindOf(CLASSINFO( wxPrinterDC ) ) || ((wxFont*)&m_font)->GetNoAntiAliasing() )
+    if ( UMAGetSystemVersion() < 0x1000 || IsKindOf(CLASSINFO( wxPrinterDC ) ) || ((wxFont*)&m_font)->GetNoAntiAliasing() )
         useGetThemeText = false ;
 #endif
     if ( height )
@@ -1550,71 +1518,21 @@ void  wxDC::DoGetTextExtent( const wxString &strtext, wxCoord *width, wxCoord *h
         *descent =YDEV2LOGREL( fi.descent );
     if ( externalLeading )
         *externalLeading = YDEV2LOGREL( fi.leading ) ;
-    int length = strtext.Length() ;
-    /*
-    const char *text = NULL ;
-    wxString macText ;
-    if ( wxApp::s_macDefaultEncodingIsPC )
-    {
-        macText = wxMacMakeMacStringFromPC( string ) ;
-        text = macText ;
-        length = macText.Length() ;
-    } 
-    else
-    {
-        text = string ;
-        length = string.Length() ;
-    }
-    */
-    int laststop = 0 ;
-    int i = 0 ;
+
     int curwidth = 0 ;
     if ( width )
     {
         *width = 0 ;
-        while( i < length )
-        {
-            if( strtext[i] == 13 || strtext[i] == 10)
-            {
-               wxString linetext = strtext.Mid( laststop , i - laststop ) ;
-                if ( height )
-                    *height += YDEV2LOGREL( fi.descent + fi.ascent + fi.leading ) ;
-#if TARGET_CARBON
-                if ( useGetThemeText )
-                {
-                    Point bounds={0,0} ;
-                    SInt16 baseline ;
-                    wxMacCFStringHolder mString( linetext ) ;
-                    ::GetThemeTextDimensions( mString,
-                        kThemeCurrentPortFont,
-                        kThemeStateActive,
-                        false,
-                        &bounds,
-                        &baseline );
-                    curwidth = bounds.h ;
-                }
-                else
-#endif
-                {
-                                       wxCharBuffer text = wxMacStringToCString(linetext) ; 
-                       curwidth = ::TextWidth( text , 0 , strlen(text) ) ;
-                }
-                if ( curwidth > *width )
-                    *width = XDEV2LOGREL( curwidth ) ;
-                laststop = i+1 ;
-            }
-            i++ ;
-        }
-        
-        wxString linetext = strtext.Mid( laststop , i - laststop ) ;
-#if TARGET_CARBON
+        wxString linetext = strtext ;
+
         if ( useGetThemeText )
         {
             Point bounds={0,0} ;
             SInt16 baseline ;
-            wxMacCFStringHolder mString( linetext ) ;
+            wxMacCFStringHolder mString( linetext , m_font.GetEncoding() ) ;
+            ThemeFontID themeFont = m_font.MacGetThemeFontID() ;
             ::GetThemeTextDimensions( mString,
-                kThemeCurrentPortFont,
+                themeFont ,
                 kThemeStateActive,
                 false,
                 &bounds,
@@ -1622,9 +1540,8 @@ void  wxDC::DoGetTextExtent( const wxString &strtext, wxCoord *width, wxCoord *h
             curwidth = bounds.h ;
         }
         else
-#endif
         {
-                       wxCharBuffer text = wxMacStringToCString(linetext) ; 
+            wxCharBuffer text = linetext.mb_str(wxConvLocal) ;  
             curwidth = ::TextWidth( text , 0 , strlen(text) ) ;
         }
         if ( curwidth > *width )
@@ -1638,18 +1555,80 @@ void  wxDC::DoGetTextExtent( const wxString &strtext, wxCoord *width, wxCoord *h
     }
 }
 
+
+bool wxDC::DoGetPartialTextExtents(const wxString& text, wxArrayInt& widths) const
+{
+    wxCHECK_MSG(Ok(), false, wxT("Invalid DC"));
+
+    widths.Empty();
+    widths.Add(0, text.Length());
+
+    if (text.Length() == 0)
+        return false;
+    
+    wxMacFastPortSetter helper(this) ;
+    MacInstallFont() ;
+#if TARGET_CARBON    
+    bool useGetThemeText = ( GetThemeTextDimensions != (void*) kUnresolvedCFragSymbolAddress ) ;
+    if ( UMAGetSystemVersion() < 0x1000 || IsKindOf(CLASSINFO( wxPrinterDC ) ) || ((wxFont*)&m_font)->GetNoAntiAliasing() )
+        useGetThemeText = false ;
+
+    if ( useGetThemeText )
+    {
+        // If anybody knows how to do this more efficiently yet still handle
+        // the fractional glyph widths that may be present when using AA
+        // fonts, please change it.  Currently it is measuring from the
+        // begining of the string for each succeding substring, which is much
+        // slower than this should be.
+        for (size_t i=0; i<text.Length(); i++)
+        {
+            wxString str(text.Left(i+1));
+            Point bounds = {0,0};
+            SInt16 baseline ;
+            wxMacCFStringHolder mString(str, m_font.GetEncoding());
+            ::GetThemeTextDimensions( mString,
+                                      m_font.MacGetThemeFontID(),
+                                      kThemeStateActive,
+                                      false,
+                                      &bounds,
+                                      &baseline );
+            widths[i] = XDEV2LOGREL(bounds.h);
+        }
+    }
+    else        
+#endif
+    {
+        wxCharBuffer buff = text.mb_str(wxConvLocal);
+        size_t len = strlen(buff);
+        short* measurements = new short[len+1];
+        MeasureText(len, buff.data(), measurements);
+
+        // Copy to widths, starting at measurements[1]
+        // NOTE: this doesn't take into account any multi-byte characters
+        // in buff, it probabkly should...
+        for (size_t i=0; i<text.Length(); i++)
+            widths[i] = XDEV2LOGREL(measurements[i+1]);
+
+        delete [] measurements;        
+    }
+
+    return true;
+}
+
+
+
 wxCoord   wxDC::GetCharWidth(void) const
 {
     wxCHECK_MSG(Ok(), 1, wxT("Invalid DC"));
-    wxMacPortSetter helper(this) ;
+    wxMacFastPortSetter helper(this) ;
     MacInstallFont() ;
     int width = 0 ;
 #if TARGET_CARBON
     bool useGetThemeText = ( GetThemeTextDimensions != (void*) kUnresolvedCFragSymbolAddress ) ;
-    if ( ((wxFont*)&m_font)->GetNoAntiAliasing() )
+    if ( UMAGetSystemVersion() < 0x1000 || ((wxFont*)&m_font)->GetNoAntiAliasing() )
         useGetThemeText = false ;
 #endif
-    char text[] = "H" ;
+    char text[] = "g" ;
 #if TARGET_CARBON
     if ( useGetThemeText )
     {
@@ -1657,7 +1636,7 @@ wxCoord   wxDC::GetCharWidth(void) const
         SInt16 baseline ;
         CFStringRef mString = CFStringCreateWithBytes( NULL , (UInt8*) text , 1 , CFStringGetSystemEncoding(), false ) ;
         ::GetThemeTextDimensions( mString,
-            kThemeCurrentPortFont,
+            m_font.MacGetThemeFontID(),
             kThemeStateActive,
             false,
             &bounds,
@@ -1676,7 +1655,7 @@ wxCoord   wxDC::GetCharWidth(void) const
 wxCoord   wxDC::GetCharHeight(void) const
 {
     wxCHECK_MSG(Ok(), 1, wxT("Invalid DC"));
-    wxMacPortSetter helper(this) ;
+    wxMacFastPortSetter helper(this) ;
     MacInstallFont() ;
     FontInfo fi ;
     ::GetFontInfo( &fi ) ;
@@ -1686,12 +1665,11 @@ wxCoord   wxDC::GetCharHeight(void) const
 void  wxDC::Clear(void)
 {
     wxCHECK_RET(Ok(), wxT("Invalid DC"));
-    wxMacPortSetter helper(this) ;
+    wxMacFastPortSetter helper(this) ;
     Rect rect = { -31000 , -31000 , 31000 , 31000 } ;
-    if (m_backgroundBrush.GetStyle() != wxTRANSPARENT)
+    if ( m_backgroundBrush.Ok() && m_backgroundBrush.GetStyle() != wxTRANSPARENT)
     {
         ::PenNormal() ;
-        //MacInstallBrush() ;
         MacSetupBackgroundForCurrentPort( m_backgroundBrush ) ;
         ::EraseRect( &rect ) ;
     }
@@ -1704,12 +1682,16 @@ void wxDC::MacInstallFont() const
     //        return ;
     Pattern blackColor ;
     MacSetupBackgroundForCurrentPort(m_backgroundBrush) ;
-    wxFontRefData * font = (wxFontRefData*) m_font.GetRefData() ;
-    if ( font )
+    if ( m_backgroundMode != wxTRANSPARENT )
+    {
+        Pattern whiteColor ;
+        ::BackPat(GetQDGlobalsWhite(&whiteColor));
+    }
+    if ( m_font.Ok() )
     {
-        ::TextFont( font->m_macFontNum ) ;
-        ::TextSize( short(m_scaleY * font->m_macFontSize) ) ;
-        ::TextFace( font->m_macFontStyle ) ;
+        ::TextFont( m_font.MacGetFontNum() ) ;
+        ::TextSize( (short)(m_scaleY * m_font.MacGetFontSize()) ) ;
+        ::TextFace( m_font.MacGetFontStyle() ) ;
         m_macFontInstalled = true ;
         m_macBrushInstalled = false ;
         m_macPenInstalled = false ;
@@ -1778,9 +1760,9 @@ void wxDC::MacInstallFont() const
     }
     ::PenMode( mode ) ;
     OSStatus status = noErr ;
-    Fixed atsuSize = IntToFixed( int(m_scaleY * font->m_macFontSize) ) ;
-    Style qdStyle = font->m_macFontStyle ;
-    ATSUFontID    atsuFont = font->m_macATSUFontID ;
+    Fixed atsuSize = IntToFixed( int(m_scaleY * m_font.MacGetFontSize()) ) ;
+    Style qdStyle = m_font.MacGetATSUAdditionalQDStyles() ;
+    ATSUFontID    atsuFont = m_font.MacGetATSUFontID() ;
     status = ::ATSUCreateStyle((ATSUStyle *)&m_macATSUIStyle) ;
     wxASSERT_MSG( status == noErr , wxT("couldn't create ATSU style") ) ;
     ATSUAttributeTag atsuTags[] =
@@ -1831,51 +1813,47 @@ void wxDC::MacInstallFont() const
     wxASSERT_MSG( status == noErr , wxT("couldn't set create ATSU style") ) ;
 }
 
-Pattern gHatchPatterns[] =
-{
-    { { 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF } },
-    { { 0x01 , 0x02 , 0x04 , 0x08 , 0x10 , 0x20 , 0x40 , 0x80 } },
-    { { 0x80 , 0x40 , 0x20 , 0x10 , 0x08 , 0x04 , 0x02 , 0x01 } },
-    { { 0x10 , 0x10 , 0x10 , 0xFF , 0x10 , 0x10 , 0x10 , 0x10 } },
-    { { 0x00 , 0x00 , 0x00 , 0xFF , 0x00 , 0x00 , 0x00 , 0x00 } },
-    { { 0x10 , 0x10 , 0x10 , 0x10 , 0x10 , 0x10 , 0x10 , 0x10 } },
-    { { 0x81 , 0x42 , 0x24 , 0x18 , 0x18 , 0x24 , 0x42 , 0x81 } } 
+Pattern gPatterns[] =
+{   // hatch patterns
+    { { 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF } } ,
+    { { 0x01 , 0x02 , 0x04 , 0x08 , 0x10 , 0x20 , 0x40 , 0x80 } } ,
+    { { 0x80 , 0x40 , 0x20 , 0x10 , 0x08 , 0x04 , 0x02 , 0x01 } } ,
+    { { 0x10 , 0x10 , 0x10 , 0xFF , 0x10 , 0x10 , 0x10 , 0x10 } } ,
+    { { 0x00 , 0x00 , 0x00 , 0xFF , 0x00 , 0x00 , 0x00 , 0x00 } } ,
+    { { 0x10 , 0x10 , 0x10 , 0x10 , 0x10 , 0x10 , 0x10 , 0x10 } } ,
+    { { 0x81 , 0x42 , 0x24 , 0x18 , 0x18 , 0x24 , 0x42 , 0x81 } } ,
+    // dash patterns
+    { { 0xCC , 0x99 , 0x33 , 0x66 , 0xCC , 0x99 , 0x33 , 0x66 } } , // DOT
+    { { 0xFE , 0xFD , 0xFB , 0xF7 , 0xEF , 0xDF , 0xBF , 0x7F } } , // LONG_DASH
+    { { 0xEE , 0xDD , 0xBB , 0x77 , 0xEE , 0xDD , 0xBB , 0x77 } } , // SHORT_DASH
+    { { 0xDE , 0xBD , 0x7B , 0xF6 , 0xED , 0xDB , 0xB7 , 0x6F } } , // DOT_DASH
 } ;
 
-static void wxMacGetHatchPattern(int hatchStyle, Pattern *pattern)
+static void wxMacGetPattern(int penStyle, Pattern *pattern)
 {
-    int theIndex = 1 ;
-    switch(hatchStyle)
-    {
-    case wxBDIAGONAL_HATCH:
-        theIndex = 2;
-        break;
-    case wxFDIAGONAL_HATCH:
-        theIndex = 3;
-        break;
-    case wxCROSS_HATCH:
-        theIndex = 4;
-        break;
-    case wxHORIZONTAL_HATCH:
-        theIndex = 5;
-        break;
-    case wxVERTICAL_HATCH:
-        theIndex = 6;
-        break;
-    case wxCROSSDIAG_HATCH:
-        theIndex = 7;
-        break;
-    default:
-        theIndex = 1; // solid pattern
-        break;
+    int index = 0;  // solid pattern by default
+    switch(penStyle)
+    {   
+        // hatches
+        case wxBDIAGONAL_HATCH:     index = 1; break;
+        case wxFDIAGONAL_HATCH:     index = 2; break;
+        case wxCROSS_HATCH:         index = 3; break;
+        case wxHORIZONTAL_HATCH:    index = 4; break;
+        case wxVERTICAL_HATCH:      index = 5; break;
+        case wxCROSSDIAG_HATCH:     index = 6; break;
+        // dashes
+        case wxDOT:                 index = 7; break;
+        case wxLONG_DASH:           index = 8; break;
+        case wxSHORT_DASH:          index = 9; break;
+        case wxDOT_DASH:            index = 10; break;
     }
-    *pattern = gHatchPatterns[theIndex-1] ;
+    *pattern = gPatterns[index];    
 }
 
 void wxDC::MacInstallPen() const
 {
     wxCHECK_RET(Ok(), wxT("Invalid DC"));
-    Pattern     blackColor;
+    //Pattern     blackColor;
     //    if ( m_macPenInstalled )
     //        return ;
     RGBColor forecolor = MAC_WXCOLORREF( m_pen.GetColour().GetPixel());
@@ -1883,67 +1861,33 @@ void wxDC::MacInstallPen() const
     ::RGBForeColor( &forecolor );
     ::RGBBackColor( &backcolor );
     ::PenNormal() ;
-    int penWidth = m_pen.GetWidth() * (int) m_scaleX ;
+    int penWidth = (int) (m_pen.GetWidth() * m_scaleX) ; ;
     // null means only one pixel, at whatever resolution
     if ( penWidth == 0 )
         penWidth = 1 ;
     ::PenSize(penWidth, penWidth);
+    
     int penStyle = m_pen.GetStyle();
-    if (penStyle == wxSOLID)
-    {
-        ::PenPat(GetQDGlobalsBlack(&blackColor));
-    }
-    else if (IS_HATCH(penStyle))
-    {
-        Pattern pat ;
-        wxMacGetHatchPattern(penStyle, &pat);
-        ::PenPat(&pat);
+    Pattern pat;
+    if (penStyle == wxUSER_DASH)
+    {   
+        // FIXME: there should be exactly 8 items in the dash
+        wxDash* dash ;
+        int number = m_pen.GetDashes(&dash) ;
+        int index = 0;
+        for ( int i = 0 ; i < 8 ; ++i )
+        {
+            pat.pat[i] = dash[index] ;
+            if (index < number - 1)
+                index++;
+        }
     }
     else
     {
-        Pattern pat = *GetQDGlobalsBlack(&blackColor) ;
-        switch( penStyle )
-        {
-        case wxDOT :
-            for ( int i = 0 ; i < 8 ; ++i )
-            {
-                pat.pat[i] = 0xCC ;
-            }
-            break ;
-        case wxLONG_DASH :
-            for ( int i = 0 ; i < 8 ; ++i )
-            {
-                pat.pat[i] = 0xFE ;
-            }
-            break ;
-        case wxSHORT_DASH :
-            for ( int i = 0 ; i < 8 ; ++i )
-            {
-                pat.pat[i] = 0xEE ;
-            }
-            break ;
-        case wxDOT_DASH :
-            for ( int i = 0 ; i < 8 ; ++i )
-            {
-                pat.pat[i] = 0x6F ;
-            }
-            break ;
-        case wxUSER_DASH :
-            {
-                wxDash* dash ;
-                m_pen.GetDashes(&dash) ;
-                // right now we don't allocate larger pixmaps
-                // int number = 
-                m_pen.GetDashes(&dash) ;
-                for ( int i = 0 ; i < 8 ; ++i )
-                {
-                    pat.pat[i] = dash[0] ;
-                }
-            }
-            break ;
-        }
-        ::PenPat(&pat);
+        wxMacGetPattern(penStyle, &pat);
     }
+    ::PenPat(&pat);
+
     short mode = patCopy ;
     // todo :
     switch( m_logicalFunction )
@@ -1991,37 +1935,40 @@ void wxDC::MacInstallPen() const
 void wxDC::MacSetupBackgroundForCurrentPort(const wxBrush& background )
 {
     Pattern whiteColor ;
-    switch( background.MacGetBrushKind() )
+    if ( background.Ok() )
     {
-    case kwxMacBrushTheme :
-        {
-            ::SetThemeBackground( background.GetMacTheme() , wxDisplayDepth() , true ) ;
-            break ;
-        }
-    case kwxMacBrushThemeBackground :
-        {
-            Rect extent ;
-            ThemeBackgroundKind bg = background.GetMacThemeBackground( &extent ) ;
-            ::ApplyThemeBackground( bg , &extent ,kThemeStateActive , wxDisplayDepth() , true ) ;
-            break ;
-        }
-    case kwxMacBrushColour :
+        switch( background.MacGetBrushKind() )
         {
-               ::RGBBackColor( &MAC_WXCOLORREF( background.GetColour().GetPixel()) );
-            int brushStyle = background.GetStyle();
-            if (brushStyle == wxSOLID)
-                ::BackPat(GetQDGlobalsWhite(&whiteColor));
-            else if (IS_HATCH(brushStyle))
+            case kwxMacBrushTheme :
             {
-                Pattern pat ;
-                wxMacGetHatchPattern(brushStyle, &pat);
-                ::BackPat(&pat);
+                ::SetThemeBackground( background.MacGetTheme() , wxDisplayDepth() , true ) ;
+                break ;
             }
-            else
+            case kwxMacBrushThemeBackground :
             {
-                ::BackPat(GetQDGlobalsWhite(&whiteColor));
+                Rect extent ;
+                ThemeBackgroundKind bg = background.MacGetThemeBackground( &extent ) ;
+                ::ApplyThemeBackground( bg , &extent ,kThemeStateActive , wxDisplayDepth() , true ) ;
+                break ;
+            }
+            case kwxMacBrushColour :
+            {
+                ::RGBBackColor( &MAC_WXCOLORREF( background.GetColour().GetPixel()) );
+                int brushStyle = background.GetStyle();
+                if (brushStyle == wxSOLID)
+                    ::BackPat(GetQDGlobalsWhite(&whiteColor));
+                else if (IS_HATCH(brushStyle))
+                {
+                    Pattern pat ;
+                    wxMacGetPattern(brushStyle, &pat);
+                    ::BackPat(&pat);
+                }
+                else
+                {
+                    ::BackPat(GetQDGlobalsWhite(&whiteColor));
+                }
+                break ;
             }
-            break ;
         }
     }
 }
@@ -2044,7 +1991,7 @@ void wxDC::MacInstallBrush() const
     else if (IS_HATCH(brushStyle))
     {
         Pattern pat ;
-        wxMacGetHatchPattern(brushStyle, &pat);
+        wxMacGetPattern(brushStyle, &pat);
         ::PenPat(&pat);
     }
     else if ( m_brush.GetStyle() == wxSTIPPLE || m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE )