1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/mac/carbon/printwin.cpp 
   3 // Purpose:     wxMacPrinter framework 
   4 // Author:      Julian Smart 
   8 // Copyright:   (c) Julian Smart 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // For compilers that support precompilation, includes "wx.h". 
  13 #include "wx/wxprec.h" 
  15 #if wxUSE_PRINTING_ARCHITECTURE 
  25     #include "wx/msgdlg.h" 
  26     #include "wx/dcprint.h" 
  30 #include "wx/mac/uma.h" 
  32 #include "wx/mac/printmac.h" 
  33 #include "wx/mac/private/print.h" 
  35 #include "wx/printdlg.h" 
  37 #include "wx/mac/printdlg.h" 
  41 IMPLEMENT_DYNAMIC_CLASS(wxMacCarbonPrintData
, wxPrintNativeDataBase
) 
  42 IMPLEMENT_DYNAMIC_CLASS(wxMacPrinter
, wxPrinterBase
) 
  43 IMPLEMENT_CLASS(wxMacPrintPreview
, wxPrintPreviewBase
) 
  45 bool wxMacCarbonPrintData::IsOk() const 
  47     return (m_macPageFormat 
!= kPMNoPageFormat
) && (m_macPrintSettings 
!= kPMNoPrintSettings
) && (m_macPrintSession 
!= kPMNoReference
); 
  49 wxMacCarbonPrintData::wxMacCarbonPrintData() 
  51     m_macPageFormat 
= kPMNoPageFormat
; 
  52     m_macPrintSettings 
= kPMNoPrintSettings
; 
  53     m_macPrintSession 
= kPMNoReference 
; 
  57 wxMacCarbonPrintData::~wxMacCarbonPrintData() 
  59     if (m_macPageFormat 
!= kPMNoPageFormat
) 
  61         (void)PMRelease(m_macPageFormat
); 
  62         m_macPageFormat 
= kPMNoPageFormat
; 
  65     if (m_macPrintSettings 
!= kPMNoPrintSettings
) 
  67         (void)PMRelease(m_macPrintSettings
); 
  68         m_macPrintSettings 
= kPMNoPrintSettings
; 
  71     if ( m_macPrintSession 
!= kPMNoReference 
) 
  73         (void)PMRelease(m_macPrintSession
); 
  74         m_macPrintSession 
= kPMNoReference
; 
  78 void wxMacCarbonPrintData::ValidateOrCreate() 
  80     OSStatus err 
= noErr 
; 
  81     if ( m_macPrintSession 
== kPMNoReference 
) 
  83         err 
= PMCreateSession( (PMPrintSession 
*) &m_macPrintSession 
) ; 
  85     //  Set up a valid PageFormat object. 
  86     if ( m_macPageFormat 
== kPMNoPageFormat
) 
  88         err 
= PMCreatePageFormat((PMPageFormat 
*) &m_macPageFormat
); 
  90         //  Note that PMPageFormat is not session-specific, but calling 
  91         //  PMSessionDefaultPageFormat assigns values specific to the printer 
  92         //  associated with the current printing session. 
  94             ( m_macPageFormat 
!= kPMNoPageFormat
)) 
  96             err 
= PMSessionDefaultPageFormat((PMPrintSession
) m_macPrintSession
, 
  97                 (PMPageFormat
) m_macPageFormat
); 
 102         err 
= PMSessionValidatePageFormat((PMPrintSession
) m_macPrintSession
, 
 103             (PMPageFormat
) m_macPageFormat
, 
 107     //  Set up a valid PrintSettings object. 
 108     if ( m_macPrintSettings 
== kPMNoPrintSettings
) 
 110         err 
= PMCreatePrintSettings((PMPrintSettings 
*) &m_macPrintSettings
); 
 112         //  Note that PMPrintSettings is not session-specific, but calling 
 113         //  PMSessionDefaultPrintSettings assigns values specific to the printer 
 114         //  associated with the current printing session. 
 115         if ((err 
== noErr
) && 
 116             ( m_macPrintSettings 
!= kPMNoPrintSettings
)) 
 118             err 
= PMSessionDefaultPrintSettings((PMPrintSession
) m_macPrintSession
, 
 119                 (PMPrintSettings
) m_macPrintSettings
); 
 124         err 
= PMSessionValidatePrintSettings((PMPrintSession
) m_macPrintSession
, 
 125             (PMPrintSettings
) m_macPrintSettings
, 
 130 bool wxMacCarbonPrintData::TransferFrom( const wxPrintData 
&data 
) 
 133     PMSetCopies( (PMPrintSettings
) m_macPrintSettings 
, data
.GetNoCopies() , false ) ; 
 134     if ( data
.IsOrientationReversed() ) 
 135         PMSetOrientation( (PMPageFormat
) m_macPageFormat 
, ( data
.GetOrientation() == wxLANDSCAPE 
) ? 
 136             kPMReverseLandscape 
: kPMReversePortrait 
, false ) ; 
 138         PMSetOrientation( (PMPageFormat
) m_macPageFormat 
, ( data
.GetOrientation() == wxLANDSCAPE 
) ? 
 139             kPMLandscape 
: kPMPortrait 
, false ) ; 
 140     // collate cannot be set 
 141 #if 0 // not yet tested 
 142     if ( !m_printerName
.empty() ) 
 143         PMSessionSetCurrentPrinter( (PMPrintSession
) m_macPrintSession 
, wxMacCFStringHolder( m_printerName 
, wxFont::GetDefaultEncoding() ) ) ; 
 147     PMGetColorMode(  (PMPrintSettings
) m_macPrintSettings
, &color 
) ; 
 148     if ( data
.GetColour() ) 
 150         if ( color 
== kPMBlackAndWhite 
) 
 151             PMSetColorMode( (PMPrintSettings
) m_macPrintSettings
, kPMColor 
) ; 
 154         PMSetColorMode( (PMPrintSettings
) m_macPrintSettings
, kPMBlackAndWhite 
) ; 
 157 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 
 158     if ( PMSetDuplex
!=NULL 
) 
 160         PMDuplexMode mode 
= 0 ; 
 161         switch( data
.GetDuplex() ) 
 163             case wxDUPLEX_HORIZONTAL 
: 
 164                 mode 
= kPMDuplexNoTumble 
; 
 166             case wxDUPLEX_VERTICAL 
: 
 167                 mode 
= kPMDuplexTumble 
; 
 169             case wxDUPLEX_SIMPLEX 
: 
 171                 mode 
= kPMDuplexNone 
; 
 174         PMSetDuplex( (PMPrintSettings
) m_macPrintSettings
, mode 
) ; 
 177     // PMQualityMode not yet accessible via API 
 182     PMSessionGetCurrentPrinter(m_macPrintSession
, &printer
); 
 183 #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5  
 184     PMPrinterGetOutputResolution( printer
,   
 185         (PMPrintSettings
) m_macPrintSettings
,  &res
) ; 
 186     // TODO transfer ? into page format ? 
 188     PMTag tag 
= kPMMaxSquareResolution
; 
 189     PMPrinterGetPrinterResolution(printer
, tag
, &res
); 
 190     PMSetResolution((PMPageFormat
) m_macPageFormat
, &res
); 
 192     // after setting the new resolution the format has to be updated, otherwise the page rect remains  
 193     // at the 'old' scaling 
 194     PMSessionValidatePageFormat((PMPrintSession
) m_macPrintSession
, 
 195             (PMPageFormat
) m_macPageFormat
, 
 196             kPMDontWantBoolean
) ; 
 201 bool wxMacCarbonPrintData::TransferTo( wxPrintData 
&data 
) 
 203     OSStatus err 
= noErr 
; 
 206     err 
= PMGetCopies( m_macPrintSettings 
, &copies 
) ; 
 208         data
.SetNoCopies( copies 
) ; 
 210     PMOrientation orientation 
; 
 211     err 
= PMGetOrientation(  m_macPageFormat 
, &orientation 
) ; 
 214         if ( orientation 
== kPMPortrait 
|| orientation 
== kPMReversePortrait 
) 
 216             data
.SetOrientation( wxPORTRAIT  
); 
 217             data
.SetOrientationReversed( orientation 
== kPMReversePortrait 
); 
 221             data
.SetOrientation( wxLANDSCAPE 
); 
 222             data
.SetOrientationReversed( orientation 
== kPMReverseLandscape 
); 
 226     // collate cannot be set 
 229         wxMacCFStringHolder name 
; 
 231         PMSessionGetCurrentPrinter( m_macPrintSession 
, 
 233         m_printerName 
= name
.AsString() ; 
 239     err 
= PMGetColorMode( m_macPrintSettings
, &color 
) ; 
 241         data
.SetColour( !(color 
== kPMBlackAndWhite
) ) ; 
 243 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 
 244     if ( PMGetDuplex
!=NULL 
) 
 246         PMDuplexMode mode 
= 0 ; 
 247         PMGetDuplex( (PMPrintSettings
) m_macPrintSettings
, &mode 
) ; 
 250             case kPMDuplexNoTumble 
: 
 251                 data
.SetDuplex(wxDUPLEX_HORIZONTAL
); 
 253             case kPMDuplexTumble 
: 
 254                 data
.SetDuplex(wxDUPLEX_VERTICAL
); 
 258                 data
.SetDuplex(wxDUPLEX_SIMPLEX
); 
 263     // PMQualityMode not yet accessible via API 
 266     PMGetPageFormatPaper( m_macPageFormat
, &paper 
); 
 269     err 
= PMGetUnadjustedPaperRect( m_macPageFormat
, &rPaper
); 
 272         wxSize 
sz((int)(( rPaper
.right 
- rPaper
.left 
) * pt2mm 
+ 0.5 ) , 
 273              (int)(( rPaper
.bottom 
- rPaper
.top 
) * pt2mm 
+ 0.5 )); 
 274         data
.SetPaperSize(sz
); 
 275         wxPaperSize id 
= wxThePrintPaperDatabase
->GetSize(wxSize(sz
.x
* 10, sz
.y 
* 10)); 
 276         if (id 
!= wxPAPER_NONE
) 
 284 void wxMacCarbonPrintData::TransferFrom( wxPageSetupData 
*data 
) 
 286     // should we setup the page rect here ? 
 287     // since MacOS sometimes has two same paper rects with different 
 288     // page rects we could make it roundtrip safe perhaps 
 291 void wxMacCarbonPrintData::TransferTo( wxPageSetupData
* data 
) 
 294     OSStatus err 
= PMGetUnadjustedPaperRect(m_macPageFormat
, &rPaper
); 
 297         wxSize 
sz((int)(( rPaper
.right 
- rPaper
.left 
) * pt2mm 
+ 0.5 ) , 
 298              (int)(( rPaper
.bottom 
- rPaper
.top 
) * pt2mm 
+ 0.5 )); 
 299         data
->SetPaperSize(sz
); 
 302         err 
= PMGetUnadjustedPageRect(m_macPageFormat 
, &rPage 
) ; 
 305             data
->SetMinMarginTopLeft( wxPoint ( 
 306                 (int)(((double) rPage
.left 
- rPaper
.left 
) * pt2mm
) , 
 307                 (int)(((double) rPage
.top 
- rPaper
.top 
) * pt2mm
) ) ) ; 
 309             data
->SetMinMarginBottomRight( wxPoint ( 
 310                 (wxCoord
)(((double) rPaper
.right 
- rPage
.right 
) * pt2mm
), 
 311                 (wxCoord
)(((double) rPaper
.bottom 
- rPage
.bottom 
) * pt2mm
)) ) ; 
 313             if ( data
->GetMarginTopLeft().x 
< data
->GetMinMarginTopLeft().x 
) 
 314                 data
->SetMarginTopLeft( wxPoint( data
->GetMinMarginTopLeft().x 
, 
 315                     data
->GetMarginTopLeft().y 
) ) ; 
 317             if ( data
->GetMarginBottomRight().x 
< data
->GetMinMarginBottomRight().x 
) 
 318                 data
->SetMarginBottomRight( wxPoint( data
->GetMinMarginBottomRight().x 
, 
 319                     data
->GetMarginBottomRight().y 
) ); 
 321             if ( data
->GetMarginTopLeft().y 
< data
->GetMinMarginTopLeft().y 
) 
 322                 data
->SetMarginTopLeft( wxPoint( data
->GetMarginTopLeft().x 
, data
->GetMinMarginTopLeft().y 
) ); 
 324             if ( data
->GetMarginBottomRight().y 
< data
->GetMinMarginBottomRight().y 
) 
 325                 data
->SetMarginBottomRight( wxPoint( data
->GetMarginBottomRight().x 
, 
 326                     data
->GetMinMarginBottomRight().y
) ); 
 331 void wxMacCarbonPrintData::TransferTo( wxPrintDialogData
* data 
) 
 333     UInt32 minPage 
, maxPage 
; 
 334     PMGetPageRange( m_macPrintSettings 
, &minPage 
, &maxPage 
) ; 
 335     data
->SetMinPage( minPage 
) ; 
 336     data
->SetMaxPage( maxPage 
) ; 
 338     PMGetCopies( m_macPrintSettings 
, &copies 
) ; 
 339     data
->SetNoCopies( copies 
) ; 
 341     PMGetFirstPage( m_macPrintSettings 
, &from 
) ; 
 342     PMGetLastPage( m_macPrintSettings 
, &to 
) ; 
 343     if ( to 
>= 0x7FFFFFFF ) //  due to an OS Bug we don't get back kPMPrintAllPages 
 345         data
->SetAllPages( true ) ; 
 346         // This means all pages, more or less 
 347         data
->SetFromPage(1); 
 348         data
->SetToPage(32000); 
 352         data
->SetFromPage( from 
) ; 
 353         data
->SetToPage( to 
) ; 
 354         data
->SetAllPages( false ); 
 358 void wxMacCarbonPrintData::TransferFrom( wxPrintDialogData
* data 
) 
 360     PMSetPageRange( m_macPrintSettings 
, data
->GetMinPage() , data
->GetMaxPage() ) ; 
 361     PMSetCopies( m_macPrintSettings 
, data
->GetNoCopies() , false ) ; 
 362     PMSetFirstPage( m_macPrintSettings 
, data
->GetFromPage() , false ) ; 
 364     if (data
->GetAllPages() || data
->GetFromPage() == 0) 
 365         PMSetLastPage( m_macPrintSettings 
, (UInt32
) kPMPrintAllPages
, true ) ; 
 367         PMSetLastPage( m_macPrintSettings 
, (UInt32
) data
->GetToPage() , false ) ; 
 374 wxMacPrinter::wxMacPrinter(wxPrintDialogData 
*data
): 
 379 wxMacPrinter::~wxMacPrinter(void) 
 383 bool wxMacPrinter::Print(wxWindow 
*parent
, wxPrintout 
*printout
, bool prompt
) 
 386     sm_abortWindow 
= NULL
; 
 391     printout
->SetIsPreview(false); 
 392     if (m_printDialogData
.GetMinPage() < 1) 
 393         m_printDialogData
.SetMinPage(1); 
 394     if (m_printDialogData
.GetMaxPage() < 1) 
 395         m_printDialogData
.SetMaxPage(9999); 
 397     // Create a suitable device context 
 398     wxPrinterDC 
*dc 
= NULL
; 
 401         wxMacPrintDialog 
dialog(parent
, & m_printDialogData
); 
 402         if (dialog
.ShowModal() == wxID_OK
) 
 404             dc 
= wxDynamicCast(dialog
.GetPrintDC(), wxPrinterDC
); 
 406             m_printDialogData 
= dialog
.GetPrintDialogData(); 
 411         dc 
= new wxPrinterDC( m_printDialogData
.GetPrintData() ) ; 
 414     // May have pressed cancel. 
 415     if (!dc 
|| !dc
->Ok()) 
 422     // on the mac we have always pixels as addressing mode with 72 dpi 
 423     printout
->SetPPIScreen(72, 72); 
 425     wxMacCarbonPrintData
* nativeData 
= (wxMacCarbonPrintData
*) 
 426           (m_printDialogData
.GetPrintData().GetNativeData()); 
 427 #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5  
 429     PMSessionGetCurrentPrinter(nativeData
->m_macPrintSession
, &printer
); 
 430     PMPrinterGetOutputResolution( printer
, nativeData
->m_macPrintSettings
, &res
) ; 
 432     PMGetResolution((PMPageFormat
) (nativeData
->m_macPageFormat
), &res
); 
 434     printout
->SetPPIPrinter(int(res
.hRes
), int(res
.vRes
)); 
 436     // Set printout parameters 
 441     printout
->SetPageSizePixels((int)w
, (int)h
); 
 442     printout
->SetPaperRectPixels(dc
->GetPaperRect()); 
 444     dc
->GetSizeMM(&mw
, &mh
); 
 445     printout
->SetPageSizeMM((int)mw
, (int)mh
); 
 447     // Create an abort window 
 450     printout
->OnPreparePrinting(); 
 452     // Get some parameters from the printout, if defined 
 453     int fromPage
, toPage
; 
 454     int minPage
, maxPage
; 
 455     printout
->GetPageInfo(&minPage
, &maxPage
, &fromPage
, &toPage
); 
 463     // Only set min and max, because from and to have been 
 465     m_printDialogData
.SetMinPage(minPage
); 
 466     m_printDialogData
.SetMaxPage(maxPage
); 
 468     wxWindow 
*win 
= CreateAbortWindow(parent
, printout
); 
 469     wxSafeYield(win
,true); 
 474         wxMessageBox(wxT("Sorry, could not create an abort dialog."), wxT("Print Error"), wxOK
, parent
); 
 480     sm_abortWindow 
= win
; 
 481     sm_abortWindow
->Show(true); 
 482     wxSafeYield(win
,true); 
 484     printout
->OnBeginPrinting(); 
 486     bool keepGoing 
= true; 
 489     for (copyCount 
= 1; copyCount 
<= m_printDialogData
.GetNoCopies(); copyCount 
++) 
 491         if (!printout
->OnBeginDocument(m_printDialogData
.GetFromPage(), m_printDialogData
.GetToPage())) 
 494             wxMessageBox(wxT("Could not start printing."), wxT("Print Error"), wxOK
, parent
); 
 501         for (pn 
= m_printDialogData
.GetFromPage(); 
 502         keepGoing 
&& (pn 
<= m_printDialogData
.GetToPage()) && printout
->HasPage(pn
); 
 513                 if ( UMAGetSystemVersion() >= 0x1000 ) 
 516 #if !wxMAC_USE_CORE_GRAPHICS 
 518                     GetPort( &thePort 
) ; 
 520                     wxSafeYield(win
,true); 
 521 #if !wxMAC_USE_CORE_GRAPHICS 
 526                 keepGoing 
= printout
->OnPrintPage(pn
); 
 530         printout
->OnEndDocument(); 
 533     printout
->OnEndPrinting(); 
 537         sm_abortWindow
->Show(false); 
 538         delete sm_abortWindow
; 
 539         sm_abortWindow 
= NULL
; 
 549 wxDC
* wxMacPrinter::PrintDialog(wxWindow 
*parent
) 
 551     wxDC
* dc 
= (wxDC
*) NULL
; 
 553     wxPrintDialog 
dialog(parent
, & m_printDialogData
); 
 554     int ret 
= dialog
.ShowModal(); 
 558         dc 
= dialog
.GetPrintDC(); 
 559         m_printDialogData 
= dialog
.GetPrintDialogData(); 
 565 bool wxMacPrinter::Setup(wxWindow 
*parent
) 
 568     wxPrintDialog 
dialog(parent
, & m_printDialogData
); 
 569     dialog
.GetPrintDialogData().SetSetupDialog(true); 
 571     int ret 
= dialog
.ShowModal(); 
 574         m_printDialogData 
= dialog
.GetPrintDialogData(); 
 576     return (ret 
== wxID_OK
); 
 586 wxMacPrintPreview::wxMacPrintPreview(wxPrintout 
*printout
, 
 587                                      wxPrintout 
*printoutForPrinting
, 
 588                                      wxPrintDialogData 
*data
) 
 589                                      : wxPrintPreviewBase(printout
, printoutForPrinting
, data
) 
 594 wxMacPrintPreview::wxMacPrintPreview(wxPrintout 
*printout
, wxPrintout 
*printoutForPrinting
, wxPrintData 
*data
): 
 595 wxPrintPreviewBase(printout
, printoutForPrinting
, data
) 
 600 wxMacPrintPreview::~wxMacPrintPreview(void) 
 604 bool wxMacPrintPreview::Print(bool interactive
) 
 606     if (!m_printPrintout
) 
 609     wxMacPrinter 
printer(&m_printDialogData
); 
 610     return printer
.Print(m_previewFrame
, m_printPrintout
, interactive
); 
 613 void wxMacPrintPreview::DetermineScaling(void) 
 615     int screenWidth 
, screenHeight 
; 
 616     wxDisplaySize( &screenWidth 
, &screenHeight 
) ; 
 618     wxSize 
ppiScreen( 72 , 72 ) ; 
 619     wxSize 
ppiPrinter( 72 , 72 ) ; 
 621     // Note that with Leopard, screen dpi=72 is no longer a given 
 622     m_previewPrintout
->SetPPIScreen( ppiScreen
.x 
, ppiScreen
.y 
) ; 
 628     // Get a device context for the currently selected printer 
 629     wxPrinterDC 
printerDC(m_printDialogData
.GetPrintData()); 
 632         printerDC
.GetSizeMM(&ww
, &hh
); 
 633         printerDC
.GetSize( &w 
, &h 
) ; 
 634         ppiPrinter 
= printerDC
.GetPPI() ; 
 635         paperRect 
= printerDC
.GetPaperRect(); 
 643         ww 
= (wxCoord
) (w 
* 25.4 / ppiPrinter
.x
) ; 
 644         hh 
= (wxCoord
) (h 
* 25.4 / ppiPrinter
.y
) ; 
 645         paperRect 
= wxRect(0, 0, w
, h
); 
 651     m_previewPrintout
->SetPageSizePixels(w 
, h
) ; 
 652     m_previewPrintout
->SetPageSizeMM(ww
, hh
); 
 653     m_previewPrintout
->SetPaperRectPixels(paperRect
); 
 654     m_previewPrintout
->SetPPIPrinter( ppiPrinter
.x 
, ppiPrinter
.y 
) ; 
 656     m_previewScaleX 
= float(ppiScreen
.x
) / ppiPrinter
.x
; 
 657     m_previewScaleY 
= float(ppiScreen
.y
) / ppiPrinter
.y
;