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