]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/dccg.cpp
Fix error and some warnings - wxTopLevelWindowMac needs toplevel.h, but we only need...
[wxWidgets.git] / src / mac / carbon / dccg.cpp
CommitLineData
613a24f7
SC
1/////////////////////////////////////////////////////////////////////////////
2// Name: dc.cpp
3// Purpose: wxDC class
4// Author: Stefan Csomor
5// Modified by:
6// Created: 01/02/97
7// RCS-ID: $Id$
8// Copyright: (c) Stefan Csomor
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation "dc.h"
14#endif
15
20b69855
SC
16#include "wx/wxprec.h"
17
613a24f7 18#include "wx/dc.h"
20b69855
SC
19
20#if wxMAC_USE_CORE_GRAPHICS
21
613a24f7
SC
22#include "wx/app.h"
23#include "wx/mac/uma.h"
24#include "wx/dcmemory.h"
25#include "wx/dcprint.h"
26#include "wx/region.h"
27#include "wx/image.h"
28#include "wx/log.h"
29
20b69855 30
613a24f7
SC
31#if __MSL__ >= 0x6000
32#include "math.h"
33using namespace std ;
34#endif
35
36#include "wx/mac/private.h"
37#include <ATSUnicode.h>
38#include <TextCommon.h>
39#include <TextEncodingConverter.h>
40#include <FixMath.h>
41#include <CGContext.h>
42
43#if !USE_SHARED_LIBRARY
44IMPLEMENT_ABSTRACT_CLASS(wxDC, wxObject)
45#endif
46
47//-----------------------------------------------------------------------------
48// constants
49//-----------------------------------------------------------------------------
50
51#if !defined( __DARWIN__ ) || defined(__MWERKS__)
52#ifndef M_PI
53const double M_PI = 3.14159265358979 ;
54#endif
55#endif
56const double RAD2DEG = 180.0 / M_PI;
57const short kEmulatedMode = -1 ;
58const short kUnsupportedMode = -2 ;
59
60extern TECObjectRef s_TECNativeCToUnicode ;
61
20b69855
SC
62// TODO Update
63// The text ctrl implementation still needs that for the non hiview implementation
613a24f7
SC
64
65wxMacWindowClipper::wxMacWindowClipper( const wxWindow* win ) :
66 wxMacPortSaver( (GrafPtr) GetWindowPort((WindowRef) win->MacGetTopLevelWindowRef()) )
67{
68 m_newPort =(GrafPtr) GetWindowPort((WindowRef) win->MacGetTopLevelWindowRef()) ;
69 m_formerClip = NewRgn() ;
70 m_newClip = NewRgn() ;
71 GetClip( m_formerClip ) ;
72
73 if ( win )
74 {
bcbbfab8
SC
75 // guard against half constructed objects, this just leads to a empty clip
76 if( win->GetPeer() )
77 {
78 int x = 0 , y = 0;
79 win->MacWindowToRootWindow( &x,&y ) ;
80 // get area including focus rect
81 CopyRgn( (RgnHandle) ((wxWindow*)win)->MacGetVisibleRegion(true).GetWXHRGN() , m_newClip ) ;
82 if ( !EmptyRgn( m_newClip ) )
83 OffsetRgn( m_newClip , x , y ) ;
84 }
613a24f7
SC
85
86 SetClip( m_newClip ) ;
87 }
88}
89
90wxMacWindowClipper::~wxMacWindowClipper()
91{
92 SetPort( m_newPort ) ;
93 SetClip( m_formerClip ) ;
94 DisposeRgn( m_newClip ) ;
95 DisposeRgn( m_formerClip ) ;
96}
97
98wxMacWindowStateSaver::wxMacWindowStateSaver( const wxWindow* win ) :
99 wxMacWindowClipper( win )
100{
101 // the port is already set at this point
102 m_newPort =(GrafPtr) GetWindowPort((WindowRef) win->MacGetTopLevelWindowRef()) ;
103 GetThemeDrawingState( &m_themeDrawingState ) ;
104}
105
106wxMacWindowStateSaver::~wxMacWindowStateSaver()
107{
108 SetPort( m_newPort ) ;
109 SetThemeDrawingState( m_themeDrawingState , true ) ;
110}
111
a8f234d2
SC
112// minimal implementation only used for appearance drawing < 10.3
113
114wxMacPortSetter::wxMacPortSetter( const wxDC* dc ) :
115 m_ph( (GrafPtr) dc->m_macPort )
116{
117 wxASSERT( dc->Ok() ) ;
118 m_dc = dc ;
119// dc->MacSetupPort(&m_ph) ;
120}
121wxMacPortSetter::~wxMacPortSetter()
122{
123// m_dc->MacCleanupPort(&m_ph) ;
124}
125
613a24f7
SC
126//-----------------------------------------------------------------------------
127// Local functions
128//-----------------------------------------------------------------------------
20b69855 129
613a24f7
SC
130static inline double dmin(double a, double b) { return a < b ? a : b; }
131static inline double dmax(double a, double b) { return a > b ? a : b; }
132static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; }
133
134//-----------------------------------------------------------------------------
20b69855
SC
135// device context implementation
136//
137// more and more of the dc functionality should be implemented by calling
138// the appropricate wxMacCGContext, but we will have to do that step by step
139// also coordinate conversions should be moved to native matrix ops
613a24f7 140//-----------------------------------------------------------------------------
613a24f7 141
20b69855 142wxMacCGPath::wxMacCGPath()
613a24f7 143{
20b69855 144 m_path = CGPathCreateMutable() ;
613a24f7
SC
145}
146
20b69855 147wxMacCGPath::~wxMacCGPath()
613a24f7 148{
20b69855
SC
149 CGPathRelease( m_path ) ;
150}
613a24f7 151
20b69855
SC
152// Starts a new subpath at
153void wxMacCGPath::MoveToPoint( wxCoord x1 , wxCoord y1 )
154{
155 CGPathMoveToPoint( m_path , NULL , x1 , y1 ) ;
156}
613a24f7 157
20b69855
SC
158void wxMacCGPath::AddLineToPoint( wxCoord x1 , wxCoord y1 )
159{
160 CGPathAddLineToPoint( m_path , NULL , x1 , y1 ) ;
161}
613a24f7 162
20b69855 163void wxMacCGPath::AddRectangle( wxCoord x, wxCoord y, wxCoord w, wxCoord h )
613a24f7 164{
20b69855
SC
165 CGRect cgRect = { { x , y } , { w , h } } ;
166 CGPathAddRect( m_path , NULL , cgRect ) ;
167}
613a24f7 168
20b69855
SC
169void wxMacCGPath::AddCircle( wxCoord x, wxCoord y , wxCoord r )
170{
171 CGPathAddArc( m_path , NULL , x , y , r , 0.0 , 2 * M_PI , true ) ;
172}
613a24f7 173
20b69855
SC
174// closes the current subpath
175void wxMacCGPath::CloseSubpath()
176{
177 CGPathCloseSubpath( m_path ) ;
178}
613a24f7 179
20b69855 180CGPathRef wxMacCGPath::GetPath() const
613a24f7 181{
20b69855
SC
182 return m_path ;
183}
184
b014adcc
SC
185// we always stock two context states, one at entry, the other one after
186// changing to HI Graphics orientation (this one is used for getting back clippings etc)
613a24f7 187
20b69855
SC
188wxMacCGContext::wxMacCGContext( CGrafPtr port )
189{
190 m_qdPort = port ;
cb4b0966 191 m_cgContext = NULL ;
20b69855
SC
192}
193
194wxMacCGContext::wxMacCGContext( CGContextRef cgcontext )
195{
196 m_qdPort = NULL ;
197 m_cgContext = cgcontext ;
b014adcc
SC
198 CGContextSaveGState( m_cgContext ) ;
199 CGContextSaveGState( m_cgContext ) ;
20b69855
SC
200}
201
202wxMacCGContext::wxMacCGContext()
203{
204 m_qdPort = NULL ;
205 m_cgContext = NULL ;
206}
613a24f7 207
20b69855
SC
208wxMacCGContext::~wxMacCGContext()
209{
b014adcc
SC
210 if ( m_cgContext )
211 {
68654a82 212 CGContextSynchronize( m_cgContext ) ;
b014adcc
SC
213 CGContextRestoreGState( m_cgContext ) ;
214 CGContextRestoreGState( m_cgContext ) ;
215 }
20b69855 216 if ( m_qdPort )
68654a82 217 CGContextRelease( m_cgContext ) ;
20b69855
SC
218}
219
220
221void wxMacCGContext::Clip( const wxRegion &region )
222{
223// ClipCGContextToRegion ( m_cgContext, &bounds , (RgnHandle) dc->m_macCurrentClipRgn ) ;
224}
225
226void wxMacCGContext::StrokePath( const wxGraphicPath *p )
227{
228 const wxMacCGPath* path = dynamic_cast< const wxMacCGPath*>( p ) ;
229 CGContextBeginPath( m_cgContext ) ;
230 CGContextAddPath( m_cgContext , path->GetPath() ) ;
231 CGContextClosePath( m_cgContext ) ;
232 CGContextStrokePath( m_cgContext ) ;
233}
234
235void wxMacCGContext::DrawPath( const wxGraphicPath *p , int fillStyle )
236{
237 const wxMacCGPath* path = dynamic_cast< const wxMacCGPath*>( p ) ;
238 CGPathDrawingMode mode = m_mode ;
239 if ( fillStyle == wxODDEVEN_RULE )
240 {
241 if ( mode == kCGPathFill )
242 mode = kCGPathEOFill ;
243 else if ( mode == kCGPathFillStroke )
244 mode = kCGPathEOFillStroke ;
245 }
246 CGContextBeginPath( m_cgContext ) ;
247 CGContextAddPath( m_cgContext , path->GetPath() ) ;
248 CGContextClosePath( m_cgContext ) ;
249 CGContextDrawPath( m_cgContext , mode ) ;
613a24f7
SC
250}
251
20b69855 252void wxMacCGContext::FillPath( const wxGraphicPath *p , const wxColor &fillColor , int fillStyle )
613a24f7 253{
20b69855
SC
254 const wxMacCGPath* path = dynamic_cast< const wxMacCGPath*>( p ) ;
255 CGContextSaveGState( m_cgContext ) ;
256
257 RGBColor col = MAC_WXCOLORREF( fillColor.GetPixel() ) ;
258 CGContextSetRGBFillColor( m_cgContext , col.red / 65536.0 , col.green / 65536.0 , col.blue / 65536.0 , 1.0 ) ;
259 CGPathDrawingMode mode = kCGPathFill ;
260
261 if ( fillStyle == wxODDEVEN_RULE )
262 mode = kCGPathEOFill ;
263
264 CGContextBeginPath( m_cgContext ) ;
265 CGContextAddPath( m_cgContext , path->GetPath() ) ;
266 CGContextClosePath( m_cgContext ) ;
267 CGContextDrawPath( m_cgContext , mode ) ;
268
269 CGContextRestoreGState( m_cgContext ) ;
270}
613a24f7 271
cb4b0966
SC
272wxGraphicPath* wxMacCGContext::CreatePath()
273{
cb4b0966
SC
274 // make sure that we now have a real cgref, before doing
275 // anything with paths
a63b4755
SC
276 CGContextRef cg = GetNativeContext() ;
277 cg = NULL ;
cb4b0966
SC
278 return new wxMacCGPath() ;
279}
280
281// in case we only got a QDPort only create a cgref now
282
283CGContextRef wxMacCGContext::GetNativeContext()
284{
285 if( m_cgContext == NULL )
286 {
287 Rect bounds ;
288 GetPortBounds( (CGrafPtr) m_qdPort , &bounds ) ;
68654a82 289 OSStatus status = CreateCGContextForPort((CGrafPtr) m_qdPort , &m_cgContext) ;
b014adcc 290 CGContextSaveGState( m_cgContext ) ;
cb4b0966
SC
291
292 wxASSERT_MSG( status == noErr , wxT("Cannot nest wxDCs on the same window") ) ;
293 CGContextTranslateCTM( m_cgContext , 0 , bounds.bottom - bounds.top ) ;
294 CGContextScaleCTM( m_cgContext , 1 , -1 ) ;
295
b014adcc 296 CGContextSaveGState( m_cgContext ) ;
cb4b0966
SC
297 SetPen( m_pen ) ;
298 SetBrush( m_brush ) ;
299 }
300 return m_cgContext ;
301}
302
303void wxMacCGContext::SetNativeContext( CGContextRef cg )
304{
b014adcc 305 wxASSERT( m_cgContext == NULL ) ;
cb4b0966 306 m_cgContext = cg ;
b014adcc 307 CGContextSaveGState( m_cgContext ) ;
cb4b0966 308}
20b69855
SC
309
310void wxMacCGContext::SetPen( const wxPen &pen )
311{
cb4b0966
SC
312 m_pen = pen ;
313 if ( m_cgContext == NULL )
314 return ;
20b69855
SC
315 bool fill = m_brush.GetStyle() != wxTRANSPARENT ;
316 bool stroke = pen.GetStyle() != wxTRANSPARENT ;
cb4b0966 317
20b69855
SC
318#if 0
319 // we can benchmark performance, should go into a setting later
320 CGContextSetShouldAntialias( m_cgContext , false ) ;
321#endif
613a24f7
SC
322 if ( fill | stroke )
323 {
613a24f7
SC
324 // setup brushes
325 m_mode = kCGPathFill ; // just a default
326
327 if ( fill )
328 {
613a24f7
SC
329 m_mode = kCGPathFill ;
330 }
331 if ( stroke )
332 {
20b69855 333 RGBColor col = MAC_WXCOLORREF( pen.GetColour().GetPixel() ) ;
613a24f7
SC
334 CGContextSetRGBStrokeColor( m_cgContext , col.red / 65536.0 , col.green / 65536.0 , col.blue / 65536.0 , 1.0 ) ;
335
336 CGLineCap cap ;
20b69855 337 switch( pen.GetCap() )
613a24f7
SC
338 {
339 case wxCAP_ROUND :
340 cap = kCGLineCapRound ;
341 break ;
342 case wxCAP_PROJECTING :
343 cap = kCGLineCapSquare ;
344 break ;
345 case wxCAP_BUTT :
346 cap = kCGLineCapButt ;
347 break ;
348 default :
349 cap = kCGLineCapButt ;
350 break ;
351 }
352 CGContextSetLineCap( m_cgContext , cap ) ;
353
354 CGLineJoin join ;
20b69855 355 switch( pen.GetJoin() )
613a24f7
SC
356 {
357 case wxJOIN_BEVEL :
358 join = kCGLineJoinBevel ;
359 break ;
360 case wxJOIN_MITER :
361 join = kCGLineJoinMiter ;
362 break ;
363 case wxJOIN_ROUND :
364 join = kCGLineJoinRound ;
365 break ;
366 default :
367 join = kCGLineJoinMiter ;
368 break;
369 }
370 CGContextSetLineJoin( m_cgContext , join ) ;
371
20b69855 372 CGContextSetLineWidth( m_cgContext , pen.GetWidth() == 0 ? 0.1 : pen.GetWidth() /* TODO * m_dc->m_scaleX */ ) ;
613a24f7
SC
373
374 m_mode = kCGPathStroke ;
375 int count = 0 ;
376 const float *lengths = NULL ;
377 float *userLengths = NULL ;
378
20b69855
SC
379 const float dotted[] = { 3 , 3 };
380 const float dashed[] = { 19 , 9 };
381 const float short_dashed[] = { 9 , 6 };
382 const float dotted_dashed[] = { 9 , 6 , 3 , 3 };
383
384 switch( pen.GetStyle() )
613a24f7
SC
385 {
386 case wxSOLID :
387 break ;
388 case wxDOT :
613a24f7
SC
389 lengths = dotted ;
390 count = WXSIZEOF(dotted);
391 break ;
392 case wxLONG_DASH :
613a24f7
SC
393 lengths = dashed ;
394 count = WXSIZEOF(dashed) ;
395 break ;
396 case wxSHORT_DASH :
613a24f7
SC
397 lengths = short_dashed ;
398 count = WXSIZEOF(short_dashed) ;
399 break ;
400 case wxDOT_DASH :
613a24f7
SC
401 lengths = dotted_dashed ;
402 count = WXSIZEOF(dotted_dashed);
403 break ;
404 case wxUSER_DASH :
405 wxDash *dashes ;
20b69855 406 count = pen.GetDashes( &dashes ) ;
613a24f7
SC
407 if ( count >0 )
408 {
409 userLengths = new float[count] ;
410 for( int i = 0 ; i < count ; ++i )
411 userLengths[i] = dashes[i] ;
412 }
413 lengths = userLengths ;
414 break ;
415 default :
416 break ;
417 }
418
419 CGContextSetLineDash( m_cgContext , 0 , lengths , count ) ;
420 delete[] userLengths ;
421 // we need to change the cap, otherwise everything overlaps
422 // and we get solid lines
423 if ( count > 0 )
424 CGContextSetLineCap( m_cgContext , kCGLineCapButt ) ;
425 }
426 if ( fill && stroke )
427 {
428 m_mode = kCGPathFillStroke ;
429 }
430
431 }
432}
20b69855
SC
433void wxMacCGContext::SetBrush( const wxBrush &brush )
434{
cb4b0966
SC
435 m_brush = brush ;
436 if ( m_cgContext == NULL )
437 return ;
438
20b69855
SC
439 bool fill = brush.GetStyle() != wxTRANSPARENT ;
440 bool stroke = m_pen.GetStyle() != wxTRANSPARENT ;
613a24f7 441
20b69855
SC
442#if 0
443 // we can benchmark performance, should go into a setting later
444 CGContextSetShouldAntialias( m_cgContext , false ) ;
445#endif
446 if ( fill | stroke )
447 {
448
449 // setup brushes
450 m_mode = kCGPathFill ; // just a default
451
452 if ( fill )
453 {
454 RGBColor col = MAC_WXCOLORREF( brush.GetColour().GetPixel() ) ;
455 CGContextSetRGBFillColor( m_cgContext , col.red / 65536.0 , col.green / 65536.0 , col.blue / 65536.0 , 1.0 ) ;
456 m_mode = kCGPathFill ;
457 }
458 if ( stroke )
459 {
460 m_mode = kCGPathStroke ;
461 }
462 if ( fill && stroke )
463 {
464 m_mode = kCGPathFillStroke ;
465 }
466
467 }
468}
469
470// snippets from Sketch Sample from Apple :
471
472#define kGenericRGBProfilePathStr "/System/Library/ColorSync/Profiles/Generic RGB Profile.icc"
473/*
474 This function locates, opens, and returns the profile reference for the calibrated
475 Generic RGB color space. It is up to the caller to call CMCloseProfile when done
476 with the profile reference this function returns.
477*/
478CMProfileRef wxMacOpenGenericProfile(void)
613a24f7 479{
20b69855
SC
480 static CMProfileRef cachedRGBProfileRef = NULL;
481
482 // we only create the profile reference once
483 if (cachedRGBProfileRef == NULL)
484 {
485 CMProfileLocation loc;
486
487 loc.locType = cmPathBasedProfile;
488 strcpy(loc.u.pathLoc.path, kGenericRGBProfilePathStr);
489
490 verify_noerr( CMOpenProfile(&cachedRGBProfileRef, &loc) );
491 }
492
493 if (cachedRGBProfileRef)
494 {
495 // clone the profile reference so that the caller has their own reference, not our cached one
496 CMCloneProfileRef(cachedRGBProfileRef);
497 }
498
499 return cachedRGBProfileRef;
613a24f7
SC
500}
501
20b69855
SC
502/*
503 Return the generic RGB color space. This is a 'get' function and the caller should
504 not release the returned value unless the caller retains it first. Usually callers
505 of this routine will immediately use the returned colorspace with CoreGraphics
506 so they typically do not need to retain it themselves.
507
508 This function creates the generic RGB color space once and hangs onto it so it can
509 return it whenever this function is called.
510*/
613a24f7 511
20b69855
SC
512CGColorSpaceRef wxMacGetGenericRGBColorSpace()
513{
514 static CGColorSpaceRef genericRGBColorSpace = NULL;
515
516 if (genericRGBColorSpace == NULL)
517 {
518 CMProfileRef genericRGBProfile = wxMacOpenGenericProfile();
519
520 if (genericRGBProfile)
521 {
522 genericRGBColorSpace = CGColorSpaceCreateWithPlatformColorSpace(genericRGBProfile);
523 wxASSERT_MSG( genericRGBColorSpace != NULL, wxT("couldn't create the generic RGB color space") ) ;
524
525 // we opened the profile so it is up to us to close it
526 CMCloseProfile(genericRGBProfile);
527 }
528 }
529 return genericRGBColorSpace;
530}
613a24f7
SC
531
532void AddEllipticArcToPath(CGContextRef c, CGPoint center, float a, float b, float fromDegree , float toDegree )
533{
534 CGContextSaveGState(c);
535 CGContextTranslateCTM(c, center.x, center.y);
536 CGContextScaleCTM(c, a, b);
537 CGContextMoveToPoint(c, 1, 0);
538 CGContextAddArc(c, 0, 0, 1, DegToRad(fromDegree), DegToRad(toDegree), 0);
539 CGContextClosePath(c);
540 CGContextRestoreGState(c);
541}
542
543void AddRoundedRectToPath(CGContextRef c, CGRect rect, float ovalWidth,
544 float ovalHeight)
545{
546 float fw, fh;
547 if (ovalWidth == 0 || ovalHeight == 0)
548 {
549 CGContextAddRect(c, rect);
550 return;
551 }
552 CGContextSaveGState(c);
553 CGContextTranslateCTM(c, CGRectGetMinX(rect), CGRectGetMinY(rect));
554 CGContextScaleCTM(c, ovalWidth, ovalHeight);
555 fw = CGRectGetWidth(rect) / ovalWidth;
556 fh = CGRectGetHeight(rect) / ovalHeight;
557 CGContextMoveToPoint(c, fw, fh/2);
558 CGContextAddArcToPoint(c, fw, fh, fw/2, fh, 1);
559 CGContextAddArcToPoint(c, 0, fh, 0, fh/2, 1);
560 CGContextAddArcToPoint(c, 0, 0, fw/2, 0, 1);
561 CGContextAddArcToPoint(c, fw, 0, fw, fh/2, 1);
562 CGContextClosePath(c);
563 CGContextRestoreGState(c);
564}
565
566wxDC::wxDC()
567{
568 m_ok = FALSE;
569 m_colour = TRUE;
570 m_mm_to_pix_x = mm2pt;
571 m_mm_to_pix_y = mm2pt;
572 m_internalDeviceOriginX = 0;
573 m_internalDeviceOriginY = 0;
574 m_externalDeviceOriginX = 0;
575 m_externalDeviceOriginY = 0;
576 m_logicalScaleX = 1.0;
577 m_logicalScaleY = 1.0;
578 m_userScaleX = 1.0;
579 m_userScaleY = 1.0;
580 m_scaleX = 1.0;
581 m_scaleY = 1.0;
582 m_needComputeScaleX = FALSE;
583 m_needComputeScaleY = FALSE;
20b69855 584
613a24f7 585 m_ok = FALSE ;
a63b4755 586 m_macPort = 0 ;
613a24f7 587 m_macLocalOrigin.x = m_macLocalOrigin.y = 0 ;
20b69855 588
613a24f7
SC
589 m_pen = *wxBLACK_PEN;
590 m_font = *wxNORMAL_FONT;
591 m_brush = *wxWHITE_BRUSH;
613a24f7 592
20b69855 593 m_macATSUIStyle = NULL ;
613a24f7 594
20b69855 595 m_graphicContext = NULL ;
613a24f7
SC
596}
597
20b69855 598wxDC::~wxDC(void)
613a24f7 599{
613a24f7
SC
600 if( m_macATSUIStyle )
601 {
602 ::ATSUDisposeStyle((ATSUStyle)m_macATSUIStyle);
603 m_macATSUIStyle = NULL ;
604 }
20b69855
SC
605
606 delete m_graphicContext ;
613a24f7
SC
607}
608
609void wxDC::DoDrawBitmap( const wxBitmap &bmp, wxCoord x, wxCoord y, bool useMask )
610{
20b69855
SC
611 wxCHECK_RET( Ok(), wxT("invalid window dc") );
612 wxCHECK_RET( bmp.Ok(), wxT("invalid bitmap") );
613 wxCoord xx = XLOG2DEVMAC(x);
614 wxCoord yy = YLOG2DEVMAC(y);
615 wxCoord w = bmp.GetWidth();
616 wxCoord h = bmp.GetHeight();
617 wxCoord ww = XLOG2DEVREL(w);
618 wxCoord hh = YLOG2DEVREL(h);
619
620 CGContextRef cg = dynamic_cast<wxMacCGContext*>(m_graphicContext)->GetNativeContext() ;
621 CGImageRef image = (CGImageRef)( bmp.CGImageCreate() ) ;
622 HIRect r = CGRectMake( xx , yy , ww , hh ) ;
623 HIViewDrawCGImage( cg , &r , image ) ;
624 CGImageRelease( image ) ;
613a24f7
SC
625}
626
627void wxDC::DoDrawIcon( const wxIcon &icon, wxCoord x, wxCoord y )
628{
629 wxCHECK_RET(Ok(), wxT("Invalid dc wxDC::DoDrawIcon"));
630 wxCHECK_RET(icon.Ok(), wxT("Invalid icon wxDC::DoDrawIcon"));
20b69855
SC
631
632 wxCoord xx = XLOG2DEVMAC(x);
633 wxCoord yy = YLOG2DEVMAC(y);
634 wxCoord w = icon.GetWidth();
635 wxCoord h = icon.GetHeight();
636 wxCoord ww = XLOG2DEVREL(w);
637 wxCoord hh = YLOG2DEVREL(h);
638
639 CGContextRef cg = dynamic_cast<wxMacCGContext*>(m_graphicContext)->GetNativeContext() ;
640 CGRect r = CGRectMake( 00 , 00 , ww , hh ) ;
641 CGContextSaveGState(cg);
642 CGContextTranslateCTM(cg, xx , yy + hh );
643 CGContextScaleCTM(cg, 1, -1);
644 PlotIconRefInContext( cg , &r , kAlignNone , kTransformNone ,
645 NULL , kPlotIconRefNormalFlags , MAC_WXHICON( icon.GetHICON() ) ) ;
646 CGContextRestoreGState( cg ) ;
613a24f7
SC
647}
648
649void wxDC::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
650{
651 wxCHECK_RET(Ok(), wxT("wxDC::DoSetClippingRegion Invalid DC"));
652 wxCoord xx, yy, ww, hh;
653 xx = XLOG2DEVMAC(x);
654 yy = YLOG2DEVMAC(y);
655 ww = XLOG2DEVREL(width);
656 hh = YLOG2DEVREL(height);
b014adcc
SC
657
658 CGContextRef cgContext = dynamic_cast<wxMacCGContext*>(m_graphicContext)->GetNativeContext() ;
659 CGRect clipRect = CGRectMake( xx ,yy , ww, hh ) ;
660 CGContextClipToRect( cgContext , clipRect ) ;
661
20b69855
SC
662// SetRectRgn( (RgnHandle) m_macCurrentClipRgn , xx , yy , xx + ww , yy + hh ) ;
663// SectRgn( (RgnHandle) m_macCurrentClipRgn , (RgnHandle) m_macBoundaryClipRgn , (RgnHandle) m_macCurrentClipRgn ) ;
613a24f7
SC
664 if( m_clipping )
665 {
666 m_clipX1 = wxMax( m_clipX1 , xx );
667 m_clipY1 = wxMax( m_clipY1 , yy );
668 m_clipX2 = wxMin( m_clipX2, (xx + ww));
669 m_clipY2 = wxMin( m_clipY2, (yy + hh));
670 }
671 else
672 {
673 m_clipping = TRUE;
674 m_clipX1 = xx;
675 m_clipY1 = yy;
676 m_clipX2 = xx + ww;
677 m_clipY2 = yy + hh;
678 }
679 // TODO as soon as we don't reset the context for each operation anymore
680 // we have to update the context as well
681}
682
683void wxDC::DoSetClippingRegionAsRegion( const wxRegion &region )
684{
685 wxCHECK_RET( Ok(), wxT("invalid window dc") ) ;
686 if (region.Empty())
687 {
688 DestroyClippingRegion();
689 return;
690 }
691 wxCoord x, y, w, h;
692 region.GetBox( x, y, w, h );
693 wxCoord xx, yy, ww, hh;
694 xx = XLOG2DEVMAC(x);
695 yy = YLOG2DEVMAC(y);
696 ww = XLOG2DEVREL(w);
697 hh = YLOG2DEVREL(h);
698 // if we have a scaling that we cannot map onto native regions
699 // we must use the box
700 if ( ww != w || hh != h )
701 {
702 wxDC::DoSetClippingRegion( x, y, w, h );
703 }
704 else
705 {
20b69855 706 /*
613a24f7
SC
707 CopyRgn( (RgnHandle) region.GetWXHRGN() , (RgnHandle) m_macCurrentClipRgn ) ;
708 if ( xx != x || yy != y )
709 {
710 OffsetRgn( (RgnHandle) m_macCurrentClipRgn , xx - x , yy - y ) ;
711 }
712 SectRgn( (RgnHandle) m_macCurrentClipRgn , (RgnHandle) m_macBoundaryClipRgn , (RgnHandle) m_macCurrentClipRgn ) ;
20b69855 713 */
613a24f7
SC
714 if( m_clipping )
715 {
716 m_clipX1 = wxMax( m_clipX1 , xx );
717 m_clipY1 = wxMax( m_clipY1 , yy );
718 m_clipX2 = wxMin( m_clipX2, (xx + ww));
719 m_clipY2 = wxMin( m_clipY2, (yy + hh));
720 }
721 else
722 {
723 m_clipping = TRUE;
724 m_clipX1 = xx;
725 m_clipY1 = yy;
726 m_clipX2 = xx + ww;
727 m_clipY2 = yy + hh;
728 }
729 }
730}
731
732void wxDC::DestroyClippingRegion()
733{
20b69855 734// CopyRgn( (RgnHandle) m_macBoundaryClipRgn , (RgnHandle) m_macCurrentClipRgn ) ;
b014adcc
SC
735 CGContextRef cgContext = dynamic_cast<wxMacCGContext*>(m_graphicContext)->GetNativeContext() ;
736 CGContextRestoreGState( cgContext );
737 CGContextSaveGState( cgContext );
738 SetPen( m_pen ) ;
739 SetBrush( m_brush ) ;
613a24f7
SC
740 m_clipping = FALSE;
741}
742
743void wxDC::DoGetSizeMM( int* width, int* height ) const
744{
745 int w = 0;
746 int h = 0;
747 GetSize( &w, &h );
748 *width = long( double(w) / (m_scaleX*m_mm_to_pix_x) );
749 *height = long( double(h) / (m_scaleY*m_mm_to_pix_y) );
750}
751
752void wxDC::SetTextForeground( const wxColour &col )
753{
754 wxCHECK_RET(Ok(), wxT("Invalid DC"));
20b69855
SC
755 if ( col != m_textForegroundColour )
756 {
757 m_textForegroundColour = col;
758 MacInstallFont() ;
759 }
613a24f7
SC
760}
761
762void wxDC::SetTextBackground( const wxColour &col )
763{
764 wxCHECK_RET(Ok(), wxT("Invalid DC"));
765 m_textBackgroundColour = col;
613a24f7
SC
766}
767
768void wxDC::SetMapMode( int mode )
769{
770 switch (mode)
771 {
772 case wxMM_TWIPS:
773 SetLogicalScale( twips2mm*m_mm_to_pix_x, twips2mm*m_mm_to_pix_y );
774 break;
775 case wxMM_POINTS:
776 SetLogicalScale( pt2mm*m_mm_to_pix_x, pt2mm*m_mm_to_pix_y );
777 break;
778 case wxMM_METRIC:
779 SetLogicalScale( m_mm_to_pix_x, m_mm_to_pix_y );
780 break;
781 case wxMM_LOMETRIC:
782 SetLogicalScale( m_mm_to_pix_x/10.0, m_mm_to_pix_y/10.0 );
783 break;
784 default:
785 case wxMM_TEXT:
786 SetLogicalScale( 1.0, 1.0 );
787 break;
788 }
789 if (mode != wxMM_TEXT)
790 {
791 m_needComputeScaleX = TRUE;
792 m_needComputeScaleY = TRUE;
793 }
794}
795
796void wxDC::SetUserScale( double x, double y )
797{
798 // allow negative ? -> no
799 m_userScaleX = x;
800 m_userScaleY = y;
801 ComputeScaleAndOrigin();
802}
803
804void wxDC::SetLogicalScale( double x, double y )
805{
806 // allow negative ?
807 m_logicalScaleX = x;
808 m_logicalScaleY = y;
809 ComputeScaleAndOrigin();
810}
811
812void wxDC::SetLogicalOrigin( wxCoord x, wxCoord y )
813{
814 m_logicalOriginX = x * m_signX; // is this still correct ?
815 m_logicalOriginY = y * m_signY;
816 ComputeScaleAndOrigin();
817}
818
819void wxDC::SetDeviceOrigin( wxCoord x, wxCoord y )
820{
821 m_externalDeviceOriginX = x;
822 m_externalDeviceOriginY = y;
823 ComputeScaleAndOrigin();
824}
825
826void wxDC::SetAxisOrientation( bool xLeftRight, bool yBottomUp )
827{
828 m_signX = (xLeftRight ? 1 : -1);
829 m_signY = (yBottomUp ? -1 : 1);
830 ComputeScaleAndOrigin();
831}
832
833wxSize wxDC::GetPPI() const
834{
835 return wxSize(72, 72);
836}
837
838int wxDC::GetDepth() const
839{
20b69855 840 return 32 ;
613a24f7
SC
841}
842
843void wxDC::ComputeScaleAndOrigin()
844{
845 // CMB: copy scale to see if it changes
846 double origScaleX = m_scaleX;
847 double origScaleY = m_scaleY;
848 m_scaleX = m_logicalScaleX * m_userScaleX;
849 m_scaleY = m_logicalScaleY * m_userScaleY;
850 m_deviceOriginX = m_internalDeviceOriginX + m_externalDeviceOriginX;
851 m_deviceOriginY = m_internalDeviceOriginY + m_externalDeviceOriginY;
852 // CMB: if scale has changed call SetPen to recalulate the line width
853 if (m_scaleX != origScaleX || m_scaleY != origScaleY)
854 {
855 // this is a bit artificial, but we need to force wxDC to think
856 // the pen has changed
857 wxPen pen(GetPen());
858 m_pen = wxNullPen;
859 SetPen(pen);
860 }
861}
862
863void wxDC::SetPalette( const wxPalette& palette )
864{
865}
866
867void wxDC::SetBackgroundMode( int mode )
868{
869 m_backgroundMode = mode ;
870}
871
872void wxDC::SetFont( const wxFont &font )
873{
874 m_font = font;
20b69855 875 MacInstallFont() ;
613a24f7
SC
876}
877
878void wxDC::SetPen( const wxPen &pen )
879{
880 if ( m_pen == pen )
881 return ;
882 m_pen = pen;
20b69855
SC
883 if ( m_graphicContext )
884 {
885 m_graphicContext->SetPen( m_pen ) ;
886 }
613a24f7
SC
887}
888
889void wxDC::SetBrush( const wxBrush &brush )
890{
891 if (m_brush == brush)
892 return;
893 m_brush = brush;
20b69855
SC
894 if ( m_graphicContext )
895 {
896 m_graphicContext->SetBrush( m_brush ) ;
897 }
613a24f7
SC
898}
899
900void wxDC::SetBackground( const wxBrush &brush )
901{
902 if (m_backgroundBrush == brush)
903 return;
904 m_backgroundBrush = brush;
905 if (!m_backgroundBrush.Ok())
906 return;
613a24f7
SC
907}
908
909void wxDC::SetLogicalFunction( int function )
910{
911 if (m_logicalFunction == function)
912 return;
913 m_logicalFunction = function ;
613a24f7
SC
914}
915
916extern bool wxDoFloodFill(wxDC *dc, wxCoord x, wxCoord y,
917 const wxColour & col, int style);
918
919bool wxDC::DoFloodFill(wxCoord x, wxCoord y,
920 const wxColour& col, int style)
921{
922 return wxDoFloodFill(this, x, y, col, style);
923}
924
925bool wxDC::DoGetPixel( wxCoord x, wxCoord y, wxColour *col ) const
926{
927 wxCHECK_MSG( Ok(), false, wxT("wxDC::DoGetPixel Invalid DC") );
880f5369
SC
928 wxCHECK_MSG( Ok(), false, wxT("wxDC::DoGetPixel Invalid DC") );
929 wxMacPortSaver helper((CGrafPtr)m_macPort) ;
930 RGBColor colour;
931 GetCPixel(
932 XLOG2DEVMAC(x) + m_macLocalOriginInPort.x - m_macLocalOrigin.x,
933 YLOG2DEVMAC(y) + m_macLocalOriginInPort.y - m_macLocalOrigin.y, &colour );
934 // Convert from Mac colour to wx
935 col->Set( colour.red >> 8,
936 colour.green >> 8,
937 colour.blue >> 8);
938 return true ;
613a24f7
SC
939}
940
941void wxDC::DoDrawLine( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2 )
942{
943 wxCHECK_RET(Ok(), wxT("Invalid DC"));
944
08c8555e
SC
945 if ( m_logicalFunction != wxCOPY )
946 return ;
947
613a24f7
SC
948 wxCoord xx1 = XLOG2DEVMAC(x1) ;
949 wxCoord yy1 = YLOG2DEVMAC(y1) ;
950 wxCoord xx2 = XLOG2DEVMAC(x2) ;
951 wxCoord yy2 = YLOG2DEVMAC(y2) ;
952
20b69855
SC
953 wxGraphicPath* path = m_graphicContext->CreatePath() ;
954 path->MoveToPoint( xx1 , yy1 ) ;
955 path->AddLineToPoint( xx2 , yy2 ) ;
956 path->CloseSubpath() ;
957 m_graphicContext->StrokePath( path ) ;
958 delete path ;
613a24f7
SC
959
960 CalcBoundingBox(x1, y1);
961 CalcBoundingBox(x2, y2);
962}
963
964void wxDC::DoCrossHair( wxCoord x, wxCoord y )
965{
966 wxCHECK_RET( Ok(), wxT("wxDC::DoCrossHair Invalid window dc") );
967
08c8555e
SC
968 if ( m_logicalFunction != wxCOPY )
969 return ;
613a24f7
SC
970
971 int w = 0;
972 int h = 0;
973 GetSize( &w, &h );
974 wxCoord xx = XLOG2DEVMAC(x);
975 wxCoord yy = YLOG2DEVMAC(y);
976
20b69855
SC
977 wxGraphicPath* path = m_graphicContext->CreatePath() ;
978 path->MoveToPoint( XLOG2DEVMAC(0), yy ) ;
979 path->AddLineToPoint( XLOG2DEVMAC(w), yy ) ;
980 path->CloseSubpath() ;
981 path->MoveToPoint( xx, YLOG2DEVMAC(0) ) ;
982 path->AddLineToPoint( xx, YLOG2DEVMAC(h) ) ;
983 path->CloseSubpath() ;
984 m_graphicContext->StrokePath( path ) ;
985 delete path ;
613a24f7
SC
986
987 CalcBoundingBox(x, y);
988 CalcBoundingBox(x+w, y+h);
989}
990
991/*
992* To draw arcs properly the angles need to be converted from the WX style:
993* Angles start on the +ve X axis and go anti-clockwise (As you would draw on
994* a normal axis on paper).
995* TO
996* the Mac style:
997* Angles start on the +ve y axis and go clockwise.
998*/
999
1000static double wxConvertWXangleToMACangle(double angle)
1001{
1002 double newAngle = 90 - angle ;
1003 if ( newAngle < 0 )
1004 newAngle += 360 ;
1005 return newAngle ;
1006}
1007
1008void wxDC::DoDrawArc( wxCoord x1, wxCoord y1,
1009 wxCoord x2, wxCoord y2,
1010 wxCoord xc, wxCoord yc )
1011{
1012 wxCHECK_RET(Ok(), wxT("wxDC::DoDrawArc Invalid DC"));
08c8555e
SC
1013
1014 if ( m_logicalFunction != wxCOPY )
1015 return ;
1016
613a24f7
SC
1017 wxCoord xx1 = XLOG2DEVMAC(x1);
1018 wxCoord yy1 = YLOG2DEVMAC(y1);
1019 wxCoord xx2 = XLOG2DEVMAC(x2);
1020 wxCoord yy2 = YLOG2DEVMAC(y2);
1021 wxCoord xxc = XLOG2DEVMAC(xc);
1022 wxCoord yyc = YLOG2DEVMAC(yc);
1023 double dx = xx1 - xxc;
1024 double dy = yy1 - yyc;
1025 double radius = sqrt((double)(dx*dx+dy*dy));
1026 wxCoord rad = (wxCoord)radius;
1027 double radius1, radius2;
1028 if (xx1 == xx2 && yy1 == yy2)
1029 {
1030 radius1 = 0.0;
1031 radius2 = 360.0;
1032 }
1033 else if (radius == 0.0)
1034 {
1035 radius1 = radius2 = 0.0;
1036 }
1037 else
1038 {
1039 radius1 = (xx1 - xxc == 0) ?
1040 (yy1 - yyc < 0) ? 90.0 : -90.0 :
1041 -atan2(double(yy1-yyc), double(xx1-xxc)) * RAD2DEG;
1042 radius2 = (xx2 - xxc == 0) ?
1043 (yy2 - yyc < 0) ? 90.0 : -90.0 :
1044 -atan2(double(yy2-yyc), double(xx2-xxc)) * RAD2DEG;
1045 }
1046 wxCoord alpha2 = wxCoord(radius2 - radius1);
8e475be4 1047 wxCoord alpha1 = wxCoord(wxConvertWXangleToMACangle(radius1));
613a24f7
SC
1048 if( (xx1 > xx2) || (yy1 > yy2) ) {
1049 alpha2 *= -1;
1050 }
20b69855
SC
1051 wxMacCGContext* mctx = ((wxMacCGContext*) m_graphicContext) ;
1052 CGContextRef ctx = mctx->GetNativeContext() ;
a63b4755 1053 AddEllipticArcToPath( ctx , CGPointMake( xxc , yyc ) , rad , rad , alpha1 , alpha2 ) ;
20b69855 1054 CGContextDrawPath( ctx , mctx->GetDrawingMode() ) ;
613a24f7
SC
1055}
1056
1057void wxDC::DoDrawEllipticArc( wxCoord x, wxCoord y, wxCoord w, wxCoord h,
1058 double sa, double ea )
1059{
1060 wxCHECK_RET(Ok(), wxT("wxDC::DoDrawEllepticArc Invalid DC"));
20b69855 1061
08c8555e
SC
1062 if ( m_logicalFunction != wxCOPY )
1063 return ;
1064
613a24f7
SC
1065 double angle = sa - ea; // Order important Mac in opposite direction to wx
1066 // we have to make sure that the filling is always counter-clockwise
1067 if ( angle > 0 )
1068 angle -= 360 ;
1069 wxCoord xx = XLOG2DEVMAC(x);
1070 wxCoord yy = YLOG2DEVMAC(y);
1071 wxCoord ww = m_signX * XLOG2DEVREL(w);
1072 wxCoord hh = m_signY * YLOG2DEVREL(h);
1073 // handle -ve width and/or height
1074 if (ww < 0) { ww = -ww; xx = xx - ww; }
1075 if (hh < 0) { hh = -hh; yy = yy - hh; }
1076 sa = wxConvertWXangleToMACangle(sa);
20b69855
SC
1077 wxMacCGContext* mctx = ((wxMacCGContext*) m_graphicContext) ;
1078 CGContextRef ctx = mctx->GetNativeContext() ;
1079 AddEllipticArcToPath( ctx , CGPointMake( xx + ww / 2 , yy + hh / 2 ) , ww / 2 , hh / 2 , sa , angle) ;
1080 CGContextDrawPath( ctx , mctx->GetDrawingMode() ) ;
613a24f7
SC
1081}
1082
1083void wxDC::DoDrawPoint( wxCoord x, wxCoord y )
1084{
1085 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1086 DoDrawLine( x , y , x + 1 , y + 1 ) ;
1087}
1088
1089void wxDC::DoDrawLines(int n, wxPoint points[],
1090 wxCoord xoffset, wxCoord yoffset)
1091{
1092 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1093
08c8555e
SC
1094 if ( m_logicalFunction != wxCOPY )
1095 return ;
1096
613a24f7
SC
1097 wxCoord x1, x2 , y1 , y2 ;
1098 x1 = XLOG2DEVMAC(points[0].x + xoffset);
1099 y1 = YLOG2DEVMAC(points[0].y + yoffset);
20b69855
SC
1100 wxGraphicPath* path = m_graphicContext->CreatePath() ;
1101 path->MoveToPoint( x1 , y1 ) ;
613a24f7
SC
1102 for (int i = 1; i < n; i++)
1103 {
1104 x2 = XLOG2DEVMAC(points[i].x + xoffset);
1105 y2 = YLOG2DEVMAC(points[i].y + yoffset);
1106
20b69855 1107 path->AddLineToPoint( x2 , y2 ) ;
613a24f7 1108 }
20b69855
SC
1109 m_graphicContext->StrokePath( path ) ;
1110 delete path ;
613a24f7
SC
1111}
1112
1113void wxDC::DoDrawPolygon(int n, wxPoint points[],
1114 wxCoord xoffset, wxCoord yoffset,
1115 int fillStyle )
1116{
1117 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1118 wxCoord x1, x2 , y1 , y2 ;
1119 if ( n== 0 || (m_brush.GetStyle() == wxTRANSPARENT && m_pen.GetStyle() == wxTRANSPARENT ) )
1120 return ;
1121
08c8555e
SC
1122 if ( m_logicalFunction != wxCOPY )
1123 return ;
1124
613a24f7
SC
1125 x2 = x1 = XLOG2DEVMAC(points[0].x + xoffset);
1126 y2 = y1 = YLOG2DEVMAC(points[0].y + yoffset);
1127
20b69855
SC
1128 wxGraphicPath* path = m_graphicContext->CreatePath() ;
1129 path->MoveToPoint( x1 , y1 ) ;
613a24f7
SC
1130 for (int i = 1; i < n; i++)
1131 {
1132 x2 = XLOG2DEVMAC(points[i].x + xoffset);
1133 y2 = YLOG2DEVMAC(points[i].y + yoffset);
1134
20b69855 1135 path->AddLineToPoint( x2 , y2 ) ;
613a24f7
SC
1136 }
1137 if ( x1 != x2 || y1 != y2 )
1138 {
20b69855 1139 path->AddLineToPoint( x1,y1 ) ;
613a24f7 1140 }
20b69855
SC
1141 path->CloseSubpath() ;
1142 m_graphicContext->DrawPath( path , fillStyle ) ;
1143 delete path ;
613a24f7
SC
1144}
1145
1146void wxDC::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
1147{
1148 wxCHECK_RET(Ok(), wxT("Invalid DC"));
08c8555e
SC
1149
1150 if ( m_logicalFunction != wxCOPY )
1151 return ;
1152
613a24f7
SC
1153 wxCoord xx = XLOG2DEVMAC(x);
1154 wxCoord yy = YLOG2DEVMAC(y);
1155 wxCoord ww = m_signX * XLOG2DEVREL(width);
1156 wxCoord hh = m_signY * YLOG2DEVREL(height);
1157 // CMB: draw nothing if transformed w or h is 0
1158 if (ww == 0 || hh == 0)
1159 return;
1160 // CMB: handle -ve width and/or height
1161 if (ww < 0)
1162 {
1163 ww = -ww;
1164 xx = xx - ww;
1165 }
1166 if (hh < 0)
1167 {
1168 hh = -hh;
1169 yy = yy - hh;
1170 }
20b69855
SC
1171 wxGraphicPath* path = m_graphicContext->CreatePath() ;
1172 path->AddRectangle(xx ,yy , ww , hh ) ;
20b69855
SC
1173 m_graphicContext->DrawPath( path ) ;
1174 delete path ;
613a24f7
SC
1175}
1176
1177void wxDC::DoDrawRoundedRectangle(wxCoord x, wxCoord y,
1178 wxCoord width, wxCoord height,
1179 double radius)
1180{
1181 wxCHECK_RET(Ok(), wxT("Invalid DC"));
08c8555e
SC
1182
1183 if ( m_logicalFunction != wxCOPY )
1184 return ;
1185
1186
613a24f7
SC
1187 if (radius < 0.0)
1188 radius = - radius * ((width < height) ? width : height);
1189 wxCoord xx = XLOG2DEVMAC(x);
1190 wxCoord yy = YLOG2DEVMAC(y);
1191 wxCoord ww = m_signX * XLOG2DEVREL(width);
1192 wxCoord hh = m_signY * YLOG2DEVREL(height);
1193 // CMB: draw nothing if transformed w or h is 0
1194 if (ww == 0 || hh == 0)
1195 return;
1196 // CMB: handle -ve width and/or height
1197 if (ww < 0)
1198 {
1199 ww = -ww;
1200 xx = xx - ww;
1201 }
1202 if (hh < 0)
1203 {
1204 hh = -hh;
1205 yy = yy - hh;
1206 }
20b69855
SC
1207 wxMacCGContext* mctx = ((wxMacCGContext*) m_graphicContext) ;
1208 CGContextRef ctx = mctx->GetNativeContext() ;
1209 AddRoundedRectToPath( ctx , CGRectMake( xx , yy , ww , hh ) , 16 ,16 ) ;
1210 CGContextDrawPath( ctx , mctx->GetDrawingMode() ) ;
613a24f7
SC
1211}
1212
1213void wxDC::DoDrawEllipse(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
1214{
1215 wxCHECK_RET(Ok(), wxT("Invalid DC"));
08c8555e
SC
1216
1217 if ( m_logicalFunction != wxCOPY )
1218 return ;
1219
613a24f7
SC
1220 wxCoord xx = XLOG2DEVMAC(x);
1221 wxCoord yy = YLOG2DEVMAC(y);
1222 wxCoord ww = m_signX * XLOG2DEVREL(width);
1223 wxCoord hh = m_signY * YLOG2DEVREL(height);
1224 // CMB: draw nothing if transformed w or h is 0
1225 if (ww == 0 || hh == 0)
1226 return;
1227 // CMB: handle -ve width and/or height
1228 if (ww < 0)
1229 {
1230 ww = -ww;
1231 xx = xx - ww;
1232 }
1233 if (hh < 0)
1234 {
1235 hh = -hh;
1236 yy = yy - hh;
1237 }
20b69855
SC
1238
1239 wxMacCGContext* mctx = ((wxMacCGContext*) m_graphicContext) ;
1240 CGContextRef ctx = mctx->GetNativeContext() ;
613a24f7 1241 if ( width == height )
20b69855
SC
1242 {
1243 CGContextBeginPath(ctx);
1244 CGContextAddArc(ctx ,
1245 xx + ww / 2,
1246 yy + hh / 2,
1247 ww / 2,
1248 0,
1249 2 * M_PI,
1250 0 ) ;
1251 CGContextClosePath(ctx);
613a24f7 1252
0d5eaa50 1253 CGContextDrawPath( ctx , mctx->GetDrawingMode() ) ;
20b69855
SC
1254 }
1255 else
1256 {
1257 AddEllipticArcToPath( ctx , CGPointMake( xx + ww / 2 , yy + hh / 2 ) , ww / 2 , hh / 2 , 0 , 360) ;
1258 CGContextDrawPath( ctx , mctx->GetDrawingMode() ) ;
1259 }
613a24f7
SC
1260}
1261
1262bool wxDC::CanDrawBitmap(void) const
1263{
1264 return true ;
1265}
1266
1267bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
1268 wxDC *source, wxCoord xsrc, wxCoord ysrc, int logical_func , bool useMask,
1269 wxCoord xsrcMask, wxCoord ysrcMask )
1270{
1271 wxCHECK_MSG(Ok(), false, wxT("wxDC::DoBlit Illegal dc"));
1272 wxCHECK_MSG(source->Ok(), false, wxT("wxDC::DoBlit Illegal source DC"));
1273 if ( logical_func == wxNO_OP )
1274 return TRUE ;
1275 if (xsrcMask == -1 && ysrcMask == -1)
1276 {
1277 xsrcMask = xsrc; ysrcMask = ysrc;
1278 }
20b69855 1279
68654a82
SC
1280 wxCoord yysrc = source->YLOG2DEVMAC(ysrc) ;
1281 wxCoord xxsrc = source->XLOG2DEVMAC(xsrc) ;
1282 wxCoord wwsrc = source->XLOG2DEVREL(width ) ;
1283 wxCoord hhsrc = source->YLOG2DEVREL(height) ;
1284
1285 wxCoord yydest = YLOG2DEVMAC(ydest) ;
1286 wxCoord xxdest = XLOG2DEVMAC(xdest) ;
1287 wxCoord wwdest = XLOG2DEVREL(width ) ;
1288 wxCoord hhdest = YLOG2DEVREL(height) ;
1289
20b69855 1290 wxMemoryDC* memdc = dynamic_cast<wxMemoryDC*>(source) ;
a8f234d2 1291 if ( memdc && logical_func == wxCOPY )
613a24f7 1292 {
20b69855
SC
1293 wxBitmap blit = memdc->GetSelectedObject() ;
1294 wxASSERT_MSG( blit.Ok() , wxT("Invalid bitmap for blitting") ) ;
1295
20b69855
SC
1296 wxCoord bmpwidth = blit.GetWidth();
1297 wxCoord bmpheight = blit.GetHeight();
1298
68654a82
SC
1299 if ( xxsrc != 0 || yysrc != 0 || bmpwidth != wwsrc || bmpheight != hhsrc )
1300 {
1301 wwsrc = wxMin( wwsrc , bmpwidth - xxsrc ) ;
1302 hhsrc = wxMin( hhsrc , bmpheight - yysrc ) ;
1303 if ( wwsrc > 0 && hhsrc > 0 )
1304 {
1305 if ( xxsrc >= 0 && yysrc >= 0 )
1306 {
1307 wxRect subrect( xxsrc, yysrc, wwsrc , hhsrc ) ;
1308 blit = blit.GetSubBitmap( subrect ) ;
1309 }
1310 else
1311 {
1312 // in this case we'd probably have to adjust the different coordinates, but
1313 // we have to find out proper contract first
1314 blit = wxNullBitmap ;
1315 }
1316 }
1317 else
1318 {
1319 blit = wxNullBitmap ;
1320 }
1321 }
1322 if ( blit.Ok() )
613a24f7 1323 {
68654a82
SC
1324 CGContextRef cg = dynamic_cast<wxMacCGContext*>(m_graphicContext)->GetNativeContext() ;
1325 CGImageRef image = (CGImageRef)( blit.CGImageCreate() ) ;
1326 HIRect r = CGRectMake( xxdest , yydest , wwdest , hhdest ) ;
1327 HIViewDrawCGImage( cg , &r , image ) ;
1328 CGImageRelease( image ) ;
613a24f7 1329 }
20b69855
SC
1330
1331 }
1332 else
1333 {
68654a82
SC
1334 /*
1335 CGContextRef cg = dynamic_cast<wxMacCGContext*>(source->GetGraphicContext())->GetNativeContext() ;
1336 void *data = CGBitmapContextGetData( cg ) ;
1337 */
a8f234d2 1338 return FALSE ; // wxFAIL_MSG( wxT("Blitting is only supported from bitmap contexts") ) ;
613a24f7 1339 }
613a24f7
SC
1340 return TRUE;
1341}
1342
613a24f7
SC
1343void wxDC::DoDrawRotatedText(const wxString& str, wxCoord x, wxCoord y,
1344 double angle)
1345{
1346 wxCHECK_RET( Ok(), wxT("wxDC::DoDrawRotatedText Invalid window dc") );
1347
1348 if ( str.Length() == 0 )
1349 return ;
1350
08c8555e
SC
1351 if ( m_logicalFunction != wxCOPY )
1352 return ;
1353
20b69855
SC
1354 wxCHECK_RET( m_macATSUIStyle != NULL , wxT("No valid font set") ) ;
1355
613a24f7
SC
1356 OSStatus status = noErr ;
1357 ATSUTextLayout atsuLayout ;
1358 UniCharCount chars = str.Length() ;
1359 UniChar* ubuf = NULL ;
1360#if SIZEOF_WCHAR_T == 4
1361 wxMBConvUTF16BE converter ;
1362#if wxUSE_UNICODE
1363 size_t unicharlen = converter.WC2MB( NULL , str.wc_str() , 0 ) ;
1364 ubuf = (UniChar*) malloc( unicharlen + 2 ) ;
1365 converter.WC2MB( (char*) ubuf , str.wc_str(), unicharlen + 2 ) ;
1366#else
1367 const wxWCharBuffer wchar = str.wc_str( wxConvLocal ) ;
1368 size_t unicharlen = converter.WC2MB( NULL , wchar.data() , 0 ) ;
1369 ubuf = (UniChar*) malloc( unicharlen + 2 ) ;
1370 converter.WC2MB( (char*) ubuf , wchar.data() , unicharlen + 2 ) ;
1371#endif
1372 chars = unicharlen / 2 ;
1373#else
1374#if wxUSE_UNICODE
1375 ubuf = (UniChar*) str.wc_str() ;
1376#else
1377 wxWCharBuffer wchar = str.wc_str( wxConvLocal ) ;
1378 chars = wxWcslen( wchar.data() ) ;
1379 ubuf = (UniChar*) wchar.data() ;
1380#endif
1381#endif
1382
1383 int drawX = XLOG2DEVMAC(x) ;
1384 int drawY = YLOG2DEVMAC(y) ;
1385
613a24f7
SC
1386 status = ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr) ubuf , 0 , chars , chars , 1 ,
1387 &chars , (ATSUStyle*) &m_macATSUIStyle , &atsuLayout ) ;
1388
1389 wxASSERT_MSG( status == noErr , wxT("couldn't create the layout of the rotated text") );
1390 int iAngle = int( angle );
1391
1392
1393
613a24f7
SC
1394 if ( abs(iAngle) > 0 )
1395 {
1396 Fixed atsuAngle = IntToFixed( iAngle ) ;
1397 ATSUAttributeTag atsuTags[] =
1398 {
1399 kATSULineRotationTag ,
1400 } ;
1401 ByteCount atsuSizes[sizeof(atsuTags)/sizeof(ATSUAttributeTag)] =
1402 {
1403 sizeof( Fixed ) ,
1404 } ;
1405 ATSUAttributeValuePtr atsuValues[sizeof(atsuTags)/sizeof(ATSUAttributeTag)] =
1406 {
1407 &atsuAngle ,
1408 } ;
1409 status = ::ATSUSetLayoutControls(atsuLayout , sizeof(atsuTags)/sizeof(ATSUAttributeTag),
1410 atsuTags, atsuSizes, atsuValues ) ;
1411 }
1412 {
20b69855 1413 CGContextRef cgContext = dynamic_cast<wxMacCGContext*>(m_graphicContext)->GetNativeContext() ;
613a24f7
SC
1414 ATSUAttributeTag atsuTags[] =
1415 {
1416 kATSUCGContextTag ,
1417 } ;
1418 ByteCount atsuSizes[sizeof(atsuTags)/sizeof(ATSUAttributeTag)] =
1419 {
1420 sizeof( CGContextRef ) ,
1421 } ;
1422 ATSUAttributeValuePtr atsuValues[sizeof(atsuTags)/sizeof(ATSUAttributeTag)] =
1423 {
1424 &cgContext ,
1425 } ;
1426 status = ::ATSUSetLayoutControls(atsuLayout , sizeof(atsuTags)/sizeof(ATSUAttributeTag),
1427 atsuTags, atsuSizes, atsuValues ) ;
1428 }
1429
1430 ATSUTextMeasurement textBefore ;
1431 ATSUTextMeasurement textAfter ;
1432 ATSUTextMeasurement ascent ;
1433 ATSUTextMeasurement descent ;
1434
1435 status = ::ATSUGetUnjustifiedBounds( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd,
1436 &textBefore , &textAfter, &ascent , &descent );
1437 wxASSERT_MSG( status == noErr , wxT("couldn't measure the rotated text") );
1438
1439 Rect rect ;
1440
1441 if ( m_backgroundMode == wxSOLID )
1442 {
20b69855
SC
1443 wxGraphicPath* path = m_graphicContext->CreatePath() ;
1444 path->MoveToPoint(
613a24f7
SC
1445 drawX ,
1446 drawY ) ;
20b69855 1447 path->AddLineToPoint(
6cac01a6
RN
1448 (int) (drawX + sin(angle/RAD2DEG) * FixedToInt(ascent + descent)) ,
1449 (int) (drawY + cos(angle/RAD2DEG) * FixedToInt(ascent + descent)) ) ;
20b69855 1450 path->AddLineToPoint(
6cac01a6
RN
1451 (int) (drawX + sin(angle/RAD2DEG) * FixedToInt(ascent + descent ) + cos(angle/RAD2DEG) * FixedToInt(textAfter)) ,
1452 (int) (drawY + cos(angle/RAD2DEG) * FixedToInt(ascent + descent) - sin(angle/RAD2DEG) * FixedToInt(textAfter)) ) ;
20b69855 1453 path->AddLineToPoint(
6cac01a6
RN
1454 (int) (drawX + cos(angle/RAD2DEG) * FixedToInt(textAfter)) ,
1455 (int) (drawY - sin(angle/RAD2DEG) * FixedToInt(textAfter)) ) ;
613a24f7 1456
20b69855
SC
1457 m_graphicContext->FillPath( path , m_textBackgroundColour ) ;
1458 delete path ;
613a24f7
SC
1459 }
1460
1461 drawX += (int)(sin(angle/RAD2DEG) * FixedToInt(ascent));
1462 drawY += (int)(cos(angle/RAD2DEG) * FixedToInt(ascent));
20b69855 1463
613a24f7
SC
1464 status = ::ATSUMeasureTextImage( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd,
1465 IntToFixed(drawX) , IntToFixed(drawY) , &rect );
1466 wxASSERT_MSG( status == noErr , wxT("couldn't measure the rotated text") );
1467
20b69855
SC
1468 CGContextSaveGState(dynamic_cast<wxMacCGContext*>(m_graphicContext)->GetNativeContext());
1469 CGContextTranslateCTM(dynamic_cast<wxMacCGContext*>(m_graphicContext)->GetNativeContext(), drawX, drawY);
1470 CGContextScaleCTM(dynamic_cast<wxMacCGContext*>(m_graphicContext)->GetNativeContext(), 1, -1);
613a24f7
SC
1471 status = ::ATSUDrawText( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd,
1472 IntToFixed(0) , IntToFixed(0) );
1473 wxASSERT_MSG( status == noErr , wxT("couldn't draw the rotated text") );
20b69855 1474 CGContextRestoreGState( dynamic_cast<wxMacCGContext*>(m_graphicContext)->GetNativeContext() ) ;
613a24f7
SC
1475
1476 CalcBoundingBox(XDEV2LOG(rect.left), YDEV2LOG(rect.top) );
1477 CalcBoundingBox(XDEV2LOG(rect.right), YDEV2LOG(rect.bottom) );
1478
1479 ::ATSUDisposeTextLayout(atsuLayout);
1480#if SIZEOF_WCHAR_T == 4
1481 free( ubuf ) ;
1482#endif
613a24f7
SC
1483}
1484
1485void wxDC::DoDrawText(const wxString& strtext, wxCoord x, wxCoord y)
1486{
1487 wxCHECK_RET(Ok(), wxT("wxDC::DoDrawText Invalid DC"));
1488 DoDrawRotatedText( strtext , x , y , 0.0 ) ;
1489}
1490
1491bool wxDC::CanGetTextExtent() const
1492{
1493 wxCHECK_MSG(Ok(), false, wxT("Invalid DC"));
1494 return true ;
1495}
1496
1497void wxDC::DoGetTextExtent( const wxString &str, wxCoord *width, wxCoord *height,
1498 wxCoord *descent, wxCoord *externalLeading ,
1499 wxFont *theFont ) const
1500{
1501 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1502 wxFont formerFont = m_font ;
1503 if ( theFont )
1504 {
1505 // work around the constness
1506 *((wxFont*)(&m_font)) = *theFont ;
20b69855 1507 MacInstallFont() ;
613a24f7
SC
1508 }
1509
613a24f7
SC
1510 if ( str.Length() == 0 )
1511 return ;
1512
20b69855
SC
1513 wxCHECK_RET( m_macATSUIStyle != NULL , wxT("No valid font set") ) ;
1514
613a24f7
SC
1515 OSStatus status = noErr ;
1516 ATSUTextLayout atsuLayout ;
1517 UniCharCount chars = str.Length() ;
1518 UniChar* ubuf = NULL ;
1519#if SIZEOF_WCHAR_T == 4
1520 wxMBConvUTF16BE converter ;
1521#if wxUSE_UNICODE
1522 size_t unicharlen = converter.WC2MB( NULL , str.wc_str() , 0 ) ;
1523 ubuf = (UniChar*) malloc( unicharlen + 2 ) ;
1524 converter.WC2MB( (char*) ubuf , str.wc_str(), unicharlen + 2 ) ;
1525#else
1526 const wxWCharBuffer wchar = str.wc_str( wxConvLocal ) ;
1527 size_t unicharlen = converter.WC2MB( NULL , wchar.data() , 0 ) ;
1528 ubuf = (UniChar*) malloc( unicharlen + 2 ) ;
1529 converter.WC2MB( (char*) ubuf , wchar.data() , unicharlen + 2 ) ;
1530#endif
1531 chars = unicharlen / 2 ;
1532#else
1533#if wxUSE_UNICODE
1534 ubuf = (UniChar*) str.wc_str() ;
1535#else
1536 wxWCharBuffer wchar = str.wc_str( wxConvLocal ) ;
1537 chars = wxWcslen( wchar.data() ) ;
1538 ubuf = (UniChar*) wchar.data() ;
1539#endif
1540#endif
1541
613a24f7
SC
1542
1543 status = ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr) ubuf , 0 , chars , chars , 1 ,
1544 &chars , (ATSUStyle*) &m_macATSUIStyle , &atsuLayout ) ;
1545
1546 wxASSERT_MSG( status == noErr , wxT("couldn't create the layout of the text") );
1547
1548 ATSUTextMeasurement textBefore ;
1549 ATSUTextMeasurement textAfter ;
1550 ATSUTextMeasurement textAscent ;
1551 ATSUTextMeasurement textDescent ;
1552
1553 status = ::ATSUGetUnjustifiedBounds( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd,
1554 &textBefore , &textAfter, &textAscent , &textDescent );
1555
1556 if ( height )
1557 *height = YDEV2LOGREL( FixedToInt(textAscent + textDescent) ) ;
1558 if ( descent )
1559 *descent =YDEV2LOGREL( FixedToInt(textDescent) );
1560 if ( externalLeading )
1561 *externalLeading = 0 ;
1562 if ( width )
1563 *width = XDEV2LOGREL( FixedToInt(textAfter - textBefore) ) ;
1564
1565 ::ATSUDisposeTextLayout(atsuLayout);
1566#if SIZEOF_WCHAR_T == 4
1567 free( ubuf ) ;
1568#endif
1569 if ( theFont )
1570 {
1571 // work around the constness
1572 *((wxFont*)(&m_font)) = formerFont ;
20b69855 1573 MacInstallFont() ;
613a24f7
SC
1574 }
1575}
1576
1577
1578bool wxDC::DoGetPartialTextExtents(const wxString& text, wxArrayInt& widths) const
1579{
1580 wxCHECK_MSG(Ok(), false, wxT("Invalid DC"));
1581
1582 widths.Empty();
1583 widths.Add(0, text.Length());
1584
1585 if (text.Length() == 0)
1586 return false;
1587
764e6694
KO
1588 ATSUTextLayout atsuLayout ;
1589 UniCharCount chars = text.Length() ;
1590 UniChar* ubuf = NULL ;
1591#if SIZEOF_WCHAR_T == 4
1592 wxMBConvUTF16BE converter ;
1593#if wxUSE_UNICODE
1594 size_t unicharlen = converter.WC2MB( NULL , text.wc_str() , 0 ) ;
1595 ubuf = (UniChar*) malloc( unicharlen + 2 ) ;
1596 converter.WC2MB( (char*) ubuf , text.wc_str(), unicharlen + 2 ) ;
1597#else
1598 const wxWCharBuffer wchar = text.wc_str( wxConvLocal ) ;
1599 size_t unicharlen = converter.WC2MB( NULL , wchar.data() , 0 ) ;
1600 ubuf = (UniChar*) malloc( unicharlen + 2 ) ;
1601 converter.WC2MB( (char*) ubuf , wchar.data() , unicharlen + 2 ) ;
1602#endif
1603 chars = unicharlen / 2 ;
1604#else
1605#if wxUSE_UNICODE
1606 ubuf = (UniChar*) text.wc_str() ;
1607#else
1608 wxWCharBuffer wchar = text.wc_str( wxConvLocal ) ;
1609 chars = wxWcslen( wchar.data() ) ;
1610 ubuf = (UniChar*) wchar.data() ;
1611#endif
1612#endif
1613
1614 OSStatus status;
1615 status = ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr) ubuf , 0 , chars , chars , 1 ,
1616 &chars , (ATSUStyle*) &m_macATSUIStyle , &atsuLayout ) ;
1617
1618 for ( int pos = 0; pos < chars; pos ++ ) {
1619 unsigned long actualNumberOfBounds = 0;
1620 ATSTrapezoid glyphBounds;
1621
1622 // We get a single bound, since the text should only require one. If it requires more, there is an issue
1623 OSStatus result;
1624 result = ATSUGetGlyphBounds( atsuLayout, 0, 0, kATSUFromTextBeginning, pos + 1, kATSUseDeviceOrigins, 1, &glyphBounds, &actualNumberOfBounds );
1625 if (result != noErr || actualNumberOfBounds != 1 )
1626 {
1627 return false;
1628 }
1629
1630 widths[pos] = XDEV2LOGREL(FixedToInt( glyphBounds.upperRight.x - glyphBounds.upperLeft.x ));
1631 //unsigned char uch = s[i];
1632
1633 }
1634 ::ATSUDisposeTextLayout(atsuLayout);
1635 return true;
613a24f7
SC
1636}
1637
613a24f7
SC
1638wxCoord wxDC::GetCharWidth(void) const
1639{
1640 wxCoord width ;
1641 DoGetTextExtent(wxT("g") , &width , NULL , NULL , NULL , NULL ) ;
1642 return width ;
1643}
1644
1645wxCoord wxDC::GetCharHeight(void) const
1646{
1647 wxCoord height ;
1648 DoGetTextExtent(wxT("g") , NULL , &height , NULL , NULL , NULL ) ;
1649 return height ;
1650}
1651
1652void wxDC::Clear(void)
1653{
1654 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1655
1656 if ( m_backgroundBrush.Ok() && m_backgroundBrush.GetStyle() != wxTRANSPARENT)
1657 {
b014adcc 1658 HIRect rect = CGRectMake( -10000 , -10000 , 20000 , 20000 ) ;
a63b4755 1659 CGContextRef cg = dynamic_cast<wxMacCGContext*>(m_graphicContext)->GetNativeContext() ;
613a24f7
SC
1660 switch( m_backgroundBrush.MacGetBrushKind() )
1661 {
1662 case kwxMacBrushTheme :
1663 {
a63b4755
SC
1664#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
1665 if ( HIThemeSetFill != 0 )
1666 {
1667 HIThemeSetFill( m_backgroundBrush.MacGetTheme() , cg ) ;
1668 CGContextFillRect(cg, rect);
1669
1670 }
1671 else
1672#endif
1673 {
1674 RGBColor color;
1675 GetThemeBrushAsColor( m_backgroundBrush.MacGetTheme() , 32, true, &color );
1676 CGContextSetRGBFillColor( cg , (float) color.red / 65536,
1677 (float) color.green / 65536, (float) color.blue / 65536, 1 );
1678 CGContextFillRect( cg, rect );
1679 }
1680 // reset to normal value
1681 RGBColor col = MAC_WXCOLORREF( GetBrush().GetColour().GetPixel() ) ;
1682 CGContextSetRGBFillColor( cg , col.red / 65536.0 , col.green / 65536.0 , col.blue / 65536.0 , 1.0 ) ;
613a24f7
SC
1683 }
1684 break ;
1685 case kwxMacBrushThemeBackground :
1686 {
a63b4755 1687 wxFAIL_MSG( wxT("There shouldn't be theme backgrounds under Quartz") ) ;
b014adcc 1688#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3
1688bb38 1689 if ( UMAGetSystemVersion() >= 0x1030 )
b014adcc
SC
1690 {
1691 HIThemeBackgroundDrawInfo drawInfo ;
1692 drawInfo.version = 0 ;
1693 drawInfo.state = kThemeStateActive ;
1694 drawInfo.kind = m_backgroundBrush.MacGetThemeBackground(NULL) ;
1695 if ( drawInfo.kind == kThemeBackgroundMetal )
a63b4755 1696 HIThemeDrawBackground( &rect , &drawInfo, cg ,
b014adcc 1697 kHIThemeOrientationNormal) ;
a63b4755 1698 HIThemeApplyBackground( &rect , &drawInfo, cg ,
b014adcc
SC
1699 kHIThemeOrientationNormal) ;
1700 }
a63b4755 1701 else
b014adcc 1702#endif
a63b4755
SC
1703 {
1704 }
613a24f7
SC
1705 }
1706 break ;
1707 case kwxMacBrushColour :
1708 {
1709 RGBColor col = MAC_WXCOLORREF( m_backgroundBrush.GetColour().GetPixel()) ;
a63b4755
SC
1710 CGContextSetRGBFillColor( cg , col.red / 65536.0 , col.green / 65536.0 , col.blue / 65536.0 , 1.0 ) ;
1711 CGContextFillRect(cg, rect);
613a24f7
SC
1712
1713 // reset to normal value
1714 col = MAC_WXCOLORREF( GetBrush().GetColour().GetPixel() ) ;
a63b4755 1715 CGContextSetRGBFillColor( cg , col.red / 65536.0 , col.green / 65536.0 , col.blue / 65536.0 , 1.0 ) ;
613a24f7
SC
1716 }
1717 break ;
1718 }
1719 }
1720}
1721
1722void wxDC::MacInstallFont() const
1723{
1724 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1725
20b69855 1726 if( m_macATSUIStyle )
613a24f7 1727 {
20b69855
SC
1728 ::ATSUDisposeStyle((ATSUStyle)m_macATSUIStyle);
1729 m_macATSUIStyle = NULL ;
613a24f7 1730 }
20b69855 1731
68654a82 1732 if ( m_font.Ok() )
613a24f7 1733 {
68654a82
SC
1734 OSStatus status = noErr ;
1735 status = ATSUCreateAndCopyStyle( (ATSUStyle) m_font.MacGetATSUStyle() , (ATSUStyle*) &m_macATSUIStyle ) ;
1736 wxASSERT_MSG( status == noErr , wxT("couldn't set create ATSU style") ) ;
20b69855 1737
68654a82
SC
1738 Fixed atsuSize = IntToFixed( int(m_scaleY * m_font.MacGetFontSize()) ) ;
1739 RGBColor atsuColor = MAC_WXCOLORREF( m_textForegroundColour.GetPixel() ) ;
1740 ATSUAttributeTag atsuTags[] =
1741 {
1742 kATSUSizeTag ,
1743 kATSUColorTag ,
1744 } ;
1745 ByteCount atsuSizes[sizeof(atsuTags)/sizeof(ATSUAttributeTag)] =
1746 {
1747 sizeof( Fixed ) ,
1748 sizeof( RGBColor ) ,
1749 } ;
1750 // Boolean kTrue = true ;
1751 // Boolean kFalse = false ;
613a24f7 1752
68654a82
SC
1753 // ATSUVerticalCharacterType kHorizontal = kATSUStronglyHorizontal;
1754 ATSUAttributeValuePtr atsuValues[sizeof(atsuTags)/sizeof(ATSUAttributeTag)] =
1755 {
1756 &atsuSize ,
1757 &atsuColor ,
1758 } ;
1759 status = ::ATSUSetAttributes((ATSUStyle)m_macATSUIStyle, sizeof(atsuTags)/sizeof(ATSUAttributeTag) ,
1760 atsuTags, atsuSizes, atsuValues);
1761
1762 wxASSERT_MSG( status == noErr , wxT("couldn't Modify ATSU style") ) ;
1763 }
613a24f7
SC
1764}
1765
1766// ---------------------------------------------------------------------------
1767// coordinates transformations
1768// ---------------------------------------------------------------------------
1769
1770wxCoord wxDCBase::DeviceToLogicalX(wxCoord x) const
1771{
1772 return ((wxDC *)this)->XDEV2LOG(x);
1773}
1774
1775wxCoord wxDCBase::DeviceToLogicalY(wxCoord y) const
1776{
1777 return ((wxDC *)this)->YDEV2LOG(y);
1778}
1779
1780wxCoord wxDCBase::DeviceToLogicalXRel(wxCoord x) const
1781{
1782 return ((wxDC *)this)->XDEV2LOGREL(x);
1783}
1784
1785wxCoord wxDCBase::DeviceToLogicalYRel(wxCoord y) const
1786{
1787 return ((wxDC *)this)->YDEV2LOGREL(y);
1788}
1789
1790wxCoord wxDCBase::LogicalToDeviceX(wxCoord x) const
1791{
1792 return ((wxDC *)this)->XLOG2DEV(x);
1793}
1794
1795wxCoord wxDCBase::LogicalToDeviceY(wxCoord y) const
1796{
1797 return ((wxDC *)this)->YLOG2DEV(y);
1798}
1799
1800wxCoord wxDCBase::LogicalToDeviceXRel(wxCoord x) const
1801{
1802 return ((wxDC *)this)->XLOG2DEVREL(x);
1803}
1804
1805wxCoord wxDCBase::LogicalToDeviceYRel(wxCoord y) const
1806{
1807 return ((wxDC *)this)->YLOG2DEVREL(y);
1808}
20b69855
SC
1809
1810#endif // wxMAC_USE_CORE_GRAPHICS
1811