1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/carbon/dcprint.cpp
3 // Purpose: wxPrinterDC class
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 01/02/97
7 // Copyright: (c) Julian Smart
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 // For compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
13
14 #if wxUSE_PRINTING_ARCHITECTURE
15
16
17 #include "wx/dcprint.h"
18
19 #ifndef WX_PRECOMP
20 #include "wx/msgdlg.h"
21 #include "wx/math.h"
22 #endif
23
24 #include "wx/osx/private.h"
25 #include "wx/osx/private/print.h"
26 #include "wx/osx/dcprint.h"
27 #include "wx/graphics.h"
28
29 wxIMPLEMENT_ABSTRACT_CLASS(wxPrinterDCImpl, wxGCDCImpl);
30
31 class wxNativePrinterDC
32 {
33 public :
wxNativePrinterDC()34 wxNativePrinterDC() {}
~wxNativePrinterDC()35 virtual ~wxNativePrinterDC() {}
36 virtual bool StartDoc( wxPrinterDC* dc , const wxString& message ) = 0;
37 virtual void EndDoc( wxPrinterDC* dc ) = 0;
38 virtual void StartPage( wxPrinterDC* dc ) = 0;
39 virtual void EndPage( wxPrinterDC* dc ) = 0;
40 virtual void GetSize( int *w , int *h) const = 0 ;
41 virtual wxSize GetPPI() const = 0 ;
42
43 // returns 0 in case of no Error, otherwise platform specific error codes
44 virtual wxUint32 GetStatus() const = 0 ;
IsOk() const45 bool IsOk() const { return GetStatus() == 0 ; }
46
47 static wxNativePrinterDC* Create(wxPrintData* data) ;
48 } ;
49
50 class wxMacCarbonPrinterDC : public wxNativePrinterDC
51 {
52 public :
53 wxMacCarbonPrinterDC( wxPrintData* data ) ;
54 virtual ~wxMacCarbonPrinterDC() ;
55 virtual bool StartDoc( wxPrinterDC* dc , const wxString& message ) wxOVERRIDE ;
56 virtual void EndDoc( wxPrinterDC* dc ) wxOVERRIDE ;
57 virtual void StartPage( wxPrinterDC* dc ) wxOVERRIDE ;
58 virtual void EndPage( wxPrinterDC* dc ) wxOVERRIDE ;
GetStatus() const59 virtual wxUint32 GetStatus() const wxOVERRIDE { return m_err ; }
60 virtual void GetSize( int *w , int *h) const wxOVERRIDE ;
61 virtual wxSize GetPPI() const wxOVERRIDE ;
62 private :
63 wxCoord m_maxX ;
64 wxCoord m_maxY ;
65 wxSize m_ppi ;
66 OSStatus m_err ;
67 } ;
68
wxMacCarbonPrinterDC(wxPrintData * data)69 wxMacCarbonPrinterDC::wxMacCarbonPrinterDC( wxPrintData* data )
70 {
71 m_err = noErr ;
72 wxOSXPrintData *native = (wxOSXPrintData*) data->GetNativeData() ;
73
74 PMRect rPage;
75 m_err = PMGetAdjustedPageRect(native->GetPageFormat(), &rPage);
76 if ( m_err != noErr )
77 return;
78
79 m_maxX = wxCoord(rPage.right - rPage.left) ;
80 m_maxY = wxCoord(rPage.bottom - rPage.top);
81
82 PMResolution res;
83 PMPrinter printer;
84 m_err = PMSessionGetCurrentPrinter(native->GetPrintSession(), &printer);
85 if ( m_err == noErr )
86 {
87 m_err = PMPrinterGetOutputResolution( printer, native->GetPrintSettings(), &res) ;
88 if ( m_err == -9589 /* kPMKeyNotFound */ )
89 {
90 m_err = noErr ;
91 res.hRes = res.vRes = 300;
92 }
93 }
94 else
95 {
96 res.hRes = res.vRes = 300;
97 }
98
99 m_maxX = wxCoord((double)m_maxX * res.hRes / 72.0);
100 m_maxY = wxCoord((double)m_maxY * res.vRes / 72.0);
101
102 m_ppi = wxSize(int(res.hRes), int(res.vRes));
103 }
104
~wxMacCarbonPrinterDC()105 wxMacCarbonPrinterDC::~wxMacCarbonPrinterDC()
106 {
107 }
108
Create(wxPrintData * data)109 wxNativePrinterDC* wxNativePrinterDC::Create(wxPrintData* data)
110 {
111 return new wxMacCarbonPrinterDC(data) ;
112 }
113
StartDoc(wxPrinterDC * dc,const wxString & message)114 bool wxMacCarbonPrinterDC::StartDoc( wxPrinterDC* dc , const wxString& message )
115 {
116 if ( m_err )
117 return false ;
118
119 wxPrinterDCImpl *impl = (wxPrinterDCImpl*) dc->GetImpl();
120 wxOSXPrintData *native = (wxOSXPrintData*) impl->GetPrintData().GetNativeData() ;
121
122 PMPrintSettingsSetJobName(native->GetPrintSettings(), wxCFStringRef(message));
123
124 m_err = PMSessionBeginCGDocumentNoDialog(native->GetPrintSession(),
125 native->GetPrintSettings(),
126 native->GetPageFormat());
127 if ( m_err != noErr )
128 return false;
129
130 PMRect rPage;
131 m_err = PMGetAdjustedPageRect(native->GetPageFormat(), &rPage);
132 if ( m_err != noErr )
133 return false ;
134
135 m_maxX = wxCoord(rPage.right - rPage.left) ;
136 m_maxY = wxCoord(rPage.bottom - rPage.top);
137
138 PMResolution res;
139 PMPrinter printer;
140
141 bool useDefaultResolution = true;
142 m_err = PMSessionGetCurrentPrinter(native->GetPrintSession(), &printer);
143 if (m_err == noErr)
144 {
145 m_err = PMPrinterGetOutputResolution( printer, native->GetPrintSettings(), &res) ;
146 if (m_err == noErr)
147 useDefaultResolution = true;
148 }
149
150 // Ignore errors which may occur while retrieving the resolution and just
151 // use the default one.
152 if ( useDefaultResolution )
153 {
154 res.hRes =
155 res.vRes = 300;
156 m_err = noErr ;
157 }
158
159 m_maxX = wxCoord((double)m_maxX * res.hRes / 72.0);
160 m_maxY = wxCoord((double)m_maxY * res.vRes / 72.0);
161
162 m_ppi = wxSize(int(res.hRes), int(res.vRes));
163 return true ;
164 }
165
EndDoc(wxPrinterDC * dc)166 void wxMacCarbonPrinterDC::EndDoc( wxPrinterDC* dc )
167 {
168 if ( m_err )
169 return ;
170
171 wxPrinterDCImpl *impl = (wxPrinterDCImpl*) dc->GetImpl();
172 wxOSXPrintData *native = (wxOSXPrintData*) impl->GetPrintData().GetNativeData() ;
173
174 m_err = PMSessionEndDocumentNoDialog(native->GetPrintSession());
175 }
176
StartPage(wxPrinterDC * dc)177 void wxMacCarbonPrinterDC::StartPage( wxPrinterDC* dc )
178 {
179 if ( m_err )
180 return ;
181
182 wxPrinterDCImpl *impl = (wxPrinterDCImpl*) dc->GetImpl();
183 wxOSXPrintData *native = (wxOSXPrintData*) impl->GetPrintData().GetNativeData() ;
184
185 m_err = PMSessionBeginPageNoDialog(native->GetPrintSession(),
186 native->GetPageFormat(),
187 NULL);
188
189 CGContextRef pageContext = NULL ;
190
191 if ( m_err == noErr )
192 {
193 m_err = PMSessionGetCGGraphicsContext(native->GetPrintSession(),
194 &pageContext );
195 }
196
197 if ( m_err != noErr )
198 {
199 PMSessionEndPageNoDialog(native->GetPrintSession());
200 PMSessionEndDocumentNoDialog(native->GetPrintSession());
201 }
202 else
203 {
204 PMRect paperRect ;
205 m_err = PMGetAdjustedPaperRect( native->GetPageFormat() , &paperRect ) ;
206 // make sure (0,0) is at the upper left of the printable area (wx conventions)
207 // Core Graphics initially has the lower left of the paper as 0,0
208 if ( !m_err )
209 CGContextTranslateCTM( pageContext , (CGFloat) -paperRect.left , (CGFloat) paperRect.bottom ) ;
210
211 // since this is a non-critical error, we set the flag back
212 m_err = noErr ;
213
214 // Leopard deprecated PMSetResolution() which will not be available in 64 bit mode, so we avoid using it.
215 // To set the proper drawing resolution, the docs suggest the use of CGContextScaleCTM(), so here we go; as a
216 // consequence though, PMGetAdjustedPaperRect() and PMGetAdjustedPageRect() return unscaled rects, so we
217 // have to manually scale them later.
218 CGContextScaleCTM( pageContext, 72.0 / (double)m_ppi.x, -72.0 / (double)m_ppi.y);
219
220 impl->SetGraphicsContext( wxGraphicsContext::CreateFromNative( pageContext ) );
221 }
222 }
223
EndPage(wxPrinterDC * dc)224 void wxMacCarbonPrinterDC::EndPage( wxPrinterDC* dc )
225 {
226 if ( m_err )
227 return ;
228
229 wxPrinterDCImpl *impl = (wxPrinterDCImpl*) dc->GetImpl();
230 wxOSXPrintData *native = (wxOSXPrintData*) impl->GetPrintData().GetNativeData() ;
231
232 m_err = PMSessionEndPageNoDialog(native->GetPrintSession());
233 if ( m_err != noErr )
234 {
235 PMSessionEndDocumentNoDialog(native->GetPrintSession());
236 }
237 // the cg context we got when starting the page isn't valid anymore, so replace it
238 impl->SetGraphicsContext( wxGraphicsContext::Create() );
239 }
240
GetSize(int * w,int * h) const241 void wxMacCarbonPrinterDC::GetSize( int *w , int *h) const
242 {
243 if ( w )
244 *w = m_maxX ;
245 if ( h )
246 *h = m_maxY ;
247 }
248
GetPPI() const249 wxSize wxMacCarbonPrinterDC::GetPPI() const
250 {
251 return m_ppi ;
252 };
253
254 //
255 //
256 //
257
wxPrinterDCImpl(wxPrinterDC * owner,const wxPrintData & printdata)258 wxPrinterDCImpl::wxPrinterDCImpl( wxPrinterDC *owner, const wxPrintData& printdata )
259 : wxGCDCImpl( owner )
260 , m_printData(printdata)
261 {
262 m_ok = false ;
263 m_printData.ConvertToNative() ;
264 m_nativePrinterDC = wxNativePrinterDC::Create( &m_printData ) ;
265 if ( m_nativePrinterDC )
266 {
267 m_ok = m_nativePrinterDC->IsOk() ;
268 if ( !m_ok )
269 {
270 wxString message ;
271 message.Printf( wxT("Print Error %u"), m_nativePrinterDC->GetStatus() ) ;
272 wxMessageDialog dialog( NULL , message , wxEmptyString, wxICON_HAND | wxOK) ;
273 dialog.ShowModal();
274 }
275 else
276 {
277 wxSize sz = GetPPI();
278 m_mm_to_pix_x = mm2inches * sz.x;
279 m_mm_to_pix_y = mm2inches * sz.y;
280 }
281 // we need at least a measuring context because people start measuring before a page
282 // gets printed at all
283 SetGraphicsContext( wxGraphicsContext::Create() );
284 }
285 }
286
GetPPI() const287 wxSize wxPrinterDCImpl::GetPPI() const
288 {
289 return m_nativePrinterDC->GetPPI() ;
290 }
291
~wxPrinterDCImpl()292 wxPrinterDCImpl::~wxPrinterDCImpl()
293 {
294 delete m_nativePrinterDC ;
295 }
296
StartDoc(const wxString & message)297 bool wxPrinterDCImpl::StartDoc( const wxString& message )
298 {
299 wxASSERT_MSG( IsOk() , wxT("Called wxPrinterDC::StartDoc from an invalid object") ) ;
300
301 if ( !m_ok )
302 return false ;
303
304 if ( m_nativePrinterDC->StartDoc( (wxPrinterDC*) GetOwner(), message ) )
305 {
306 // in case we have to do additional things when successful
307 }
308 m_ok = m_nativePrinterDC->IsOk() ;
309 if ( !m_ok )
310 {
311 wxString message ;
312 message.Printf( wxT("Print Error %u"), m_nativePrinterDC->GetStatus() ) ;
313 wxMessageDialog dialog( NULL , message , wxEmptyString, wxICON_HAND | wxOK) ;
314 dialog.ShowModal();
315 }
316
317 return m_ok ;
318 }
319
EndDoc()320 void wxPrinterDCImpl::EndDoc()
321 {
322 if ( !m_ok )
323 return ;
324
325 m_nativePrinterDC->EndDoc( (wxPrinterDC*) GetOwner() ) ;
326 m_ok = m_nativePrinterDC->IsOk() ;
327
328 if ( !m_ok )
329 {
330 wxString message ;
331 message.Printf( wxT("Print Error %u"), m_nativePrinterDC->GetStatus() ) ;
332 wxMessageDialog dialog( NULL , message , wxEmptyString, wxICON_HAND | wxOK) ;
333 dialog.ShowModal();
334 }
335 }
336
GetPaperRect() const337 wxRect wxPrinterDCImpl::GetPaperRect() const
338 {
339 wxCoord w, h;
340 GetOwner()->GetSize(&w, &h);
341 wxRect pageRect(0, 0, w, h);
342 wxOSXPrintData *native = (wxOSXPrintData*) m_printData.GetNativeData() ;
343 OSStatus err = noErr ;
344 PMRect rPaper;
345 err = PMGetAdjustedPaperRect(native->GetPageFormat(), &rPaper);
346 if ( err != noErr )
347 return pageRect;
348
349 wxSize ppi = GetOwner()->GetPPI();
350 rPaper.right *= (ppi.x / 72.0);
351 rPaper.bottom *= (ppi.y / 72.0);
352 rPaper.left *= (ppi.x / 72.0);
353 rPaper.top *= (ppi.y / 72.0);
354
355 return wxRect(wxCoord(rPaper.left), wxCoord(rPaper.top),
356 wxCoord(rPaper.right - rPaper.left), wxCoord(rPaper.bottom - rPaper.top));
357 }
358
StartPage()359 void wxPrinterDCImpl::StartPage()
360 {
361 if ( !m_ok )
362 return ;
363
364 m_logicalFunction = wxCOPY;
365 // m_textAlignment = wxALIGN_TOP_LEFT;
366 m_backgroundMode = wxBRUSHSTYLE_TRANSPARENT;
367
368 m_textForegroundColour = *wxBLACK;
369 m_textBackgroundColour = *wxWHITE;
370 m_pen = *wxBLACK_PEN;
371 m_font = *wxNORMAL_FONT;
372 m_brush = *wxTRANSPARENT_BRUSH;
373 m_backgroundBrush = *wxWHITE_BRUSH;
374
375 m_nativePrinterDC->StartPage( (wxPrinterDC*) GetOwner() ) ;
376 m_ok = m_nativePrinterDC->IsOk() ;
377
378 }
379
EndPage()380 void wxPrinterDCImpl::EndPage()
381 {
382 if ( !m_ok )
383 return ;
384
385 m_nativePrinterDC->EndPage( (wxPrinterDC*) GetOwner() );
386 m_ok = m_nativePrinterDC->IsOk() ;
387 }
388
DoGetSize(int * width,int * height) const389 void wxPrinterDCImpl::DoGetSize(int *width, int *height) const
390 {
391 wxCHECK_RET( m_ok , wxT("GetSize() doesn't work without a valid wxPrinterDC") );
392 m_nativePrinterDC->GetSize(width, height ) ;
393 }
394
395 #endif
396