X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/a47ae718e2211f64a44eb1238f7e8594c5c3f01b..d109c5849ed117966311a44875c97ae3d77b44e5:/src/mac/carbon/dc.cpp diff --git a/src/mac/carbon/dc.cpp b/src/mac/carbon/dc.cpp index d830f68a1e..3084e7224c 100644 --- a/src/mac/carbon/dc.cpp +++ b/src/mac/carbon/dc.cpp @@ -28,10 +28,10 @@ using namespace std ; #endif #include "wx/mac/private.h" -#include "ATSUnicode.h" -#include "TextCommon.h" -#include "TextEncodingConverter.h" -#include "FixMath.h" +#include +#include +#include +#include #if !USE_SHARED_LIBRARY IMPLEMENT_ABSTRACT_CLASS(wxDC, wxObject) #endif @@ -79,8 +79,7 @@ public : wxMacFastPortSetter( const wxDC *dc ) { wxASSERT( dc->Ok() ) ; - GetPort( &m_oldPort ) ; - SetPort( (GrafPtr) dc->m_macPort ) ; + m_swapped = QDSwapPort( (GrafPtr) dc->m_macPort , &m_oldPort ) ; m_clipRgn = NewRgn() ; GetClip( m_clipRgn ) ; m_dc = dc ; @@ -88,13 +87,15 @@ public : } ~wxMacFastPortSetter() { - SetPort( (GrafPtr) m_dc->m_macPort ) ; + // SetPort( (GrafPtr) m_dc->m_macPort ) ; SetClip( m_clipRgn ) ; - SetPort( m_oldPort ) ; + 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 ; @@ -104,71 +105,49 @@ private : typedef wxMacPortSetter wxMacFastPortSetter ; #endif -#if 0 - -// start moving to a dual implementation for QD and CGContextRef - -class wxMacGraphicsContext -{ -public : - void DrawBitmap( const wxBitmap &bmp, wxCoord x, wxCoord y, bool useMask ) = 0 ; - void SetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height ) = 0 ; - void SetClippingRegion( const wxRegion ®ion ) = 0 ; - void DestroyClippingRegion() = 0 ; - void SetTextForeground( const wxColour &col ) = 0 ; - void SetTextBackground( const wxColour &col ) = 0 ; - void SetLogicalScale( double x , double y ) = 0 ; - void SetUserScale( double x , double y ) = 0; -} ; - -class wxMacQuickDrawContext : public wxMacGraphicsContext -{ -public : -} ; - -#endif - -wxMacWindowClipper::wxMacWindowClipper( const wxWindow* win ) +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 //----------------------------------------------------------------------------- @@ -533,7 +512,7 @@ void wxDC::DestroyClippingRegion() { wxMacFastPortSetter helper(this) ; CopyRgn( (RgnHandle) m_macBoundaryClipRgn , (RgnHandle) m_macCurrentClipRgn ) ; - m_clipping = FALSE; + ResetClipping(); } void wxDC::DoGetSizeMM( int* width, int* height ) const @@ -617,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); @@ -666,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); } } @@ -1358,7 +1322,7 @@ 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); @@ -1367,29 +1331,46 @@ void wxDC::DoDrawRotatedText(const wxString& str, wxCoord x, wxCoord y, if ( str.Length() == 0 ) return ; - +*/ 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 + 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 ) ; - int wlen = wxWcslen( wchar.data() ) ; - status = ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr) wchar.data() , 0 , wlen , wlen , 1 , - &chars , (ATSUStyle*) &m_macATSUIStyle , &atsuLayout ) ; + 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) ; @@ -1435,6 +1416,9 @@ 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 SIZEOF_WCHAR_T == 4 + free( ubuf ) ; +#endif } void wxDC::DoDrawText(const wxString& strtext, wxCoord x, wxCoord y) @@ -1471,64 +1455,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 = linetext.mb_str(wxConvLocal) ; - ::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 ) { @@ -1536,7 +1470,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, @@ -1546,7 +1480,7 @@ void wxDC::DoDrawText(const wxString& strtext, wxCoord x, wxCoord y) ::EraseRect( &background ) ; } ::DrawThemeTextBox( mString, - kThemeCurrentPortFont, + m_font.MacGetThemeFontID() , kThemeStateActive, false, &frame, @@ -1557,6 +1491,14 @@ void wxDC::DoDrawText(const wxString& strtext, wxCoord x, wxCoord y) #endif { 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) ) ; } } @@ -1595,57 +1537,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() ; - 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 = linetext.mb_str(wxConvLocal) ; - 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, @@ -1653,7 +1559,6 @@ void wxDC::DoGetTextExtent( const wxString &strtext, wxCoord *width, wxCoord *h curwidth = bounds.h ; } else -#endif { wxCharBuffer text = linetext.mb_str(wxConvLocal) ; curwidth = ::TextWidth( text , 0 , strlen(text) ) ; @@ -1669,6 +1574,68 @@ 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; iGetNoAntiAliasing() ) useGetThemeText = false ; #endif - char text[] = "H" ; + char text[] = "g" ; #if TARGET_CARBON if ( useGetThemeText ) { @@ -1688,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, @@ -1719,10 +1686,9 @@ void wxDC::Clear(void) wxCHECK_RET(Ok(), wxT("Invalid DC")); 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 ) ; } @@ -1735,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 ; @@ -1809,9 +1774,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[] = @@ -1984,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 ; - wxMacGetPattern(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 ; } } }