]> git.saurik.com Git - wxWidgets.git/blame - src/mac/dc.cpp
suppressed wrong debug error messages from SetFocus
[wxWidgets.git] / src / mac / dc.cpp
CommitLineData
e9576ca5
SC
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"
03e11df5 17#include "wx/app.h"
2f1ae414 18#include "wx/mac/uma.h"
3dec57ad
SC
19#include "wx/dcmemory.h"
20#include "wx/region.h"
21#include "wx/image.h"
e9576ca5 22
5b781a67
SC
23#if __MSL__ >= 0x6000
24#include "math.h"
25#endif
26
2f1ae414 27#if !USE_SHARED_LIBRARY
e9576ca5 28IMPLEMENT_ABSTRACT_CLASS(wxDC, wxObject)
2f1ae414 29#endif
e9576ca5
SC
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
f5c6eb5c 41#ifndef __DARWIN__
3dec57ad 42const double M_PI = 3.14159265358979 ;
2461b2e7 43#endif
3dec57ad
SC
44const double RAD2DEG = 180.0 / M_PI;
45
46//-----------------------------------------------------------------------------
47// Local functions
48//-----------------------------------------------------------------------------
49
50static inline double dmin(double a, double b) { return a < b ? a : b; }
51static inline double dmax(double a, double b) { return a > b ? a : b; }
52static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; }
e9576ca5
SC
53
54//-----------------------------------------------------------------------------
55// wxDC
56//-----------------------------------------------------------------------------
57
2f1ae414 58wxDC::wxDC()
e9576ca5
SC
59{
60 m_ok = FALSE;
e9576ca5 61 m_colour = TRUE;
e9576ca5 62
2f1ae414
SC
63 m_mm_to_pix_x = mm2pt;
64 m_mm_to_pix_y = mm2pt;
e9576ca5 65
e9576ca5
SC
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
e9576ca5
SC
78 m_needComputeScaleX = FALSE;
79 m_needComputeScaleY = FALSE;
80
e9576ca5
SC
81 m_maxX = m_maxY = -100000;
82 m_minY = m_minY = 100000;
83
519cb848 84 m_macPort = NULL ;
8208e181 85 m_macMask = NULL ;
519cb848
SC
86 m_ok = FALSE ;
87
88 m_macFontInstalled = false ;
89 m_macBrushInstalled = false ;
90 m_macPenInstalled = false ;
91
519cb848 92 m_macLocalOrigin.h = m_macLocalOrigin.v = 0 ;
ffba56ed
SC
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 ) ;
9ff647cf
SC
98
99 m_pen = *wxBLACK_PEN;
100 m_font = *wxNORMAL_FONT;
101 m_brush = *wxWHITE_BRUSH;
3dec57ad 102}
f87a708b 103wxMacPortSetter::wxMacPortSetter( const wxDC* dc ) :
0eaa1d68
SC
104 m_ph( dc->m_macPort )
105{
106 wxASSERT( dc->Ok() ) ;
107
108 dc->MacSetupPort(&m_ph) ;
109}
110
111wxMacPortSetter::~wxMacPortSetter()
112{
113}
114
e9576ca5
SC
115wxDC::~wxDC(void)
116{
ffba56ed
SC
117 DisposeRgn( m_macBoundaryClipRgn ) ;
118 DisposeRgn( m_macCurrentClipRgn ) ;
3dec57ad 119}
0eaa1d68 120void wxDC::MacSetupPort(AGAPortHelper* help) const
519cb848 121{
ffba56ed 122 SetClip( m_macCurrentClipRgn);
519cb848
SC
123
124 m_macFontInstalled = false ;
125 m_macBrushInstalled = false ;
126 m_macPenInstalled = false ;
127}
128
2f1ae414 129void wxDC::DoDrawBitmap( const wxBitmap &bmp, wxCoord x, wxCoord y, bool useMask )
519cb848 130{
3dec57ad
SC
131 wxCHECK_RET( Ok(), wxT("invalid window dc") );
132
133 wxCHECK_RET( bmp.Ok(), wxT("invalid bitmap") );
134
135 wxMacPortSetter helper(this) ;
136
7d9d1fd7
SC
137 wxCoord xx = XLOG2DEVMAC(x);
138 wxCoord yy = YLOG2DEVMAC(y);
3dec57ad
SC
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 ) ;
519cb848 163 }
3dec57ad
SC
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
519cb848
SC
224}
225
2f1ae414 226void wxDC::DoDrawIcon( const wxIcon &icon, wxCoord x, wxCoord y )
e9576ca5 227{
3dec57ad
SC
228 wxCHECK_RET(Ok(), wxT("Invalid dc wxDC::DoDrawIcon"));
229
230 wxCHECK_RET(icon.Ok(), wxT("Invalid icon wxDC::DoDrawIcon"));
231
a2f94f40 232 DoDrawBitmap( icon , x , y , icon.GetMask() != NULL ) ;
3dec57ad 233}
2f1ae414 234void wxDC::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
e9576ca5 235{
3dec57ad
SC
236 wxCHECK_RET(Ok(), wxT("wxDC::DoSetClippingRegion Invalid DC"));
237 wxCoord xx, yy, ww, hh;
238
7d9d1fd7
SC
239 xx = XLOG2DEVMAC(x);
240 yy = YLOG2DEVMAC(y);
3dec57ad
SC
241 ww = XLOG2DEVREL(width);
242 hh = YLOG2DEVREL(height);
e9576ca5 243
ffba56ed
SC
244 SetRectRgn( m_macCurrentClipRgn , xx , yy , xx + ww , yy + hh ) ;
245 SectRgn( m_macCurrentClipRgn , m_macBoundaryClipRgn , m_macCurrentClipRgn ) ;
246
3dec57ad
SC
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}
2f1ae414
SC
264void wxDC::DoSetClippingRegionAsRegion( const wxRegion &region )
265{
3dec57ad 266 wxCHECK_RET( Ok(), wxT("invalid window dc") ) ;
2f1ae414 267
0eaa1d68 268 wxMacPortSetter helper(this) ;
2f1ae414
SC
269 if (region.Empty())
270 {
271 DestroyClippingRegion();
272 return;
273 }
274
ffba56ed
SC
275 wxCoord x, y, w, h;
276 region.GetBox( x, y, w, h );
2f1ae414 277 wxCoord xx, yy, ww, hh;
ffba56ed 278
7d9d1fd7
SC
279 xx = XLOG2DEVMAC(x);
280 yy = YLOG2DEVMAC(y);
ffba56ed
SC
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
ee41971c
UJ
316}
317
3dec57ad 318void wxDC::DestroyClippingRegion()
e9576ca5 319{
0eaa1d68 320 wxMacPortSetter helper(this) ;
ffba56ed 321 CopyRgn( m_macBoundaryClipRgn , m_macCurrentClipRgn ) ;
e9576ca5 322 m_clipping = FALSE;
3dec57ad 323}
2f1ae414 324void wxDC::DoGetSize( int* width, int* height ) const
e9576ca5
SC
325{
326 *width = m_maxX-m_minX;
327 *height = m_maxY-m_minY;
3dec57ad 328}
2f1ae414 329void wxDC::DoGetSizeMM( int* width, int* height ) const
e9576ca5
SC
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) );
3dec57ad 336}
e9576ca5
SC
337void wxDC::SetTextForeground( const wxColour &col )
338{
3dec57ad
SC
339 wxCHECK_RET(Ok(), wxT("Invalid DC"));
340 m_textForegroundColour = col;
341 m_macFontInstalled = false ;
342}
e9576ca5
SC
343void wxDC::SetTextBackground( const wxColour &col )
344{
3dec57ad
SC
345 wxCHECK_RET(Ok(), wxT("Invalid DC"));
346 m_textBackgroundColour = col;
347 m_macFontInstalled = false ;
348}
e9576ca5
SC
349void wxDC::SetMapMode( int mode )
350{
351 switch (mode)
352 {
e3065973 353 case wxMM_TWIPS:
e9576ca5
SC
354 SetLogicalScale( twips2mm*m_mm_to_pix_x, twips2mm*m_mm_to_pix_y );
355 break;
e3065973 356 case wxMM_POINTS:
e9576ca5
SC
357 SetLogicalScale( pt2mm*m_mm_to_pix_x, pt2mm*m_mm_to_pix_y );
358 break;
e3065973 359 case wxMM_METRIC:
e9576ca5
SC
360 SetLogicalScale( m_mm_to_pix_x, m_mm_to_pix_y );
361 break;
e3065973 362 case wxMM_LOMETRIC:
e9576ca5
SC
363 SetLogicalScale( m_mm_to_pix_x/10.0, m_mm_to_pix_y/10.0 );
364 break;
365 default:
e3065973 366 case wxMM_TEXT:
e9576ca5
SC
367 SetLogicalScale( 1.0, 1.0 );
368 break;
3dec57ad 369 }
e3065973 370 if (mode != wxMM_TEXT)
e9576ca5
SC
371 {
372 m_needComputeScaleX = TRUE;
373 m_needComputeScaleY = TRUE;
3dec57ad
SC
374 }
375}
e9576ca5
SC
376void wxDC::SetUserScale( double x, double y )
377{
378 // allow negative ? -> no
379 m_userScaleX = x;
380 m_userScaleY = y;
381 ComputeScaleAndOrigin();
3dec57ad 382}
e9576ca5
SC
383void wxDC::SetLogicalScale( double x, double y )
384{
385 // allow negative ?
386 m_logicalScaleX = x;
387 m_logicalScaleY = y;
388 ComputeScaleAndOrigin();
3dec57ad 389}
2f1ae414 390void wxDC::SetLogicalOrigin( wxCoord x, wxCoord y )
e9576ca5
SC
391{
392 m_logicalOriginX = x * m_signX; // is this still correct ?
393 m_logicalOriginY = y * m_signY;
394 ComputeScaleAndOrigin();
3dec57ad 395}
2f1ae414 396void wxDC::SetDeviceOrigin( wxCoord x, wxCoord y )
e9576ca5
SC
397{
398 m_externalDeviceOriginX = x;
399 m_externalDeviceOriginY = y;
400 ComputeScaleAndOrigin();
3dec57ad
SC
401}
402
403#if 0
e9576ca5
SC
404void wxDC::SetInternalDeviceOrigin( long x, long y )
405{
406 m_internalDeviceOriginX = x;
407 m_internalDeviceOriginY = y;
408 ComputeScaleAndOrigin();
3dec57ad 409}
e9576ca5
SC
410void wxDC::GetInternalDeviceOrigin( long *x, long *y )
411{
412 if (x) *x = m_internalDeviceOriginX;
413 if (y) *y = m_internalDeviceOriginY;
3dec57ad
SC
414}
415#endif
e9576ca5
SC
416void wxDC::SetAxisOrientation( bool xLeftRight, bool yBottomUp )
417{
418 m_signX = (xLeftRight ? 1 : -1);
419 m_signY = (yBottomUp ? -1 : 1);
420 ComputeScaleAndOrigin();
3dec57ad 421}/*
e9576ca5
SC
422
423void 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;
3dec57ad 429}*/
2f1ae414
SC
430wxSize wxDC::GetPPI() const
431{
432 return wxSize(72, 72);
433}
434
435int wxDC::GetDepth() const
436{
437 return wxDisplayDepth() ;
438}
e9576ca5 439
3dec57ad 440void wxDC::ComputeScaleAndOrigin()
e9576ca5
SC
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 {
5b781a67
SC
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);
e9576ca5 461 }
3dec57ad 462}
519cb848
SC
463void wxDC::SetPalette( const wxPalette& palette )
464{
465}
466
467void wxDC::SetBackgroundMode( int mode )
468{
469 m_backgroundMode = mode ;
470}
471
472void wxDC::SetFont( const wxFont &font )
473{
3dec57ad
SC
474 m_font = font;
475 m_macFontInstalled = false ;
519cb848
SC
476}
477
478void wxDC::SetPen( const wxPen &pen )
479{
519cb848
SC
480 if ( m_pen == pen )
481 return ;
482
483 m_pen = pen;
3dec57ad 484
519cb848
SC
485 m_macPenInstalled = false ;
486}
487
488void wxDC::SetBrush( const wxBrush &brush )
489{
519cb848
SC
490 if (m_brush == brush)
491 return;
492
493 m_brush = brush;
494 m_macBrushInstalled = false ;
495}
496
497void wxDC::SetBackground( const wxBrush &brush )
498{
519cb848
SC
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
509void 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
2f1ae414
SC
520void wxDC::DoFloodFill( wxCoord x, wxCoord y, const wxColour& col,
521 int style )
519cb848
SC
522{
523}
524
2f1ae414 525bool wxDC::DoGetPixel( wxCoord x, wxCoord y, wxColour *col ) const
519cb848 526{
3dec57ad
SC
527 wxCHECK_MSG( Ok(), false, wxT("wxDC::DoGetPixel Invalid DC") );
528 wxMacPortSetter helper(this) ;
529
530 RGBColor colour;
531
7d9d1fd7 532 GetCPixel( XLOG2DEVMAC(x), YLOG2DEVMAC(y), &colour );
3dec57ad
SC
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 ;
519cb848
SC
540}
541
2f1ae414 542void wxDC::DoDrawLine( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2 )
519cb848 543{
3dec57ad 544 wxCHECK_RET(Ok(), wxT("Invalid DC"));
519cb848 545
0eaa1d68 546 wxMacPortSetter helper(this) ;
519cb848
SC
547
548 if (m_pen.GetStyle() != wxTRANSPARENT)
549 {
550 MacInstallPen() ;
3dec57ad
SC
551 wxCoord offset = ( (m_pen.GetWidth() == 0 ? 1 :
552 m_pen.GetWidth() ) * (wxCoord)m_scaleX - 1) / 2;
553
7d9d1fd7
SC
554 wxCoord xx1 = XLOG2DEVMAC(x1) - offset;
555 wxCoord yy1 = YLOG2DEVMAC(y1) - offset;
556 wxCoord xx2 = XLOG2DEVMAC(x2) - offset;
557 wxCoord yy2 = YLOG2DEVMAC(y2) - offset;
2301e281
RR
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);
3dec57ad 582 }
519cb848
SC
583}
584
2f1ae414 585void wxDC::DoCrossHair( wxCoord x, wxCoord y )
519cb848 586{
3dec57ad
SC
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 );
7d9d1fd7
SC
594 wxCoord xx = XLOG2DEVMAC(x);
595 wxCoord yy = YLOG2DEVMAC(y);
3dec57ad
SC
596
597 MacInstallPen();
7d9d1fd7
SC
598 ::MoveTo( XLOG2DEVMAC(0), yy );
599 ::LineTo( XLOG2DEVMAC(w), yy );
600 ::MoveTo( xx, YLOG2DEVMAC(0) );
601 ::LineTo( xx, YLOG2DEVMAC(h) );
3dec57ad
SC
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 */
616static 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;
519cb848
SC
638}
639
2f1ae414
SC
640void wxDC::DoDrawArc( wxCoord x1, wxCoord y1,
641 wxCoord x2, wxCoord y2,
642 wxCoord xc, wxCoord yc )
519cb848 643{
3dec57ad
SC
644 wxCHECK_RET(Ok(), wxT("wxDC::DoDrawArc Invalid DC"));
645
7d9d1fd7
SC
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);
3dec57ad
SC
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 }
519cb848
SC
692}
693
2f1ae414
SC
694void wxDC::DoDrawEllipticArc( wxCoord x, wxCoord y, wxCoord w, wxCoord h,
695 double sa, double ea )
519cb848 696{
3dec57ad
SC
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
7d9d1fd7
SC
702 wxCoord xx = XLOG2DEVMAC(x);
703 wxCoord yy = YLOG2DEVMAC(y);
3dec57ad
SC
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 }
519cb848
SC
726}
727
2f1ae414 728void wxDC::DoDrawPoint( wxCoord x, wxCoord y )
519cb848 729{
3dec57ad 730 wxCHECK_RET(Ok(), wxT("Invalid DC"));
519cb848 731
0eaa1d68 732 wxMacPortSetter helper(this) ;
519cb848
SC
733
734 if (m_pen.GetStyle() != wxTRANSPARENT)
735 {
736 MacInstallPen() ;
7d9d1fd7
SC
737 wxCoord xx1 = XLOG2DEVMAC(x);
738 wxCoord yy1 = YLOG2DEVMAC(y);
519cb848
SC
739
740 ::MoveTo(xx1,yy1);
741 ::LineTo(xx1+1, yy1+1);
3dec57ad 742 }
519cb848
SC
743}
744
2f1ae414
SC
745void wxDC::DoDrawLines(int n, wxPoint points[],
746 wxCoord xoffset, wxCoord yoffset)
519cb848 747{
3dec57ad 748 wxCHECK_RET(Ok(), wxT("Invalid DC"));
0eaa1d68 749 wxMacPortSetter helper(this) ;
519cb848
SC
750
751 if (m_pen.GetStyle() == wxTRANSPARENT)
752 return;
753
03e11df5 754 MacInstallPen() ;
519cb848 755
3dec57ad
SC
756 wxCoord offset = ( (m_pen.GetWidth() == 0 ? 1 :
757 m_pen.GetWidth() ) * (wxCoord)m_scaleX - 1) / 2 ;
758
759 wxCoord x1, x2 , y1 , y2 ;
7d9d1fd7
SC
760 x1 = XLOG2DEVMAC(points[0].x + xoffset);
761 y1 = YLOG2DEVMAC(points[0].y + yoffset);
3dec57ad 762 ::MoveTo(x1 - offset, y1 - offset );
519cb848
SC
763
764 for (int i = 0; i < n-1; i++)
765 {
7d9d1fd7
SC
766 x2 = XLOG2DEVMAC(points[i+1].x + xoffset);
767 y2 = YLOG2DEVMAC(points[i+1].y + yoffset);
3dec57ad 768 ::LineTo( x2 - offset, y2 - offset );
519cb848
SC
769 }
770}
771
2f1ae414
SC
772void wxDC::DoDrawPolygon(int n, wxPoint points[],
773 wxCoord xoffset, wxCoord yoffset,
774 int fillStyle )
519cb848 775{
32ea1f98
RR
776 wxCHECK_RET(Ok(), wxT("Invalid DC"));
777 wxMacPortSetter helper(this) ;
778
779 wxCoord x1, x2 , y1 , y2 ;
519cb848 780
75f7bc3b
SC
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
32ea1f98
RR
799 if (m_brush.GetStyle() != wxTRANSPARENT)
800 {
32ea1f98
RR
801
802 MacInstallBrush();
803 ::PaintPoly( polygon );
804
3dec57ad 805 }
519cb848
SC
806
807 if (m_pen.GetStyle() != wxTRANSPARENT)
808 {
32ea1f98 809
519cb848
SC
810 MacInstallPen() ;
811 ::FramePoly( polygon ) ;
32ea1f98 812
3dec57ad 813 }
75f7bc3b 814 KillPoly( polygon );
519cb848
SC
815}
816
3dec57ad 817void wxDC::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
519cb848 818{
3dec57ad
SC
819 wxCHECK_RET(Ok(), wxT("Invalid DC"));
820 wxMacPortSetter helper(this) ;
821
7d9d1fd7
SC
822 wxCoord xx = XLOG2DEVMAC(x);
823 wxCoord yy = YLOG2DEVMAC(y);
3dec57ad
SC
824 wxCoord ww = m_signX * XLOG2DEVREL(width);
825 wxCoord hh = m_signY * YLOG2DEVREL(height);
519cb848
SC
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 ) ;
3dec57ad 850 }
519cb848
SC
851
852 if (m_pen.GetStyle() != wxTRANSPARENT)
853 {
854 MacInstallPen() ;
855 ::FrameRect( &rect ) ;
3dec57ad 856 }
519cb848
SC
857}
858
2f1ae414
SC
859void wxDC::DoDrawRoundedRectangle(wxCoord x, wxCoord y,
860 wxCoord width, wxCoord height,
861 double radius)
519cb848 862{
3dec57ad
SC
863 wxCHECK_RET(Ok(), wxT("Invalid DC"));
864 wxMacPortSetter helper(this) ;
519cb848 865
3dec57ad
SC
866 if (radius < 0.0)
867 radius = - radius * ((width < height) ? width : height);
519cb848 868
7d9d1fd7
SC
869 wxCoord xx = XLOG2DEVMAC(x);
870 wxCoord yy = YLOG2DEVMAC(y);
3dec57ad
SC
871 wxCoord ww = m_signX * XLOG2DEVREL(width);
872 wxCoord hh = m_signY * YLOG2DEVREL(height);
519cb848
SC
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() ;
03e11df5 896 ::PaintRoundRect( &rect , int(radius * 2) , int(radius * 2) ) ;
3dec57ad 897 }
519cb848
SC
898
899 if (m_pen.GetStyle() != wxTRANSPARENT)
900 {
901 MacInstallPen() ;
03e11df5 902 ::FrameRoundRect( &rect , int(radius * 2) , int(radius * 2) ) ;
3dec57ad 903 }
519cb848
SC
904}
905
2f1ae414 906void wxDC::DoDrawEllipse(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
519cb848 907{
3dec57ad
SC
908 wxCHECK_RET(Ok(), wxT("Invalid DC"));
909 wxMacPortSetter helper(this) ;
519cb848 910
7d9d1fd7
SC
911 wxCoord xx = XLOG2DEVMAC(x);
912 wxCoord yy = YLOG2DEVMAC(y);
3dec57ad
SC
913 wxCoord ww = m_signX * XLOG2DEVREL(width);
914 wxCoord hh = m_signY * YLOG2DEVREL(height);
519cb848
SC
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 ) ;
3dec57ad 939 }
519cb848
SC
940
941 if (m_pen.GetStyle() != wxTRANSPARENT)
942 {
943 MacInstallPen() ;
944 ::FrameOval( &rect ) ;
3dec57ad 945 }
519cb848
SC
946}
947
519cb848
SC
948
949
950bool wxDC::CanDrawBitmap(void) const
951{
952 return true ;
953}
954
955
2f1ae414 956bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
0cbff120
JS
957 wxDC *source, wxCoord xsrc, wxCoord ysrc, int logical_func , bool useMask,
958 wxCoord xsrcMask, wxCoord ysrcMask )
519cb848 959{
3dec57ad
SC
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) ;
519cb848 963
0cbff120
JS
964 /* TODO: use the mask origin when drawing transparently */
965 if (xsrcMask == -1 && ysrcMask == -1)
966 {
967 xsrcMask = xsrc; ysrcMask = ysrc;
968 }
969
519cb848
SC
970 CGrafPtr sourcePort = (CGrafPtr) source->m_macPort ;
971 PixMapHandle bmappixels = GetGWorldPixMap( sourcePort ) ;
03e11df5
GD
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 ) ;
519cb848
SC
978
979 if ( LockPixels(bmappixels) )
980 {
981 Rect srcrect , dstrect ;
7d9d1fd7
SC
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 ) ;
8208e181
SC
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 :
2f1ae414 1001 // logical_func == wxSRC_OR ? srcOr :
8208e181
SC
1002 // logical_func == wxSRC_AND ? SRCAND :
1003 srcCopy );
1004
1005 if ( useMask && source->m_macMask )
1006 {
1dcbbdcf
SC
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 }
8208e181
SC
1032 }
1033 else
1034 {
3dec57ad
SC
1035 CopyBits( GetPortBitMapForCopyBits( sourcePort ) ,
1036 GetPortBitMapForCopyBits( m_macPort ) ,
8208e181
SC
1037 &srcrect, &dstrect, mode, NULL ) ;
1038 }
519cb848
SC
1039 UnlockPixels( bmappixels ) ;
1040 }
1041
1042 m_macPenInstalled = false ;
1043 m_macBrushInstalled = false ;
1044 m_macFontInstalled = false ;
1045
1046 return TRUE;
1047}
1048
2f1ae414 1049void wxDC::DoDrawRotatedText(const wxString& text, wxCoord x, wxCoord y,
3dec57ad 1050 double angle)
2f1ae414 1051{
3dec57ad
SC
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 {
7d9d1fd7 1127 SetCPixel(XLOG2DEVMAC(x + dstX), YLOG2DEVMAC(y + dstY),
3dec57ad
SC
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 {
7d9d1fd7
SC
1138 ::MoveTo(XLOG2DEVMAC(x + x4), YLOG2DEVMAC(y + y4 + font->descent));
1139 ::LineTo(XLOG2DEVMAC(x + x3), YLOG2DEVMAC(y + y3 + font->descent));
3dec57ad
SC
1140 }
1141#endif // 0
1142
1143 // update the bounding box
1144 CalcBoundingBox(x + minX, y + minY);
1145 CalcBoundingBox(x + maxX, y + maxY);
2f1ae414
SC
1146}
1147void wxDC::DoDrawText(const wxString& strtext, wxCoord x, wxCoord y)
519cb848 1148{
3dec57ad
SC
1149 wxCHECK_RET(Ok(), wxT("wxDC::DoDrawText Invalid DC"));
1150 wxMacPortSetter helper(this) ;
519cb848 1151
7d9d1fd7
SC
1152 long xx = XLOG2DEVMAC(x);
1153 long yy = YLOG2DEVMAC(y);
519cb848
SC
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 {
2f1ae414 1184 macText = wxMacMakeMacStringFromPC( strtext ) ;
519cb848
SC
1185 text = macText ;
1186 length = macText.Length() ;
1187 }
1188 else
1189 {
2f1ae414
SC
1190 text = strtext ;
1191 length = strtext.Length() ;
519cb848
SC
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
3dec57ad 1215bool wxDC::CanGetTextExtent() const
519cb848 1216{
3dec57ad 1217 wxCHECK_MSG(Ok(), false, wxT("Invalid DC"));
519cb848
SC
1218
1219 return true ;
1220}
1221
2f1ae414
SC
1222void wxDC::DoGetTextExtent( const wxString &string, wxCoord *width, wxCoord *height,
1223 wxCoord *descent, wxCoord *externalLeading ,
1224 wxFont *theFont ) const
519cb848 1225{
3dec57ad 1226 wxCHECK_RET(Ok(), wxT("Invalid DC"));
0eaa1d68 1227 wxMacPortSetter helper(this) ;
519cb848
SC
1228
1229 wxFont formerFont = m_font ;
1230
1231 if ( theFont )
1232 {
1233 wxFontRefData * font = (wxFontRefData*) m_font.GetRefData() ;
1234
1235 if ( font )
1236 {
519cb848 1237 ::TextFont( font->m_macFontNum ) ;
2f1ae414 1238 ::TextSize( YLOG2DEVREL( font->m_macFontSize) ) ;
519cb848
SC
1239 ::TextFace( font->m_macFontStyle ) ;
1240 }
1241 }
1242 else
1243 {
1244 MacInstallFont() ;
1245 }
1246
1247 FontInfo fi ;
1248 ::GetFontInfo( &fi ) ;
1249
2f1ae414
SC
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 ) ;
519cb848
SC
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 ;
2f1ae414 1275 if ( width )
519cb848 1276 {
2f1ae414
SC
1277 *width = 0 ;
1278
1279 while( i < length )
519cb848 1280 {
2f1ae414
SC
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++ ;
519cb848 1291 }
2f1ae414
SC
1292
1293 curwidth = ::TextWidth( text , laststop , i - laststop ) ;
1294 if ( curwidth > *width )
1295 *width = XDEV2LOGREL( curwidth ) ;
519cb848 1296 }
519cb848
SC
1297
1298 if ( theFont )
1299 {
1300 m_macFontInstalled = false ;
1301 }
1302}
1303
ee41971c 1304wxCoord wxDC::GetCharWidth(void) const
519cb848 1305{
3dec57ad 1306 wxCHECK_MSG(Ok(), 1, wxT("Invalid DC"));
519cb848 1307
0eaa1d68 1308 wxMacPortSetter helper(this) ;
519cb848
SC
1309
1310 MacInstallFont() ;
1311
c257d44d 1312 int width = ::TextWidth( "n" , 0 , 1 ) ;
519cb848 1313
c257d44d 1314 return YDEV2LOGREL(width) ;
519cb848
SC
1315}
1316
ee41971c 1317wxCoord wxDC::GetCharHeight(void) const
519cb848 1318{
3dec57ad 1319 wxCHECK_MSG(Ok(), 1, wxT("Invalid DC"));
519cb848 1320
3dec57ad 1321 wxMacPortSetter helper(this) ;
519cb848
SC
1322
1323 MacInstallFont() ;
1324
1325 FontInfo fi ;
1326 ::GetFontInfo( &fi ) ;
1327
2f1ae414 1328 return YDEV2LOGREL( fi.descent + fi.ascent );
519cb848
SC
1329}
1330
1331void wxDC::Clear(void)
1332{
3dec57ad
SC
1333 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1334 wxMacPortSetter helper(this) ;
519cb848
SC
1335 Rect rect = { -32767 , -32767 , 32767 , 32767 } ;
1336
1337 if (m_backgroundBrush.GetStyle() != wxTRANSPARENT)
1338 {
1339 MacInstallBrush() ;
1340 ::EraseRect( &rect ) ;
3dec57ad 1341 }
519cb848
SC
1342}
1343
1344void wxDC::MacInstallFont() const
1345{
3dec57ad 1346 wxCHECK_RET(Ok(), wxT("Invalid DC"));
0eaa1d68
SC
1347// if ( m_macFontInstalled )
1348// return ;
2f1ae414
SC
1349 Pattern blackColor ;
1350
519cb848
SC
1351 wxFontRefData * font = (wxFontRefData*) m_font.GetRefData() ;
1352
1353 if ( font )
1354 {
1355 ::TextFont( font->m_macFontNum ) ;
03e11df5 1356 ::TextSize( short(m_scaleY * font->m_macFontSize) ) ;
519cb848
SC
1357 ::TextFace( font->m_macFontStyle ) ;
1358
1359 m_macFontInstalled = true ;
1360 m_macBrushInstalled = false ;
1361 m_macPenInstalled = false ;
03e11df5
GD
1362
1363 RGBColor forecolor = m_textForegroundColour.GetPixel();
1364 RGBColor backcolor = m_textBackgroundColour.GetPixel();
1365 ::RGBForeColor( &forecolor );
1366 ::RGBBackColor( &backcolor );
519cb848
SC
1367 }
1368 else
1369 {
1370 short fontnum ;
1371
1372 GetFNum( "\pGeneva" , &fontnum ) ;
1373 ::TextFont( fontnum ) ;
03e11df5 1374 ::TextSize( short(m_scaleY * 10) ) ;
519cb848
SC
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 ;
519cb848 1382
03e11df5
GD
1383 RGBColor forecolor = m_textForegroundColour.GetPixel();
1384 RGBColor backcolor = m_textBackgroundColour.GetPixel();
1385 ::RGBForeColor( &forecolor );
1386 ::RGBBackColor( &backcolor );
1387 }
519cb848
SC
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
2f1ae414 1399 ::PenPat(GetQDGlobalsBlack(&blackColor));
519cb848
SC
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
2f1ae414
SC
1425// case wxSRC_OR: // source _bitmap_ OR destination
1426// case wxSRC_AND: // source _bitmap_ AND destination
519cb848
SC
1427 break ;
1428 }
1429 ::PenMode( mode ) ;
1430}
1431
1432static void wxMacGetHatchPattern(int hatchStyle, Pattern *pattern)
1433{
75f7bc3b
SC
1434 // we have our own pattern list now
1435 int thePatListID = 128;
519cb848
SC
1436 int theIndex;
1437 switch(hatchStyle)
1438 {
1439 case wxBDIAGONAL_HATCH:
75f7bc3b 1440 theIndex = 2;
519cb848
SC
1441 break;
1442 case wxFDIAGONAL_HATCH:
75f7bc3b 1443 theIndex = 3;
519cb848
SC
1444 break;
1445 case wxCROSS_HATCH:
75f7bc3b 1446 theIndex = 4;
519cb848
SC
1447 break;
1448 case wxHORIZONTAL_HATCH:
75f7bc3b 1449 theIndex = 5;
519cb848
SC
1450 break;
1451 case wxVERTICAL_HATCH:
1452 theIndex = 6;
1453 break;
1454 case wxCROSSDIAG_HATCH:
75f7bc3b 1455 theIndex = 7;
519cb848
SC
1456 break;
1457 default:
1458 theIndex = 1; // solid pattern
1459 break;
1460 }
1461 GetIndPattern( pattern, thePatListID, theIndex);
1462}
1463
1464void wxDC::MacInstallPen() const
1465{
3dec57ad 1466 wxCHECK_RET(Ok(), wxT("Invalid DC"));
519cb848 1467
2f1ae414
SC
1468 Pattern blackColor;
1469
0eaa1d68
SC
1470// if ( m_macPenInstalled )
1471// return ;
519cb848 1472
03e11df5
GD
1473 RGBColor forecolor = m_pen.GetColour().GetPixel();
1474 RGBColor backcolor = m_backgroundBrush.GetColour().GetPixel();
1475 ::RGBForeColor( &forecolor );
1476 ::RGBBackColor( &backcolor );
519cb848
SC
1477
1478 ::PenNormal() ;
3dec57ad 1479 int penWidth = m_pen.GetWidth() * (int) m_scaleX ;
0b014ec7
SC
1480
1481 // null means only one pixel, at whatever resolution
1482 if ( penWidth == 0 )
1483 penWidth = 1 ;
519cb848
SC
1484 ::PenSize(penWidth, penWidth);
1485
1486 int penStyle = m_pen.GetStyle();
1487
1488 if (penStyle == wxSOLID)
03e11df5 1489 {
2f1ae414 1490 ::PenPat(GetQDGlobalsBlack(&blackColor));
03e11df5 1491 }
519cb848
SC
1492 else if (IS_HATCH(penStyle))
1493 {
1494 Pattern pat ;
1495 wxMacGetHatchPattern(penStyle, &pat);
1496 ::PenPat(&pat);
1497 }
1498 else
1499 {
1ff301c4
SC
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);
519cb848
SC
1540 }
1541
1542 short mode = patCopy ;
1543
1544 // todo :
1545
1546 switch( m_logicalFunction )
1547 {
1ff301c4
SC
1548 case wxCOPY: // only foreground color, leave background (thus not patCopy)
1549 mode = patOr ;
519cb848
SC
1550 break ;
1551 case wxINVERT: // NOT dst
1ff301c4 1552// ::PenPat(GetQDGlobalsBlack(&blackColor));
519cb848
SC
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
2f1ae414
SC
1578// case wxSRC_OR: // source _bitmap_ OR destination
1579// case wxSRC_AND: // source _bitmap_ AND destination
519cb848
SC
1580 break ;
1581 }
1582 ::PenMode( mode ) ;
1583 m_macPenInstalled = true ;
1584 m_macBrushInstalled = false ;
1585 m_macFontInstalled = false ;
1586}
1587
7d9d1fd7 1588void wxDC::MacSetupBackgroundForCurrentPort(const wxBrush& background )
1dcbbdcf
SC
1589{
1590 Pattern whiteColor ;
7d9d1fd7
SC
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 }
1dcbbdcf
SC
1624}
1625
519cb848
SC
1626void wxDC::MacInstallBrush() const
1627{
3dec57ad 1628 wxCHECK_RET(Ok(), wxT("Invalid DC"));
0eaa1d68 1629
1dcbbdcf 1630 Pattern blackColor ;
0eaa1d68
SC
1631// if ( m_macBrushInstalled )
1632// return ;
519cb848
SC
1633
1634 // foreground
1635
1dcbbdcf 1636 ::RGBForeColor( &m_brush.GetColour().GetPixel() );
519cb848
SC
1637
1638 int brushStyle = m_brush.GetStyle();
1639 if (brushStyle == wxSOLID)
2f1ae414 1640 ::PenPat(GetQDGlobalsBlack(&blackColor));
519cb848
SC
1641 else if (IS_HATCH(brushStyle))
1642 {
1643 Pattern pat ;
1644 wxMacGetHatchPattern(brushStyle, &pat);
1645 ::PenPat(&pat);
1646 }
1ff301c4 1647 else if ( m_brush.GetStyle() == wxSTIPPLE || m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE )
519cb848 1648 {
1ff301c4
SC
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));
519cb848
SC
1687 }
1688
1689
1690 // background
1691
1dcbbdcf 1692 MacSetupBackgroundForCurrentPort( m_backgroundBrush ) ;
519cb848 1693
519cb848
SC
1694
1695 // todo :
1696
1dcbbdcf 1697 short mode = patCopy ;
519cb848
SC
1698 switch( m_logicalFunction )
1699 {
1700 case wxCOPY: // src
1701 mode = patCopy ;
1702 break ;
1703 case wxINVERT: // NOT dst
2f1ae414 1704 ::PenPat(GetQDGlobalsBlack(&blackColor));
519cb848
SC
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
2f1ae414
SC
1730// case wxSRC_OR: // source _bitmap_ OR destination
1731// case wxSRC_AND: // source _bitmap_ AND destination
519cb848
SC
1732 break ;
1733 }
1734 ::PenMode( mode ) ;
1735 m_macBrushInstalled = true ;
1736 m_macPenInstalled = false ;
1737 m_macFontInstalled = false ;
1738}
1739
2f1ae414
SC
1740// ---------------------------------------------------------------------------
1741// coordinates transformations
1742// ---------------------------------------------------------------------------
519cb848 1743
2f1ae414
SC
1744
1745wxCoord wxDCBase::DeviceToLogicalX(wxCoord x) const
1746{
1747 return ((wxDC *)this)->XDEV2LOG(x);
1748}
1749
1750wxCoord wxDCBase::DeviceToLogicalY(wxCoord y) const
1751{
1752 return ((wxDC *)this)->YDEV2LOG(y);
1753}
1754
1755wxCoord wxDCBase::DeviceToLogicalXRel(wxCoord x) const
1756{
1757 return ((wxDC *)this)->XDEV2LOGREL(x);
1758}
1759
1760wxCoord wxDCBase::DeviceToLogicalYRel(wxCoord y) const
1761{
1762 return ((wxDC *)this)->YDEV2LOGREL(y);
1763}
1764
1765wxCoord wxDCBase::LogicalToDeviceX(wxCoord x) const
1766{
1767 return ((wxDC *)this)->XLOG2DEV(x);
1768}
1769
1770wxCoord wxDCBase::LogicalToDeviceY(wxCoord y) const
1771{
1772 return ((wxDC *)this)->YLOG2DEV(y);
1773}
1774
1775wxCoord wxDCBase::LogicalToDeviceXRel(wxCoord x) const
1776{
1777 return ((wxDC *)this)->XLOG2DEVREL(x);
1778}
1779
1780wxCoord wxDCBase::LogicalToDeviceYRel(wxCoord y) const
1781{
1782 return ((wxDC *)this)->YLOG2DEVREL(y);
1783}