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