]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/dccg.cpp
Clean up indentation / tabs from previous patch
[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
16#include "wx/dc.h"
17#include "wx/app.h"
18#include "wx/mac/uma.h"
19#include "wx/dcmemory.h"
20#include "wx/dcprint.h"
21#include "wx/region.h"
22#include "wx/image.h"
23#include "wx/log.h"
24
25#if __MSL__ >= 0x6000
26#include "math.h"
27using namespace std ;
28#endif
29
30#include "wx/mac/private.h"
31#include <ATSUnicode.h>
32#include <TextCommon.h>
33#include <TextEncodingConverter.h>
34#include <FixMath.h>
35#include <CGContext.h>
36
37#if !USE_SHARED_LIBRARY
38IMPLEMENT_ABSTRACT_CLASS(wxDC, wxObject)
39#endif
40
41//-----------------------------------------------------------------------------
42// constants
43//-----------------------------------------------------------------------------
44
45#if !defined( __DARWIN__ ) || defined(__MWERKS__)
46#ifndef M_PI
47const double M_PI = 3.14159265358979 ;
48#endif
49#endif
50const double RAD2DEG = 180.0 / M_PI;
51const short kEmulatedMode = -1 ;
52const short kUnsupportedMode = -2 ;
53
54extern TECObjectRef s_TECNativeCToUnicode ;
55
56// set to 0 if problems arise
57#define wxMAC_EXPERIMENTAL_DC 1
58
59wxMacPortSetter::wxMacPortSetter( const wxDC* dc ) :
60 m_ph( (GrafPtr) dc->m_macPort )
61{
62 wxASSERT( dc->Ok() ) ;
63 m_dc = dc ;
64 dc->MacSetupPort(&m_ph) ;
65}
66wxMacPortSetter::~wxMacPortSetter()
67{
68 m_dc->MacCleanupPort(&m_ph) ;
69}
70
71#if wxMAC_EXPERIMENTAL_DC
72class wxMacFastPortSetter
73{
74public :
75 wxMacFastPortSetter( const wxDC *dc )
76 {
77 wxASSERT( dc->Ok() ) ;
78 GetPort( &m_oldPort ) ;
79 SetPort( (GrafPtr) dc->m_macPort ) ;
80 m_clipRgn = NewRgn() ;
81 GetClip( m_clipRgn ) ;
82 m_dc = dc ;
83 dc->MacSetupPort( NULL ) ;
84 }
85 ~wxMacFastPortSetter()
86 {
87 SetPort( (GrafPtr) m_dc->m_macPort ) ;
88 SetClip( m_clipRgn ) ;
89 SetPort( m_oldPort ) ;
90 m_dc->MacCleanupPort( NULL ) ;
91 DisposeRgn( m_clipRgn ) ;
92 }
93private :
94 RgnHandle m_clipRgn ;
95 GrafPtr m_oldPort ;
96 const wxDC* m_dc ;
97} ;
98
99#else
100typedef wxMacPortSetter wxMacFastPortSetter ;
101#endif
102
103wxMacWindowClipper::wxMacWindowClipper( const wxWindow* win ) :
104 wxMacPortSaver( (GrafPtr) GetWindowPort((WindowRef) win->MacGetTopLevelWindowRef()) )
105{
106 m_newPort =(GrafPtr) GetWindowPort((WindowRef) win->MacGetTopLevelWindowRef()) ;
107 m_formerClip = NewRgn() ;
108 m_newClip = NewRgn() ;
109 GetClip( m_formerClip ) ;
110
111 if ( win )
112 {
113 int x = 0 , y = 0;
114 win->MacWindowToRootWindow( &x,&y ) ;
115 // get area including focus rect
116 CopyRgn( (RgnHandle) ((wxWindow*)win)->MacGetVisibleRegion(true).GetWXHRGN() , m_newClip ) ;
117 if ( !EmptyRgn( m_newClip ) )
118 OffsetRgn( m_newClip , x , y ) ;
119
120 SetClip( m_newClip ) ;
121 }
122}
123
124wxMacWindowClipper::~wxMacWindowClipper()
125{
126 SetPort( m_newPort ) ;
127 SetClip( m_formerClip ) ;
128 DisposeRgn( m_newClip ) ;
129 DisposeRgn( m_formerClip ) ;
130}
131
132wxMacWindowStateSaver::wxMacWindowStateSaver( const wxWindow* win ) :
133 wxMacWindowClipper( win )
134{
135 // the port is already set at this point
136 m_newPort =(GrafPtr) GetWindowPort((WindowRef) win->MacGetTopLevelWindowRef()) ;
137 GetThemeDrawingState( &m_themeDrawingState ) ;
138}
139
140wxMacWindowStateSaver::~wxMacWindowStateSaver()
141{
142 SetPort( m_newPort ) ;
143 SetThemeDrawingState( m_themeDrawingState , true ) ;
144}
145
146//-----------------------------------------------------------------------------
147// Local functions
148//-----------------------------------------------------------------------------
149static inline double dmin(double a, double b) { return a < b ? a : b; }
150static inline double dmax(double a, double b) { return a > b ? a : b; }
151static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; }
152
153//-----------------------------------------------------------------------------
154// wxDC
155//-----------------------------------------------------------------------------
156// this function emulates all wx colour manipulations, used to verify the implementation
157// by setting the mode in the blitting functions to kEmulatedMode
158void wxMacCalculateColour( int logical_func , const RGBColor &srcColor , RGBColor &dstColor ) ;
159
160void wxMacCalculateColour( int logical_func , const RGBColor &srcColor , RGBColor &dstColor )
161{
162 switch ( logical_func )
163 {
164 case wxAND: // src AND dst
165 dstColor.red = dstColor.red & srcColor.red ;
166 dstColor.green = dstColor.green & srcColor.green ;
167 dstColor.blue = dstColor.blue & srcColor.blue ;
168 break ;
169 case wxAND_INVERT: // (NOT src) AND dst
170 dstColor.red = dstColor.red & ~srcColor.red ;
171 dstColor.green = dstColor.green & ~srcColor.green ;
172 dstColor.blue = dstColor.blue & ~srcColor.blue ;
173 break ;
174 case wxAND_REVERSE:// src AND (NOT dst)
175 dstColor.red = ~dstColor.red & srcColor.red ;
176 dstColor.green = ~dstColor.green & srcColor.green ;
177 dstColor.blue = ~dstColor.blue & srcColor.blue ;
178 break ;
179 case wxCLEAR: // 0
180 dstColor.red = 0 ;
181 dstColor.green = 0 ;
182 dstColor.blue = 0 ;
183 break ;
184 case wxCOPY: // src
185 dstColor.red = srcColor.red ;
186 dstColor.green = srcColor.green ;
187 dstColor.blue = srcColor.blue ;
188 break ;
189 case wxEQUIV: // (NOT src) XOR dst
190 dstColor.red = dstColor.red ^ ~srcColor.red ;
191 dstColor.green = dstColor.green ^ ~srcColor.green ;
192 dstColor.blue = dstColor.blue ^ ~srcColor.blue ;
193 break ;
194 case wxINVERT: // NOT dst
195 dstColor.red = ~dstColor.red ;
196 dstColor.green = ~dstColor.green ;
197 dstColor.blue = ~dstColor.blue ;
198 break ;
199 case wxNAND: // (NOT src) OR (NOT dst)
200 dstColor.red = ~dstColor.red | ~srcColor.red ;
201 dstColor.green = ~dstColor.green | ~srcColor.green ;
202 dstColor.blue = ~dstColor.blue | ~srcColor.blue ;
203 break ;
204 case wxNOR: // (NOT src) AND (NOT dst)
205 dstColor.red = ~dstColor.red & ~srcColor.red ;
206 dstColor.green = ~dstColor.green & ~srcColor.green ;
207 dstColor.blue = ~dstColor.blue & ~srcColor.blue ;
208 break ;
209 case wxNO_OP: // dst
210 break ;
211 case wxOR: // src OR dst
212 dstColor.red = dstColor.red | srcColor.red ;
213 dstColor.green = dstColor.green | srcColor.green ;
214 dstColor.blue = dstColor.blue | srcColor.blue ;
215 break ;
216 case wxOR_INVERT: // (NOT src) OR dst
217 dstColor.red = dstColor.red | ~srcColor.red ;
218 dstColor.green = dstColor.green | ~srcColor.green ;
219 dstColor.blue = dstColor.blue | ~srcColor.blue ;
220 break ;
221 case wxOR_REVERSE: // src OR (NOT dst)
222 dstColor.red = ~dstColor.red | srcColor.red ;
223 dstColor.green = ~dstColor.green | srcColor.green ;
224 dstColor.blue = ~dstColor.blue | srcColor.blue ;
225 break ;
226 case wxSET: // 1
227 dstColor.red = 0xFFFF ;
228 dstColor.green = 0xFFFF ;
229 dstColor.blue = 0xFFFF ;
230 break ;
231 case wxSRC_INVERT: // (NOT src)
232 dstColor.red = ~srcColor.red ;
233 dstColor.green = ~srcColor.green ;
234 dstColor.blue = ~srcColor.blue ;
235 break ;
236 case wxXOR: // src XOR dst
237 dstColor.red = dstColor.red ^ srcColor.red ;
238 dstColor.green = dstColor.green ^ srcColor.green ;
239 dstColor.blue = dstColor.blue ^ srcColor.blue ;
240 break ;
241 }
242}
243
244class WXDLLEXPORT wxMacCGPath
245{
246 DECLARE_NO_COPY_CLASS(wxMacCGPath)
247public :
248
249 wxMacCGPath()
250 {
251 m_path = CGPathCreateMutable() ;
252 }
253
254 ~wxMacCGPath()
255 {
256 CGPathRelease( m_path ) ;
257 }
258
259 // Starts a new subpath at
260 void MoveToPoint( wxCoord x1 , wxCoord y1 )
261 {
262 CGPathMoveToPoint( m_path , NULL , x1 , y1 ) ;
263 }
264
265 void AddLineToPoint( wxCoord x1 , wxCoord y1 )
266 {
267 CGPathAddLineToPoint( m_path , NULL , x1 , y1 ) ;
268 }
269
270 void AddRectangle( wxCoord x, wxCoord y, wxCoord w, wxCoord h )
271 {
272 CGRect cgRect = { { x , y } , { w , h } } ;
273 CGPathAddRect( m_path , NULL , cgRect ) ;
274 }
275
276 void AddRectangle( CGRect cgRect )
277 {
278 CGPathAddRect( m_path , NULL , cgRect ) ;
279 }
280
281 void AddCircle( CGPoint center , float r )
282 {
283 CGPathAddArc( m_path , NULL , center.x , center.y , r , 0.0 , 2 * M_PI , true ) ;
284 }
285
286 // closes the current subpath
287 void CloseSubpath()
288 {
289 CGPathCloseSubpath( m_path ) ;
290 }
291
292 CGPathRef GetPath() const
293 {
294 return m_path ;
295 }
296private :
297 CGMutablePathRef m_path ;
298} ;
299
300class WXDLLEXPORT wxMacCGContext
301{
302 DECLARE_NO_COPY_CLASS(wxMacCGContext)
303
304public:
305 wxMacCGContext( const wxDC* dc ) ;
306 ~wxMacCGContext() ;
307
308 void StrokePath( const wxMacCGPath &path )
309 {
310
311 CGContextBeginPath( m_cgContext ) ;
312 CGContextAddPath( m_cgContext , path.GetPath() ) ;
313 CGContextClosePath( m_cgContext ) ;
314 CGContextStrokePath( m_cgContext ) ;
315 }
316
317 void DrawPath( const wxMacCGPath &path , int fillStyle = wxWINDING_RULE )
318 {
319 CGPathDrawingMode mode = m_mode ;
320 if ( fillStyle == wxODDEVEN_RULE )
321 {
322 if ( mode == kCGPathFill )
323 mode = kCGPathEOFill ;
324 else if ( mode == kCGPathFillStroke )
325 mode = kCGPathEOFillStroke ;
326 }
327 CGContextBeginPath( m_cgContext ) ;
328 CGContextAddPath( m_cgContext , path.GetPath() ) ;
329 CGContextClosePath( m_cgContext ) ;
330 CGContextDrawPath( m_cgContext , mode ) ;
331 }
332
333 void FillPath( const wxMacCGPath &path , const wxColor &fillColor , int fillStyle = wxWINDING_RULE )
334 {
335 RGBColor col = MAC_WXCOLORREF( fillColor.GetPixel() ) ;
336 CGContextSetRGBFillColor( m_cgContext , col.red / 65536.0 , col.green / 65536.0 , col.blue / 65536.0 , 1.0 ) ;
337 CGPathDrawingMode mode = kCGPathFill ;
338
339 if ( fillStyle == wxODDEVEN_RULE )
340 mode = kCGPathEOFill ;
341
342 CGContextBeginPath( m_cgContext ) ;
343 CGContextAddPath( m_cgContext , path.GetPath() ) ;
344 CGContextClosePath( m_cgContext ) ;
345 CGContextDrawPath( m_cgContext , mode ) ;
346 if ( m_dc->GetBrush().GetStyle() )
347 {
348 RGBColor col = MAC_WXCOLORREF( m_dc->GetBrush().GetColour().GetPixel() ) ;
349 CGContextSetRGBFillColor( m_cgContext , col.red / 65536.0 , col.green / 65536.0 , col.blue / 65536.0 , 1.0 ) ;
350 }
351 }
352
353 void SetupPenAndBrush() ;
354 CGContextRef GetNativeContext() { return m_cgContext ; }
355private:
356 CGContextRef m_cgContext ;
357 CGPathDrawingMode m_mode ;
358 const wxDC* m_dc ;
359} ;
360
361wxMacCGContext::wxMacCGContext( const wxDC* dc )
362{
363 wxASSERT( dc->Ok() ) ;
364
365 Rect bounds ;
366 GetPortBounds( (CGrafPtr) dc->m_macPort , &bounds ) ;
367 OSStatus status = QDBeginCGContext( (CGrafPtr) dc->m_macPort , &m_cgContext ) ;
368 wxASSERT_MSG( status == noErr , wxT("Cannot nest wxDCs on the same window") ) ;
369 ClipCGContextToRegion ( m_cgContext, &bounds , (RgnHandle) dc->m_macCurrentClipRgn ) ;
370
371 CGContextTranslateCTM( m_cgContext , 0 , bounds.bottom - bounds.top ) ;
372 CGContextScaleCTM( m_cgContext , 1 , -1 ) ;
373
374 m_dc = dc ;
375 SetupPenAndBrush() ;
376}
377
378void wxMacCGContext::SetupPenAndBrush()
379{
380 bool fill = m_dc->GetBrush().GetStyle() != wxTRANSPARENT ;
381 bool stroke = m_dc->GetPen().GetStyle() != wxTRANSPARENT ;
382
383 if ( fill | stroke )
384 {
385
386 // setup brushes
387 m_mode = kCGPathFill ; // just a default
388
389 if ( fill )
390 {
391 RGBColor col = MAC_WXCOLORREF( m_dc->GetBrush().GetColour().GetPixel() ) ;
392 CGContextSetRGBFillColor( m_cgContext , col.red / 65536.0 , col.green / 65536.0 , col.blue / 65536.0 , 1.0 ) ;
393 m_mode = kCGPathFill ;
394 }
395 if ( stroke )
396 {
397 RGBColor col = MAC_WXCOLORREF( m_dc->GetPen().GetColour().GetPixel() ) ;
398 CGContextSetRGBStrokeColor( m_cgContext , col.red / 65536.0 , col.green / 65536.0 , col.blue / 65536.0 , 1.0 ) ;
399
400 CGLineCap cap ;
401 switch( m_dc->GetPen().GetCap() )
402 {
403 case wxCAP_ROUND :
404 cap = kCGLineCapRound ;
405 break ;
406 case wxCAP_PROJECTING :
407 cap = kCGLineCapSquare ;
408 break ;
409 case wxCAP_BUTT :
410 cap = kCGLineCapButt ;
411 break ;
412 default :
413 cap = kCGLineCapButt ;
414 break ;
415 }
416 CGContextSetLineCap( m_cgContext , cap ) ;
417
418 CGLineJoin join ;
419 switch( m_dc->GetPen().GetJoin() )
420 {
421 case wxJOIN_BEVEL :
422 join = kCGLineJoinBevel ;
423 break ;
424 case wxJOIN_MITER :
425 join = kCGLineJoinMiter ;
426 break ;
427 case wxJOIN_ROUND :
428 join = kCGLineJoinRound ;
429 break ;
430 default :
431 join = kCGLineJoinMiter ;
432 break;
433 }
434 CGContextSetLineJoin( m_cgContext , join ) ;
435
436 CGContextSetLineWidth( m_cgContext , m_dc->GetPen().GetWidth() == 0 ? 0.1 : m_dc->GetPen().GetWidth() /* TODO * m_dc->m_scaleX */ ) ;
437
438 m_mode = kCGPathStroke ;
439 int count = 0 ;
440 const float *lengths = NULL ;
441 float *userLengths = NULL ;
442
443 switch( m_dc->GetPen().GetStyle() )
444 {
445 case wxSOLID :
446 break ;
447 case wxDOT :
448 const float dotted[] = { 3 , 3 };
449 lengths = dotted ;
450 count = WXSIZEOF(dotted);
451 break ;
452 case wxLONG_DASH :
453 const float dashed[] = { 19 , 9 };
454 lengths = dashed ;
455 count = WXSIZEOF(dashed) ;
456 break ;
457 case wxSHORT_DASH :
458 const float short_dashed[] = { 9 , 6 };
459 lengths = short_dashed ;
460 count = WXSIZEOF(short_dashed) ;
461 break ;
462 case wxDOT_DASH :
463 const float dotted_dashed[] = { 9 , 6 , 3 , 3 };
464 lengths = dotted_dashed ;
465 count = WXSIZEOF(dotted_dashed);
466 break ;
467 case wxUSER_DASH :
468 wxDash *dashes ;
469 count = m_dc->GetPen().GetDashes( &dashes ) ;
470 if ( count >0 )
471 {
472 userLengths = new float[count] ;
473 for( int i = 0 ; i < count ; ++i )
474 userLengths[i] = dashes[i] ;
475 }
476 lengths = userLengths ;
477 break ;
478 default :
479 break ;
480 }
481
482 CGContextSetLineDash( m_cgContext , 0 , lengths , count ) ;
483 delete[] userLengths ;
484 // we need to change the cap, otherwise everything overlaps
485 // and we get solid lines
486 if ( count > 0 )
487 CGContextSetLineCap( m_cgContext , kCGLineCapButt ) ;
488 }
489 if ( fill && stroke )
490 {
491 m_mode = kCGPathFillStroke ;
492 }
493
494 }
495}
496
497wxMacCGContext::~wxMacCGContext()
498{
499 QDEndCGContext( (CGrafPtr) m_dc->m_macPort , &m_cgContext ) ;
500}
501
502
503#define wxMacGraphicContext wxMacCGContext
504#define wxMacGraphicPath wxMacCGPath
505
506void AddEllipticArcToPath(CGContextRef c, CGPoint center, float a, float b, float fromDegree , float toDegree )
507{
508 CGContextSaveGState(c);
509 CGContextTranslateCTM(c, center.x, center.y);
510 CGContextScaleCTM(c, a, b);
511 CGContextMoveToPoint(c, 1, 0);
512 CGContextAddArc(c, 0, 0, 1, DegToRad(fromDegree), DegToRad(toDegree), 0);
513 CGContextClosePath(c);
514 CGContextRestoreGState(c);
515}
516
517void AddRoundedRectToPath(CGContextRef c, CGRect rect, float ovalWidth,
518 float ovalHeight)
519{
520 float fw, fh;
521 if (ovalWidth == 0 || ovalHeight == 0)
522 {
523 CGContextAddRect(c, rect);
524 return;
525 }
526 CGContextSaveGState(c);
527 CGContextTranslateCTM(c, CGRectGetMinX(rect), CGRectGetMinY(rect));
528 CGContextScaleCTM(c, ovalWidth, ovalHeight);
529 fw = CGRectGetWidth(rect) / ovalWidth;
530 fh = CGRectGetHeight(rect) / ovalHeight;
531 CGContextMoveToPoint(c, fw, fh/2);
532 CGContextAddArcToPoint(c, fw, fh, fw/2, fh, 1);
533 CGContextAddArcToPoint(c, 0, fh, 0, fh/2, 1);
534 CGContextAddArcToPoint(c, 0, 0, fw/2, 0, 1);
535 CGContextAddArcToPoint(c, fw, 0, fw, fh/2, 1);
536 CGContextClosePath(c);
537 CGContextRestoreGState(c);
538}
539
540wxDC::wxDC()
541{
542 m_ok = FALSE;
543 m_colour = TRUE;
544 m_mm_to_pix_x = mm2pt;
545 m_mm_to_pix_y = mm2pt;
546 m_internalDeviceOriginX = 0;
547 m_internalDeviceOriginY = 0;
548 m_externalDeviceOriginX = 0;
549 m_externalDeviceOriginY = 0;
550 m_logicalScaleX = 1.0;
551 m_logicalScaleY = 1.0;
552 m_userScaleX = 1.0;
553 m_userScaleY = 1.0;
554 m_scaleX = 1.0;
555 m_scaleY = 1.0;
556 m_needComputeScaleX = FALSE;
557 m_needComputeScaleY = FALSE;
558 m_macPort = NULL ;
559 m_macMask = NULL ;
560 m_ok = FALSE ;
561 m_macFontInstalled = false ;
562 m_macBrushInstalled = false ;
563 m_macPenInstalled = false ;
564 m_macLocalOrigin.x = m_macLocalOrigin.y = 0 ;
565 m_macBoundaryClipRgn = NewRgn() ;
566 m_macCurrentClipRgn = NewRgn() ;
567 SetRectRgn( (RgnHandle) m_macBoundaryClipRgn , -32000 , -32000 , 32000 , 32000 ) ;
568 SetRectRgn( (RgnHandle) m_macCurrentClipRgn , -32000 , -32000 , 32000 , 32000 ) ;
569 m_pen = *wxBLACK_PEN;
570 m_font = *wxNORMAL_FONT;
571 m_brush = *wxWHITE_BRUSH;
572#ifdef __WXDEBUG__
573 // needed to debug possible errors with two active drawing methods at the same time on
574 // the same DC
575 m_macCurrentPortStateHelper = NULL ;
576#endif
577 m_macATSUIStyle = NULL ;
578 m_macAliasWasEnabled = false;
579 m_macForegroundPixMap = NULL ;
580 m_macBackgroundPixMap = NULL ;
581 m_macGraphicContext = NULL ;
582}
583
584wxDC::~wxDC(void)
585{
586 DisposeRgn( (RgnHandle) m_macBoundaryClipRgn ) ;
587 DisposeRgn( (RgnHandle) m_macCurrentClipRgn ) ;
588 delete m_macGraphicContext ;
589
590}
591
592void wxDC::MacSetupGraphicContext()
593{
594 m_macGraphicContext = new wxMacCGContext( this ) ;
595}
596
597void wxDC::MacSetupPort(wxMacPortStateHelper* help) const
598{
599#ifdef __WXDEBUG__
600 wxASSERT( m_macCurrentPortStateHelper == NULL ) ;
601 m_macCurrentPortStateHelper = help ;
602#endif
603 SetClip( (RgnHandle) m_macCurrentClipRgn);
604#if ! wxMAC_EXPERIMENTAL_DC
605 m_macFontInstalled = false ;
606 m_macBrushInstalled = false ;
607 m_macPenInstalled = false ;
608#endif
609}
610void wxDC::MacCleanupPort(wxMacPortStateHelper* help) const
611{
612#ifdef __WXDEBUG__
613 wxASSERT( m_macCurrentPortStateHelper == help ) ;
614 m_macCurrentPortStateHelper = NULL ;
615#endif
616 if( m_macATSUIStyle )
617 {
618 ::ATSUDisposeStyle((ATSUStyle)m_macATSUIStyle);
619 m_macATSUIStyle = NULL ;
620 }
621 if ( m_macAliasWasEnabled )
622 {
623 SetAntiAliasedTextEnabled(m_macFormerAliasState, m_macFormerAliasSize);
624 m_macAliasWasEnabled = false ;
625 }
626 if ( m_macForegroundPixMap )
627 {
628 Pattern blackColor ;
629 ::PenPat(GetQDGlobalsBlack(&blackColor));
630 DisposePixPat( (PixPatHandle) m_macForegroundPixMap ) ;
631 m_macForegroundPixMap = NULL ;
632 }
633 if ( m_macBackgroundPixMap )
634 {
635 Pattern whiteColor ;
636 ::BackPat(GetQDGlobalsWhite(&whiteColor));
637 DisposePixPat( (PixPatHandle) m_macBackgroundPixMap ) ;
638 m_macBackgroundPixMap = NULL ;
639 }
640}
641
642void wxDC::DoDrawBitmap( const wxBitmap &bmp, wxCoord x, wxCoord y, bool useMask )
643{
644 wxCHECK_RET( Ok(), wxT("invalid window dc") );
645 wxCHECK_RET( bmp.Ok(), wxT("invalid bitmap") );
646 wxCoord xx = XLOG2DEVMAC(x);
647 wxCoord yy = YLOG2DEVMAC(y);
648 wxCoord w = bmp.GetWidth();
649 wxCoord h = bmp.GetHeight();
650 wxCoord ww = XLOG2DEVREL(w);
651 wxCoord hh = YLOG2DEVREL(h);
652 // Set up drawing mode
653 short mode = (m_logicalFunction == wxCOPY ? srcCopy :
654 //m_logicalFunction == wxCLEAR ? WHITENESS :
655 //m_logicalFunction == wxSET ? BLACKNESS :
656 m_logicalFunction == wxINVERT ? hilite :
657 //m_logicalFunction == wxAND ? MERGECOPY :
658 m_logicalFunction == wxOR ? srcOr :
659 m_logicalFunction == wxSRC_INVERT ? notSrcCopy :
660 m_logicalFunction == wxXOR ? srcXor :
661 m_logicalFunction == wxOR_REVERSE ? notSrcOr :
662 //m_logicalFunction == wxAND_REVERSE ? SRCERASE :
663 //m_logicalFunction == wxSRC_OR ? srcOr :
664 //m_logicalFunction == wxSRC_AND ? SRCAND :
665 srcCopy );
666 if ( bmp.GetBitmapType() == kMacBitmapTypePict ) {
667 Rect bitmaprect = { 0 , 0 , hh, ww };
668 ::OffsetRect( &bitmaprect, xx, yy ) ;
669 ::DrawPicture( (PicHandle) bmp.GetPict(), &bitmaprect ) ;
670 }
671 else if ( bmp.GetBitmapType() == kMacBitmapTypeGrafWorld )
672 {
673 GWorldPtr bmapworld = MAC_WXHBITMAP( bmp.GetHBITMAP() );
674 PixMapHandle bmappixels ;
675 // Set foreground and background colours (for bitmaps depth = 1)
676 if(bmp.GetDepth() == 1)
677 {
678 RGBColor fore = MAC_WXCOLORREF(m_textForegroundColour.GetPixel());
679 RGBColor back = MAC_WXCOLORREF(m_textBackgroundColour.GetPixel());
680 RGBForeColor(&fore);
681 RGBBackColor(&back);
682 }
683 else
684 {
685 RGBColor white = { 0xFFFF, 0xFFFF,0xFFFF} ;
686 RGBColor black = { 0,0,0} ;
687 RGBForeColor( &black ) ;
688 RGBBackColor( &white ) ;
689 }
690 bmappixels = GetGWorldPixMap( bmapworld ) ;
691 wxCHECK_RET(LockPixels(bmappixels),
692 wxT("DoDrawBitmap: Unable to lock pixels"));
693 Rect source = { 0, 0, h, w };
694 Rect dest = { yy, xx, yy + hh, xx + ww };
695 if ( useMask && bmp.GetMask() )
696 {
697 if( LockPixels(GetGWorldPixMap(MAC_WXHBITMAP(bmp.GetMask()->GetMaskBitmap()))))
698 {
699 CopyDeepMask
700 (
701 GetPortBitMapForCopyBits(bmapworld),
702 GetPortBitMapForCopyBits(MAC_WXHBITMAP(bmp.GetMask()->GetMaskBitmap())),
703 GetPortBitMapForCopyBits( MAC_WXHBITMAP(m_macPort) ),
704 &source, &source, &dest, mode, NULL
705 );
706 UnlockPixels(GetGWorldPixMap(MAC_WXHBITMAP(bmp.GetMask()->GetMaskBitmap())));
707 }
708 }
709 else {
710 CopyBits( GetPortBitMapForCopyBits( bmapworld ),
711 GetPortBitMapForCopyBits( MAC_WXHBITMAP(m_macPort) ),
712 &source, &dest, mode, NULL ) ;
713 }
714 UnlockPixels( bmappixels ) ;
715 }
716 else if ( bmp.GetBitmapType() == kMacBitmapTypeIcon )
717 {
718 Rect bitmaprect = { 0 , 0 , bmp.GetHeight(), bmp.GetWidth() } ;
719 OffsetRect( &bitmaprect, xx, yy ) ;
720 PlotCIconHandle( &bitmaprect , atNone , ttNone , MAC_WXHICON(bmp.GetHICON()) ) ;
721 }
722 m_macPenInstalled = false ;
723 m_macBrushInstalled = false ;
724 m_macFontInstalled = false ;
725}
726
727void wxDC::DoDrawIcon( const wxIcon &icon, wxCoord x, wxCoord y )
728{
729 wxCHECK_RET(Ok(), wxT("Invalid dc wxDC::DoDrawIcon"));
730 wxCHECK_RET(icon.Ok(), wxT("Invalid icon wxDC::DoDrawIcon"));
731 DoDrawBitmap( icon , x , y , icon.GetMask() != NULL ) ;
732}
733
734void wxDC::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
735{
736 wxCHECK_RET(Ok(), wxT("wxDC::DoSetClippingRegion Invalid DC"));
737 wxCoord xx, yy, ww, hh;
738 xx = XLOG2DEVMAC(x);
739 yy = YLOG2DEVMAC(y);
740 ww = XLOG2DEVREL(width);
741 hh = YLOG2DEVREL(height);
742 SetRectRgn( (RgnHandle) m_macCurrentClipRgn , xx , yy , xx + ww , yy + hh ) ;
743 SectRgn( (RgnHandle) m_macCurrentClipRgn , (RgnHandle) m_macBoundaryClipRgn , (RgnHandle) m_macCurrentClipRgn ) ;
744 if( m_clipping )
745 {
746 m_clipX1 = wxMax( m_clipX1 , xx );
747 m_clipY1 = wxMax( m_clipY1 , yy );
748 m_clipX2 = wxMin( m_clipX2, (xx + ww));
749 m_clipY2 = wxMin( m_clipY2, (yy + hh));
750 }
751 else
752 {
753 m_clipping = TRUE;
754 m_clipX1 = xx;
755 m_clipY1 = yy;
756 m_clipX2 = xx + ww;
757 m_clipY2 = yy + hh;
758 }
759 // TODO as soon as we don't reset the context for each operation anymore
760 // we have to update the context as well
761}
762
763void wxDC::DoSetClippingRegionAsRegion( const wxRegion &region )
764{
765 wxCHECK_RET( Ok(), wxT("invalid window dc") ) ;
766 if (region.Empty())
767 {
768 DestroyClippingRegion();
769 return;
770 }
771 wxCoord x, y, w, h;
772 region.GetBox( x, y, w, h );
773 wxCoord xx, yy, ww, hh;
774 xx = XLOG2DEVMAC(x);
775 yy = YLOG2DEVMAC(y);
776 ww = XLOG2DEVREL(w);
777 hh = YLOG2DEVREL(h);
778 // if we have a scaling that we cannot map onto native regions
779 // we must use the box
780 if ( ww != w || hh != h )
781 {
782 wxDC::DoSetClippingRegion( x, y, w, h );
783 }
784 else
785 {
786 CopyRgn( (RgnHandle) region.GetWXHRGN() , (RgnHandle) m_macCurrentClipRgn ) ;
787 if ( xx != x || yy != y )
788 {
789 OffsetRgn( (RgnHandle) m_macCurrentClipRgn , xx - x , yy - y ) ;
790 }
791 SectRgn( (RgnHandle) m_macCurrentClipRgn , (RgnHandle) m_macBoundaryClipRgn , (RgnHandle) m_macCurrentClipRgn ) ;
792 if( m_clipping )
793 {
794 m_clipX1 = wxMax( m_clipX1 , xx );
795 m_clipY1 = wxMax( m_clipY1 , yy );
796 m_clipX2 = wxMin( m_clipX2, (xx + ww));
797 m_clipY2 = wxMin( m_clipY2, (yy + hh));
798 }
799 else
800 {
801 m_clipping = TRUE;
802 m_clipX1 = xx;
803 m_clipY1 = yy;
804 m_clipX2 = xx + ww;
805 m_clipY2 = yy + hh;
806 }
807 }
808}
809
810void wxDC::DestroyClippingRegion()
811{
812 CopyRgn( (RgnHandle) m_macBoundaryClipRgn , (RgnHandle) m_macCurrentClipRgn ) ;
813 m_clipping = FALSE;
814}
815
816void wxDC::DoGetSizeMM( int* width, int* height ) const
817{
818 int w = 0;
819 int h = 0;
820 GetSize( &w, &h );
821 *width = long( double(w) / (m_scaleX*m_mm_to_pix_x) );
822 *height = long( double(h) / (m_scaleY*m_mm_to_pix_y) );
823}
824
825void wxDC::SetTextForeground( const wxColour &col )
826{
827 wxCHECK_RET(Ok(), wxT("Invalid DC"));
828 m_textForegroundColour = col;
829 m_macFontInstalled = false ;
830}
831
832void wxDC::SetTextBackground( const wxColour &col )
833{
834 wxCHECK_RET(Ok(), wxT("Invalid DC"));
835 m_textBackgroundColour = col;
836 m_macFontInstalled = false ;
837}
838
839void wxDC::SetMapMode( int mode )
840{
841 switch (mode)
842 {
843 case wxMM_TWIPS:
844 SetLogicalScale( twips2mm*m_mm_to_pix_x, twips2mm*m_mm_to_pix_y );
845 break;
846 case wxMM_POINTS:
847 SetLogicalScale( pt2mm*m_mm_to_pix_x, pt2mm*m_mm_to_pix_y );
848 break;
849 case wxMM_METRIC:
850 SetLogicalScale( m_mm_to_pix_x, m_mm_to_pix_y );
851 break;
852 case wxMM_LOMETRIC:
853 SetLogicalScale( m_mm_to_pix_x/10.0, m_mm_to_pix_y/10.0 );
854 break;
855 default:
856 case wxMM_TEXT:
857 SetLogicalScale( 1.0, 1.0 );
858 break;
859 }
860 if (mode != wxMM_TEXT)
861 {
862 m_needComputeScaleX = TRUE;
863 m_needComputeScaleY = TRUE;
864 }
865}
866
867void wxDC::SetUserScale( double x, double y )
868{
869 // allow negative ? -> no
870 m_userScaleX = x;
871 m_userScaleY = y;
872 ComputeScaleAndOrigin();
873}
874
875void wxDC::SetLogicalScale( double x, double y )
876{
877 // allow negative ?
878 m_logicalScaleX = x;
879 m_logicalScaleY = y;
880 ComputeScaleAndOrigin();
881}
882
883void wxDC::SetLogicalOrigin( wxCoord x, wxCoord y )
884{
885 m_logicalOriginX = x * m_signX; // is this still correct ?
886 m_logicalOriginY = y * m_signY;
887 ComputeScaleAndOrigin();
888}
889
890void wxDC::SetDeviceOrigin( wxCoord x, wxCoord y )
891{
892 m_externalDeviceOriginX = x;
893 m_externalDeviceOriginY = y;
894 ComputeScaleAndOrigin();
895}
896
897void wxDC::SetAxisOrientation( bool xLeftRight, bool yBottomUp )
898{
899 m_signX = (xLeftRight ? 1 : -1);
900 m_signY = (yBottomUp ? -1 : 1);
901 ComputeScaleAndOrigin();
902}
903
904wxSize wxDC::GetPPI() const
905{
906 return wxSize(72, 72);
907}
908
909int wxDC::GetDepth() const
910{
911 if ( IsPortColor( (CGrafPtr) m_macPort ) )
912 {
913 return ( (**GetPortPixMap( (CGrafPtr) m_macPort)).pixelSize ) ;
914 }
915 return 1 ;
916}
917
918void wxDC::ComputeScaleAndOrigin()
919{
920 // CMB: copy scale to see if it changes
921 double origScaleX = m_scaleX;
922 double origScaleY = m_scaleY;
923 m_scaleX = m_logicalScaleX * m_userScaleX;
924 m_scaleY = m_logicalScaleY * m_userScaleY;
925 m_deviceOriginX = m_internalDeviceOriginX + m_externalDeviceOriginX;
926 m_deviceOriginY = m_internalDeviceOriginY + m_externalDeviceOriginY;
927 // CMB: if scale has changed call SetPen to recalulate the line width
928 if (m_scaleX != origScaleX || m_scaleY != origScaleY)
929 {
930 // this is a bit artificial, but we need to force wxDC to think
931 // the pen has changed
932 wxPen pen(GetPen());
933 m_pen = wxNullPen;
934 SetPen(pen);
935 }
936}
937
938void wxDC::SetPalette( const wxPalette& palette )
939{
940}
941
942void wxDC::SetBackgroundMode( int mode )
943{
944 m_backgroundMode = mode ;
945}
946
947void wxDC::SetFont( const wxFont &font )
948{
949 m_font = font;
950 m_macFontInstalled = false ;
951}
952
953void wxDC::SetPen( const wxPen &pen )
954{
955 if ( m_pen == pen )
956 return ;
957 m_pen = pen;
958 m_macPenInstalled = false ;
959 m_macGraphicContext->SetupPenAndBrush() ;
960}
961
962void wxDC::SetBrush( const wxBrush &brush )
963{
964 if (m_brush == brush)
965 return;
966 m_brush = brush;
967 m_macBrushInstalled = false ;
968 m_macGraphicContext->SetupPenAndBrush() ;
969}
970
971void wxDC::SetBackground( const wxBrush &brush )
972{
973 if (m_backgroundBrush == brush)
974 return;
975 m_backgroundBrush = brush;
976 if (!m_backgroundBrush.Ok())
977 return;
978 m_macBrushInstalled = false ;
979}
980
981void wxDC::SetLogicalFunction( int function )
982{
983 if (m_logicalFunction == function)
984 return;
985 m_logicalFunction = function ;
986 m_macFontInstalled = false ;
987 m_macBrushInstalled = false ;
988 m_macPenInstalled = false ;
989}
990
991extern bool wxDoFloodFill(wxDC *dc, wxCoord x, wxCoord y,
992 const wxColour & col, int style);
993
994bool wxDC::DoFloodFill(wxCoord x, wxCoord y,
995 const wxColour& col, int style)
996{
997 return wxDoFloodFill(this, x, y, col, style);
998}
999
1000bool wxDC::DoGetPixel( wxCoord x, wxCoord y, wxColour *col ) const
1001{
1002 wxCHECK_MSG( Ok(), false, wxT("wxDC::DoGetPixel Invalid DC") );
1003 RGBColor colour;
1004 GetCPixel( XLOG2DEVMAC(x), YLOG2DEVMAC(y), &colour );
1005 // Convert from Mac colour to wx
1006 col->Set( colour.red >> 8,
1007 colour.green >> 8,
1008 colour.blue >> 8);
1009 return true ;
1010}
1011
1012void wxDC::DoDrawLine( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2 )
1013{
1014 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1015
1016 wxCoord xx1 = XLOG2DEVMAC(x1) ;
1017 wxCoord yy1 = YLOG2DEVMAC(y1) ;
1018 wxCoord xx2 = XLOG2DEVMAC(x2) ;
1019 wxCoord yy2 = YLOG2DEVMAC(y2) ;
1020
1021 wxMacGraphicPath path ;
1022 path.MoveToPoint( xx1 , yy1 ) ;
1023 path.AddLineToPoint( xx2 , yy2 ) ;
1024 path.CloseSubpath() ;
1025 m_macGraphicContext->StrokePath( path ) ;
1026
1027 CalcBoundingBox(x1, y1);
1028 CalcBoundingBox(x2, y2);
1029}
1030
1031void wxDC::DoCrossHair( wxCoord x, wxCoord y )
1032{
1033 wxCHECK_RET( Ok(), wxT("wxDC::DoCrossHair Invalid window dc") );
1034
1035
1036 int w = 0;
1037 int h = 0;
1038 GetSize( &w, &h );
1039 wxCoord xx = XLOG2DEVMAC(x);
1040 wxCoord yy = YLOG2DEVMAC(y);
1041
1042 wxMacGraphicPath path ;
1043 path.MoveToPoint( XLOG2DEVMAC(0), yy ) ;
1044 path.AddLineToPoint( XLOG2DEVMAC(w), yy ) ;
1045 path.CloseSubpath() ;
1046 path.MoveToPoint( xx, YLOG2DEVMAC(0) ) ;
1047 path.AddLineToPoint( xx, YLOG2DEVMAC(h) ) ;
1048 path.CloseSubpath() ;
1049 m_macGraphicContext->StrokePath( path ) ;
1050
1051 CalcBoundingBox(x, y);
1052 CalcBoundingBox(x+w, y+h);
1053}
1054
1055/*
1056* To draw arcs properly the angles need to be converted from the WX style:
1057* Angles start on the +ve X axis and go anti-clockwise (As you would draw on
1058* a normal axis on paper).
1059* TO
1060* the Mac style:
1061* Angles start on the +ve y axis and go clockwise.
1062*/
1063
1064static double wxConvertWXangleToMACangle(double angle)
1065{
1066 double newAngle = 90 - angle ;
1067 if ( newAngle < 0 )
1068 newAngle += 360 ;
1069 return newAngle ;
1070}
1071
1072void wxDC::DoDrawArc( wxCoord x1, wxCoord y1,
1073 wxCoord x2, wxCoord y2,
1074 wxCoord xc, wxCoord yc )
1075{
1076 wxCHECK_RET(Ok(), wxT("wxDC::DoDrawArc Invalid DC"));
1077 wxCoord xx1 = XLOG2DEVMAC(x1);
1078 wxCoord yy1 = YLOG2DEVMAC(y1);
1079 wxCoord xx2 = XLOG2DEVMAC(x2);
1080 wxCoord yy2 = YLOG2DEVMAC(y2);
1081 wxCoord xxc = XLOG2DEVMAC(xc);
1082 wxCoord yyc = YLOG2DEVMAC(yc);
1083 double dx = xx1 - xxc;
1084 double dy = yy1 - yyc;
1085 double radius = sqrt((double)(dx*dx+dy*dy));
1086 wxCoord rad = (wxCoord)radius;
1087 double radius1, radius2;
1088 if (xx1 == xx2 && yy1 == yy2)
1089 {
1090 radius1 = 0.0;
1091 radius2 = 360.0;
1092 }
1093 else if (radius == 0.0)
1094 {
1095 radius1 = radius2 = 0.0;
1096 }
1097 else
1098 {
1099 radius1 = (xx1 - xxc == 0) ?
1100 (yy1 - yyc < 0) ? 90.0 : -90.0 :
1101 -atan2(double(yy1-yyc), double(xx1-xxc)) * RAD2DEG;
1102 radius2 = (xx2 - xxc == 0) ?
1103 (yy2 - yyc < 0) ? 90.0 : -90.0 :
1104 -atan2(double(yy2-yyc), double(xx2-xxc)) * RAD2DEG;
1105 }
1106 wxCoord alpha2 = wxCoord(radius2 - radius1);
1107 wxCoord alpha1 = wxCoord(wxConvertWXangleToMACangle(radius1));
1108 if( (xx1 > xx2) || (yy1 > yy2) ) {
1109 alpha2 *= -1;
1110 }
1111 Rect r = { yyc - rad, xxc - rad, yyc + rad, xxc + rad };
1112 /*
1113 CGPathDrawingMode mode ;
1114 CGContextRef cgContext = wxBeginCGContext( this , &mode ) ;
1115
1116 AddEllipticArcToPath( cgContext , CGPointMake( xxc , yyc ) , rad , rad , 0 , 180 ) ;
1117
1118 CGContextDrawPath( cgContext , mode ) ;
1119
1120 QDEndCGContext( (CGrafPtr) m_macPort , &cgContext ) ;
1121 */
1122}
1123
1124void wxDC::DoDrawEllipticArc( wxCoord x, wxCoord y, wxCoord w, wxCoord h,
1125 double sa, double ea )
1126{
1127 wxCHECK_RET(Ok(), wxT("wxDC::DoDrawEllepticArc Invalid DC"));
1128 Rect r;
1129 double angle = sa - ea; // Order important Mac in opposite direction to wx
1130 // we have to make sure that the filling is always counter-clockwise
1131 if ( angle > 0 )
1132 angle -= 360 ;
1133 wxCoord xx = XLOG2DEVMAC(x);
1134 wxCoord yy = YLOG2DEVMAC(y);
1135 wxCoord ww = m_signX * XLOG2DEVREL(w);
1136 wxCoord hh = m_signY * YLOG2DEVREL(h);
1137 // handle -ve width and/or height
1138 if (ww < 0) { ww = -ww; xx = xx - ww; }
1139 if (hh < 0) { hh = -hh; yy = yy - hh; }
1140 sa = wxConvertWXangleToMACangle(sa);
1141 /*
1142 CGPathDrawingMode mode ;
1143 CGContextRef cgContext = wxBeginCGContext( this , &mode ) ;
1144
1145 AddEllipticArcToPath( cgContext , CGPointMake( xx + ww / 2 , yy + hh / 2 ) , ww / 2 , hh / 2 , sa , angle) ;
1146
1147 CGContextDrawPath( cgContext , mode ) ;
1148
1149 QDEndCGContext( (CGrafPtr) m_macPort , &cgContext ) ;
1150 */
1151}
1152
1153void wxDC::DoDrawPoint( wxCoord x, wxCoord y )
1154{
1155 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1156 DoDrawLine( x , y , x + 1 , y + 1 ) ;
1157}
1158
1159void wxDC::DoDrawLines(int n, wxPoint points[],
1160 wxCoord xoffset, wxCoord yoffset)
1161{
1162 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1163
1164 wxCoord x1, x2 , y1 , y2 ;
1165 x1 = XLOG2DEVMAC(points[0].x + xoffset);
1166 y1 = YLOG2DEVMAC(points[0].y + yoffset);
1167 wxMacGraphicPath path ;
1168 path.MoveToPoint( x1 , y1 ) ;
1169 for (int i = 1; i < n; i++)
1170 {
1171 x2 = XLOG2DEVMAC(points[i].x + xoffset);
1172 y2 = YLOG2DEVMAC(points[i].y + yoffset);
1173
1174 path.AddLineToPoint( x2 , y2 ) ;
1175 }
1176 path.CloseSubpath() ;
1177 m_macGraphicContext->StrokePath( path ) ;
1178}
1179
1180void wxDC::DoDrawPolygon(int n, wxPoint points[],
1181 wxCoord xoffset, wxCoord yoffset,
1182 int fillStyle )
1183{
1184 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1185 wxCoord x1, x2 , y1 , y2 ;
1186 if ( n== 0 || (m_brush.GetStyle() == wxTRANSPARENT && m_pen.GetStyle() == wxTRANSPARENT ) )
1187 return ;
1188
1189 x2 = x1 = XLOG2DEVMAC(points[0].x + xoffset);
1190 y2 = y1 = YLOG2DEVMAC(points[0].y + yoffset);
1191
1192 wxMacGraphicPath path ;
1193 path.MoveToPoint( x1 , y1 ) ;
1194 for (int i = 1; i < n; i++)
1195 {
1196 x2 = XLOG2DEVMAC(points[i].x + xoffset);
1197 y2 = YLOG2DEVMAC(points[i].y + yoffset);
1198
1199 path.AddLineToPoint( x2 , y2 ) ;
1200 }
1201 if ( x1 != x2 || y1 != y2 )
1202 {
1203 path.AddLineToPoint( x1,y1 ) ;
1204 }
1205 path.CloseSubpath() ;
1206 m_macGraphicContext->DrawPath( path , fillStyle ) ;
1207}
1208
1209void wxDC::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
1210{
1211 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1212 wxCoord xx = XLOG2DEVMAC(x);
1213 wxCoord yy = YLOG2DEVMAC(y);
1214 wxCoord ww = m_signX * XLOG2DEVREL(width);
1215 wxCoord hh = m_signY * YLOG2DEVREL(height);
1216 // CMB: draw nothing if transformed w or h is 0
1217 if (ww == 0 || hh == 0)
1218 return;
1219 // CMB: handle -ve width and/or height
1220 if (ww < 0)
1221 {
1222 ww = -ww;
1223 xx = xx - ww;
1224 }
1225 if (hh < 0)
1226 {
1227 hh = -hh;
1228 yy = yy - hh;
1229 }
1230 wxMacGraphicPath path ;
1231 path.AddRectangle(xx ,yy , ww , hh ) ;
1232 path.CloseSubpath() ;
1233 m_macGraphicContext->DrawPath( path ) ;
1234}
1235
1236void wxDC::DoDrawRoundedRectangle(wxCoord x, wxCoord y,
1237 wxCoord width, wxCoord height,
1238 double radius)
1239{
1240 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1241 if (radius < 0.0)
1242 radius = - radius * ((width < height) ? width : height);
1243 wxCoord xx = XLOG2DEVMAC(x);
1244 wxCoord yy = YLOG2DEVMAC(y);
1245 wxCoord ww = m_signX * XLOG2DEVREL(width);
1246 wxCoord hh = m_signY * YLOG2DEVREL(height);
1247 // CMB: draw nothing if transformed w or h is 0
1248 if (ww == 0 || hh == 0)
1249 return;
1250 // CMB: handle -ve width and/or height
1251 if (ww < 0)
1252 {
1253 ww = -ww;
1254 xx = xx - ww;
1255 }
1256 if (hh < 0)
1257 {
1258 hh = -hh;
1259 yy = yy - hh;
1260 }
1261 Rect rect = { yy , xx , yy + hh , xx + ww } ;
1262 if (m_brush.GetStyle() != wxTRANSPARENT)
1263 {
1264 MacInstallBrush() ;
1265 ::PaintRoundRect( &rect , int(radius * 2) , int(radius * 2) ) ;
1266 }
1267 if (m_pen.GetStyle() != wxTRANSPARENT)
1268 {
1269 MacInstallPen() ;
1270 ::FrameRoundRect( &rect , int(radius * 2) , int(radius * 2) ) ;
1271 }
1272}
1273
1274void wxDC::DoDrawEllipse(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
1275{
1276 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1277 wxCoord xx = XLOG2DEVMAC(x);
1278 wxCoord yy = YLOG2DEVMAC(y);
1279 wxCoord ww = m_signX * XLOG2DEVREL(width);
1280 wxCoord hh = m_signY * YLOG2DEVREL(height);
1281 // CMB: draw nothing if transformed w or h is 0
1282 if (ww == 0 || hh == 0)
1283 return;
1284 // CMB: handle -ve width and/or height
1285 if (ww < 0)
1286 {
1287 ww = -ww;
1288 xx = xx - ww;
1289 }
1290 if (hh < 0)
1291 {
1292 hh = -hh;
1293 yy = yy - hh;
1294 }
1295 CGPoint center = CGPointMake( xx + ww / 2 , yy + hh / 2 ) ;
1296
1297 wxMacGraphicPath path ;
1298 if ( width == height )
1299 path.AddCircle( center , width / 2.0 ) ;
1300 path.CloseSubpath() ;
1301 m_macGraphicContext->DrawPath( path ) ;
1302
1303 /*
1304 CGPathDrawingMode mode ;
1305 CGContextRef cgContext = wxBeginCGContext( this , &mode ) ;
1306
1307 AddEllipticArcToPath( cgContext , CGPointMake( xx + ww / 2 , yy + hh / 2 ) , ww / 2 , hh / 2 , 0 , 360) ;
1308
1309 CGContextDrawPath( cgContext , mode ) ;
1310
1311 QDEndCGContext( (CGrafPtr) m_macPort , &cgContext ) ;
1312 */
1313}
1314
1315bool wxDC::CanDrawBitmap(void) const
1316{
1317 return true ;
1318}
1319
1320bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
1321 wxDC *source, wxCoord xsrc, wxCoord ysrc, int logical_func , bool useMask,
1322 wxCoord xsrcMask, wxCoord ysrcMask )
1323{
1324 wxCHECK_MSG(Ok(), false, wxT("wxDC::DoBlit Illegal dc"));
1325 wxCHECK_MSG(source->Ok(), false, wxT("wxDC::DoBlit Illegal source DC"));
1326 if ( logical_func == wxNO_OP )
1327 return TRUE ;
1328 if (xsrcMask == -1 && ysrcMask == -1)
1329 {
1330 xsrcMask = xsrc; ysrcMask = ysrc;
1331 }
1332 // correct the parameter in case this dc does not have a mask at all
1333 if ( useMask && !source->m_macMask )
1334 useMask = false ;
1335 Rect srcrect , dstrect ;
1336 srcrect.top = source->YLOG2DEVMAC(ysrc) ;
1337 srcrect.left = source->XLOG2DEVMAC(xsrc) ;
1338 srcrect.right = source->XLOG2DEVMAC(xsrc + width ) ;
1339 srcrect.bottom = source->YLOG2DEVMAC(ysrc + height) ;
1340 dstrect.top = YLOG2DEVMAC(ydest) ;
1341 dstrect.left = XLOG2DEVMAC(xdest) ;
1342 dstrect.bottom = YLOG2DEVMAC(ydest + height ) ;
1343 dstrect.right = XLOG2DEVMAC(xdest + width ) ;
1344 short mode = kUnsupportedMode ;
1345 bool invertDestinationFirst = false ;
1346 switch ( logical_func )
1347 {
1348 case wxAND: // src AND dst
1349 mode = adMin ; // ok
1350 break ;
1351 case wxAND_INVERT: // (NOT src) AND dst
1352 mode = notSrcOr ; // ok
1353 break ;
1354 case wxAND_REVERSE:// src AND (NOT dst)
1355 invertDestinationFirst = true ;
1356 mode = srcOr ;
1357 break ;
1358 case wxCLEAR: // 0
1359 mode = kEmulatedMode ;
1360 break ;
1361 case wxCOPY: // src
1362 mode = srcCopy ; // ok
1363 break ;
1364 case wxEQUIV: // (NOT src) XOR dst
1365 mode = srcXor ; // ok
1366 break ;
1367 case wxINVERT: // NOT dst
1368 mode = kEmulatedMode ; //or hilite ;
1369 break ;
1370 case wxNAND: // (NOT src) OR (NOT dst)
1371 invertDestinationFirst = true ;
1372 mode = srcBic ;
1373 break ;
1374 case wxNOR: // (NOT src) AND (NOT dst)
1375 invertDestinationFirst = true ;
1376 mode = notSrcOr ;
1377 break ;
1378 case wxNO_OP: // dst
1379 mode = kEmulatedMode ; // this has already been handled upon entry
1380 break ;
1381 case wxOR: // src OR dst
1382 mode = notSrcBic ;
1383 break ;
1384 case wxOR_INVERT: // (NOT src) OR dst
1385 mode = srcBic ;
1386 break ;
1387 case wxOR_REVERSE: // src OR (NOT dst)
1388 invertDestinationFirst = true ;
1389 mode = notSrcBic ;
1390 break ;
1391 case wxSET: // 1
1392 mode = kEmulatedMode ;
1393 break ;
1394 case wxSRC_INVERT: // (NOT src)
1395 mode = notSrcCopy ; // ok
1396 break ;
1397 case wxXOR: // src XOR dst
1398 mode = notSrcXor ; // ok
1399 break ;
1400 default :
1401 break ;
1402 }
1403 if ( mode == kUnsupportedMode )
1404 {
1405 wxFAIL_MSG(wxT("unsupported blitting mode" ));
1406 return FALSE ;
1407 }
1408 CGrafPtr sourcePort = (CGrafPtr) source->m_macPort ;
1409 PixMapHandle bmappixels = GetGWorldPixMap( sourcePort ) ;
1410 if ( LockPixels(bmappixels) )
1411 {
1412 if ( source->GetDepth() == 1 )
1413 {
1414 RGBForeColor( &MAC_WXCOLORREF(m_textForegroundColour.GetPixel()) ) ;
1415 RGBBackColor( &MAC_WXCOLORREF(m_textBackgroundColour.GetPixel()) ) ;
1416 }
1417 else
1418 {
1419 // the modes need this, otherwise we'll end up having really nice colors...
1420 RGBColor white = { 0xFFFF, 0xFFFF,0xFFFF} ;
1421 RGBColor black = { 0,0,0} ;
1422 RGBForeColor( &black ) ;
1423 RGBBackColor( &white ) ;
1424 }
1425 if ( useMask && source->m_macMask )
1426 {
1427 if ( mode == srcCopy )
1428 {
1429 if ( LockPixels( GetGWorldPixMap( MAC_WXHBITMAP(source->m_macMask) ) ) )
1430 {
1431 CopyMask( GetPortBitMapForCopyBits( sourcePort ) ,
1432 GetPortBitMapForCopyBits( MAC_WXHBITMAP(source->m_macMask) ) ,
1433 GetPortBitMapForCopyBits( MAC_WXHBITMAP(m_macPort) ) ,
1434 &srcrect, &srcrect , &dstrect ) ;
1435 UnlockPixels( GetGWorldPixMap( MAC_WXHBITMAP(source->m_macMask) ) ) ;
1436 }
1437 }
1438 else
1439 {
1440 RgnHandle clipRgn = NewRgn() ;
1441 LockPixels( GetGWorldPixMap( MAC_WXHBITMAP(source->m_macMask) ) ) ;
1442 BitMapToRegion( clipRgn , (BitMap*) *GetGWorldPixMap( MAC_WXHBITMAP(source->m_macMask) ) ) ;
1443 UnlockPixels( GetGWorldPixMap( MAC_WXHBITMAP(source->m_macMask) ) ) ;
1444 OffsetRgn( clipRgn , -srcrect.left + dstrect.left, -srcrect.top + dstrect.top ) ;
1445 if ( mode == kEmulatedMode )
1446 {
1447 Pattern pat ;
1448 ::PenPat(GetQDGlobalsBlack(&pat));
1449 if ( logical_func == wxSET )
1450 {
1451 RGBColor col= { 0xFFFF, 0xFFFF, 0xFFFF } ;
1452 ::RGBForeColor( &col ) ;
1453 ::PaintRgn( clipRgn ) ;
1454 }
1455 else if ( logical_func == wxCLEAR )
1456 {
1457 RGBColor col= { 0x0000, 0x0000, 0x0000 } ;
1458 ::RGBForeColor( &col ) ;
1459 ::PaintRgn( clipRgn ) ;
1460 }
1461 else if ( logical_func == wxINVERT )
1462 {
1463 MacInvertRgn( clipRgn ) ;
1464 }
1465 else
1466 {
1467 for ( int y = 0 ; y < srcrect.right - srcrect.left ; ++y )
1468 {
1469 for ( int x = 0 ; x < srcrect.bottom - srcrect.top ; ++x )
1470 {
1471 Point dstPoint = { dstrect.top + y , dstrect.left + x } ;
1472 Point srcPoint = { srcrect.top + y , srcrect.left + x } ;
1473 if ( PtInRgn( dstPoint , clipRgn ) )
1474 {
1475 RGBColor srcColor ;
1476 RGBColor dstColor ;
1477 SetPort( (GrafPtr) sourcePort ) ;
1478 GetCPixel( srcPoint.h , srcPoint.v , &srcColor) ;
1479 SetPort( (GrafPtr) m_macPort ) ;
1480 GetCPixel( dstPoint.h , dstPoint.v , &dstColor ) ;
1481 wxMacCalculateColour( logical_func , srcColor , dstColor ) ;
1482 SetCPixel( dstPoint.h , dstPoint.v , &dstColor ) ;
1483 }
1484 }
1485 }
1486 }
1487 }
1488 else
1489 {
1490 if ( invertDestinationFirst )
1491 {
1492 MacInvertRgn( clipRgn ) ;
1493 }
1494 CopyBits( GetPortBitMapForCopyBits( sourcePort ) ,
1495 GetPortBitMapForCopyBits( MAC_WXHBITMAP(m_macPort) ) ,
1496 &srcrect, &dstrect, mode, clipRgn ) ;
1497 }
1498 DisposeRgn( clipRgn ) ;
1499 }
1500 }
1501 else
1502 {
1503 RgnHandle clipRgn = NewRgn() ;
1504 SetRectRgn( clipRgn , dstrect.left , dstrect.top , dstrect.right , dstrect.bottom ) ;
1505 if ( mode == kEmulatedMode )
1506 {
1507 Pattern pat ;
1508 ::PenPat(GetQDGlobalsBlack(&pat));
1509 if ( logical_func == wxSET )
1510 {
1511 RGBColor col= { 0xFFFF, 0xFFFF, 0xFFFF } ;
1512 ::RGBForeColor( &col ) ;
1513 ::PaintRgn( clipRgn ) ;
1514 }
1515 else if ( logical_func == wxCLEAR )
1516 {
1517 RGBColor col= { 0x0000, 0x0000, 0x0000 } ;
1518 ::RGBForeColor( &col ) ;
1519 ::PaintRgn( clipRgn ) ;
1520 }
1521 else if ( logical_func == wxINVERT )
1522 {
1523 MacInvertRgn( clipRgn ) ;
1524 }
1525 else
1526 {
1527 for ( int y = 0 ; y < srcrect.right - srcrect.left ; ++y )
1528 {
1529 for ( int x = 0 ; x < srcrect.bottom - srcrect.top ; ++x )
1530 {
1531 Point dstPoint = { dstrect.top + y , dstrect.left + x } ;
1532 Point srcPoint = { srcrect.top + y , srcrect.left + x } ;
1533 {
1534 RGBColor srcColor ;
1535 RGBColor dstColor ;
1536 SetPort( (GrafPtr) sourcePort ) ;
1537 GetCPixel( srcPoint.h , srcPoint.v , &srcColor) ;
1538 SetPort( (GrafPtr) m_macPort ) ;
1539 GetCPixel( dstPoint.h , dstPoint.v , &dstColor ) ;
1540 wxMacCalculateColour( logical_func , srcColor , dstColor ) ;
1541 SetCPixel( dstPoint.h , dstPoint.v , &dstColor ) ;
1542 }
1543 }
1544 }
1545 }
1546 }
1547 else
1548 {
1549 if ( invertDestinationFirst )
1550 {
1551 MacInvertRgn( clipRgn ) ;
1552 }
1553 CopyBits( GetPortBitMapForCopyBits( sourcePort ) ,
1554 GetPortBitMapForCopyBits( MAC_WXHBITMAP(m_macPort) ) ,
1555 &srcrect, &dstrect, mode, NULL ) ;
1556 }
1557 DisposeRgn( clipRgn ) ;
1558 }
1559 UnlockPixels( bmappixels ) ;
1560 }
1561 m_macPenInstalled = false ;
1562 m_macBrushInstalled = false ;
1563 m_macFontInstalled = false ;
1564 return TRUE;
1565}
1566
1567#ifndef FixedToInt
1568// as macro in FixMath.h for 10.3
1569inline Fixed IntToFixed( int inInt )
1570{
1571 return (((SInt32) inInt) << 16);
1572}
1573
1574inline int FixedToInt( Fixed inFixed )
1575{
1576 return (((SInt32) inFixed) >> 16);
1577}
1578#endif
1579
1580void wxDC::DoDrawRotatedText(const wxString& str, wxCoord x, wxCoord y,
1581 double angle)
1582{
1583 wxCHECK_RET( Ok(), wxT("wxDC::DoDrawRotatedText Invalid window dc") );
1584
1585 if ( str.Length() == 0 )
1586 return ;
1587
1588 OSStatus status = noErr ;
1589 ATSUTextLayout atsuLayout ;
1590 UniCharCount chars = str.Length() ;
1591 UniChar* ubuf = NULL ;
1592#if SIZEOF_WCHAR_T == 4
1593 wxMBConvUTF16BE converter ;
1594#if wxUSE_UNICODE
1595 size_t unicharlen = converter.WC2MB( NULL , str.wc_str() , 0 ) ;
1596 ubuf = (UniChar*) malloc( unicharlen + 2 ) ;
1597 converter.WC2MB( (char*) ubuf , str.wc_str(), unicharlen + 2 ) ;
1598#else
1599 const wxWCharBuffer wchar = str.wc_str( wxConvLocal ) ;
1600 size_t unicharlen = converter.WC2MB( NULL , wchar.data() , 0 ) ;
1601 ubuf = (UniChar*) malloc( unicharlen + 2 ) ;
1602 converter.WC2MB( (char*) ubuf , wchar.data() , unicharlen + 2 ) ;
1603#endif
1604 chars = unicharlen / 2 ;
1605#else
1606#if wxUSE_UNICODE
1607 ubuf = (UniChar*) str.wc_str() ;
1608#else
1609 wxWCharBuffer wchar = str.wc_str( wxConvLocal ) ;
1610 chars = wxWcslen( wchar.data() ) ;
1611 ubuf = (UniChar*) wchar.data() ;
1612#endif
1613#endif
1614
1615 int drawX = XLOG2DEVMAC(x) ;
1616 int drawY = YLOG2DEVMAC(y) ;
1617
1618 MacInstallFont() ;
1619
1620 status = ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr) ubuf , 0 , chars , chars , 1 ,
1621 &chars , (ATSUStyle*) &m_macATSUIStyle , &atsuLayout ) ;
1622
1623 wxASSERT_MSG( status == noErr , wxT("couldn't create the layout of the rotated text") );
1624 int iAngle = int( angle );
1625
1626
1627
1628 CGContextSaveGState(m_macGraphicContext->GetNativeContext());
1629 if ( abs(iAngle) > 0 )
1630 {
1631 Fixed atsuAngle = IntToFixed( iAngle ) ;
1632 ATSUAttributeTag atsuTags[] =
1633 {
1634 kATSULineRotationTag ,
1635 } ;
1636 ByteCount atsuSizes[sizeof(atsuTags)/sizeof(ATSUAttributeTag)] =
1637 {
1638 sizeof( Fixed ) ,
1639 } ;
1640 ATSUAttributeValuePtr atsuValues[sizeof(atsuTags)/sizeof(ATSUAttributeTag)] =
1641 {
1642 &atsuAngle ,
1643 } ;
1644 status = ::ATSUSetLayoutControls(atsuLayout , sizeof(atsuTags)/sizeof(ATSUAttributeTag),
1645 atsuTags, atsuSizes, atsuValues ) ;
1646 }
1647 {
1648 CGContextRef cgContext = m_macGraphicContext->GetNativeContext() ;
1649 ATSUAttributeTag atsuTags[] =
1650 {
1651 kATSUCGContextTag ,
1652 } ;
1653 ByteCount atsuSizes[sizeof(atsuTags)/sizeof(ATSUAttributeTag)] =
1654 {
1655 sizeof( CGContextRef ) ,
1656 } ;
1657 ATSUAttributeValuePtr atsuValues[sizeof(atsuTags)/sizeof(ATSUAttributeTag)] =
1658 {
1659 &cgContext ,
1660 } ;
1661 status = ::ATSUSetLayoutControls(atsuLayout , sizeof(atsuTags)/sizeof(ATSUAttributeTag),
1662 atsuTags, atsuSizes, atsuValues ) ;
1663 }
1664
1665 ATSUTextMeasurement textBefore ;
1666 ATSUTextMeasurement textAfter ;
1667 ATSUTextMeasurement ascent ;
1668 ATSUTextMeasurement descent ;
1669
1670 status = ::ATSUGetUnjustifiedBounds( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd,
1671 &textBefore , &textAfter, &ascent , &descent );
1672 wxASSERT_MSG( status == noErr , wxT("couldn't measure the rotated text") );
1673
1674 Rect rect ;
1675
1676 if ( m_backgroundMode == wxSOLID )
1677 {
1678 wxMacGraphicPath path ;
1679 path.MoveToPoint(
1680 drawX ,
1681 drawY ) ;
1682 path.AddLineToPoint(
1683 drawX + sin(angle/RAD2DEG) * FixedToInt(ascent + descent) ,
1684 drawY + cos(angle/RAD2DEG) * FixedToInt(ascent + descent) ) ;
1685 path.AddLineToPoint(
1686 drawX + sin(angle/RAD2DEG) * FixedToInt(ascent + descent ) + cos(angle/RAD2DEG) * FixedToInt(textAfter) ,
1687 drawY + cos(angle/RAD2DEG) * FixedToInt(ascent + descent) - sin(angle/RAD2DEG) * FixedToInt(textAfter) ) ;
1688 path.AddLineToPoint(
1689 drawX + cos(angle/RAD2DEG) * FixedToInt(textAfter) ,
1690 drawY - sin(angle/RAD2DEG) * FixedToInt(textAfter) ) ;
1691
1692 m_macGraphicContext->FillPath( path , m_textBackgroundColour ) ;
1693 }
1694
1695 drawX += (int)(sin(angle/RAD2DEG) * FixedToInt(ascent));
1696 drawY += (int)(cos(angle/RAD2DEG) * FixedToInt(ascent));
1697 status = ::ATSUMeasureTextImage( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd,
1698 IntToFixed(drawX) , IntToFixed(drawY) , &rect );
1699 wxASSERT_MSG( status == noErr , wxT("couldn't measure the rotated text") );
1700
1701 CGContextTranslateCTM(m_macGraphicContext->GetNativeContext(), drawX, drawY);
1702 CGContextScaleCTM(m_macGraphicContext->GetNativeContext(), 1, -1);
1703 status = ::ATSUDrawText( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd,
1704 IntToFixed(0) , IntToFixed(0) );
1705 wxASSERT_MSG( status == noErr , wxT("couldn't draw the rotated text") );
1706
1707 CalcBoundingBox(XDEV2LOG(rect.left), YDEV2LOG(rect.top) );
1708 CalcBoundingBox(XDEV2LOG(rect.right), YDEV2LOG(rect.bottom) );
1709
1710 ::ATSUDisposeTextLayout(atsuLayout);
1711#if SIZEOF_WCHAR_T == 4
1712 free( ubuf ) ;
1713#endif
1714 CGContextRestoreGState( m_macGraphicContext->GetNativeContext() ) ;
1715}
1716
1717void wxDC::DoDrawText(const wxString& strtext, wxCoord x, wxCoord y)
1718{
1719 wxCHECK_RET(Ok(), wxT("wxDC::DoDrawText Invalid DC"));
1720 DoDrawRotatedText( strtext , x , y , 0.0 ) ;
1721}
1722
1723bool wxDC::CanGetTextExtent() const
1724{
1725 wxCHECK_MSG(Ok(), false, wxT("Invalid DC"));
1726 return true ;
1727}
1728
1729void wxDC::DoGetTextExtent( const wxString &str, wxCoord *width, wxCoord *height,
1730 wxCoord *descent, wxCoord *externalLeading ,
1731 wxFont *theFont ) const
1732{
1733 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1734 wxFont formerFont = m_font ;
1735 if ( theFont )
1736 {
1737 // work around the constness
1738 *((wxFont*)(&m_font)) = *theFont ;
1739 }
1740
1741
1742 if ( str.Length() == 0 )
1743 return ;
1744
1745 OSStatus status = noErr ;
1746 ATSUTextLayout atsuLayout ;
1747 UniCharCount chars = str.Length() ;
1748 UniChar* ubuf = NULL ;
1749#if SIZEOF_WCHAR_T == 4
1750 wxMBConvUTF16BE converter ;
1751#if wxUSE_UNICODE
1752 size_t unicharlen = converter.WC2MB( NULL , str.wc_str() , 0 ) ;
1753 ubuf = (UniChar*) malloc( unicharlen + 2 ) ;
1754 converter.WC2MB( (char*) ubuf , str.wc_str(), unicharlen + 2 ) ;
1755#else
1756 const wxWCharBuffer wchar = str.wc_str( wxConvLocal ) ;
1757 size_t unicharlen = converter.WC2MB( NULL , wchar.data() , 0 ) ;
1758 ubuf = (UniChar*) malloc( unicharlen + 2 ) ;
1759 converter.WC2MB( (char*) ubuf , wchar.data() , unicharlen + 2 ) ;
1760#endif
1761 chars = unicharlen / 2 ;
1762#else
1763#if wxUSE_UNICODE
1764 ubuf = (UniChar*) str.wc_str() ;
1765#else
1766 wxWCharBuffer wchar = str.wc_str( wxConvLocal ) ;
1767 chars = wxWcslen( wchar.data() ) ;
1768 ubuf = (UniChar*) wchar.data() ;
1769#endif
1770#endif
1771
1772 MacInstallFont() ;
1773
1774 status = ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr) ubuf , 0 , chars , chars , 1 ,
1775 &chars , (ATSUStyle*) &m_macATSUIStyle , &atsuLayout ) ;
1776
1777 wxASSERT_MSG( status == noErr , wxT("couldn't create the layout of the text") );
1778
1779 ATSUTextMeasurement textBefore ;
1780 ATSUTextMeasurement textAfter ;
1781 ATSUTextMeasurement textAscent ;
1782 ATSUTextMeasurement textDescent ;
1783
1784 status = ::ATSUGetUnjustifiedBounds( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd,
1785 &textBefore , &textAfter, &textAscent , &textDescent );
1786
1787 if ( height )
1788 *height = YDEV2LOGREL( FixedToInt(textAscent + textDescent) ) ;
1789 if ( descent )
1790 *descent =YDEV2LOGREL( FixedToInt(textDescent) );
1791 if ( externalLeading )
1792 *externalLeading = 0 ;
1793 if ( width )
1794 *width = XDEV2LOGREL( FixedToInt(textAfter - textBefore) ) ;
1795
1796 ::ATSUDisposeTextLayout(atsuLayout);
1797#if SIZEOF_WCHAR_T == 4
1798 free( ubuf ) ;
1799#endif
1800 if ( theFont )
1801 {
1802 // work around the constness
1803 *((wxFont*)(&m_font)) = formerFont ;
1804 m_macFontInstalled = false ;
1805 }
1806}
1807
1808
1809bool wxDC::DoGetPartialTextExtents(const wxString& text, wxArrayInt& widths) const
1810{
1811 wxCHECK_MSG(Ok(), false, wxT("Invalid DC"));
1812
1813 widths.Empty();
1814 widths.Add(0, text.Length());
1815
1816 if (text.Length() == 0)
1817 return false;
1818
1819 MacInstallFont() ;
1820#if TARGET_CARBON
1821 bool useGetThemeText = ( GetThemeTextDimensions != (void*) kUnresolvedCFragSymbolAddress ) ;
1822 if ( UMAGetSystemVersion() < 0x1000 || IsKindOf(CLASSINFO( wxPrinterDC ) ) || ((wxFont*)&m_font)->GetNoAntiAliasing() )
1823 useGetThemeText = false ;
1824
1825 if ( useGetThemeText )
1826 {
1827 // If anybody knows how to do this more efficiently yet still handle
1828 // the fractional glyph widths that may be present when using AA
1829 // fonts, please change it. Currently it is measuring from the
1830 // begining of the string for each succeding substring, which is much
1831 // slower than this should be.
1832 for (size_t i=0; i<text.Length(); i++)
1833 {
1834 wxString str(text.Left(i+1));
1835 Point bounds = {0,0};
1836 SInt16 baseline ;
1837 wxMacCFStringHolder mString(str, m_font.GetEncoding());
1838 ::GetThemeTextDimensions( mString,
1839 kThemeCurrentPortFont,
1840 kThemeStateActive,
1841 false,
1842 &bounds,
1843 &baseline );
1844 widths[i] = XDEV2LOGREL(bounds.h);
1845 }
1846 }
1847 else
1848#endif
1849 {
1850 wxCharBuffer buff = text.mb_str(wxConvLocal);
1851 size_t len = strlen(buff);
1852 short* measurements = new short[len+1];
1853 MeasureText(len, buff.data(), measurements);
1854
1855 // Copy to widths, starting at measurements[1]
1856 // NOTE: this doesn't take into account any multi-byte characters
1857 // in buff, it probabkly should...
1858 for (size_t i=0; i<text.Length(); i++)
1859 widths[i] = XDEV2LOGREL(measurements[i+1]);
1860
1861 delete [] measurements;
1862 }
1863
1864 return true;
1865}
1866
1867
1868
1869wxCoord wxDC::GetCharWidth(void) const
1870{
1871 wxCoord width ;
1872 DoGetTextExtent(wxT("g") , &width , NULL , NULL , NULL , NULL ) ;
1873 return width ;
1874}
1875
1876wxCoord wxDC::GetCharHeight(void) const
1877{
1878 wxCoord height ;
1879 DoGetTextExtent(wxT("g") , NULL , &height , NULL , NULL , NULL ) ;
1880 return height ;
1881}
1882
1883void wxDC::Clear(void)
1884{
1885 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1886
1887 if ( m_backgroundBrush.Ok() && m_backgroundBrush.GetStyle() != wxTRANSPARENT)
1888 {
1889 HIRect rect = CGRectMake( -10000 , -10000 , 20000 , 20000 ) ;
1890 switch( m_backgroundBrush.MacGetBrushKind() )
1891 {
1892 case kwxMacBrushTheme :
1893 {
1894 }
1895 break ;
1896 case kwxMacBrushThemeBackground :
1897 {
1898 HIThemeBackgroundDrawInfo drawInfo ;
1899 drawInfo.version = 0 ;
1900 drawInfo.state = kThemeStateActive ;
1901 drawInfo.kind = m_backgroundBrush.MacGetThemeBackground(NULL) ;
1902 HIThemeDrawBackground( &rect , &drawInfo, m_macGraphicContext->GetNativeContext() ,
1903 kHIThemeOrientationNormal) ;
1904
1905 }
1906 break ;
1907 case kwxMacBrushColour :
1908 {
1909 RGBColor col = MAC_WXCOLORREF( m_backgroundBrush.GetColour().GetPixel()) ;
1910 CGContextSetRGBFillColor( m_macGraphicContext->GetNativeContext() , col.red / 65536.0 , col.green / 65536.0 , col.blue / 65536.0 , 1.0 ) ;
1911 CGContextFillRect(m_macGraphicContext->GetNativeContext(), rect);
1912
1913 // reset to normal value
1914 col = MAC_WXCOLORREF( GetBrush().GetColour().GetPixel() ) ;
1915 CGContextSetRGBFillColor( m_macGraphicContext->GetNativeContext() , col.red / 65536.0 , col.green / 65536.0 , col.blue / 65536.0 , 1.0 ) ;
1916 }
1917 break ;
1918 }
1919 }
1920}
1921
1922void wxDC::MacInstallFont() const
1923{
1924 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1925
1926/*
1927 // if ( m_macFontInstalled )
1928 // return ;
1929 Pattern blackColor ;
1930 MacSetupBackgroundForCurrentPort(m_backgroundBrush) ;
1931 if ( m_font.Ok() )
1932 {
1933 ::TextFont( m_font.MacGetFontNum() ) ;
1934 ::TextSize( (short)(m_scaleY * m_font.MacGetFontSize()) ) ;
1935 ::TextFace( m_font.MacGetFontStyle() ) ;
1936 m_macFontInstalled = true ;
1937 m_macBrushInstalled = false ;
1938 m_macPenInstalled = false ;
1939 RGBColor forecolor = MAC_WXCOLORREF( m_textForegroundColour.GetPixel());
1940 RGBColor backcolor = MAC_WXCOLORREF( m_textBackgroundColour.GetPixel());
1941 ::RGBForeColor( &forecolor );
1942 ::RGBBackColor( &backcolor );
1943 }
1944 else
1945 {
1946 FontFamilyID fontId ;
1947 Str255 fontName ;
1948 SInt16 fontSize ;
1949 Style fontStyle ;
1950 GetThemeFont(kThemeSmallSystemFont , GetApplicationScript() , fontName , &fontSize , &fontStyle ) ;
1951 GetFNum( fontName, &fontId );
1952 ::TextFont( fontId ) ;
1953 ::TextSize( short(m_scaleY * fontSize) ) ;
1954 ::TextFace( fontStyle ) ;
1955 // todo reset after spacing changes - or store the current spacing somewhere
1956 m_macFontInstalled = true ;
1957 m_macBrushInstalled = false ;
1958 m_macPenInstalled = false ;
1959 RGBColor forecolor = MAC_WXCOLORREF( m_textForegroundColour.GetPixel());
1960 RGBColor backcolor = MAC_WXCOLORREF( m_textBackgroundColour.GetPixel());
1961 ::RGBForeColor( &forecolor );
1962 ::RGBBackColor( &backcolor );
1963 }
1964 short mode = patCopy ;
1965 // todo :
1966 switch( m_logicalFunction )
1967 {
1968 case wxCOPY: // src
1969 mode = patCopy ;
1970 break ;
1971 case wxINVERT: // NOT dst
1972 ::PenPat(GetQDGlobalsBlack(&blackColor));
1973 mode = patXor ;
1974 break ;
1975 case wxXOR: // src XOR dst
1976 mode = patXor ;
1977 break ;
1978 case wxOR_REVERSE: // src OR (NOT dst)
1979 mode = notPatOr ;
1980 break ;
1981 case wxSRC_INVERT: // (NOT src)
1982 mode = notPatCopy ;
1983 break ;
1984 case wxAND: // src AND dst
1985 mode = adMin ;
1986 break ;
1987 // unsupported TODO
1988 case wxCLEAR: // 0
1989 case wxAND_REVERSE:// src AND (NOT dst)
1990 case wxAND_INVERT: // (NOT src) AND dst
1991 case wxNO_OP: // dst
1992 case wxNOR: // (NOT src) AND (NOT dst)
1993 case wxEQUIV: // (NOT src) XOR dst
1994 case wxOR_INVERT: // (NOT src) OR dst
1995 case wxNAND: // (NOT src) OR (NOT dst)
1996 case wxOR: // src OR dst
1997 case wxSET: // 1
1998 // case wxSRC_OR: // source _bitmap_ OR destination
1999 // case wxSRC_AND: // source _bitmap_ AND destination
2000 break ;
2001 }
2002 ::PenMode( mode ) ;
2003*/
2004 OSStatus status = noErr ;
2005 Fixed atsuSize = IntToFixed( int(m_scaleY * m_font.MacGetFontSize()) ) ;
2006 Style qdStyle = m_font.MacGetFontStyle() ;
2007 ATSUFontID atsuFont = m_font.MacGetATSUFontID() ;
2008 status = ::ATSUCreateStyle((ATSUStyle *)&m_macATSUIStyle) ;
2009 wxASSERT_MSG( status == noErr , wxT("couldn't create ATSU style") ) ;
2010 ATSUAttributeTag atsuTags[] =
2011 {
2012 kATSUFontTag ,
2013 kATSUSizeTag ,
2014 kATSUColorTag ,
2015 // kATSUBaselineClassTag ,
2016 kATSUVerticalCharacterTag,
2017 kATSUQDBoldfaceTag ,
2018 kATSUQDItalicTag ,
2019 kATSUQDUnderlineTag ,
2020 kATSUQDCondensedTag ,
2021 kATSUQDExtendedTag ,
2022 } ;
2023 ByteCount atsuSizes[sizeof(atsuTags)/sizeof(ATSUAttributeTag)] =
2024 {
2025 sizeof( ATSUFontID ) ,
2026 sizeof( Fixed ) ,
2027 sizeof( RGBColor ) ,
2028 // sizeof( BslnBaselineClass ) ,
2029 sizeof( ATSUVerticalCharacterType),
2030 sizeof( Boolean ) ,
2031 sizeof( Boolean ) ,
2032 sizeof( Boolean ) ,
2033 sizeof( Boolean ) ,
2034 sizeof( Boolean ) ,
2035 } ;
2036 Boolean kTrue = true ;
2037 Boolean kFalse = false ;
2038 //BslnBaselineClass kBaselineDefault = kBSLNHangingBaseline ;
2039 ATSUVerticalCharacterType kHorizontal = kATSUStronglyHorizontal;
2040 ATSUAttributeValuePtr atsuValues[sizeof(atsuTags)/sizeof(ATSUAttributeTag)] =
2041 {
2042 &atsuFont ,
2043 &atsuSize ,
2044 &MAC_WXCOLORREF( m_textForegroundColour.GetPixel() ) ,
2045 // &kBaselineDefault ,
2046 &kHorizontal,
2047 (qdStyle & bold) ? &kTrue : &kFalse ,
2048 (qdStyle & italic) ? &kTrue : &kFalse ,
2049 (qdStyle & underline) ? &kTrue : &kFalse ,
2050 (qdStyle & condense) ? &kTrue : &kFalse ,
2051 (qdStyle & extend) ? &kTrue : &kFalse ,
2052 } ;
2053 status = ::ATSUSetAttributes((ATSUStyle)m_macATSUIStyle, sizeof(atsuTags)/sizeof(ATSUAttributeTag) ,
2054 atsuTags, atsuSizes, atsuValues);
2055 wxASSERT_MSG( status == noErr , wxT("couldn't set create ATSU style") ) ;
2056}
2057
2058Pattern gPatterns[] =
2059{ // hatch patterns
2060 { { 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF } } ,
2061 { { 0x01 , 0x02 , 0x04 , 0x08 , 0x10 , 0x20 , 0x40 , 0x80 } } ,
2062 { { 0x80 , 0x40 , 0x20 , 0x10 , 0x08 , 0x04 , 0x02 , 0x01 } } ,
2063 { { 0x10 , 0x10 , 0x10 , 0xFF , 0x10 , 0x10 , 0x10 , 0x10 } } ,
2064 { { 0x00 , 0x00 , 0x00 , 0xFF , 0x00 , 0x00 , 0x00 , 0x00 } } ,
2065 { { 0x10 , 0x10 , 0x10 , 0x10 , 0x10 , 0x10 , 0x10 , 0x10 } } ,
2066 { { 0x81 , 0x42 , 0x24 , 0x18 , 0x18 , 0x24 , 0x42 , 0x81 } } ,
2067 // dash patterns
2068 { { 0xCC , 0x99 , 0x33 , 0x66 , 0xCC , 0x99 , 0x33 , 0x66 } } , // DOT
2069 { { 0xFE , 0xFD , 0xFB , 0xF7 , 0xEF , 0xDF , 0xBF , 0x7F } } , // LONG_DASH
2070 { { 0xEE , 0xDD , 0xBB , 0x77 , 0xEE , 0xDD , 0xBB , 0x77 } } , // SHORT_DASH
2071 { { 0xDE , 0xBD , 0x7B , 0xF6 , 0xED , 0xDB , 0xB7 , 0x6F } } , // DOT_DASH
2072} ;
2073
2074static void wxMacGetPattern(int penStyle, Pattern *pattern)
2075{
2076 int index = 0; // solid pattern by default
2077 switch(penStyle)
2078 {
2079 // hatches
2080 case wxBDIAGONAL_HATCH: index = 1; break;
2081 case wxFDIAGONAL_HATCH: index = 2; break;
2082 case wxCROSS_HATCH: index = 3; break;
2083 case wxHORIZONTAL_HATCH: index = 4; break;
2084 case wxVERTICAL_HATCH: index = 5; break;
2085 case wxCROSSDIAG_HATCH: index = 6; break;
2086 // dashes
2087 case wxDOT: index = 7; break;
2088 case wxLONG_DASH: index = 8; break;
2089 case wxSHORT_DASH: index = 9; break;
2090 case wxDOT_DASH: index = 10; break;
2091 }
2092 *pattern = gPatterns[index];
2093}
2094
2095void wxDC::MacInstallPen() const
2096{
2097/*
2098 wxCHECK_RET(Ok(), wxT("Invalid DC"));
2099 //Pattern blackColor;
2100 // if ( m_macPenInstalled )
2101 // return ;
2102 RGBColor forecolor = MAC_WXCOLORREF( m_pen.GetColour().GetPixel());
2103 RGBColor backcolor = MAC_WXCOLORREF( m_backgroundBrush.GetColour().GetPixel());
2104 ::RGBForeColor( &forecolor );
2105 ::RGBBackColor( &backcolor );
2106 ::PenNormal() ;
2107 int penWidth = (int) (m_pen.GetWidth() * m_scaleX) ; ;
2108 // null means only one pixel, at whatever resolution
2109 if ( penWidth == 0 )
2110 penWidth = 1 ;
2111 ::PenSize(penWidth, penWidth);
2112
2113 int penStyle = m_pen.GetStyle();
2114 Pattern pat;
2115 if (penStyle == wxUSER_DASH)
2116 {
2117 // FIXME: there should be exactly 8 items in the dash
2118 wxDash* dash ;
2119 int number = m_pen.GetDashes(&dash) ;
2120 int index = 0;
2121 for ( int i = 0 ; i < 8 ; ++i )
2122 {
2123 pat.pat[i] = dash[index] ;
2124 if (index < number - 1)
2125 index++;
2126 }
2127 }
2128 else
2129 {
2130 wxMacGetPattern(penStyle, &pat);
2131 }
2132 ::PenPat(&pat);
2133
2134 short mode = patCopy ;
2135 // todo :
2136 switch( m_logicalFunction )
2137 {
2138 case wxCOPY: // only foreground color, leave background (thus not patCopy)
2139 mode = patOr ;
2140 break ;
2141 case wxINVERT: // NOT dst
2142 // ::PenPat(GetQDGlobalsBlack(&blackColor));
2143 mode = patXor ;
2144 break ;
2145 case wxXOR: // src XOR dst
2146 mode = patXor ;
2147 break ;
2148 case wxOR_REVERSE: // src OR (NOT dst)
2149 mode = notPatOr ;
2150 break ;
2151 case wxSRC_INVERT: // (NOT src)
2152 mode = notPatCopy ;
2153 break ;
2154 case wxAND: // src AND dst
2155 mode = adMin ;
2156 break ;
2157 // unsupported TODO
2158 case wxCLEAR: // 0
2159 case wxAND_REVERSE:// src AND (NOT dst)
2160 case wxAND_INVERT: // (NOT src) AND dst
2161 case wxNO_OP: // dst
2162 case wxNOR: // (NOT src) AND (NOT dst)
2163 case wxEQUIV: // (NOT src) XOR dst
2164 case wxOR_INVERT: // (NOT src) OR dst
2165 case wxNAND: // (NOT src) OR (NOT dst)
2166 case wxOR: // src OR dst
2167 case wxSET: // 1
2168 // case wxSRC_OR: // source _bitmap_ OR destination
2169 // case wxSRC_AND: // source _bitmap_ AND destination
2170 break ;
2171 }
2172 ::PenMode( mode ) ;
2173 m_macPenInstalled = true ;
2174 m_macBrushInstalled = false ;
2175 m_macFontInstalled = false ;
2176*/
2177}
2178
2179void wxDC::MacSetupBackgroundForCurrentPort(const wxBrush& background )
2180{
2181 Pattern whiteColor ;
2182 switch( background.MacGetBrushKind() )
2183 {
2184 case kwxMacBrushTheme :
2185 {
2186 ::SetThemeBackground( background.MacGetTheme() , wxDisplayDepth() , true ) ;
2187 break ;
2188 }
2189 case kwxMacBrushThemeBackground :
2190 {
2191 Rect extent ;
2192 ThemeBackgroundKind bg = background.MacGetThemeBackground( &extent ) ;
2193 ::ApplyThemeBackground( bg , &extent ,kThemeStateActive , wxDisplayDepth() , true ) ;
2194 break ;
2195 }
2196 case kwxMacBrushColour :
2197 {
2198 ::RGBBackColor( &MAC_WXCOLORREF( background.GetColour().GetPixel()) );
2199 int brushStyle = background.GetStyle();
2200 if (brushStyle == wxSOLID)
2201 ::BackPat(GetQDGlobalsWhite(&whiteColor));
2202 else if (IS_HATCH(brushStyle))
2203 {
2204 Pattern pat ;
2205 wxMacGetPattern(brushStyle, &pat);
2206 ::BackPat(&pat);
2207 }
2208 else
2209 {
2210 ::BackPat(GetQDGlobalsWhite(&whiteColor));
2211 }
2212 break ;
2213 }
2214 }
2215}
2216
2217void wxDC::MacInstallBrush() const
2218{
2219 wxCHECK_RET(Ok(), wxT("Invalid DC"));
2220 Pattern blackColor ;
2221 // if ( m_macBrushInstalled )
2222 // return ;
2223 // foreground
2224 bool backgroundTransparent = (GetBackgroundMode() == wxTRANSPARENT) ;
2225 ::RGBForeColor( &MAC_WXCOLORREF( m_brush.GetColour().GetPixel()) );
2226 ::RGBBackColor( &MAC_WXCOLORREF( m_backgroundBrush.GetColour().GetPixel()) );
2227 int brushStyle = m_brush.GetStyle();
2228 if (brushStyle == wxSOLID)
2229 {
2230 ::PenPat(GetQDGlobalsBlack(&blackColor));
2231 }
2232 else if (IS_HATCH(brushStyle))
2233 {
2234 Pattern pat ;
2235 wxMacGetPattern(brushStyle, &pat);
2236 ::PenPat(&pat);
2237 }
2238 else if ( m_brush.GetStyle() == wxSTIPPLE || m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE )
2239 {
2240 // we force this in order to be compliant with wxMSW
2241 backgroundTransparent = false ;
2242 // for these the text fore (and back for MASK_OPAQUE) colors are used
2243 wxBitmap* bitmap = m_brush.GetStipple() ;
2244 int width = bitmap->GetWidth() ;
2245 int height = bitmap->GetHeight() ;
2246 GWorldPtr gw = NULL ;
2247 if ( m_brush.GetStyle() == wxSTIPPLE )
2248 gw = MAC_WXHBITMAP(bitmap->GetHBITMAP()) ;
2249 else
2250 gw = MAC_WXHBITMAP(bitmap->GetMask()->GetMaskBitmap()) ;
2251 PixMapHandle gwpixmaphandle = GetGWorldPixMap( gw ) ;
2252 LockPixels( gwpixmaphandle ) ;
2253 bool isMonochrome = !IsPortColor( gw ) ;
2254 if ( !isMonochrome )
2255 {
2256 if ( (**gwpixmaphandle).pixelSize == 1 )
2257 isMonochrome = true ;
2258 }
2259 if ( isMonochrome && width == 8 && height == 8 )
2260 {
2261 ::RGBForeColor( &MAC_WXCOLORREF( m_textForegroundColour.GetPixel()) );
2262 ::RGBForeColor( &MAC_WXCOLORREF( m_textBackgroundColour.GetPixel()) );
2263 BitMap* gwbitmap = (BitMap*) *gwpixmaphandle ; // since the color depth is 1 it is a BitMap
2264 UInt8 *gwbits = (UInt8*) gwbitmap->baseAddr ;
2265 int alignment = gwbitmap->rowBytes & 0x7FFF ;
2266 Pattern pat ;
2267 for ( int i = 0 ; i < 8 ; ++i )
2268 {
2269 pat.pat[i] = gwbits[i*alignment+0] ;
2270 }
2271 UnlockPixels( GetGWorldPixMap( gw ) ) ;
2272 ::PenPat( &pat ) ;
2273 }
2274 else
2275 {
2276 // this will be the code to handle power of 2 patterns, we will have to arrive at a nice
2277 // caching scheme before putting this into production
2278 Handle image;
2279 long imageSize;
2280 PixPatHandle pixpat = NewPixPat() ;
2281 CopyPixMap(gwpixmaphandle, (**pixpat).patMap);
2282 imageSize = GetPixRowBytes((**pixpat).patMap) *
2283 ((**(**pixpat).patMap).bounds.bottom -
2284 (**(**pixpat).patMap).bounds.top);
2285 PtrToHand( (**gwpixmaphandle).baseAddr, &image, imageSize );
2286 (**pixpat).patData = image;
2287 if ( isMonochrome )
2288 {
2289 CTabHandle ctable = ((**((**pixpat).patMap)).pmTable) ;
2290 ColorSpecPtr ctspec = (ColorSpecPtr) &(**ctable).ctTable ;
2291 if ( ctspec[0].rgb.red == 0x0000 )
2292 {
2293 ctspec[1].rgb = MAC_WXCOLORREF( m_textBackgroundColour.GetPixel()) ;
2294 ctspec[0].rgb = MAC_WXCOLORREF( m_textForegroundColour.GetPixel()) ;
2295 }
2296 else
2297 {
2298 ctspec[0].rgb = MAC_WXCOLORREF( m_textBackgroundColour.GetPixel()) ;
2299 ctspec[1].rgb = MAC_WXCOLORREF( m_textForegroundColour.GetPixel()) ;
2300 }
2301 ::CTabChanged( ctable ) ;
2302 }
2303 ::PenPixPat(pixpat);
2304 m_macForegroundPixMap = pixpat ;
2305 }
2306 UnlockPixels( gwpixmaphandle ) ;
2307 }
2308 else
2309 {
2310 ::PenPat(GetQDGlobalsBlack(&blackColor));
2311 }
2312 short mode = patCopy ;
2313 switch( m_logicalFunction )
2314 {
2315 case wxCOPY: // src
2316 if ( backgroundTransparent )
2317 mode = patOr ;
2318 else
2319 mode = patCopy ;
2320 break ;
2321 case wxINVERT: // NOT dst
2322 if ( !backgroundTransparent )
2323 {
2324 ::PenPat(GetQDGlobalsBlack(&blackColor));
2325 }
2326 mode = patXor ;
2327 break ;
2328 case wxXOR: // src XOR dst
2329 mode = patXor ;
2330 break ;
2331 case wxOR_REVERSE: // src OR (NOT dst)
2332 mode = notPatOr ;
2333 break ;
2334 case wxSRC_INVERT: // (NOT src)
2335 mode = notPatCopy ;
2336 break ;
2337 case wxAND: // src AND dst
2338 mode = adMin ;
2339 break ;
2340 // unsupported TODO
2341 case wxCLEAR: // 0
2342 case wxAND_REVERSE:// src AND (NOT dst)
2343 case wxAND_INVERT: // (NOT src) AND dst
2344 case wxNO_OP: // dst
2345 case wxNOR: // (NOT src) AND (NOT dst)
2346 case wxEQUIV: // (NOT src) XOR dst
2347 case wxOR_INVERT: // (NOT src) OR dst
2348 case wxNAND: // (NOT src) OR (NOT dst)
2349 case wxOR: // src OR dst
2350 case wxSET: // 1
2351 // case wxSRC_OR: // source _bitmap_ OR destination
2352 // case wxSRC_AND: // source _bitmap_ AND destination
2353 break ;
2354 }
2355 ::PenMode( mode ) ;
2356 m_macBrushInstalled = true ;
2357 m_macPenInstalled = false ;
2358 m_macFontInstalled = false ;
2359}
2360
2361// ---------------------------------------------------------------------------
2362// coordinates transformations
2363// ---------------------------------------------------------------------------
2364
2365wxCoord wxDCBase::DeviceToLogicalX(wxCoord x) const
2366{
2367 return ((wxDC *)this)->XDEV2LOG(x);
2368}
2369
2370wxCoord wxDCBase::DeviceToLogicalY(wxCoord y) const
2371{
2372 return ((wxDC *)this)->YDEV2LOG(y);
2373}
2374
2375wxCoord wxDCBase::DeviceToLogicalXRel(wxCoord x) const
2376{
2377 return ((wxDC *)this)->XDEV2LOGREL(x);
2378}
2379
2380wxCoord wxDCBase::DeviceToLogicalYRel(wxCoord y) const
2381{
2382 return ((wxDC *)this)->YDEV2LOGREL(y);
2383}
2384
2385wxCoord wxDCBase::LogicalToDeviceX(wxCoord x) const
2386{
2387 return ((wxDC *)this)->XLOG2DEV(x);
2388}
2389
2390wxCoord wxDCBase::LogicalToDeviceY(wxCoord y) const
2391{
2392 return ((wxDC *)this)->YLOG2DEV(y);
2393}
2394
2395wxCoord wxDCBase::LogicalToDeviceXRel(wxCoord x) const
2396{
2397 return ((wxDC *)this)->XLOG2DEVREL(x);
2398}
2399
2400wxCoord wxDCBase::LogicalToDeviceYRel(wxCoord y) const
2401{
2402 return ((wxDC *)this)->YLOG2DEVREL(y);
2403}