]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/printmac.cpp
Merged wxRichTextAttr and wxTextAttrEx into wxTextAttr, and added a font table
[wxWidgets.git] / src / mac / carbon / printmac.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/mac/carbon/printwin.cpp
3 // Purpose: wxMacPrinter framework
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #if wxUSE_PRINTING_ARCHITECTURE
16
17 #ifdef __BORLANDC__
18 #pragma hdrstop
19 #endif
20
21 #ifndef WX_PRECOMP
22 #include "wx/utils.h"
23 #include "wx/dc.h"
24 #include "wx/app.h"
25 #include "wx/msgdlg.h"
26 #include "wx/dcprint.h"
27 #include "wx/math.h"
28 #endif
29
30 #include "wx/mac/uma.h"
31
32 #include "wx/mac/printmac.h"
33 #include "wx/mac/private/print.h"
34
35 #include "wx/printdlg.h"
36 #include "wx/paper.h"
37 #include "wx/mac/printdlg.h"
38
39 #include <stdlib.h>
40
41 IMPLEMENT_DYNAMIC_CLASS(wxMacCarbonPrintData, wxPrintNativeDataBase)
42 IMPLEMENT_DYNAMIC_CLASS(wxMacPrinter, wxPrinterBase)
43 IMPLEMENT_CLASS(wxMacPrintPreview, wxPrintPreviewBase)
44
45 bool wxMacCarbonPrintData::IsOk() const
46 {
47 return (m_macPageFormat != kPMNoPageFormat) && (m_macPrintSettings != kPMNoPrintSettings) && (m_macPrintSession != kPMNoReference);
48 }
49 wxMacCarbonPrintData::wxMacCarbonPrintData()
50 {
51 m_macPageFormat = kPMNoPageFormat;
52 m_macPrintSettings = kPMNoPrintSettings;
53 m_macPrintSession = kPMNoReference ;
54 ValidateOrCreate() ;
55 }
56
57 wxMacCarbonPrintData::~wxMacCarbonPrintData()
58 {
59 if (m_macPageFormat != kPMNoPageFormat)
60 {
61 (void)PMRelease(m_macPageFormat);
62 m_macPageFormat = kPMNoPageFormat;
63 }
64
65 if (m_macPrintSettings != kPMNoPrintSettings)
66 {
67 (void)PMRelease(m_macPrintSettings);
68 m_macPrintSettings = kPMNoPrintSettings;
69 }
70
71 if ( m_macPrintSession != kPMNoReference )
72 {
73 (void)PMRelease(m_macPrintSession);
74 m_macPrintSession = kPMNoReference;
75 }
76 }
77
78 void wxMacCarbonPrintData::ValidateOrCreate()
79 {
80 OSStatus err = noErr ;
81 if ( m_macPrintSession == kPMNoReference )
82 {
83 err = PMCreateSession( (PMPrintSession *) &m_macPrintSession ) ;
84 }
85 // Set up a valid PageFormat object.
86 if ( m_macPageFormat == kPMNoPageFormat)
87 {
88 err = PMCreatePageFormat((PMPageFormat *) &m_macPageFormat);
89
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.
93 if ((err == noErr) &&
94 ( m_macPageFormat != kPMNoPageFormat))
95 {
96 err = PMSessionDefaultPageFormat((PMPrintSession) m_macPrintSession,
97 (PMPageFormat) m_macPageFormat);
98 }
99 }
100 else
101 {
102 err = PMSessionValidatePageFormat((PMPrintSession) m_macPrintSession,
103 (PMPageFormat) m_macPageFormat,
104 kPMDontWantBoolean);
105 }
106
107 // Set up a valid PrintSettings object.
108 if ( m_macPrintSettings == kPMNoPrintSettings)
109 {
110 err = PMCreatePrintSettings((PMPrintSettings *) &m_macPrintSettings);
111
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))
117 {
118 err = PMSessionDefaultPrintSettings((PMPrintSession) m_macPrintSession,
119 (PMPrintSettings) m_macPrintSettings);
120 }
121 }
122 else
123 {
124 err = PMSessionValidatePrintSettings((PMPrintSession) m_macPrintSession,
125 (PMPrintSettings) m_macPrintSettings,
126 kPMDontWantBoolean);
127 }
128 }
129
130 bool wxMacCarbonPrintData::TransferFrom( const wxPrintData &data )
131 {
132 ValidateOrCreate() ;
133 PMSetCopies( (PMPrintSettings) m_macPrintSettings , data.GetNoCopies() , false ) ;
134 if ( data.IsOrientationReversed() )
135 PMSetOrientation( (PMPageFormat) m_macPageFormat , ( data.GetOrientation() == wxLANDSCAPE ) ?
136 kPMReverseLandscape : kPMReversePortrait , false ) ;
137 else
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() ) ) ;
144 #endif
145 #ifndef __LP64__
146 PMColorMode color ;
147 PMGetColorMode( (PMPrintSettings) m_macPrintSettings, &color ) ;
148 if ( data.GetColour() )
149 {
150 if ( color == kPMBlackAndWhite )
151 PMSetColorMode( (PMPrintSettings) m_macPrintSettings, kPMColor ) ;
152 }
153 else
154 PMSetColorMode( (PMPrintSettings) m_macPrintSettings, kPMBlackAndWhite ) ;
155 #endif
156
157 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
158 if ( PMSetDuplex!=NULL )
159 {
160 PMDuplexMode mode = 0 ;
161 switch( data.GetDuplex() )
162 {
163 case wxDUPLEX_HORIZONTAL :
164 mode = kPMDuplexNoTumble ;
165 break ;
166 case wxDUPLEX_VERTICAL :
167 mode = kPMDuplexTumble ;
168 break ;
169 case wxDUPLEX_SIMPLEX :
170 default :
171 mode = kPMDuplexNone ;
172 break ;
173 }
174 PMSetDuplex( (PMPrintSettings) m_macPrintSettings, mode ) ;
175 }
176 #endif
177 // PMQualityMode not yet accessible via API
178 // todo paperSize
179
180 PMResolution res;
181 PMPrinter printer;
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 ?
187 #else
188 PMTag tag = kPMMaxSquareResolution;
189 PMPrinterGetPrinterResolution(printer, tag, &res);
190 PMSetResolution((PMPageFormat) m_macPageFormat, &res);
191 #endif
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) ;
197
198 return true ;
199 }
200
201 bool wxMacCarbonPrintData::TransferTo( wxPrintData &data )
202 {
203 OSStatus err = noErr ;
204
205 UInt32 copies ;
206 err = PMGetCopies( m_macPrintSettings , &copies ) ;
207 if ( err == noErr )
208 data.SetNoCopies( copies ) ;
209
210 PMOrientation orientation ;
211 err = PMGetOrientation( m_macPageFormat , &orientation ) ;
212 if ( err == noErr )
213 {
214 if ( orientation == kPMPortrait || orientation == kPMReversePortrait )
215 {
216 data.SetOrientation( wxPORTRAIT );
217 data.SetOrientationReversed( orientation == kPMReversePortrait );
218 }
219 else
220 {
221 data.SetOrientation( wxLANDSCAPE );
222 data.SetOrientationReversed( orientation == kPMReverseLandscape );
223 }
224 }
225
226 // collate cannot be set
227 #if 0
228 {
229 wxMacCFStringHolder name ;
230 PMPrinter printer ;
231 PMSessionGetCurrentPrinter( m_macPrintSession ,
232 &printer ) ;
233 m_printerName = name.AsString() ;
234 }
235 #endif
236
237 #ifndef __LP64__
238 PMColorMode color ;
239 err = PMGetColorMode( m_macPrintSettings, &color ) ;
240 if ( err == noErr )
241 data.SetColour( !(color == kPMBlackAndWhite) ) ;
242 #endif
243 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
244 if ( PMGetDuplex!=NULL )
245 {
246 PMDuplexMode mode = 0 ;
247 PMGetDuplex( (PMPrintSettings) m_macPrintSettings, &mode ) ;
248 switch( mode )
249 {
250 case kPMDuplexNoTumble :
251 data.SetDuplex(wxDUPLEX_HORIZONTAL);
252 break ;
253 case kPMDuplexTumble :
254 data.SetDuplex(wxDUPLEX_VERTICAL);
255 break ;
256 case kPMDuplexNone :
257 default :
258 data.SetDuplex(wxDUPLEX_SIMPLEX);
259 break ;
260 }
261 }
262 #endif
263 // PMQualityMode not yet accessible via API
264
265 PMPaper paper ;
266 PMGetPageFormatPaper( m_macPageFormat, &paper );
267
268 PMRect rPaper;
269 err = PMGetUnadjustedPaperRect( m_macPageFormat, &rPaper);
270 if ( err == noErr )
271 {
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)
277 {
278 data.SetPaperId(id);
279 }
280 }
281 return true ;
282 }
283
284 void wxMacCarbonPrintData::TransferFrom( wxPageSetupData *data )
285 {
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
289 }
290
291 void wxMacCarbonPrintData::TransferTo( wxPageSetupData* data )
292 {
293 PMRect rPaper;
294 OSStatus err = PMGetUnadjustedPaperRect(m_macPageFormat, &rPaper);
295 if ( err == noErr )
296 {
297 wxSize sz((int)(( rPaper.right - rPaper.left ) * pt2mm + 0.5 ) ,
298 (int)(( rPaper.bottom - rPaper.top ) * pt2mm + 0.5 ));
299 data->SetPaperSize(sz);
300
301 PMRect rPage ;
302 err = PMGetUnadjustedPageRect(m_macPageFormat , &rPage ) ;
303 if ( err == noErr )
304 {
305 data->SetMinMarginTopLeft( wxPoint (
306 (int)(((double) rPage.left - rPaper.left ) * pt2mm) ,
307 (int)(((double) rPage.top - rPaper.top ) * pt2mm) ) ) ;
308
309 data->SetMinMarginBottomRight( wxPoint (
310 (wxCoord)(((double) rPaper.right - rPage.right ) * pt2mm),
311 (wxCoord)(((double) rPaper.bottom - rPage.bottom ) * pt2mm)) ) ;
312
313 if ( data->GetMarginTopLeft().x < data->GetMinMarginTopLeft().x )
314 data->SetMarginTopLeft( wxPoint( data->GetMinMarginTopLeft().x ,
315 data->GetMarginTopLeft().y ) ) ;
316
317 if ( data->GetMarginBottomRight().x < data->GetMinMarginBottomRight().x )
318 data->SetMarginBottomRight( wxPoint( data->GetMinMarginBottomRight().x ,
319 data->GetMarginBottomRight().y ) );
320
321 if ( data->GetMarginTopLeft().y < data->GetMinMarginTopLeft().y )
322 data->SetMarginTopLeft( wxPoint( data->GetMarginTopLeft().x , data->GetMinMarginTopLeft().y ) );
323
324 if ( data->GetMarginBottomRight().y < data->GetMinMarginBottomRight().y )
325 data->SetMarginBottomRight( wxPoint( data->GetMarginBottomRight().x ,
326 data->GetMinMarginBottomRight().y) );
327 }
328 }
329 }
330
331 void wxMacCarbonPrintData::TransferTo( wxPrintDialogData* data )
332 {
333 UInt32 minPage , maxPage ;
334 PMGetPageRange( m_macPrintSettings , &minPage , &maxPage ) ;
335 data->SetMinPage( minPage ) ;
336 data->SetMaxPage( maxPage ) ;
337 UInt32 copies ;
338 PMGetCopies( m_macPrintSettings , &copies ) ;
339 data->SetNoCopies( copies ) ;
340 UInt32 from , to ;
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
344 {
345 data->SetAllPages( true ) ;
346 // This means all pages, more or less
347 data->SetFromPage(1);
348 data->SetToPage(32000);
349 }
350 else
351 {
352 data->SetFromPage( from ) ;
353 data->SetToPage( to ) ;
354 data->SetAllPages( false );
355 }
356 }
357
358 void wxMacCarbonPrintData::TransferFrom( wxPrintDialogData* data )
359 {
360 PMSetPageRange( m_macPrintSettings , data->GetMinPage() , data->GetMaxPage() ) ;
361 PMSetCopies( m_macPrintSettings , data->GetNoCopies() , false ) ;
362 PMSetFirstPage( m_macPrintSettings , data->GetFromPage() , false ) ;
363
364 if (data->GetAllPages() || data->GetFromPage() == 0)
365 PMSetLastPage( m_macPrintSettings , (UInt32) kPMPrintAllPages, true ) ;
366 else
367 PMSetLastPage( m_macPrintSettings , (UInt32) data->GetToPage() , false ) ;
368 }
369
370 /*
371 * Printer
372 */
373
374 wxMacPrinter::wxMacPrinter(wxPrintDialogData *data):
375 wxPrinterBase(data)
376 {
377 }
378
379 wxMacPrinter::~wxMacPrinter(void)
380 {
381 }
382
383 bool wxMacPrinter::Print(wxWindow *parent, wxPrintout *printout, bool prompt)
384 {
385 sm_abortIt = false;
386 sm_abortWindow = NULL;
387
388 if (!printout)
389 return false;
390
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);
396
397 // Create a suitable device context
398 wxPrinterDC *dc = NULL;
399 if (prompt)
400 {
401 wxMacPrintDialog dialog(parent, & m_printDialogData);
402 if (dialog.ShowModal() == wxID_OK)
403 {
404 dc = wxDynamicCast(dialog.GetPrintDC(), wxPrinterDC);
405 wxASSERT(dc);
406 m_printDialogData = dialog.GetPrintDialogData();
407 }
408 }
409 else
410 {
411 dc = new wxPrinterDC( m_printDialogData.GetPrintData() ) ;
412 }
413
414 // May have pressed cancel.
415 if (!dc || !dc->Ok())
416 {
417 if (dc)
418 delete dc;
419 return false;
420 }
421
422 // on the mac we have always pixels as addressing mode with 72 dpi
423 printout->SetPPIScreen(72, 72);
424 PMResolution res;
425 wxMacCarbonPrintData* nativeData = (wxMacCarbonPrintData*)
426 (m_printDialogData.GetPrintData().GetNativeData());
427 #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
428 PMPrinter printer;
429 PMSessionGetCurrentPrinter(nativeData->m_macPrintSession, &printer);
430 PMPrinterGetOutputResolution( printer, nativeData->m_macPrintSettings, &res) ;
431 #else
432 PMGetResolution((PMPageFormat) (nativeData->m_macPageFormat), &res);
433 #endif
434 printout->SetPPIPrinter(int(res.hRes), int(res.vRes));
435
436 // Set printout parameters
437 printout->SetDC(dc);
438
439 int w, h;
440 dc->GetSize(&w, &h);
441 printout->SetPageSizePixels((int)w, (int)h);
442 printout->SetPaperRectPixels(dc->GetPaperRect());
443 wxCoord mw, mh;
444 dc->GetSizeMM(&mw, &mh);
445 printout->SetPageSizeMM((int)mw, (int)mh);
446
447 // Create an abort window
448 wxBeginBusyCursor();
449
450 printout->OnPreparePrinting();
451
452 // Get some parameters from the printout, if defined
453 int fromPage, toPage;
454 int minPage, maxPage;
455 printout->GetPageInfo(&minPage, &maxPage, &fromPage, &toPage);
456
457 if (maxPage == 0)
458 {
459 wxEndBusyCursor();
460 return false;
461 }
462
463 // Only set min and max, because from and to have been
464 // set by the user
465 m_printDialogData.SetMinPage(minPage);
466 m_printDialogData.SetMaxPage(maxPage);
467
468 wxWindow *win = CreateAbortWindow(parent, printout);
469 wxSafeYield(win,true);
470
471 if (!win)
472 {
473 wxEndBusyCursor();
474 wxMessageBox(wxT("Sorry, could not create an abort dialog."), wxT("Print Error"), wxOK, parent);
475 delete dc;
476
477 return false;
478 }
479
480 sm_abortWindow = win;
481 sm_abortWindow->Show(true);
482 wxSafeYield(win,true);
483
484 printout->OnBeginPrinting();
485
486 bool keepGoing = true;
487
488 int copyCount;
489 for (copyCount = 1; copyCount <= m_printDialogData.GetNoCopies(); copyCount ++)
490 {
491 if (!printout->OnBeginDocument(m_printDialogData.GetFromPage(), m_printDialogData.GetToPage()))
492 {
493 wxEndBusyCursor();
494 wxMessageBox(wxT("Could not start printing."), wxT("Print Error"), wxOK, parent);
495 break;
496 }
497 if (sm_abortIt)
498 break;
499
500 int pn;
501 for (pn = m_printDialogData.GetFromPage();
502 keepGoing && (pn <= m_printDialogData.GetToPage()) && printout->HasPage(pn);
503 pn++)
504 {
505 if (sm_abortIt)
506 {
507 keepGoing = false;
508 break;
509 }
510 else
511 {
512 #if TARGET_CARBON
513 if ( UMAGetSystemVersion() >= 0x1000 )
514 #endif
515 {
516 #if !wxMAC_USE_CORE_GRAPHICS
517 GrafPtr thePort ;
518 GetPort( &thePort ) ;
519 #endif
520 wxSafeYield(win,true);
521 #if !wxMAC_USE_CORE_GRAPHICS
522 SetPort( thePort ) ;
523 #endif
524 }
525 dc->StartPage();
526 keepGoing = printout->OnPrintPage(pn);
527 dc->EndPage();
528 }
529 }
530 printout->OnEndDocument();
531 }
532
533 printout->OnEndPrinting();
534
535 if (sm_abortWindow)
536 {
537 sm_abortWindow->Show(false);
538 delete sm_abortWindow;
539 sm_abortWindow = NULL;
540 }
541
542 wxEndBusyCursor();
543
544 delete dc;
545
546 return true;
547 }
548
549 wxDC* wxMacPrinter::PrintDialog(wxWindow *parent)
550 {
551 wxDC* dc = (wxDC*) NULL;
552
553 wxPrintDialog dialog(parent, & m_printDialogData);
554 int ret = dialog.ShowModal();
555
556 if (ret == wxID_OK)
557 {
558 dc = dialog.GetPrintDC();
559 m_printDialogData = dialog.GetPrintDialogData();
560 }
561
562 return dc;
563 }
564
565 bool wxMacPrinter::Setup(wxWindow *parent)
566 {
567 #if 0
568 wxPrintDialog dialog(parent, & m_printDialogData);
569 dialog.GetPrintDialogData().SetSetupDialog(true);
570
571 int ret = dialog.ShowModal();
572
573 if (ret == wxID_OK)
574 m_printDialogData = dialog.GetPrintDialogData();
575
576 return (ret == wxID_OK);
577 #endif
578
579 return wxID_CANCEL;
580 }
581
582 /*
583 * Print preview
584 */
585
586 wxMacPrintPreview::wxMacPrintPreview(wxPrintout *printout,
587 wxPrintout *printoutForPrinting,
588 wxPrintDialogData *data)
589 : wxPrintPreviewBase(printout, printoutForPrinting, data)
590 {
591 DetermineScaling();
592 }
593
594 wxMacPrintPreview::wxMacPrintPreview(wxPrintout *printout, wxPrintout *printoutForPrinting, wxPrintData *data):
595 wxPrintPreviewBase(printout, printoutForPrinting, data)
596 {
597 DetermineScaling();
598 }
599
600 wxMacPrintPreview::~wxMacPrintPreview(void)
601 {
602 }
603
604 bool wxMacPrintPreview::Print(bool interactive)
605 {
606 if (!m_printPrintout)
607 return false;
608
609 wxMacPrinter printer(&m_printDialogData);
610 return printer.Print(m_previewFrame, m_printPrintout, interactive);
611 }
612
613 void wxMacPrintPreview::DetermineScaling(void)
614 {
615 int screenWidth , screenHeight ;
616 wxDisplaySize( &screenWidth , &screenHeight ) ;
617
618 wxSize ppiScreen( 72 , 72 ) ;
619 wxSize ppiPrinter( 72 , 72 ) ;
620
621 // Note that with Leopard, screen dpi=72 is no longer a given
622 m_previewPrintout->SetPPIScreen( ppiScreen.x , ppiScreen.y ) ;
623
624 wxCoord w , h ;
625 wxCoord ww, hh;
626 wxRect paperRect;
627
628 // Get a device context for the currently selected printer
629 wxPrinterDC printerDC(m_printDialogData.GetPrintData());
630 if (printerDC.Ok())
631 {
632 printerDC.GetSizeMM(&ww, &hh);
633 printerDC.GetSize( &w , &h ) ;
634 ppiPrinter = printerDC.GetPPI() ;
635 paperRect = printerDC.GetPaperRect();
636 m_isOk = true ;
637 }
638 else
639 {
640 // use some defaults
641 w = 8 * 72 ;
642 h = 11 * 72 ;
643 ww = (wxCoord) (w * 25.4 / ppiPrinter.x) ;
644 hh = (wxCoord) (h * 25.4 / ppiPrinter.y) ;
645 paperRect = wxRect(0, 0, w, h);
646 m_isOk = false ;
647 }
648 m_pageWidth = w;
649 m_pageHeight = h;
650
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 ) ;
655
656 m_previewScaleX = float(ppiScreen.x) / ppiPrinter.x;
657 m_previewScaleY = float(ppiScreen.y) / ppiPrinter.y;
658 }
659
660 #endif