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