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