]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/graphics.cpp
add alt popup window style allowing to use keyboard and comboboxes in the popup windo...
[wxWidgets.git] / src / mac / carbon / graphics.cpp
CommitLineData
50581042
SC
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/mac/carbon/dccg.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#include "wx/wxprec.h"
13
f43426c1 14#if wxUSE_GRAPHICS_CONTEXT && wxMAC_USE_CORE_GRAPHICS
50581042 15
83b96a06
PC
16#include "wx/graphics.h"
17
50581042 18#ifndef WX_PRECOMP
cc5de8fe 19 #include "wx/dcclient.h"
50581042 20 #include "wx/log.h"
50581042 21 #include "wx/region.h"
50581042
SC
22#endif
23
24#include "wx/mac/uma.h"
25
50581042
SC
26#ifdef __MSL__
27 #if __MSL__ >= 0x6000
28 #include "math.h"
29 // in case our functions were defined outside std, we make it known all the same
30 namespace std { }
31 using namespace std;
32 #endif
33#endif
34
35#include "wx/mac/private.h"
36
37#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4
38typedef float CGFloat;
39#endif
40
41//
42// Graphics Path
43//
44
45class WXDLLEXPORT wxMacCoreGraphicsPath : public wxGraphicsPath
46{
47 DECLARE_NO_COPY_CLASS(wxMacCoreGraphicsPath)
48public :
49 wxMacCoreGraphicsPath();
50 ~wxMacCoreGraphicsPath();
51
52 // begins a new subpath at (x,y)
53 virtual void MoveToPoint( wxDouble x, wxDouble y );
54
55 // adds a straight line from the current point to (x,y)
56 virtual void AddLineToPoint( wxDouble x, wxDouble y );
57
58 // adds a cubic Bezier curve from the current point, using two control points and an end point
59 virtual void AddCurveToPoint( wxDouble cx1, wxDouble cy1, wxDouble cx2, wxDouble cy2, wxDouble x, wxDouble y );
60
61 // closes the current sub-path
62 virtual void CloseSubpath();
63
64 // gets the last point of the current path, (0,0) if not yet set
65 virtual void GetCurrentPoint( wxDouble& x, wxDouble&y);
66
67 // adds an arc of a circle centering at (x,y) with radius (r) from startAngle to endAngle
68 virtual void AddArc( wxDouble x, wxDouble y, wxDouble r, wxDouble startAngle, wxDouble endAngle, bool clockwise );
69
70 //
71 // These are convenience functions which - if not available natively will be assembled
72 // using the primitives from above
73 //
74
75 // adds a quadratic Bezier curve from the current point, using a control point and an end point
76 virtual void AddQuadCurveToPoint( wxDouble cx, wxDouble cy, wxDouble x, wxDouble y );
77
78 // appends a rectangle as a new closed subpath
79 virtual void AddRectangle( wxDouble x, wxDouble y, wxDouble w, wxDouble h );
80
81 // appends an ellipsis as a new closed subpath fitting the passed rectangle
82 virtual void AddCircle( wxDouble x, wxDouble y, wxDouble r );
83
84 // draws a an arc to two tangents connecting (current) to (x1,y1) and (x1,y1) to (x2,y2), also a straight line from (current) to (x1,y1)
85 virtual void AddArcToPoint( wxDouble x1, wxDouble y1 , wxDouble x2, wxDouble y2, wxDouble r );
86
87 CGPathRef GetPath() const;
88private :
89 CGMutablePathRef m_path;
90};
91
92wxMacCoreGraphicsPath::wxMacCoreGraphicsPath()
93{
94 m_path = CGPathCreateMutable();
95}
96
97wxMacCoreGraphicsPath::~wxMacCoreGraphicsPath()
98{
99 CGPathRelease( m_path );
100}
101
102// opens (starts) a new subpath
103void wxMacCoreGraphicsPath::MoveToPoint( wxDouble x1 , wxDouble y1 )
104{
105 CGPathMoveToPoint( m_path , NULL , x1 , y1 );
106}
107
108void wxMacCoreGraphicsPath::AddLineToPoint( wxDouble x1 , wxDouble y1 )
109{
110 CGPathAddLineToPoint( m_path , NULL , x1 , y1 );
111}
112
113void wxMacCoreGraphicsPath::AddCurveToPoint( wxDouble cx1, wxDouble cy1, wxDouble cx2, wxDouble cy2, wxDouble x, wxDouble y )
114{
115 CGPathAddCurveToPoint( m_path , NULL , cx1 , cy1 , cx2, cy2, x , y );
116}
117
118void wxMacCoreGraphicsPath::AddQuadCurveToPoint( wxDouble cx1, wxDouble cy1, wxDouble x, wxDouble y )
119{
120 CGPathAddQuadCurveToPoint( m_path , NULL , cx1 , cy1 , x , y );
121}
122
123void wxMacCoreGraphicsPath::AddRectangle( wxDouble x, wxDouble y, wxDouble w, wxDouble h )
124{
125 CGRect cgRect = { { x , y } , { w , h } };
126 CGPathAddRect( m_path , NULL , cgRect );
127}
128
129void wxMacCoreGraphicsPath::AddCircle( wxDouble x, wxDouble y , wxDouble r )
130{
131 CGPathAddArc( m_path , NULL , x , y , r , 0.0 , 2 * M_PI , true );
132}
133
134// adds an arc of a circle centering at (x,y) with radius (r) from startAngle to endAngle
135void wxMacCoreGraphicsPath::AddArc( wxDouble x, wxDouble y, wxDouble r, wxDouble startAngle, wxDouble endAngle, bool clockwise )
136{
a798c64c
SC
137 // inverse direction as we the 'normal' state is a y axis pointing down, ie mirrored to the standard core graphics setup
138 CGPathAddArc( m_path, NULL , x, y, r, startAngle, endAngle, !clockwise);
50581042
SC
139}
140
141void wxMacCoreGraphicsPath::AddArcToPoint( wxDouble x1, wxDouble y1 , wxDouble x2, wxDouble y2, wxDouble r )
142{
143 CGPathAddArcToPoint( m_path, NULL , x1, y1, x2, y2, r);
144}
145
146// closes the current subpath
147void wxMacCoreGraphicsPath::CloseSubpath()
148{
149 CGPathCloseSubpath( m_path );
150}
151
152CGPathRef wxMacCoreGraphicsPath::GetPath() const
153{
154 return m_path;
155}
156
157// gets the last point of the current path, (0,0) if not yet set
158void wxMacCoreGraphicsPath::GetCurrentPoint( wxDouble& x, wxDouble&y)
159{
160 CGPoint p = CGPathGetCurrentPoint( m_path );
161 x = p.x;
162 y = p.y;
163}
164
165//
166// Graphics Context
167//
168
169class WXDLLEXPORT wxMacCoreGraphicsContext : public wxGraphicsContext
170{
171 DECLARE_NO_COPY_CLASS(wxMacCoreGraphicsContext)
172
173public:
50581042
SC
174 wxMacCoreGraphicsContext( CGContextRef cgcontext );
175
1056ddcf
SC
176 wxMacCoreGraphicsContext( WindowRef window );
177
50581042
SC
178 wxMacCoreGraphicsContext();
179
180 ~wxMacCoreGraphicsContext();
181
1056ddcf 182 void Init();
50581042
SC
183
184 // creates a path instance that corresponds to the type of graphics context, ie GDIPlus, cairo, CoreGraphics ...
185 virtual wxGraphicsPath * CreatePath();
186
187 // push the current state of the context, ie the transformation matrix on a stack
188 virtual void PushState();
189
190 // pops a stored state from the stack
191 virtual void PopState();
192
193 // clips drawings to the region
194 virtual void Clip( const wxRegion &region );
195
1056ddcf
SC
196 // clips drawings to the rect
197 virtual void Clip( wxDouble x, wxDouble y, wxDouble w, wxDouble h );
198
199 // resets the clipping to original extent
200 virtual void ResetClip();
201
202 virtual void * GetNativeContext();
203
50581042
SC
204 //
205 // transformation
206 //
207
208 // translate
209 virtual void Translate( wxDouble dx , wxDouble dy );
210
211 // scale
212 virtual void Scale( wxDouble xScale , wxDouble yScale );
213
214 // rotate (radians)
215 virtual void Rotate( wxDouble angle );
216
217 //
218 // setting the paint
219 //
220
221 // sets the pan
222 virtual void SetPen( const wxPen &pen );
223
224 // sets the brush for filling
225 virtual void SetBrush( const wxBrush &brush );
226
227 // sets the brush to a linear gradient, starting at (x1,y1) with color c1 to (x2,y2) with color c2
228 virtual void SetLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2,
229 const wxColour&c1, const wxColour&c2);
230
231 // sets the brush to a radial gradient originating at (xo,yc) with color oColor and ends on a circle around (xc,yc)
232 // with radius r and color cColor
233 virtual void SetRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius,
234 const wxColour &oColor, const wxColour &cColor);
235
236 // sets the font
237 virtual void SetFont( const wxFont &font );
238
239 // sets the text color
240 virtual void SetTextColor( const wxColour &col );
241
242 // strokes along a path with the current pen
243 virtual void StrokePath( const wxGraphicsPath *path );
244
245 // fills a path with the current brush
246 virtual void FillPath( const wxGraphicsPath *path, int fillStyle = wxWINDING_RULE );
247
248 // draws a path by first filling and then stroking
249 virtual void DrawPath( const wxGraphicsPath *path, int fillStyle = wxWINDING_RULE );
250
251 //
252 // text
253 //
254
255 virtual void DrawText( const wxString &str, wxDouble x, wxDouble y );
256
257 virtual void DrawText( const wxString &str, wxDouble x, wxDouble y, wxDouble angle );
258
259 virtual void GetTextExtent( const wxString &text, wxDouble *width, wxDouble *height,
260 wxDouble *descent, wxDouble *externalLeading ) const;
261
262 virtual void GetPartialTextExtents(const wxString& text, wxArrayDouble& widths) const;
263
264 //
265 // image support
266 //
267
268 virtual void DrawBitmap( const wxBitmap &bmp, wxDouble x, wxDouble y, wxDouble w, wxDouble h );
269
270 virtual void DrawIcon( const wxIcon &icon, wxDouble x, wxDouble y, wxDouble w, wxDouble h );
271
50581042
SC
272 void SetNativeContext( CGContextRef cg );
273 CGPathDrawingMode GetDrawingMode() const { return m_mode; }
274
275private:
276 CGContextRef m_cgContext;
1056ddcf
SC
277 WindowRef m_windowRef;
278 bool m_releaseContext;
50581042
SC
279 CGPathDrawingMode m_mode;
280 ATSUStyle m_macATSUIStyle;
281 wxPen m_pen;
282 wxBrush m_brush;
1056ddcf 283 wxFont m_font;
50581042
SC
284 wxColor m_textForegroundColor;
285};
286
287//-----------------------------------------------------------------------------
288// constants
289//-----------------------------------------------------------------------------
290
291#if !defined( __DARWIN__ ) || defined(__MWERKS__)
292#ifndef M_PI
293const double M_PI = 3.14159265358979;
294#endif
295#endif
296
83b96a06 297static const double RAD2DEG = 180.0 / M_PI;
50581042
SC
298
299//-----------------------------------------------------------------------------
300// device context implementation
301//
302// more and more of the dc functionality should be implemented by calling
303// the appropricate wxMacCoreGraphicsContext, but we will have to do that step by step
304// also coordinate conversions should be moved to native matrix ops
305//-----------------------------------------------------------------------------
306
307// we always stock two context states, one at entry, to be able to preserve the
308// state we were called with, the other one after changing to HI Graphics orientation
309// (this one is used for getting back clippings etc)
310
311//-----------------------------------------------------------------------------
312// wxGraphicsPath implementation
313//-----------------------------------------------------------------------------
314
315//-----------------------------------------------------------------------------
316// wxGraphicsContext implementation
317//-----------------------------------------------------------------------------
318
1056ddcf 319void wxMacCoreGraphicsContext::Init()
50581042 320{
50581042
SC
321 m_cgContext = NULL;
322 m_mode = kCGPathFill;
323 m_macATSUIStyle = NULL;
1056ddcf 324 m_releaseContext = false;
50581042
SC
325}
326
327wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( CGContextRef cgcontext )
328{
1056ddcf
SC
329 Init();
330 m_cgContext = cgcontext;
50581042
SC
331 CGContextSaveGState( m_cgContext );
332 CGContextSaveGState( m_cgContext );
333}
334
1056ddcf
SC
335wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( WindowRef window )
336{
337 Init();
338 m_windowRef = window;
339 OSStatus status = QDBeginCGContext( GetWindowPort( window ) , &m_cgContext );
340 wxASSERT_MSG( status == noErr , wxT("Cannot nest wxDCs on the same window") );
341 Rect bounds;
342 GetWindowBounds( window, kWindowContentRgn, &bounds );
343 CGContextSaveGState( m_cgContext );
344 CGContextTranslateCTM( m_cgContext , 0 , bounds.bottom - bounds.top );
345 CGContextScaleCTM( m_cgContext , 1 , -1 );
346 CGContextSaveGState( m_cgContext );
347 m_releaseContext = true;
348}
349
50581042
SC
350wxMacCoreGraphicsContext::wxMacCoreGraphicsContext()
351{
1056ddcf 352 Init();
50581042
SC
353}
354
355wxMacCoreGraphicsContext::~wxMacCoreGraphicsContext()
356{
357 if ( m_cgContext )
358 {
359 CGContextSynchronize( m_cgContext );
360 CGContextRestoreGState( m_cgContext );
361 CGContextRestoreGState( m_cgContext );
362 }
363
1056ddcf
SC
364 if ( m_releaseContext )
365 QDEndCGContext( GetWindowPort( m_windowRef ) , &m_cgContext);
50581042
SC
366}
367
368void wxMacCoreGraphicsContext::Clip( const wxRegion &region )
369{
1056ddcf
SC
370 HIShapeRef shape = HIShapeCreateWithQDRgn( (RgnHandle) region.GetWXHRGN() );
371 HIShapeReplacePathInCGContext( shape, m_cgContext );
372 CGContextClip( m_cgContext );
373 CFRelease( shape );
374}
375
376// clips drawings to the rect
377void wxMacCoreGraphicsContext::Clip( wxDouble x, wxDouble y, wxDouble w, wxDouble h )
378{
379 HIRect r = CGRectMake( x , y , w , h );
380 CGContextClipToRect( m_cgContext, r );
381}
382
383 // resets the clipping to original extent
384void wxMacCoreGraphicsContext::ResetClip()
385{
386 CGContextRestoreGState( m_cgContext );
387 CGContextSaveGState( m_cgContext );
50581042
SC
388}
389
390void wxMacCoreGraphicsContext::StrokePath( const wxGraphicsPath *p )
391{
392 const wxMacCoreGraphicsPath* path = dynamic_cast< const wxMacCoreGraphicsPath*>( p );
1056ddcf
SC
393 int width = m_pen.GetWidth();
394 if ( width == 0 )
395 width = 1 ;
396 if ( m_pen.GetStyle() == wxTRANSPARENT )
397 width = 0 ;
398
399 bool offset = ( width % 2 ) == 1 ;
400
401 if ( offset )
402 CGContextTranslateCTM( m_cgContext, 0.5, 0.5 );
403
50581042
SC
404 CGContextAddPath( m_cgContext , path->GetPath() );
405 CGContextStrokePath( m_cgContext );
1056ddcf
SC
406
407 if ( offset )
408 CGContextTranslateCTM( m_cgContext, -0.5, -0.5 );
50581042
SC
409}
410
411void wxMacCoreGraphicsContext::DrawPath( const wxGraphicsPath *p , int fillStyle )
412{
413 const wxMacCoreGraphicsPath* path = dynamic_cast< const wxMacCoreGraphicsPath*>( p );
414 CGPathDrawingMode mode = m_mode;
415
416 if ( fillStyle == wxODDEVEN_RULE )
417 {
418 if ( mode == kCGPathFill )
419 mode = kCGPathEOFill;
420 else if ( mode == kCGPathFillStroke )
421 mode = kCGPathEOFillStroke;
422 }
423
1056ddcf
SC
424 int width = m_pen.GetWidth();
425 if ( width == 0 )
426 width = 1 ;
427 if ( m_pen.GetStyle() == wxTRANSPARENT )
428 width = 0 ;
429
430 bool offset = ( width % 2 ) == 1 ;
431
432 if ( offset )
433 CGContextTranslateCTM( m_cgContext, 0.5, 0.5 );
434
50581042
SC
435 CGContextAddPath( m_cgContext , path->GetPath() );
436 CGContextDrawPath( m_cgContext , mode );
1056ddcf
SC
437
438 if ( offset )
439 CGContextTranslateCTM( m_cgContext, -0.5, -0.5 );
50581042
SC
440}
441
442void wxMacCoreGraphicsContext::FillPath( const wxGraphicsPath *p , int fillStyle )
443{
444 const wxMacCoreGraphicsPath* path = dynamic_cast< const wxMacCoreGraphicsPath*>( p );
445
446 CGContextAddPath( m_cgContext , path->GetPath() );
447 if ( fillStyle == wxODDEVEN_RULE )
448 CGContextEOFillPath( m_cgContext );
449 else
450 CGContextFillPath( m_cgContext );
451}
452
453wxGraphicsPath* wxMacCoreGraphicsContext::CreatePath()
454{
50581042
SC
455 return new wxMacCoreGraphicsPath();
456}
457
50581042
SC
458void wxMacCoreGraphicsContext::SetNativeContext( CGContextRef cg )
459{
460 // we allow either setting or clearing but not replacing
461 wxASSERT( m_cgContext == NULL || cg == NULL );
462
463 if ( cg )
464 CGContextSaveGState( cg );
465 m_cgContext = cg;
466}
467
468void wxMacCoreGraphicsContext::Translate( wxDouble dx , wxDouble dy )
469{
470 CGContextTranslateCTM( m_cgContext, dx, dy );
471}
472
473void wxMacCoreGraphicsContext::Scale( wxDouble xScale , wxDouble yScale )
474{
475 CGContextScaleCTM( m_cgContext , xScale , yScale );
476}
477
478void wxMacCoreGraphicsContext::Rotate( wxDouble angle )
479{
480 CGContextRotateCTM( m_cgContext , angle );
481}
482
483void wxMacCoreGraphicsContext::DrawBitmap( const wxBitmap &bmp, wxDouble x, wxDouble y, wxDouble w, wxDouble h )
484{
485 CGImageRef image = (CGImageRef)( bmp.CGImageCreate() );
486 HIRect r = CGRectMake( x , y , w , h );
487 HIViewDrawCGImage( m_cgContext , &r , image );
488 CGImageRelease( image );
489}
490
491void wxMacCoreGraphicsContext::DrawIcon( const wxIcon &icon, wxDouble x, wxDouble y, wxDouble w, wxDouble h )
492{
493 CGRect r = CGRectMake( 00 , 00 , w , h );
494 CGContextSaveGState( m_cgContext );
495 CGContextTranslateCTM( m_cgContext, x , y + h );
496 CGContextScaleCTM( m_cgContext, 1, -1 );
497 PlotIconRefInContext( m_cgContext , &r , kAlignNone , kTransformNone ,
498 NULL , kPlotIconRefNormalFlags , MAC_WXHICON( icon.GetHICON() ) );
499 CGContextRestoreGState( m_cgContext );
500}
501
502void wxMacCoreGraphicsContext::PushState()
503{
504 CGContextSaveGState( m_cgContext );
505}
506
507void wxMacCoreGraphicsContext::PopState()
508{
509 CGContextRestoreGState( m_cgContext );
510}
511
512void wxMacCoreGraphicsContext::SetTextColor( const wxColour &col )
513{
514 m_textForegroundColor = col;
1056ddcf
SC
515 // to recreate the native font after color change
516 SetFont( m_font );
50581042
SC
517}
518
519#pragma mark -
520#pragma mark wxMacCoreGraphicsPattern, ImagePattern, HatchPattern classes
521
522// CGPattern wrapper class: always allocate on heap, never call destructor
523
524class wxMacCoreGraphicsPattern
525{
526public :
527 wxMacCoreGraphicsPattern() {}
528
529 // is guaranteed to be called only with a non-Null CGContextRef
530 virtual void Render( CGContextRef ctxRef ) = 0;
531
532 operator CGPatternRef() const { return m_patternRef; }
533
534protected :
535 virtual ~wxMacCoreGraphicsPattern()
536 {
537 // as this is called only when the m_patternRef is been released;
538 // don't release it again
539 }
540
541 static void _Render( void *info, CGContextRef ctxRef )
542 {
543 wxMacCoreGraphicsPattern* self = (wxMacCoreGraphicsPattern*) info;
544 if ( self && ctxRef )
545 self->Render( ctxRef );
546 }
547
548 static void _Dispose( void *info )
549 {
550 wxMacCoreGraphicsPattern* self = (wxMacCoreGraphicsPattern*) info;
551 delete self;
552 }
553
554 CGPatternRef m_patternRef;
555
556 static const CGPatternCallbacks ms_Callbacks;
557};
558
559const CGPatternCallbacks wxMacCoreGraphicsPattern::ms_Callbacks = { 0, &wxMacCoreGraphicsPattern::_Render, &wxMacCoreGraphicsPattern::_Dispose };
560
561class ImagePattern : public wxMacCoreGraphicsPattern
562{
563public :
83b96a06 564 ImagePattern( const wxBitmap* bmp , const CGAffineTransform& transform )
50581042
SC
565 {
566 wxASSERT( bmp && bmp->Ok() );
567
568 Init( (CGImageRef) bmp->CGImageCreate() , transform );
569 }
570
571 // ImagePattern takes ownership of CGImageRef passed in
83b96a06 572 ImagePattern( CGImageRef image , const CGAffineTransform& transform )
50581042
SC
573 {
574 if ( image )
575 CFRetain( image );
576
577 Init( image , transform );
578 }
579
580 virtual void Render( CGContextRef ctxRef )
581 {
582 if (m_image != NULL)
583 HIViewDrawCGImage( ctxRef, &m_imageBounds, m_image );
584 }
585
586protected :
83b96a06 587 void Init( CGImageRef image, const CGAffineTransform& transform )
50581042
SC
588 {
589 m_image = image;
590 if ( m_image )
591 {
592 m_imageBounds = CGRectMake( 0.0, 0.0, (CGFloat)CGImageGetWidth( m_image ), (CGFloat)CGImageGetHeight( m_image ) );
593 m_patternRef = CGPatternCreate(
594 this , m_imageBounds, transform ,
595 m_imageBounds.size.width, m_imageBounds.size.height,
596 kCGPatternTilingNoDistortion, true , &wxMacCoreGraphicsPattern::ms_Callbacks );
597 }
598 }
599
600 virtual ~ImagePattern()
601 {
602 if ( m_image )
603 CGImageRelease( m_image );
604 }
605
606 CGImageRef m_image;
607 CGRect m_imageBounds;
608};
609
610class HatchPattern : public wxMacCoreGraphicsPattern
611{
612public :
83b96a06 613 HatchPattern( int hatchstyle, const CGAffineTransform& transform )
50581042
SC
614 {
615 m_hatch = hatchstyle;
616 m_imageBounds = CGRectMake( 0.0, 0.0, 8.0 , 8.0 );
617 m_patternRef = CGPatternCreate(
618 this , m_imageBounds, transform ,
619 m_imageBounds.size.width, m_imageBounds.size.height,
620 kCGPatternTilingNoDistortion, false , &wxMacCoreGraphicsPattern::ms_Callbacks );
621 }
622
623 void StrokeLineSegments( CGContextRef ctxRef , const CGPoint pts[] , size_t count )
624 {
625#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
626 if ( UMAGetSystemVersion() >= 0x1040 )
627 {
628 CGContextStrokeLineSegments( ctxRef , pts , count );
629 }
630 else
631#endif
632 {
633 CGContextBeginPath( ctxRef );
634 for (size_t i = 0; i < count; i += 2)
635 {
636 CGContextMoveToPoint(ctxRef, pts[i].x, pts[i].y);
637 CGContextAddLineToPoint(ctxRef, pts[i+1].x, pts[i+1].y);
638 }
639 CGContextStrokePath(ctxRef);
640 }
641 }
642
643 virtual void Render( CGContextRef ctxRef )
644 {
645 switch ( m_hatch )
646 {
647 case wxBDIAGONAL_HATCH :
648 {
649 CGPoint pts[] =
650 {
651 { 8.0 , 0.0 } , { 0.0 , 8.0 }
652 };
653 StrokeLineSegments( ctxRef , pts , 2 );
654 }
655 break;
656
657 case wxCROSSDIAG_HATCH :
658 {
659 CGPoint pts[] =
660 {
661 { 0.0 , 0.0 } , { 8.0 , 8.0 } ,
662 { 8.0 , 0.0 } , { 0.0 , 8.0 }
663 };
664 StrokeLineSegments( ctxRef , pts , 4 );
665 }
666 break;
667
668 case wxFDIAGONAL_HATCH :
669 {
670 CGPoint pts[] =
671 {
672 { 0.0 , 0.0 } , { 8.0 , 8.0 }
673 };
674 StrokeLineSegments( ctxRef , pts , 2 );
675 }
676 break;
677
678 case wxCROSS_HATCH :
679 {
680 CGPoint pts[] =
681 {
682 { 0.0 , 4.0 } , { 8.0 , 4.0 } ,
683 { 4.0 , 0.0 } , { 4.0 , 8.0 } ,
684 };
685 StrokeLineSegments( ctxRef , pts , 4 );
686 }
687 break;
688
689 case wxHORIZONTAL_HATCH :
690 {
691 CGPoint pts[] =
692 {
693 { 0.0 , 4.0 } , { 8.0 , 4.0 } ,
694 };
695 StrokeLineSegments( ctxRef , pts , 2 );
696 }
697 break;
698
699 case wxVERTICAL_HATCH :
700 {
701 CGPoint pts[] =
702 {
703 { 4.0 , 0.0 } , { 4.0 , 8.0 } ,
704 };
705 StrokeLineSegments( ctxRef , pts , 2 );
706 }
707 break;
708
709 default:
710 break;
711 }
712 }
713
714protected :
715 virtual ~HatchPattern() {}
716
717 CGRect m_imageBounds;
718 int m_hatch;
719};
720
721#pragma mark -
722
723void wxMacCoreGraphicsContext::SetPen( const wxPen &pen )
724{
725 m_pen = pen;
726 if ( m_cgContext == NULL )
727 return;
728
729 bool fill = m_brush.GetStyle() != wxTRANSPARENT;
730 bool stroke = pen.GetStyle() != wxTRANSPARENT;
731
732#if 0
733 // we can benchmark performance; should go into a setting eventually
734 CGContextSetShouldAntialias( m_cgContext , false );
735#endif
736
83b96a06 737 if ( fill || stroke )
50581042
SC
738 {
739 // set up brushes
740 m_mode = kCGPathFill; // just a default
741
742 if ( stroke )
743 {
744 CGContextSetRGBStrokeColor( m_cgContext , pen.GetColour().Red() / 255.0 , pen.GetColour().Green() / 255.0 ,
745 pen.GetColour().Blue() / 255.0 , pen.GetColour().Alpha() / 255.0 );
746
747 // TODO: * m_dc->m_scaleX
748 CGFloat penWidth = pen.GetWidth();
749 if (penWidth <= 0.0)
750 penWidth = 0.1;
751 CGContextSetLineWidth( m_cgContext , penWidth );
752
753 CGLineCap cap;
754 switch ( pen.GetCap() )
755 {
756 case wxCAP_ROUND :
757 cap = kCGLineCapRound;
758 break;
759
760 case wxCAP_PROJECTING :
761 cap = kCGLineCapSquare;
762 break;
763
764 case wxCAP_BUTT :
765 cap = kCGLineCapButt;
766 break;
767
768 default :
769 cap = kCGLineCapButt;
770 break;
771 }
772
773 CGLineJoin join;
774 switch ( pen.GetJoin() )
775 {
776 case wxJOIN_BEVEL :
777 join = kCGLineJoinBevel;
778 break;
779
780 case wxJOIN_MITER :
781 join = kCGLineJoinMiter;
782 break;
783
784 case wxJOIN_ROUND :
785 join = kCGLineJoinRound;
786 break;
787
788 default :
789 join = kCGLineJoinMiter;
790 break;
791 }
792
793 m_mode = kCGPathStroke;
794 int count = 0;
795
796 const CGFloat *lengths = NULL;
797 CGFloat *userLengths = NULL;
798
799 const CGFloat dashUnit = penWidth < 1.0 ? 1.0 : penWidth;
800
801 const CGFloat dotted[] = { dashUnit , dashUnit + 2.0 };
802 const CGFloat short_dashed[] = { 9.0 , 6.0 };
803 const CGFloat dashed[] = { 19.0 , 9.0 };
804 const CGFloat dotted_dashed[] = { 9.0 , 6.0 , 3.0 , 3.0 };
805
806 switch ( pen.GetStyle() )
807 {
808 case wxSOLID :
809 break;
810
811 case wxDOT :
812 lengths = dotted;
813 count = WXSIZEOF(dotted);
814 break;
815
816 case wxLONG_DASH :
817 lengths = dashed;
818 count = WXSIZEOF(dashed);
819 break;
820
821 case wxSHORT_DASH :
822 lengths = short_dashed;
823 count = WXSIZEOF(short_dashed);
824 break;
825
826 case wxDOT_DASH :
827 lengths = dotted_dashed;
828 count = WXSIZEOF(dotted_dashed);
829 break;
830
831 case wxUSER_DASH :
832 wxDash *dashes;
833 count = pen.GetDashes( &dashes );
834 if ((dashes != NULL) && (count > 0))
835 {
836 userLengths = new CGFloat[count];
837 for ( int i = 0; i < count; ++i )
838 {
839 userLengths[i] = dashes[i] * dashUnit;
840
841 if ( i % 2 == 1 && userLengths[i] < dashUnit + 2.0 )
842 userLengths[i] = dashUnit + 2.0;
843 else if ( i % 2 == 0 && userLengths[i] < dashUnit )
844 userLengths[i] = dashUnit;
845 }
846 }
847 lengths = userLengths;
848 break;
849
850 case wxSTIPPLE :
851 {
852 CGFloat alphaArray[1] = { 1.0 };
853 wxBitmap* bmp = pen.GetStipple();
854 if ( bmp && bmp->Ok() )
855 {
856 wxMacCFRefHolder<CGColorSpaceRef> patternSpace( CGColorSpaceCreatePattern( NULL ) );
857 CGContextSetStrokeColorSpace( m_cgContext , patternSpace );
858 wxMacCFRefHolder<CGPatternRef> pattern( *( new ImagePattern( bmp , CGContextGetCTM( m_cgContext ) ) ) );
859 CGContextSetStrokePattern( m_cgContext, pattern , alphaArray );
860 }
861 }
862 break;
863
864 default :
865 {
866 wxMacCFRefHolder<CGColorSpaceRef> patternSpace( CGColorSpaceCreatePattern( wxMacGetGenericRGBColorSpace() ) );
867 CGContextSetStrokeColorSpace( m_cgContext , patternSpace );
868 wxMacCFRefHolder<CGPatternRef> pattern( *( new HatchPattern( pen.GetStyle() , CGContextGetCTM( m_cgContext ) ) ) );
869
870 CGFloat colorArray[4] = { pen.GetColour().Red() / 255.0 , pen.GetColour().Green() / 255.0 ,
871 pen.GetColour().Blue() / 255.0 , pen.GetColour().Alpha() / 255.0 };
872
873 CGContextSetStrokePattern( m_cgContext, pattern , colorArray );
874 }
875 break;
876 }
877
878 if ((lengths != NULL) && (count > 0))
879 {
880 CGContextSetLineDash( m_cgContext , 0 , lengths , count );
881 // force the line cap, otherwise we get artifacts (overlaps) and just solid lines
882 cap = kCGLineCapButt;
883 }
884 else
885 {
886 CGContextSetLineDash( m_cgContext , 0 , NULL , 0 );
887 }
888
889 CGContextSetLineCap( m_cgContext , cap );
890 CGContextSetLineJoin( m_cgContext , join );
891
892 delete[] userLengths;
893 }
894
895 if ( fill && stroke )
896 m_mode = kCGPathFillStroke;
897 }
898}
899
900void wxMacCoreGraphicsContext::SetBrush( const wxBrush &brush )
901{
902 m_brush = brush;
903 if ( m_cgContext == NULL )
904 return;
905
906 bool fill = brush.GetStyle() != wxTRANSPARENT;
907 bool stroke = m_pen.GetStyle() != wxTRANSPARENT;
908
909#if 0
910 // we can benchmark performance, should go into a setting later
911 CGContextSetShouldAntialias( m_cgContext , false );
912#endif
913
83b96a06 914 if ( fill || stroke )
50581042
SC
915 {
916 // setup brushes
917 m_mode = kCGPathFill; // just a default
918
919 if ( fill )
920 {
921 if ( brush.GetStyle() == wxSOLID )
922 {
923 CGContextSetRGBFillColor( m_cgContext , brush.GetColour().Red() / 255.0 , brush.GetColour().Green() / 255.0 ,
924 brush.GetColour().Blue() / 255.0 , brush.GetColour().Alpha() / 255.0 );
925 }
926 else if ( brush.IsHatch() )
927 {
928 wxMacCFRefHolder<CGColorSpaceRef> patternSpace( CGColorSpaceCreatePattern( wxMacGetGenericRGBColorSpace() ) );
929 CGContextSetFillColorSpace( m_cgContext , patternSpace );
930 wxMacCFRefHolder<CGPatternRef> pattern( *( new HatchPattern( brush.GetStyle() , CGContextGetCTM( m_cgContext ) ) ) );
931
932 CGFloat colorArray[4] = { brush.GetColour().Red() / 255.0 , brush.GetColour().Green() / 255.0 ,
933 brush.GetColour().Blue() / 255.0 , brush.GetColour().Alpha() / 255.0 };
934
935 CGContextSetFillPattern( m_cgContext, pattern , colorArray );
936 }
937 else
938 {
939 // now brush is a bitmap
940 CGFloat alphaArray[1] = { 1.0 };
941 wxBitmap* bmp = brush.GetStipple();
942 if ( bmp && bmp->Ok() )
943 {
944 wxMacCFRefHolder<CGColorSpaceRef> patternSpace( CGColorSpaceCreatePattern( NULL ) );
945 CGContextSetFillColorSpace( m_cgContext , patternSpace );
946 wxMacCFRefHolder<CGPatternRef> pattern( *( new ImagePattern( bmp , CGContextGetCTM( m_cgContext ) ) ) );
947 CGContextSetFillPattern( m_cgContext, pattern , alphaArray );
948 }
949 }
950
951 m_mode = kCGPathFill;
952 }
953
954 if ( fill && stroke )
955 m_mode = kCGPathFillStroke;
956 else if ( stroke )
957 m_mode = kCGPathStroke;
958 }
959}
960
961// sets the brush to a linear gradient, starting at (x1,y1) with color c1 to (x2,y2) with color c2
962void wxMacCoreGraphicsContext::SetLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2,
963 const wxColour&c1, const wxColour&c2)
964{
965}
966
967// sets the brush to a radial gradient originating at (xo,yc) with color oColor and ends on a circle around (xc,yc)
968// with radius r and color cColor
969void wxMacCoreGraphicsContext::SetRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius,
970 const wxColour &oColor, const wxColour &cColor)
971{
972}
973
974
975void wxMacCoreGraphicsContext::DrawText( const wxString &str, wxDouble x, wxDouble y )
976{
977 DrawText(str, x, y, 0.0);
978}
979
38af4365 980void wxMacCoreGraphicsContext::DrawText( const wxString &str, wxDouble x, wxDouble y, wxDouble angle )
50581042
SC
981{
982 OSStatus status = noErr;
983 ATSUTextLayout atsuLayout;
984 UniCharCount chars = str.length();
985 UniChar* ubuf = NULL;
986
987#if SIZEOF_WCHAR_T == 4
988 wxMBConvUTF16 converter;
989#if wxUSE_UNICODE
990 size_t unicharlen = converter.WC2MB( NULL , str.wc_str() , 0 );
991 ubuf = (UniChar*) malloc( unicharlen + 2 );
992 converter.WC2MB( (char*) ubuf , str.wc_str(), unicharlen + 2 );
993#else
994 const wxWCharBuffer wchar = str.wc_str( wxConvLocal );
995 size_t unicharlen = converter.WC2MB( NULL , wchar.data() , 0 );
996 ubuf = (UniChar*) malloc( unicharlen + 2 );
997 converter.WC2MB( (char*) ubuf , wchar.data() , unicharlen + 2 );
998#endif
999 chars = unicharlen / 2;
1000#else
1001#if wxUSE_UNICODE
1002 ubuf = (UniChar*) str.wc_str();
1003#else
1004 wxWCharBuffer wchar = str.wc_str( wxConvLocal );
1005 chars = wxWcslen( wchar.data() );
1006 ubuf = (UniChar*) wchar.data();
1007#endif
1008#endif
1009
1010 status = ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr) ubuf , 0 , chars , chars , 1 ,
1011 &chars , (ATSUStyle*) &m_macATSUIStyle , &atsuLayout );
1012
1013 wxASSERT_MSG( status == noErr , wxT("couldn't create the layout of the rotated text") );
1014
1015 status = ::ATSUSetTransientFontMatching( atsuLayout , true );
1016 wxASSERT_MSG( status == noErr , wxT("couldn't setup transient font matching") );
1017
1018 int iAngle = int( angle * RAD2DEG );
1019 if ( abs(iAngle) > 0 )
1020 {
1021 Fixed atsuAngle = IntToFixed( iAngle );
1022 ATSUAttributeTag atsuTags[] =
1023 {
1024 kATSULineRotationTag ,
1025 };
1026 ByteCount atsuSizes[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
1027 {
1028 sizeof( Fixed ) ,
1029 };
1030 ATSUAttributeValuePtr atsuValues[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
1031 {
1032 &atsuAngle ,
1033 };
1034 status = ::ATSUSetLayoutControls(atsuLayout , sizeof(atsuTags) / sizeof(ATSUAttributeTag),
1035 atsuTags, atsuSizes, atsuValues );
1036 }
1037
1038 {
1039 ATSUAttributeTag atsuTags[] =
1040 {
1041 kATSUCGContextTag ,
1042 };
1043 ByteCount atsuSizes[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
1044 {
1045 sizeof( CGContextRef ) ,
1046 };
1047 ATSUAttributeValuePtr atsuValues[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
1048 {
1049 &m_cgContext ,
1050 };
1051 status = ::ATSUSetLayoutControls(atsuLayout , sizeof(atsuTags) / sizeof(ATSUAttributeTag),
1052 atsuTags, atsuSizes, atsuValues );
1053 }
1054
1055 ATSUTextMeasurement textBefore, textAfter;
1056 ATSUTextMeasurement ascent, descent;
1057
1058 status = ::ATSUGetUnjustifiedBounds( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd,
1059 &textBefore , &textAfter, &ascent , &descent );
1060
1061 wxASSERT_MSG( status == noErr , wxT("couldn't measure the rotated text") );
1062
1063 Rect rect;
1064/*
1065 // TODO
1066 if ( m_backgroundMode == wxSOLID )
1067 {
1068 wxGraphicsPath* path = m_graphicContext->CreatePath();
1069 path->MoveToPoint( drawX , drawY );
1070 path->AddLineToPoint(
1071 (int) (drawX + sin(angle / RAD2DEG) * FixedToInt(ascent + descent)) ,
1072 (int) (drawY + cos(angle / RAD2DEG) * FixedToInt(ascent + descent)) );
1073 path->AddLineToPoint(
1074 (int) (drawX + sin(angle / RAD2DEG) * FixedToInt(ascent + descent ) + cos(angle / RAD2DEG) * FixedToInt(textAfter)) ,
1075 (int) (drawY + cos(angle / RAD2DEG) * FixedToInt(ascent + descent) - sin(angle / RAD2DEG) * FixedToInt(textAfter)) );
1076 path->AddLineToPoint(
1077 (int) (drawX + cos(angle / RAD2DEG) * FixedToInt(textAfter)) ,
1078 (int) (drawY - sin(angle / RAD2DEG) * FixedToInt(textAfter)) );
1079
1080 m_graphicContext->FillPath( path , m_textBackgroundColour );
1081 delete path;
1082 }
1083*/
1084 x += (int)(sin(angle / RAD2DEG) * FixedToInt(ascent));
1085 y += (int)(cos(angle / RAD2DEG) * FixedToInt(ascent));
1086
1087 status = ::ATSUMeasureTextImage( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd,
1088 IntToFixed(x) , IntToFixed(y) , &rect );
1089 wxASSERT_MSG( status == noErr , wxT("couldn't measure the rotated text") );
1090
1091 CGContextSaveGState(m_cgContext);
1092 CGContextTranslateCTM(m_cgContext, x, y);
1093 CGContextScaleCTM(m_cgContext, 1, -1);
1094 status = ::ATSUDrawText( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd,
1095 IntToFixed(0) , IntToFixed(0) );
1096
1097 wxASSERT_MSG( status == noErr , wxT("couldn't draw the rotated text") );
1098
1099 CGContextRestoreGState(m_cgContext);
1100
1101 ::ATSUDisposeTextLayout(atsuLayout);
1102
1103#if SIZEOF_WCHAR_T == 4
1104 free( ubuf );
1105#endif
1106}
1107
1108void wxMacCoreGraphicsContext::GetTextExtent( const wxString &str, wxDouble *width, wxDouble *height,
1109 wxDouble *descent, wxDouble *externalLeading ) const
1110{
1111 wxCHECK_RET( m_macATSUIStyle != NULL, wxT("wxDC(cg)::DoGetTextExtent - no valid font set") );
1112
1113 OSStatus status = noErr;
1114
1115 ATSUTextLayout atsuLayout;
1116 UniCharCount chars = str.length();
1117 UniChar* ubuf = NULL;
1118
1119#if SIZEOF_WCHAR_T == 4
1120 wxMBConvUTF16 converter;
1121#if wxUSE_UNICODE
1122 size_t unicharlen = converter.WC2MB( NULL , str.wc_str() , 0 );
1123 ubuf = (UniChar*) malloc( unicharlen + 2 );
1124 converter.WC2MB( (char*) ubuf , str.wc_str(), unicharlen + 2 );
1125#else
1126 const wxWCharBuffer wchar = str.wc_str( wxConvLocal );
1127 size_t unicharlen = converter.WC2MB( NULL , wchar.data() , 0 );
1128 ubuf = (UniChar*) malloc( unicharlen + 2 );
1129 converter.WC2MB( (char*) ubuf , wchar.data() , unicharlen + 2 );
1130#endif
1131 chars = unicharlen / 2;
1132#else
1133#if wxUSE_UNICODE
1134 ubuf = (UniChar*) str.wc_str();
1135#else
1136 wxWCharBuffer wchar = str.wc_str( wxConvLocal );
1137 chars = wxWcslen( wchar.data() );
1138 ubuf = (UniChar*) wchar.data();
1139#endif
1140#endif
1141
1142 status = ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr) ubuf , 0 , chars , chars , 1 ,
1143 &chars , (ATSUStyle*) &m_macATSUIStyle , &atsuLayout );
1144
1145 wxASSERT_MSG( status == noErr , wxT("couldn't create the layout of the text") );
1146
1147 ATSUTextMeasurement textBefore, textAfter;
1148 ATSUTextMeasurement textAscent, textDescent;
1149
1150 status = ::ATSUGetUnjustifiedBounds( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd,
1151 &textBefore , &textAfter, &textAscent , &textDescent );
1152
1153 if ( height )
1154 *height = FixedToInt(textAscent + textDescent);
1155 if ( descent )
1156 *descent = FixedToInt(textDescent);
1157 if ( externalLeading )
1158 *externalLeading = 0;
1159 if ( width )
1160 *width = FixedToInt(textAfter - textBefore);
1161
1162 ::ATSUDisposeTextLayout(atsuLayout);
1163}
1164
1165void wxMacCoreGraphicsContext::GetPartialTextExtents(const wxString& text, wxArrayDouble& widths) const
1166{
1167 widths.Empty();
1168 widths.Add(0, text.length());
1169
1170 if (text.empty())
1171 return;
1172
1173 ATSUTextLayout atsuLayout;
1174 UniCharCount chars = text.length();
1175 UniChar* ubuf = NULL;
1176
1177#if SIZEOF_WCHAR_T == 4
1178 wxMBConvUTF16 converter;
1179#if wxUSE_UNICODE
1180 size_t unicharlen = converter.WC2MB( NULL , text.wc_str() , 0 );
1181 ubuf = (UniChar*) malloc( unicharlen + 2 );
1182 converter.WC2MB( (char*) ubuf , text.wc_str(), unicharlen + 2 );
1183#else
1184 const wxWCharBuffer wchar = text.wc_str( wxConvLocal );
1185 size_t unicharlen = converter.WC2MB( NULL , wchar.data() , 0 );
1186 ubuf = (UniChar*) malloc( unicharlen + 2 );
1187 converter.WC2MB( (char*) ubuf , wchar.data() , unicharlen + 2 );
1188#endif
1189 chars = unicharlen / 2;
1190#else
1191#if wxUSE_UNICODE
1192 ubuf = (UniChar*) text.wc_str();
1193#else
1194 wxWCharBuffer wchar = text.wc_str( wxConvLocal );
1195 chars = wxWcslen( wchar.data() );
1196 ubuf = (UniChar*) wchar.data();
1197#endif
1198#endif
1199
83b96a06 1200 ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr) ubuf , 0 , chars , chars , 1 ,
50581042
SC
1201 &chars , (ATSUStyle*) &m_macATSUIStyle , &atsuLayout );
1202
1203 for ( int pos = 0; pos < (int)chars; pos ++ )
1204 {
1205 unsigned long actualNumberOfBounds = 0;
1206 ATSTrapezoid glyphBounds;
1207
1208 // We get a single bound, since the text should only require one. If it requires more, there is an issue
1209 OSStatus result;
1210 result = ATSUGetGlyphBounds( atsuLayout, 0, 0, kATSUFromTextBeginning, pos + 1,
1211 kATSUseDeviceOrigins, 1, &glyphBounds, &actualNumberOfBounds );
1212 if (result != noErr || actualNumberOfBounds != 1 )
1213 return;
1214
1215 widths[pos] = FixedToInt( glyphBounds.upperRight.x - glyphBounds.upperLeft.x );
1216 //unsigned char uch = s[i];
1217 }
1218
1219 ::ATSUDisposeTextLayout(atsuLayout);
1220}
1221
1222void wxMacCoreGraphicsContext::SetFont( const wxFont &font )
1223{
1224 if ( m_macATSUIStyle )
1225 {
1226 ::ATSUDisposeStyle((ATSUStyle)m_macATSUIStyle);
1227 m_macATSUIStyle = NULL;
1228 }
1229
1230 if ( font.Ok() )
1231 {
1056ddcf 1232 m_font = font ;
50581042
SC
1233 OSStatus status;
1234
1235 status = ATSUCreateAndCopyStyle( (ATSUStyle) font.MacGetATSUStyle() , (ATSUStyle*) &m_macATSUIStyle );
1236
1237 wxASSERT_MSG( status == noErr, wxT("couldn't create ATSU style") );
1238
1239 // we need the scale here ...
1240
1241 Fixed atsuSize = IntToFixed( int( /*m_scaleY*/ 1 * font.MacGetFontSize()) );
1242 RGBColor atsuColor = MAC_WXCOLORREF( m_textForegroundColor.GetPixel() );
1243 ATSUAttributeTag atsuTags[] =
1244 {
1245 kATSUSizeTag ,
1246 kATSUColorTag ,
1247 };
1248 ByteCount atsuSizes[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
1249 {
1250 sizeof( Fixed ) ,
1251 sizeof( RGBColor ) ,
1252 };
1253 ATSUAttributeValuePtr atsuValues[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
1254 {
1255 &atsuSize ,
1256 &atsuColor ,
1257 };
1258
1259 status = ::ATSUSetAttributes(
1260 (ATSUStyle)m_macATSUIStyle, sizeof(atsuTags) / sizeof(ATSUAttributeTag) ,
1261 atsuTags, atsuSizes, atsuValues);
1262
1263 wxASSERT_MSG( status == noErr , wxT("couldn't modify ATSU style") );
1264 }
1265}
1266
1056ddcf
SC
1267void * wxMacCoreGraphicsContext::GetNativeContext()
1268{
1269 return m_cgContext;
1270}
1271
50581042
SC
1272wxGraphicsContext* wxGraphicsContext::Create( const wxWindowDC &dc )
1273{
1274 return new wxMacCoreGraphicsContext((CGContextRef)dc.GetWindow()->MacGetCGContextRef() );
1275}
1276
1056ddcf
SC
1277wxGraphicsContext* wxGraphicsContext::Create( wxWindow * window )
1278{
7471064e
SC
1279 wxGraphicsContext* ctx = new wxMacCoreGraphicsContext( (WindowRef) window->MacGetTopLevelWindowRef() );
1280 CGContextRef cg = (CGContextRef) ctx->GetNativeContext() ;
1281 CGContextRestoreGState( cg );
1282 int x , y;
1283 x = y = 0;
1284 window->MacWindowToRootWindow( &x , &y );
1285 CGContextTranslateCTM( cg, x, y );
1286 CGContextSaveGState( cg );
1287 return ctx;
1288
1056ddcf
SC
1289}
1290
1291wxGraphicsContext* wxGraphicsContext::CreateFromNative( void * context )
1292{
1293 return new wxMacCoreGraphicsContext((CGContextRef)context);
1294}
1295
513b47e9
SC
1296wxGraphicsContext* wxGraphicsContext::CreateFromNativeWindow( void * window )
1297{
1298 return new wxMacCoreGraphicsContext((WindowRef)window);
1299}
1300
50581042 1301#endif // wxMAC_USE_CORE_GRAPHICS