2 // "$Id: Fl_Quartz_Printer.mm 8467 2011-02-23 14:36:18Z manolo $"
4 // Mac OS X-specific printing support (objective-c++) for the Fast Light Tool Kit (FLTK).
6 // Copyright 2010 by Bill Spitzak and others.
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
23 // Please report all bugs and problems to:
25 // http://www.fltk.org/str.php
29 #include <FL/Fl_Printer.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)
42 scale_x = scale_y = 1.;
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
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
67 if(retval != NSOKButton) {
68 Fl::first_window()->show();
72 printSession = (PMPrintSession)[info PMPrintSession];
73 pageFormat = (PMPageFormat)[info PMPageFormat];
74 printSettings = (PMPrintSettings)[info PMPrintSettings];
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);
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();
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();
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);
129 status = PMSessionBeginDocumentNoDialog(printSession, printSettings, pageFormat);
132 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
135 if (status != noErr) return 1;
136 y_offset = x_offset = 0;
141 void Fl_System_Printer::margins(int *left, int *top, int *right, int *bottom)
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);
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);
163 int Fl_System_Printer::printable_rect(int *w, int *h)
170 status = PMGetAdjustedPageRect(pageFormat, &pmRect);
171 if (status != noErr) return 1;
173 x = (int)pmRect.left;
175 *w = int((int)(pmRect.right - x) / scale_x + 1);
176 *h = int((int)(pmRect.bottom - y) / scale_y + 1);
180 void Fl_System_Printer::origin(int x, int 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;
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)
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);
242 status = PMSessionGetGraphicsContext(printSession,NULL,(void **)&fl_gc);
244 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
248 float win_scale_x, win_scale_y;
251 PMGetPageFormatPaper(pageFormat, &paper);
252 PMPaperMargins margins;
253 PMPaperGetMargins(paper, &margins);
254 PMOrientation orientation;
255 PMGetOrientation(pageFormat, &orientation);
257 status = PMGetAdjustedPageRect(pageFormat, &pmRect);
258 double h = pmRect.bottom - pmRect.top;
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);
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
276 if( status == noErr) gc = fl_gc;
277 return status != noErr;
280 int Fl_System_Printer::end_page (void)
282 CGContextFlush(fl_gc);
283 CGContextRestoreGState(fl_gc);
284 CGContextRestoreGState(fl_gc);
285 OSStatus status = PMSessionEndPageNoDialog(printSession);
287 return status != noErr;
290 void Fl_System_Printer::end_job (void)
294 status = PMSessionError(printSession);
295 if (status != noErr) {
296 fl_alert ("PM Session error %d", (int)status);
298 PMSessionEndDocumentNoDialog(printSession);
299 Fl_Display_Device::display_device()->set_current();
301 Fl::first_window()->show();
307 // End of "$Id: Fl_Quartz_Printer.mm 8467 2011-02-23 14:36:18Z manolo $".