]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/dc.cpp
setting and restoring the graf port
[wxWidgets.git] / src / mac / carbon / 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 #if __MSL__ >= 0x6000
24 #include "math.h"
25 #endif
26
27 #if !USE_SHARED_LIBRARY
28 IMPLEMENT_ABSTRACT_CLASS(wxDC, wxObject)
29 #endif
30
31 //-----------------------------------------------------------------------------
32 // constants
33 //-----------------------------------------------------------------------------
34
35 #define mm2inches 0.0393700787402
36 #define inches2mm 25.4
37 #define mm2twips 56.6929133859
38 #define twips2mm 0.0176388888889
39 #define mm2pt 2.83464566929
40 #define pt2mm 0.352777777778
41 #ifndef __DARWIN__
42 const double M_PI = 3.14159265358979 ;
43 #endif
44 const double RAD2DEG = 180.0 / M_PI;
45
46 //-----------------------------------------------------------------------------
47 // Local functions
48 //-----------------------------------------------------------------------------
49
50 static inline double dmin(double a, double b) { return a < b ? a : b; }
51 static inline double dmax(double a, double b) { return a > b ? a : b; }
52 static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; }
53
54 //-----------------------------------------------------------------------------
55 // wxDC
56 //-----------------------------------------------------------------------------
57
58 wxDC::wxDC()
59 {
60 m_ok = FALSE;
61 m_colour = TRUE;
62
63 m_mm_to_pix_x = mm2pt;
64 m_mm_to_pix_y = mm2pt;
65
66 m_internalDeviceOriginX = 0;
67 m_internalDeviceOriginY = 0;
68 m_externalDeviceOriginX = 0;
69 m_externalDeviceOriginY = 0;
70
71 m_logicalScaleX = 1.0;
72 m_logicalScaleY = 1.0;
73 m_userScaleX = 1.0;
74 m_userScaleY = 1.0;
75 m_scaleX = 1.0;
76 m_scaleY = 1.0;
77
78 m_needComputeScaleX = FALSE;
79 m_needComputeScaleY = FALSE;
80
81 m_maxX = m_maxY = -100000;
82 m_minY = m_minY = 100000;
83
84 m_macPort = NULL ;
85 m_macMask = NULL ;
86 m_ok = FALSE ;
87
88 m_macFontInstalled = false ;
89 m_macBrushInstalled = false ;
90 m_macPenInstalled = false ;
91
92 m_macLocalOrigin.h = m_macLocalOrigin.v = 0 ;
93 m_macBoundaryClipRgn = NewRgn() ;
94 m_macCurrentClipRgn = NewRgn() ;
95
96 SetRectRgn( m_macBoundaryClipRgn , -32000 , -32000 , 32000 , 32000 ) ;
97 SetRectRgn( m_macCurrentClipRgn , -32000 , -32000 , 32000 , 32000 ) ;
98
99 m_pen = *wxBLACK_PEN;
100 m_font = *wxNORMAL_FONT;
101 m_brush = *wxWHITE_BRUSH;
102 }
103 wxMacPortSetter::wxMacPortSetter( const wxDC* dc ) :
104 m_ph( dc->m_macPort )
105 {
106 wxASSERT( dc->Ok() ) ;
107
108 dc->MacSetupPort(&m_ph) ;
109 }
110
111 wxMacPortSetter::~wxMacPortSetter()
112 {
113 }
114
115 wxDC::~wxDC(void)
116 {
117 DisposeRgn( m_macBoundaryClipRgn ) ;
118 DisposeRgn( m_macCurrentClipRgn ) ;
119 }
120 void wxDC::MacSetupPort(AGAPortHelper* help) const
121 {
122 SetClip( m_macCurrentClipRgn);
123
124 m_macFontInstalled = false ;
125 m_macBrushInstalled = false ;
126 m_macPenInstalled = false ;
127 }
128
129 void wxDC::DoDrawBitmap( const wxBitmap &bmp, wxCoord x, wxCoord y, bool useMask )
130 {
131 wxCHECK_RET( Ok(), wxT("invalid window dc") );
132
133 wxCHECK_RET( bmp.Ok(), wxT("invalid bitmap") );
134
135 wxMacPortSetter helper(this) ;
136
137 wxCoord xx = XLOG2DEVMAC(x);
138 wxCoord yy = YLOG2DEVMAC(y);
139 wxCoord w = bmp.GetWidth();
140 wxCoord h = bmp.GetHeight();
141 wxCoord ww = XLOG2DEVREL(w);
142 wxCoord hh = YLOG2DEVREL(h);
143
144 // Set up drawing mode
145 short mode = (m_logicalFunction == wxCOPY ? srcCopy :
146 //m_logicalFunction == wxCLEAR ? WHITENESS :
147 //m_logicalFunction == wxSET ? BLACKNESS :
148 m_logicalFunction == wxINVERT ? hilite :
149 //m_logicalFunction == wxAND ? MERGECOPY :
150 m_logicalFunction == wxOR ? srcOr :
151 m_logicalFunction == wxSRC_INVERT ? notSrcCopy :
152 m_logicalFunction == wxXOR ? srcXor :
153 m_logicalFunction == wxOR_REVERSE ? notSrcOr :
154 //m_logicalFunction == wxAND_REVERSE ? SRCERASE :
155 //m_logicalFunction == wxSRC_OR ? srcOr :
156 //m_logicalFunction == wxSRC_AND ? SRCAND :
157 srcCopy );
158
159 if ( bmp.GetBitmapType() == kMacBitmapTypePict ) {
160 Rect bitmaprect = { 0 , 0 , hh, ww };
161 ::OffsetRect( &bitmaprect, xx, yy ) ;
162 ::DrawPicture( bmp.GetPict(), &bitmaprect ) ;
163 }
164 else if ( bmp.GetBitmapType() == kMacBitmapTypeGrafWorld )
165 {
166 GWorldPtr bmapworld = bmp.GetHBITMAP();
167 PixMapHandle bmappixels ;
168
169 // Set foreground and background colours (for bitmaps depth = 1)
170 if(bmp.GetDepth() == 1)
171 {
172 RGBColor fore = m_textForegroundColour.GetPixel();
173 RGBColor back = m_textBackgroundColour.GetPixel();
174 RGBForeColor(&fore);
175 RGBBackColor(&back);
176 }
177 else
178 {
179 RGBColor white = { 0xFFFF, 0xFFFF,0xFFFF} ;
180 RGBColor black = { 0,0,0} ;
181 RGBForeColor( &black ) ;
182 RGBBackColor( &white ) ;
183 }
184
185 bmappixels = GetGWorldPixMap( bmapworld ) ;
186
187 wxCHECK_RET(LockPixels(bmappixels),
188 wxT("DoDrawBitmap: Unable to lock pixels"));
189
190 Rect source = { 0, 0, h, w };
191 Rect dest = { yy, xx, yy + hh, xx + ww };
192
193 if ( useMask && bmp.GetMask() )
194 {
195 if( LockPixels(GetGWorldPixMap(bmp.GetMask()->GetMaskBitmap())))
196 {
197 CopyDeepMask
198 (
199 GetPortBitMapForCopyBits(bmapworld),
200 GetPortBitMapForCopyBits(bmp.GetMask()->GetMaskBitmap()),
201 GetPortBitMapForCopyBits( m_macPort ),
202 &source, &source, &dest, mode, NULL
203 );
204 UnlockPixels(GetGWorldPixMap(bmp.GetMask()->GetMaskBitmap()));
205 }
206 }
207 else {
208 CopyBits( GetPortBitMapForCopyBits( bmapworld ),
209 GetPortBitMapForCopyBits( m_macPort ),
210 &source, &dest, mode, NULL ) ;
211 }
212 UnlockPixels( bmappixels ) ;
213 }
214 else if ( bmp.GetBitmapType() == kMacBitmapTypeIcon )
215 {
216 Rect bitmaprect = { 0 , 0 , bmp.GetHeight(), bmp.GetWidth() } ;
217 OffsetRect( &bitmaprect, xx, yy ) ;
218 PlotCIconHandle( &bitmaprect , atNone , ttNone , bmp.GetHICON() ) ;
219 }
220 m_macPenInstalled = false ;
221 m_macBrushInstalled = false ;
222 m_macFontInstalled = false ;
223
224 }
225
226 void wxDC::DoDrawIcon( const wxIcon &icon, wxCoord x, wxCoord y )
227 {
228 wxCHECK_RET(Ok(), wxT("Invalid dc wxDC::DoDrawIcon"));
229
230 wxCHECK_RET(icon.Ok(), wxT("Invalid icon wxDC::DoDrawIcon"));
231
232 DoDrawBitmap( icon , x , y , icon.GetMask() != NULL ) ;
233 }
234 void wxDC::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
235 {
236 wxCHECK_RET(Ok(), wxT("wxDC::DoSetClippingRegion Invalid DC"));
237 wxCoord xx, yy, ww, hh;
238
239 xx = XLOG2DEVMAC(x);
240 yy = YLOG2DEVMAC(y);
241 ww = XLOG2DEVREL(width);
242 hh = YLOG2DEVREL(height);
243
244 SetRectRgn( m_macCurrentClipRgn , xx , yy , xx + ww , yy + hh ) ;
245 SectRgn( m_macCurrentClipRgn , m_macBoundaryClipRgn , m_macCurrentClipRgn ) ;
246
247 if( m_clipping )
248 {
249 m_clipX1 = wxMax( m_clipX1 , xx );
250 m_clipY1 = wxMax( m_clipY1 , yy );
251 m_clipX2 = wxMin( m_clipX2, (xx + ww));
252 m_clipY2 = wxMin( m_clipY2, (yy + hh));
253 }
254 else
255 {
256 m_clipping = TRUE;
257 m_clipX1 = xx;
258 m_clipY1 = yy;
259 m_clipX2 = xx + ww;
260 m_clipY2 = yy + hh;
261 }
262
263 }
264 void wxDC::DoSetClippingRegionAsRegion( const wxRegion &region )
265 {
266 wxCHECK_RET( Ok(), wxT("invalid window dc") ) ;
267
268 wxMacPortSetter helper(this) ;
269 if (region.Empty())
270 {
271 DestroyClippingRegion();
272 return;
273 }
274
275 wxCoord x, y, w, h;
276 region.GetBox( x, y, w, h );
277 wxCoord xx, yy, ww, hh;
278
279 xx = XLOG2DEVMAC(x);
280 yy = YLOG2DEVMAC(y);
281 ww = XLOG2DEVREL(w);
282 hh = YLOG2DEVREL(h);
283
284 // if we have a scaling that we cannot map onto native regions
285 // we must use the box
286
287 if ( ww != w || hh != h )
288 {
289 wxDC::DoSetClippingRegion( x, y, w, h );
290 }
291 else
292 {
293 CopyRgn( region.GetWXHRGN() , m_macCurrentClipRgn ) ;
294 if ( xx != x || yy != y )
295 {
296 OffsetRgn( m_macCurrentClipRgn , xx - x , yy - y ) ;
297 }
298 SectRgn( m_macCurrentClipRgn , m_macBoundaryClipRgn , m_macCurrentClipRgn ) ;
299 if( m_clipping )
300 {
301 m_clipX1 = wxMax( m_clipX1 , xx );
302 m_clipY1 = wxMax( m_clipY1 , yy );
303 m_clipX2 = wxMin( m_clipX2, (xx + ww));
304 m_clipY2 = wxMin( m_clipY2, (yy + hh));
305 }
306 else
307 {
308 m_clipping = TRUE;
309 m_clipX1 = xx;
310 m_clipY1 = yy;
311 m_clipX2 = xx + ww;
312 m_clipY2 = yy + hh;
313 }
314 }
315
316 }
317
318 void wxDC::DestroyClippingRegion()
319 {
320 wxMacPortSetter helper(this) ;
321 CopyRgn( m_macBoundaryClipRgn , m_macCurrentClipRgn ) ;
322 m_clipping = FALSE;
323 }
324 void wxDC::DoGetSize( int* width, int* height ) const
325 {
326 *width = m_maxX-m_minX;
327 *height = m_maxY-m_minY;
328 }
329 void wxDC::DoGetSizeMM( int* width, int* height ) const
330 {
331 int w = 0;
332 int h = 0;
333 GetSize( &w, &h );
334 *width = long( double(w) / (m_scaleX*m_mm_to_pix_x) );
335 *height = long( double(h) / (m_scaleY*m_mm_to_pix_y) );
336 }
337 void wxDC::SetTextForeground( const wxColour &col )
338 {
339 wxCHECK_RET(Ok(), wxT("Invalid DC"));
340 m_textForegroundColour = col;
341 m_macFontInstalled = false ;
342 }
343 void wxDC::SetTextBackground( const wxColour &col )
344 {
345 wxCHECK_RET(Ok(), wxT("Invalid DC"));
346 m_textBackgroundColour = col;
347 m_macFontInstalled = false ;
348 }
349 void wxDC::SetMapMode( int mode )
350 {
351 switch (mode)
352 {
353 case wxMM_TWIPS:
354 SetLogicalScale( twips2mm*m_mm_to_pix_x, twips2mm*m_mm_to_pix_y );
355 break;
356 case wxMM_POINTS:
357 SetLogicalScale( pt2mm*m_mm_to_pix_x, pt2mm*m_mm_to_pix_y );
358 break;
359 case wxMM_METRIC:
360 SetLogicalScale( m_mm_to_pix_x, m_mm_to_pix_y );
361 break;
362 case wxMM_LOMETRIC:
363 SetLogicalScale( m_mm_to_pix_x/10.0, m_mm_to_pix_y/10.0 );
364 break;
365 default:
366 case wxMM_TEXT:
367 SetLogicalScale( 1.0, 1.0 );
368 break;
369 }
370 if (mode != wxMM_TEXT)
371 {
372 m_needComputeScaleX = TRUE;
373 m_needComputeScaleY = TRUE;
374 }
375 }
376 void wxDC::SetUserScale( double x, double y )
377 {
378 // allow negative ? -> no
379 m_userScaleX = x;
380 m_userScaleY = y;
381 ComputeScaleAndOrigin();
382 }
383 void wxDC::SetLogicalScale( double x, double y )
384 {
385 // allow negative ?
386 m_logicalScaleX = x;
387 m_logicalScaleY = y;
388 ComputeScaleAndOrigin();
389 }
390 void wxDC::SetLogicalOrigin( wxCoord x, wxCoord y )
391 {
392 m_logicalOriginX = x * m_signX; // is this still correct ?
393 m_logicalOriginY = y * m_signY;
394 ComputeScaleAndOrigin();
395 }
396 void wxDC::SetDeviceOrigin( wxCoord x, wxCoord y )
397 {
398 m_externalDeviceOriginX = x;
399 m_externalDeviceOriginY = y;
400 ComputeScaleAndOrigin();
401 }
402
403 #if 0
404 void wxDC::SetInternalDeviceOrigin( long x, long y )
405 {
406 m_internalDeviceOriginX = x;
407 m_internalDeviceOriginY = y;
408 ComputeScaleAndOrigin();
409 }
410 void wxDC::GetInternalDeviceOrigin( long *x, long *y )
411 {
412 if (x) *x = m_internalDeviceOriginX;
413 if (y) *y = m_internalDeviceOriginY;
414 }
415 #endif
416 void wxDC::SetAxisOrientation( bool xLeftRight, bool yBottomUp )
417 {
418 m_signX = (xLeftRight ? 1 : -1);
419 m_signY = (yBottomUp ? -1 : 1);
420 ComputeScaleAndOrigin();
421 }/*
422
423 void wxDC::CalcBoundingBox( long x, long y )
424 {
425 if (x < m_minX) m_minX = x;
426 if (y < m_minY) m_minY = y;
427 if (x > m_maxX) m_maxX = x;
428 if (y > m_maxY) m_maxY = y;
429 }*/
430 wxSize wxDC::GetPPI() const
431 {
432 return wxSize(72, 72);
433 }
434
435 int wxDC::GetDepth() const
436 {
437 return wxDisplayDepth() ;
438 }
439
440 void wxDC::ComputeScaleAndOrigin()
441 {
442 // CMB: copy scale to see if it changes
443 double origScaleX = m_scaleX;
444 double origScaleY = m_scaleY;
445
446 m_scaleX = m_logicalScaleX * m_userScaleX;
447 m_scaleY = m_logicalScaleY * m_userScaleY;
448
449 m_deviceOriginX = m_internalDeviceOriginX + m_externalDeviceOriginX;
450 m_deviceOriginY = m_internalDeviceOriginY + m_externalDeviceOriginY;
451
452 // CMB: if scale has changed call SetPen to recalulate the line width
453 if (m_scaleX != origScaleX || m_scaleY != origScaleY)
454 {
455 // this is a bit artificial, but we need to force wxDC to think
456 // the pen has changed
457 wxPen* pen = & GetPen();
458 wxPen tempPen;
459 m_pen = tempPen;
460 SetPen(* pen);
461 }
462 }
463 void wxDC::SetPalette( const wxPalette& palette )
464 {
465 }
466
467 void wxDC::SetBackgroundMode( int mode )
468 {
469 m_backgroundMode = mode ;
470 }
471
472 void wxDC::SetFont( const wxFont &font )
473 {
474 m_font = font;
475 m_macFontInstalled = false ;
476 }
477
478 void wxDC::SetPen( const wxPen &pen )
479 {
480 if ( m_pen == pen )
481 return ;
482
483 m_pen = pen;
484
485 m_macPenInstalled = false ;
486 }
487
488 void wxDC::SetBrush( const wxBrush &brush )
489 {
490 if (m_brush == brush)
491 return;
492
493 m_brush = brush;
494 m_macBrushInstalled = false ;
495 }
496
497 void wxDC::SetBackground( const wxBrush &brush )
498 {
499 if (m_backgroundBrush == brush)
500 return;
501
502 m_backgroundBrush = brush;
503
504 if (!m_backgroundBrush.Ok())
505 return;
506 m_macBrushInstalled = false ;
507 }
508
509 void wxDC::SetLogicalFunction( int function )
510 {
511 if (m_logicalFunction == function)
512 return;
513
514 m_logicalFunction = function ;
515 m_macFontInstalled = false ;
516 m_macBrushInstalled = false ;
517 m_macPenInstalled = false ;
518 }
519
520 void wxDC::DoFloodFill( wxCoord x, wxCoord y, const wxColour& col,
521 int style )
522 {
523 }
524
525 bool wxDC::DoGetPixel( wxCoord x, wxCoord y, wxColour *col ) const
526 {
527 wxCHECK_MSG( Ok(), false, wxT("wxDC::DoGetPixel Invalid DC") );
528 wxMacPortSetter helper(this) ;
529
530 RGBColor colour;
531
532 GetCPixel( XLOG2DEVMAC(x), YLOG2DEVMAC(y), &colour );
533
534 // Convert from Mac colour to wx
535 col->Set( colour.red >> 8,
536 colour.green >> 8,
537 colour.blue >> 8);
538
539 return true ;
540 }
541
542 void wxDC::DoDrawLine( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2 )
543 {
544 wxCHECK_RET(Ok(), wxT("Invalid DC"));
545
546 wxMacPortSetter helper(this) ;
547
548 if (m_pen.GetStyle() != wxTRANSPARENT)
549 {
550 MacInstallPen() ;
551 wxCoord offset = ( (m_pen.GetWidth() == 0 ? 1 :
552 m_pen.GetWidth() ) * (wxCoord)m_scaleX - 1) / 2;
553
554 wxCoord xx1 = XLOG2DEVMAC(x1) - offset;
555 wxCoord yy1 = YLOG2DEVMAC(y1) - offset;
556 wxCoord xx2 = XLOG2DEVMAC(x2) - offset;
557 wxCoord yy2 = YLOG2DEVMAC(y2) - offset;
558
559 if ((m_pen.GetCap() == wxCAP_ROUND) &&
560 (m_pen.GetWidth() <= 1))
561 {
562 // Implement LAST_NOT for MAC at least for
563 // orthogonal lines. RR.
564 if (xx1 == xx2)
565 {
566 if (yy1 < yy2)
567 yy2--;
568 if (yy1 > yy2)
569 yy2++;
570 }
571 if (yy1 == yy2)
572 {
573 if (xx1 < xx2)
574 xx2--;
575 if (xx1 > xx2)
576 xx2++;
577 }
578 }
579
580 ::MoveTo(xx1, yy1);
581 ::LineTo(xx2, yy2);
582 }
583 }
584
585 void wxDC::DoCrossHair( wxCoord x, wxCoord y )
586 {
587 wxCHECK_RET( Ok(), wxT("wxDC::DoCrossHair Invalid window dc") );
588
589 if (m_pen.GetStyle() != wxTRANSPARENT)
590 {
591 int w = 0;
592 int h = 0;
593 GetSize( &w, &h );
594 wxCoord xx = XLOG2DEVMAC(x);
595 wxCoord yy = YLOG2DEVMAC(y);
596
597 MacInstallPen();
598 ::MoveTo( XLOG2DEVMAC(0), yy );
599 ::LineTo( XLOG2DEVMAC(w), yy );
600 ::MoveTo( xx, YLOG2DEVMAC(0) );
601 ::LineTo( xx, YLOG2DEVMAC(h) );
602 }
603 }
604
605 /*
606 * To draw arcs properly the angles need to be converted from the WX style:
607 * Angles start on the +ve X axis and go anti-clockwise (As you would draw on
608 * a normal axis on paper).
609 * TO
610 * the Mac style:
611 * Angles start on the +ve y axis and go clockwise.
612 * To achive this I work out which quadrant the angle lies in then map this to
613 * the equivalent quadrant on the Mac. (Sin and Cos values reveal which
614 * quadrant you are in).
615 */
616 static double wxConvertWXangleToMACangle(double angle)
617 {
618 double sin_a, cos_a;
619
620 sin_a = sin(angle / RAD2DEG);
621 cos_a = cos(angle / RAD2DEG);
622
623 if( (sin_a >= 0.0) && (cos_a >= 0.0) ) {
624 angle = acos(sin_a) * RAD2DEG;
625 }
626 else if( (sin_a >= 0.0) && (cos_a <= 0.0) ) {
627 sin_a *= -1;
628 angle = acos(sin_a) * RAD2DEG + 180;
629 }
630 else if( (sin_a <= 0.0) && (cos_a >= 0.0) ) {
631 angle = acos(sin_a) * RAD2DEG + 180;
632 }
633 else if( (sin_a < 0.0) && (cos_a < 0.0) ) {
634 sin_a *= -1;
635 angle = acos(sin_a) * RAD2DEG + 180;
636 }
637 return angle;
638 }
639
640 void wxDC::DoDrawArc( wxCoord x1, wxCoord y1,
641 wxCoord x2, wxCoord y2,
642 wxCoord xc, wxCoord yc )
643 {
644 wxCHECK_RET(Ok(), wxT("wxDC::DoDrawArc Invalid DC"));
645
646 wxCoord xx1 = XLOG2DEVMAC(x1);
647 wxCoord yy1 = YLOG2DEVMAC(y1);
648 wxCoord xx2 = XLOG2DEVMAC(x2);
649 wxCoord yy2 = YLOG2DEVMAC(y2);
650 wxCoord xxc = XLOG2DEVMAC(xc);
651 wxCoord yyc = YLOG2DEVMAC(yc);
652 double dx = xx1 - xxc;
653 double dy = yy1 - yyc;
654 double radius = sqrt((double)(dx*dx+dy*dy));
655 wxCoord rad = (wxCoord)radius;
656 double radius1, radius2;
657
658 if (xx1 == xx2 && yy1 == yy2)
659 {
660 radius1 = 0.0;
661 radius2 = 360.0;
662 }
663 else if (radius == 0.0)
664 {
665 radius1 = radius2 = 0.0;
666 }
667 else
668 {
669 radius1 = (xx1 - xxc == 0) ?
670 (yy1 - yyc < 0) ? 90.0 : -90.0 :
671 -atan2(double(yy1-yyc), double(xx1-xxc)) * RAD2DEG;
672 radius2 = (xx2 - xxc == 0) ?
673 (yy2 - yyc < 0) ? 90.0 : -90.0 :
674 -atan2(double(yy2-yyc), double(xx2-xxc)) * RAD2DEG;
675 }
676 wxCoord alpha2 = wxCoord(radius2 - radius1);
677 wxCoord alpha1 = wxCoord(wxConvertWXangleToMACangle(radius1));
678 if( (xx1 > xx2) || (yy1 > yy2) ) {
679 alpha2 *= -1;
680 }
681
682 Rect r = { yyc - rad, xxc - rad, yyc + rad, xxc + rad };
683
684 if(m_brush.GetStyle() != wxTRANSPARENT) {
685 MacInstallBrush();
686 PaintArc(&r, alpha1, alpha2);
687 }
688 if(m_pen.GetStyle() != wxTRANSPARENT) {
689 MacInstallPen();
690 FrameArc(&r, alpha1, alpha2);
691 }
692 }
693
694 void wxDC::DoDrawEllipticArc( wxCoord x, wxCoord y, wxCoord w, wxCoord h,
695 double sa, double ea )
696 {
697 wxCHECK_RET(Ok(), wxT("wxDC::DoDrawEllepticArc Invalid DC"));
698
699 Rect r;
700 double angle = sa - ea; // Order important Mac in opposite direction to wx
701
702 wxCoord xx = XLOG2DEVMAC(x);
703 wxCoord yy = YLOG2DEVMAC(y);
704 wxCoord ww = m_signX * XLOG2DEVREL(w);
705 wxCoord hh = m_signY * YLOG2DEVREL(h);
706
707 // handle -ve width and/or height
708 if (ww < 0) { ww = -ww; xx = xx - ww; }
709 if (hh < 0) { hh = -hh; yy = yy - hh; }
710
711 sa = wxConvertWXangleToMACangle(sa);
712
713 r.top = yy;
714 r.left = xx;
715 r.bottom = yy + hh;
716 r.right = xx + ww;
717
718 if(m_brush.GetStyle() != wxTRANSPARENT) {
719 MacInstallBrush();
720 PaintArc(&r, (short)sa, (short)angle);
721 }
722 if(m_pen.GetStyle() != wxTRANSPARENT) {
723 MacInstallPen();
724 FrameArc(&r, (short)sa, (short)angle);
725 }
726 }
727
728 void wxDC::DoDrawPoint( wxCoord x, wxCoord y )
729 {
730 wxCHECK_RET(Ok(), wxT("Invalid DC"));
731
732 wxMacPortSetter helper(this) ;
733
734 if (m_pen.GetStyle() != wxTRANSPARENT)
735 {
736 MacInstallPen() ;
737 wxCoord xx1 = XLOG2DEVMAC(x);
738 wxCoord yy1 = YLOG2DEVMAC(y);
739
740 ::MoveTo(xx1,yy1);
741 ::LineTo(xx1+1, yy1+1);
742 }
743 }
744
745 void wxDC::DoDrawLines(int n, wxPoint points[],
746 wxCoord xoffset, wxCoord yoffset)
747 {
748 wxCHECK_RET(Ok(), wxT("Invalid DC"));
749 wxMacPortSetter helper(this) ;
750
751 if (m_pen.GetStyle() == wxTRANSPARENT)
752 return;
753
754 MacInstallPen() ;
755
756 wxCoord offset = ( (m_pen.GetWidth() == 0 ? 1 :
757 m_pen.GetWidth() ) * (wxCoord)m_scaleX - 1) / 2 ;
758
759 wxCoord x1, x2 , y1 , y2 ;
760 x1 = XLOG2DEVMAC(points[0].x + xoffset);
761 y1 = YLOG2DEVMAC(points[0].y + yoffset);
762 ::MoveTo(x1 - offset, y1 - offset );
763
764 for (int i = 0; i < n-1; i++)
765 {
766 x2 = XLOG2DEVMAC(points[i+1].x + xoffset);
767 y2 = YLOG2DEVMAC(points[i+1].y + yoffset);
768 ::LineTo( x2 - offset, y2 - offset );
769 }
770 }
771
772 void wxDC::DoDrawPolygon(int n, wxPoint points[],
773 wxCoord xoffset, wxCoord yoffset,
774 int fillStyle )
775 {
776 wxCHECK_RET(Ok(), wxT("Invalid DC"));
777 wxMacPortSetter helper(this) ;
778
779 wxCoord x1, x2 , y1 , y2 ;
780
781 if (m_brush.GetStyle() != wxTRANSPARENT)
782 {
783 PolyHandle polygon = OpenPoly();
784
785 x1 = XLOG2DEVMAC(points[0].x + xoffset);
786 y1 = YLOG2DEVMAC(points[0].y + yoffset);
787 ::MoveTo(x1,y1);
788
789 for (int i = 0; i < n-1; i++)
790 {
791 x2 = XLOG2DEVMAC(points[i+1].x + xoffset);
792 y2 = YLOG2DEVMAC(points[i+1].y + yoffset);
793 ::LineTo(x2, y2);
794 }
795
796 ClosePoly();
797
798 MacInstallBrush();
799 ::PaintPoly( polygon );
800
801 KillPoly( polygon );
802 }
803
804 if (m_pen.GetStyle() != wxTRANSPARENT)
805 {
806 PolyHandle polygon = OpenPoly();
807
808 x1 = XLOG2DEVMAC(points[0].x + xoffset);
809 y1 = YLOG2DEVMAC(points[0].y + yoffset);
810 ::MoveTo(x1,y1);
811
812 for (int i = 0; i < n-1; i++)
813 {
814 x2 = XLOG2DEVMAC(points[i+1].x + xoffset);
815 y2 = YLOG2DEVMAC(points[i+1].y + yoffset);
816 ::LineTo(x2, y2);
817 }
818
819 // return to origin to close path
820 ::LineTo(x1,y1);
821
822 ClosePoly();
823
824 MacInstallPen() ;
825 ::FramePoly( polygon ) ;
826
827 KillPoly( polygon );
828 }
829 }
830
831 void wxDC::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
832 {
833 wxCHECK_RET(Ok(), wxT("Invalid DC"));
834 wxMacPortSetter helper(this) ;
835
836 wxCoord xx = XLOG2DEVMAC(x);
837 wxCoord yy = YLOG2DEVMAC(y);
838 wxCoord ww = m_signX * XLOG2DEVREL(width);
839 wxCoord hh = m_signY * YLOG2DEVREL(height);
840
841 // CMB: draw nothing if transformed w or h is 0
842 if (ww == 0 || hh == 0)
843 return;
844
845 // CMB: handle -ve width and/or height
846 if (ww < 0)
847 {
848 ww = -ww;
849 xx = xx - ww;
850 }
851
852 if (hh < 0)
853 {
854 hh = -hh;
855 yy = yy - hh;
856 }
857
858 Rect rect = { yy , xx , yy + hh , xx + ww } ;
859
860 if (m_brush.GetStyle() != wxTRANSPARENT)
861 {
862 MacInstallBrush() ;
863 ::PaintRect( &rect ) ;
864 }
865
866 if (m_pen.GetStyle() != wxTRANSPARENT)
867 {
868 MacInstallPen() ;
869 ::FrameRect( &rect ) ;
870 }
871 }
872
873 void wxDC::DoDrawRoundedRectangle(wxCoord x, wxCoord y,
874 wxCoord width, wxCoord height,
875 double radius)
876 {
877 wxCHECK_RET(Ok(), wxT("Invalid DC"));
878 wxMacPortSetter helper(this) ;
879
880 if (radius < 0.0)
881 radius = - radius * ((width < height) ? width : height);
882
883 wxCoord xx = XLOG2DEVMAC(x);
884 wxCoord yy = YLOG2DEVMAC(y);
885 wxCoord ww = m_signX * XLOG2DEVREL(width);
886 wxCoord hh = m_signY * YLOG2DEVREL(height);
887
888 // CMB: draw nothing if transformed w or h is 0
889 if (ww == 0 || hh == 0)
890 return;
891
892 // CMB: handle -ve width and/or height
893 if (ww < 0)
894 {
895 ww = -ww;
896 xx = xx - ww;
897 }
898
899 if (hh < 0)
900 {
901 hh = -hh;
902 yy = yy - hh;
903 }
904
905 Rect rect = { yy , xx , yy + hh , xx + ww } ;
906
907 if (m_brush.GetStyle() != wxTRANSPARENT)
908 {
909 MacInstallBrush() ;
910 ::PaintRoundRect( &rect , int(radius * 2) , int(radius * 2) ) ;
911 }
912
913 if (m_pen.GetStyle() != wxTRANSPARENT)
914 {
915 MacInstallPen() ;
916 ::FrameRoundRect( &rect , int(radius * 2) , int(radius * 2) ) ;
917 }
918 }
919
920 void wxDC::DoDrawEllipse(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
921 {
922 wxCHECK_RET(Ok(), wxT("Invalid DC"));
923 wxMacPortSetter helper(this) ;
924
925 wxCoord xx = XLOG2DEVMAC(x);
926 wxCoord yy = YLOG2DEVMAC(y);
927 wxCoord ww = m_signX * XLOG2DEVREL(width);
928 wxCoord hh = m_signY * YLOG2DEVREL(height);
929
930 // CMB: draw nothing if transformed w or h is 0
931 if (ww == 0 || hh == 0)
932 return;
933
934 // CMB: handle -ve width and/or height
935 if (ww < 0)
936 {
937 ww = -ww;
938 xx = xx - ww;
939 }
940
941 if (hh < 0)
942 {
943 hh = -hh;
944 yy = yy - hh;
945 }
946
947 Rect rect = { yy , xx , yy + hh , xx + ww } ;
948
949 if (m_brush.GetStyle() != wxTRANSPARENT)
950 {
951 MacInstallBrush() ;
952 ::PaintOval( &rect ) ;
953 }
954
955 if (m_pen.GetStyle() != wxTRANSPARENT)
956 {
957 MacInstallPen() ;
958 ::FrameOval( &rect ) ;
959 }
960 }
961
962
963
964 bool wxDC::CanDrawBitmap(void) const
965 {
966 return true ;
967 }
968
969
970 bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
971 wxDC *source, wxCoord xsrc, wxCoord ysrc, int logical_func , bool useMask,
972 wxCoord xsrcMask, wxCoord ysrcMask )
973 {
974 wxCHECK_MSG(Ok(), false, wxT("wxDC::DoBlit Illegal dc"));
975 wxCHECK_MSG(source->Ok(), false, wxT("wxDC::DoBlit Illegal source DC"));
976 wxMacPortSetter helper(this) ;
977
978 /* TODO: use the mask origin when drawing transparently */
979 if (xsrcMask == -1 && ysrcMask == -1)
980 {
981 xsrcMask = xsrc; ysrcMask = ysrc;
982 }
983
984 CGrafPtr sourcePort = (CGrafPtr) source->m_macPort ;
985 PixMapHandle bmappixels = GetGWorldPixMap( sourcePort ) ;
986 RGBColor white = { 0xFFFF, 0xFFFF,0xFFFF} ;
987 RGBColor black = { 0,0,0} ;
988 RGBColor forecolor = m_textForegroundColour.GetPixel();
989 RGBColor backcolor = m_textBackgroundColour.GetPixel();
990 RGBForeColor( &forecolor ) ;
991 RGBBackColor( &backcolor ) ;
992
993 if ( LockPixels(bmappixels) )
994 {
995 Rect srcrect , dstrect ;
996 srcrect.top = source->YLOG2DEVMAC(ysrc) ;
997 srcrect.left = source->XLOG2DEVMAC(xsrc) ;
998 srcrect.right = source->XLOG2DEVMAC(xsrc + width ) ;
999 srcrect.bottom = source->YLOG2DEVMAC(ysrc + height) ;
1000 dstrect.top = YLOG2DEVMAC(ydest) ;
1001 dstrect.left = XLOG2DEVMAC(xdest) ;
1002 dstrect.bottom = YLOG2DEVMAC(ydest + height ) ;
1003 dstrect.right = XLOG2DEVMAC(xdest + width ) ;
1004
1005 short mode = (logical_func == wxCOPY ? srcCopy :
1006 // logical_func == wxCLEAR ? WHITENESS :
1007 // logical_func == wxSET ? BLACKNESS :
1008 logical_func == wxINVERT ? hilite :
1009 // logical_func == wxAND ? MERGECOPY :
1010 logical_func == wxOR ? srcOr :
1011 logical_func == wxSRC_INVERT ? notSrcCopy :
1012 logical_func == wxXOR ? srcXor :
1013 // logical_func == wxOR_REVERSE ? MERGEPAINT :
1014 // logical_func == wxAND_REVERSE ? SRCERASE :
1015 // logical_func == wxSRC_OR ? srcOr :
1016 // logical_func == wxSRC_AND ? SRCAND :
1017 srcCopy );
1018
1019 if ( useMask && source->m_macMask )
1020 {
1021 if ( mode == srcCopy )
1022 {
1023 if ( LockPixels( GetGWorldPixMap( source->m_macMask ) ) )
1024 {
1025 CopyMask( GetPortBitMapForCopyBits( sourcePort ) ,
1026 GetPortBitMapForCopyBits( source->m_macMask ) ,
1027 GetPortBitMapForCopyBits( m_macPort ) ,
1028 &srcrect, &srcrect , &dstrect ) ;
1029 UnlockPixels( GetGWorldPixMap( source->m_macMask ) ) ;
1030 }
1031 }
1032 else
1033 {
1034 RgnHandle clipRgn = NewRgn() ;
1035
1036 LockPixels( GetGWorldPixMap( source->m_macMask ) ) ;
1037 BitMapToRegion( clipRgn , (BitMap*) *GetGWorldPixMap( source->m_macMask ) ) ;
1038 UnlockPixels( GetGWorldPixMap( source->m_macMask ) ) ;
1039 //OffsetRgn( clipRgn , -source->m_macMask->portRect.left , -source->m_macMask->portRect.top ) ;
1040 OffsetRgn( clipRgn , -srcrect.left + dstrect.left, -srcrect.top + dstrect.top ) ;
1041 CopyBits( GetPortBitMapForCopyBits( sourcePort ) ,
1042 GetPortBitMapForCopyBits( m_macPort ) ,
1043 &srcrect, &dstrect, mode, clipRgn ) ;
1044 DisposeRgn( clipRgn ) ;
1045 }
1046 }
1047 else
1048 {
1049 CopyBits( GetPortBitMapForCopyBits( sourcePort ) ,
1050 GetPortBitMapForCopyBits( m_macPort ) ,
1051 &srcrect, &dstrect, mode, NULL ) ;
1052 }
1053 UnlockPixels( bmappixels ) ;
1054 }
1055
1056 m_macPenInstalled = false ;
1057 m_macBrushInstalled = false ;
1058 m_macFontInstalled = false ;
1059
1060 return TRUE;
1061 }
1062
1063 void wxDC::DoDrawRotatedText(const wxString& text, wxCoord x, wxCoord y,
1064 double angle)
1065 {
1066 wxCHECK_RET( Ok(), wxT("wxDC::DoDrawRotatedText Invalid window dc") );
1067
1068 if (angle == 0.0)
1069 {
1070 DrawText(text, x, y);
1071 return;
1072 }
1073
1074 MacInstallFont();
1075
1076 // the size of the text
1077 wxCoord w, h;
1078 GetTextExtent(text, &w, &h);
1079
1080 // draw the string normally
1081 wxBitmap src(w, h);
1082 wxMemoryDC dc;
1083 dc.SelectObject(src);
1084 dc.SetFont(GetFont());
1085 dc.SetBackground(*wxWHITE_BRUSH);
1086 dc.SetBrush(*wxBLACK_BRUSH);
1087 dc.Clear();
1088 dc.DrawText(text, 0, 0);
1089 dc.SetFont(wxNullFont);
1090 dc.SelectObject(wxNullBitmap);
1091
1092 wxMacPortSetter helper(this) ;
1093
1094 // Calculate the size of the rotated bounding box.
1095 double rad = DegToRad(angle);
1096 double dx = cos(rad);
1097 double dy = sin(rad);
1098
1099 // the rectngle vertices are counted clockwise with the first one being at
1100 // (0, 0) (or, rather, at (x, y))
1101 double x2 = w * dx;
1102 double y2 = -w * dy; // y axis points to the bottom, hence minus
1103 double x4 = h * dy;
1104 double y4 = h * dx;
1105 double x3 = x4 + x2;
1106 double y3 = y4 + y2;
1107
1108 // calc max and min
1109 wxCoord maxX = (wxCoord)(dmax(x2, dmax(x3, x4)) + 0.5);
1110 wxCoord maxY = (wxCoord)(dmax(y2, dmax(y3, y4)) + 0.5);
1111 wxCoord minX = (wxCoord)(dmin(x2, dmin(x3, x4)) - 0.5);
1112 wxCoord minY = (wxCoord)(dmin(y2, dmin(y3, y4)) - 0.5);
1113
1114 // prepare to blit-with-rotate the bitmap to the DC
1115 wxImage image(src);
1116
1117 RGBColor colText = m_textForegroundColour.GetPixel();
1118 RGBColor colBack = m_textBackgroundColour.GetPixel();
1119
1120 unsigned char *data = image.GetData();
1121
1122 wxCoord dstX, dstY;
1123 double r, angleOrig;
1124 bool textPixel;
1125
1126 // paint pixel by pixel
1127 for ( wxCoord srcX = 0; srcX < w; srcX++ )
1128 {
1129 for ( wxCoord srcY = 0; srcY < h; srcY++ )
1130 {
1131 // transform source coords to dest coords
1132 r = sqrt( (double)(srcX * srcX + srcY * srcY) );
1133 angleOrig = atan2((double)srcY, (double)srcX) - rad;
1134 dstX = (wxCoord)(r * cos(angleOrig) + 0.5);
1135 dstY = (wxCoord)(r * sin(angleOrig) + 0.5);
1136
1137 // black pixel?
1138 textPixel = data[(srcY*w + srcX)*3] == 0;
1139 if ( textPixel || (m_backgroundMode == wxSOLID) )
1140 {
1141 SetCPixel(XLOG2DEVMAC(x + dstX), YLOG2DEVMAC(y + dstY),
1142 textPixel ? &colText : &colBack);
1143 }
1144 }
1145 }
1146
1147 // it would be better to draw with non underlined font and draw the line
1148 // manually here (it would be more straight...)
1149 #if 0
1150 if ( m_font.GetUnderlined() )
1151 {
1152 ::MoveTo(XLOG2DEVMAC(x + x4), YLOG2DEVMAC(y + y4 + font->descent));
1153 ::LineTo(XLOG2DEVMAC(x + x3), YLOG2DEVMAC(y + y3 + font->descent));
1154 }
1155 #endif // 0
1156
1157 // update the bounding box
1158 CalcBoundingBox(x + minX, y + minY);
1159 CalcBoundingBox(x + maxX, y + maxY);
1160 }
1161 void wxDC::DoDrawText(const wxString& strtext, wxCoord x, wxCoord y)
1162 {
1163 wxCHECK_RET(Ok(), wxT("wxDC::DoDrawText Invalid DC"));
1164 wxMacPortSetter helper(this) ;
1165
1166 long xx = XLOG2DEVMAC(x);
1167 long yy = YLOG2DEVMAC(y);
1168
1169 // if (m_pen.GetStyle() != wxTRANSPARENT)
1170 {
1171 MacInstallFont() ;
1172 /*
1173 Rect clip = { -32000 , -32000 , 32000 , 32000 } ;
1174
1175 ::ClipRect( &clip ) ;
1176 */
1177
1178 FontInfo fi ;
1179 ::GetFontInfo( &fi ) ;
1180
1181 yy += fi.ascent ;
1182 ::MoveTo( xx , yy );
1183 if ( m_backgroundMode == wxTRANSPARENT )
1184 {
1185 ::TextMode( srcOr) ;
1186 }
1187 else
1188 {
1189 ::TextMode( srcCopy ) ;
1190 }
1191
1192 const char *text = NULL ;
1193 int length = 0 ;
1194 wxString macText ;
1195
1196 if ( wxApp::s_macDefaultEncodingIsPC )
1197 {
1198 macText = wxMacMakeMacStringFromPC( strtext ) ;
1199 text = macText ;
1200 length = macText.Length() ;
1201 }
1202 else
1203 {
1204 text = strtext ;
1205 length = strtext.Length() ;
1206 }
1207
1208 int laststop = 0 ;
1209 int i = 0 ;
1210 int line = 0 ;
1211
1212 while( i < length )
1213 {
1214 if( text[i] == 13 || text[i] == 10)
1215 {
1216 ::DrawText( text , laststop , i - laststop ) ;
1217 line++ ;
1218 ::MoveTo( xx , yy + line*(fi.descent + fi.ascent + fi.leading) );
1219 laststop = i+1 ;
1220 }
1221 i++ ;
1222 }
1223
1224 ::DrawText( text , laststop , i - laststop ) ;
1225 ::TextMode( srcOr ) ;
1226 }
1227 }
1228
1229 bool wxDC::CanGetTextExtent() const
1230 {
1231 wxCHECK_MSG(Ok(), false, wxT("Invalid DC"));
1232
1233 return true ;
1234 }
1235
1236 void wxDC::DoGetTextExtent( const wxString &string, wxCoord *width, wxCoord *height,
1237 wxCoord *descent, wxCoord *externalLeading ,
1238 wxFont *theFont ) const
1239 {
1240 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1241 wxMacPortSetter helper(this) ;
1242
1243 wxFont formerFont = m_font ;
1244
1245 if ( theFont )
1246 {
1247 wxFontRefData * font = (wxFontRefData*) m_font.GetRefData() ;
1248
1249 if ( font )
1250 {
1251 ::TextFont( font->m_macFontNum ) ;
1252 ::TextSize( YLOG2DEVREL( font->m_macFontSize) ) ;
1253 ::TextFace( font->m_macFontStyle ) ;
1254 }
1255 }
1256 else
1257 {
1258 MacInstallFont() ;
1259 }
1260
1261 FontInfo fi ;
1262 ::GetFontInfo( &fi ) ;
1263
1264 if ( height )
1265 *height = YDEV2LOGREL( fi.descent + fi.ascent ) ;
1266 if ( descent )
1267 *descent =YDEV2LOGREL( fi.descent );
1268 if ( externalLeading )
1269 *externalLeading = YDEV2LOGREL( fi.leading ) ;
1270
1271 const char *text = NULL ;
1272 int length = 0 ;
1273 wxString macText ;
1274 if ( wxApp::s_macDefaultEncodingIsPC )
1275 {
1276 macText = wxMacMakeMacStringFromPC( string ) ;
1277 text = macText ;
1278 length = macText.Length() ;
1279 }
1280 else
1281 {
1282 text = string ;
1283 length = string.Length() ;
1284 }
1285
1286 int laststop = 0 ;
1287 int i = 0 ;
1288 int curwidth = 0 ;
1289 if ( width )
1290 {
1291 *width = 0 ;
1292
1293 while( i < length )
1294 {
1295 if( text[i] == 13 || text[i] == 10)
1296 {
1297 if ( height )
1298 *height += YDEV2LOGREL( fi.descent + fi.ascent + fi.leading ) ;
1299 curwidth = ::TextWidth( text , laststop , i - laststop ) ;
1300 if ( curwidth > *width )
1301 *width = XDEV2LOGREL( curwidth ) ;
1302 laststop = i+1 ;
1303 }
1304 i++ ;
1305 }
1306
1307 curwidth = ::TextWidth( text , laststop , i - laststop ) ;
1308 if ( curwidth > *width )
1309 *width = XDEV2LOGREL( curwidth ) ;
1310 }
1311
1312 if ( theFont )
1313 {
1314 m_macFontInstalled = false ;
1315 }
1316 }
1317
1318 wxCoord wxDC::GetCharWidth(void) const
1319 {
1320 wxCHECK_MSG(Ok(), 1, wxT("Invalid DC"));
1321
1322 wxMacPortSetter helper(this) ;
1323
1324 MacInstallFont() ;
1325
1326 int width = ::TextWidth( "n" , 0 , 1 ) ;
1327
1328 return YDEV2LOGREL(width) ;
1329 }
1330
1331 wxCoord wxDC::GetCharHeight(void) const
1332 {
1333 wxCHECK_MSG(Ok(), 1, wxT("Invalid DC"));
1334
1335 wxMacPortSetter helper(this) ;
1336
1337 MacInstallFont() ;
1338
1339 FontInfo fi ;
1340 ::GetFontInfo( &fi ) ;
1341
1342 return YDEV2LOGREL( fi.descent + fi.ascent );
1343 }
1344
1345 void wxDC::Clear(void)
1346 {
1347 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1348 wxMacPortSetter helper(this) ;
1349 Rect rect = { -32767 , -32767 , 32767 , 32767 } ;
1350
1351 if (m_backgroundBrush.GetStyle() != wxTRANSPARENT)
1352 {
1353 MacInstallBrush() ;
1354 ::EraseRect( &rect ) ;
1355 }
1356 }
1357
1358 void wxDC::MacInstallFont() const
1359 {
1360 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1361 // if ( m_macFontInstalled )
1362 // return ;
1363 Pattern blackColor ;
1364
1365 wxFontRefData * font = (wxFontRefData*) m_font.GetRefData() ;
1366
1367 if ( font )
1368 {
1369 ::TextFont( font->m_macFontNum ) ;
1370 ::TextSize( short(m_scaleY * font->m_macFontSize) ) ;
1371 ::TextFace( font->m_macFontStyle ) ;
1372
1373 m_macFontInstalled = true ;
1374 m_macBrushInstalled = false ;
1375 m_macPenInstalled = false ;
1376
1377 RGBColor forecolor = m_textForegroundColour.GetPixel();
1378 RGBColor backcolor = m_textBackgroundColour.GetPixel();
1379 ::RGBForeColor( &forecolor );
1380 ::RGBBackColor( &backcolor );
1381 }
1382 else
1383 {
1384 short fontnum ;
1385
1386 GetFNum( "\pGeneva" , &fontnum ) ;
1387 ::TextFont( fontnum ) ;
1388 ::TextSize( short(m_scaleY * 10) ) ;
1389 ::TextFace( 0 ) ;
1390
1391 // todo reset after spacing changes - or store the current spacing somewhere
1392
1393 m_macFontInstalled = true ;
1394 m_macBrushInstalled = false ;
1395 m_macPenInstalled = false ;
1396
1397 RGBColor forecolor = m_textForegroundColour.GetPixel();
1398 RGBColor backcolor = m_textBackgroundColour.GetPixel();
1399 ::RGBForeColor( &forecolor );
1400 ::RGBBackColor( &backcolor );
1401 }
1402
1403 short mode = patCopy ;
1404
1405 // todo :
1406
1407 switch( m_logicalFunction )
1408 {
1409 case wxCOPY: // src
1410 mode = patCopy ;
1411 break ;
1412 case wxINVERT: // NOT dst
1413 ::PenPat(GetQDGlobalsBlack(&blackColor));
1414 mode = patXor ;
1415 break ;
1416 case wxXOR: // src XOR dst
1417 mode = patXor ;
1418 break ;
1419 case wxOR_REVERSE: // src OR (NOT dst)
1420 mode = notPatOr ;
1421 break ;
1422 case wxSRC_INVERT: // (NOT src)
1423 mode = notPatCopy ;
1424 break ;
1425
1426 // unsupported TODO
1427
1428 case wxCLEAR: // 0
1429 case wxAND_REVERSE:// src AND (NOT dst)
1430 case wxAND: // src AND dst
1431 case wxAND_INVERT: // (NOT src) AND dst
1432 case wxNO_OP: // dst
1433 case wxNOR: // (NOT src) AND (NOT dst)
1434 case wxEQUIV: // (NOT src) XOR dst
1435 case wxOR_INVERT: // (NOT src) OR dst
1436 case wxNAND: // (NOT src) OR (NOT dst)
1437 case wxOR: // src OR dst
1438 case wxSET: // 1
1439 // case wxSRC_OR: // source _bitmap_ OR destination
1440 // case wxSRC_AND: // source _bitmap_ AND destination
1441 break ;
1442 }
1443 ::PenMode( mode ) ;
1444 }
1445
1446 static void wxMacGetHatchPattern(int hatchStyle, Pattern *pattern)
1447 {
1448 int thePatListID = sysPatListID;
1449 int theIndex;
1450 switch(hatchStyle)
1451 {
1452 case wxBDIAGONAL_HATCH:
1453 theIndex = 34; // WCH: this is not good
1454 break;
1455 case wxFDIAGONAL_HATCH:
1456 theIndex = 26;
1457 break;
1458 case wxCROSS_HATCH:
1459 theIndex = 5;
1460 break;
1461 case wxHORIZONTAL_HATCH:
1462 theIndex = 25;
1463 break;
1464 case wxVERTICAL_HATCH:
1465 theIndex = 6;
1466 break;
1467 case wxCROSSDIAG_HATCH:
1468 theIndex = 4; // WCH: this is not good
1469 break;
1470 default:
1471 theIndex = 1; // solid pattern
1472 break;
1473 }
1474 GetIndPattern( pattern, thePatListID, theIndex);
1475 }
1476
1477 void wxDC::MacInstallPen() const
1478 {
1479 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1480
1481 Pattern blackColor;
1482
1483 // if ( m_macPenInstalled )
1484 // return ;
1485
1486 RGBColor forecolor = m_pen.GetColour().GetPixel();
1487 RGBColor backcolor = m_backgroundBrush.GetColour().GetPixel();
1488 ::RGBForeColor( &forecolor );
1489 ::RGBBackColor( &backcolor );
1490
1491 ::PenNormal() ;
1492 int penWidth = m_pen.GetWidth() * (int) m_scaleX ;
1493
1494 // null means only one pixel, at whatever resolution
1495 if ( penWidth == 0 )
1496 penWidth = 1 ;
1497 ::PenSize(penWidth, penWidth);
1498
1499 int penStyle = m_pen.GetStyle();
1500
1501 if (penStyle == wxSOLID)
1502 {
1503 ::PenPat(GetQDGlobalsBlack(&blackColor));
1504 }
1505 else if (IS_HATCH(penStyle))
1506 {
1507 Pattern pat ;
1508 wxMacGetHatchPattern(penStyle, &pat);
1509 ::PenPat(&pat);
1510 }
1511 else
1512 {
1513 ::PenPat(GetQDGlobalsBlack(&blackColor));
1514 }
1515
1516 short mode = patCopy ;
1517
1518 // todo :
1519
1520 switch( m_logicalFunction )
1521 {
1522 case wxCOPY: // src
1523 mode = patCopy ;
1524 break ;
1525 case wxINVERT: // NOT dst
1526 ::PenPat(GetQDGlobalsBlack(&blackColor));
1527 mode = patXor ;
1528 break ;
1529 case wxXOR: // src XOR dst
1530 mode = patXor ;
1531 break ;
1532 case wxOR_REVERSE: // src OR (NOT dst)
1533 mode = notPatOr ;
1534 break ;
1535 case wxSRC_INVERT: // (NOT src)
1536 mode = notPatCopy ;
1537 break ;
1538
1539 // unsupported TODO
1540
1541 case wxCLEAR: // 0
1542 case wxAND_REVERSE:// src AND (NOT dst)
1543 case wxAND: // src AND dst
1544 case wxAND_INVERT: // (NOT src) AND dst
1545 case wxNO_OP: // dst
1546 case wxNOR: // (NOT src) AND (NOT dst)
1547 case wxEQUIV: // (NOT src) XOR dst
1548 case wxOR_INVERT: // (NOT src) OR dst
1549 case wxNAND: // (NOT src) OR (NOT dst)
1550 case wxOR: // src OR dst
1551 case wxSET: // 1
1552 // case wxSRC_OR: // source _bitmap_ OR destination
1553 // case wxSRC_AND: // source _bitmap_ AND destination
1554 break ;
1555 }
1556 ::PenMode( mode ) ;
1557 m_macPenInstalled = true ;
1558 m_macBrushInstalled = false ;
1559 m_macFontInstalled = false ;
1560 }
1561
1562 void wxDC::MacSetupBackgroundForCurrentPort(const wxBrush& background )
1563 {
1564 Pattern whiteColor ;
1565 switch( background.MacGetBrushKind() )
1566 {
1567 case kwxMacBrushTheme :
1568 {
1569 ::SetThemeBackground( background.GetMacTheme() , wxDisplayDepth() , true ) ;
1570 break ;
1571 }
1572 case kwxMacBrushThemeBackground :
1573 {
1574 Rect extent ;
1575 ThemeBackgroundKind bg = background.GetMacThemeBackground( &extent ) ;
1576 ::ApplyThemeBackground( bg , &extent ,kThemeStateActive , wxDisplayDepth() , true ) ;
1577 break ;
1578 }
1579 case kwxMacBrushColour :
1580 {
1581 ::RGBBackColor( &background.GetColour().GetPixel() );
1582 int brushStyle = background.GetStyle();
1583 if (brushStyle == wxSOLID)
1584 ::BackPat(GetQDGlobalsWhite(&whiteColor));
1585 else if (IS_HATCH(brushStyle))
1586 {
1587 Pattern pat ;
1588 wxMacGetHatchPattern(brushStyle, &pat);
1589 ::BackPat(&pat);
1590 }
1591 else
1592 {
1593 ::BackPat(GetQDGlobalsWhite(&whiteColor));
1594 }
1595 break ;
1596 }
1597 }
1598 }
1599
1600 void wxDC::MacInstallBrush() const
1601 {
1602 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1603
1604 Pattern blackColor ;
1605 // if ( m_macBrushInstalled )
1606 // return ;
1607
1608 // foreground
1609
1610 ::RGBForeColor( &m_brush.GetColour().GetPixel() );
1611
1612 int brushStyle = m_brush.GetStyle();
1613 if (brushStyle == wxSOLID)
1614 ::PenPat(GetQDGlobalsBlack(&blackColor));
1615 else if (IS_HATCH(brushStyle))
1616 {
1617 Pattern pat ;
1618 wxMacGetHatchPattern(brushStyle, &pat);
1619 ::PenPat(&pat);
1620 }
1621 else
1622 {
1623 ::PenPat(GetQDGlobalsBlack(&blackColor));
1624 }
1625
1626
1627 // background
1628
1629 MacSetupBackgroundForCurrentPort( m_backgroundBrush ) ;
1630
1631
1632 // todo :
1633
1634 short mode = patCopy ;
1635 switch( m_logicalFunction )
1636 {
1637 case wxCOPY: // src
1638 mode = patCopy ;
1639 break ;
1640 case wxINVERT: // NOT dst
1641 ::PenPat(GetQDGlobalsBlack(&blackColor));
1642 mode = patXor ;
1643 break ;
1644 case wxXOR: // src XOR dst
1645 mode = patXor ;
1646 break ;
1647 case wxOR_REVERSE: // src OR (NOT dst)
1648 mode = notPatOr ;
1649 break ;
1650 case wxSRC_INVERT: // (NOT src)
1651 mode = notPatCopy ;
1652 break ;
1653
1654 // unsupported TODO
1655
1656 case wxCLEAR: // 0
1657 case wxAND_REVERSE:// src AND (NOT dst)
1658 case wxAND: // src AND dst
1659 case wxAND_INVERT: // (NOT src) AND dst
1660 case wxNO_OP: // dst
1661 case wxNOR: // (NOT src) AND (NOT dst)
1662 case wxEQUIV: // (NOT src) XOR dst
1663 case wxOR_INVERT: // (NOT src) OR dst
1664 case wxNAND: // (NOT src) OR (NOT dst)
1665 case wxOR: // src OR dst
1666 case wxSET: // 1
1667 // case wxSRC_OR: // source _bitmap_ OR destination
1668 // case wxSRC_AND: // source _bitmap_ AND destination
1669 break ;
1670 }
1671 ::PenMode( mode ) ;
1672 m_macBrushInstalled = true ;
1673 m_macPenInstalled = false ;
1674 m_macFontInstalled = false ;
1675 }
1676
1677 // ---------------------------------------------------------------------------
1678 // coordinates transformations
1679 // ---------------------------------------------------------------------------
1680
1681
1682 wxCoord wxDCBase::DeviceToLogicalX(wxCoord x) const
1683 {
1684 return ((wxDC *)this)->XDEV2LOG(x);
1685 }
1686
1687 wxCoord wxDCBase::DeviceToLogicalY(wxCoord y) const
1688 {
1689 return ((wxDC *)this)->YDEV2LOG(y);
1690 }
1691
1692 wxCoord wxDCBase::DeviceToLogicalXRel(wxCoord x) const
1693 {
1694 return ((wxDC *)this)->XDEV2LOGREL(x);
1695 }
1696
1697 wxCoord wxDCBase::DeviceToLogicalYRel(wxCoord y) const
1698 {
1699 return ((wxDC *)this)->YDEV2LOGREL(y);
1700 }
1701
1702 wxCoord wxDCBase::LogicalToDeviceX(wxCoord x) const
1703 {
1704 return ((wxDC *)this)->XLOG2DEV(x);
1705 }
1706
1707 wxCoord wxDCBase::LogicalToDeviceY(wxCoord y) const
1708 {
1709 return ((wxDC *)this)->YLOG2DEV(y);
1710 }
1711
1712 wxCoord wxDCBase::LogicalToDeviceXRel(wxCoord x) const
1713 {
1714 return ((wxDC *)this)->XLOG2DEVREL(x);
1715 }
1716
1717 wxCoord wxDCBase::LogicalToDeviceYRel(wxCoord y) const
1718 {
1719 return ((wxDC *)this)->YLOG2DEVREL(y);
1720 }