themes: Workaround for bug where a background color of RGB 0,0,0 in Black color schem...
[ntk.git] / src / Fl_Quartz_Printer.mm
blob9aceec205996efa31e8e0ec5e58061a7d036159c
1 //
2 // "$Id: Fl_Quartz_Printer.mm 8467 2011-02-23 14:36:18Z manolo $"
3 //
4 // Mac OS X-specific printing support (objective-c++) for the Fast Light Tool Kit (FLTK).
5 //
6 // Copyright 2010 by Bill Spitzak and others.
7 //
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Library General Public
10 // License as published by the Free Software Foundation; either
11 // version 2 of the License, or (at your option) any later version.
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 // Library General Public License for more details.
18 // You should have received a copy of the GNU Library General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 // USA.
23 // Please report all bugs and problems to:
25 //     http://www.fltk.org/str.php
28 #ifdef __APPLE__
29 #include <FL/Fl_Printer.H>
31 #include <FL/Fl.H>
32 #include <FL/fl_ask.H>
33 #include <FL/fl_draw.H>
34 #import <Cocoa/Cocoa.h>
36 extern void fl_quartz_restore_line_style_();
38 Fl_System_Printer::Fl_System_Printer(void)
40   x_offset = 0;
41   y_offset = 0;
42   scale_x = scale_y = 1.;
43   gc = 0;
44   driver(Fl_Display_Device::display_device()->driver());
47 Fl_System_Printer::~Fl_System_Printer(void) {}
49 int Fl_System_Printer::start_job (int pagecount, int *frompage, int *topage)
50 //printing using a Quartz graphics context
51 //returns 0 iff OK
53   OSStatus status = 0;
54   Fl_X::q_release_context();
55 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
56   if( [NSPrintPanel instancesRespondToSelector:@selector(runModalWithPrintInfo:)] &&
57      [NSPrintInfo instancesRespondToSelector:@selector(PMPrintSession)] ) {
58     NSAutoreleasePool *localPool;
59     localPool = [[NSAutoreleasePool alloc] init]; 
60     NSPrintInfo *info = [NSPrintInfo sharedPrintInfo];
61     NSPageLayout *layout = [NSPageLayout pageLayout];
62     NSInteger retval = [layout runModal];
63     if(retval == NSOKButton) {
64       NSPrintPanel *panel = [NSPrintPanel printPanel];
65       retval = (NSInteger)[panel runModalWithPrintInfo:info];//from 10.5 only
66     }
67     if(retval != NSOKButton) {
68       Fl::first_window()->show();
69       [localPool release];
70       return 1;
71     }
72     printSession = (PMPrintSession)[info PMPrintSession];
73     pageFormat = (PMPageFormat)[info PMPageFormat];
74     printSettings = (PMPrintSettings)[info PMPrintSettings];
75     UInt32 from32, to32;
76     PMGetFirstPage(printSettings, &from32); 
77     if (frompage) *frompage = (int)from32;
78     PMGetLastPage(printSettings, &to32); 
79     if (topage) *topage = (int)to32;
80     if(topage && *topage > pagecount) *topage = pagecount;
81     status = PMSessionBeginCGDocumentNoDialog(printSession, printSettings, pageFormat);
82     [localPool release];
83   }
84   else {
85 #endif
86     
87 #if !__LP64__
88     Boolean accepted;
89     status = PMCreateSession(&printSession);
90     if (status != noErr) return 1;
91     status = PMCreatePageFormat(&pageFormat);
92     status = PMSessionDefaultPageFormat(printSession, pageFormat);
93     if (status != noErr) return 1;
94     // get pointer to the PMSessionPageSetupDialog Carbon function
95     typedef OSStatus (*dialog_f)(PMPrintSession, PMPageFormat, Boolean *);
96     static dialog_f f = NULL;
97     if (!f) f = (dialog_f)Fl_X::get_carbon_function("PMSessionPageSetupDialog");
98     status = (*f)(printSession, pageFormat, &accepted);
99     if (status != noErr || !accepted) {
100       Fl::first_window()->show();
101       return 1;
102     }
103     status = PMCreatePrintSettings(&printSettings);
104     if (status != noErr || printSettings == kPMNoPrintSettings) return 1;
105     status = PMSessionDefaultPrintSettings (printSession, printSettings);
106     if (status != noErr) return 1;
107     PMSetPageRange(printSettings, 1, (UInt32)kPMPrintAllPages);
108     // get pointer to the PMSessionPrintDialog Carbon function
109     typedef OSStatus (*dialog_f2)(PMPrintSession, PMPrintSettings, PMPageFormat, Boolean *);
110     static dialog_f2 f2 = NULL;
111     if (!f2) f2 = (dialog_f2)Fl_X::get_carbon_function("PMSessionPrintDialog");
112     status = (*f2)(printSession, printSettings, pageFormat, &accepted);
113     if (!accepted) status = kPMCancel;
114     if (status != noErr) {
115       Fl::first_window()->show();
116       return 1;
117     }
118     UInt32 from32, to32;
119     PMGetFirstPage(printSettings, &from32); 
120     if (frompage) *frompage = (int)from32;
121     PMGetLastPage(printSettings, &to32); 
122     if (topage) *topage = (int)to32;
123     if(topage && *topage > pagecount) *topage = pagecount;
124     CFStringRef mystring[1];
125     mystring[0] = kPMGraphicsContextCoreGraphics;
126     CFArrayRef array = CFArrayCreate(NULL, (const void **)mystring, 1, &kCFTypeArrayCallBacks);
127     status = PMSessionSetDocumentFormatGeneration(printSession, kPMDocumentFormatDefault, array, NULL);
128     CFRelease(array);
129     status = PMSessionBeginDocumentNoDialog(printSession, printSettings, pageFormat);
130 #endif //__LP64__
131     
132 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
133   }
134 #endif
135   if (status != noErr) return 1;
136   y_offset = x_offset = 0;
137   this->set_current();
138   return 0;
141 void Fl_System_Printer::margins(int *left, int *top, int *right, int *bottom)
143   PMPaper paper;
144   PMGetPageFormatPaper(pageFormat, &paper);
145   PMOrientation orientation;
146   PMGetOrientation(pageFormat, &orientation);
147   PMPaperMargins margins;
148   PMPaperGetMargins(paper, &margins);
149   if(orientation == kPMPortrait) {
150     if (left) *left = (int)(margins.left / scale_x + 0.5);
151     if (top) *top = (int)(margins.top / scale_y + 0.5);
152     if (right) *right = (int)(margins.right / scale_x + 0.5);
153     if (bottom) *bottom = (int)(margins.bottom / scale_y + 0.5);
154     }
155   else {
156     if (left) *left = (int)(margins.top / scale_x + 0.5);
157     if (top) *top = (int)(margins.left / scale_y + 0.5);
158     if (right) *right = (int)(margins.bottom / scale_x + 0.5);
159     if (bottom) *bottom = (int)(margins.right / scale_y + 0.5);
160   }
163 int Fl_System_Printer::printable_rect(int *w, int *h)
164 //returns 0 iff OK
166   OSStatus status;
167   PMRect pmRect;
168   int x, y;
169   
170   status = PMGetAdjustedPageRect(pageFormat, &pmRect);
171   if (status != noErr) return 1;
172   
173   x = (int)pmRect.left;
174   y = (int)pmRect.top;
175   *w = int((int)(pmRect.right - x) / scale_x + 1);
176   *h = int((int)(pmRect.bottom - y) / scale_y + 1);
177   return 0;
180 void Fl_System_Printer::origin(int x, int y)
182   x_offset = x;
183   y_offset = y;
184   CGContextRestoreGState(fl_gc);
185   CGContextRestoreGState(fl_gc);
186   CGContextSaveGState(fl_gc);
187   CGContextScaleCTM(fl_gc, scale_x, scale_y);
188   CGContextTranslateCTM(fl_gc, x, y);
189   CGContextRotateCTM(fl_gc, angle);
190   CGContextSaveGState(fl_gc);
193 void Fl_System_Printer::scale (float s_x, float s_y)
195   if (s_y == 0.) s_y = s_x;
196   scale_x = s_x;
197   scale_y = s_y;
198   CGContextRestoreGState(fl_gc);
199   CGContextRestoreGState(fl_gc);
200   CGContextSaveGState(fl_gc);
201   CGContextScaleCTM(fl_gc, scale_x, scale_y);
202   CGContextRotateCTM(fl_gc, angle);
203   x_offset = y_offset = 0;
204   CGContextSaveGState(fl_gc);
207 void Fl_System_Printer::rotate (float rot_angle)
209   angle = - rot_angle * M_PI / 180.;
210   CGContextRestoreGState(fl_gc);
211   CGContextRestoreGState(fl_gc);
212   CGContextSaveGState(fl_gc);
213   CGContextScaleCTM(fl_gc, scale_x, scale_y);
214   CGContextTranslateCTM(fl_gc, x_offset, y_offset);
215   CGContextRotateCTM(fl_gc, angle);
216   CGContextSaveGState(fl_gc);
219 void Fl_System_Printer::translate(int x, int y)
221   CGContextSaveGState(fl_gc);
222   CGContextTranslateCTM(fl_gc, x, y );
223   CGContextSaveGState(fl_gc);
226 void Fl_System_Printer::untranslate(void)
228   CGContextRestoreGState(fl_gc);
229   CGContextRestoreGState(fl_gc);
232 int Fl_System_Printer::start_page (void)
233 {       
234   OSStatus status = PMSessionBeginPageNoDialog(printSession, pageFormat, NULL);
235 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
236   if ( PMSessionGetCGGraphicsContext != NULL ) {
237     status = PMSessionGetCGGraphicsContext(printSession, &fl_gc);
238   }
239   else {
240 #endif
241 #if ! __LP64__
242     status = PMSessionGetGraphicsContext(printSession,NULL,(void **)&fl_gc);
243 #endif
244 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
245   }
246 #endif
247   PMRect pmRect;
248   float win_scale_x, win_scale_y;
250   PMPaper paper;
251   PMGetPageFormatPaper(pageFormat, &paper);
252   PMPaperMargins margins;
253   PMPaperGetMargins(paper, &margins);
254   PMOrientation orientation;
255   PMGetOrientation(pageFormat, &orientation);
256   
257   status = PMGetAdjustedPageRect(pageFormat, &pmRect);
258   double h = pmRect.bottom - pmRect.top;
259   x_offset = 0;
260   y_offset = 0; 
261   angle = 0;
262   scale_x = scale_y = 1;
263   win_scale_x = win_scale_y = 1;
264   if(orientation == kPMPortrait)
265     CGContextTranslateCTM(fl_gc, margins.left, margins.bottom + h);
266   else
267     CGContextTranslateCTM(fl_gc, margins.top, margins.right + h);
268   CGContextScaleCTM(fl_gc, win_scale_x, - win_scale_y);
269   fl_quartz_restore_line_style_();
270   CGContextSetShouldAntialias(fl_gc, false);
271   CGContextSaveGState(fl_gc);
272   CGContextSaveGState(fl_gc);
273   fl_line_style(FL_SOLID);
274   fl_window = (void *)1; // TODO: something better
275   fl_clip_region(0);
276   if( status == noErr) gc = fl_gc;
277   return status != noErr;
280 int Fl_System_Printer::end_page (void)
281 {       
282   CGContextFlush(fl_gc);
283   CGContextRestoreGState(fl_gc);
284   CGContextRestoreGState(fl_gc);
285   OSStatus status = PMSessionEndPageNoDialog(printSession);
286   gc = NULL;
287   return status != noErr;
290 void Fl_System_Printer::end_job (void)
292   OSStatus status;
293   
294   status = PMSessionError(printSession);
295   if (status != noErr) {
296     fl_alert ("PM Session error %d", (int)status);
297   }
298   PMSessionEndDocumentNoDialog(printSession);
299   Fl_Display_Device::display_device()->set_current();
300   fl_gc = 0;
301   Fl::first_window()->show();
304 #endif // __APPLE__
307 // End of "$Id: Fl_Quartz_Printer.mm 8467 2011-02-23 14:36:18Z manolo $".