1 /* 2 * Copyright (c) 2011, 2020, 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 40 static jclass sjc_Paper = NULL; 41 static jclass sjc_PageFormat = NULL; 42 static jclass sjc_CPrinterJob = NULL; 43 static jclass sjc_CPrinterDialog = NULL; 44 static jmethodID sjm_getNSPrintInfo = NULL; 45 static 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 62 static NSPrintInfo* createDefaultNSPrintInfo(); 63 64 static void makeBestFit(NSPrintInfo* src); 65 66 static void nsPrintInfoToJavaPaper(JNIEnv* env, NSPrintInfo* src, jobject dst); 67 static void javaPaperToNSPrintInfo(JNIEnv* env, jobject src, NSPrintInfo* dst); 68 69 static void nsPrintInfoToJavaPageFormat(JNIEnv* env, NSPrintInfo* src, jobject dst); 70 static void javaPageFormatToNSPrintInfo(JNIEnv* env, jobject srcPrinterJob, jobject srcPageFormat, NSPrintInfo* dst); 71 72 static void nsPrintInfoToJavaPrinterJob(JNIEnv* env, NSPrintInfo* src, jobject dstPrinterJob, jobject dstPageable); 73 static 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 84 static 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 113 static 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 156 static 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 205 static 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 246 static 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 298 static 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 354 static 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 362 // get the selected printer's name, and set the appropriate PrintService on the Java side 363 NSString *name = [[src printer] name]; 364 jstring printerName = NSStringToJavaString(env, name); 365 (*env)->CallVoidMethod(env, dstPrinterJob, jm_setService, printerName); 366 CHECK_EXCEPTION(); 367 368 NSMutableDictionary* printingDictionary = [src dictionary]; 369 370 NSNumber* nsCopies = [printingDictionary objectForKey:NSPrintCopies]; 371 if ([nsCopies respondsToSelector:@selector(integerValue)]) 372 { 373 (*env)->CallVoidMethod(env, dstPrinterJob, jm_setCopiesAttribute, [nsCopies integerValue]); // AWT_THREADING Safe (known object) 374 CHECK_EXCEPTION(); 375 } 376 377 NSNumber* nsCollated = [printingDictionary objectForKey:NSPrintMustCollate]; 378 if ([nsCollated respondsToSelector:@selector(boolValue)]) 379 { 380 (*env)->CallVoidMethod(env, dstPrinterJob, jm_setCollated, [nsCollated boolValue] ? JNI_TRUE : JNI_FALSE); // AWT_THREADING Safe (known object) 381 CHECK_EXCEPTION(); 382 } 383 384 NSNumber* nsPrintAllPages = [printingDictionary objectForKey:NSPrintAllPages]; 385 if ([nsPrintAllPages respondsToSelector:@selector(boolValue)]) 386 { 387 jint jFirstPage = 0, jLastPage = java_awt_print_Pageable_UNKNOWN_NUMBER_OF_PAGES; 388 jboolean isRangeSet = false; 389 if (![nsPrintAllPages boolValue]) 390 { 391 NSNumber* nsFirstPage = [printingDictionary objectForKey:NSPrintFirstPage]; 392 if ([nsFirstPage respondsToSelector:@selector(integerValue)]) 393 { 394 jFirstPage = [nsFirstPage integerValue] - 1; 395 } 396 397 NSNumber* nsLastPage = [printingDictionary objectForKey:NSPrintLastPage]; 398 if ([nsLastPage respondsToSelector:@selector(integerValue)]) 399 { 400 jLastPage = [nsLastPage integerValue] - 1; 401 } 402 isRangeSet = true; 403 } 404 (*env)->CallVoidMethod(env, dstPrinterJob, jm_setPageRangeAttribute, 405 jFirstPage, jLastPage, isRangeSet); // AWT_THREADING Safe (known object) 406 CHECK_EXCEPTION(); 407 408 } 409 } 410 411 static void javaPrinterJobToNSPrintInfo(JNIEnv* env, jobject srcPrinterJob, jobject srcPageable, NSPrintInfo* dst) 412 { 413 AWT_ASSERT_NOT_APPKIT_THREAD; 414 415 DECLARE_CLASS(jc_Pageable, "java/awt/print/Pageable"); 416 DECLARE_METHOD(jm_getCopies, sjc_CPrinterJob, "getCopiesInt", "()I"); 417 DECLARE_METHOD(jm_isCollated, sjc_CPrinterJob, "isCollated", "()Z"); 418 DECLARE_METHOD(jm_getFromPage, sjc_CPrinterJob, "getFromPageAttrib", "()I"); 419 DECLARE_METHOD(jm_getToPage, sjc_CPrinterJob, "getToPageAttrib", "()I"); 420 DECLARE_METHOD(jm_getMinPage, sjc_CPrinterJob, "getMinPageAttrib", "()I"); 421 DECLARE_METHOD(jm_getMaxPage, sjc_CPrinterJob, "getMaxPageAttrib", "()I"); 422 DECLARE_METHOD(jm_getSelectAttrib, sjc_CPrinterJob, "getSelectAttrib", "()I"); 423 DECLARE_METHOD(jm_getNumberOfPages, jc_Pageable, "getNumberOfPages", "()I"); 424 DECLARE_METHOD(jm_getPageFormat, sjc_CPrinterJob, "getPageFormatFromAttributes", "()Ljava/awt/print/PageFormat;"); 425 426 NSMutableDictionary* printingDictionary = [dst dictionary]; 427 428 jint copies = (*env)->CallIntMethod(env, srcPrinterJob, jm_getCopies); // AWT_THREADING Safe (known object) 429 CHECK_EXCEPTION(); 430 [printingDictionary setObject:[NSNumber numberWithInteger:copies] forKey:NSPrintCopies]; 431 432 jboolean collated = (*env)->CallBooleanMethod(env, srcPrinterJob, jm_isCollated); // AWT_THREADING Safe (known object) 433 CHECK_EXCEPTION(); 434 [printingDictionary setObject:[NSNumber numberWithBool:collated ? YES : NO] forKey:NSPrintMustCollate]; 435 jint selectID = (*env)->CallIntMethod(env, srcPrinterJob, jm_getSelectAttrib); 436 CHECK_EXCEPTION(); 437 jint fromPage = (*env)->CallIntMethod(env, srcPrinterJob, jm_getFromPage); 438 CHECK_EXCEPTION(); 439 jint toPage = (*env)->CallIntMethod(env, srcPrinterJob, jm_getToPage); 440 CHECK_EXCEPTION(); 441 if (selectID ==0) { 442 [printingDictionary setObject:[NSNumber numberWithBool:YES] forKey:NSPrintAllPages]; 443 } else if (selectID == 2) { 444 // In Mac 10.7, Print ALL is deselected if PrintSelection is YES whether 445 // NSPrintAllPages is YES or NO 446 [printingDictionary setObject:[NSNumber numberWithBool:NO] forKey:NSPrintAllPages]; 447 [printingDictionary setObject:[NSNumber numberWithBool:YES] forKey:NSPrintSelectionOnly]; 448 } else { 449 jint minPage = (*env)->CallIntMethod(env, srcPrinterJob, jm_getMinPage); 450 CHECK_EXCEPTION(); 451 jint maxPage = (*env)->CallIntMethod(env, srcPrinterJob, jm_getMaxPage); 452 CHECK_EXCEPTION(); 453 454 // for PD_SELECTION or PD_NOSELECTION, check from/to page 455 // to determine which radio button to select 456 if (fromPage > minPage || toPage < maxPage) { 457 [printingDictionary setObject:[NSNumber numberWithBool:NO] forKey:NSPrintAllPages]; 458 } else { 459 [printingDictionary setObject:[NSNumber numberWithBool:YES] forKey:NSPrintAllPages]; 460 } 461 } 462 463 // setting fromPage and toPage will not be shown in the dialog if printing All pages 464 [printingDictionary setObject:[NSNumber numberWithInteger:fromPage] forKey:NSPrintFirstPage]; 465 [printingDictionary setObject:[NSNumber numberWithInteger:toPage] forKey:NSPrintLastPage]; 466 467 jobject page = (*env)->CallObjectMethod(env, srcPrinterJob, jm_getPageFormat); 468 CHECK_EXCEPTION(); 469 if (page != NULL) { 470 javaPageFormatToNSPrintInfo(env, NULL, page, dst); 471 } 472 } 473 474 /* 475 * Class: sun_lwawt_macosx_CPrinterJob 476 * Method: abortDoc 477 * Signature: ()V 478 */ 479 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPrinterJob_abortDoc 480 (JNIEnv *env, jobject jthis) 481 { 482 JNI_COCOA_ENTER(env); 483 // This is only called during the printLoop from the printLoop thread 484 NSPrintOperation* printLoop = [NSPrintOperation currentOperation]; 485 NSPrintInfo* printInfo = [printLoop printInfo]; 486 [printInfo setJobDisposition:NSPrintCancelJob]; 487 JNI_COCOA_EXIT(env); 488 } 489 490 /* 491 * Class: sun_lwawt_macosx_CPrinterJob 492 * Method: getDefaultPage 493 * Signature: (Ljava/awt/print/PageFormat;)V 494 */ 495 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPrinterJob_getDefaultPage 496 (JNIEnv *env, jobject jthis, jobject page) 497 { 498 JNI_COCOA_ENTER(env); 499 NSPrintInfo* printInfo = createDefaultNSPrintInfo(env, NULL); 500 501 nsPrintInfoToJavaPageFormat(env, printInfo, page); 502 503 [printInfo release]; 504 JNI_COCOA_EXIT(env); 505 } 506 507 /* 508 * Class: sun_lwawt_macosx_CPrinterJob 509 * Method: validatePaper 510 * Signature: (Ljava/awt/print/Paper;Ljava/awt/print/Paper;)V 511 */ 512 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPrinterJob_validatePaper 513 (JNIEnv *env, jobject jthis, jobject origpaper, jobject newpaper) 514 { 515 JNI_COCOA_ENTER(env); 516 517 518 NSPrintInfo* printInfo = createDefaultNSPrintInfo(env, NULL); 519 javaPaperToNSPrintInfo(env, origpaper, printInfo); 520 makeBestFit(printInfo); 521 nsPrintInfoToJavaPaper(env, printInfo, newpaper); 522 [printInfo release]; 523 524 JNI_COCOA_EXIT(env); 525 } 526 527 /* 528 * Class: sun_lwawt_macosx_CPrinterJob 529 * Method: createNSPrintInfo 530 * Signature: ()J 531 */ 532 JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CPrinterJob_createNSPrintInfo 533 (JNIEnv *env, jobject jthis) 534 { 535 jlong result = -1; 536 JNI_COCOA_ENTER(env); 537 // This is used to create the NSPrintInfo for this PrinterJob. Thread 538 // safety is assured by the java side of this call. 539 540 NSPrintInfo* printInfo = createDefaultNSPrintInfo(env, NULL); 541 542 result = ptr_to_jlong(printInfo); 543 544 JNI_COCOA_EXIT(env); 545 return result; 546 } 547 548 /* 549 * Class: sun_lwawt_macosx_CPrinterJob 550 * Method: dispose 551 * Signature: (J)V 552 */ 553 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPrinterJob_dispose 554 (JNIEnv *env, jobject jthis, jlong nsPrintInfo) 555 { 556 JNI_COCOA_ENTER(env); 557 if (nsPrintInfo != -1) 558 { 559 NSPrintInfo* printInfo = (NSPrintInfo*)jlong_to_ptr(nsPrintInfo); 560 [printInfo release]; 561 } 562 JNI_COCOA_EXIT(env); 563 } 564 565 566 /* 567 * Class: sun_lwawt_macosx_CPrinterJob 568 * Method: printLoop 569 * Signature: ()V 570 */ 571 JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_CPrinterJob_printLoop 572 (JNIEnv *env, jobject jthis, jboolean blocks, jint firstPage, jint lastPage) 573 { 574 AWT_ASSERT_NOT_APPKIT_THREAD; 575 576 GET_CPRINTERJOB_CLASS_RETURN(NO); 577 DECLARE_METHOD_RETURN(jm_getPageFormat, sjc_CPrinterJob, "getPageFormat", "(I)Ljava/awt/print/PageFormat;", NO); 578 DECLARE_METHOD_RETURN(jm_getPageFormatArea, sjc_CPrinterJob, "getPageFormatArea", "(Ljava/awt/print/PageFormat;)Ljava/awt/geom/Rectangle2D;", NO); 579 DECLARE_METHOD_RETURN(jm_getPrinterName, sjc_CPrinterJob, "getPrinterName", "()Ljava/lang/String;", NO); 580 DECLARE_METHOD_RETURN(jm_getPageable, sjc_CPrinterJob, "getPageable", "()Ljava/awt/print/Pageable;", NO); 581 DECLARE_METHOD_RETURN(jm_getPrinterTray, sjc_CPrinterJob, "getPrinterTray", "()Ljava/lang/String;", NO); 582 583 jboolean retVal = JNI_FALSE; 584 585 JNI_COCOA_ENTER(env); 586 // Get the first page's PageFormat for setting things up (This introduces 587 // and is a facet of the same problem in Radar 2818593/2708932). 588 jobject page = (*env)->CallObjectMethod(env, jthis, jm_getPageFormat, 0); // AWT_THREADING Safe (!appKit) 589 CHECK_EXCEPTION(); 590 if (page != NULL) { 591 jobject pageFormatArea = (*env)->CallObjectMethod(env, jthis, jm_getPageFormatArea, page); // AWT_THREADING Safe (!appKit) 592 CHECK_EXCEPTION(); 593 594 PrinterView* printerView = [[PrinterView alloc] initWithFrame:JavaToNSRect(env, pageFormatArea) withEnv:env withPrinterJob:jthis]; 595 [printerView setFirstPage:firstPage lastPage:lastPage]; 596 597 GET_NSPRINTINFO_METHOD_RETURN(NO) 598 NSPrintInfo* printInfo = (NSPrintInfo*)jlong_to_ptr((*env)->CallLongMethod(env, jthis, sjm_getNSPrintInfo)); // AWT_THREADING Safe (known object) 599 CHECK_EXCEPTION(); 600 jobject printerTrayObj = (*env)->CallObjectMethod(env, jthis, jm_getPrinterTray); 601 CHECK_EXCEPTION(); 602 if (printerTrayObj != NULL) { 603 NSString *printerTray = JavaStringToNSString(env, printerTrayObj); 604 if (printerTray != nil) { 605 [[printInfo printSettings] setObject:printerTray forKey:@"InputSlot"]; 606 } 607 } 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 } 649 JNI_COCOA_EXIT(env); 650 return retVal; 651 } 652 653 /* 654 * Class: sun_lwawt_macosx_CPrinterPageDialog 655 * Method: showDialog 656 * Signature: ()Z 657 */ 658 JNIEXPORT 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; 666 JNI_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 700 JNI_COCOA_EXIT(env); 701 return result; 702 } 703 704 /* 705 * Class: sun_lwawt_macosx_CPrinterJobDialog 706 * Method: showDialog 707 * Signature: ()Z 708 */ 709 JNIEXPORT 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; 716 JNI_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 747 JNI_COCOA_EXIT(env); 748 return result; 749 }