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 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 } else { 366 (*env)->CallVoidMethod(env, dstPrinterJob, jm_setPrintToFile, false); 367 } 368 369 // get the selected printer's name, and set the appropriate PrintService on the Java side 370 NSString *name = [[src printer] name]; 371 jstring printerName = NSStringToJavaString(env, name); 372 (*env)->CallVoidMethod(env, dstPrinterJob, jm_setService, printerName); 373 CHECK_EXCEPTION(); 374 375 NSMutableDictionary* printingDictionary = [src dictionary]; 376 377 NSNumber* nsCopies = [printingDictionary objectForKey:NSPrintCopies]; 378 if ([nsCopies respondsToSelector:@selector(integerValue)]) 379 { 380 (*env)->CallVoidMethod(env, dstPrinterJob, jm_setCopiesAttribute, [nsCopies integerValue]); // AWT_THREADING Safe (known object) 381 CHECK_EXCEPTION(); 382 } 383 384 NSNumber* nsCollated = [printingDictionary objectForKey:NSPrintMustCollate]; 385 if ([nsCollated respondsToSelector:@selector(boolValue)]) 386 { 387 (*env)->CallVoidMethod(env, dstPrinterJob, jm_setCollated, [nsCollated boolValue] ? JNI_TRUE : JNI_FALSE); // AWT_THREADING Safe (known object) 388 CHECK_EXCEPTION(); 389 } 390 391 NSNumber* nsPrintAllPages = [printingDictionary objectForKey:NSPrintAllPages]; 392 if ([nsPrintAllPages respondsToSelector:@selector(boolValue)]) 393 { 394 jint jFirstPage = 0, jLastPage = java_awt_print_Pageable_UNKNOWN_NUMBER_OF_PAGES; 395 jboolean isRangeSet = false; 396 if (![nsPrintAllPages boolValue]) 397 { 398 NSNumber* nsFirstPage = [printingDictionary objectForKey:NSPrintFirstPage]; 399 if ([nsFirstPage respondsToSelector:@selector(integerValue)]) 400 { 401 jFirstPage = [nsFirstPage integerValue] - 1; 402 } 403 404 NSNumber* nsLastPage = [printingDictionary objectForKey:NSPrintLastPage]; 405 if ([nsLastPage respondsToSelector:@selector(integerValue)]) 406 { 407 jLastPage = [nsLastPage integerValue] - 1; 408 } 409 isRangeSet = true; 410 } 411 (*env)->CallVoidMethod(env, dstPrinterJob, jm_setPageRangeAttribute, 412 jFirstPage, jLastPage, isRangeSet); // AWT_THREADING Safe (known object) 413 CHECK_EXCEPTION(); 414 415 } 416} 417 418static void javaPrinterJobToNSPrintInfo(JNIEnv* env, jobject srcPrinterJob, jobject srcPageable, NSPrintInfo* dst) 419{ 420 AWT_ASSERT_NOT_APPKIT_THREAD; 421 422 DECLARE_CLASS(jc_Pageable, "java/awt/print/Pageable"); 423 DECLARE_METHOD(jm_getCopies, sjc_CPrinterJob, "getCopiesInt", "()I"); 424 DECLARE_METHOD(jm_isCollated, sjc_CPrinterJob, "isCollated", "()Z"); 425 DECLARE_METHOD(jm_getFromPage, sjc_CPrinterJob, "getFromPageAttrib", "()I"); 426 DECLARE_METHOD(jm_getToPage, sjc_CPrinterJob, "getToPageAttrib", "()I"); 427 DECLARE_METHOD(jm_getMinPage, sjc_CPrinterJob, "getMinPageAttrib", "()I"); 428 DECLARE_METHOD(jm_getMaxPage, sjc_CPrinterJob, "getMaxPageAttrib", "()I"); 429 DECLARE_METHOD(jm_getSelectAttrib, sjc_CPrinterJob, "getSelectAttrib", "()I"); 430 DECLARE_METHOD(jm_getNumberOfPages, jc_Pageable, "getNumberOfPages", "()I"); 431 DECLARE_METHOD(jm_getPageFormat, sjc_CPrinterJob, "getPageFormatFromAttributes", "()Ljava/awt/print/PageFormat;"); 432 433 NSMutableDictionary* printingDictionary = [dst dictionary]; 434 435 jint copies = (*env)->CallIntMethod(env, srcPrinterJob, jm_getCopies); // AWT_THREADING Safe (known object) 436 CHECK_EXCEPTION(); 437 [printingDictionary setObject:[NSNumber numberWithInteger:copies] forKey:NSPrintCopies]; 438 439 jboolean collated = (*env)->CallBooleanMethod(env, srcPrinterJob, jm_isCollated); // AWT_THREADING Safe (known object) 440 CHECK_EXCEPTION(); 441 [printingDictionary setObject:[NSNumber numberWithBool:collated ? YES : NO] forKey:NSPrintMustCollate]; 442 jint selectID = (*env)->CallIntMethod(env, srcPrinterJob, jm_getSelectAttrib); 443 CHECK_EXCEPTION(); 444 jint fromPage = (*env)->CallIntMethod(env, srcPrinterJob, jm_getFromPage); 445 CHECK_EXCEPTION(); 446 jint toPage = (*env)->CallIntMethod(env, srcPrinterJob, jm_getToPage); 447 CHECK_EXCEPTION(); 448 if (selectID ==0) { 449 [printingDictionary setObject:[NSNumber numberWithBool:YES] forKey:NSPrintAllPages]; 450 } else if (selectID == 2) { 451 // In Mac 10.7, Print ALL is deselected if PrintSelection is YES whether 452 // NSPrintAllPages is YES or NO 453 [printingDictionary setObject:[NSNumber numberWithBool:NO] forKey:NSPrintAllPages]; 454 [printingDictionary setObject:[NSNumber numberWithBool:YES] forKey:NSPrintSelectionOnly]; 455 } else { 456 jint minPage = (*env)->CallIntMethod(env, srcPrinterJob, jm_getMinPage); 457 CHECK_EXCEPTION(); 458 jint maxPage = (*env)->CallIntMethod(env, srcPrinterJob, jm_getMaxPage); 459 CHECK_EXCEPTION(); 460 461 // for PD_SELECTION or PD_NOSELECTION, check from/to page 462 // to determine which radio button to select 463 if (fromPage > minPage || toPage < maxPage) { 464 [printingDictionary setObject:[NSNumber numberWithBool:NO] forKey:NSPrintAllPages]; 465 } else { 466 [printingDictionary setObject:[NSNumber numberWithBool:YES] forKey:NSPrintAllPages]; 467 } 468 } 469 470 // setting fromPage and toPage will not be shown in the dialog if printing All pages 471 [printingDictionary setObject:[NSNumber numberWithInteger:fromPage] forKey:NSPrintFirstPage]; 472 [printingDictionary setObject:[NSNumber numberWithInteger:toPage] forKey:NSPrintLastPage]; 473 474 jobject page = (*env)->CallObjectMethod(env, srcPrinterJob, jm_getPageFormat); 475 CHECK_EXCEPTION(); 476 if (page != NULL) { 477 javaPageFormatToNSPrintInfo(env, NULL, page, dst); 478 } 479} 480 481/* 482 * Class: sun_lwawt_macosx_CPrinterJob 483 * Method: abortDoc 484 * Signature: ()V 485 */ 486JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPrinterJob_abortDoc 487 (JNIEnv *env, jobject jthis) 488{ 489JNI_COCOA_ENTER(env); 490 // This is only called during the printLoop from the printLoop thread 491 NSPrintOperation* printLoop = [NSPrintOperation currentOperation]; 492 NSPrintInfo* printInfo = [printLoop printInfo]; 493 [printInfo setJobDisposition:NSPrintCancelJob]; 494JNI_COCOA_EXIT(env); 495} 496 497/* 498 * Class: sun_lwawt_macosx_CPrinterJob 499 * Method: getDefaultPage 500 * Signature: (Ljava/awt/print/PageFormat;)V 501 */ 502JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPrinterJob_getDefaultPage 503 (JNIEnv *env, jobject jthis, jobject page) 504{ 505JNI_COCOA_ENTER(env); 506 NSPrintInfo* printInfo = createDefaultNSPrintInfo(env, NULL); 507 508 nsPrintInfoToJavaPageFormat(env, printInfo, page); 509 510 [printInfo release]; 511JNI_COCOA_EXIT(env); 512} 513 514/* 515 * Class: sun_lwawt_macosx_CPrinterJob 516 * Method: validatePaper 517 * Signature: (Ljava/awt/print/Paper;Ljava/awt/print/Paper;)V 518 */ 519JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPrinterJob_validatePaper 520 (JNIEnv *env, jobject jthis, jobject origpaper, jobject newpaper) 521{ 522JNI_COCOA_ENTER(env); 523 524 525 NSPrintInfo* printInfo = createDefaultNSPrintInfo(env, NULL); 526 javaPaperToNSPrintInfo(env, origpaper, printInfo); 527 makeBestFit(printInfo); 528 nsPrintInfoToJavaPaper(env, printInfo, newpaper); 529 [printInfo release]; 530 531JNI_COCOA_EXIT(env); 532} 533 534/* 535 * Class: sun_lwawt_macosx_CPrinterJob 536 * Method: createNSPrintInfo 537 * Signature: ()J 538 */ 539JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CPrinterJob_createNSPrintInfo 540 (JNIEnv *env, jobject jthis) 541{ 542 jlong result = -1; 543JNI_COCOA_ENTER(env); 544 // This is used to create the NSPrintInfo for this PrinterJob. Thread 545 // safety is assured by the java side of this call. 546 547 NSPrintInfo* printInfo = createDefaultNSPrintInfo(env, NULL); 548 549 result = ptr_to_jlong(printInfo); 550 551JNI_COCOA_EXIT(env); 552 return result; 553} 554 555/* 556 * Class: sun_lwawt_macosx_CPrinterJob 557 * Method: dispose 558 * Signature: (J)V 559 */ 560JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPrinterJob_dispose 561 (JNIEnv *env, jobject jthis, jlong nsPrintInfo) 562{ 563JNI_COCOA_ENTER(env); 564 if (nsPrintInfo != -1) 565 { 566 NSPrintInfo* printInfo = (NSPrintInfo*)jlong_to_ptr(nsPrintInfo); 567 [printInfo release]; 568 } 569JNI_COCOA_EXIT(env); 570} 571 572 573/* 574 * Class: sun_lwawt_macosx_CPrinterJob 575 * Method: printLoop 576 * Signature: ()V 577 */ 578JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_CPrinterJob_printLoop 579 (JNIEnv *env, jobject jthis, jboolean blocks, jint firstPage, jint lastPage) 580{ 581 AWT_ASSERT_NOT_APPKIT_THREAD; 582 583 GET_CPRINTERJOB_CLASS_RETURN(NO); 584 DECLARE_METHOD_RETURN(jm_getPageFormat, sjc_CPrinterJob, "getPageFormat", "(I)Ljava/awt/print/PageFormat;", NO); 585 DECLARE_METHOD_RETURN(jm_getPageFormatArea, sjc_CPrinterJob, "getPageFormatArea", "(Ljava/awt/print/PageFormat;)Ljava/awt/geom/Rectangle2D;", NO); 586 DECLARE_METHOD_RETURN(jm_getPrinterName, sjc_CPrinterJob, "getPrinterName", "()Ljava/lang/String;", NO); 587 DECLARE_METHOD_RETURN(jm_getPageable, sjc_CPrinterJob, "getPageable", "()Ljava/awt/print/Pageable;", NO); 588 DECLARE_METHOD_RETURN(jm_getPrinterTray, sjc_CPrinterJob, "getPrinterTray", "()Ljava/lang/String;", NO); 589 590 jboolean retVal = JNI_FALSE; 591 592JNI_COCOA_ENTER(env); 593 // Get the first page's PageFormat for setting things up (This introduces 594 // and is a facet of the same problem in Radar 2818593/2708932). 595 jobject page = (*env)->CallObjectMethod(env, jthis, jm_getPageFormat, 0); // AWT_THREADING Safe (!appKit) 596 CHECK_EXCEPTION(); 597 if (page != NULL) { 598 jobject pageFormatArea = (*env)->CallObjectMethod(env, jthis, jm_getPageFormatArea, page); // AWT_THREADING Safe (!appKit) 599 CHECK_EXCEPTION(); 600 601 PrinterView* printerView = [[PrinterView alloc] initWithFrame:JavaToNSRect(env, pageFormatArea) withEnv:env withPrinterJob:jthis]; 602 [printerView setFirstPage:firstPage lastPage:lastPage]; 603 604 GET_NSPRINTINFO_METHOD_RETURN(NO) 605 NSPrintInfo* printInfo = (NSPrintInfo*)jlong_to_ptr((*env)->CallLongMethod(env, jthis, sjm_getNSPrintInfo)); // AWT_THREADING Safe (known object) 606 CHECK_EXCEPTION(); 607 jobject printerTrayObj = (*env)->CallObjectMethod(env, jthis, jm_getPrinterTray); 608 CHECK_EXCEPTION(); 609 if (printerTrayObj != NULL) { 610 NSString *printerTray = JavaStringToNSString(env, printerTrayObj); 611 if (printerTray != nil) { 612 [[printInfo printSettings] setObject:printerTray forKey:@"InputSlot"]; 613 } 614 } 615 616 // <rdar://problem/4156975> passing jthis CPrinterJob as well, so we can extract the printer name from the current job 617 javaPageFormatToNSPrintInfo(env, jthis, page, printInfo); 618 619 // <rdar://problem/4093799> NSPrinterInfo is not correctly set to the selected printer 620 // from the Java side of CPrinterJob. Had always assumed the default printer was the one we wanted. 621 jobject printerNameObj = (*env)->CallObjectMethod(env, jthis, jm_getPrinterName); 622 CHECK_EXCEPTION(); 623 if (printerNameObj != NULL) { 624 NSString *printerName = JavaStringToNSString(env, printerNameObj); 625 if (printerName != nil) { 626 NSPrinter *printer = [NSPrinter printerWithName:printerName]; 627 if (printer != nil) [printInfo setPrinter:printer]; 628 } 629 } 630 631 // <rdar://problem/4367998> JTable.print attributes are ignored 632 jobject pageable = (*env)->CallObjectMethod(env, jthis, jm_getPageable); // AWT_THREADING Safe (!appKit) 633 CHECK_EXCEPTION(); 634 javaPrinterJobToNSPrintInfo(env, jthis, pageable, printInfo); 635 636 PrintModel* printModel = [[PrintModel alloc] initWithPrintInfo:printInfo]; 637 638 (void)[printModel runPrintLoopWithView:printerView waitUntilDone:blocks withEnv:env]; 639 640 // Only set this if we got far enough to call runPrintLoopWithView, or we will spin CPrinterJob.print() forever! 641 retVal = JNI_TRUE; 642 643 [printModel release]; 644 [printerView release]; 645 646 if (page != NULL) 647 { 648 (*env)->DeleteLocalRef(env, page); 649 } 650 651 if (pageFormatArea != NULL) 652 { 653 (*env)->DeleteLocalRef(env, pageFormatArea); 654 } 655 } 656JNI_COCOA_EXIT(env); 657 return retVal; 658} 659 660/* 661 * Class: sun_lwawt_macosx_CPrinterPageDialog 662 * Method: showDialog 663 * Signature: ()Z 664 */ 665JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_CPrinterPageDialog_showDialog 666 (JNIEnv *env, jobject jthis) 667{ 668 669 DECLARE_CLASS_RETURN(jc_CPrinterPageDialog, "sun/lwawt/macosx/CPrinterPageDialog", NO); 670 DECLARE_FIELD_RETURN(jm_page, jc_CPrinterPageDialog, "fPage", "Ljava/awt/print/PageFormat;", NO); 671 672 jboolean result = JNI_FALSE; 673JNI_COCOA_ENTER(env); 674 GET_CPRINTERDIALOG_FIELD_RETURN(NO); 675 GET_NSPRINTINFO_METHOD_RETURN(NO) 676 jobject printerJob = (*env)->GetObjectField(env, jthis, sjm_printerJob); 677 if (printerJob == NULL) return NO; 678 NSPrintInfo* printInfo = (NSPrintInfo*)jlong_to_ptr((*env)->CallLongMethod(env, printerJob, sjm_getNSPrintInfo)); // AWT_THREADING Safe (known object) 679 CHECK_EXCEPTION(); 680 if (printInfo == NULL) return result; 681 682 jobject page = (*env)->GetObjectField(env, jthis, jm_page); 683 if (page == NULL) return NO; 684 685 // <rdar://problem/4156975> passing NULL, because only a CPrinterJob has a real printer associated with it 686 javaPageFormatToNSPrintInfo(env, NULL, page, printInfo); 687 688 PrintModel* printModel = [[PrintModel alloc] initWithPrintInfo:printInfo]; 689 result = [printModel runPageSetup]; 690 [printModel release]; 691 692 if (result) 693 { 694 nsPrintInfoToJavaPageFormat(env, printInfo, page); 695 } 696 697 if (printerJob != NULL) 698 { 699 (*env)->DeleteLocalRef(env, printerJob); 700 } 701 702 if (page != NULL) 703 { 704 (*env)->DeleteLocalRef(env, page); 705 } 706 707JNI_COCOA_EXIT(env); 708 return result; 709} 710 711/* 712 * Class: sun_lwawt_macosx_CPrinterJobDialog 713 * Method: showDialog 714 * Signature: ()Z 715 */ 716JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_CPrinterJobDialog_showDialog 717 (JNIEnv *env, jobject jthis) 718{ 719 DECLARE_CLASS_RETURN(jc_CPrinterJobDialog, "sun/lwawt/macosx/CPrinterJobDialog", NO); 720 DECLARE_FIELD_RETURN(jm_pageable, jc_CPrinterJobDialog, "fPageable", "Ljava/awt/print/Pageable;", NO); 721 722 jboolean result = JNI_FALSE; 723JNI_COCOA_ENTER(env); 724 GET_CPRINTERDIALOG_FIELD_RETURN(NO); 725 jobject printerJob = (*env)->GetObjectField(env, jthis, sjm_printerJob); 726 if (printerJob == NULL) return NO; 727 GET_NSPRINTINFO_METHOD_RETURN(NO) 728 NSPrintInfo* printInfo = (NSPrintInfo*)jlong_to_ptr((*env)->CallLongMethod(env, printerJob, sjm_getNSPrintInfo)); // AWT_THREADING Safe (known object) 729 730 jobject pageable = (*env)->GetObjectField(env, jthis, jm_pageable); 731 if (pageable == NULL) return NO; 732 733 javaPrinterJobToNSPrintInfo(env, printerJob, pageable, printInfo); 734 735 PrintModel* printModel = [[PrintModel alloc] initWithPrintInfo:printInfo]; 736 result = [printModel runJobSetup]; 737 [printModel release]; 738 739 if (result) 740 { 741 nsPrintInfoToJavaPrinterJob(env, printInfo, printerJob, pageable); 742 } 743 744 if (printerJob != NULL) 745 { 746 (*env)->DeleteLocalRef(env, printerJob); 747 } 748 749 if (pageable != NULL) 750 { 751 (*env)->DeleteLocalRef(env, pageable); 752 } 753 754JNI_COCOA_EXIT(env); 755 return result; 756} 757