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