X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/e40298d54ecd5b109222a7c60aa2ef084a304d69..b16f4bfab29a541cbb24febe07983087776388cb:/src/mac/carbon/dc.cpp diff --git a/src/mac/carbon/dc.cpp b/src/mac/carbon/dc.cpp index 9dff84e4d3..3084e7224c 100644 --- a/src/mac/carbon/dc.cpp +++ b/src/mac/carbon/dc.cpp @@ -17,6 +17,7 @@ #include "wx/app.h" #include "wx/mac/uma.h" #include "wx/dcmemory.h" +#include "wx/dcprint.h" #include "wx/region.h" #include "wx/image.h" #include "wx/log.h" @@ -25,10 +26,12 @@ #include "math.h" using namespace std ; #endif + #include "wx/mac/private.h" -#include "ATSUnicode.h" -#include "TextCommon.h" -#include "TextEncodingConverter.h" +#include +#include +#include +#include #if !USE_SHARED_LIBRARY IMPLEMENT_ABSTRACT_CLASS(wxDC, wxObject) #endif @@ -43,13 +46,20 @@ IMPLEMENT_ABSTRACT_CLASS(wxDC, wxObject) #define twips2mm 0.0176388888889 #define mm2pt 2.83464566929 #define pt2mm 0.352777777778 -#ifndef __DARWIN__ +#if !defined( __DARWIN__ ) || defined(__MWERKS__) +#ifndef M_PI const double M_PI = 3.14159265358979 ; #endif +#endif 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 ) { @@ -57,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 ) ; -#endif - RgnHandle insidergn = NewRgn() ; 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 ) ; } } 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 //----------------------------------------------------------------------------- @@ -234,7 +278,11 @@ wxDC::wxDC() m_pen = *wxBLACK_PEN; m_font = *wxNORMAL_FONT; m_brush = *wxWHITE_BRUSH; +#ifdef __WXDEBUG__ + // needed to debug possible errors with two active drawing methods at the same time on + // the same DC m_macCurrentPortStateHelper = NULL ; +#endif m_macATSUIStyle = NULL ; m_macAliasWasEnabled = false; m_macForegroundPixMap = NULL ; @@ -249,18 +297,23 @@ wxDC::~wxDC(void) void wxDC::MacSetupPort(wxMacPortStateHelper* help) const { +#ifdef __WXDEBUG__ wxASSERT( m_macCurrentPortStateHelper == NULL ) ; 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__ wxASSERT( m_macCurrentPortStateHelper == help ) ; m_macCurrentPortStateHelper = NULL ; +#endif if( m_macATSUIStyle ) { ::ATSUDisposeStyle((ATSUStyle)m_macATSUIStyle); @@ -291,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(); @@ -410,12 +463,12 @@ void wxDC::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord hei void wxDC::DoSetClippingRegionAsRegion( const wxRegion ®ion ) { 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; @@ -457,15 +510,9 @@ void wxDC::DoSetClippingRegionAsRegion( const wxRegion ®ion ) void wxDC::DestroyClippingRegion() { - wxMacPortSetter helper(this) ; + wxMacFastPortSetter helper(this) ; CopyRgn( (RgnHandle) m_macBoundaryClipRgn , (RgnHandle) m_macCurrentClipRgn ) ; - m_clipping = FALSE; -} - -void wxDC::DoGetSize( int* width, int* height ) const -{ - *width = m_maxX-m_minX; - *height = m_maxY-m_minY; + ResetClipping(); } void wxDC::DoGetSizeMM( int* width, int* height ) const @@ -549,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); @@ -598,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); } } @@ -668,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 @@ -681,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() ; @@ -719,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; @@ -759,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); @@ -809,7 +841,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 @@ -840,7 +872,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); @@ -855,7 +887,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() ; @@ -878,7 +910,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 ; @@ -914,7 +946,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); @@ -951,7 +983,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); @@ -988,7 +1020,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); @@ -1054,7 +1086,7 @@ bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height, switch ( logical_func ) { case wxAND: // src AND dst - mode = srcOr ; // ok + mode = adMin ; // ok break ; case wxAND_INVERT: // (NOT src) AND dst mode = notSrcOr ; // ok @@ -1110,14 +1142,14 @@ bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height, } if ( mode == kUnsupportedMode ) { - wxFAIL_MSG("unsupported blitting mode" ); + wxFAIL_MSG(wxT("unsupported blitting mode" )); return FALSE ; } CGrafPtr sourcePort = (CGrafPtr) source->m_macPort ; PixMapHandle bmappixels = GetGWorldPixMap( sourcePort ) ; if ( LockPixels(bmappixels) ) { - wxMacPortSetter helper(this) ; + wxMacFastPortSetter helper(this) ; if ( source->GetDepth() == 1 ) { RGBForeColor( &MAC_WXCOLORREF(m_textForegroundColour.GetPixel()) ) ; @@ -1273,6 +1305,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); @@ -1282,54 +1316,62 @@ inline int FixedToInt( Fixed inFixed ) { return (((SInt32) inFixed) >> 16); } +#endif void wxDC::DoDrawRotatedText(const wxString& str, wxCoord x, wxCoord y, double angle) { 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() ; - wxString text ; - if ( wxApp::s_macDefaultEncodingIsPC ) - { - text = wxMacMakeMacStringFromPC( str ) ; - } - else - { - text = str ; - } - 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 ; - TECObjectRef ec; - status = TECCreateConverter(&ec, kTextEncodingMacRoman, kTextEncodingUnicodeDefault); - wxASSERT_MSG( status == noErr , "couldn't start converter" ) ; - ByteCount byteOutLen ; - ByteCount byteInLen = text.Length() ; - ByteCount byteBufferLen = byteInLen *2 ; - char* buf = new char[byteBufferLen] ; - status = TECConvertText(ec, (ConstTextPtr)text.c_str() , byteInLen, &byteInLen, - (TextPtr)buf, byteBufferLen, &byteOutLen); - wxASSERT_MSG( status == noErr , "couldn't convert text" ) ; - status = TECDisposeConverter(ec); - wxASSERT_MSG( status == noErr , "couldn't dispose converter" ) ; ATSUTextLayout atsuLayout ; - UniCharCount chars = byteOutLen / 2 ; - status = ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr) buf , 0 , byteOutLen / 2 , byteOutLen / 2 , 1 , + UniCharCount chars = str.Length() ; + UniChar* ubuf = NULL ; +#if SIZEOF_WCHAR_T == 4 + wxMBConvUTF16BE 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 , "couldn't create the layout of the rotated text" ); + + wxASSERT_MSG( status == noErr , wxT("couldn't create the layout of the rotated text") ); int iAngle = int( angle ); int drawX = XLOG2DEVMAC(x) ; int drawY = YLOG2DEVMAC(y) ; @@ -1361,31 +1403,34 @@ void wxDC::DoDrawRotatedText(const wxString& str, wxCoord x, wxCoord y, status = ::ATSUMeasureText( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd, &textBefore , &textAfter, &ascent , &descent ); - drawX += sin(angle/RAD2DEG) * FixedToInt(ascent) ; - drawY += cos(angle/RAD2DEG) * FixedToInt(ascent) ; + drawX += (int)(sin(angle/RAD2DEG) * FixedToInt(ascent)); + drawY += (int)(cos(angle/RAD2DEG) * FixedToInt(ascent)); status = ::ATSUDrawText( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd, IntToFixed(drawX) , IntToFixed(drawY) ); - wxASSERT_MSG( status == noErr , "couldn't draw the rotated text" ); + wxASSERT_MSG( status == noErr , wxT("couldn't draw the rotated text") ); Rect rect ; status = ::ATSUMeasureTextImage( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd, IntToFixed(drawX) , IntToFixed(drawY) , &rect ); - wxASSERT_MSG( status == noErr , "couldn't measure the rotated text" ); + wxASSERT_MSG( status == noErr , wxT("couldn't measure the rotated text") ); OffsetRect( &rect , -m_macLocalOrigin.x , -m_macLocalOrigin.y ) ; CalcBoundingBox(XDEV2LOG(rect.left), YDEV2LOG(rect.top) ); CalcBoundingBox(XDEV2LOG(rect.right), YDEV2LOG(rect.bottom) ); ::ATSUDisposeTextLayout(atsuLayout); - delete[] buf ; +#if SIZEOF_WCHAR_T == 4 + free( ubuf ) ; +#endif } 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 ( m_font.GetNoAntiAliasing() ) + if ( UMAGetSystemVersion() < 0x1000 || IsKindOf(CLASSINFO( wxPrinterDC ) ) || m_font.GetNoAntiAliasing() ) useDrawThemeText = false ; #endif MacInstallFont() ; @@ -1410,81 +1455,22 @@ void wxDC::DoDrawText(const wxString& strtext, wxCoord x, wxCoord y) { ::TextMode( srcCopy ) ; } - const char *text = NULL ; - int length = 0 ; - wxString macText ; - if ( wxApp::s_macDefaultEncodingIsPC ) - { - macText = wxMacMakeMacStringFromPC( strtext ) ; - text = macText ; - length = macText.Length() ; - } - else - { - text = strtext ; - length = strtext.Length() ; - } - int laststop = 0 ; - int i = 0 ; int line = 0 ; { - while( i < length ) - { - if( text[i] == 13 || text[i] == 10) - { -#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 } ; - CFStringRef mString = CFStringCreateWithBytes( NULL , (UInt8*) text + laststop , i - laststop , CFStringGetSystemEncoding(), false ) ; - 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 ); - CFRelease( mString ) ; - line++ ; - } - else -#endif - { - ::DrawText( text , laststop , i - laststop ) ; - line++ ; - ::MoveTo( xx , yy + line*(fi.descent + fi.ascent + fi.leading) ); - } - laststop = i+1 ; - } - i++ ; - } + 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 } ; - CFStringRef mString = CFStringCreateWithCString( NULL , text + laststop , kCFStringEncodingMacRoman ) ; + wxMacCFStringHolder mString( linetext , m_font.GetEncoding()) ; + if ( m_backgroundMode != wxTRANSPARENT ) { Point bounds={0,0} ; Rect background = frame ; SInt16 baseline ; ::GetThemeTextDimensions( mString, - kThemeCurrentPortFont, + m_font.MacGetThemeFontID() , kThemeStateActive, false, &bounds, @@ -1494,19 +1480,27 @@ void wxDC::DoDrawText(const wxString& strtext, wxCoord x, wxCoord y) ::EraseRect( &background ) ; } ::DrawThemeTextBox( mString, - kThemeCurrentPortFont, + m_font.MacGetThemeFontID() , kThemeStateActive, false, &frame, teJustLeft, nil ); - CFRelease( mString ) ; } else #endif { - ::DrawText( text , laststop , i - laststop ) ; - } + wxCharBuffer text = linetext.mb_str(wxConvLocal) ; + if ( m_backgroundMode != wxTRANSPARENT ) + { + Rect frame = { yy - fi.ascent + line*(fi.descent + fi.ascent + fi.leading) ,xx , yy - fi.ascent + (line+1)*(fi.descent + fi.ascent + fi.leading) , xx + 10000 } ; + short width = ::TextWidth( text , 0 , strlen(text) ) ; + frame.right = frame.left + width ; + + ::EraseRect( &frame ) ; + } + ::DrawText( text , 0 , strlen(text) ) ; + } } ::TextMode( srcOr ) ; } @@ -1517,12 +1511,12 @@ bool wxDC::CanGetTextExtent() const return true ; } -void wxDC::DoGetTextExtent( const wxString &string, wxCoord *width, wxCoord *height, +void wxDC::DoGetTextExtent( const wxString &strtext, wxCoord *width, wxCoord *height, wxCoord *descent, wxCoord *externalLeading , wxFont *theFont ) const { wxCHECK_RET(Ok(), wxT("Invalid DC")); - wxMacPortSetter helper(this) ; + wxMacFastPortSetter helper(this) ; wxFont formerFont = m_font ; if ( theFont ) { @@ -1534,7 +1528,7 @@ void wxDC::DoGetTextExtent( const wxString &string, wxCoord *width, wxCoord *he ::GetFontInfo( &fi ) ; #if TARGET_CARBON bool useGetThemeText = ( GetThemeTextDimensions != (void*) kUnresolvedCFragSymbolAddress ) ; - if ( ((wxFont*)&m_font)->GetNoAntiAliasing() ) + if ( UMAGetSystemVersion() < 0x1000 || IsKindOf(CLASSINFO( wxPrinterDC ) ) || ((wxFont*)&m_font)->GetNoAntiAliasing() ) useGetThemeText = false ; #endif if ( height ) @@ -1543,78 +1537,31 @@ void wxDC::DoGetTextExtent( const wxString &string, wxCoord *width, wxCoord *he *descent =YDEV2LOGREL( fi.descent ); if ( externalLeading ) *externalLeading = YDEV2LOGREL( fi.leading ) ; - const char *text = NULL ; - int length = 0 ; - 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( text[i] == 13 || text[i] == 10) - { - if ( height ) - *height += YDEV2LOGREL( fi.descent + fi.ascent + fi.leading ) ; -#if TARGET_CARBON - if ( useGetThemeText ) - { - Point bounds={0,0} ; - SInt16 baseline ; - CFStringRef mString = CFStringCreateWithBytes( NULL , (UInt8*) text + laststop , i - laststop , CFStringGetSystemEncoding(), false ) ; - ::GetThemeTextDimensions( mString, - kThemeCurrentPortFont, - kThemeStateActive, - false, - &bounds, - &baseline ); - CFRelease( mString ) ; - curwidth = bounds.h ; - } - else -#endif - { - curwidth = ::TextWidth( text , laststop , i - laststop ) ; - } - if ( curwidth > *width ) - *width = XDEV2LOGREL( curwidth ) ; - laststop = i+1 ; - } - i++ ; - } - -#if TARGET_CARBON + wxString linetext = strtext ; + if ( useGetThemeText ) { Point bounds={0,0} ; SInt16 baseline ; - CFStringRef mString = CFStringCreateWithBytes( NULL , (UInt8*) text + laststop , i - laststop , CFStringGetSystemEncoding(), false ) ; + wxMacCFStringHolder mString( linetext , m_font.GetEncoding() ) ; + ThemeFontID themeFont = m_font.MacGetThemeFontID() ; ::GetThemeTextDimensions( mString, - kThemeCurrentPortFont, + themeFont , kThemeStateActive, false, &bounds, &baseline ); - CFRelease( mString ) ; curwidth = bounds.h ; } else -#endif { - curwidth = ::TextWidth( text , laststop , i - laststop ) ; + wxCharBuffer text = linetext.mb_str(wxConvLocal) ; + curwidth = ::TextWidth( text , 0 , strlen(text) ) ; } if ( curwidth > *width ) *width = XDEV2LOGREL( curwidth ) ; @@ -1627,18 +1574,80 @@ void wxDC::DoGetTextExtent( const wxString &string, wxCoord *width, wxCoord *he } } + +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; iGetNoAntiAliasing() ) + if ( UMAGetSystemVersion() < 0x1000 || ((wxFont*)&m_font)->GetNoAntiAliasing() ) useGetThemeText = false ; #endif - char text[] = "H" ; + char text[] = "g" ; #if TARGET_CARBON if ( useGetThemeText ) { @@ -1646,7 +1655,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, @@ -1665,7 +1674,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 ) ; @@ -1675,12 +1684,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 ) ; } @@ -1693,12 +1701,11 @@ void wxDC::MacInstallFont() const // return ; Pattern blackColor ; MacSetupBackgroundForCurrentPort(m_backgroundBrush) ; - wxFontRefData * font = (wxFontRefData*) m_font.GetRefData() ; - if ( font ) + 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 ; @@ -1747,10 +1754,12 @@ void wxDC::MacInstallFont() const case wxSRC_INVERT: // (NOT src) mode = notPatCopy ; break ; + case wxAND: // src AND dst + mode = adMin ; + break ; // unsupported TODO case wxCLEAR: // 0 case wxAND_REVERSE:// src AND (NOT dst) - case wxAND: // src AND dst case wxAND_INVERT: // (NOT src) AND dst case wxNO_OP: // dst case wxNOR: // (NOT src) AND (NOT dst) @@ -1765,11 +1774,11 @@ 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 ; - status = ::ATSUCreateStyle(&(ATSUStyle)m_macATSUIStyle) ; - wxASSERT_MSG( status == noErr , "couldn't create ATSU style" ) ; + 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[] = { kATSUFontTag , @@ -1798,7 +1807,7 @@ void wxDC::MacInstallFont() const } ; Boolean kTrue = true ; Boolean kFalse = false ; - BslnBaselineClass kBaselineDefault = kBSLNHangingBaseline ; + //BslnBaselineClass kBaselineDefault = kBSLNHangingBaseline ; ATSUVerticalCharacterType kHorizontal = kATSUStronglyHorizontal; ATSUAttributeValuePtr atsuValues[sizeof(atsuTags)/sizeof(ATSUAttributeTag)] = { @@ -1813,56 +1822,52 @@ void wxDC::MacInstallFont() const (qdStyle & condense) ? &kTrue : &kFalse , (qdStyle & extend) ? &kTrue : &kFalse , } ; - status = ::ATSUSetAttributes((ATSUStyle)m_macATSUIStyle, sizeof(atsuTags)/sizeof(ATSUAttributeTag), + status = ::ATSUSetAttributes((ATSUStyle)m_macATSUIStyle, sizeof(atsuTags)/sizeof(ATSUAttributeTag) , atsuTags, atsuSizes, atsuValues); - wxASSERT_MSG( status == noErr , "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 } } + wxASSERT_MSG( status == noErr , wxT("couldn't set create ATSU style") ) ; +} + +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()); @@ -1870,67 +1875,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 ) @@ -1951,10 +1922,12 @@ void wxDC::MacInstallPen() const case wxSRC_INVERT: // (NOT src) mode = notPatCopy ; break ; + case wxAND: // src AND dst + mode = adMin ; + break ; // unsupported TODO case wxCLEAR: // 0 case wxAND_REVERSE:// src AND (NOT dst) - case wxAND: // src AND dst case wxAND_INVERT: // (NOT src) AND dst case wxNO_OP: // dst case wxNOR: // (NOT src) AND (NOT dst) @@ -1976,37 +1949,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 ; } } } @@ -2029,7 +2005,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 ) @@ -2131,10 +2107,12 @@ void wxDC::MacInstallBrush() const case wxSRC_INVERT: // (NOT src) mode = notPatCopy ; break ; + case wxAND: // src AND dst + mode = adMin ; + break ; // unsupported TODO case wxCLEAR: // 0 case wxAND_REVERSE:// src AND (NOT dst) - case wxAND: // src AND dst case wxAND_INVERT: // (NOT src) AND dst case wxNO_OP: // dst case wxNOR: // (NOT src) AND (NOT dst) @@ -2195,4 +2173,4 @@ wxCoord wxDCBase::LogicalToDeviceXRel(wxCoord x) const wxCoord wxDCBase::LogicalToDeviceYRel(wxCoord y) const { return ((wxDC *)this)->YLOG2DEVREL(y); -} \ No newline at end of file +}