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( &m_macPrintSession 
) ; 
  85     //  Set up a valid PageFormat object. 
  86     if ( m_macPageFormat 
== kPMNoPageFormat
) 
  88         err 
= PMCreatePageFormat(&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(m_macPrintSession
, 
 102         err 
= PMSessionValidatePageFormat(m_macPrintSession
, 
 107     //  Set up a valid PrintSettings object. 
 108     if ( m_macPrintSettings 
== kPMNoPrintSettings
) 
 110         err 
= PMCreatePrintSettings( &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(m_macPrintSession
, 
 124         err 
= PMSessionValidatePrintSettings( m_macPrintSession
, 
 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 
, wxCFStringRef( 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     PMDuplexMode mode 
= 0 ; 
 158     switch( data
.GetDuplex() ) 
 160         case wxDUPLEX_HORIZONTAL 
: 
 161             mode 
= kPMDuplexNoTumble 
; 
 163         case wxDUPLEX_VERTICAL 
: 
 164             mode 
= kPMDuplexTumble 
; 
 166         case wxDUPLEX_SIMPLEX 
: 
 168             mode 
= kPMDuplexNone 
; 
 171     PMSetDuplex( (PMPrintSettings
) m_macPrintSettings
, mode 
) ; 
 173     // PMQualityMode not yet accessible via API 
 178     PMSessionGetCurrentPrinter(m_macPrintSession
, &printer
); 
 179 #if 0 // MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5  
 180     PMPrinterGetOutputResolution( printer
,   
 181         (PMPrintSettings
) m_macPrintSettings
,  &res
) ; 
 182     // TODO transfer ? into page format ? 
 185     PMTag tag 
= kPMMaxSquareResolution
; 
 186     PMPrinterGetPrinterResolution(printer
, tag
, &res
); 
 187     PMSetResolution((PMPageFormat
) m_macPageFormat
, &res
); 
 189     // after setting the new resolution the format has to be updated, otherwise the page rect remains  
 190     // at the 'old' scaling 
 191     PMSessionValidatePageFormat((PMPrintSession
) m_macPrintSession
, 
 192             (PMPageFormat
) m_macPageFormat
, 
 193             kPMDontWantBoolean
) ; 
 198 bool wxMacCarbonPrintData::TransferTo( wxPrintData 
&data 
) 
 200     OSStatus err 
= noErr 
; 
 203     err 
= PMGetCopies( m_macPrintSettings 
, &copies 
) ; 
 205         data
.SetNoCopies( copies 
) ; 
 207     PMOrientation orientation 
; 
 208     err 
= PMGetOrientation(  m_macPageFormat 
, &orientation 
) ; 
 211         if ( orientation 
== kPMPortrait 
|| orientation 
== kPMReversePortrait 
) 
 213             data
.SetOrientation( wxPORTRAIT  
); 
 214             data
.SetOrientationReversed( orientation 
== kPMReversePortrait 
); 
 218             data
.SetOrientation( wxLANDSCAPE 
); 
 219             data
.SetOrientationReversed( orientation 
== kPMReverseLandscape 
); 
 223     // collate cannot be set 
 228         PMSessionGetCurrentPrinter( m_macPrintSession 
, 
 230         m_printerName 
= name
.AsString() ; 
 236     err 
= PMGetColorMode( m_macPrintSettings
, &color 
) ; 
 238         data
.SetColour( !(color 
== kPMBlackAndWhite
) ) ; 
 240     PMDuplexMode mode 
= 0 ; 
 241     PMGetDuplex( (PMPrintSettings
) m_macPrintSettings
, &mode 
) ; 
 244         case kPMDuplexNoTumble 
: 
 245             data
.SetDuplex(wxDUPLEX_HORIZONTAL
); 
 247         case kPMDuplexTumble 
: 
 248             data
.SetDuplex(wxDUPLEX_VERTICAL
); 
 252             data
.SetDuplex(wxDUPLEX_SIMPLEX
); 
 255     // PMQualityMode not yet accessible via API 
 258     PMGetPageFormatPaper( m_macPageFormat
, &paper 
); 
 261     err 
= PMGetUnadjustedPaperRect( m_macPageFormat
, &rPaper
); 
 264         wxSize 
sz((int)(( rPaper
.right 
- rPaper
.left 
) * pt2mm 
+ 0.5 ) , 
 265              (int)(( rPaper
.bottom 
- rPaper
.top 
) * pt2mm 
+ 0.5 )); 
 266         data
.SetPaperSize(sz
); 
 267         wxPaperSize id 
= wxThePrintPaperDatabase
->GetSize(wxSize(sz
.x
* 10, sz
.y 
* 10)); 
 268         if (id 
!= wxPAPER_NONE
) 
 276 void wxMacCarbonPrintData::TransferFrom( wxPageSetupData 
*WXUNUSED(data
) ) 
 278     // should we setup the page rect here ? 
 279     // since MacOS sometimes has two same paper rects with different 
 280     // page rects we could make it roundtrip safe perhaps 
 283 void wxMacCarbonPrintData::TransferTo( wxPageSetupData
* data 
) 
 286     OSStatus err 
= PMGetUnadjustedPaperRect(m_macPageFormat
, &rPaper
); 
 289         wxSize 
sz((int)(( rPaper
.right 
- rPaper
.left 
) * pt2mm 
+ 0.5 ) , 
 290              (int)(( rPaper
.bottom 
- rPaper
.top 
) * pt2mm 
+ 0.5 )); 
 291         data
->SetPaperSize(sz
); 
 294         err 
= PMGetUnadjustedPageRect(m_macPageFormat 
, &rPage 
) ; 
 297             data
->SetMinMarginTopLeft( wxPoint ( 
 298                 (int)(((double) rPage
.left 
- rPaper
.left 
) * pt2mm
) , 
 299                 (int)(((double) rPage
.top 
- rPaper
.top 
) * pt2mm
) ) ) ; 
 301             data
->SetMinMarginBottomRight( wxPoint ( 
 302                 (wxCoord
)(((double) rPaper
.right 
- rPage
.right 
) * pt2mm
), 
 303                 (wxCoord
)(((double) rPaper
.bottom 
- rPage
.bottom 
) * pt2mm
)) ) ; 
 305             if ( data
->GetMarginTopLeft().x 
< data
->GetMinMarginTopLeft().x 
) 
 306                 data
->SetMarginTopLeft( wxPoint( data
->GetMinMarginTopLeft().x 
, 
 307                     data
->GetMarginTopLeft().y 
) ) ; 
 309             if ( data
->GetMarginBottomRight().x 
< data
->GetMinMarginBottomRight().x 
) 
 310                 data
->SetMarginBottomRight( wxPoint( data
->GetMinMarginBottomRight().x 
, 
 311                     data
->GetMarginBottomRight().y 
) ); 
 313             if ( data
->GetMarginTopLeft().y 
< data
->GetMinMarginTopLeft().y 
) 
 314                 data
->SetMarginTopLeft( wxPoint( data
->GetMarginTopLeft().x 
, data
->GetMinMarginTopLeft().y 
) ); 
 316             if ( data
->GetMarginBottomRight().y 
< data
->GetMinMarginBottomRight().y 
) 
 317                 data
->SetMarginBottomRight( wxPoint( data
->GetMarginBottomRight().x 
, 
 318                     data
->GetMinMarginBottomRight().y
) ); 
 323 void wxMacCarbonPrintData::TransferTo( wxPrintDialogData
* data 
) 
 325     UInt32 minPage 
, maxPage 
; 
 326     PMGetPageRange( m_macPrintSettings 
, &minPage 
, &maxPage 
) ; 
 327     data
->SetMinPage( minPage 
) ; 
 328     data
->SetMaxPage( maxPage 
) ; 
 330     PMGetCopies( m_macPrintSettings 
, &copies 
) ; 
 331     data
->SetNoCopies( copies 
) ; 
 333     PMGetFirstPage( m_macPrintSettings 
, &from 
) ; 
 334     PMGetLastPage( m_macPrintSettings 
, &to 
) ; 
 335     if ( to 
>= 0x7FFFFFFF ) //  due to an OS Bug we don't get back kPMPrintAllPages 
 337         data
->SetAllPages( true ) ; 
 338         // This means all pages, more or less 
 339         data
->SetFromPage(1); 
 340         data
->SetToPage(32000); 
 344         data
->SetFromPage( from 
) ; 
 345         data
->SetToPage( to 
) ; 
 346         data
->SetAllPages( false ); 
 350 void wxMacCarbonPrintData::TransferFrom( wxPrintDialogData
* data 
) 
 352     PMSetPageRange( m_macPrintSettings 
, data
->GetMinPage() , data
->GetMaxPage() ) ; 
 353     PMSetCopies( m_macPrintSettings 
, data
->GetNoCopies() , false ) ; 
 354     PMSetFirstPage( m_macPrintSettings 
, data
->GetFromPage() , false ) ; 
 356     if (data
->GetAllPages() || data
->GetFromPage() == 0) 
 357         PMSetLastPage( m_macPrintSettings 
, (UInt32
) kPMPrintAllPages
, true ) ; 
 359         PMSetLastPage( m_macPrintSettings 
, (UInt32
) data
->GetToPage() , false ) ; 
 366 wxMacPrinter::wxMacPrinter(wxPrintDialogData 
*data
): 
 371 wxMacPrinter::~wxMacPrinter(void) 
 375 bool wxMacPrinter::Print(wxWindow 
*parent
, wxPrintout 
*printout
, bool prompt
) 
 378     sm_abortWindow 
= NULL
; 
 383     printout
->SetIsPreview(false); 
 384     if (m_printDialogData
.GetMinPage() < 1) 
 385         m_printDialogData
.SetMinPage(1); 
 386     if (m_printDialogData
.GetMaxPage() < 1) 
 387         m_printDialogData
.SetMaxPage(9999); 
 389     // Create a suitable device context 
 390     wxPrinterDC 
*dc 
= NULL
; 
 393         wxMacPrintDialog 
dialog(parent
, & m_printDialogData
); 
 394         if (dialog
.ShowModal() == wxID_OK
) 
 396             dc 
= wxDynamicCast(dialog
.GetPrintDC(), wxPrinterDC
); 
 398             m_printDialogData 
= dialog
.GetPrintDialogData(); 
 403         dc 
= new wxPrinterDC( m_printDialogData
.GetPrintData() ) ; 
 406     // May have pressed cancel. 
 407     if (!dc 
|| !dc
->IsOk()) 
 414     // on the mac we have always pixels as addressing mode with 72 dpi 
 415     printout
->SetPPIScreen(72, 72); 
 417     wxMacCarbonPrintData
* nativeData 
= (wxMacCarbonPrintData
*) 
 418           (m_printDialogData
.GetPrintData().GetNativeData()); 
 419 #if 0 // MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5  
 421     PMSessionGetCurrentPrinter(nativeData
->m_macPrintSession
, &printer
); 
 422     PMPrinterGetOutputResolution( printer
, nativeData
->m_macPrintSettings
, &res
) ; 
 424     PMGetResolution((PMPageFormat
) (nativeData
->m_macPageFormat
), &res
); 
 426     printout
->SetPPIPrinter(int(res
.hRes
), int(res
.vRes
)); 
 428     // Set printout parameters 
 433     printout
->SetPageSizePixels((int)w
, (int)h
); 
 434     printout
->SetPaperRectPixels(dc
->GetPaperRect()); 
 436     dc
->GetSizeMM(&mw
, &mh
); 
 437     printout
->SetPageSizeMM((int)mw
, (int)mh
); 
 439     // Create an abort window 
 442     printout
->OnPreparePrinting(); 
 444     // Get some parameters from the printout, if defined 
 445     int fromPage
, toPage
; 
 446     int minPage
, maxPage
; 
 447     printout
->GetPageInfo(&minPage
, &maxPage
, &fromPage
, &toPage
); 
 455     // Only set min and max, because from and to have been 
 457     m_printDialogData
.SetMinPage(minPage
); 
 458     m_printDialogData
.SetMaxPage(maxPage
); 
 460     wxWindow 
*win 
= CreateAbortWindow(parent
, printout
); 
 461     wxSafeYield(win
,true); 
 466         wxMessageBox(wxT("Sorry, could not create an abort dialog."), wxT("Print Error"), wxOK
, parent
); 
 472     sm_abortWindow 
= win
; 
 473     sm_abortWindow
->Show(true); 
 474     wxSafeYield(win
,true); 
 476     printout
->OnBeginPrinting(); 
 478     bool keepGoing 
= true; 
 481     for (copyCount 
= 1; copyCount 
<= m_printDialogData
.GetNoCopies(); copyCount 
++) 
 483         if (!printout
->OnBeginDocument(m_printDialogData
.GetFromPage(), m_printDialogData
.GetToPage())) 
 486             wxMessageBox(wxT("Could not start printing."), wxT("Print Error"), wxOK
, parent
); 
 493         for (pn 
= m_printDialogData
.GetFromPage(); 
 494         keepGoing 
&& (pn 
<= m_printDialogData
.GetToPage()) && printout
->HasPage(pn
); 
 504                 wxSafeYield(win
,true); 
 506                 keepGoing 
= printout
->OnPrintPage(pn
); 
 510         printout
->OnEndDocument(); 
 513     printout
->OnEndPrinting(); 
 517         sm_abortWindow
->Show(false); 
 518         delete sm_abortWindow
; 
 519         sm_abortWindow 
= NULL
; 
 529 wxDC
* wxMacPrinter::PrintDialog(wxWindow 
*parent
) 
 531     wxDC
* dc 
= (wxDC
*) NULL
; 
 533     wxPrintDialog 
dialog(parent
, & m_printDialogData
); 
 534     int ret 
= dialog
.ShowModal(); 
 538         dc 
= dialog
.GetPrintDC(); 
 539         m_printDialogData 
= dialog
.GetPrintDialogData(); 
 545 bool wxMacPrinter::Setup(wxWindow 
*WXUNUSED(parent
)) 
 548     wxPrintDialog 
dialog(parent
, & m_printDialogData
); 
 549     dialog
.GetPrintDialogData().SetSetupDialog(true); 
 551     int ret 
= dialog
.ShowModal(); 
 554         m_printDialogData 
= dialog
.GetPrintDialogData(); 
 556     return (ret 
== wxID_OK
); 
 566 wxMacPrintPreview::wxMacPrintPreview(wxPrintout 
*printout
, 
 567                                      wxPrintout 
*printoutForPrinting
, 
 568                                      wxPrintDialogData 
*data
) 
 569                                      : wxPrintPreviewBase(printout
, printoutForPrinting
, data
) 
 574 wxMacPrintPreview::wxMacPrintPreview(wxPrintout 
*printout
, wxPrintout 
*printoutForPrinting
, wxPrintData 
*data
): 
 575 wxPrintPreviewBase(printout
, printoutForPrinting
, data
) 
 580 wxMacPrintPreview::~wxMacPrintPreview(void) 
 584 bool wxMacPrintPreview::Print(bool interactive
) 
 586     if (!m_printPrintout
) 
 589     wxMacPrinter 
printer(&m_printDialogData
); 
 590     return printer
.Print(m_previewFrame
, m_printPrintout
, interactive
); 
 593 void wxMacPrintPreview::DetermineScaling(void) 
 595     int screenWidth 
, screenHeight 
; 
 596     wxDisplaySize( &screenWidth 
, &screenHeight 
) ; 
 598     wxSize 
ppiScreen( 72 , 72 ) ; 
 599     wxSize 
ppiPrinter( 72 , 72 ) ; 
 601     // Note that with Leopard, screen dpi=72 is no longer a given 
 602     m_previewPrintout
->SetPPIScreen( ppiScreen
.x 
, ppiScreen
.y 
) ; 
 608     // Get a device context for the currently selected printer 
 609     wxPrinterDC 
printerDC(m_printDialogData
.GetPrintData()); 
 610     if (printerDC
.IsOk()) 
 612         printerDC
.GetSizeMM(&ww
, &hh
); 
 613         printerDC
.GetSize( &w 
, &h 
) ; 
 614         ppiPrinter 
= printerDC
.GetPPI() ; 
 615         paperRect 
= printerDC
.GetPaperRect(); 
 623         ww 
= (wxCoord
) (w 
* 25.4 / ppiPrinter
.x
) ; 
 624         hh 
= (wxCoord
) (h 
* 25.4 / ppiPrinter
.y
) ; 
 625         paperRect 
= wxRect(0, 0, w
, h
); 
 631     m_previewPrintout
->SetPageSizePixels(w 
, h
) ; 
 632     m_previewPrintout
->SetPageSizeMM(ww
, hh
); 
 633     m_previewPrintout
->SetPaperRectPixels(paperRect
); 
 634     m_previewPrintout
->SetPPIPrinter( ppiPrinter
.x 
, ppiPrinter
.y 
) ; 
 636     m_previewScaleX 
= float(ppiScreen
.x
) / ppiPrinter
.x
; 
 637     m_previewScaleY 
= float(ppiScreen
.y
) / ppiPrinter
.y
;