]> git.saurik.com Git - wxWidgets.git/blame - src/mac/dc.cpp
minor compilation warning corrections
[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
76a5e5d2 23
5b781a67
SC
24#if __MSL__ >= 0x6000
25#include "math.h"
b34039cf 26using namespace std ;
5b781a67
SC
27#endif
28
b34039cf 29#include "wx/mac/private.h"
66a09d47
SC
30#include "ATSUnicode.h"
31#include "TextCommon.h"
32#include "TextEncodingConverter.h"
b34039cf 33
2f1ae414 34#if !USE_SHARED_LIBRARY
e9576ca5 35IMPLEMENT_ABSTRACT_CLASS(wxDC, wxObject)
2f1ae414 36#endif
e9576ca5
SC
37
38//-----------------------------------------------------------------------------
39// constants
40//-----------------------------------------------------------------------------
41
42#define mm2inches 0.0393700787402
43#define inches2mm 25.4
44#define mm2twips 56.6929133859
45#define twips2mm 0.0176388888889
46#define mm2pt 2.83464566929
47#define pt2mm 0.352777777778
f5c6eb5c 48#ifndef __DARWIN__
3dec57ad 49const double M_PI = 3.14159265358979 ;
2461b2e7 50#endif
3dec57ad 51const double RAD2DEG = 180.0 / M_PI;
76a5e5d2
SC
52const short kEmulatedMode = -1 ;
53const short kUnsupportedMode = -2 ;
54
66a09d47
SC
55wxMacPortSetter::wxMacPortSetter( const wxDC* dc ) :
56 m_ph( (GrafPtr) dc->m_macPort )
57{
58 wxASSERT( dc->Ok() ) ;
59 m_dc = dc ;
60 dc->MacSetupPort(&m_ph) ;
61}
62
63wxMacPortSetter::~wxMacPortSetter()
64{
65 m_dc->MacCleanupPort(&m_ph) ;
66}
67
3dec57ad
SC
68//-----------------------------------------------------------------------------
69// Local functions
70//-----------------------------------------------------------------------------
71
72static inline double dmin(double a, double b) { return a < b ? a : b; }
73static inline double dmax(double a, double b) { return a > b ? a : b; }
74static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; }
e9576ca5
SC
75
76//-----------------------------------------------------------------------------
77// wxDC
78//-----------------------------------------------------------------------------
79
76a5e5d2
SC
80// this function emulates all wx colour manipulations, used to verify the implementation
81// by setting the mode in the blitting functions to kEmulatedMode
82
83void wxMacCalculateColour( int logical_func , const RGBColor &srcColor , RGBColor &dstColor ) ;
84void wxMacCalculateColour( int logical_func , const RGBColor &srcColor , RGBColor &dstColor )
85{
86 switch ( logical_func )
87 {
88 case wxAND: // src AND dst
89 dstColor.red = dstColor.red & srcColor.red ;
90 dstColor.green = dstColor.green & srcColor.green ;
91 dstColor.blue = dstColor.blue & srcColor.blue ;
92 break ;
93 case wxAND_INVERT: // (NOT src) AND dst
94 dstColor.red = dstColor.red & ~srcColor.red ;
95 dstColor.green = dstColor.green & ~srcColor.green ;
96 dstColor.blue = dstColor.blue & ~srcColor.blue ;
97 break ;
98 case wxAND_REVERSE:// src AND (NOT dst)
99 dstColor.red = ~dstColor.red & srcColor.red ;
100 dstColor.green = ~dstColor.green & srcColor.green ;
101 dstColor.blue = ~dstColor.blue & srcColor.blue ;
102 break ;
103 case wxCLEAR: // 0
104 dstColor.red = 0 ;
105 dstColor.green = 0 ;
106 dstColor.blue = 0 ;
107 break ;
108 case wxCOPY: // src
109 dstColor.red = srcColor.red ;
110 dstColor.green = srcColor.green ;
111 dstColor.blue = srcColor.blue ;
112 break ;
113 case wxEQUIV: // (NOT src) XOR dst
114 dstColor.red = dstColor.red ^ ~srcColor.red ;
115 dstColor.green = dstColor.green ^ ~srcColor.green ;
116 dstColor.blue = dstColor.blue ^ ~srcColor.blue ;
117 break ;
118 case wxINVERT: // NOT dst
119 dstColor.red = ~dstColor.red ;
120 dstColor.green = ~dstColor.green ;
121 dstColor.blue = ~dstColor.blue ;
122 break ;
123 case wxNAND: // (NOT src) OR (NOT dst)
124 dstColor.red = ~dstColor.red | ~srcColor.red ;
125 dstColor.green = ~dstColor.green | ~srcColor.green ;
126 dstColor.blue = ~dstColor.blue | ~srcColor.blue ;
127 break ;
128 case wxNOR: // (NOT src) AND (NOT dst)
129 dstColor.red = ~dstColor.red & ~srcColor.red ;
130 dstColor.green = ~dstColor.green & ~srcColor.green ;
131 dstColor.blue = ~dstColor.blue & ~srcColor.blue ;
132 break ;
133 case wxNO_OP: // dst
134 break ;
135 case wxOR: // src OR dst
136 dstColor.red = dstColor.red | srcColor.red ;
137 dstColor.green = dstColor.green | srcColor.green ;
138 dstColor.blue = dstColor.blue | srcColor.blue ;
139 break ;
140 case wxOR_INVERT: // (NOT src) OR dst
141 dstColor.red = dstColor.red | ~srcColor.red ;
142 dstColor.green = dstColor.green | ~srcColor.green ;
143 dstColor.blue = dstColor.blue | ~srcColor.blue ;
144 break ;
145 case wxOR_REVERSE: // src OR (NOT dst)
146 dstColor.red = ~dstColor.red | srcColor.red ;
147 dstColor.green = ~dstColor.green | srcColor.green ;
148 dstColor.blue = ~dstColor.blue | srcColor.blue ;
149 break ;
150 case wxSET: // 1
151 dstColor.red = 0xFFFF ;
152 dstColor.green = 0xFFFF ;
153 dstColor.blue = 0xFFFF ;
154 break ;
155 case wxSRC_INVERT: // (NOT src)
156 dstColor.red = ~srcColor.red ;
157 dstColor.green = ~srcColor.green ;
158 dstColor.blue = ~srcColor.blue ;
159 break ;
160 case wxXOR: // src XOR dst
161 dstColor.red = dstColor.red ^ srcColor.red ;
162 dstColor.green = dstColor.green ^ srcColor.green ;
163 dstColor.blue = dstColor.blue ^ srcColor.blue ;
164 break ;
165 }
166
167}
168
2f1ae414 169wxDC::wxDC()
e9576ca5
SC
170{
171 m_ok = FALSE;
e9576ca5 172 m_colour = TRUE;
e9576ca5 173
2f1ae414
SC
174 m_mm_to_pix_x = mm2pt;
175 m_mm_to_pix_y = mm2pt;
e9576ca5 176
e9576ca5
SC
177 m_internalDeviceOriginX = 0;
178 m_internalDeviceOriginY = 0;
179 m_externalDeviceOriginX = 0;
180 m_externalDeviceOriginY = 0;
181
182 m_logicalScaleX = 1.0;
183 m_logicalScaleY = 1.0;
184 m_userScaleX = 1.0;
185 m_userScaleY = 1.0;
186 m_scaleX = 1.0;
187 m_scaleY = 1.0;
188
e9576ca5
SC
189 m_needComputeScaleX = FALSE;
190 m_needComputeScaleY = FALSE;
191
519cb848 192 m_macPort = NULL ;
8208e181 193 m_macMask = NULL ;
519cb848
SC
194 m_ok = FALSE ;
195
196 m_macFontInstalled = false ;
197 m_macBrushInstalled = false ;
198 m_macPenInstalled = false ;
199
76a5e5d2 200 m_macLocalOrigin.x = m_macLocalOrigin.y = 0 ;
ffba56ed
SC
201 m_macBoundaryClipRgn = NewRgn() ;
202 m_macCurrentClipRgn = NewRgn() ;
203
76a5e5d2
SC
204 SetRectRgn( (RgnHandle) m_macBoundaryClipRgn , -32000 , -32000 , 32000 , 32000 ) ;
205 SetRectRgn( (RgnHandle) m_macCurrentClipRgn , -32000 , -32000 , 32000 , 32000 ) ;
9ff647cf
SC
206
207 m_pen = *wxBLACK_PEN;
208 m_font = *wxNORMAL_FONT;
209 m_brush = *wxWHITE_BRUSH;
66a09d47
SC
210 m_macCurrentPortStateHelper = NULL ;
211 m_macATSUIStyle = NULL ;
212 m_macAliasWasEnabled = false;
213 m_macForegroundPixMap = NULL ;
214 m_macBackgroundPixMap = NULL ;
0eaa1d68
SC
215}
216
e9576ca5
SC
217wxDC::~wxDC(void)
218{
76a5e5d2
SC
219 DisposeRgn( (RgnHandle) m_macBoundaryClipRgn ) ;
220 DisposeRgn( (RgnHandle) m_macCurrentClipRgn ) ;
3dec57ad 221}
76a5e5d2 222void wxDC::MacSetupPort(wxMacPortStateHelper* help) const
519cb848 223{
66a09d47
SC
224 wxASSERT( m_macCurrentPortStateHelper == NULL ) ;
225 m_macCurrentPortStateHelper = help ;
76a5e5d2 226 SetClip( (RgnHandle) m_macCurrentClipRgn);
519cb848
SC
227
228 m_macFontInstalled = false ;
229 m_macBrushInstalled = false ;
230 m_macPenInstalled = false ;
231}
232
66a09d47
SC
233void wxDC::MacCleanupPort(wxMacPortStateHelper* help) const
234{
235 wxASSERT( m_macCurrentPortStateHelper == help ) ;
236 m_macCurrentPortStateHelper = NULL ;
237 if( m_macATSUIStyle )
238 {
239 ::ATSUDisposeStyle((ATSUStyle)m_macATSUIStyle);
240 m_macATSUIStyle = NULL ;
241 }
242 if ( m_macAliasWasEnabled )
243 {
244 SetAntiAliasedTextEnabled(m_macFormerAliasState, m_macFormerAliasSize);
245 m_macAliasWasEnabled = false ;
246 }
247 if ( m_macForegroundPixMap )
248 {
249 Pattern blackColor ;
250 ::PenPat(GetQDGlobalsBlack(&blackColor));
c99d6f99 251 DisposePixPat( (PixPatHandle) m_macForegroundPixMap ) ;
66a09d47
SC
252 m_macForegroundPixMap = NULL ;
253 }
254 if ( m_macBackgroundPixMap )
255 {
256 Pattern whiteColor ;
257 ::BackPat(GetQDGlobalsWhite(&whiteColor));
c99d6f99 258 DisposePixPat( (PixPatHandle) m_macBackgroundPixMap ) ;
66a09d47
SC
259 m_macBackgroundPixMap = NULL ;
260 }
261}
262
2f1ae414 263void wxDC::DoDrawBitmap( const wxBitmap &bmp, wxCoord x, wxCoord y, bool useMask )
519cb848 264{
3dec57ad
SC
265 wxCHECK_RET( Ok(), wxT("invalid window dc") );
266
267 wxCHECK_RET( bmp.Ok(), wxT("invalid bitmap") );
268
269 wxMacPortSetter helper(this) ;
270
7d9d1fd7
SC
271 wxCoord xx = XLOG2DEVMAC(x);
272 wxCoord yy = YLOG2DEVMAC(y);
3dec57ad
SC
273 wxCoord w = bmp.GetWidth();
274 wxCoord h = bmp.GetHeight();
275 wxCoord ww = XLOG2DEVREL(w);
276 wxCoord hh = YLOG2DEVREL(h);
277
278 // Set up drawing mode
279 short mode = (m_logicalFunction == wxCOPY ? srcCopy :
280 //m_logicalFunction == wxCLEAR ? WHITENESS :
281 //m_logicalFunction == wxSET ? BLACKNESS :
282 m_logicalFunction == wxINVERT ? hilite :
283 //m_logicalFunction == wxAND ? MERGECOPY :
284 m_logicalFunction == wxOR ? srcOr :
285 m_logicalFunction == wxSRC_INVERT ? notSrcCopy :
286 m_logicalFunction == wxXOR ? srcXor :
287 m_logicalFunction == wxOR_REVERSE ? notSrcOr :
288 //m_logicalFunction == wxAND_REVERSE ? SRCERASE :
289 //m_logicalFunction == wxSRC_OR ? srcOr :
290 //m_logicalFunction == wxSRC_AND ? SRCAND :
291 srcCopy );
292
293 if ( bmp.GetBitmapType() == kMacBitmapTypePict ) {
294 Rect bitmaprect = { 0 , 0 , hh, ww };
295 ::OffsetRect( &bitmaprect, xx, yy ) ;
76a5e5d2 296 ::DrawPicture( (PicHandle) bmp.GetPict(), &bitmaprect ) ;
519cb848 297 }
3dec57ad
SC
298 else if ( bmp.GetBitmapType() == kMacBitmapTypeGrafWorld )
299 {
76a5e5d2 300 GWorldPtr bmapworld = MAC_WXHBITMAP( bmp.GetHBITMAP() );
3dec57ad
SC
301 PixMapHandle bmappixels ;
302
303 // Set foreground and background colours (for bitmaps depth = 1)
304 if(bmp.GetDepth() == 1)
305 {
76a5e5d2
SC
306 RGBColor fore = MAC_WXCOLORREF(m_textForegroundColour.GetPixel());
307 RGBColor back = MAC_WXCOLORREF(m_textBackgroundColour.GetPixel());
3dec57ad
SC
308 RGBForeColor(&fore);
309 RGBBackColor(&back);
310 }
311 else
312 {
313 RGBColor white = { 0xFFFF, 0xFFFF,0xFFFF} ;
314 RGBColor black = { 0,0,0} ;
315 RGBForeColor( &black ) ;
316 RGBBackColor( &white ) ;
317 }
318
319 bmappixels = GetGWorldPixMap( bmapworld ) ;
320
321 wxCHECK_RET(LockPixels(bmappixels),
322 wxT("DoDrawBitmap: Unable to lock pixels"));
323
324 Rect source = { 0, 0, h, w };
325 Rect dest = { yy, xx, yy + hh, xx + ww };
326
327 if ( useMask && bmp.GetMask() )
328 {
76a5e5d2 329 if( LockPixels(GetGWorldPixMap(MAC_WXHBITMAP(bmp.GetMask()->GetMaskBitmap()))))
3dec57ad
SC
330 {
331 CopyDeepMask
332 (
333 GetPortBitMapForCopyBits(bmapworld),
76a5e5d2
SC
334 GetPortBitMapForCopyBits(MAC_WXHBITMAP(bmp.GetMask()->GetMaskBitmap())),
335 GetPortBitMapForCopyBits( MAC_WXHBITMAP(m_macPort) ),
3dec57ad
SC
336 &source, &source, &dest, mode, NULL
337 );
76a5e5d2 338 UnlockPixels(GetGWorldPixMap(MAC_WXHBITMAP(bmp.GetMask()->GetMaskBitmap())));
3dec57ad
SC
339 }
340 }
341 else {
342 CopyBits( GetPortBitMapForCopyBits( bmapworld ),
76a5e5d2 343 GetPortBitMapForCopyBits( MAC_WXHBITMAP(m_macPort) ),
3dec57ad
SC
344 &source, &dest, mode, NULL ) ;
345 }
346 UnlockPixels( bmappixels ) ;
347 }
348 else if ( bmp.GetBitmapType() == kMacBitmapTypeIcon )
349 {
350 Rect bitmaprect = { 0 , 0 , bmp.GetHeight(), bmp.GetWidth() } ;
351 OffsetRect( &bitmaprect, xx, yy ) ;
76a5e5d2 352 PlotCIconHandle( &bitmaprect , atNone , ttNone , MAC_WXHICON(bmp.GetHICON()) ) ;
3dec57ad
SC
353 }
354 m_macPenInstalled = false ;
355 m_macBrushInstalled = false ;
356 m_macFontInstalled = false ;
357
519cb848
SC
358}
359
2f1ae414 360void wxDC::DoDrawIcon( const wxIcon &icon, wxCoord x, wxCoord y )
e9576ca5 361{
3dec57ad
SC
362 wxCHECK_RET(Ok(), wxT("Invalid dc wxDC::DoDrawIcon"));
363
364 wxCHECK_RET(icon.Ok(), wxT("Invalid icon wxDC::DoDrawIcon"));
365
a2f94f40 366 DoDrawBitmap( icon , x , y , icon.GetMask() != NULL ) ;
3dec57ad 367}
2f1ae414 368void wxDC::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
e9576ca5 369{
3dec57ad
SC
370 wxCHECK_RET(Ok(), wxT("wxDC::DoSetClippingRegion Invalid DC"));
371 wxCoord xx, yy, ww, hh;
372
7d9d1fd7
SC
373 xx = XLOG2DEVMAC(x);
374 yy = YLOG2DEVMAC(y);
3dec57ad
SC
375 ww = XLOG2DEVREL(width);
376 hh = YLOG2DEVREL(height);
e9576ca5 377
76a5e5d2
SC
378 SetRectRgn( (RgnHandle) m_macCurrentClipRgn , xx , yy , xx + ww , yy + hh ) ;
379 SectRgn( (RgnHandle) m_macCurrentClipRgn , (RgnHandle) m_macBoundaryClipRgn , (RgnHandle) m_macCurrentClipRgn ) ;
ffba56ed 380
3dec57ad
SC
381 if( m_clipping )
382 {
383 m_clipX1 = wxMax( m_clipX1 , xx );
384 m_clipY1 = wxMax( m_clipY1 , yy );
385 m_clipX2 = wxMin( m_clipX2, (xx + ww));
386 m_clipY2 = wxMin( m_clipY2, (yy + hh));
387 }
388 else
389 {
390 m_clipping = TRUE;
391 m_clipX1 = xx;
392 m_clipY1 = yy;
393 m_clipX2 = xx + ww;
394 m_clipY2 = yy + hh;
395 }
396
397}
2f1ae414
SC
398void wxDC::DoSetClippingRegionAsRegion( const wxRegion &region )
399{
3dec57ad 400 wxCHECK_RET( Ok(), wxT("invalid window dc") ) ;
2f1ae414 401
0eaa1d68 402 wxMacPortSetter helper(this) ;
2f1ae414
SC
403 if (region.Empty())
404 {
405 DestroyClippingRegion();
406 return;
407 }
408
ffba56ed
SC
409 wxCoord x, y, w, h;
410 region.GetBox( x, y, w, h );
2f1ae414 411 wxCoord xx, yy, ww, hh;
ffba56ed 412
7d9d1fd7
SC
413 xx = XLOG2DEVMAC(x);
414 yy = YLOG2DEVMAC(y);
ffba56ed
SC
415 ww = XLOG2DEVREL(w);
416 hh = YLOG2DEVREL(h);
417
418 // if we have a scaling that we cannot map onto native regions
419 // we must use the box
420
421 if ( ww != w || hh != h )
422 {
423 wxDC::DoSetClippingRegion( x, y, w, h );
424 }
425 else
426 {
76a5e5d2 427 CopyRgn( (RgnHandle) region.GetWXHRGN() , (RgnHandle) m_macCurrentClipRgn ) ;
ffba56ed
SC
428 if ( xx != x || yy != y )
429 {
76a5e5d2 430 OffsetRgn( (RgnHandle) m_macCurrentClipRgn , xx - x , yy - y ) ;
ffba56ed 431 }
76a5e5d2 432 SectRgn( (RgnHandle) m_macCurrentClipRgn , (RgnHandle) m_macBoundaryClipRgn , (RgnHandle) m_macCurrentClipRgn ) ;
ffba56ed
SC
433 if( m_clipping )
434 {
435 m_clipX1 = wxMax( m_clipX1 , xx );
436 m_clipY1 = wxMax( m_clipY1 , yy );
437 m_clipX2 = wxMin( m_clipX2, (xx + ww));
438 m_clipY2 = wxMin( m_clipY2, (yy + hh));
439 }
440 else
441 {
442 m_clipping = TRUE;
443 m_clipX1 = xx;
444 m_clipY1 = yy;
445 m_clipX2 = xx + ww;
446 m_clipY2 = yy + hh;
447 }
448 }
449
ee41971c
UJ
450}
451
3dec57ad 452void wxDC::DestroyClippingRegion()
e9576ca5 453{
0eaa1d68 454 wxMacPortSetter helper(this) ;
76a5e5d2 455 CopyRgn( (RgnHandle) m_macBoundaryClipRgn , (RgnHandle) m_macCurrentClipRgn ) ;
e9576ca5 456 m_clipping = FALSE;
3dec57ad 457}
2f1ae414 458void wxDC::DoGetSize( int* width, int* height ) const
e9576ca5
SC
459{
460 *width = m_maxX-m_minX;
461 *height = m_maxY-m_minY;
3dec57ad 462}
2f1ae414 463void wxDC::DoGetSizeMM( int* width, int* height ) const
e9576ca5
SC
464{
465 int w = 0;
466 int h = 0;
467 GetSize( &w, &h );
468 *width = long( double(w) / (m_scaleX*m_mm_to_pix_x) );
469 *height = long( double(h) / (m_scaleY*m_mm_to_pix_y) );
3dec57ad 470}
e9576ca5
SC
471void wxDC::SetTextForeground( const wxColour &col )
472{
3dec57ad
SC
473 wxCHECK_RET(Ok(), wxT("Invalid DC"));
474 m_textForegroundColour = col;
475 m_macFontInstalled = false ;
476}
e9576ca5
SC
477void wxDC::SetTextBackground( const wxColour &col )
478{
3dec57ad
SC
479 wxCHECK_RET(Ok(), wxT("Invalid DC"));
480 m_textBackgroundColour = col;
481 m_macFontInstalled = false ;
482}
e9576ca5
SC
483void wxDC::SetMapMode( int mode )
484{
485 switch (mode)
486 {
e3065973 487 case wxMM_TWIPS:
e9576ca5
SC
488 SetLogicalScale( twips2mm*m_mm_to_pix_x, twips2mm*m_mm_to_pix_y );
489 break;
e3065973 490 case wxMM_POINTS:
e9576ca5
SC
491 SetLogicalScale( pt2mm*m_mm_to_pix_x, pt2mm*m_mm_to_pix_y );
492 break;
e3065973 493 case wxMM_METRIC:
e9576ca5
SC
494 SetLogicalScale( m_mm_to_pix_x, m_mm_to_pix_y );
495 break;
e3065973 496 case wxMM_LOMETRIC:
e9576ca5
SC
497 SetLogicalScale( m_mm_to_pix_x/10.0, m_mm_to_pix_y/10.0 );
498 break;
499 default:
e3065973 500 case wxMM_TEXT:
e9576ca5
SC
501 SetLogicalScale( 1.0, 1.0 );
502 break;
3dec57ad 503 }
e3065973 504 if (mode != wxMM_TEXT)
e9576ca5
SC
505 {
506 m_needComputeScaleX = TRUE;
507 m_needComputeScaleY = TRUE;
3dec57ad
SC
508 }
509}
e9576ca5
SC
510void wxDC::SetUserScale( double x, double y )
511{
512 // allow negative ? -> no
513 m_userScaleX = x;
514 m_userScaleY = y;
515 ComputeScaleAndOrigin();
3dec57ad 516}
e9576ca5
SC
517void wxDC::SetLogicalScale( double x, double y )
518{
519 // allow negative ?
520 m_logicalScaleX = x;
521 m_logicalScaleY = y;
522 ComputeScaleAndOrigin();
3dec57ad 523}
2f1ae414 524void wxDC::SetLogicalOrigin( wxCoord x, wxCoord y )
e9576ca5
SC
525{
526 m_logicalOriginX = x * m_signX; // is this still correct ?
527 m_logicalOriginY = y * m_signY;
528 ComputeScaleAndOrigin();
3dec57ad 529}
2f1ae414 530void wxDC::SetDeviceOrigin( wxCoord x, wxCoord y )
e9576ca5
SC
531{
532 m_externalDeviceOriginX = x;
533 m_externalDeviceOriginY = y;
534 ComputeScaleAndOrigin();
3dec57ad
SC
535}
536
537#if 0
e9576ca5
SC
538void wxDC::SetInternalDeviceOrigin( long x, long y )
539{
540 m_internalDeviceOriginX = x;
541 m_internalDeviceOriginY = y;
542 ComputeScaleAndOrigin();
3dec57ad 543}
e9576ca5
SC
544void wxDC::GetInternalDeviceOrigin( long *x, long *y )
545{
546 if (x) *x = m_internalDeviceOriginX;
547 if (y) *y = m_internalDeviceOriginY;
3dec57ad
SC
548}
549#endif
e9576ca5
SC
550void wxDC::SetAxisOrientation( bool xLeftRight, bool yBottomUp )
551{
552 m_signX = (xLeftRight ? 1 : -1);
553 m_signY = (yBottomUp ? -1 : 1);
554 ComputeScaleAndOrigin();
76a5e5d2
SC
555}
556
2f1ae414
SC
557wxSize wxDC::GetPPI() const
558{
559 return wxSize(72, 72);
560}
561
562int wxDC::GetDepth() const
563{
c99d6f99
SC
564 if ( IsPortColor( (CGrafPtr) m_macPort ) )
565 {
566 return ( (**GetPortPixMap( (CGrafPtr) m_macPort)).pixelSize ) ;
567 }
568 return 1 ;
2f1ae414 569}
e9576ca5 570
3dec57ad 571void wxDC::ComputeScaleAndOrigin()
e9576ca5
SC
572{
573 // CMB: copy scale to see if it changes
574 double origScaleX = m_scaleX;
575 double origScaleY = m_scaleY;
576
577 m_scaleX = m_logicalScaleX * m_userScaleX;
578 m_scaleY = m_logicalScaleY * m_userScaleY;
579
580 m_deviceOriginX = m_internalDeviceOriginX + m_externalDeviceOriginX;
581 m_deviceOriginY = m_internalDeviceOriginY + m_externalDeviceOriginY;
582
583 // CMB: if scale has changed call SetPen to recalulate the line width
584 if (m_scaleX != origScaleX || m_scaleY != origScaleY)
585 {
5b781a67
SC
586 // this is a bit artificial, but we need to force wxDC to think
587 // the pen has changed
588 wxPen* pen = & GetPen();
589 wxPen tempPen;
590 m_pen = tempPen;
591 SetPen(* pen);
e9576ca5 592 }
3dec57ad 593}
519cb848
SC
594void wxDC::SetPalette( const wxPalette& palette )
595{
596}
597
598void wxDC::SetBackgroundMode( int mode )
599{
600 m_backgroundMode = mode ;
601}
602
603void wxDC::SetFont( const wxFont &font )
604{
3dec57ad
SC
605 m_font = font;
606 m_macFontInstalled = false ;
519cb848
SC
607}
608
609void wxDC::SetPen( const wxPen &pen )
610{
519cb848
SC
611 if ( m_pen == pen )
612 return ;
613
614 m_pen = pen;
3dec57ad 615
519cb848
SC
616 m_macPenInstalled = false ;
617}
618
619void wxDC::SetBrush( const wxBrush &brush )
620{
519cb848
SC
621 if (m_brush == brush)
622 return;
623
624 m_brush = brush;
625 m_macBrushInstalled = false ;
626}
627
628void wxDC::SetBackground( const wxBrush &brush )
629{
519cb848
SC
630 if (m_backgroundBrush == brush)
631 return;
632
633 m_backgroundBrush = brush;
634
635 if (!m_backgroundBrush.Ok())
636 return;
637 m_macBrushInstalled = false ;
638}
639
640void wxDC::SetLogicalFunction( int function )
641{
642 if (m_logicalFunction == function)
643 return;
644
645 m_logicalFunction = function ;
646 m_macFontInstalled = false ;
647 m_macBrushInstalled = false ;
648 m_macPenInstalled = false ;
649}
650
2f1ae414
SC
651void wxDC::DoFloodFill( wxCoord x, wxCoord y, const wxColour& col,
652 int style )
519cb848
SC
653{
654}
655
2f1ae414 656bool wxDC::DoGetPixel( wxCoord x, wxCoord y, wxColour *col ) const
519cb848 657{
3dec57ad
SC
658 wxCHECK_MSG( Ok(), false, wxT("wxDC::DoGetPixel Invalid DC") );
659 wxMacPortSetter helper(this) ;
660
661 RGBColor colour;
662
7d9d1fd7 663 GetCPixel( XLOG2DEVMAC(x), YLOG2DEVMAC(y), &colour );
3dec57ad
SC
664
665 // Convert from Mac colour to wx
666 col->Set( colour.red >> 8,
667 colour.green >> 8,
668 colour.blue >> 8);
669
670 return true ;
519cb848
SC
671}
672
2f1ae414 673void wxDC::DoDrawLine( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2 )
519cb848 674{
3dec57ad 675 wxCHECK_RET(Ok(), wxT("Invalid DC"));
519cb848 676
0eaa1d68 677 wxMacPortSetter helper(this) ;
519cb848
SC
678
679 if (m_pen.GetStyle() != wxTRANSPARENT)
680 {
681 MacInstallPen() ;
3dec57ad
SC
682 wxCoord offset = ( (m_pen.GetWidth() == 0 ? 1 :
683 m_pen.GetWidth() ) * (wxCoord)m_scaleX - 1) / 2;
684
7d9d1fd7
SC
685 wxCoord xx1 = XLOG2DEVMAC(x1) - offset;
686 wxCoord yy1 = YLOG2DEVMAC(y1) - offset;
687 wxCoord xx2 = XLOG2DEVMAC(x2) - offset;
688 wxCoord yy2 = YLOG2DEVMAC(y2) - offset;
2301e281
RR
689
690 if ((m_pen.GetCap() == wxCAP_ROUND) &&
691 (m_pen.GetWidth() <= 1))
692 {
693 // Implement LAST_NOT for MAC at least for
694 // orthogonal lines. RR.
695 if (xx1 == xx2)
696 {
697 if (yy1 < yy2)
698 yy2--;
699 if (yy1 > yy2)
700 yy2++;
701 }
702 if (yy1 == yy2)
703 {
704 if (xx1 < xx2)
705 xx2--;
706 if (xx1 > xx2)
707 xx2++;
708 }
709 }
710
711 ::MoveTo(xx1, yy1);
712 ::LineTo(xx2, yy2);
3dec57ad 713 }
519cb848
SC
714}
715
2f1ae414 716void wxDC::DoCrossHair( wxCoord x, wxCoord y )
519cb848 717{
3dec57ad
SC
718 wxCHECK_RET( Ok(), wxT("wxDC::DoCrossHair Invalid window dc") );
719
720 if (m_pen.GetStyle() != wxTRANSPARENT)
721 {
722 int w = 0;
723 int h = 0;
724 GetSize( &w, &h );
7d9d1fd7
SC
725 wxCoord xx = XLOG2DEVMAC(x);
726 wxCoord yy = YLOG2DEVMAC(y);
3dec57ad
SC
727
728 MacInstallPen();
7d9d1fd7
SC
729 ::MoveTo( XLOG2DEVMAC(0), yy );
730 ::LineTo( XLOG2DEVMAC(w), yy );
731 ::MoveTo( xx, YLOG2DEVMAC(0) );
732 ::LineTo( xx, YLOG2DEVMAC(h) );
66a09d47
SC
733
734 CalcBoundingBox(x, y);
735 CalcBoundingBox(x+w, y+h);
736
3dec57ad
SC
737 }
738}
739
740/*
741 * To draw arcs properly the angles need to be converted from the WX style:
742 * Angles start on the +ve X axis and go anti-clockwise (As you would draw on
743 * a normal axis on paper).
744 * TO
745 * the Mac style:
746 * Angles start on the +ve y axis and go clockwise.
747 * To achive this I work out which quadrant the angle lies in then map this to
748 * the equivalent quadrant on the Mac. (Sin and Cos values reveal which
749 * quadrant you are in).
750 */
751static double wxConvertWXangleToMACangle(double angle)
752{
753 double sin_a, cos_a;
754
755 sin_a = sin(angle / RAD2DEG);
756 cos_a = cos(angle / RAD2DEG);
757
758 if( (sin_a >= 0.0) && (cos_a >= 0.0) ) {
759 angle = acos(sin_a) * RAD2DEG;
760 }
761 else if( (sin_a >= 0.0) && (cos_a <= 0.0) ) {
762 sin_a *= -1;
763 angle = acos(sin_a) * RAD2DEG + 180;
764 }
765 else if( (sin_a <= 0.0) && (cos_a >= 0.0) ) {
766 angle = acos(sin_a) * RAD2DEG + 180;
767 }
768 else if( (sin_a < 0.0) && (cos_a < 0.0) ) {
769 sin_a *= -1;
770 angle = acos(sin_a) * RAD2DEG + 180;
771 }
772 return angle;
519cb848
SC
773}
774
2f1ae414
SC
775void wxDC::DoDrawArc( wxCoord x1, wxCoord y1,
776 wxCoord x2, wxCoord y2,
777 wxCoord xc, wxCoord yc )
519cb848 778{
3dec57ad
SC
779 wxCHECK_RET(Ok(), wxT("wxDC::DoDrawArc Invalid DC"));
780
7d9d1fd7
SC
781 wxCoord xx1 = XLOG2DEVMAC(x1);
782 wxCoord yy1 = YLOG2DEVMAC(y1);
783 wxCoord xx2 = XLOG2DEVMAC(x2);
784 wxCoord yy2 = YLOG2DEVMAC(y2);
785 wxCoord xxc = XLOG2DEVMAC(xc);
786 wxCoord yyc = YLOG2DEVMAC(yc);
3dec57ad
SC
787 double dx = xx1 - xxc;
788 double dy = yy1 - yyc;
789 double radius = sqrt((double)(dx*dx+dy*dy));
790 wxCoord rad = (wxCoord)radius;
791 double radius1, radius2;
792
793 if (xx1 == xx2 && yy1 == yy2)
794 {
795 radius1 = 0.0;
796 radius2 = 360.0;
797 }
798 else if (radius == 0.0)
799 {
800 radius1 = radius2 = 0.0;
801 }
802 else
803 {
804 radius1 = (xx1 - xxc == 0) ?
805 (yy1 - yyc < 0) ? 90.0 : -90.0 :
806 -atan2(double(yy1-yyc), double(xx1-xxc)) * RAD2DEG;
807 radius2 = (xx2 - xxc == 0) ?
808 (yy2 - yyc < 0) ? 90.0 : -90.0 :
809 -atan2(double(yy2-yyc), double(xx2-xxc)) * RAD2DEG;
810 }
811 wxCoord alpha2 = wxCoord(radius2 - radius1);
812 wxCoord alpha1 = wxCoord(wxConvertWXangleToMACangle(radius1));
813 if( (xx1 > xx2) || (yy1 > yy2) ) {
814 alpha2 *= -1;
815 }
816
817 Rect r = { yyc - rad, xxc - rad, yyc + rad, xxc + rad };
818
819 if(m_brush.GetStyle() != wxTRANSPARENT) {
820 MacInstallBrush();
821 PaintArc(&r, alpha1, alpha2);
822 }
823 if(m_pen.GetStyle() != wxTRANSPARENT) {
824 MacInstallPen();
825 FrameArc(&r, alpha1, alpha2);
826 }
519cb848
SC
827}
828
2f1ae414
SC
829void wxDC::DoDrawEllipticArc( wxCoord x, wxCoord y, wxCoord w, wxCoord h,
830 double sa, double ea )
519cb848 831{
3dec57ad
SC
832 wxCHECK_RET(Ok(), wxT("wxDC::DoDrawEllepticArc Invalid DC"));
833
834 Rect r;
835 double angle = sa - ea; // Order important Mac in opposite direction to wx
836
7d9d1fd7
SC
837 wxCoord xx = XLOG2DEVMAC(x);
838 wxCoord yy = YLOG2DEVMAC(y);
3dec57ad
SC
839 wxCoord ww = m_signX * XLOG2DEVREL(w);
840 wxCoord hh = m_signY * YLOG2DEVREL(h);
841
842 // handle -ve width and/or height
843 if (ww < 0) { ww = -ww; xx = xx - ww; }
844 if (hh < 0) { hh = -hh; yy = yy - hh; }
845
846 sa = wxConvertWXangleToMACangle(sa);
847
848 r.top = yy;
849 r.left = xx;
850 r.bottom = yy + hh;
851 r.right = xx + ww;
852
853 if(m_brush.GetStyle() != wxTRANSPARENT) {
854 MacInstallBrush();
855 PaintArc(&r, (short)sa, (short)angle);
856 }
857 if(m_pen.GetStyle() != wxTRANSPARENT) {
858 MacInstallPen();
859 FrameArc(&r, (short)sa, (short)angle);
860 }
519cb848
SC
861}
862
2f1ae414 863void wxDC::DoDrawPoint( wxCoord x, wxCoord y )
519cb848 864{
3dec57ad 865 wxCHECK_RET(Ok(), wxT("Invalid DC"));
519cb848 866
0eaa1d68 867 wxMacPortSetter helper(this) ;
519cb848
SC
868
869 if (m_pen.GetStyle() != wxTRANSPARENT)
870 {
871 MacInstallPen() ;
7d9d1fd7
SC
872 wxCoord xx1 = XLOG2DEVMAC(x);
873 wxCoord yy1 = YLOG2DEVMAC(y);
519cb848
SC
874
875 ::MoveTo(xx1,yy1);
876 ::LineTo(xx1+1, yy1+1);
3dec57ad 877 }
519cb848
SC
878}
879
2f1ae414
SC
880void wxDC::DoDrawLines(int n, wxPoint points[],
881 wxCoord xoffset, wxCoord yoffset)
519cb848 882{
3dec57ad 883 wxCHECK_RET(Ok(), wxT("Invalid DC"));
0eaa1d68 884 wxMacPortSetter helper(this) ;
519cb848
SC
885
886 if (m_pen.GetStyle() == wxTRANSPARENT)
887 return;
888
03e11df5 889 MacInstallPen() ;
519cb848 890
3dec57ad
SC
891 wxCoord offset = ( (m_pen.GetWidth() == 0 ? 1 :
892 m_pen.GetWidth() ) * (wxCoord)m_scaleX - 1) / 2 ;
893
894 wxCoord x1, x2 , y1 , y2 ;
7d9d1fd7
SC
895 x1 = XLOG2DEVMAC(points[0].x + xoffset);
896 y1 = YLOG2DEVMAC(points[0].y + yoffset);
3dec57ad 897 ::MoveTo(x1 - offset, y1 - offset );
519cb848
SC
898
899 for (int i = 0; i < n-1; i++)
900 {
7d9d1fd7
SC
901 x2 = XLOG2DEVMAC(points[i+1].x + xoffset);
902 y2 = YLOG2DEVMAC(points[i+1].y + yoffset);
3dec57ad 903 ::LineTo( x2 - offset, y2 - offset );
519cb848
SC
904 }
905}
906
2f1ae414
SC
907void wxDC::DoDrawPolygon(int n, wxPoint points[],
908 wxCoord xoffset, wxCoord yoffset,
909 int fillStyle )
519cb848 910{
32ea1f98
RR
911 wxCHECK_RET(Ok(), wxT("Invalid DC"));
912 wxMacPortSetter helper(this) ;
913
914 wxCoord x1, x2 , y1 , y2 ;
519cb848 915
75f7bc3b
SC
916 if ( m_brush.GetStyle() == wxTRANSPARENT && m_pen.GetStyle() == wxTRANSPARENT )
917 return ;
918
919 PolyHandle polygon = OpenPoly();
920
921 x1 = XLOG2DEVMAC(points[0].x + xoffset);
922 y1 = YLOG2DEVMAC(points[0].y + yoffset);
923 ::MoveTo(x1,y1);
924
76a5e5d2 925 for (int i = 1; i < n; i++)
75f7bc3b 926 {
76a5e5d2
SC
927 x2 = XLOG2DEVMAC(points[i].x + xoffset);
928 y2 = YLOG2DEVMAC(points[i].y + yoffset);
75f7bc3b
SC
929 ::LineTo(x2, y2);
930 }
931
76a5e5d2
SC
932 // close the polyline if necessary
933 if ( x1 != x2 || y1 != y2 )
934 {
935 ::LineTo(x1,y1 ) ;
936 }
937
75f7bc3b
SC
938 ClosePoly();
939
32ea1f98
RR
940 if (m_brush.GetStyle() != wxTRANSPARENT)
941 {
32ea1f98
RR
942
943 MacInstallBrush();
944 ::PaintPoly( polygon );
945
3dec57ad 946 }
519cb848
SC
947
948 if (m_pen.GetStyle() != wxTRANSPARENT)
949 {
32ea1f98 950
519cb848
SC
951 MacInstallPen() ;
952 ::FramePoly( polygon ) ;
32ea1f98 953
3dec57ad 954 }
75f7bc3b 955 KillPoly( polygon );
519cb848
SC
956}
957
3dec57ad 958void wxDC::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
519cb848 959{
3dec57ad
SC
960 wxCHECK_RET(Ok(), wxT("Invalid DC"));
961 wxMacPortSetter helper(this) ;
962
7d9d1fd7
SC
963 wxCoord xx = XLOG2DEVMAC(x);
964 wxCoord yy = YLOG2DEVMAC(y);
3dec57ad
SC
965 wxCoord ww = m_signX * XLOG2DEVREL(width);
966 wxCoord hh = m_signY * YLOG2DEVREL(height);
519cb848
SC
967
968 // CMB: draw nothing if transformed w or h is 0
969 if (ww == 0 || hh == 0)
970 return;
971
972 // CMB: handle -ve width and/or height
973 if (ww < 0)
974 {
975 ww = -ww;
976 xx = xx - ww;
977 }
978
979 if (hh < 0)
980 {
981 hh = -hh;
982 yy = yy - hh;
983 }
984
985 Rect rect = { yy , xx , yy + hh , xx + ww } ;
986
987 if (m_brush.GetStyle() != wxTRANSPARENT)
988 {
989 MacInstallBrush() ;
990 ::PaintRect( &rect ) ;
3dec57ad 991 }
519cb848
SC
992
993 if (m_pen.GetStyle() != wxTRANSPARENT)
994 {
995 MacInstallPen() ;
996 ::FrameRect( &rect ) ;
3dec57ad 997 }
519cb848
SC
998}
999
2f1ae414
SC
1000void wxDC::DoDrawRoundedRectangle(wxCoord x, wxCoord y,
1001 wxCoord width, wxCoord height,
1002 double radius)
519cb848 1003{
3dec57ad
SC
1004 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1005 wxMacPortSetter helper(this) ;
519cb848 1006
3dec57ad
SC
1007 if (radius < 0.0)
1008 radius = - radius * ((width < height) ? width : height);
519cb848 1009
7d9d1fd7
SC
1010 wxCoord xx = XLOG2DEVMAC(x);
1011 wxCoord yy = YLOG2DEVMAC(y);
3dec57ad
SC
1012 wxCoord ww = m_signX * XLOG2DEVREL(width);
1013 wxCoord hh = m_signY * YLOG2DEVREL(height);
519cb848
SC
1014
1015 // CMB: draw nothing if transformed w or h is 0
1016 if (ww == 0 || hh == 0)
1017 return;
1018
1019 // CMB: handle -ve width and/or height
1020 if (ww < 0)
1021 {
1022 ww = -ww;
1023 xx = xx - ww;
1024 }
1025
1026 if (hh < 0)
1027 {
1028 hh = -hh;
1029 yy = yy - hh;
1030 }
1031
1032 Rect rect = { yy , xx , yy + hh , xx + ww } ;
1033
1034 if (m_brush.GetStyle() != wxTRANSPARENT)
1035 {
1036 MacInstallBrush() ;
03e11df5 1037 ::PaintRoundRect( &rect , int(radius * 2) , int(radius * 2) ) ;
3dec57ad 1038 }
519cb848
SC
1039
1040 if (m_pen.GetStyle() != wxTRANSPARENT)
1041 {
1042 MacInstallPen() ;
03e11df5 1043 ::FrameRoundRect( &rect , int(radius * 2) , int(radius * 2) ) ;
3dec57ad 1044 }
519cb848
SC
1045}
1046
2f1ae414 1047void wxDC::DoDrawEllipse(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
519cb848 1048{
3dec57ad
SC
1049 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1050 wxMacPortSetter helper(this) ;
519cb848 1051
7d9d1fd7
SC
1052 wxCoord xx = XLOG2DEVMAC(x);
1053 wxCoord yy = YLOG2DEVMAC(y);
3dec57ad
SC
1054 wxCoord ww = m_signX * XLOG2DEVREL(width);
1055 wxCoord hh = m_signY * YLOG2DEVREL(height);
519cb848
SC
1056
1057 // CMB: draw nothing if transformed w or h is 0
1058 if (ww == 0 || hh == 0)
1059 return;
1060
1061 // CMB: handle -ve width and/or height
1062 if (ww < 0)
1063 {
1064 ww = -ww;
1065 xx = xx - ww;
1066 }
1067
1068 if (hh < 0)
1069 {
1070 hh = -hh;
1071 yy = yy - hh;
1072 }
1073
1074 Rect rect = { yy , xx , yy + hh , xx + ww } ;
1075
1076 if (m_brush.GetStyle() != wxTRANSPARENT)
1077 {
1078 MacInstallBrush() ;
1079 ::PaintOval( &rect ) ;
3dec57ad 1080 }
519cb848
SC
1081
1082 if (m_pen.GetStyle() != wxTRANSPARENT)
1083 {
1084 MacInstallPen() ;
1085 ::FrameOval( &rect ) ;
3dec57ad 1086 }
519cb848
SC
1087}
1088
519cb848
SC
1089
1090
1091bool wxDC::CanDrawBitmap(void) const
1092{
1093 return true ;
1094}
1095
1096
2f1ae414 1097bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
0cbff120
JS
1098 wxDC *source, wxCoord xsrc, wxCoord ysrc, int logical_func , bool useMask,
1099 wxCoord xsrcMask, wxCoord ysrcMask )
519cb848 1100{
3dec57ad
SC
1101 wxCHECK_MSG(Ok(), false, wxT("wxDC::DoBlit Illegal dc"));
1102 wxCHECK_MSG(source->Ok(), false, wxT("wxDC::DoBlit Illegal source DC"));
76a5e5d2
SC
1103
1104 if ( logical_func == wxNO_OP )
1105 return TRUE ;
519cb848 1106
0cbff120
JS
1107 if (xsrcMask == -1 && ysrcMask == -1)
1108 {
1109 xsrcMask = xsrc; ysrcMask = ysrc;
1110 }
1111
76a5e5d2
SC
1112 // correct the parameter in case this dc does not have a mask at all
1113
1114 if ( useMask && !source->m_macMask )
1115 useMask = false ;
1116
1117 Rect srcrect , dstrect ;
1118 srcrect.top = source->YLOG2DEVMAC(ysrc) ;
1119 srcrect.left = source->XLOG2DEVMAC(xsrc) ;
1120 srcrect.right = source->XLOG2DEVMAC(xsrc + width ) ;
1121 srcrect.bottom = source->YLOG2DEVMAC(ysrc + height) ;
1122 dstrect.top = YLOG2DEVMAC(ydest) ;
1123 dstrect.left = XLOG2DEVMAC(xdest) ;
1124 dstrect.bottom = YLOG2DEVMAC(ydest + height ) ;
1125 dstrect.right = XLOG2DEVMAC(xdest + width ) ;
1126
1127 short mode = kUnsupportedMode ;
1128 bool invertDestinationFirst = false ;
1129 switch ( logical_func )
1130 {
1131 case wxAND: // src AND dst
1132 mode = srcOr ; // ok
1133 break ;
1134 case wxAND_INVERT: // (NOT src) AND dst
1135 mode = notSrcOr ; // ok
1136 break ;
1137 case wxAND_REVERSE:// src AND (NOT dst)
1138 invertDestinationFirst = true ;
1139 mode = srcOr ;
1140 break ;
1141 case wxCLEAR: // 0
1142 mode = kEmulatedMode ;
1143 break ;
1144 case wxCOPY: // src
1145 mode = srcCopy ; // ok
1146 break ;
1147 case wxEQUIV: // (NOT src) XOR dst
1148 mode = srcXor ; // ok
1149 break ;
1150 case wxINVERT: // NOT dst
1151 mode = kEmulatedMode ; //or hilite ;
1152 break ;
1153 case wxNAND: // (NOT src) OR (NOT dst)
1154 invertDestinationFirst = true ;
1155 mode = srcBic ;
1156 break ;
1157 case wxNOR: // (NOT src) AND (NOT dst)
1158 invertDestinationFirst = true ;
1159 mode = notSrcOr ;
1160 break ;
1161 case wxNO_OP: // dst
1162 mode = kEmulatedMode ; // this has already been handled upon entry
1163 break ;
1164 case wxOR: // src OR dst
1165 mode = notSrcBic ;
1166 break ;
1167 case wxOR_INVERT: // (NOT src) OR dst
1168 mode = srcBic ;
1169 break ;
1170 case wxOR_REVERSE: // src OR (NOT dst)
1171 invertDestinationFirst = true ;
1172 mode = notSrcBic ;
1173 break ;
1174 case wxSET: // 1
1175 mode = kEmulatedMode ;
1176 break ;
1177 case wxSRC_INVERT: // (NOT src)
1178 mode = notSrcCopy ; // ok
1179 break ;
1180 case wxXOR: // src XOR dst
1181 mode = notSrcXor ; // ok
1182 break ;
1183
1184 default :
1185 break ;
1186
1187 }
1188
1189 if ( mode == kUnsupportedMode )
1190 {
1191 wxFAIL_MSG("unsupported blitting mode" )
1192 return FALSE ;
1193 }
1194
519cb848
SC
1195 CGrafPtr sourcePort = (CGrafPtr) source->m_macPort ;
1196 PixMapHandle bmappixels = GetGWorldPixMap( sourcePort ) ;
519cb848
SC
1197 if ( LockPixels(bmappixels) )
1198 {
76a5e5d2
SC
1199 wxMacPortSetter helper(this) ;
1200 RGBColor tempColor ;
1201
1202 if ( source->GetDepth() == 1 )
1203 {
1204 RGBForeColor( &MAC_WXCOLORREF(m_textForegroundColour.GetPixel()) ) ;
1205 RGBBackColor( &MAC_WXCOLORREF(m_textBackgroundColour.GetPixel()) ) ;
1206 }
1207 else
1208 {
1209 // the modes need this, otherwise we'll end up having really nice colors...
1210 RGBColor white = { 0xFFFF, 0xFFFF,0xFFFF} ;
1211 RGBColor black = { 0,0,0} ;
1212 RGBForeColor( &black ) ;
1213 RGBBackColor( &white ) ;
1214 }
8208e181
SC
1215
1216 if ( useMask && source->m_macMask )
1217 {
1dcbbdcf
SC
1218 if ( mode == srcCopy )
1219 {
76a5e5d2 1220 if ( LockPixels( GetGWorldPixMap( MAC_WXHBITMAP(source->m_macMask) ) ) )
1dcbbdcf
SC
1221 {
1222 CopyMask( GetPortBitMapForCopyBits( sourcePort ) ,
76a5e5d2
SC
1223 GetPortBitMapForCopyBits( MAC_WXHBITMAP(source->m_macMask) ) ,
1224 GetPortBitMapForCopyBits( MAC_WXHBITMAP(m_macPort) ) ,
1dcbbdcf 1225 &srcrect, &srcrect , &dstrect ) ;
76a5e5d2 1226 UnlockPixels( GetGWorldPixMap( MAC_WXHBITMAP(source->m_macMask) ) ) ;
1dcbbdcf
SC
1227 }
1228 }
1229 else
1230 {
1231 RgnHandle clipRgn = NewRgn() ;
76a5e5d2
SC
1232 LockPixels( GetGWorldPixMap( MAC_WXHBITMAP(source->m_macMask) ) ) ;
1233 BitMapToRegion( clipRgn , (BitMap*) *GetGWorldPixMap( MAC_WXHBITMAP(source->m_macMask) ) ) ;
1234 UnlockPixels( GetGWorldPixMap( MAC_WXHBITMAP(source->m_macMask) ) ) ;
1dcbbdcf 1235 OffsetRgn( clipRgn , -srcrect.left + dstrect.left, -srcrect.top + dstrect.top ) ;
76a5e5d2
SC
1236 if ( mode == kEmulatedMode )
1237 {
1238 Pattern pat ;
1239 ::PenPat(GetQDGlobalsBlack(&pat));
1240 if ( logical_func == wxSET )
1241 {
1242 RGBColor col= { 0xFFFF, 0xFFFF, 0xFFFF } ;
1243 ::RGBForeColor( &col ) ;
1244 ::PaintRgn( clipRgn ) ;
1245 }
1246 else if ( logical_func == wxCLEAR )
1247 {
1248 RGBColor col= { 0x0000, 0x0000, 0x0000 } ;
1249 ::RGBForeColor( &col ) ;
1250 ::PaintRgn( clipRgn ) ;
1251 }
1252 else if ( logical_func == wxINVERT )
1253 {
1254 MacInvertRgn( clipRgn ) ;
1255 }
1256 else
1257 {
1258 for ( int y = 0 ; y < srcrect.right - srcrect.left ; ++y )
1259 {
1260 for ( int x = 0 ; x < srcrect.bottom - srcrect.top ; ++x )
1261 {
1262 Point dstPoint = { dstrect.top + y , dstrect.left + x } ;
1263 Point srcPoint = { srcrect.top + y , srcrect.left + x } ;
1264 if ( PtInRgn( dstPoint , clipRgn ) )
1265 {
1266 RGBColor srcColor ;
1267 RGBColor dstColor ;
1268
1269 SetPort( (GrafPtr) sourcePort ) ;
1270 GetCPixel( srcPoint.h , srcPoint.v , &srcColor) ;
1271 SetPort( (GrafPtr) m_macPort ) ;
1272 GetCPixel( dstPoint.h , dstPoint.v , &dstColor ) ;
1273
1274 wxMacCalculateColour( logical_func , srcColor , dstColor ) ;
1275 SetCPixel( dstPoint.h , dstPoint.v , &dstColor ) ;
1276 }
1277 }
1278 }
76a5e5d2
SC
1279 }
1280 }
1281 else
1282 {
1283 if ( invertDestinationFirst )
1284 {
1285 MacInvertRgn( clipRgn ) ;
1286 }
1287 CopyBits( GetPortBitMapForCopyBits( sourcePort ) ,
1288 GetPortBitMapForCopyBits( MAC_WXHBITMAP(m_macPort) ) ,
1289 &srcrect, &dstrect, mode, clipRgn ) ;
1290 }
1dcbbdcf
SC
1291 DisposeRgn( clipRgn ) ;
1292 }
8208e181
SC
1293 }
1294 else
1295 {
0d54461f
SC
1296 RgnHandle clipRgn = NewRgn() ;
1297 SetRectRgn( clipRgn , dstrect.left , dstrect.top , dstrect.right , dstrect.bottom ) ;
76a5e5d2
SC
1298 if ( mode == kEmulatedMode )
1299 {
0d54461f
SC
1300 Pattern pat ;
1301 ::PenPat(GetQDGlobalsBlack(&pat));
1302 if ( logical_func == wxSET )
1303 {
1304 RGBColor col= { 0xFFFF, 0xFFFF, 0xFFFF } ;
1305 ::RGBForeColor( &col ) ;
1306 ::PaintRgn( clipRgn ) ;
1307 }
1308 else if ( logical_func == wxCLEAR )
1309 {
1310 RGBColor col= { 0x0000, 0x0000, 0x0000 } ;
1311 ::RGBForeColor( &col ) ;
1312 ::PaintRgn( clipRgn ) ;
1313 }
1314 else if ( logical_func == wxINVERT )
1315 {
1316 MacInvertRgn( clipRgn ) ;
1317 }
1318 else
1319 {
1320 for ( int y = 0 ; y < srcrect.right - srcrect.left ; ++y )
1321 {
1322 for ( int x = 0 ; x < srcrect.bottom - srcrect.top ; ++x )
1323 {
1324 Point dstPoint = { dstrect.top + y , dstrect.left + x } ;
1325 Point srcPoint = { srcrect.top + y , srcrect.left + x } ;
1326
1327 {
1328 RGBColor srcColor ;
1329 RGBColor dstColor ;
1330
1331 SetPort( (GrafPtr) sourcePort ) ;
1332 GetCPixel( srcPoint.h , srcPoint.v , &srcColor) ;
1333 SetPort( (GrafPtr) m_macPort ) ;
1334 GetCPixel( dstPoint.h , dstPoint.v , &dstColor ) ;
1335
1336 wxMacCalculateColour( logical_func , srcColor , dstColor ) ;
1337 SetCPixel( dstPoint.h , dstPoint.v , &dstColor ) ;
1338 }
1339 }
1340 }
1341 }
1342
76a5e5d2
SC
1343 }
1344 else
1345 {
0d54461f
SC
1346 if ( invertDestinationFirst )
1347 {
1348 MacInvertRgn( clipRgn ) ;
1349 }
1350 CopyBits( GetPortBitMapForCopyBits( sourcePort ) ,
1351 GetPortBitMapForCopyBits( MAC_WXHBITMAP(m_macPort) ) ,
1352 &srcrect, &dstrect, mode, NULL ) ;
76a5e5d2 1353 }
0d54461f 1354 DisposeRgn( clipRgn ) ;
8208e181 1355 }
519cb848
SC
1356 UnlockPixels( bmappixels ) ;
1357 }
1358
1359 m_macPenInstalled = false ;
1360 m_macBrushInstalled = false ;
1361 m_macFontInstalled = false ;
1362
1363 return TRUE;
1364}
1365
66a09d47
SC
1366inline Fixed IntToFixed( int inInt )
1367 {
1368 return (((SInt32) inInt) << 16);
1369 }
1370
1371
1372void wxDC::DoDrawRotatedText(const wxString& str, wxCoord x, wxCoord y,
3dec57ad 1373 double angle)
2f1ae414 1374{
3dec57ad
SC
1375 wxCHECK_RET( Ok(), wxT("wxDC::DoDrawRotatedText Invalid window dc") );
1376
1377 if (angle == 0.0)
1378 {
66a09d47 1379 DrawText(str, x, y);
3dec57ad
SC
1380 return;
1381 }
1382
3dec57ad 1383 wxMacPortSetter helper(this) ;
66a09d47
SC
1384 MacInstallFont() ;
1385
1386 wxString text ;
1387 if ( wxApp::s_macDefaultEncodingIsPC )
1388 {
1389 text = wxMacMakeMacStringFromPC( str ) ;
1390 }
1391 else
1392 {
1393 text = str ;
1394 }
3dec57ad 1395
66a09d47
SC
1396 wxFontRefData * font = (wxFontRefData*) m_font.GetRefData() ;
1397 if ( 0 )
3dec57ad 1398 {
66a09d47
SC
1399 m_macFormerAliasState = IsAntiAliasedTextEnabled(&m_macFormerAliasSize);
1400 SetAntiAliasedTextEnabled(true, m_scaleY * font->m_macFontSize);
1401 m_macAliasWasEnabled = true ;
3dec57ad 1402 }
66a09d47
SC
1403
1404 OSStatus status = noErr ;
1405
1406 TECObjectRef ec;
1407 status = TECCreateConverter(&ec, kTextEncodingMacRoman, kTextEncodingUnicodeDefault);
1408 wxASSERT_MSG( status == noErr , "couldn't start converter" ) ;
1409
1410 ByteCount byteOutLen ;
1411 ByteCount byteInLen = text.Length() ;
1412 ByteCount byteBufferLen = byteInLen *2 ;
1413 char* buf = new char[byteBufferLen] ;
1414
1415 status = TECConvertText(ec, (ConstTextPtr)text.c_str() , byteInLen, &byteInLen,
1416 (TextPtr)buf, byteBufferLen, &byteOutLen);
1417
1418 wxASSERT_MSG( status == noErr , "couldn't convert text" ) ;
1419 status = TECDisposeConverter(ec);
1420 wxASSERT_MSG( status == noErr , "couldn't dispose converter" ) ;
1421
1422 ATSUTextLayout atsuLayout ;
1423 UniCharCount chars = byteOutLen / 2 ;
1424 status = ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr) buf , 0 , byteOutLen / 2 , byteOutLen / 2 , 1 ,
1425 &chars , (ATSUStyle*) &m_macATSUIStyle , &atsuLayout ) ;
1426 wxASSERT_MSG( status == noErr , "couldn't create the layout of the rotated text" );
1427
1428 Fixed atsuAngle = IntToFixed( angle ) ;
1429 ByteCount angleSize = sizeof(Fixed) ;
1430 ATSUAttributeTag rotationTag = kATSULineRotationTag ;
1431 ATSUAttributeValuePtr angleValue = &atsuAngle ;
1432 status = ::ATSUSetLayoutControls(atsuLayout , 1 , &rotationTag , &angleSize , &angleValue ) ;
1433
1434 status = ::ATSUDrawText( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd,
1435 IntToFixed(XLOG2DEVMAC(x) ) , IntToFixed(YLOG2DEVMAC(y) ) );
1436 wxASSERT_MSG( status == noErr , "couldn't draw the rotated text" );
1437 Rect rect ;
1438 status = ::ATSUMeasureTextImage( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd,
1439 IntToFixed(XLOG2DEVMAC(x) ) , IntToFixed(YLOG2DEVMAC(y) ) , &rect );
1440 wxASSERT_MSG( status == noErr , "couldn't measure the rotated text" );
1441
1442 OffsetRect( &rect , -m_macLocalOrigin.x , -m_macLocalOrigin.y ) ;
1443 CalcBoundingBox(XDEV2LOG(rect.left), YDEV2LOG(rect.top) );
1444 CalcBoundingBox(XDEV2LOG(rect.right), YDEV2LOG(rect.bottom) );
1445 ::ATSUDisposeTextLayout(atsuLayout);
1446 delete[] buf ;
2f1ae414 1447}
66a09d47 1448
2f1ae414 1449void wxDC::DoDrawText(const wxString& strtext, wxCoord x, wxCoord y)
519cb848 1450{
3dec57ad
SC
1451 wxCHECK_RET(Ok(), wxT("wxDC::DoDrawText Invalid DC"));
1452 wxMacPortSetter helper(this) ;
519cb848 1453
7d9d1fd7
SC
1454 long xx = XLOG2DEVMAC(x);
1455 long yy = YLOG2DEVMAC(y);
519cb848 1456
66a09d47
SC
1457 MacInstallFont() ;
1458 if ( 0 )
1459 {
1460 m_macFormerAliasState = IsAntiAliasedTextEnabled(&m_macFormerAliasSize);
1461 SetAntiAliasedTextEnabled(true, 8);
1462 m_macAliasWasEnabled = true ;
1463 }
1464
1465 FontInfo fi ;
1466 ::GetFontInfo( &fi ) ;
1467
1468 yy += fi.ascent ;
1469 ::MoveTo( xx , yy );
1470 if ( m_backgroundMode == wxTRANSPARENT )
519cb848 1471 {
66a09d47
SC
1472 ::TextMode( srcOr) ;
1473 }
1474 else
1475 {
1476 ::TextMode( srcCopy ) ;
1477 }
519cb848 1478
66a09d47
SC
1479 const char *text = NULL ;
1480 int length = 0 ;
1481 wxString macText ;
519cb848 1482
66a09d47
SC
1483 if ( wxApp::s_macDefaultEncodingIsPC )
1484 {
1485 macText = wxMacMakeMacStringFromPC( strtext ) ;
1486 text = macText ;
1487 length = macText.Length() ;
1488 }
1489 else
1490 {
1491 text = strtext ;
1492 length = strtext.Length() ;
1493 }
1494
1495 int laststop = 0 ;
1496 int i = 0 ;
1497 int line = 0 ;
1498
1499 while( i < length )
1500 {
1501 if( text[i] == 13 || text[i] == 10)
519cb848 1502 {
66a09d47
SC
1503 ::DrawText( text , laststop , i - laststop ) ;
1504 line++ ;
1505 ::MoveTo( xx , yy + line*(fi.descent + fi.ascent + fi.leading) );
1506 laststop = i+1 ;
519cb848 1507 }
66a09d47 1508 i++ ;
519cb848 1509 }
66a09d47
SC
1510
1511 ::DrawText( text , laststop , i - laststop ) ;
1512 ::TextMode( srcOr ) ;
519cb848
SC
1513}
1514
3dec57ad 1515bool wxDC::CanGetTextExtent() const
519cb848 1516{
3dec57ad 1517 wxCHECK_MSG(Ok(), false, wxT("Invalid DC"));
519cb848
SC
1518
1519 return true ;
1520}
1521
2f1ae414
SC
1522void wxDC::DoGetTextExtent( const wxString &string, wxCoord *width, wxCoord *height,
1523 wxCoord *descent, wxCoord *externalLeading ,
1524 wxFont *theFont ) const
519cb848 1525{
3dec57ad 1526 wxCHECK_RET(Ok(), wxT("Invalid DC"));
0eaa1d68 1527 wxMacPortSetter helper(this) ;
519cb848
SC
1528
1529 wxFont formerFont = m_font ;
1530
1531 if ( theFont )
1532 {
1533 wxFontRefData * font = (wxFontRefData*) m_font.GetRefData() ;
1534
1535 if ( font )
1536 {
519cb848 1537 ::TextFont( font->m_macFontNum ) ;
2f1ae414 1538 ::TextSize( YLOG2DEVREL( font->m_macFontSize) ) ;
519cb848
SC
1539 ::TextFace( font->m_macFontStyle ) ;
1540 }
1541 }
1542 else
1543 {
1544 MacInstallFont() ;
1545 }
1546
1547 FontInfo fi ;
1548 ::GetFontInfo( &fi ) ;
1549
2f1ae414
SC
1550 if ( height )
1551 *height = YDEV2LOGREL( fi.descent + fi.ascent ) ;
1552 if ( descent )
1553 *descent =YDEV2LOGREL( fi.descent );
1554 if ( externalLeading )
1555 *externalLeading = YDEV2LOGREL( fi.leading ) ;
519cb848
SC
1556
1557 const char *text = NULL ;
1558 int length = 0 ;
1559 wxString macText ;
1560 if ( wxApp::s_macDefaultEncodingIsPC )
1561 {
1562 macText = wxMacMakeMacStringFromPC( string ) ;
1563 text = macText ;
1564 length = macText.Length() ;
1565 }
1566 else
1567 {
1568 text = string ;
1569 length = string.Length() ;
1570 }
1571
1572 int laststop = 0 ;
1573 int i = 0 ;
1574 int curwidth = 0 ;
2f1ae414 1575 if ( width )
519cb848 1576 {
2f1ae414
SC
1577 *width = 0 ;
1578
1579 while( i < length )
519cb848 1580 {
2f1ae414
SC
1581 if( text[i] == 13 || text[i] == 10)
1582 {
1583 if ( height )
1584 *height += YDEV2LOGREL( fi.descent + fi.ascent + fi.leading ) ;
1585 curwidth = ::TextWidth( text , laststop , i - laststop ) ;
1586 if ( curwidth > *width )
1587 *width = XDEV2LOGREL( curwidth ) ;
1588 laststop = i+1 ;
1589 }
1590 i++ ;
519cb848 1591 }
2f1ae414
SC
1592
1593 curwidth = ::TextWidth( text , laststop , i - laststop ) ;
1594 if ( curwidth > *width )
1595 *width = XDEV2LOGREL( curwidth ) ;
519cb848 1596 }
519cb848
SC
1597
1598 if ( theFont )
1599 {
1600 m_macFontInstalled = false ;
1601 }
1602}
1603
ee41971c 1604wxCoord wxDC::GetCharWidth(void) const
519cb848 1605{
3dec57ad 1606 wxCHECK_MSG(Ok(), 1, wxT("Invalid DC"));
519cb848 1607
0eaa1d68 1608 wxMacPortSetter helper(this) ;
519cb848
SC
1609
1610 MacInstallFont() ;
1611
c257d44d 1612 int width = ::TextWidth( "n" , 0 , 1 ) ;
519cb848 1613
c257d44d 1614 return YDEV2LOGREL(width) ;
519cb848
SC
1615}
1616
ee41971c 1617wxCoord wxDC::GetCharHeight(void) const
519cb848 1618{
3dec57ad 1619 wxCHECK_MSG(Ok(), 1, wxT("Invalid DC"));
519cb848 1620
3dec57ad 1621 wxMacPortSetter helper(this) ;
519cb848
SC
1622
1623 MacInstallFont() ;
1624
1625 FontInfo fi ;
1626 ::GetFontInfo( &fi ) ;
1627
2f1ae414 1628 return YDEV2LOGREL( fi.descent + fi.ascent );
519cb848
SC
1629}
1630
1631void wxDC::Clear(void)
1632{
3dec57ad
SC
1633 wxCHECK_RET(Ok(), wxT("Invalid DC"));
1634 wxMacPortSetter helper(this) ;
66a09d47 1635 Rect rect = { -32000 , -32000 , 32000 , 32000 } ;
519cb848
SC
1636
1637 if (m_backgroundBrush.GetStyle() != wxTRANSPARENT)
1638 {
66a09d47
SC
1639 ::PenNormal() ;
1640 //MacInstallBrush() ;
76a5e5d2 1641 MacSetupBackgroundForCurrentPort( m_backgroundBrush ) ;
519cb848 1642 ::EraseRect( &rect ) ;
3dec57ad 1643 }
519cb848
SC
1644}
1645
1646void wxDC::MacInstallFont() const
1647{
3dec57ad 1648 wxCHECK_RET(Ok(), wxT("Invalid DC"));
0eaa1d68
SC
1649// if ( m_macFontInstalled )
1650// return ;
2f1ae414
SC
1651 Pattern blackColor ;
1652
519cb848
SC
1653 wxFontRefData * font = (wxFontRefData*) m_font.GetRefData() ;
1654
1655 if ( font )
1656 {
1657 ::TextFont( font->m_macFontNum ) ;
03e11df5 1658 ::TextSize( short(m_scaleY * font->m_macFontSize) ) ;
519cb848
SC
1659 ::TextFace( font->m_macFontStyle ) ;
1660
1661 m_macFontInstalled = true ;
1662 m_macBrushInstalled = false ;
1663 m_macPenInstalled = false ;
03e11df5 1664
76a5e5d2
SC
1665 RGBColor forecolor = MAC_WXCOLORREF( m_textForegroundColour.GetPixel());
1666 RGBColor backcolor = MAC_WXCOLORREF( m_textBackgroundColour.GetPixel());
03e11df5
GD
1667 ::RGBForeColor( &forecolor );
1668 ::RGBBackColor( &backcolor );
519cb848
SC
1669 }
1670 else
1671 {
1672 short fontnum ;
1673
1674 GetFNum( "\pGeneva" , &fontnum ) ;
1675 ::TextFont( fontnum ) ;
03e11df5 1676 ::TextSize( short(m_scaleY * 10) ) ;
519cb848
SC
1677 ::TextFace( 0 ) ;
1678
1679 // todo reset after spacing changes - or store the current spacing somewhere
1680
1681 m_macFontInstalled = true ;
1682 m_macBrushInstalled = false ;
1683 m_macPenInstalled = false ;
519cb848 1684
76a5e5d2
SC
1685 RGBColor forecolor = MAC_WXCOLORREF( m_textForegroundColour.GetPixel());
1686 RGBColor backcolor = MAC_WXCOLORREF( m_textBackgroundColour.GetPixel());
03e11df5
GD
1687 ::RGBForeColor( &forecolor );
1688 ::RGBBackColor( &backcolor );
1689 }
519cb848
SC
1690
1691 short mode = patCopy ;
1692
1693 // todo :
1694
1695 switch( m_logicalFunction )
1696 {
1697 case wxCOPY: // src
1698 mode = patCopy ;
1699 break ;
1700 case wxINVERT: // NOT dst
2f1ae414 1701 ::PenPat(GetQDGlobalsBlack(&blackColor));
519cb848
SC
1702 mode = patXor ;
1703 break ;
1704 case wxXOR: // src XOR dst
1705 mode = patXor ;
1706 break ;
1707 case wxOR_REVERSE: // src OR (NOT dst)
1708 mode = notPatOr ;
1709 break ;
1710 case wxSRC_INVERT: // (NOT src)
1711 mode = notPatCopy ;
1712 break ;
1713
1714 // unsupported TODO
1715
1716 case wxCLEAR: // 0
1717 case wxAND_REVERSE:// src AND (NOT dst)
1718 case wxAND: // src AND dst
1719 case wxAND_INVERT: // (NOT src) AND dst
1720 case wxNO_OP: // dst
1721 case wxNOR: // (NOT src) AND (NOT dst)
1722 case wxEQUIV: // (NOT src) XOR dst
1723 case wxOR_INVERT: // (NOT src) OR dst
1724 case wxNAND: // (NOT src) OR (NOT dst)
1725 case wxOR: // src OR dst
1726 case wxSET: // 1
2f1ae414
SC
1727// case wxSRC_OR: // source _bitmap_ OR destination
1728// case wxSRC_AND: // source _bitmap_ AND destination
519cb848
SC
1729 break ;
1730 }
1731 ::PenMode( mode ) ;
66a09d47
SC
1732
1733 OSStatus status = noErr ;
1734
1735 Fixed atsuSize = IntToFixed(m_scaleY * font->m_macFontSize) ;
1736
1737 Style qdStyle = font->m_macFontStyle ;
1738 ATSUFontID atsuFont = font->m_macATSUFontID ;
1739
1740 status = ::ATSUCreateStyle(&(ATSUStyle)m_macATSUIStyle) ;
1741 wxASSERT_MSG( status == noErr , "couldn't create ATSU style" ) ;
1742
1743 ATSUAttributeTag atsuTags[] =
1744 {
1745 kATSUFontTag ,
1746 kATSUSizeTag ,
1747 kATSUColorTag ,
1748
1749 kATSUQDBoldfaceTag ,
1750 kATSUQDItalicTag ,
1751 kATSUQDUnderlineTag ,
1752 kATSUQDCondensedTag ,
1753 kATSUQDExtendedTag ,
1754
1755 } ;
1756
1757 ByteCount atsuSizes[sizeof(atsuTags)/sizeof(ATSUAttributeTag)] =
1758 {
1759 sizeof( ATSUFontID ) ,
1760 sizeof( Fixed ) ,
1761 sizeof( RGBColor ) ,
1762 sizeof( Boolean ) ,
1763 sizeof( Boolean ) ,
1764 sizeof( Boolean ) ,
1765 sizeof( Boolean ) ,
1766 sizeof( Boolean ) ,
1767 } ;
1768
1769 Boolean kTrue = true ;
1770 Boolean kFalse = false ;
1771
1772 ATSUAttributeValuePtr atsuValues[sizeof(atsuTags)/sizeof(ATSUAttributeTag)] =
1773 {
1774 &atsuFont ,
1775 &atsuSize ,
1776 &MAC_WXCOLORREF( m_textForegroundColour.GetPixel() ) ,
1777
1778 (qdStyle & bold) ? &kTrue : &kFalse ,
1779 (qdStyle & italic) ? &kTrue : &kFalse ,
1780 (qdStyle & underline) ? &kTrue : &kFalse ,
1781 (qdStyle & condense) ? &kTrue : &kFalse ,
1782 (qdStyle & extend) ? &kTrue : &kFalse ,
1783 } ;
1784
1785 status = ::ATSUSetAttributes((ATSUStyle)m_macATSUIStyle, sizeof(atsuTags)/sizeof(ATSUAttributeTag),
1786 atsuTags, atsuSizes, atsuValues);
1787 wxASSERT_MSG( status == noErr , "couldn't set create ATSU style" ) ;
1788
519cb848
SC
1789}
1790
ffd67837
SC
1791Pattern gHatchPatterns[] =
1792{
1793 { 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF } ,
1794 { 0x01 , 0x02 , 0x04 , 0x08 , 0x10 , 0x20 , 0x40 , 0x80 } ,
1795 { 0x80 , 0x40 , 0x20 , 0x10 , 0x08 , 0x04 , 0x02 , 0x01 } ,
1796 { 0x10 , 0x10 , 0x10 , 0xFF , 0x10 , 0x10 , 0x10 , 0x10 } ,
1797 { 0x00 , 0x00 , 0x00 , 0xFF , 0x00 , 0x00 , 0x00 , 0x00 } ,
1798 { 0x10 , 0x10 , 0x10 , 0x10 , 0x10 , 0x10 , 0x10 , 0x10 } ,
1799 { 0x81 , 0x42 , 0x24 , 0x18 , 0x18 , 0x24 , 0x42 , 0x81 } ,
1800} ;
1801
519cb848
SC
1802static void wxMacGetHatchPattern(int hatchStyle, Pattern *pattern)
1803{
ffd67837
SC
1804 int theIndex = 1 ;
1805
519cb848
SC
1806 switch(hatchStyle)
1807 {
1808 case wxBDIAGONAL_HATCH:
75f7bc3b 1809 theIndex = 2;
519cb848
SC
1810 break;
1811 case wxFDIAGONAL_HATCH:
75f7bc3b 1812 theIndex = 3;
519cb848
SC
1813 break;
1814 case wxCROSS_HATCH:
75f7bc3b 1815 theIndex = 4;
519cb848
SC
1816 break;
1817 case wxHORIZONTAL_HATCH:
75f7bc3b 1818 theIndex = 5;
519cb848
SC
1819 break;
1820 case wxVERTICAL_HATCH:
1821 theIndex = 6;
1822 break;
1823 case wxCROSSDIAG_HATCH:
75f7bc3b 1824 theIndex = 7;
519cb848
SC
1825 break;
1826 default:
1827 theIndex = 1; // solid pattern
1828 break;
1829 }
ffd67837 1830 *pattern = gHatchPatterns[theIndex-1] ;
519cb848
SC
1831}
1832
1833void wxDC::MacInstallPen() const
1834{
3dec57ad 1835 wxCHECK_RET(Ok(), wxT("Invalid DC"));
519cb848 1836
2f1ae414
SC
1837 Pattern blackColor;
1838
0eaa1d68
SC
1839// if ( m_macPenInstalled )
1840// return ;
519cb848 1841
76a5e5d2
SC
1842 RGBColor forecolor = MAC_WXCOLORREF( m_pen.GetColour().GetPixel());
1843 RGBColor backcolor = MAC_WXCOLORREF( m_backgroundBrush.GetColour().GetPixel());
03e11df5
GD
1844 ::RGBForeColor( &forecolor );
1845 ::RGBBackColor( &backcolor );
519cb848
SC
1846
1847 ::PenNormal() ;
3dec57ad 1848 int penWidth = m_pen.GetWidth() * (int) m_scaleX ;
0b014ec7
SC
1849
1850 // null means only one pixel, at whatever resolution
1851 if ( penWidth == 0 )
1852 penWidth = 1 ;
519cb848
SC
1853 ::PenSize(penWidth, penWidth);
1854
1855 int penStyle = m_pen.GetStyle();
1856
1857 if (penStyle == wxSOLID)
03e11df5 1858 {
2f1ae414 1859 ::PenPat(GetQDGlobalsBlack(&blackColor));
03e11df5 1860 }
519cb848
SC
1861 else if (IS_HATCH(penStyle))
1862 {
1863 Pattern pat ;
1864 wxMacGetHatchPattern(penStyle, &pat);
1865 ::PenPat(&pat);
1866 }
1867 else
1868 {
1ff301c4
SC
1869 Pattern pat = *GetQDGlobalsBlack(&blackColor) ;
1870 switch( penStyle )
1871 {
1872 case wxDOT :
1873 for ( int i = 0 ; i < 8 ; ++i )
1874 {
1875 pat.pat[i] = 0xCC ;
1876 }
1877 break ;
1878 case wxLONG_DASH :
1879 for ( int i = 0 ; i < 8 ; ++i )
1880 {
1881 pat.pat[i] = 0xFE ;
1882 }
1883 break ;
1884 case wxSHORT_DASH :
1885 for ( int i = 0 ; i < 8 ; ++i )
1886 {
1887 pat.pat[i] = 0xEE ;
1888 }
1889 break ;
1890 case wxDOT_DASH :
1891 for ( int i = 0 ; i < 8 ; ++i )
1892 {
1893 pat.pat[i] = 0x6F ;
1894 }
1895 break ;
1896 case wxUSER_DASH :
1897 {
1898 wxDash* dash ;
1899 int number = m_pen.GetDashes(&dash) ;
1900 // right now we don't allocate larger pixmaps
1901 for ( int i = 0 ; i < 8 ; ++i )
1902 {
1903 pat.pat[i] = dash[0] ;
1904 }
1905 }
1906 break ;
1907 }
1908 ::PenPat(&pat);
519cb848
SC
1909 }
1910
1911 short mode = patCopy ;
1912
1913 // todo :
1914
1915 switch( m_logicalFunction )
1916 {
1ff301c4
SC
1917 case wxCOPY: // only foreground color, leave background (thus not patCopy)
1918 mode = patOr ;
519cb848
SC
1919 break ;
1920 case wxINVERT: // NOT dst
1ff301c4 1921// ::PenPat(GetQDGlobalsBlack(&blackColor));
519cb848
SC
1922 mode = patXor ;
1923 break ;
1924 case wxXOR: // src XOR dst
1925 mode = patXor ;
1926 break ;
1927 case wxOR_REVERSE: // src OR (NOT dst)
1928 mode = notPatOr ;
1929 break ;
1930 case wxSRC_INVERT: // (NOT src)
1931 mode = notPatCopy ;
1932 break ;
1933
1934 // unsupported TODO
1935
1936 case wxCLEAR: // 0
1937 case wxAND_REVERSE:// src AND (NOT dst)
1938 case wxAND: // src AND dst
1939 case wxAND_INVERT: // (NOT src) AND dst
1940 case wxNO_OP: // dst
1941 case wxNOR: // (NOT src) AND (NOT dst)
1942 case wxEQUIV: // (NOT src) XOR dst
1943 case wxOR_INVERT: // (NOT src) OR dst
1944 case wxNAND: // (NOT src) OR (NOT dst)
1945 case wxOR: // src OR dst
1946 case wxSET: // 1
2f1ae414
SC
1947// case wxSRC_OR: // source _bitmap_ OR destination
1948// case wxSRC_AND: // source _bitmap_ AND destination
519cb848
SC
1949 break ;
1950 }
1951 ::PenMode( mode ) ;
1952 m_macPenInstalled = true ;
1953 m_macBrushInstalled = false ;
1954 m_macFontInstalled = false ;
1955}
1956
7d9d1fd7 1957void wxDC::MacSetupBackgroundForCurrentPort(const wxBrush& background )
1dcbbdcf
SC
1958{
1959 Pattern whiteColor ;
7d9d1fd7
SC
1960 switch( background.MacGetBrushKind() )
1961 {
1962 case kwxMacBrushTheme :
1963 {
1964 ::SetThemeBackground( background.GetMacTheme() , wxDisplayDepth() , true ) ;
1965 break ;
1966 }
1967 case kwxMacBrushThemeBackground :
1968 {
1969 Rect extent ;
1970 ThemeBackgroundKind bg = background.GetMacThemeBackground( &extent ) ;
1971 ::ApplyThemeBackground( bg , &extent ,kThemeStateActive , wxDisplayDepth() , true ) ;
1972 break ;
1973 }
1974 case kwxMacBrushColour :
1975 {
66a09d47 1976 ::RGBBackColor( &MAC_WXCOLORREF( background.GetColour().GetPixel()) );
7d9d1fd7
SC
1977 int brushStyle = background.GetStyle();
1978 if (brushStyle == wxSOLID)
1979 ::BackPat(GetQDGlobalsWhite(&whiteColor));
1980 else if (IS_HATCH(brushStyle))
1981 {
1982 Pattern pat ;
1983 wxMacGetHatchPattern(brushStyle, &pat);
1984 ::BackPat(&pat);
1985 }
1986 else
1987 {
1988 ::BackPat(GetQDGlobalsWhite(&whiteColor));
1989 }
1990 break ;
1991 }
1992 }
1dcbbdcf
SC
1993}
1994
519cb848
SC
1995void wxDC::MacInstallBrush() const
1996{
3dec57ad 1997 wxCHECK_RET(Ok(), wxT("Invalid DC"));
0eaa1d68 1998
1dcbbdcf 1999 Pattern blackColor ;
0eaa1d68
SC
2000// if ( m_macBrushInstalled )
2001// return ;
519cb848
SC
2002
2003 // foreground
76a5e5d2
SC
2004
2005 bool backgroundTransparent = (GetBackgroundMode() == wxTRANSPARENT) ;
519cb848 2006
76a5e5d2 2007 ::RGBForeColor( &MAC_WXCOLORREF( m_brush.GetColour().GetPixel()) );
0d54461f 2008 ::RGBBackColor( &MAC_WXCOLORREF( m_backgroundBrush.GetColour().GetPixel()) );
519cb848
SC
2009
2010 int brushStyle = m_brush.GetStyle();
2011 if (brushStyle == wxSOLID)
0d54461f 2012 {
2f1ae414 2013 ::PenPat(GetQDGlobalsBlack(&blackColor));
0d54461f 2014 }
519cb848
SC
2015 else if (IS_HATCH(brushStyle))
2016 {
2017 Pattern pat ;
2018 wxMacGetHatchPattern(brushStyle, &pat);
2019 ::PenPat(&pat);
2020 }
1ff301c4 2021 else if ( m_brush.GetStyle() == wxSTIPPLE || m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE )
519cb848 2022 {
76a5e5d2
SC
2023 // we force this in order to be compliant with wxMSW
2024 backgroundTransparent = false ;
1ff301c4
SC
2025 // for these the text fore (and back for MASK_OPAQUE) colors are used
2026 wxBitmap* bitmap = m_brush.GetStipple() ;
2027 int width = bitmap->GetWidth() ;
2028 int height = bitmap->GetHeight() ;
76a5e5d2
SC
2029 GWorldPtr gw = NULL ;
2030
1ff301c4 2031 if ( m_brush.GetStyle() == wxSTIPPLE )
76a5e5d2
SC
2032 gw = MAC_WXHBITMAP(bitmap->GetHBITMAP()) ;
2033 else
2034 gw = MAC_WXHBITMAP(bitmap->GetMask()->GetMaskBitmap()) ;
2035
2036 PixMapHandle gwpixmaphandle = GetGWorldPixMap( gw ) ;
2037 LockPixels( gwpixmaphandle ) ;
2038
2039 bool isMonochrome = !IsPortColor( gw ) ;
2040
2041 if ( !isMonochrome )
2042 {
2043 if ( (**gwpixmaphandle).pixelSize == 1 )
2044 isMonochrome = true ;
2045 }
2046
66a09d47 2047 if ( isMonochrome && width == 8 && height == 8 )
1ff301c4 2048 {
76a5e5d2 2049 ::RGBForeColor( &MAC_WXCOLORREF( m_textForegroundColour.GetPixel()) );
0d54461f 2050 ::RGBForeColor( &MAC_WXCOLORREF( m_textBackgroundColour.GetPixel()) );
76a5e5d2
SC
2051 BitMap* gwbitmap = (BitMap*) *gwpixmaphandle ; // since the color depth is 1 it is a BitMap
2052 UInt8 *gwbits = (UInt8*) gwbitmap->baseAddr ;
2053 int alignment = gwbitmap->rowBytes & 0x7FFF ;
66a09d47
SC
2054 Pattern pat ;
2055 for ( int i = 0 ; i < 8 ; ++i )
2056 {
2057 pat.pat[i] = gwbits[i*alignment+0] ;
2058 }
2059 UnlockPixels( GetGWorldPixMap( gw ) ) ;
2060 ::PenPat( &pat ) ;
2061 }
2062 else
2063 {
76a5e5d2
SC
2064 // this will be the code to handle power of 2 patterns, we will have to arrive at a nice
2065 // caching scheme before putting this into production
66a09d47
SC
2066 Handle image;
2067 long imageSize;
2068 PixPatHandle pixpat = NewPixPat() ;
2069
2070 CopyPixMap(gwpixmaphandle, (**pixpat).patMap);
2071 imageSize = GetPixRowBytes((**pixpat).patMap) *
2072 ((**(**pixpat).patMap).bounds.bottom -
2073 (**(**pixpat).patMap).bounds.top);
2074
2075 PtrToHand( (**gwpixmaphandle).baseAddr, &image, imageSize );
2076 (**pixpat).patData = image;
2077 if ( isMonochrome )
2078 {
76a5e5d2
SC
2079 CTabHandle ctable = ((**((**pixpat).patMap)).pmTable) ;
2080 ColorSpecPtr ctspec = (ColorSpecPtr) &(**ctable).ctTable ;
2081 if ( ctspec[0].rgb.red == 0x0000 )
2082 {
2083 ctspec[1].rgb = MAC_WXCOLORREF( m_textBackgroundColour.GetPixel()) ;
2084 ctspec[0].rgb = MAC_WXCOLORREF( m_textForegroundColour.GetPixel()) ;
2085 }
2086 else
2087 {
2088 ctspec[0].rgb = MAC_WXCOLORREF( m_textBackgroundColour.GetPixel()) ;
2089 ctspec[1].rgb = MAC_WXCOLORREF( m_textForegroundColour.GetPixel()) ;
2090 }
2091 ::CTabChanged( ctable ) ;
66a09d47
SC
2092 }
2093 ::PenPixPat(pixpat);
2094 m_macForegroundPixMap = pixpat ;
1ff301c4 2095 }
76a5e5d2 2096 UnlockPixels( gwpixmaphandle ) ;
1ff301c4
SC
2097 }
2098 else
2099 {
2100 ::PenPat(GetQDGlobalsBlack(&blackColor));
519cb848 2101 }
0d54461f 2102
1dcbbdcf 2103 short mode = patCopy ;
519cb848
SC
2104 switch( m_logicalFunction )
2105 {
2106 case wxCOPY: // src
76a5e5d2
SC
2107 if ( backgroundTransparent )
2108 mode = patOr ;
2109 else
2110 mode = patCopy ;
519cb848
SC
2111 break ;
2112 case wxINVERT: // NOT dst
76a5e5d2
SC
2113 if ( !backgroundTransparent )
2114 {
2115 ::PenPat(GetQDGlobalsBlack(&blackColor));
2116 }
519cb848
SC
2117 mode = patXor ;
2118 break ;
2119 case wxXOR: // src XOR dst
2120 mode = patXor ;
2121 break ;
2122 case wxOR_REVERSE: // src OR (NOT dst)
2123 mode = notPatOr ;
2124 break ;
2125 case wxSRC_INVERT: // (NOT src)
2126 mode = notPatCopy ;
2127 break ;
2128
2129 // unsupported TODO
2130
2131 case wxCLEAR: // 0
2132 case wxAND_REVERSE:// src AND (NOT dst)
2133 case wxAND: // src AND dst
2134 case wxAND_INVERT: // (NOT src) AND dst
2135 case wxNO_OP: // dst
2136 case wxNOR: // (NOT src) AND (NOT dst)
2137 case wxEQUIV: // (NOT src) XOR dst
2138 case wxOR_INVERT: // (NOT src) OR dst
2139 case wxNAND: // (NOT src) OR (NOT dst)
2140 case wxOR: // src OR dst
2141 case wxSET: // 1
2f1ae414
SC
2142// case wxSRC_OR: // source _bitmap_ OR destination
2143// case wxSRC_AND: // source _bitmap_ AND destination
519cb848
SC
2144 break ;
2145 }
2146 ::PenMode( mode ) ;
2147 m_macBrushInstalled = true ;
2148 m_macPenInstalled = false ;
2149 m_macFontInstalled = false ;
2150}
2151
2f1ae414
SC
2152// ---------------------------------------------------------------------------
2153// coordinates transformations
2154// ---------------------------------------------------------------------------
519cb848 2155
2f1ae414
SC
2156
2157wxCoord wxDCBase::DeviceToLogicalX(wxCoord x) const
2158{
2159 return ((wxDC *)this)->XDEV2LOG(x);
2160}
2161
2162wxCoord wxDCBase::DeviceToLogicalY(wxCoord y) const
2163{
2164 return ((wxDC *)this)->YDEV2LOG(y);
2165}
2166
2167wxCoord wxDCBase::DeviceToLogicalXRel(wxCoord x) const
2168{
2169 return ((wxDC *)this)->XDEV2LOGREL(x);
2170}
2171
2172wxCoord wxDCBase::DeviceToLogicalYRel(wxCoord y) const
2173{
2174 return ((wxDC *)this)->YDEV2LOGREL(y);
2175}
2176
2177wxCoord wxDCBase::LogicalToDeviceX(wxCoord x) const
2178{
2179 return ((wxDC *)this)->XLOG2DEV(x);
2180}
2181
2182wxCoord wxDCBase::LogicalToDeviceY(wxCoord y) const
2183{
2184 return ((wxDC *)this)->YLOG2DEV(y);
2185}
2186
2187wxCoord wxDCBase::LogicalToDeviceXRel(wxCoord x) const
2188{
2189 return ((wxDC *)this)->XLOG2DEVREL(x);
2190}
2191
2192wxCoord wxDCBase::LogicalToDeviceYRel(wxCoord y) const
2193{
2194 return ((wxDC *)this)->YLOG2DEVREL(y);
2195}