]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/dc.cpp
removing dependancy on mac headers from public wx headers (eventually adding wx/mac...
[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 && m_pen.GetStyle() == wxTRANSPARENT )
782 return ;
783
784 PolyHandle polygon = OpenPoly();
785
786 x1 = XLOG2DEVMAC(points[0].x + xoffset);
787 y1 = YLOG2DEVMAC(points[0].y + yoffset);
788 ::MoveTo(x1,y1);
789
790 for (int i = 0; i < n-1; i++)
791 {
792 x2 = XLOG2DEVMAC(points[i+1].x + xoffset);
793 y2 = YLOG2DEVMAC(points[i+1].y + yoffset);
794 ::LineTo(x2, y2);
795 }
796
797 ClosePoly();
798
799 if (m_brush.GetStyle() != wxTRANSPARENT)
800 {
801
802 MacInstallBrush();
803 ::PaintPoly( polygon );
804
805 }
806
807 if (m_pen.GetStyle() != wxTRANSPARENT)
808 {
809
810 MacInstallPen() ;
811 ::FramePoly( polygon ) ;
812
813 }
814 KillPoly( polygon );
815 }
816
817 void wxDC::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
818 {
819 wxCHECK_RET(Ok(), wxT("Invalid DC"));
820 wxMacPortSetter helper(this) ;
821
822 wxCoord xx = XLOG2DEVMAC(x);
823 wxCoord yy = YLOG2DEVMAC(y);
824 wxCoord ww = m_signX * XLOG2DEVREL(width);
825 wxCoord hh = m_signY * YLOG2DEVREL(height);
826
827 // CMB: draw nothing if transformed w or h is 0
828 if (ww == 0 || hh == 0)
829 return;
830
831 // CMB: handle -ve width and/or height
832 if (ww < 0)
833 {
834 ww = -ww;
835 xx = xx - ww;
836 }
837
838 if (hh < 0)
839 {
840 hh = -hh;
841 yy = yy - hh;
842 }
843
844 Rect rect = { yy , xx , yy + hh , xx + ww } ;
845
846 if (m_brush.GetStyle() != wxTRANSPARENT)
847 {
848 MacInstallBrush() ;
849 ::PaintRect( &rect ) ;
850 }
851
852 if (m_pen.GetStyle() != wxTRANSPARENT)
853 {
854 MacInstallPen() ;
855 ::FrameRect( &rect ) ;
856 }
857 }
858
859 void wxDC::DoDrawRoundedRectangle(wxCoord x, wxCoord y,
860 wxCoord width, wxCoord height,
861 double radius)
862 {
863 wxCHECK_RET(Ok(), wxT("Invalid DC"));
864 wxMacPortSetter helper(this) ;
865
866 if (radius < 0.0)
867 radius = - radius * ((width < height) ? width : height);
868
869 wxCoord xx = XLOG2DEVMAC(x);
870 wxCoord yy = YLOG2DEVMAC(y);
871 wxCoord ww = m_signX * XLOG2DEVREL(width);
872 wxCoord hh = m_signY * YLOG2DEVREL(height);
873
874 // CMB: draw nothing if transformed w or h is 0
875 if (ww == 0 || hh == 0)
876 return;
877
878 // CMB: handle -ve width and/or height
879 if (ww < 0)
880 {
881 ww = -ww;
882 xx = xx - ww;
883 }
884
885 if (hh < 0)
886 {
887 hh = -hh;
888 yy = yy - hh;
889 }
890
891 Rect rect = { yy , xx , yy + hh , xx + ww } ;
892
893 if (m_brush.GetStyle() != wxTRANSPARENT)
894 {
895 MacInstallBrush() ;
896 ::PaintRoundRect( &rect , int(radius * 2) , int(radius * 2) ) ;
897 }
898
899 if (m_pen.GetStyle() != wxTRANSPARENT)
900 {
901 MacInstallPen() ;
902 ::FrameRoundRect( &rect , int(radius * 2) , int(radius * 2) ) ;
903 }
904 }
905
906 void wxDC::DoDrawEllipse(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
907 {
908 wxCHECK_RET(Ok(), wxT("Invalid DC"));
909 wxMacPortSetter helper(this) ;
910
911 wxCoord xx = XLOG2DEVMAC(x);
912 wxCoord yy = YLOG2DEVMAC(y);
913 wxCoord ww = m_signX * XLOG2DEVREL(width);
914 wxCoord hh = m_signY * YLOG2DEVREL(height);
915
916 // CMB: draw nothing if transformed w or h is 0
917 if (ww == 0 || hh == 0)
918 return;
919
920 // CMB: handle -ve width and/or height
921 if (ww < 0)
922 {
923 ww = -ww;
924 xx = xx - ww;
925 }
926
927 if (hh < 0)
928 {
929 hh = -hh;
930 yy = yy - hh;
931 }
932
933 Rect rect = { yy , xx , yy + hh , xx + ww } ;
934
935 if (m_brush.GetStyle() != wxTRANSPARENT)
936 {
937 MacInstallBrush() ;
938 ::PaintOval( &rect ) ;
939 }
940
941 if (m_pen.GetStyle() != wxTRANSPARENT)
942 {
943 MacInstallPen() ;
944 ::FrameOval( &rect ) ;
945 }
946 }
947
948
949
950 bool wxDC::CanDrawBitmap(void) const
951 {
952 return true ;
953 }
954
955
956 bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
957 wxDC *source, wxCoord xsrc, wxCoord ysrc, int logical_func , bool useMask,
958 wxCoord xsrcMask, wxCoord ysrcMask )
959 {
960 wxCHECK_MSG(Ok(), false, wxT("wxDC::DoBlit Illegal dc"));
961 wxCHECK_MSG(source->Ok(), false, wxT("wxDC::DoBlit Illegal source DC"));
962 wxMacPortSetter helper(this) ;
963
964 /* TODO: use the mask origin when drawing transparently */
965 if (xsrcMask == -1 && ysrcMask == -1)
966 {
967 xsrcMask = xsrc; ysrcMask = ysrc;
968 }
969
970 CGrafPtr sourcePort = (CGrafPtr) source->m_macPort ;
971 PixMapHandle bmappixels = GetGWorldPixMap( sourcePort ) ;
972 RGBColor white = { 0xFFFF, 0xFFFF,0xFFFF} ;
973 RGBColor black = { 0,0,0} ;
974 RGBColor forecolor = m_textForegroundColour.GetPixel();
975 RGBColor backcolor = m_textBackgroundColour.GetPixel();
976 RGBForeColor( &forecolor ) ;
977 RGBBackColor( &backcolor ) ;
978
979 if ( LockPixels(bmappixels) )
980 {
981 Rect srcrect , dstrect ;
982 srcrect.top = source->YLOG2DEVMAC(ysrc) ;
983 srcrect.left = source->XLOG2DEVMAC(xsrc) ;
984 srcrect.right = source->XLOG2DEVMAC(xsrc + width ) ;
985 srcrect.bottom = source->YLOG2DEVMAC(ysrc + height) ;
986 dstrect.top = YLOG2DEVMAC(ydest) ;
987 dstrect.left = XLOG2DEVMAC(xdest) ;
988 dstrect.bottom = YLOG2DEVMAC(ydest + height ) ;
989 dstrect.right = XLOG2DEVMAC(xdest + width ) ;
990
991 short mode = (logical_func == wxCOPY ? srcCopy :
992 // logical_func == wxCLEAR ? WHITENESS :
993 // logical_func == wxSET ? BLACKNESS :
994 logical_func == wxINVERT ? hilite :
995 // logical_func == wxAND ? MERGECOPY :
996 logical_func == wxOR ? srcOr :
997 logical_func == wxSRC_INVERT ? notSrcCopy :
998 logical_func == wxXOR ? srcXor :
999 // logical_func == wxOR_REVERSE ? MERGEPAINT :
1000 // logical_func == wxAND_REVERSE ? SRCERASE :
1001 // logical_func == wxSRC_OR ? srcOr :
1002 // logical_func == wxSRC_AND ? SRCAND :
1003 srcCopy );
1004
1005 if ( useMask && source->m_macMask )
1006 {
1007 if ( mode == srcCopy )
1008 {
1009 if ( LockPixels( GetGWorldPixMap( source->m_macMask ) ) )
1010 {
1011 CopyMask( GetPortBitMapForCopyBits( sourcePort ) ,
1012 GetPortBitMapForCopyBits( source->m_macMask ) ,
1013 GetPortBitMapForCopyBits( m_macPort ) ,
1014 &srcrect, &srcrect , &dstrect ) ;
1015 UnlockPixels( GetGWorldPixMap( source->m_macMask ) ) ;
1016 }
1017 }
1018 else
1019 {
1020 RgnHandle clipRgn = NewRgn() ;
1021
1022 LockPixels( GetGWorldPixMap( source->m_macMask ) ) ;
1023 BitMapToRegion( clipRgn , (BitMap*) *GetGWorldPixMap( source->m_macMask ) ) ;
1024 UnlockPixels( GetGWorldPixMap( source->m_macMask ) ) ;
1025 //OffsetRgn( clipRgn , -source->m_macMask->portRect.left , -source->m_macMask->portRect.top ) ;
1026 OffsetRgn( clipRgn , -srcrect.left + dstrect.left, -srcrect.top + dstrect.top ) ;
1027 CopyBits( GetPortBitMapForCopyBits( sourcePort ) ,
1028 GetPortBitMapForCopyBits( m_macPort ) ,
1029 &srcrect, &dstrect, mode, clipRgn ) ;
1030 DisposeRgn( clipRgn ) ;
1031 }
1032 }
1033 else
1034 {
1035 CopyBits( GetPortBitMapForCopyBits( sourcePort ) ,
1036 GetPortBitMapForCopyBits( m_macPort ) ,
1037 &srcrect, &dstrect, mode, NULL ) ;
1038 }
1039 UnlockPixels( bmappixels ) ;
1040 }
1041
1042 m_macPenInstalled = false ;
1043 m_macBrushInstalled = false ;
1044 m_macFontInstalled = false ;
1045
1046 return TRUE;
1047 }
1048
1049 void wxDC::DoDrawRotatedText(const wxString& text, wxCoord x, wxCoord y,
1050 double angle)
1051 {
1052 wxCHECK_RET( Ok(), wxT("wxDC::DoDrawRotatedText Invalid window dc") );
1053
1054 if (angle == 0.0)
1055 {
1056 DrawText(text, x, y);
1057 return;
1058 }
1059
1060 MacInstallFont();
1061
1062 // the size of the text
1063 wxCoord w, h;
1064 GetTextExtent(text, &w, &h);
1065
1066 // draw the string normally
1067 wxBitmap src(w, h);
1068 wxMemoryDC dc;
1069 dc.SelectObject(src);
1070 dc.SetFont(GetFont());
1071 dc.SetBackground(*wxWHITE_BRUSH);
1072 dc.SetBrush(*wxBLACK_BRUSH);
1073 dc.Clear();
1074 dc.DrawText(text, 0, 0);
1075 dc.SetFont(wxNullFont);
1076 dc.SelectObject(wxNullBitmap);
1077
1078 wxMacPortSetter helper(this) ;
1079
1080 // Calculate the size of the rotated bounding box.
1081 double rad = DegToRad(angle);
1082 double dx = cos(rad);
1083 double dy = sin(rad);
1084
1085 // the rectngle vertices are counted clockwise with the first one being at
1086 // (0, 0) (or, rather, at (x, y))
1087 double x2 = w * dx;
1088 double y2 = -w * dy; // y axis points to the bottom, hence minus
1089 double x4 = h * dy;
1090 double y4 = h * dx;
1091 double x3 = x4 + x2;
1092 double y3 = y4 + y2;
1093
1094 // calc max and min
1095 wxCoord maxX = (wxCoord)(dmax(x2, dmax(x3, x4)) + 0.5);
1096 wxCoord maxY = (wxCoord)(dmax(y2, dmax(y3, y4)) + 0.5);
1097 wxCoord minX = (wxCoord)(dmin(x2, dmin(x3, x4)) - 0.5);
1098 wxCoord minY = (wxCoord)(dmin(y2, dmin(y3, y4)) - 0.5);
1099
1100 // prepare to blit-with-rotate the bitmap to the DC
1101 wxImage image(src);
1102
1103 RGBColor colText = m_textForegroundColour.GetPixel();
1104 RGBColor colBack = m_textBackgroundColour.GetPixel();
1105
1106 unsigned char *data = image.GetData();
1107
1108 wxCoord dstX, dstY;
1109 double r, angleOrig;
1110 bool textPixel;
1111
1112 // paint pixel by pixel
1113 for ( wxCoord srcX = 0; srcX < w; srcX++ )
1114 {
1115 for ( wxCoord srcY = 0; srcY < h; srcY++ )
1116 {
1117 // transform source coords to dest coords
1118 r = sqrt( (double)(srcX * srcX + srcY * srcY) );
1119 angleOrig = atan2((double)srcY, (double)srcX) - rad;
1120 dstX = (wxCoord)(r * cos(angleOrig) + 0.5);
1121 dstY = (wxCoord)(r * sin(angleOrig) + 0.5);
1122
1123 // black pixel?
1124 textPixel = data[(srcY*w + srcX)*3] == 0;
1125 if ( textPixel || (m_backgroundMode == wxSOLID) )
1126 {
1127 SetCPixel(XLOG2DEVMAC(x + dstX), YLOG2DEVMAC(y + dstY),
1128 textPixel ? &colText : &colBack);
1129 }
1130 }
1131 }
1132
1133 // it would be better to draw with non underlined font and draw the line
1134 // manually here (it would be more straight...)
1135 #if 0
1136 if ( m_font.GetUnderlined() )
1137 {
1138 ::MoveTo(XLOG2DEVMAC(x + x4), YLOG2DEVMAC(y + y4 + font->descent));
1139 ::LineTo(XLOG2DEVMAC(x + x3), YLOG2DEVMAC(y + y3 + font->descent));
1140 }
1141 #endif // 0
1142
1143 // update the bounding box
1144 CalcBoundingBox(x + minX, y + minY);
1145 CalcBoundingBox(x + maxX, y + maxY);
1146 }
1147 void wxDC::DoDrawText(const wxString& strtext, wxCoord x, wxCoord y)
1148 {
1149 wxCHECK_RET(Ok(), wxT("wxDC::DoDrawText Invalid DC"));
1150 wxMacPortSetter helper(this) ;
1151
1152 long xx = XLOG2DEVMAC(x);
1153 long yy = YLOG2DEVMAC(y);
1154
1155 // if (m_pen.GetStyle() != wxTRANSPARENT)
1156 {
1157 MacInstallFont() ;
1158 /*
1159 Rect clip = { -32000 , -32000 , 32000 , 32000 } ;
1160
1161 ::ClipRect( &clip ) ;
1162 */
1163
1164 FontInfo fi ;
1165 ::GetFontInfo( &fi ) ;
1166
1167 yy += fi.ascent ;
1168 ::MoveTo( xx , yy );
1169 if ( m_backgroundMode == wxTRANSPARENT )
1170 {
1171 ::TextMode( srcOr) ;
1172 }
1173 else
1174 {
1175 ::TextMode( srcCopy ) ;
1176 }
1177
1178 const char *text = NULL ;
1179 int length = 0 ;
1180 wxString macText ;
1181
1182 if ( wxApp::s_macDefaultEncodingIsPC )
1183 {
1184 macText = wxMacMakeMacStringFromPC( strtext ) ;
1185 text = macText ;
1186 length = macText.Length() ;
1187 }
1188 else
1189 {
1190 text = strtext ;
1191 length = strtext.Length() ;
1192 }
1193
1194 int laststop = 0 ;
1195 int i = 0 ;
1196 int line = 0 ;
1197
1198 while( i < length )
1199 {
1200 if( text[i] == 13 || text[i] == 10)
1201 {
1202 ::DrawText( text , laststop , i - laststop ) ;
1203 line++ ;
1204 ::MoveTo( xx , yy + line*(fi.descent + fi.ascent + fi.leading) );
1205 laststop = i+1 ;
1206 }
1207 i++ ;
1208 }
1209
1210 ::DrawText( text , laststop , i - laststop ) ;
1211 ::TextMode( srcOr ) ;
1212 }
1213 }
1214
1215 bool wxDC::CanGetTextExtent() const
1216 {
1217 wxCHECK_MSG(Ok(), false, wxT("Invalid DC"));
1218
1219 return true ;
1220 }
1221
1222 void wxDC::DoGetTextExtent( const wxString &string, wxCoord *width, wxCoord *height,
1223 wxCoord *descent, wxCoord *externalLeading ,
1224 wxFont *theFont ) const
1225 {
1226 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1227 wxMacPortSetter helper(this) ;
1228
1229 wxFont formerFont = m_font ;
1230
1231 if ( theFont )
1232 {
1233 wxFontRefData * font = (wxFontRefData*) m_font.GetRefData() ;
1234
1235 if ( font )
1236 {
1237 ::TextFont( font->m_macFontNum ) ;
1238 ::TextSize( YLOG2DEVREL( font->m_macFontSize) ) ;
1239 ::TextFace( font->m_macFontStyle ) ;
1240 }
1241 }
1242 else
1243 {
1244 MacInstallFont() ;
1245 }
1246
1247 FontInfo fi ;
1248 ::GetFontInfo( &fi ) ;
1249
1250 if ( height )
1251 *height = YDEV2LOGREL( fi.descent + fi.ascent ) ;
1252 if ( descent )
1253 *descent =YDEV2LOGREL( fi.descent );
1254 if ( externalLeading )
1255 *externalLeading = YDEV2LOGREL( fi.leading ) ;
1256
1257 const char *text = NULL ;
1258 int length = 0 ;
1259 wxString macText ;
1260 if ( wxApp::s_macDefaultEncodingIsPC )
1261 {
1262 macText = wxMacMakeMacStringFromPC( string ) ;
1263 text = macText ;
1264 length = macText.Length() ;
1265 }
1266 else
1267 {
1268 text = string ;
1269 length = string.Length() ;
1270 }
1271
1272 int laststop = 0 ;
1273 int i = 0 ;
1274 int curwidth = 0 ;
1275 if ( width )
1276 {
1277 *width = 0 ;
1278
1279 while( i < length )
1280 {
1281 if( text[i] == 13 || text[i] == 10)
1282 {
1283 if ( height )
1284 *height += YDEV2LOGREL( fi.descent + fi.ascent + fi.leading ) ;
1285 curwidth = ::TextWidth( text , laststop , i - laststop ) ;
1286 if ( curwidth > *width )
1287 *width = XDEV2LOGREL( curwidth ) ;
1288 laststop = i+1 ;
1289 }
1290 i++ ;
1291 }
1292
1293 curwidth = ::TextWidth( text , laststop , i - laststop ) ;
1294 if ( curwidth > *width )
1295 *width = XDEV2LOGREL( curwidth ) ;
1296 }
1297
1298 if ( theFont )
1299 {
1300 m_macFontInstalled = false ;
1301 }
1302 }
1303
1304 wxCoord wxDC::GetCharWidth(void) const
1305 {
1306 wxCHECK_MSG(Ok(), 1, wxT("Invalid DC"));
1307
1308 wxMacPortSetter helper(this) ;
1309
1310 MacInstallFont() ;
1311
1312 int width = ::TextWidth( "n" , 0 , 1 ) ;
1313
1314 return YDEV2LOGREL(width) ;
1315 }
1316
1317 wxCoord wxDC::GetCharHeight(void) const
1318 {
1319 wxCHECK_MSG(Ok(), 1, wxT("Invalid DC"));
1320
1321 wxMacPortSetter helper(this) ;
1322
1323 MacInstallFont() ;
1324
1325 FontInfo fi ;
1326 ::GetFontInfo( &fi ) ;
1327
1328 return YDEV2LOGREL( fi.descent + fi.ascent );
1329 }
1330
1331 void wxDC::Clear(void)
1332 {
1333 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1334 wxMacPortSetter helper(this) ;
1335 Rect rect = { -32767 , -32767 , 32767 , 32767 } ;
1336
1337 if (m_backgroundBrush.GetStyle() != wxTRANSPARENT)
1338 {
1339 MacInstallBrush() ;
1340 ::EraseRect( &rect ) ;
1341 }
1342 }
1343
1344 void wxDC::MacInstallFont() const
1345 {
1346 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1347 // if ( m_macFontInstalled )
1348 // return ;
1349 Pattern blackColor ;
1350
1351 wxFontRefData * font = (wxFontRefData*) m_font.GetRefData() ;
1352
1353 if ( font )
1354 {
1355 ::TextFont( font->m_macFontNum ) ;
1356 ::TextSize( short(m_scaleY * font->m_macFontSize) ) ;
1357 ::TextFace( font->m_macFontStyle ) ;
1358
1359 m_macFontInstalled = true ;
1360 m_macBrushInstalled = false ;
1361 m_macPenInstalled = false ;
1362
1363 RGBColor forecolor = m_textForegroundColour.GetPixel();
1364 RGBColor backcolor = m_textBackgroundColour.GetPixel();
1365 ::RGBForeColor( &forecolor );
1366 ::RGBBackColor( &backcolor );
1367 }
1368 else
1369 {
1370 short fontnum ;
1371
1372 GetFNum( "\pGeneva" , &fontnum ) ;
1373 ::TextFont( fontnum ) ;
1374 ::TextSize( short(m_scaleY * 10) ) ;
1375 ::TextFace( 0 ) ;
1376
1377 // todo reset after spacing changes - or store the current spacing somewhere
1378
1379 m_macFontInstalled = true ;
1380 m_macBrushInstalled = false ;
1381 m_macPenInstalled = false ;
1382
1383 RGBColor forecolor = m_textForegroundColour.GetPixel();
1384 RGBColor backcolor = m_textBackgroundColour.GetPixel();
1385 ::RGBForeColor( &forecolor );
1386 ::RGBBackColor( &backcolor );
1387 }
1388
1389 short mode = patCopy ;
1390
1391 // todo :
1392
1393 switch( m_logicalFunction )
1394 {
1395 case wxCOPY: // src
1396 mode = patCopy ;
1397 break ;
1398 case wxINVERT: // NOT dst
1399 ::PenPat(GetQDGlobalsBlack(&blackColor));
1400 mode = patXor ;
1401 break ;
1402 case wxXOR: // src XOR dst
1403 mode = patXor ;
1404 break ;
1405 case wxOR_REVERSE: // src OR (NOT dst)
1406 mode = notPatOr ;
1407 break ;
1408 case wxSRC_INVERT: // (NOT src)
1409 mode = notPatCopy ;
1410 break ;
1411
1412 // unsupported TODO
1413
1414 case wxCLEAR: // 0
1415 case wxAND_REVERSE:// src AND (NOT dst)
1416 case wxAND: // src AND dst
1417 case wxAND_INVERT: // (NOT src) AND dst
1418 case wxNO_OP: // dst
1419 case wxNOR: // (NOT src) AND (NOT dst)
1420 case wxEQUIV: // (NOT src) XOR dst
1421 case wxOR_INVERT: // (NOT src) OR dst
1422 case wxNAND: // (NOT src) OR (NOT dst)
1423 case wxOR: // src OR dst
1424 case wxSET: // 1
1425 // case wxSRC_OR: // source _bitmap_ OR destination
1426 // case wxSRC_AND: // source _bitmap_ AND destination
1427 break ;
1428 }
1429 ::PenMode( mode ) ;
1430 }
1431
1432 static void wxMacGetHatchPattern(int hatchStyle, Pattern *pattern)
1433 {
1434 // we have our own pattern list now
1435 int thePatListID = 128;
1436 int theIndex;
1437 switch(hatchStyle)
1438 {
1439 case wxBDIAGONAL_HATCH:
1440 theIndex = 2;
1441 break;
1442 case wxFDIAGONAL_HATCH:
1443 theIndex = 3;
1444 break;
1445 case wxCROSS_HATCH:
1446 theIndex = 4;
1447 break;
1448 case wxHORIZONTAL_HATCH:
1449 theIndex = 5;
1450 break;
1451 case wxVERTICAL_HATCH:
1452 theIndex = 6;
1453 break;
1454 case wxCROSSDIAG_HATCH:
1455 theIndex = 7;
1456 break;
1457 default:
1458 theIndex = 1; // solid pattern
1459 break;
1460 }
1461 GetIndPattern( pattern, thePatListID, theIndex);
1462 }
1463
1464 void wxDC::MacInstallPen() const
1465 {
1466 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1467
1468 Pattern blackColor;
1469
1470 // if ( m_macPenInstalled )
1471 // return ;
1472
1473 RGBColor forecolor = m_pen.GetColour().GetPixel();
1474 RGBColor backcolor = m_backgroundBrush.GetColour().GetPixel();
1475 ::RGBForeColor( &forecolor );
1476 ::RGBBackColor( &backcolor );
1477
1478 ::PenNormal() ;
1479 int penWidth = m_pen.GetWidth() * (int) m_scaleX ;
1480
1481 // null means only one pixel, at whatever resolution
1482 if ( penWidth == 0 )
1483 penWidth = 1 ;
1484 ::PenSize(penWidth, penWidth);
1485
1486 int penStyle = m_pen.GetStyle();
1487
1488 if (penStyle == wxSOLID)
1489 {
1490 ::PenPat(GetQDGlobalsBlack(&blackColor));
1491 }
1492 else if (IS_HATCH(penStyle))
1493 {
1494 Pattern pat ;
1495 wxMacGetHatchPattern(penStyle, &pat);
1496 ::PenPat(&pat);
1497 }
1498 else
1499 {
1500 Pattern pat = *GetQDGlobalsBlack(&blackColor) ;
1501 switch( penStyle )
1502 {
1503 case wxDOT :
1504 for ( int i = 0 ; i < 8 ; ++i )
1505 {
1506 pat.pat[i] = 0xCC ;
1507 }
1508 break ;
1509 case wxLONG_DASH :
1510 for ( int i = 0 ; i < 8 ; ++i )
1511 {
1512 pat.pat[i] = 0xFE ;
1513 }
1514 break ;
1515 case wxSHORT_DASH :
1516 for ( int i = 0 ; i < 8 ; ++i )
1517 {
1518 pat.pat[i] = 0xEE ;
1519 }
1520 break ;
1521 case wxDOT_DASH :
1522 for ( int i = 0 ; i < 8 ; ++i )
1523 {
1524 pat.pat[i] = 0x6F ;
1525 }
1526 break ;
1527 case wxUSER_DASH :
1528 {
1529 wxDash* dash ;
1530 int number = m_pen.GetDashes(&dash) ;
1531 // right now we don't allocate larger pixmaps
1532 for ( int i = 0 ; i < 8 ; ++i )
1533 {
1534 pat.pat[i] = dash[0] ;
1535 }
1536 }
1537 break ;
1538 }
1539 ::PenPat(&pat);
1540 }
1541
1542 short mode = patCopy ;
1543
1544 // todo :
1545
1546 switch( m_logicalFunction )
1547 {
1548 case wxCOPY: // only foreground color, leave background (thus not patCopy)
1549 mode = patOr ;
1550 break ;
1551 case wxINVERT: // NOT dst
1552 // ::PenPat(GetQDGlobalsBlack(&blackColor));
1553 mode = patXor ;
1554 break ;
1555 case wxXOR: // src XOR dst
1556 mode = patXor ;
1557 break ;
1558 case wxOR_REVERSE: // src OR (NOT dst)
1559 mode = notPatOr ;
1560 break ;
1561 case wxSRC_INVERT: // (NOT src)
1562 mode = notPatCopy ;
1563 break ;
1564
1565 // unsupported TODO
1566
1567 case wxCLEAR: // 0
1568 case wxAND_REVERSE:// src AND (NOT dst)
1569 case wxAND: // src AND dst
1570 case wxAND_INVERT: // (NOT src) AND dst
1571 case wxNO_OP: // dst
1572 case wxNOR: // (NOT src) AND (NOT dst)
1573 case wxEQUIV: // (NOT src) XOR dst
1574 case wxOR_INVERT: // (NOT src) OR dst
1575 case wxNAND: // (NOT src) OR (NOT dst)
1576 case wxOR: // src OR dst
1577 case wxSET: // 1
1578 // case wxSRC_OR: // source _bitmap_ OR destination
1579 // case wxSRC_AND: // source _bitmap_ AND destination
1580 break ;
1581 }
1582 ::PenMode( mode ) ;
1583 m_macPenInstalled = true ;
1584 m_macBrushInstalled = false ;
1585 m_macFontInstalled = false ;
1586 }
1587
1588 void wxDC::MacSetupBackgroundForCurrentPort(const wxBrush& background )
1589 {
1590 Pattern whiteColor ;
1591 switch( background.MacGetBrushKind() )
1592 {
1593 case kwxMacBrushTheme :
1594 {
1595 ::SetThemeBackground( background.GetMacTheme() , wxDisplayDepth() , true ) ;
1596 break ;
1597 }
1598 case kwxMacBrushThemeBackground :
1599 {
1600 Rect extent ;
1601 ThemeBackgroundKind bg = background.GetMacThemeBackground( &extent ) ;
1602 ::ApplyThemeBackground( bg , &extent ,kThemeStateActive , wxDisplayDepth() , true ) ;
1603 break ;
1604 }
1605 case kwxMacBrushColour :
1606 {
1607 ::RGBBackColor( &background.GetColour().GetPixel() );
1608 int brushStyle = background.GetStyle();
1609 if (brushStyle == wxSOLID)
1610 ::BackPat(GetQDGlobalsWhite(&whiteColor));
1611 else if (IS_HATCH(brushStyle))
1612 {
1613 Pattern pat ;
1614 wxMacGetHatchPattern(brushStyle, &pat);
1615 ::BackPat(&pat);
1616 }
1617 else
1618 {
1619 ::BackPat(GetQDGlobalsWhite(&whiteColor));
1620 }
1621 break ;
1622 }
1623 }
1624 }
1625
1626 void wxDC::MacInstallBrush() const
1627 {
1628 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1629
1630 Pattern blackColor ;
1631 // if ( m_macBrushInstalled )
1632 // return ;
1633
1634 // foreground
1635
1636 ::RGBForeColor( &m_brush.GetColour().GetPixel() );
1637
1638 int brushStyle = m_brush.GetStyle();
1639 if (brushStyle == wxSOLID)
1640 ::PenPat(GetQDGlobalsBlack(&blackColor));
1641 else if (IS_HATCH(brushStyle))
1642 {
1643 Pattern pat ;
1644 wxMacGetHatchPattern(brushStyle, &pat);
1645 ::PenPat(&pat);
1646 }
1647 else if ( m_brush.GetStyle() == wxSTIPPLE || m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE )
1648 {
1649 // for these the text fore (and back for MASK_OPAQUE) colors are used
1650 wxBitmap* bitmap = m_brush.GetStipple() ;
1651 int width = bitmap->GetWidth() ;
1652 int height = bitmap->GetHeight() ;
1653 int depth = bitmap->GetDepth() ;
1654 if ( m_brush.GetStyle() == wxSTIPPLE )
1655 {
1656 GWorldPtr gw = bitmap->GetHBITMAP() ;
1657 if ( width == 8 && height == 8 && depth == 1)
1658 {
1659 Pattern pat ;
1660 LockPixels( GetGWorldPixMap( gw ) ) ;
1661 BitMap* gwbitmap = (BitMap*) *GetGWorldPixMap( gw ) ; // since the color depth is 1 it is a BitMap
1662 int alignment = gwbitmap->rowBytes & 0x7FFF ;
1663 UInt8 *gwbits = (UInt8*) gwbitmap->baseAddr ;
1664 for ( int i = 0 ; i < 8 ; ++i )
1665 {
1666 pat.pat[i] = gwbits[i*alignment+0] ;
1667 }
1668 UnlockPixels( GetGWorldPixMap( gw ) ) ;
1669
1670 ::PenPat( &pat ) ;
1671 }
1672 else
1673 {
1674 ::PenPat(GetQDGlobalsBlack(&blackColor));
1675 }
1676 }
1677 else if (m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE )
1678 {
1679 ::RGBForeColor( &m_textForegroundColour.GetPixel() );
1680 ::RGBForeColor( &m_textBackgroundColour.GetPixel() );
1681 ::PenPat(GetQDGlobalsBlack(&blackColor));
1682 }
1683 }
1684 else
1685 {
1686 ::PenPat(GetQDGlobalsBlack(&blackColor));
1687 }
1688
1689
1690 // background
1691
1692 MacSetupBackgroundForCurrentPort( m_backgroundBrush ) ;
1693
1694
1695 // todo :
1696
1697 short mode = patCopy ;
1698 switch( m_logicalFunction )
1699 {
1700 case wxCOPY: // src
1701 mode = patCopy ;
1702 break ;
1703 case wxINVERT: // NOT dst
1704 ::PenPat(GetQDGlobalsBlack(&blackColor));
1705 mode = patXor ;
1706 break ;
1707 case wxXOR: // src XOR dst
1708 mode = patXor ;
1709 break ;
1710 case wxOR_REVERSE: // src OR (NOT dst)
1711 mode = notPatOr ;
1712 break ;
1713 case wxSRC_INVERT: // (NOT src)
1714 mode = notPatCopy ;
1715 break ;
1716
1717 // unsupported TODO
1718
1719 case wxCLEAR: // 0
1720 case wxAND_REVERSE:// src AND (NOT dst)
1721 case wxAND: // src AND dst
1722 case wxAND_INVERT: // (NOT src) AND dst
1723 case wxNO_OP: // dst
1724 case wxNOR: // (NOT src) AND (NOT dst)
1725 case wxEQUIV: // (NOT src) XOR dst
1726 case wxOR_INVERT: // (NOT src) OR dst
1727 case wxNAND: // (NOT src) OR (NOT dst)
1728 case wxOR: // src OR dst
1729 case wxSET: // 1
1730 // case wxSRC_OR: // source _bitmap_ OR destination
1731 // case wxSRC_AND: // source _bitmap_ AND destination
1732 break ;
1733 }
1734 ::PenMode( mode ) ;
1735 m_macBrushInstalled = true ;
1736 m_macPenInstalled = false ;
1737 m_macFontInstalled = false ;
1738 }
1739
1740 // ---------------------------------------------------------------------------
1741 // coordinates transformations
1742 // ---------------------------------------------------------------------------
1743
1744
1745 wxCoord wxDCBase::DeviceToLogicalX(wxCoord x) const
1746 {
1747 return ((wxDC *)this)->XDEV2LOG(x);
1748 }
1749
1750 wxCoord wxDCBase::DeviceToLogicalY(wxCoord y) const
1751 {
1752 return ((wxDC *)this)->YDEV2LOG(y);
1753 }
1754
1755 wxCoord wxDCBase::DeviceToLogicalXRel(wxCoord x) const
1756 {
1757 return ((wxDC *)this)->XDEV2LOGREL(x);
1758 }
1759
1760 wxCoord wxDCBase::DeviceToLogicalYRel(wxCoord y) const
1761 {
1762 return ((wxDC *)this)->YDEV2LOGREL(y);
1763 }
1764
1765 wxCoord wxDCBase::LogicalToDeviceX(wxCoord x) const
1766 {
1767 return ((wxDC *)this)->XLOG2DEV(x);
1768 }
1769
1770 wxCoord wxDCBase::LogicalToDeviceY(wxCoord y) const
1771 {
1772 return ((wxDC *)this)->YLOG2DEV(y);
1773 }
1774
1775 wxCoord wxDCBase::LogicalToDeviceXRel(wxCoord x) const
1776 {
1777 return ((wxDC *)this)->XLOG2DEVREL(x);
1778 }
1779
1780 wxCoord wxDCBase::LogicalToDeviceYRel(wxCoord y) const
1781 {
1782 return ((wxDC *)this)->YLOG2DEVREL(y);
1783 }