1/* 2 * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 27#import "java_awt_print_PageFormat.h" 28#import "java_awt_print_Pageable.h" 29#import "sun_lwawt_macosx_CPrinterJob.h" 30#import "sun_lwawt_macosx_CPrinterPageDialog.h" 31 32#import <Cocoa/Cocoa.h> 33 34#import "PrinterView.h" 35#import "PrintModel.h" 36#import "ThreadUtilities.h" 37#import "GeomUtilities.h" 38#import "JNIUtilities.h" 39 40static jclass sjc_Paper = NULL; 41static jclass sjc_PageFormat = NULL; 42static jclass sjc_CPrinterJob = NULL; 43static jclass sjc_CPrinterDialog = NULL; 44static jmethodID sjm_getNSPrintInfo = NULL; 45static jmethodID sjm_printerJob = NULL; 46 47#define GET_PAPER_CLASS() GET_CLASS(sjc_Paper, "java/awt/print/Paper"); 48#define GET_PAGEFORMAT_CLASS() GET_CLASS(sjc_PageFormat, "java/awt/print/PageFormat"); 49#define GET_CPRINTERDIALOG_CLASS() GET_CLASS(sjc_CPrinterDialog, "sun/lwawt/macosx/CPrinterDialog"); 50#define GET_CPRINTERDIALOG_CLASS_RETURN(ret) GET_CLASS_RETURN(sjc_CPrinterDialog, "sun/lwawt/macosx/CPrinterDialog", ret); 51#define GET_CPRINTERJOB_CLASS() GET_CLASS(sjc_CPrinterJob, "sun/lwawt/macosx/CPrinterJob"); 52#define GET_CPRINTERJOB_CLASS_RETURN(ret) GET_CLASS_RETURN(sjc_CPrinterJob, "sun/lwawt/macosx/CPrinterJob", ret); 53 54#define GET_NSPRINTINFO_METHOD_RETURN(ret) \ 55 GET_CPRINTERJOB_CLASS_RETURN(ret); \ 56 GET_METHOD_RETURN(sjm_getNSPrintInfo, sjc_CPrinterJob, "getNSPrintInfo", "()J", ret); 57 58#define GET_CPRINTERDIALOG_FIELD_RETURN(ret) \ 59 GET_CPRINTERDIALOG_CLASS_RETURN(ret); \ 60 GET_FIELD_RETURN(sjm_printerJob, sjc_CPrinterDialog, "fPrinterJob", "Lsun/lwawt/macosx/CPrinterJob;", ret); 61 62static NSPrintInfo* createDefaultNSPrintInfo(); 63 64static void makeBestFit(NSPrintInfo* src); 65 66static void nsPrintInfoToJavaPaper(JNIEnv* env, NSPrintInfo* src, jobject dst); 67static void javaPaperToNSPrintInfo(JNIEnv* env, jobject src, NSPrintInfo* dst); 68 69static void nsPrintInfoToJavaPageFormat(JNIEnv* env, NSPrintInfo* src, jobject dst); 70static void javaPageFormatToNSPrintInfo(JNIEnv* env, jobject srcPrinterJob, jobject srcPageFormat, NSPrintInfo* dst); 71 72static void nsPrintInfoToJavaPrinterJob(JNIEnv* env, NSPrintInfo* src, jobject dstPrinterJob, jobject dstPageable); 73static void javaPrinterJobToNSPrintInfo(JNIEnv* env, jobject srcPrinterJob, jobject srcPageable, NSPrintInfo* dst); 74 75 76#ifdef __MAC_10_9 // code for SDK 10.9 or newer 77#define NS_PORTRAIT NSPaperOrientationPortrait 78#define NS_LANDSCAPE NSPaperOrientationLandscape 79#else // code for SDK 10.8 or older 80#define NS_PORTRAIT NSPortraitOrientation 81#define NS_LANDSCAPE NSLandscapeOrientation 82#endif 83 84static NSPrintInfo* createDefaultNSPrintInfo(JNIEnv* env, jstring printer) 85{ 86 NSPrintInfo* defaultPrintInfo = [[NSPrintInfo sharedPrintInfo] copy]; 87 if (printer != NULL) 88 { 89 NSPrinter* nsPrinter = [NSPrinter printerWithName:JavaStringToNSString(env, printer)]; 90 if (nsPrinter != nil) 91 { 92 [defaultPrintInfo setPrinter:nsPrinter]; 93 } 94 } 95 [defaultPrintInfo setUpPrintOperationDefaultValues]; 96 97 // cmc 05/18/04 radr://3160443 : setUpPrintOperationDefaultValues sets the 98 // page margins to 72, 72, 90, 90 - need to use [NSPrintInfo imageablePageBounds] 99 // to get values from the printer. 100 // NOTE: currently [NSPrintInfo imageablePageBounds] does not update itself when 101 // the user selects a different printer - see radr://3657453. However, rather than 102 // directly querying the PPD here, we'll let AppKit printing do the work. The AppKit 103 // printing bug above is set to be fixed for Tiger. 104 NSRect imageableRect = [defaultPrintInfo imageablePageBounds]; 105 [defaultPrintInfo setLeftMargin: imageableRect.origin.x]; 106 [defaultPrintInfo setBottomMargin: imageableRect.origin.y]; //top and bottom are flipped because [NSPrintInfo imageablePageBounds] returns a flipped NSRect (bottom-left to top-right). 107 [defaultPrintInfo setRightMargin: [defaultPrintInfo paperSize].width-imageableRect.origin.x-imageableRect.size.width]; 108 [defaultPrintInfo setTopMargin: [defaultPrintInfo paperSize].height-imageableRect.origin.y-imageableRect.size.height]; 109 110 return defaultPrintInfo; 111} 112 113static void makeBestFit(NSPrintInfo* src) 114{ 115 // This will look at the NSPrintInfo's margins. If they are out of bounds to the 116 // imageable area of the page, it will set them to the largest possible size. 117 118 NSRect imageable = [src imageablePageBounds]; 119 120 NSSize paperSize = [src paperSize]; 121 122 CGFloat fullLeftM = imageable.origin.x; 123 CGFloat fullRightM = paperSize.width - (imageable.origin.x + imageable.size.width); 124 125 // These are flipped because [NSPrintInfo imageablePageBounds] returns a flipped 126 // NSRect (bottom-left to top-right). 127 CGFloat fullTopM = paperSize.height - (imageable.origin.y + imageable.size.height); 128 CGFloat fullBottomM = imageable.origin.y; 129 130 if (fullLeftM > [src leftMargin]) 131 { 132 [src setLeftMargin:fullLeftM]; 133 } 134 135 if (fullRightM > [src rightMargin]) 136 { 137 [src setRightMargin:fullRightM]; 138 } 139 140 if (fullTopM > [src topMargin]) 141 { 142 [src setTopMargin:fullTopM]; 143 } 144 145 if (fullBottomM > [src bottomMargin]) 146 { 147 [src setBottomMargin:fullBottomM]; 148 } 149} 150 151// In AppKit Printing, the rectangle is always oriented. In AppKit Printing, setting 152// the rectangle will always set the orientation. 153// In java printing, the rectangle is oriented if accessed from PageFormat. It is 154// not oriented when accessed from Paper. 155 156static void nsPrintInfoToJavaPaper(JNIEnv* env, NSPrintInfo* src, jobject dst) 157{ 158 GET_PAGEFORMAT_CLASS(); 159 GET_PAPER_CLASS(); 160 DECLARE_METHOD(jm_setSize, sjc_Paper, "setSize", "(DD)V"); 161 DECLARE_METHOD(jm_setImageableArea, sjc_Paper, "setImageableArea", "(DDDD)V"); 162 163 jdouble jPaperW, jPaperH; 164 165 // NSPrintInfo paperSize is oriented. java Paper is not oriented. Take 166 // the -[NSPrintInfo orientation] into account when setting the Paper 167 // rectangle. 168 169 NSSize paperSize = [src paperSize]; 170 switch ([src orientation]) { 171 case NS_PORTRAIT: 172 jPaperW = paperSize.width; 173 jPaperH = paperSize.height; 174 break; 175 176 case NS_LANDSCAPE: 177 jPaperW = paperSize.height; 178 jPaperH = paperSize.width; 179 break; 180 181 default: 182 jPaperW = paperSize.width; 183 jPaperH = paperSize.height; 184 break; 185 } 186 187 (*env)->CallVoidMethod(env, dst, jm_setSize, jPaperW, jPaperH); // AWT_THREADING Safe (known object - always actual Paper) 188 CHECK_EXCEPTION(); 189 190 // Set the imageable area from the margins 191 CGFloat leftM = [src leftMargin]; 192 CGFloat rightM = [src rightMargin]; 193 CGFloat topM = [src topMargin]; 194 CGFloat bottomM = [src bottomMargin]; 195 196 jdouble jImageX = leftM; 197 jdouble jImageY = topM; 198 jdouble jImageW = jPaperW - (leftM + rightM); 199 jdouble jImageH = jPaperH - (topM + bottomM); 200 201 (*env)->CallVoidMethod(env, dst, jm_setImageableArea, jImageX, jImageY, jImageW, jImageH); // AWT_THREADING Safe (known object - always actual Paper) 202 CHECK_EXCEPTION(); 203} 204 205static void javaPaperToNSPrintInfo(JNIEnv* env, jobject src, NSPrintInfo* dst) 206{ 207 AWT_ASSERT_NOT_APPKIT_THREAD; 208 209 GET_PAGEFORMAT_CLASS(); 210 GET_PAPER_CLASS(); 211 DECLARE_METHOD(jm_getWidth, sjc_Paper, "getWidth", "()D"); 212 DECLARE_METHOD(jm_getHeight, sjc_Paper, "getHeight", "()D"); 213 DECLARE_METHOD(jm_getImageableX, sjc_Paper, "getImageableX", "()D"); 214 DECLARE_METHOD(jm_getImageableY, sjc_Paper, "getImageableY", "()D"); 215 DECLARE_METHOD(jm_getImageableW, sjc_Paper, "getImageableWidth", "()D"); 216 DECLARE_METHOD(jm_getImageableH, sjc_Paper, "getImageableHeight", "()D"); 217 218 // java Paper is always Portrait oriented. Set NSPrintInfo with this 219 // rectangle, and it's orientation may change. If necessary, be sure to call 220 // -[NSPrintInfo setOrientation] after this call, which will then 221 // adjust the -[NSPrintInfo paperSize] as well. 222 223 jdouble jPhysicalWidth = (*env)->CallDoubleMethod(env, src, jm_getWidth); // AWT_THREADING Safe (!appKit) 224 CHECK_EXCEPTION(); 225 jdouble jPhysicalHeight = (*env)->CallDoubleMethod(env, src, jm_getHeight); // AWT_THREADING Safe (!appKit) 226 CHECK_EXCEPTION(); 227 228 [dst setPaperSize:NSMakeSize(jPhysicalWidth, jPhysicalHeight)]; 229 230 // Set the margins from the imageable area 231 jdouble jImageX = (*env)->CallDoubleMethod(env, src, jm_getImageableX); // AWT_THREADING Safe (!appKit) 232 CHECK_EXCEPTION(); 233 jdouble jImageY = (*env)->CallDoubleMethod(env, src, jm_getImageableY); // AWT_THREADING Safe (!appKit) 234 CHECK_EXCEPTION(); 235 jdouble jImageW = (*env)->CallDoubleMethod(env, src, jm_getImageableW); // AWT_THREADING Safe (!appKit) 236 CHECK_EXCEPTION(); 237 jdouble jImageH = (*env)->CallDoubleMethod(env, src, jm_getImageableH); // AWT_THREADING Safe (!appKit) 238 CHECK_EXCEPTION(); 239 240 [dst setLeftMargin:(CGFloat)jImageX]; 241 [dst setTopMargin:(CGFloat)jImageY]; 242 [dst setRightMargin:(CGFloat)(jPhysicalWidth - jImageW - jImageX)]; 243 [dst setBottomMargin:(CGFloat)(jPhysicalHeight - jImageH - jImageY)]; 244} 245 246static void nsPrintInfoToJavaPageFormat(JNIEnv* env, NSPrintInfo* src, jobject dst) 247{ 248 AWT_ASSERT_NOT_APPKIT_THREAD; 249 250 GET_CPRINTERJOB_CLASS(); 251 GET_PAGEFORMAT_CLASS(); 252 GET_PAPER_CLASS(); 253 DECLARE_METHOD(jm_setOrientation, sjc_PageFormat, "setOrientation", "(I)V"); 254 DECLARE_METHOD(jm_setPaper, sjc_PageFormat, "setPaper", "(Ljava/awt/print/Paper;)V"); 255 DECLARE_METHOD(jm_Paper_ctor, sjc_Paper, "<init>", "()V"); 256 257 jint jOrientation; 258 switch ([src orientation]) { 259 case NS_PORTRAIT: 260 jOrientation = java_awt_print_PageFormat_PORTRAIT; 261 break; 262 263 case NS_LANDSCAPE: 264 jOrientation = java_awt_print_PageFormat_LANDSCAPE; //+++gdb Are LANDSCAPE and REVERSE_LANDSCAPE still inverted? 265 break; 266 267/* 268 // AppKit printing doesn't support REVERSE_LANDSCAPE. Radar 2960295. 269 case NSReverseLandscapeOrientation: 270 jOrientation = java_awt_print_PageFormat.REVERSE_LANDSCAPE; //+++gdb Are LANDSCAPE and REVERSE_LANDSCAPE still inverted? 271 break; 272*/ 273 274 default: 275 jOrientation = java_awt_print_PageFormat_PORTRAIT; 276 break; 277 } 278 279 (*env)->CallVoidMethod(env, dst, jm_setOrientation, jOrientation); // AWT_THREADING Safe (!appKit) 280 CHECK_EXCEPTION(); 281 282 // Create a new Paper 283 jobject paper = (*env)->NewObject(env, sjc_Paper, jm_Paper_ctor); // AWT_THREADING Safe (known object) 284 CHECK_EXCEPTION(); 285 if (paper == NULL) { 286 return; 287 } 288 289 nsPrintInfoToJavaPaper(env, src, paper); 290 291 // Set the Paper in the PageFormat 292 (*env)->CallVoidMethod(env, dst, jm_setPaper, paper); // AWT_THREADING Safe (!appKit) 293 CHECK_EXCEPTION(); 294 295 (*env)->DeleteLocalRef(env, paper); 296} 297 298static void javaPageFormatToNSPrintInfo(JNIEnv* env, jobject srcPrintJob, jobject srcPageFormat, NSPrintInfo* dstPrintInfo) 299{ 300 AWT_ASSERT_NOT_APPKIT_THREAD; 301 302 GET_CPRINTERJOB_CLASS(); 303 GET_PAGEFORMAT_CLASS(); 304 GET_PAPER_CLASS(); 305 DECLARE_METHOD(jm_getOrientation, sjc_PageFormat, "getOrientation", "()I"); 306 DECLARE_METHOD(jm_getPaper, sjc_PageFormat, "getPaper", "()Ljava/awt/print/Paper;"); 307 DECLARE_METHOD(jm_getPrinterName, sjc_CPrinterJob, "getPrinterName", "()Ljava/lang/String;"); 308 309 // When setting page information (orientation, size) in NSPrintInfo, set the 310 // rectangle first. This is because setting the orientation will change the 311 // rectangle to match. 312 313 // Set up the paper. This will force Portrait since java Paper is 314 // not oriented. Then setting the NSPrintInfo orientation below 315 // will flip NSPrintInfo's info as necessary. 316 jobject paper = (*env)->CallObjectMethod(env, srcPageFormat, jm_getPaper); // AWT_THREADING Safe (!appKit) 317 CHECK_EXCEPTION(); 318 javaPaperToNSPrintInfo(env, paper, dstPrintInfo); 319 (*env)->DeleteLocalRef(env, paper); 320 321 switch ((*env)->CallIntMethod(env, srcPageFormat, jm_getOrientation)) { // AWT_THREADING Safe (!appKit) 322 case java_awt_print_PageFormat_PORTRAIT: 323 [dstPrintInfo setOrientation:NS_PORTRAIT]; 324 break; 325 326 case java_awt_print_PageFormat_LANDSCAPE: 327 [dstPrintInfo setOrientation:NS_LANDSCAPE]; //+++gdb Are LANDSCAPE and REVERSE_LANDSCAPE still inverted? 328 break; 329 330 // AppKit printing doesn't support REVERSE_LANDSCAPE. Radar 2960295. 331 case java_awt_print_PageFormat_REVERSE_LANDSCAPE: 332 [dstPrintInfo setOrientation:NS_LANDSCAPE]; //+++gdb Are LANDSCAPE and REVERSE_LANDSCAPE still inverted? 333 break; 334 335 default: 336 [dstPrintInfo setOrientation:NS_PORTRAIT]; 337 break; 338 } 339 CHECK_EXCEPTION(); 340 341 // <rdar://problem/4022422> NSPrinterInfo is not correctly set to the selected printer 342 // from the Java side of CPrinterJob. Has always assumed the default printer was the one we wanted. 343 if (srcPrintJob == NULL) return; 344 jobject printerNameObj = (*env)->CallObjectMethod(env, srcPrintJob, jm_getPrinterName); 345 CHECK_EXCEPTION(); 346 if (printerNameObj == NULL) return; 347 NSString *printerName = JavaStringToNSString(env, printerNameObj); 348 if (printerName == nil) return; 349 NSPrinter *printer = [NSPrinter printerWithName:printerName]; 350 if (printer == nil) return; 351 [dstPrintInfo setPrinter:printer]; 352} 353 354static void nsPrintInfoToJavaPrinterJob(JNIEnv* env, NSPrintInfo* src, jobject dstPrinterJob, jobject dstPageable) 355{ 356 GET_CPRINTERJOB_CLASS(); 357 DECLARE_METHOD(jm_setService, sjc_CPrinterJob, "setPrinterServiceFromNative", "(Ljava/lang/String;)V"); 358 DECLARE_METHOD(jm_setCopiesAttribute, sjc_CPrinterJob, "setCopiesAttribute", "(I)V"); 359 DECLARE_METHOD(jm_setCollated, sjc_CPrinterJob, "setCollated", "(Z)V"); 360 DECLARE_METHOD(jm_setPageRangeAttribute, sjc_CPrinterJob, "setPageRangeAttribute", "(IIZ)V"); 361 DECLARE_METHOD(jm_setPrintToFile, sjc_CPrinterJob, "setPrintToFile", "(Z)V"); 362 363 if (src.jobDisposition == NSPrintSaveJob) { 364 (*env)->CallVoidMethod(env, dstPrinterJob, jm_setPrintToFile, true); 365 CHECK_EXCEPTION(); 366 } else { 367 (*env)->CallVoidMethod(env, dstPrinterJob, jm_setPrintToFile, false); 368 CHECK_EXCEPTION(); 369 } 370 371 // get the selected printer's name, and set the appropriate PrintService on the Java side 372 NSString *name = [[src printer] name]; 373 jstring printerName = NSStringToJavaString(env, name); 374 (*env)->CallVoidMethod(env, dstPrinterJob, jm_setService, printerName); 375 CHECK_EXCEPTION(); 376 377 NSMutableDictionary* printingDictionary = [src dictionary]; 378 379 NSNumber* nsCopies = [printingDictionary objectForKey:NSPrintCopies]; 380 if ([nsCopies respondsToSelector:@selector(integerValue)]) 381 { 382 (*env)->CallVoidMethod(env, dstPrinterJob, jm_setCopiesAttribute, [nsCopies integerValue]); // AWT_THREADING Safe (known object) 383 CHECK_EXCEPTION(); 384 } 385 386 NSNumber* nsCollated = [printingDictionary objectForKey:NSPrintMustCollate]; 387 if ([nsCollated respondsToSelector:@selector(boolValue)]) 388 { 389 (*env)->CallVoidMethod(env, dstPrinterJob, jm_setCollated, [nsCollated boolValue] ? JNI_TRUE : JNI_FALSE); // AWT_THREADING Safe (known object) 390 CHECK_EXCEPTION(); 391 } 392 393 NSNumber* nsPrintAllPages = [printingDictionary objectForKey:NSPrintAllPages]; 394 if ([nsPrintAllPages respondsToSelector:@selector(boolValue)]) 395 { 396 jint jFirstPage = 0, jLastPage = java_awt_print_Pageable_UNKNOWN_NUMBER_OF_PAGES; 397 jboolean isRangeSet = false; 398 if (![nsPrintAllPages boolValue]) 399 { 400 NSNumber* nsFirstPage = [printingDictionary objectForKey:NSPrintFirstPage]; 401 if ([nsFirstPage respondsToSelector:@selector(integerValue)]) 402 { 403 jFirstPage = [nsFirstPage integerValue] - 1; 404 } 405 406 NSNumber* nsLastPage = [printingDictionary objectForKey:NSPrintLastPage]; 407 if ([nsLastPage respondsToSelector:@selector(integerValue)]) 408 { 409 jLastPage = [nsLastPage integerValue] - 1; 410 } 411 isRangeSet = true; 412 } 413 (*env)->CallVoidMethod(env, dstPrinterJob, jm_setPageRangeAttribute, 414 jFirstPage, jLastPage, isRangeSet); // AWT_THREADING Safe (known object) 415 CHECK_EXCEPTION(); 416 417 } 418} 419 420static void javaPrinterJobToNSPrintInfo(JNIEnv* env, jobject srcPrinterJob, jobject srcPageable, NSPrintInfo* dst) 421{ 422 AWT_ASSERT_NOT_APPKIT_THREAD; 423 424 DECLARE_CLASS(jc_Pageable, "java/awt/print/Pageable"); 425 DECLARE_METHOD(jm_getCopies, sjc_CPrinterJob, "getCopiesInt", "()I"); 426 DECLARE_METHOD(jm_isCollated, sjc_CPrinterJob, "isCollated", "()Z"); 427 DECLARE_METHOD(jm_getFromPage, sjc_CPrinterJob, "getFromPageAttrib", "()I"); 428 DECLARE_METHOD(jm_getToPage, sjc_CPrinterJob, "getToPageAttrib", "()I"); 429 DECLARE_METHOD(jm_getMinPage, sjc_CPrinterJob, "getMinPageAttrib", "()I"); 430 DECLARE_METHOD(jm_getMaxPage, sjc_CPrinterJob, "getMaxPageAttrib", "()I"); 431 DECLARE_METHOD(jm_getSelectAttrib, sjc_CPrinterJob, "getSelectAttrib", "()I"); 432 DECLARE_METHOD(jm_getNumberOfPages, jc_Pageable, "getNumberOfPages", "()I"); 433 DECLARE_METHOD(jm_getPageFormat, sjc_CPrinterJob, "getPageFormatFromAttributes", "()Ljava/awt/print/PageFormat;"); 434 435 NSMutableDictionary* printingDictionary = [dst dictionary]; 436 437 jint copies = (*env)->CallIntMethod(env, srcPrinterJob, jm_getCopies); // AWT_THREADING Safe (known object) 438 CHECK_EXCEPTION(); 439 [printingDictionary setObject:[NSNumber numberWithInteger:copies] forKey:NSPrintCopies]; 440 441 jboolean collated = (*env)->CallBooleanMethod(env, srcPrinterJob, jm_isCollated); // AWT_THREADING Safe (known object) 442 CHECK_EXCEPTION(); 443 [printingDictionary setObject:[NSNumber numberWithBool:collated ? YES : NO] forKey:NSPrintMustCollate]; 444 jint selectID = (*env)->CallIntMethod(env, srcPrinterJob, jm_getSelectAttrib); 445 CHECK_EXCEPTION(); 446 jint fromPage = (*env)->CallIntMethod(env, srcPrinterJob, jm_getFromPage); 447 CHECK_EXCEPTION(); 448 jint toPage = (*env)->CallIntMethod(env, srcPrinterJob, jm_getToPage); 449 CHECK_EXCEPTION(); 450 if (selectID ==0) { 451 [printingDictionary setObject:[NSNumber numberWithBool:YES] forKey:NSPrintAllPages]; 452 } else if (selectID == 2) { 453 // In Mac 10.7, Print ALL is deselected if PrintSelection is YES whether 454 // NSPrintAllPages is YES or NO 455 [printingDictionary setObject:[NSNumber numberWithBool:NO] forKey:NSPrintAllPages]; 456 [printingDictionary setObject:[NSNumber numberWithBool:YES] forKey:NSPrintSelectionOnly]; 457 } else { 458 jint minPage = (*env)->CallIntMethod(env, srcPrinterJob, jm_getMinPage); 459 CHECK_EXCEPTION(); 460 jint maxPage = (*env)->CallIntMethod(env, srcPrinterJob, jm_getMaxPage); 461 CHECK_EXCEPTION(); 462 463 // for PD_SELECTION or PD_NOSELECTION, check from/to page 464 // to determine which radio button to select 465 if (fromPage > minPage || toPage < maxPage) { 466 [printingDictionary setObject:[NSNumber numberWithBool:NO] forKey:NSPrintAllPages]; 467 } else { 468 [printingDictionary setObject:[NSNumber numberWithBool:YES] forKey:NSPrintAllPages]; 469 } 470 } 471 472 // setting fromPage and toPage will not be shown in the dialog if printing All pages 473 [printingDictionary setObject:[NSNumber numberWithInteger:fromPage] forKey:NSPrintFirstPage]; 474 [printingDictionary setObject:[NSNumber numberWithInteger:toPage] forKey:NSPrintLastPage]; 475 476 jobject page = (*env)->CallObjectMethod(env, srcPrinterJob, jm_getPageFormat); 477 CHECK_EXCEPTION(); 478 if (page != NULL) { 479 javaPageFormatToNSPrintInfo(env, NULL, page, dst); 480 } 481} 482 483/* 484 * Class: sun_lwawt_macosx_CPrinterJob 485 * Method: abortDoc 486 * Signature: ()V 487 */ 488JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPrinterJob_abortDoc 489 (JNIEnv *env, jobject jthis) 490{ 491JNI_COCOA_ENTER(env); 492 // This is only called during the printLoop from the printLoop thread 493 NSPrintOperation* printLoop = [NSPrintOperation currentOperation]; 494 NSPrintInfo* printInfo = [printLoop printInfo]; 495 [printInfo setJobDisposition:NSPrintCancelJob]; 496JNI_COCOA_EXIT(env); 497} 498 499/* 500 * Class: sun_lwawt_macosx_CPrinterJob 501 * Method: getDefaultPage 502 * Signature: (Ljava/awt/print/PageFormat;)V 503 */ 504JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPrinterJob_getDefaultPage 505 (JNIEnv *env, jobject jthis, jobject page) 506{ 507JNI_COCOA_ENTER(env); 508 NSPrintInfo* printInfo = createDefaultNSPrintInfo(env, NULL); 509 510 nsPrintInfoToJavaPageFormat(env, printInfo, page); 511 512 [printInfo release]; 513JNI_COCOA_EXIT(env); 514} 515 516/* 517 * Class: sun_lwawt_macosx_CPrinterJob 518 * Method: validatePaper 519 * Signature: (Ljava/awt/print/Paper;Ljava/awt/print/Paper;)V 520 */ 521JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPrinterJob_validatePaper 522 (JNIEnv *env, jobject jthis, jobject origpaper, jobject newpaper) 523{ 524JNI_COCOA_ENTER(env); 525 526 527 NSPrintInfo* printInfo = createDefaultNSPrintInfo(env, NULL); 528 javaPaperToNSPrintInfo(env, origpaper, printInfo); 529 makeBestFit(printInfo); 530 nsPrintInfoToJavaPaper(env, printInfo, newpaper); 531 [printInfo release]; 532 533JNI_COCOA_EXIT(env); 534} 535 536/* 537 * Class: sun_lwawt_macosx_CPrinterJob 538 * Method: createNSPrintInfo 539 * Signature: ()J 540 */ 541JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CPrinterJob_createNSPrintInfo 542 (JNIEnv *env, jobject jthis) 543{ 544 jlong result = -1; 545JNI_COCOA_ENTER(env); 546 // This is used to create the NSPrintInfo for this PrinterJob. Thread 547 // safety is assured by the java side of this call. 548 549 NSPrintInfo* printInfo = createDefaultNSPrintInfo(env, NULL); 550 551 result = ptr_to_jlong(printInfo); 552 553JNI_COCOA_EXIT(env); 554 return result; 555} 556 557/* 558 * Class: sun_lwawt_macosx_CPrinterJob 559 * Method: dispose 560 * Signature: (J)V 561 */ 562JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPrinterJob_dispose 563 (JNIEnv *env, jobject jthis, jlong nsPrintInfo) 564{ 565JNI_COCOA_ENTER(env); 566 if (nsPrintInfo != -1) 567 { 568 NSPrintInfo* printInfo = (NSPrintInfo*)jlong_to_ptr(nsPrintInfo); 569 [printInfo release]; 570 } 571JNI_COCOA_EXIT(env); 572} 573 574 575/* 576 * Class: sun_lwawt_macosx_CPrinterJob 577 * Method: printLoop 578 * Signature: ()V 579 */ 580JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_CPrinterJob_printLoop 581 (JNIEnv *env, jobject jthis, jboolean blocks, jint firstPage, jint lastPage) 582{ 583 AWT_ASSERT_NOT_APPKIT_THREAD; 584 585 GET_CPRINTERJOB_CLASS_RETURN(NO); 586 DECLARE_METHOD_RETURN(jm_getPageFormat, sjc_CPrinterJob, "getPageFormat", "(I)Ljava/awt/print/PageFormat;", NO); 587 DECLARE_METHOD_RETURN(jm_getPageFormatArea, sjc_CPrinterJob, "getPageFormatArea", "(Ljava/awt/print/PageFormat;)Ljava/awt/geom/Rectangle2D;", NO); 588 DECLARE_METHOD_RETURN(jm_getPrinterName, sjc_CPrinterJob, "getPrinterName", "()Ljava/lang/String;", NO); 589 DECLARE_METHOD_RETURN(jm_getPageable, sjc_CPrinterJob, "getPageable", "()Ljava/awt/print/Pageable;", NO); 590 591 jboolean retVal = JNI_FALSE; 592 593JNI_COCOA_ENTER(env); 594 // Get the first page's PageFormat for setting things up (This introduces 595 // and is a facet of the same problem in Radar 2818593/2708932). 596 jobject page = (*env)->CallObjectMethod(env, jthis, jm_getPageFormat, 0); // AWT_THREADING Safe (!appKit) 597 CHECK_EXCEPTION(); 598 if (page != NULL) { 599 jobject pageFormatArea = (*env)->CallObjectMethod(env, jthis, jm_getPageFormatArea, page); // AWT_THREADING Safe (!appKit) 600 CHECK_EXCEPTION(); 601 602 PrinterView* printerView = [[PrinterView alloc] initWithFrame:JavaToNSRect(env, pageFormatArea) withEnv:env withPrinterJob:jthis]; 603 [printerView setFirstPage:firstPage lastPage:lastPage]; 604 605 GET_NSPRINTINFO_METHOD_RETURN(NO) 606 NSPrintInfo* printInfo = (NSPrintInfo*)jlong_to_ptr((*env)->CallLongMethod(env, jthis, sjm_getNSPrintInfo)); // AWT_THREADING Safe (known object) 607 CHECK_EXCEPTION(); 608 609 // <rdar://problem/4156975> passing jthis CPrinterJob as well, so we can extract the printer name from the current job 610 javaPageFormatToNSPrintInfo(env, jthis, page, printInfo); 611 612 // <rdar://problem/4093799> NSPrinterInfo is not correctly set to the selected printer 613 // from the Java side of CPrinterJob. Had always assumed the default printer was the one we wanted. 614 jobject printerNameObj = (*env)->CallObjectMethod(env, jthis, jm_getPrinterName); 615 CHECK_EXCEPTION(); 616 if (printerNameObj != NULL) { 617 NSString *printerName = JavaStringToNSString(env, printerNameObj); 618 if (printerName != nil) { 619 NSPrinter *printer = [NSPrinter printerWithName:printerName]; 620 if (printer != nil) [printInfo setPrinter:printer]; 621 } 622 } 623 624 // <rdar://problem/4367998> JTable.print attributes are ignored 625 jobject pageable = (*env)->CallObjectMethod(env, jthis, jm_getPageable); // AWT_THREADING Safe (!appKit) 626 CHECK_EXCEPTION(); 627 javaPrinterJobToNSPrintInfo(env, jthis, pageable, printInfo); 628 629 PrintModel* printModel = [[PrintModel alloc] initWithPrintInfo:printInfo]; 630 631 (void)[printModel runPrintLoopWithView:printerView waitUntilDone:blocks withEnv:env]; 632 633 // Only set this if we got far enough to call runPrintLoopWithView, or we will spin CPrinterJob.print() forever! 634 retVal = JNI_TRUE; 635 636 [printModel release]; 637 [printerView release]; 638 639 if (page != NULL) 640 { 641 (*env)->DeleteLocalRef(env, page); 642 } 643 644 if (pageFormatArea != NULL) 645 { 646 (*env)->DeleteLocalRef(env, pageFormatArea); 647 } 648 } 649JNI_COCOA_EXIT(env); 650 return retVal; 651} 652 653/* 654 * Class: sun_lwawt_macosx_CPrinterPageDialog 655 * Method: showDialog 656 * Signature: ()Z 657 */ 658JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_CPrinterPageDialog_showDialog 659 (JNIEnv *env, jobject jthis) 660{ 661 662 DECLARE_CLASS_RETURN(jc_CPrinterPageDialog, "sun/lwawt/macosx/CPrinterPageDialog", NO); 663 DECLARE_FIELD_RETURN(jm_page, jc_CPrinterPageDialog, "fPage", "Ljava/awt/print/PageFormat;", NO); 664 665 jboolean result = JNI_FALSE; 666JNI_COCOA_ENTER(env); 667 GET_CPRINTERDIALOG_FIELD_RETURN(NO); 668 GET_NSPRINTINFO_METHOD_RETURN(NO) 669 jobject printerJob = (*env)->GetObjectField(env, jthis, sjm_printerJob); 670 if (printerJob == NULL) return NO; 671 NSPrintInfo* printInfo = (NSPrintInfo*)jlong_to_ptr((*env)->CallLongMethod(env, printerJob, sjm_getNSPrintInfo)); // AWT_THREADING Safe (known object) 672 CHECK_EXCEPTION(); 673 if (printInfo == NULL) return result; 674 675 jobject page = (*env)->GetObjectField(env, jthis, jm_page); 676 if (page == NULL) return NO; 677 678 // <rdar://problem/4156975> passing NULL, because only a CPrinterJob has a real printer associated with it 679 javaPageFormatToNSPrintInfo(env, NULL, page, printInfo); 680 681 PrintModel* printModel = [[PrintModel alloc] initWithPrintInfo:printInfo]; 682 result = [printModel runPageSetup]; 683 [printModel release]; 684 685 if (result) 686 { 687 nsPrintInfoToJavaPageFormat(env, printInfo, page); 688 } 689 690 if (printerJob != NULL) 691 { 692 (*env)->DeleteLocalRef(env, printerJob); 693 } 694 695 if (page != NULL) 696 { 697 (*env)->DeleteLocalRef(env, page); 698 } 699 700JNI_COCOA_EXIT(env); 701 return result; 702} 703 704/* 705 * Class: sun_lwawt_macosx_CPrinterJobDialog 706 * Method: showDialog 707 * Signature: ()Z 708 */ 709JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_CPrinterJobDialog_showDialog 710 (JNIEnv *env, jobject jthis) 711{ 712 DECLARE_CLASS_RETURN(jc_CPrinterJobDialog, "sun/lwawt/macosx/CPrinterJobDialog", NO); 713 DECLARE_FIELD_RETURN(jm_pageable, jc_CPrinterJobDialog, "fPageable", "Ljava/awt/print/Pageable;", NO); 714 715 jboolean result = JNI_FALSE; 716JNI_COCOA_ENTER(env); 717 GET_CPRINTERDIALOG_FIELD_RETURN(NO); 718 jobject printerJob = (*env)->GetObjectField(env, jthis, sjm_printerJob); 719 if (printerJob == NULL) return NO; 720 GET_NSPRINTINFO_METHOD_RETURN(NO) 721 NSPrintInfo* printInfo = (NSPrintInfo*)jlong_to_ptr((*env)->CallLongMethod(env, printerJob, sjm_getNSPrintInfo)); // AWT_THREADING Safe (known object) 722 723 jobject pageable = (*env)->GetObjectField(env, jthis, jm_pageable); 724 if (pageable == NULL) return NO; 725 726 javaPrinterJobToNSPrintInfo(env, printerJob, pageable, printInfo); 727 728 PrintModel* printModel = [[PrintModel alloc] initWithPrintInfo:printInfo]; 729 result = [printModel runJobSetup]; 730 [printModel release]; 731 732 if (result) 733 { 734 nsPrintInfoToJavaPrinterJob(env, printInfo, printerJob, pageable); 735 } 736 737 if (printerJob != NULL) 738 { 739 (*env)->DeleteLocalRef(env, printerJob); 740 } 741 742 if (pageable != NULL) 743 { 744 (*env)->DeleteLocalRef(env, pageable); 745 } 746 747JNI_COCOA_EXIT(env); 748 return result; 749} 750