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