1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/mac/carbon/dcclient.cpp 
   3 // Purpose:     wxClientDC class 
   4 // Author:      Stefan Csomor 
   8 // Copyright:   (c) Stefan Csomor 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 #include "wx/wxprec.h" 
  14 #include "wx/dcclient.h" 
  18     #include "wx/window.h" 
  19     #include "wx/dcmemory.h" 
  20     #include "wx/settings.h" 
  21     #include "wx/toplevel.h" 
  23     #include "wx/region.h" 
  26 #include "wx/graphics.h" 
  27 #include "wx/rawbmp.h" 
  28 #include "wx/mac/private.h" 
  30 //----------------------------------------------------------------------------- 
  32 //----------------------------------------------------------------------------- 
  34 //----------------------------------------------------------------------------- 
  36 //----------------------------------------------------------------------------- 
  38 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
) 
  39 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
) 
  40 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxWindowDC
) 
  46 #include "wx/mac/uma.h" 
  47 #include "wx/notebook.h" 
  48 #include "wx/tabctrl.h" 
  51 static wxBrush 
MacGetBackgroundBrush( wxWindow
* window 
) 
  53     wxBrush bkdBrush 
= window
->MacGetBackgroundBrush() ; 
  55 #if !TARGET_API_MAC_OSX 
  56     // transparency cannot be handled by the OS when not using composited windows 
  57     wxWindow
* parent 
= window
->GetParent() ; 
  59     // if we have some 'pseudo' transparency 
  60     if ( ! bkdBrush
.Ok() || bkdBrush
.GetStyle() == wxTRANSPARENT 
|| window
->GetBackgroundColour() == wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE 
) ) 
  62         // walk up until we find something 
  63         while ( parent 
!= NULL 
) 
  65             if ( parent
->GetBackgroundColour() != wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE 
) ) 
  67                 // if we have any other colours in the hierarchy 
  68                 bkdBrush
.SetColour( parent
->GetBackgroundColour() ) ; 
  72             if ( parent
->IsKindOf( CLASSINFO(wxTopLevelWindow
) ) ) 
  74                 bkdBrush 
= parent
->MacGetBackgroundBrush() ; 
  78             if ( parent
->IsKindOf( CLASSINFO( wxNotebook 
) ) 
  80                  || parent
->IsKindOf( CLASSINFO( wxTabCtrl 
) ) 
  81 #endif // wxUSE_TAB_DIALOG 
  84                 Rect extent 
= { 0 , 0 , 0 , 0 } ; 
  87                 wxSize size 
= parent
->GetSize() ; 
  88                 parent
->MacClientToRootWindow( &x 
, &y 
) ; 
  92                 extent
.right 
= x 
+ size
.x 
; 
  93                 extent
.bottom 
= y 
+ size
.y 
; 
  94                 bkdBrush
.MacSetThemeBackground( kThemeBackgroundTabPane 
, (WXRECTPTR
) &extent 
) ; 
  98             parent 
= parent
->GetParent() ; 
 102     if ( !bkdBrush
.Ok() || bkdBrush
.GetStyle() == wxTRANSPARENT 
) 
 104         // if we did not find something, use a default 
 105         bkdBrush
.MacSetTheme( kThemeBrushDialogBackgroundActive 
) ; 
 112 wxWindowDC::wxWindowDC() 
 115 #if wxMAC_USE_CORE_GRAPHICS 
 120 wxWindowDC::wxWindowDC(wxWindow 
*window
) 
 123     wxTopLevelWindowMac
* rootwindow 
= window
->MacGetTopLevelWindow() ; 
 129 #if wxMAC_USE_CORE_GRAPHICS 
 130     m_window
->GetSize( &m_width 
, &m_height
); 
 131     CGContextRef cg 
= (CGContextRef
) window
->MacGetCGContextRef(); 
 135         SetGraphicsContext( wxGraphicsContext::Create( window 
) ) ; 
 139         CGContextSaveGState( cg 
); 
 141         // make sure the context is having its origin at the wx-window coordinates of the 
 142         // view (read at the top of window.cpp about the differences) 
 143         if ( window
->MacGetLeftBorderSize() != 0 || window
->MacGetTopBorderSize() != 0 ) 
 144             CGContextTranslateCTM( cg 
, -window
->MacGetLeftBorderSize() , -window
->MacGetTopBorderSize() ); 
 146         SetGraphicsContext( wxGraphicsContext::CreateFromNative( cg 
) ); 
 148     SetClippingRegion( 0 , 0 , m_width 
, m_height 
) ; 
 152     window
->MacWindowToRootWindow( &x 
, &y 
) ; 
 153     m_deviceLocalOriginX 
= x
; 
 154     m_deviceLocalOriginY 
= y
; 
 155     m_macPort 
= UMAGetWindowPort( (WindowRef
) rootwindow
->MacGetWindowRef() ) ; 
 157     CopyRgn( (RgnHandle
) window
->MacGetVisibleRegion(true).GetWXHRGN() , (RgnHandle
) m_macBoundaryClipRgn 
) ; 
 158     OffsetRgn( (RgnHandle
) m_macBoundaryClipRgn 
, m_deviceLocalOriginX 
, m_deviceLocalOriginY 
) ; 
 159     CopyRgn( (RgnHandle
) m_macBoundaryClipRgn 
, (RgnHandle
) m_macCurrentClipRgn 
) ; 
 161     SetBackground(MacGetBackgroundBrush(window
)); 
 163     SetFont( window
->GetFont() ) ; 
 166 wxWindowDC::~wxWindowDC() 
 168 #if wxMAC_USE_CORE_GRAPHICS 
 171         // this must not necessarily be the current context, we must restore the state of the 
 172         // cg we started with above (before the CGContextTranslateCTM call) 
 173         CGContextRef cg 
= (CGContextRef
) m_window
->MacGetCGContextRef(); 
 174         CGContextRestoreGState(cg
); 
 179 void wxWindowDC::DoGetSize( int* width
, int* height 
) const 
 181 #if wxMAC_USE_CORE_GRAPHICS 
 187     wxCHECK_RET( m_window
, _T("GetSize() doesn't work without window") ); 
 188     m_window
->GetSize(width
, height
); 
 192 wxBitmap 
wxWindowDC::DoGetAsBitmap(const wxRect 
*subrect
) const 
 194     // wxScreenDC is derived from wxWindowDC, so a screen dc will 
 195     // call this method when a Blit is performed with it as a source. 
 199     ControlRef handle 
= (ControlRef
) m_window
->GetHandle(); 
 205     CGContextRef context
; 
 210     HIViewCreateOffscreenImage( handle
, 0, &rect
, &image
); 
 213     int width 
= subrect 
!= NULL 
? subrect
->width 
: (int)rect
.size
.width
; 
 214     int height 
= subrect 
!=  NULL 
? subrect
->height 
: (int)rect
.size
.height 
; 
 216     bytesPerRow 
= ( ( width 
* 8 * 4 + 7 ) / 8 ); 
 218     data 
= calloc( 1, bytesPerRow 
* height 
); 
 219     context 
= CGBitmapContextCreate( data
, width
, height
, 8, bytesPerRow
, CGColorSpaceCreateDeviceRGB(), kCGImageAlphaPremultipliedFirst 
); 
 222         rect 
= CGRectOffset( rect
, -subrect
->x
, -subrect
->y 
) ; 
 223     CGContextDrawImage( context
, rect
, image 
); 
 225     unsigned char* buffer 
= (unsigned char*) data
; 
 226     wxBitmap bmp 
= wxBitmap(width
, height
, 32); 
 227     wxAlphaPixelData 
pixData(bmp
, wxPoint(0,0), wxSize(width
, height
)); 
 230     wxAlphaPixelData::Iterator 
p(pixData
); 
 231     for (int y
=0; y
<height
; y
++) { 
 232         wxAlphaPixelData::Iterator rowStart 
= p
; 
 233         for (int x
=0; x
<width
; x
++) { 
 234             unsigned char a 
= buffer
[3]; 
 235             p
.Red()   = a
; buffer
++; 
 236             p
.Green() = a
; buffer
++; 
 237             p
.Blue()  = a
; buffer
++; 
 238             p
.Alpha() = a
; buffer
++; 
 242         p
.OffsetY(pixData
, 1); 
 252 wxClientDC::wxClientDC() 
 257 #if wxMAC_USE_CORE_GRAPHICS 
 258 wxClientDC::wxClientDC(wxWindow 
*window
) : 
 261     wxPoint origin 
= window
->GetClientAreaOrigin() ; 
 262     m_window
->GetClientSize( &m_width 
, &m_height
); 
 263     SetDeviceOrigin( origin
.x
, origin
.y 
); 
 264     SetClippingRegion( 0 , 0 , m_width 
, m_height 
) ; 
 267 wxClientDC::wxClientDC(wxWindow 
*window
) 
 270     wxTopLevelWindowMac
* rootwindow 
= window
->MacGetTopLevelWindow() ; 
 274     WindowRef windowref 
= (WindowRef
) rootwindow
->MacGetWindowRef() ; 
 275     wxPoint origin 
= window
->GetClientAreaOrigin() ; 
 276     wxSize size 
= window
->GetClientSize() ; 
 280     window
->MacWindowToRootWindow( &x 
, &y 
) ; 
 281     m_macPort 
= UMAGetWindowPort( windowref 
) ; 
 284     m_deviceLocalOriginX 
= x 
; 
 285     m_deviceLocalOriginY 
= y 
; 
 286     SetRectRgn( (RgnHandle
) m_macBoundaryClipRgn 
, origin
.x 
, origin
.y 
, origin
.x 
+ size
.x 
, origin
.y 
+ size
.y 
) ; 
 287     SectRgn( (RgnHandle
) m_macBoundaryClipRgn 
, (RgnHandle
) window
->MacGetVisibleRegion().GetWXHRGN() , (RgnHandle
) m_macBoundaryClipRgn 
) ; 
 288     OffsetRgn( (RgnHandle
) m_macBoundaryClipRgn 
, -origin
.x 
, -origin
.y 
) ; 
 289     OffsetRgn( (RgnHandle
) m_macBoundaryClipRgn 
, m_deviceLocalOriginX 
, m_deviceLocalOriginY 
) ; 
 290     CopyRgn( (RgnHandle
) m_macBoundaryClipRgn 
,(RgnHandle
)  m_macCurrentClipRgn 
) ; 
 292     SetBackground(MacGetBackgroundBrush(window
)); 
 293     SetFont( window
->GetFont() ) ; 
 297 wxClientDC::~wxClientDC() 
 301 #if !wxMAC_USE_CORE_GRAPHICS 
 302 void wxClientDC::DoGetSize(int *width
, int *height
) const 
 304     wxCHECK_RET( m_window
, _T("GetSize() doesn't work without window") ); 
 306     m_window
->GetClientSize( width
, height 
); 
 314 wxPaintDC::wxPaintDC() 
 319 #if wxMAC_USE_CORE_GRAPHICS 
 320 wxPaintDC::wxPaintDC(wxWindow 
*window
) : 
 323     wxPoint origin 
= window
->GetClientAreaOrigin() ; 
 324     m_window
->GetClientSize( &m_width 
, &m_height
); 
 325     SetDeviceOrigin( origin
.x
, origin
.y 
); 
 326     SetClippingRegion( 0 , 0 , m_width 
, m_height 
) ; 
 329 wxPaintDC::wxPaintDC(wxWindow 
*window
) 
 332     wxTopLevelWindowMac
* rootwindow 
= window
->MacGetTopLevelWindow() ; 
 333     WindowRef windowref 
= (WindowRef
) rootwindow
->MacGetWindowRef() ; 
 334     wxPoint origin 
= window
->GetClientAreaOrigin() ; 
 335     wxSize size 
= window
->GetClientSize() ; 
 339     window
->MacWindowToRootWindow( &x 
, &y 
) ; 
 340     m_macPort 
= UMAGetWindowPort( windowref 
) ; 
 343 #if wxMAC_USE_CORE_GRAPHICS 
 344     if ( window
->MacGetCGContextRef() ) 
 346         m_graphicContext 
= new wxMacCGContext( (CGContextRef
) window
->MacGetCGContextRef() ) ; 
 347         m_graphicContext
->SetPen( m_pen 
) ; 
 348         m_graphicContext
->SetBrush( m_brush 
) ; 
 349         SetClippingRegion( 0 , 0 , size
.x 
, size
.y 
) ; 
 350         SetBackground(MacGetBackgroundBrush(window
)); 
 354         wxLogDebug(wxT("You cannot create a wxPaintDC outside an OS-draw event") ) ; 
 355         m_graphicContext 
= NULL 
; 
 357     // there is no out-of-order drawing on OSX 
 359     m_deviceLocalOriginX 
= x 
; 
 360     m_deviceLocalOriginY 
= y 
; 
 361     SetRectRgn( (RgnHandle
) m_macBoundaryClipRgn 
, origin
.x 
, origin
.y 
, origin
.x 
+ size
.x 
, origin
.y 
+ size
.y 
) ; 
 362     SectRgn( (RgnHandle
) m_macBoundaryClipRgn 
, (RgnHandle
) window
->MacGetVisibleRegion().GetWXHRGN() , (RgnHandle
) m_macBoundaryClipRgn 
) ; 
 363     OffsetRgn( (RgnHandle
) m_macBoundaryClipRgn 
, -origin
.x 
, -origin
.y 
) ; 
 364     SectRgn( (RgnHandle
) m_macBoundaryClipRgn  
, (RgnHandle
) window
->GetUpdateRegion().GetWXHRGN() , (RgnHandle
) m_macBoundaryClipRgn 
) ; 
 365     OffsetRgn( (RgnHandle
) m_macBoundaryClipRgn 
, m_deviceLocalOriginX 
, m_deviceLocalOriginY 
) ; 
 366     CopyRgn( (RgnHandle
) m_macBoundaryClipRgn 
, (RgnHandle
) m_macCurrentClipRgn 
) ; 
 367     SetBackground(MacGetBackgroundBrush(window
)); 
 370     SetFont( window
->GetFont() ) ; 
 374 wxPaintDC::~wxPaintDC() 
 378 #if !wxMAC_USE_CORE_GRAPHICS 
 379 void wxPaintDC::DoGetSize(int *width
, int *height
) const 
 381     wxCHECK_RET( m_window
, _T("GetSize() doesn't work without window") ); 
 383     m_window
->GetClientSize( width
, height 
);