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