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