1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/core/printmac.cpp
3 // Purpose: wxMacPrinter framework
4 // Author: Julian Smart, Stefan Csomor
8 // Copyright: (c) Julian Smart, Stefan Csomor
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/osx/private.h"
32 #include "wx/osx/printmac.h"
33 #include "wx/osx/private/print.h"
35 #include "wx/printdlg.h"
37 #include "wx/osx/printdlg.h"
42 // move to print_osx.cpp
45 IMPLEMENT_DYNAMIC_CLASS(wxOSXPrintData
, wxPrintNativeDataBase
)
47 bool wxOSXPrintData::IsOk() const
49 return (m_macPageFormat
!= kPMNoPageFormat
) && (m_macPrintSettings
!= kPMNoPrintSettings
) && (m_macPrintSession
!= kPMNoReference
);
52 wxOSXPrintData::wxOSXPrintData()
54 m_macPageFormat
= kPMNoPageFormat
;
55 m_macPrintSettings
= kPMNoPrintSettings
;
56 m_macPrintSession
= kPMNoReference
;
57 m_macPaper
= kPMNoData
;
60 wxOSXPrintData::~wxOSXPrintData()
64 void wxOSXPrintData::UpdateFromPMState()
68 void wxOSXPrintData::UpdateToPMState()
72 bool wxOSXPrintData::TransferFrom( const wxPrintData
&data
)
75 PMSessionGetCurrentPrinter(m_macPrintSession
, &printer
);
77 wxSize papersize
= wxDefaultSize
;
78 const wxPaperSize paperId
= data
.GetPaperId();
79 if ( paperId
!= wxPAPER_NONE
&& wxThePrintPaperDatabase
)
81 papersize
= wxThePrintPaperDatabase
->GetSize(paperId
);
82 if ( papersize
!= wxDefaultSize
)
90 papersize
= data
.GetPaperSize();
93 if ( papersize
!= wxDefaultSize
)
95 papersize
.x
= (wxInt32
) (papersize
.x
* mm2pt
);
96 papersize
.y
= (wxInt32
) (papersize
.y
* mm2pt
);
99 PMPaperGetHeight(m_macPaper
, &height
);
100 PMPaperGetWidth(m_macPaper
, &width
);
102 if ( fabs( width
- papersize
.x
) >= 5 ||
103 fabs( height
- papersize
.y
) >= 5 )
105 // we have to change the current paper
106 CFArrayRef paperlist
= 0 ;
107 if ( PMPrinterGetPaperList( printer
, &paperlist
) == noErr
)
109 PMPaper bestPaper
= kPMNoData
;
110 CFIndex top
= CFArrayGetCount(paperlist
);
111 for ( CFIndex i
= 0 ; i
< top
; ++ i
)
113 PMPaper paper
= (PMPaper
) CFArrayGetValueAtIndex( paperlist
, i
);
114 PMPaperGetHeight(paper
, &height
);
115 PMPaperGetWidth(paper
, &width
);
116 if ( fabs( width
- papersize
.x
) < 5 &&
117 fabs( height
- papersize
.y
) < 5 )
119 // TODO test for duplicate hits and use additional
120 // criteria for best match
124 PMPaper paper
= kPMNoData
;
125 if ( bestPaper
== kPMNoData
)
127 const PMPaperMargins margins
= { 0.0, 0.0, 0.0, 0.0 };
128 wxString id
, name(wxT("Custom paper"));
129 id
.Printf(wxT("wxPaperCustom%dx%d"), papersize
.x
, papersize
.y
);
131 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
132 if ( PMPaperCreateCustom
!= NULL
)
134 PMPaperCreateCustom(printer
, wxCFStringRef( id
, wxFont::GetDefaultEncoding() ), wxCFStringRef( name
, wxFont::GetDefaultEncoding() ),
135 papersize
.x
, papersize
.y
, &margins
, &paper
);
138 #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
139 if ( paper
== kPMNoData
)
141 PMPaperCreate(printer
, wxCFStringRef( id
, wxFont::GetDefaultEncoding() ), wxCFStringRef( name
, wxFont::GetDefaultEncoding() ),
142 papersize
.x
, papersize
.y
, &margins
, &paper
);
146 if ( bestPaper
!= kPMNoData
)
148 PMPageFormat pageFormat
;
149 PMCreatePageFormatWithPMPaper(&pageFormat
, bestPaper
);
150 PMCopyPageFormat( pageFormat
, m_macPageFormat
);
151 PMRelease(pageFormat
);
152 PMGetPageFormatPaper(m_macPageFormat
, &m_macPaper
);
159 CFArrayRef printerList
;
160 CFIndex index
, count
;
163 if (PMServerCreatePrinterList(kPMServerLocal
, &printerList
) == noErr
)
165 count
= CFArrayGetCount(printerList
);
166 for (index
= 0; index
< count
; index
++)
168 printer
= (PMPrinter
)CFArrayGetValueAtIndex(printerList
, index
);
169 if ((data
.GetPrinterName().empty()) && (PMPrinterIsDefault(printer
)))
173 name
= PMPrinterGetName(printer
);
175 if (data
.GetPrinterName() == wxCFStringRef(name
).AsString())
180 PMSessionSetCurrentPMPrinter(m_macPrintSession
, printer
);
181 CFRelease(printerList
);
184 PMSetCopies( m_macPrintSettings
, data
.GetNoCopies() , false ) ;
185 PMSetCollate(m_macPrintSettings
, data
.GetCollate());
186 if ( data
.IsOrientationReversed() )
187 PMSetOrientation( m_macPageFormat
, ( data
.GetOrientation() == wxLANDSCAPE
) ?
188 kPMReverseLandscape
: kPMReversePortrait
, false ) ;
190 PMSetOrientation( m_macPageFormat
, ( data
.GetOrientation() == wxLANDSCAPE
) ?
191 kPMLandscape
: kPMPortrait
, false ) ;
193 PMDuplexMode mode
= 0 ;
194 switch( data
.GetDuplex() )
196 case wxDUPLEX_HORIZONTAL
:
197 mode
= kPMDuplexNoTumble
;
199 case wxDUPLEX_VERTICAL
:
200 mode
= kPMDuplexTumble
;
202 case wxDUPLEX_SIMPLEX
:
204 mode
= kPMDuplexNone
;
207 PMSetDuplex( m_macPrintSettings
, mode
) ;
209 // PMQualityMode not yet accessible via API
212 if ( data
.IsOrientationReversed() )
213 PMSetOrientation( m_macPageFormat
, ( data
.GetOrientation() == wxLANDSCAPE
) ?
214 kPMReverseLandscape
: kPMReversePortrait
, false ) ;
216 PMSetOrientation( m_macPageFormat
, ( data
.GetOrientation() == wxLANDSCAPE
) ?
217 kPMLandscape
: kPMPortrait
, false ) ;
220 // PMQualityMode not accessible via API
221 // TODO: use our quality property to determine optimal resolution
223 PMTag tag
= kPMMaxSquareResolution
;
224 PMPrinterGetPrinterResolution(printer
, tag
, &res
);
225 PMSetResolution( m_macPageFormat
, &res
);
228 // after setting the new resolution the format has to be updated, otherwise the page rect remains
229 // at the 'old' scaling
231 PMSessionValidatePageFormat(m_macPrintSession
,
232 m_macPageFormat
, kPMDontWantBoolean
);
233 PMSessionValidatePrintSettings(m_macPrintSession
,
234 m_macPrintSettings
, kPMDontWantBoolean
);
242 bool wxOSXPrintData::TransferTo( wxPrintData
&data
)
244 OSStatus err
= noErr
;
249 err
= PMGetCopies( m_macPrintSettings
, &copies
) ;
251 data
.SetNoCopies( copies
) ;
253 PMOrientation orientation
;
254 err
= PMGetOrientation( m_macPageFormat
, &orientation
) ;
257 if ( orientation
== kPMPortrait
|| orientation
== kPMReversePortrait
)
259 data
.SetOrientation( wxPORTRAIT
);
260 data
.SetOrientationReversed( orientation
== kPMReversePortrait
);
264 data
.SetOrientation( wxLANDSCAPE
);
265 data
.SetOrientationReversed( orientation
== kPMReverseLandscape
);
270 if (PMGetCollate(m_macPrintSettings
, &collate
) == noErr
)
271 data
.SetCollate(collate
);
275 PMSessionGetCurrentPrinter( m_macPrintSession
, &printer
);
276 if (PMPrinterIsDefault(printer
))
277 data
.SetPrinterName(wxEmptyString
);
280 name
= PMPrinterGetName(printer
);
282 data
.SetPrinterName(wxCFStringRef(name
).AsString());
285 PMDuplexMode mode
= 0 ;
286 PMGetDuplex( m_macPrintSettings
, &mode
) ;
289 case kPMDuplexNoTumble
:
290 data
.SetDuplex(wxDUPLEX_HORIZONTAL
);
292 case kPMDuplexTumble
:
293 data
.SetDuplex(wxDUPLEX_VERTICAL
);
297 data
.SetDuplex(wxDUPLEX_SIMPLEX
);
300 // PMQualityMode not yet accessible via API
302 double height
, width
;
303 PMPaperGetHeight(m_macPaper
, &height
);
304 PMPaperGetWidth(m_macPaper
, &width
);
306 wxSize
sz((int)(width
* pt2mm
+ 0.5 ) ,
307 (int)(height
* pt2mm
+ 0.5 ));
308 data
.SetPaperSize(sz
);
309 wxPaperSize id
= wxThePrintPaperDatabase
->GetSize(wxSize(sz
.x
* 10, sz
.y
* 10));
310 if (id
!= wxPAPER_NONE
)
317 void wxOSXPrintData::TransferFrom( wxPageSetupData
*WXUNUSED(data
) )
319 // should we setup the page rect here ?
320 // since MacOS sometimes has two same paper rects with different
321 // page rects we could make it roundtrip safe perhaps
324 void wxOSXPrintData::TransferTo( wxPageSetupData
* data
)
330 OSStatus err
= PMGetUnadjustedPaperRect(m_macPageFormat
, &rPaper
);
333 wxSize
sz((int)(( rPaper
.right
- rPaper
.left
) * pt2mm
+ 0.5 ) ,
334 (int)(( rPaper
.bottom
- rPaper
.top
) * pt2mm
+ 0.5 ));
335 data
->SetPaperSize(sz
);
338 err
= PMGetUnadjustedPageRect(m_macPageFormat
, &rPage
) ;
341 data
->SetMinMarginTopLeft( wxPoint (
342 (int)(((double) rPage
.left
- rPaper
.left
) * pt2mm
) ,
343 (int)(((double) rPage
.top
- rPaper
.top
) * pt2mm
) ) ) ;
345 data
->SetMinMarginBottomRight( wxPoint (
346 (wxCoord
)(((double) rPaper
.right
- rPage
.right
) * pt2mm
),
347 (wxCoord
)(((double) rPaper
.bottom
- rPage
.bottom
) * pt2mm
)) ) ;
349 if ( data
->GetMarginTopLeft().x
< data
->GetMinMarginTopLeft().x
)
350 data
->SetMarginTopLeft( wxPoint( data
->GetMinMarginTopLeft().x
,
351 data
->GetMarginTopLeft().y
) ) ;
353 if ( data
->GetMarginBottomRight().x
< data
->GetMinMarginBottomRight().x
)
354 data
->SetMarginBottomRight( wxPoint( data
->GetMinMarginBottomRight().x
,
355 data
->GetMarginBottomRight().y
) );
357 if ( data
->GetMarginTopLeft().y
< data
->GetMinMarginTopLeft().y
)
358 data
->SetMarginTopLeft( wxPoint( data
->GetMarginTopLeft().x
, data
->GetMinMarginTopLeft().y
) );
360 if ( data
->GetMarginBottomRight().y
< data
->GetMinMarginBottomRight().y
)
361 data
->SetMarginBottomRight( wxPoint( data
->GetMarginBottomRight().x
,
362 data
->GetMinMarginBottomRight().y
) );
367 void wxOSXPrintData::TransferTo( wxPrintDialogData
* data
)
372 UInt32 minPage
, maxPage
;
373 PMGetPageRange( m_macPrintSettings
, &minPage
, &maxPage
) ;
374 data
->SetMinPage( minPage
) ;
375 data
->SetMaxPage( maxPage
) ;
377 PMGetCopies( m_macPrintSettings
, &copies
) ;
378 data
->SetNoCopies( copies
) ;
380 PMGetFirstPage( m_macPrintSettings
, &from
) ;
381 PMGetLastPage( m_macPrintSettings
, &to
) ;
382 if ( to
>= 0x7FFFFFFF ) // due to an OS Bug we don't get back kPMPrintAllPages
384 data
->SetAllPages( true ) ;
385 // This means all pages, more or less
386 data
->SetFromPage(1);
387 data
->SetToPage(9999);
391 data
->SetFromPage( from
) ;
392 data
->SetToPage( to
) ;
393 data
->SetAllPages( false );
397 void wxOSXPrintData::TransferFrom( wxPrintDialogData
* data
)
399 // Respect the value of m_printAllPages
400 if ( data
->GetAllPages() )
401 PMSetPageRange( m_macPrintSettings
, data
->GetMinPage() , (UInt32
) kPMPrintAllPages
) ;
403 PMSetPageRange( m_macPrintSettings
, data
->GetMinPage() , data
->GetMaxPage() ) ;
404 PMSetCopies( m_macPrintSettings
, data
->GetNoCopies() , false ) ;
405 PMSetFirstPage( m_macPrintSettings
, data
->GetFromPage() , false ) ;
407 if (data
->GetAllPages() || data
->GetFromPage() == 0)
408 PMSetLastPage( m_macPrintSettings
, (UInt32
) kPMPrintAllPages
, true ) ;
410 PMSetLastPage( m_macPrintSettings
, (UInt32
) data
->GetToPage() , false ) ;
416 wxPrintNativeDataBase
* wxOSXCreatePrintData()
419 return new wxOSXCocoaPrintData();
422 return new wxOSXCarbonPrintData();
431 IMPLEMENT_DYNAMIC_CLASS(wxMacPrinter
, wxPrinterBase
)
433 wxMacPrinter::wxMacPrinter(wxPrintDialogData
*data
):
438 wxMacPrinter::~wxMacPrinter(void)
442 bool wxMacPrinter::Print(wxWindow
*parent
, wxPrintout
*printout
, bool prompt
)
445 sm_abortWindow
= NULL
;
450 printout
->SetIsPreview(false);
451 if (m_printDialogData
.GetMinPage() < 1)
452 m_printDialogData
.SetMinPage(1);
453 if (m_printDialogData
.GetMaxPage() < 1)
454 m_printDialogData
.SetMaxPage(9999);
456 // Create a suitable device context
457 wxPrinterDC
*dc
= NULL
;
460 wxMacPrintDialog
dialog(parent
, & m_printDialogData
);
461 if (dialog
.ShowModal() == wxID_OK
)
463 dc
= wxDynamicCast(dialog
.GetPrintDC(), wxPrinterDC
);
465 m_printDialogData
= dialog
.GetPrintDialogData();
470 dc
= new wxPrinterDC( m_printDialogData
.GetPrintData() ) ;
473 // May have pressed cancel.
474 if (!dc
|| !dc
->IsOk())
480 // on the mac we have always pixels as addressing mode with 72 dpi
481 printout
->SetPPIScreen(72, 72);
484 wxOSXPrintData
* nativeData
= (wxOSXPrintData
*)
485 (m_printDialogData
.GetPrintData().GetNativeData());
486 PMGetResolution( (nativeData
->GetPageFormat()), &res
);
487 printout
->SetPPIPrinter(int(res
.hRes
), int(res
.vRes
));
489 // Set printout parameters
494 printout
->SetPageSizePixels((int)w
, (int)h
);
495 printout
->SetPaperRectPixels(dc
->GetPaperRect());
497 dc
->GetSizeMM(&mw
, &mh
);
498 printout
->SetPageSizeMM((int)mw
, (int)mh
);
500 // Create an abort window
503 printout
->OnPreparePrinting();
505 // Get some parameters from the printout, if defined
506 int fromPage
, toPage
;
507 int minPage
, maxPage
;
508 printout
->GetPageInfo(&minPage
, &maxPage
, &fromPage
, &toPage
);
516 // Only set min and max, because from and to have been
518 m_printDialogData
.SetMinPage(minPage
);
519 m_printDialogData
.SetMaxPage(maxPage
);
521 printout
->OnBeginPrinting();
523 bool keepGoing
= true;
525 if (!printout
->OnBeginDocument(m_printDialogData
.GetFromPage(), m_printDialogData
.GetToPage()))
528 wxMessageBox(wxT("Could not start printing."), wxT("Print Error"), wxOK
, parent
);
532 for (pn
= m_printDialogData
.GetFromPage();
533 keepGoing
&& (pn
<= m_printDialogData
.GetToPage()) && printout
->HasPage(pn
);
544 keepGoing
= printout
->OnPrintPage(pn
);
548 printout
->OnEndDocument();
550 printout
->OnEndPrinting();
554 sm_abortWindow
->Show(false);
555 delete sm_abortWindow
;
556 sm_abortWindow
= NULL
;
566 wxDC
* wxMacPrinter::PrintDialog(wxWindow
*parent
)
570 wxPrintDialog
dialog(parent
, & m_printDialogData
);
571 int ret
= dialog
.ShowModal();
575 dc
= dialog
.GetPrintDC();
576 m_printDialogData
= dialog
.GetPrintDialogData();
582 bool wxMacPrinter::Setup(wxWindow
*WXUNUSED(parent
))
585 wxPrintDialog
dialog(parent
, & m_printDialogData
);
586 dialog
.GetPrintDialogData().SetSetupDialog(true);
588 int ret
= dialog
.ShowModal();
591 m_printDialogData
= dialog
.GetPrintDialogData();
593 return (ret
== wxID_OK
);
603 IMPLEMENT_CLASS(wxMacPrintPreview
, wxPrintPreviewBase
)
605 wxMacPrintPreview::wxMacPrintPreview(wxPrintout
*printout
,
606 wxPrintout
*printoutForPrinting
,
607 wxPrintDialogData
*data
)
608 : wxPrintPreviewBase(printout
, printoutForPrinting
, data
)
613 wxMacPrintPreview::wxMacPrintPreview(wxPrintout
*printout
, wxPrintout
*printoutForPrinting
, wxPrintData
*data
):
614 wxPrintPreviewBase(printout
, printoutForPrinting
, data
)
619 wxMacPrintPreview::~wxMacPrintPreview(void)
623 bool wxMacPrintPreview::Print(bool interactive
)
625 if (!m_printPrintout
)
628 wxMacPrinter
printer(&m_printDialogData
);
629 return printer
.Print(m_previewFrame
, m_printPrintout
, interactive
);
632 void wxMacPrintPreview::DetermineScaling(void)
634 int screenWidth
, screenHeight
;
635 wxDisplaySize( &screenWidth
, &screenHeight
) ;
637 wxSize
ppiScreen( 72 , 72 ) ;
638 wxSize
ppiPrinter( 72 , 72 ) ;
640 // Note that with Leopard, screen dpi=72 is no longer a given
641 m_previewPrintout
->SetPPIScreen( ppiScreen
.x
, ppiScreen
.y
) ;
647 // Get a device context for the currently selected printer
648 wxPrinterDC
printerDC(m_printDialogData
.GetPrintData());
649 if (printerDC
.IsOk())
651 printerDC
.GetSizeMM(&ww
, &hh
);
652 printerDC
.GetSize( &w
, &h
) ;
653 ppiPrinter
= printerDC
.GetPPI() ;
654 paperRect
= printerDC
.GetPaperRect();
662 ww
= (wxCoord
) (w
* 25.4 / ppiPrinter
.x
) ;
663 hh
= (wxCoord
) (h
* 25.4 / ppiPrinter
.y
) ;
664 paperRect
= wxRect(0, 0, w
, h
);
670 m_previewPrintout
->SetPageSizePixels(w
, h
) ;
671 m_previewPrintout
->SetPageSizeMM(ww
, hh
);
672 m_previewPrintout
->SetPaperRectPixels(paperRect
);
673 m_previewPrintout
->SetPPIPrinter( ppiPrinter
.x
, ppiPrinter
.y
) ;
675 m_previewScaleX
= float(ppiScreen
.x
) / ppiPrinter
.x
;
676 m_previewScaleY
= float(ppiScreen
.y
) / ppiPrinter
.y
;
680 // end of print_osx.cpp
685 IMPLEMENT_DYNAMIC_CLASS(wxOSXCarbonPrintData
, wxOSXPrintData
)
687 wxOSXCarbonPrintData::wxOSXCarbonPrintData()
689 if ( PMCreateSession( &m_macPrintSession
) == noErr
)
691 if ( PMCreatePageFormat(&m_macPageFormat
) == noErr
)
693 PMSessionDefaultPageFormat(m_macPrintSession
,
695 PMGetPageFormatPaper(m_macPageFormat
, &m_macPaper
);
698 if ( PMCreatePrintSettings(&m_macPrintSettings
) == noErr
)
700 PMSessionDefaultPrintSettings(m_macPrintSession
,
706 wxOSXCarbonPrintData::~wxOSXCarbonPrintData()
708 (void)PMRelease(m_macPageFormat
);
709 (void)PMRelease(m_macPrintSettings
);
710 (void)PMRelease(m_macPrintSession
);