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