DRC | 2ff39b8 | 2011-07-28 08:38:59 +0000 | [diff] [blame] | 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. |
| 12 | // |
| 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. |
| 17 | // |
| 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. |
| 22 | // |
| 23 | // Please report all bugs and problems to: |
| 24 | // |
| 25 | // http://www.fltk.org/str.php |
| 26 | // |
| 27 | |
| 28 | #ifdef __APPLE__ |
| 29 | #include <FL/Fl_Printer.H> |
| 30 | |
| 31 | #include <FL/Fl.H> |
| 32 | #include <FL/fl_ask.H> |
| 33 | #include <FL/fl_draw.H> |
| 34 | #import <Cocoa/Cocoa.h> |
| 35 | |
| 36 | extern void fl_quartz_restore_line_style_(); |
| 37 | |
| 38 | Fl_System_Printer::Fl_System_Printer(void) |
| 39 | { |
| 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()); |
| 45 | } |
| 46 | |
| 47 | Fl_System_Printer::~Fl_System_Printer(void) {} |
| 48 | |
| 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 |
| 52 | { |
| 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; |
| 139 | } |
| 140 | |
| 141 | void Fl_System_Printer::margins(int *left, int *top, int *right, int *bottom) |
| 142 | { |
| 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 | } |
| 161 | } |
| 162 | |
| 163 | int Fl_System_Printer::printable_rect(int *w, int *h) |
| 164 | //returns 0 iff OK |
| 165 | { |
| 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; |
| 178 | } |
| 179 | |
| 180 | void Fl_System_Printer::origin(int x, int y) |
| 181 | { |
| 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); |
| 191 | } |
| 192 | |
| 193 | void Fl_System_Printer::scale (float s_x, float s_y) |
| 194 | { |
| 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); |
| 205 | } |
| 206 | |
| 207 | void Fl_System_Printer::rotate (float rot_angle) |
| 208 | { |
| 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); |
| 217 | } |
| 218 | |
| 219 | void Fl_System_Printer::translate(int x, int y) |
| 220 | { |
| 221 | CGContextSaveGState(fl_gc); |
| 222 | CGContextTranslateCTM(fl_gc, x, y ); |
| 223 | CGContextSaveGState(fl_gc); |
| 224 | } |
| 225 | |
| 226 | void Fl_System_Printer::untranslate(void) |
| 227 | { |
| 228 | CGContextRestoreGState(fl_gc); |
| 229 | CGContextRestoreGState(fl_gc); |
| 230 | } |
| 231 | |
| 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; |
| 249 | |
| 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; |
| 278 | } |
| 279 | |
| 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; |
| 288 | } |
| 289 | |
| 290 | void Fl_System_Printer::end_job (void) |
| 291 | { |
| 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(); |
| 302 | } |
| 303 | |
| 304 | #endif // __APPLE__ |
| 305 | |
| 306 | // |
| 307 | // End of "$Id: Fl_Quartz_Printer.mm 8467 2011-02-23 14:36:18Z manolo $". |
| 308 | // |