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 wxCHECK_RET( window
, _T("invalid window in wxClientDC") );
262 wxPoint origin
= window
->GetClientAreaOrigin() ;
263 m_window
->GetClientSize( &m_width
, &m_height
);
264 SetDeviceOrigin( origin
.x
, origin
.y
);
265 SetClippingRegion( 0 , 0 , m_width
, m_height
) ;
268 wxClientDC::wxClientDC(wxWindow
*window
)
270 wxCHECK_RET( window
, _T("invalid window in wxClientDC") );
272 wxTopLevelWindowMac
* rootwindow
= window
->MacGetTopLevelWindow() ;
276 WindowRef windowref
= (WindowRef
) rootwindow
->MacGetWindowRef() ;
277 wxPoint origin
= window
->GetClientAreaOrigin() ;
278 wxSize size
= window
->GetClientSize() ;
282 window
->MacWindowToRootWindow( &x
, &y
) ;
283 m_macPort
= UMAGetWindowPort( windowref
) ;
286 m_deviceLocalOriginX
= x
;
287 m_deviceLocalOriginY
= y
;
288 SetRectRgn( (RgnHandle
) m_macBoundaryClipRgn
, origin
.x
, origin
.y
, origin
.x
+ size
.x
, origin
.y
+ size
.y
) ;
289 SectRgn( (RgnHandle
) m_macBoundaryClipRgn
, (RgnHandle
) window
->MacGetVisibleRegion().GetWXHRGN() , (RgnHandle
) m_macBoundaryClipRgn
) ;
290 OffsetRgn( (RgnHandle
) m_macBoundaryClipRgn
, -origin
.x
, -origin
.y
) ;
291 OffsetRgn( (RgnHandle
) m_macBoundaryClipRgn
, m_deviceLocalOriginX
, m_deviceLocalOriginY
) ;
292 CopyRgn( (RgnHandle
) m_macBoundaryClipRgn
,(RgnHandle
) m_macCurrentClipRgn
) ;
294 SetBackground(MacGetBackgroundBrush(window
));
295 SetFont( window
->GetFont() ) ;
299 wxClientDC::~wxClientDC()
303 #if !wxMAC_USE_CORE_GRAPHICS
304 void wxClientDC::DoGetSize(int *width
, int *height
) const
306 wxCHECK_RET( m_window
, _T("GetSize() doesn't work without window") );
308 m_window
->GetClientSize( width
, height
);
316 wxPaintDC::wxPaintDC()
321 #if wxMAC_USE_CORE_GRAPHICS
322 wxPaintDC::wxPaintDC(wxWindow
*window
) :
325 wxPoint origin
= window
->GetClientAreaOrigin() ;
326 m_window
->GetClientSize( &m_width
, &m_height
);
327 SetDeviceOrigin( origin
.x
, origin
.y
);
328 SetClippingRegion( 0 , 0 , m_width
, m_height
) ;
331 wxPaintDC::wxPaintDC(wxWindow
*window
)
334 wxTopLevelWindowMac
* rootwindow
= window
->MacGetTopLevelWindow() ;
335 WindowRef windowref
= (WindowRef
) rootwindow
->MacGetWindowRef() ;
336 wxPoint origin
= window
->GetClientAreaOrigin() ;
337 wxSize size
= window
->GetClientSize() ;
341 window
->MacWindowToRootWindow( &x
, &y
) ;
342 m_macPort
= UMAGetWindowPort( windowref
) ;
345 #if wxMAC_USE_CORE_GRAPHICS
346 if ( window
->MacGetCGContextRef() )
348 m_graphicContext
= new wxMacCGContext( (CGContextRef
) window
->MacGetCGContextRef() ) ;
349 m_graphicContext
->SetPen( m_pen
) ;
350 m_graphicContext
->SetBrush( m_brush
) ;
351 SetClippingRegion( 0 , 0 , size
.x
, size
.y
) ;
352 SetBackground(MacGetBackgroundBrush(window
));
356 wxLogDebug(wxT("You cannot create a wxPaintDC outside an OS-draw event") ) ;
357 m_graphicContext
= NULL
;
359 // there is no out-of-order drawing on OSX
361 m_deviceLocalOriginX
= x
;
362 m_deviceLocalOriginY
= y
;
363 SetRectRgn( (RgnHandle
) m_macBoundaryClipRgn
, origin
.x
, origin
.y
, origin
.x
+ size
.x
, origin
.y
+ size
.y
) ;
364 SectRgn( (RgnHandle
) m_macBoundaryClipRgn
, (RgnHandle
) window
->MacGetVisibleRegion().GetWXHRGN() , (RgnHandle
) m_macBoundaryClipRgn
) ;
365 OffsetRgn( (RgnHandle
) m_macBoundaryClipRgn
, -origin
.x
, -origin
.y
) ;
366 SectRgn( (RgnHandle
) m_macBoundaryClipRgn
, (RgnHandle
) window
->GetUpdateRegion().GetWXHRGN() , (RgnHandle
) m_macBoundaryClipRgn
) ;
367 OffsetRgn( (RgnHandle
) m_macBoundaryClipRgn
, m_deviceLocalOriginX
, m_deviceLocalOriginY
) ;
368 CopyRgn( (RgnHandle
) m_macBoundaryClipRgn
, (RgnHandle
) m_macCurrentClipRgn
) ;
369 SetBackground(MacGetBackgroundBrush(window
));
372 SetFont( window
->GetFont() ) ;
376 wxPaintDC::~wxPaintDC()
380 #if !wxMAC_USE_CORE_GRAPHICS
381 void wxPaintDC::DoGetSize(int *width
, int *height
) const
383 wxCHECK_RET( m_window
, _T("GetSize() doesn't work without window") );
385 m_window
->GetClientSize( width
, height
);