1 /*
   2  * Copyright (c) 2011, 2013, 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 #import <JavaNativeFoundation/JavaNativeFoundation.h>
  34 
  35 #import "PrinterView.h"
  36 #import "PrintModel.h"
  37 #import "ThreadUtilities.h"
  38 #import "GeomUtilities.h"
  39 
  40 static JNF_CLASS_CACHE(sjc_Paper, "java/awt/print/Paper");
  41 static JNF_CLASS_CACHE(sjc_PageFormat, "java/awt/print/PageFormat");
  42 static JNF_CLASS_CACHE(sjc_CPrinterJob, "sun/lwawt/macosx/CPrinterJob");
  43 static JNF_CLASS_CACHE(sjc_CPrinterDialog, "sun/lwawt/macosx/CPrinterDialog");
  44 static JNF_MEMBER_CACHE(sjm_getNSPrintInfo, sjc_CPrinterJob, "getNSPrintInfo", "()J");
  45 static JNF_MEMBER_CACHE(sjm_printerJob, sjc_CPrinterDialog, "fPrinterJob", "Lsun/lwawt/macosx/CPrinterJob;");
  46 
  47 static NSPrintInfo* createDefaultNSPrintInfo();
  48 
  49 static void makeBestFit(NSPrintInfo* src);
  50 
  51 static void nsPrintInfoToJavaPaper(JNIEnv* env, NSPrintInfo* src, jobject dst);
  52 static void javaPaperToNSPrintInfo(JNIEnv* env, jobject src, NSPrintInfo* dst);
  53 
  54 static void nsPrintInfoToJavaPageFormat(JNIEnv* env, NSPrintInfo* src, jobject dst);
  55 static void javaPageFormatToNSPrintInfo(JNIEnv* env, jobject srcPrinterJob, jobject srcPageFormat, NSPrintInfo* dst);
  56 
  57 static void nsPrintInfoToJavaPrinterJob(JNIEnv* env, NSPrintInfo* src, jobject dstPrinterJob, jobject dstPageable);
  58 static void javaPrinterJobToNSPrintInfo(JNIEnv* env, jobject srcPrinterJob, jobject srcPageable, NSPrintInfo* dst);
  59 
  60 
  61 static NSPrintInfo* createDefaultNSPrintInfo(JNIEnv* env, jstring printer)
  62 {
  63     NSPrintInfo* defaultPrintInfo = [[NSPrintInfo sharedPrintInfo] copy];
  64     if (printer != NULL)
  65     {
  66         NSPrinter* nsPrinter = [NSPrinter printerWithName:JNFJavaToNSString(env, printer)];
  67         if (nsPrinter != nil)
  68         {
  69             [defaultPrintInfo setPrinter:nsPrinter];
  70         }
  71     }
  72     [defaultPrintInfo setUpPrintOperationDefaultValues];
  73 
  74     // cmc 05/18/04 radr://3160443 : setUpPrintOperationDefaultValues sets the
  75     // page margins to 72, 72, 90, 90 - need to use [NSPrintInfo imageablePageBounds]
  76     // to get values from the printer.
  77     // NOTE: currently [NSPrintInfo imageablePageBounds] does not update itself when
  78     // the user selects a different printer - see radr://3657453. However, rather than
  79     // directly querying the PPD here, we'll let AppKit printing do the work. The AppKit
  80     // printing bug above is set to be fixed for Tiger.
  81     NSRect imageableRect = [defaultPrintInfo imageablePageBounds];
  82     [defaultPrintInfo setLeftMargin: imageableRect.origin.x];
  83     [defaultPrintInfo setBottomMargin: imageableRect.origin.y]; //top and bottom are flipped because [NSPrintInfo imageablePageBounds] returns a flipped NSRect (bottom-left to top-right).
  84     [defaultPrintInfo setRightMargin: [defaultPrintInfo paperSize].width-imageableRect.origin.x-imageableRect.size.width];
  85     [defaultPrintInfo setTopMargin: [defaultPrintInfo paperSize].height-imageableRect.origin.y-imageableRect.size.height];
  86 
  87     return defaultPrintInfo;
  88 }
  89 
  90 static void makeBestFit(NSPrintInfo* src)
  91 {
  92     // This will look at the NSPrintInfo's margins. If they are out of bounds to the
  93     // imageable area of the page, it will set them to the largest possible size.
  94 
  95     NSRect imageable = [src imageablePageBounds];
  96 
  97     NSSize paperSize = [src paperSize];
  98 
  99     CGFloat fullLeftM = imageable.origin.x;
 100     CGFloat fullRightM = paperSize.width - (imageable.origin.x + imageable.size.width);
 101 
 102     // These are flipped because [NSPrintInfo imageablePageBounds] returns a flipped
 103     //  NSRect (bottom-left to top-right).
 104     CGFloat fullTopM = paperSize.height - (imageable.origin.y + imageable.size.height);
 105     CGFloat fullBottomM = imageable.origin.y;
 106 
 107     if (fullLeftM > [src leftMargin])
 108     {
 109         [src setLeftMargin:fullLeftM];
 110     }
 111 
 112     if (fullRightM > [src rightMargin])
 113     {
 114         [src setRightMargin:fullRightM];
 115     }
 116 
 117     if (fullTopM > [src topMargin])
 118     {
 119         [src setTopMargin:fullTopM];
 120     }
 121 
 122     if (fullBottomM > [src bottomMargin])
 123     {
 124         [src setBottomMargin:fullBottomM];
 125     }
 126 }
 127 
 128 // In AppKit Printing, the rectangle is always oriented. In AppKit Printing, setting
 129 //  the rectangle will always set the orientation.
 130 // In java printing, the rectangle is oriented if accessed from PageFormat. It is
 131 //  not oriented when accessed from Paper.
 132 
 133 static void nsPrintInfoToJavaPaper(JNIEnv* env, NSPrintInfo* src, jobject dst)
 134 {
 135     static JNF_MEMBER_CACHE(jm_setSize, sjc_Paper, "setSize", "(DD)V");
 136     static JNF_MEMBER_CACHE(jm_setImageableArea, sjc_Paper, "setImageableArea", "(DDDD)V");
 137 
 138     jdouble jPaperW, jPaperH;
 139 
 140     // NSPrintInfo paperSize is oriented. java Paper is not oriented. Take
 141     //  the -[NSPrintInfo orientation] into account when setting the Paper
 142     //  rectangle.
 143 
 144     NSSize paperSize = [src paperSize];
 145     switch ([src orientation]) {
 146         case NSPortraitOrientation:
 147             jPaperW = paperSize.width;
 148             jPaperH = paperSize.height;
 149             break;
 150 
 151         case NSLandscapeOrientation:
 152             jPaperW = paperSize.height;
 153             jPaperH = paperSize.width;
 154             break;
 155 
 156         default:
 157             jPaperW = paperSize.width;
 158             jPaperH = paperSize.height;
 159             break;
 160     }
 161 
 162     JNFCallVoidMethod(env, dst, jm_setSize, jPaperW, jPaperH); // AWT_THREADING Safe (known object - always actual Paper)
 163 
 164     // Set the imageable area from the margins
 165     CGFloat leftM = [src leftMargin];
 166     CGFloat rightM = [src rightMargin];
 167     CGFloat topM = [src topMargin];
 168     CGFloat bottomM = [src bottomMargin];
 169 
 170     jdouble jImageX = leftM;
 171     jdouble jImageY = topM;
 172     jdouble jImageW = jPaperW - (leftM + rightM);
 173     jdouble jImageH = jPaperH - (topM + bottomM);
 174 
 175     JNFCallVoidMethod(env, dst, jm_setImageableArea, jImageX, jImageY, jImageW, jImageH); // AWT_THREADING Safe (known object - always actual Paper)
 176 }
 177 
 178 static void javaPaperToNSPrintInfo(JNIEnv* env, jobject src, NSPrintInfo* dst)
 179 {
 180     AWT_ASSERT_NOT_APPKIT_THREAD;
 181 
 182     static JNF_MEMBER_CACHE(jm_getWidth, sjc_Paper, "getWidth", "()D");
 183     static JNF_MEMBER_CACHE(jm_getHeight, sjc_Paper, "getHeight", "()D");
 184     static JNF_MEMBER_CACHE(jm_getImageableX, sjc_Paper, "getImageableX", "()D");
 185     static JNF_MEMBER_CACHE(jm_getImageableY, sjc_Paper, "getImageableY", "()D");
 186     static JNF_MEMBER_CACHE(jm_getImageableW, sjc_Paper, "getImageableWidth", "()D");
 187     static JNF_MEMBER_CACHE(jm_getImageableH, sjc_Paper, "getImageableHeight", "()D");
 188 
 189     // java Paper is always Portrait oriented. Set NSPrintInfo with this
 190     //  rectangle, and it's orientation may change. If necessary, be sure to call
 191     //  -[NSPrintInfo setOrientation] after this call, which will then
 192     //  adjust the -[NSPrintInfo paperSize] as well.
 193 
 194     jdouble jPhysicalWidth = JNFCallDoubleMethod(env, src, jm_getWidth); // AWT_THREADING Safe (!appKit)
 195     jdouble jPhysicalHeight = JNFCallDoubleMethod(env, src, jm_getHeight); // AWT_THREADING Safe (!appKit)
 196 
 197     [dst setPaperSize:NSMakeSize(jPhysicalWidth, jPhysicalHeight)];
 198 
 199     // Set the margins from the imageable area
 200     jdouble jImageX = JNFCallDoubleMethod(env, src, jm_getImageableX); // AWT_THREADING Safe (!appKit)
 201     jdouble jImageY = JNFCallDoubleMethod(env, src, jm_getImageableY); // AWT_THREADING Safe (!appKit)
 202     jdouble jImageW = JNFCallDoubleMethod(env, src, jm_getImageableW); // AWT_THREADING Safe (!appKit)
 203     jdouble jImageH = JNFCallDoubleMethod(env, src, jm_getImageableH); // AWT_THREADING Safe (!appKit)
 204 
 205     [dst setLeftMargin:(CGFloat)jImageX];
 206     [dst setTopMargin:(CGFloat)jImageY];
 207     [dst setRightMargin:(CGFloat)(jPhysicalWidth - jImageW - jImageX)];
 208     [dst setBottomMargin:(CGFloat)(jPhysicalHeight - jImageH - jImageY)];
 209 }
 210 
 211 static void nsPrintInfoToJavaPageFormat(JNIEnv* env, NSPrintInfo* src, jobject dst)
 212 {
 213     AWT_ASSERT_NOT_APPKIT_THREAD;
 214 
 215     static JNF_MEMBER_CACHE(jm_setOrientation, sjc_PageFormat, "setOrientation", "(I)V");
 216     static JNF_MEMBER_CACHE(jm_setPaper, sjc_PageFormat, "setPaper", "(Ljava/awt/print/Paper;)V");
 217     static JNF_CTOR_CACHE(jm_Paper_ctor, sjc_Paper, "()V");
 218 
 219     jint jOrientation;
 220     NSPrintingOrientation nsOrientation = [src orientation];
 221     switch (nsOrientation) {
 222         case NSPortraitOrientation:
 223             jOrientation = java_awt_print_PageFormat_PORTRAIT;
 224             break;
 225 
 226         case NSLandscapeOrientation:
 227             jOrientation = java_awt_print_PageFormat_LANDSCAPE; //+++gdb Are LANDSCAPE and REVERSE_LANDSCAPE still inverted?
 228             break;
 229 
 230 /*
 231         // AppKit printing doesn't support REVERSE_LANDSCAPE. Radar 2960295.
 232         case NSReverseLandscapeOrientation:
 233             jOrientation = java_awt_print_PageFormat.REVERSE_LANDSCAPE; //+++gdb Are LANDSCAPE and REVERSE_LANDSCAPE still inverted?
 234             break;
 235 */
 236 
 237         default:
 238             jOrientation = java_awt_print_PageFormat_PORTRAIT;
 239             break;
 240     }
 241 
 242     JNFCallVoidMethod(env, dst, jm_setOrientation, jOrientation); // AWT_THREADING Safe (!appKit)
 243 
 244     // Create a new Paper
 245     jobject paper = JNFNewObject(env, jm_Paper_ctor); // AWT_THREADING Safe (known object)
 246 
 247     nsPrintInfoToJavaPaper(env, src, paper);
 248 
 249     // Set the Paper in the PageFormat
 250     JNFCallVoidMethod(env, dst, jm_setPaper, paper); // AWT_THREADING Safe (!appKit)
 251 
 252     (*env)->DeleteLocalRef(env, paper);
 253 }
 254 
 255 static void javaPageFormatToNSPrintInfo(JNIEnv* env, jobject srcPrintJob, jobject srcPageFormat, NSPrintInfo* dstPrintInfo)
 256 {
 257     AWT_ASSERT_NOT_APPKIT_THREAD;
 258 
 259     static JNF_MEMBER_CACHE(jm_getOrientation, sjc_PageFormat, "getOrientation", "()I");
 260     static JNF_MEMBER_CACHE(jm_getPaper, sjc_PageFormat, "getPaper", "()Ljava/awt/print/Paper;");
 261     static JNF_MEMBER_CACHE(jm_getPrinterName, sjc_CPrinterJob, "getPrinterName", "()Ljava/lang/String;");
 262 
 263     // When setting page information (orientation, size) in NSPrintInfo, set the
 264     //  rectangle first. This is because setting the orientation will change the
 265     //  rectangle to match.
 266 
 267     // Set up the paper. This will force Portrait since java Paper is
 268     //  not oriented. Then setting the NSPrintInfo orientation below
 269     //  will flip NSPrintInfo's info as necessary.
 270     jobject paper = JNFCallObjectMethod(env, srcPageFormat, jm_getPaper); // AWT_THREADING Safe (!appKit)
 271     javaPaperToNSPrintInfo(env, paper, dstPrintInfo);
 272     (*env)->DeleteLocalRef(env, paper);
 273 
 274     switch (JNFCallIntMethod(env, srcPageFormat, jm_getOrientation)) { // AWT_THREADING Safe (!appKit)
 275         case java_awt_print_PageFormat_PORTRAIT:
 276             [dstPrintInfo setOrientation:NSPortraitOrientation];
 277             break;
 278 
 279         case java_awt_print_PageFormat_LANDSCAPE:
 280             [dstPrintInfo setOrientation:NSLandscapeOrientation]; //+++gdb Are LANDSCAPE and REVERSE_LANDSCAPE still inverted?
 281             break;
 282 
 283         // AppKit printing doesn't support REVERSE_LANDSCAPE. Radar 2960295.
 284         case java_awt_print_PageFormat_REVERSE_LANDSCAPE:
 285             [dstPrintInfo setOrientation:NSLandscapeOrientation]; //+++gdb Are LANDSCAPE and REVERSE_LANDSCAPE still inverted?
 286             break;
 287 
 288         default:
 289             [dstPrintInfo setOrientation:NSPortraitOrientation];
 290             break;
 291     }
 292 
 293     // <rdar://problem/4022422> NSPrinterInfo is not correctly set to the selected printer
 294     // from the Java side of CPrinterJob. Has always assumed the default printer was the one we wanted.
 295     if (srcPrintJob == NULL) return;
 296     jobject printerNameObj = JNFCallObjectMethod(env, srcPrintJob, jm_getPrinterName);
 297     if (printerNameObj == NULL) return;
 298     NSString *printerName = JNFJavaToNSString(env, printerNameObj);
 299     if (printerName == nil) return;
 300     NSPrinter *printer = [NSPrinter printerWithName:printerName];
 301     if (printer == nil) return;
 302     [dstPrintInfo setPrinter:printer];
 303 }
 304 
 305 static void nsPrintInfoToJavaPrinterJob(JNIEnv* env, NSPrintInfo* src, jobject dstPrinterJob, jobject dstPageable)
 306 {
 307     static JNF_MEMBER_CACHE(jm_setService, sjc_CPrinterJob, "setPrinterServiceFromNative", "(Ljava/lang/String;)V");
 308     static JNF_MEMBER_CACHE(jm_setCopies, sjc_CPrinterJob, "setCopies", "(I)V");
 309     static JNF_MEMBER_CACHE(jm_setCollated, sjc_CPrinterJob, "setCollated", "(Z)V");
 310     static JNF_MEMBER_CACHE(jm_setPageRange, sjc_CPrinterJob, "setPageRange", "(II)V");
 311 
 312     // get the selected printer's name, and set the appropriate PrintService on the Java side
 313     NSString *name = [[src printer] name];
 314     jstring printerName = JNFNSToJavaString(env, name);
 315     JNFCallVoidMethod(env, dstPrinterJob, jm_setService, printerName);
 316 
 317 
 318     NSMutableDictionary* printingDictionary = [src dictionary];
 319 
 320     NSNumber* nsCopies = [printingDictionary objectForKey:NSPrintCopies];
 321     if ([nsCopies respondsToSelector:@selector(integerValue)])
 322     {
 323         JNFCallVoidMethod(env, dstPrinterJob, jm_setCopies, [nsCopies integerValue]); // AWT_THREADING Safe (known object)
 324     }
 325 
 326     NSNumber* nsCollated = [printingDictionary objectForKey:NSPrintMustCollate];
 327     if ([nsCollated respondsToSelector:@selector(boolValue)])
 328     {
 329         JNFCallVoidMethod(env, dstPrinterJob, jm_setCollated, [nsCollated boolValue] ? JNI_TRUE : JNI_FALSE); // AWT_THREADING Safe (known object)
 330     }
 331 
 332     NSNumber* nsPrintAllPages = [printingDictionary objectForKey:NSPrintAllPages];
 333     if ([nsPrintAllPages respondsToSelector:@selector(boolValue)])
 334     {
 335         jint jFirstPage = 0, jLastPage = java_awt_print_Pageable_UNKNOWN_NUMBER_OF_PAGES;
 336         if (![nsPrintAllPages boolValue])
 337         {
 338             NSNumber* nsFirstPage = [printingDictionary objectForKey:NSPrintFirstPage];
 339             if ([nsFirstPage respondsToSelector:@selector(integerValue)])
 340             {
 341                 jFirstPage = [nsFirstPage integerValue] - 1;
 342             }
 343 
 344             NSNumber* nsLastPage = [printingDictionary objectForKey:NSPrintLastPage];
 345             if ([nsLastPage respondsToSelector:@selector(integerValue)])
 346             {
 347                 jLastPage = [nsLastPage integerValue] - 1;
 348             }
 349         }
 350 
 351         JNFCallVoidMethod(env, dstPrinterJob, jm_setPageRange, jFirstPage, jLastPage); // AWT_THREADING Safe (known object)
 352     }
 353 }
 354 
 355 static void javaPrinterJobToNSPrintInfo(JNIEnv* env, jobject srcPrinterJob, jobject srcPageable, NSPrintInfo* dst)
 356 {
 357     AWT_ASSERT_NOT_APPKIT_THREAD;
 358 
 359     static JNF_CLASS_CACHE(jc_Pageable, "java/awt/print/Pageable");
 360     static JNF_MEMBER_CACHE(jm_getCopies, sjc_CPrinterJob, "getCopiesInt", "()I");
 361     static JNF_MEMBER_CACHE(jm_isCollated, sjc_CPrinterJob, "isCollated", "()Z");
 362     static JNF_MEMBER_CACHE(jm_getFromPage, sjc_CPrinterJob, "getFromPageAttrib", "()I");
 363     static JNF_MEMBER_CACHE(jm_getToPage, sjc_CPrinterJob, "getToPageAttrib", "()I");
 364     static JNF_MEMBER_CACHE(jm_getSelectAttrib, sjc_CPrinterJob, "getSelectAttrib", "()I");
 365     static JNF_MEMBER_CACHE(jm_getNumberOfPages, jc_Pageable, "getNumberOfPages", "()I");
 366     static JNF_MEMBER_CACHE(jm_getPageFormat, sjc_CPrinterJob, "getPageFormatFromAttributes", "()Ljava/awt/print/PageFormat;");
 367 
 368     NSMutableDictionary* printingDictionary = [dst dictionary];
 369 
 370     jint copies = JNFCallIntMethod(env, srcPrinterJob, jm_getCopies); // AWT_THREADING Safe (known object)
 371     [printingDictionary setObject:[NSNumber numberWithInteger:copies] forKey:NSPrintCopies];
 372 
 373     jboolean collated = JNFCallBooleanMethod(env, srcPrinterJob, jm_isCollated); // AWT_THREADING Safe (known object)
 374     [printingDictionary setObject:[NSNumber numberWithBool:collated ? YES : NO] forKey:NSPrintMustCollate];
 375     jint jNumPages = JNFCallIntMethod(env, srcPageable, jm_getNumberOfPages); // AWT_THREADING Safe (!appKit)
 376     if (jNumPages != java_awt_print_Pageable_UNKNOWN_NUMBER_OF_PAGES)
 377     {
 378         jint selectID = JNFCallIntMethod(env, srcPrinterJob, jm_getSelectAttrib);
 379         if (selectID ==0) {
 380             [printingDictionary setObject:[NSNumber numberWithBool:YES] forKey:NSPrintAllPages];
 381         } else if (selectID == 2) {
 382             // In Mac 10.7,  Print ALL is deselected if PrintSelection is YES whether
 383             // NSPrintAllPages is YES or NO
 384             [printingDictionary setObject:[NSNumber numberWithBool:NO] forKey:NSPrintAllPages];
 385             [printingDictionary setObject:[NSNumber numberWithBool:YES] forKey:NSPrintSelectionOnly];
 386         } else {
 387             [printingDictionary setObject:[NSNumber numberWithBool:NO] forKey:NSPrintAllPages];
 388         }
 389 
 390         jint fromPage = JNFCallIntMethod(env, srcPrinterJob, jm_getFromPage);
 391         jint toPage = JNFCallIntMethod(env, srcPrinterJob, jm_getToPage);
 392         // setting fromPage and toPage will not be shown in the dialog if printing All pages
 393         [printingDictionary setObject:[NSNumber numberWithInteger:fromPage] forKey:NSPrintFirstPage];
 394         [printingDictionary setObject:[NSNumber numberWithInteger:toPage] forKey:NSPrintLastPage];
 395     }
 396     else
 397     {
 398         [printingDictionary setObject:[NSNumber numberWithBool:YES] forKey:NSPrintAllPages];
 399     }
 400     jobject page = JNFCallObjectMethod(env, srcPrinterJob, jm_getPageFormat); 
 401     if (page != NULL) {
 402         javaPageFormatToNSPrintInfo(env, NULL, page, dst);
 403     }
 404 }
 405 
 406 /*
 407  * Class:     sun_lwawt_macosx_CPrinterJob
 408  * Method:    abortDoc
 409  * Signature: ()V
 410  */
 411 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPrinterJob_abortDoc
 412   (JNIEnv *env, jobject jthis)
 413 {
 414 JNF_COCOA_ENTER(env);
 415     // This is only called during the printLoop from the printLoop thread
 416     NSPrintOperation* printLoop = [NSPrintOperation currentOperation];
 417     NSPrintInfo* printInfo = [printLoop printInfo];
 418     [printInfo setJobDisposition:NSPrintCancelJob];
 419 JNF_COCOA_EXIT(env);
 420 }
 421 
 422 /*
 423  * Class:     sun_lwawt_macosx_CPrinterJob
 424  * Method:    getDefaultPage
 425  * Signature: (Ljava/awt/print/PageFormat;)V
 426  */
 427 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPrinterJob_getDefaultPage
 428   (JNIEnv *env, jobject jthis, jobject page)
 429 {
 430 JNF_COCOA_ENTER(env);
 431     NSPrintInfo* printInfo = createDefaultNSPrintInfo(env, NULL);
 432 
 433     nsPrintInfoToJavaPageFormat(env, printInfo, page);
 434 
 435     [printInfo release];
 436 JNF_COCOA_EXIT(env);
 437 }
 438 
 439 /*
 440  * Class:     sun_lwawt_macosx_CPrinterJob
 441  * Method:    validatePaper
 442  * Signature: (Ljava/awt/print/Paper;Ljava/awt/print/Paper;)V
 443  */
 444 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPrinterJob_validatePaper
 445   (JNIEnv *env, jobject jthis, jobject origpaper, jobject newpaper)
 446 {
 447 JNF_COCOA_ENTER(env);
 448 
 449     NSPrintInfo* printInfo = createDefaultNSPrintInfo(env, NULL);
 450     javaPaperToNSPrintInfo(env, origpaper, printInfo);
 451     makeBestFit(printInfo);
 452     nsPrintInfoToJavaPaper(env, printInfo, newpaper);
 453     [printInfo release];
 454 
 455 JNF_COCOA_EXIT(env);
 456 }
 457 
 458 /*
 459  * Class:     sun_lwawt_macosx_CPrinterJob
 460  * Method:    createNSPrintInfo
 461  * Signature: ()J
 462  */
 463 JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CPrinterJob_createNSPrintInfo
 464   (JNIEnv *env, jobject jthis)
 465 {
 466     jlong result = -1;
 467 JNF_COCOA_ENTER(env);
 468     // This is used to create the NSPrintInfo for this PrinterJob. Thread
 469     //  safety is assured by the java side of this call.
 470 
 471     NSPrintInfo* printInfo = createDefaultNSPrintInfo(env, NULL);
 472 
 473     result = ptr_to_jlong(printInfo);
 474 
 475 JNF_COCOA_EXIT(env);
 476     return result;
 477 }
 478 
 479 /*
 480  * Class:     sun_lwawt_macosx_CPrinterJob
 481  * Method:    dispose
 482  * Signature: (J)V
 483  */
 484 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPrinterJob_dispose
 485   (JNIEnv *env, jobject jthis, jlong nsPrintInfo)
 486 {
 487 JNF_COCOA_ENTER(env);
 488     if (nsPrintInfo != -1)
 489     {
 490         NSPrintInfo* printInfo = (NSPrintInfo*)jlong_to_ptr(nsPrintInfo);
 491         [printInfo release];
 492     }
 493 JNF_COCOA_EXIT(env);
 494 }
 495 
 496 
 497 /*
 498  * Class:     sun_lwawt_macosx_CPrinterJob
 499  * Method:    printLoop
 500  * Signature: ()V
 501  */
 502 JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_CPrinterJob_printLoop
 503   (JNIEnv *env, jobject jthis, jboolean blocks, jint firstPage, jint lastPage)
 504 {
 505     AWT_ASSERT_NOT_APPKIT_THREAD;
 506 
 507     static JNF_MEMBER_CACHE(jm_getPageFormat, sjc_CPrinterJob, "getPageFormat", "(I)Ljava/awt/print/PageFormat;");
 508     static JNF_MEMBER_CACHE(jm_getPageFormatArea, sjc_CPrinterJob, "getPageFormatArea", "(Ljava/awt/print/PageFormat;)Ljava/awt/geom/Rectangle2D;");
 509     static JNF_MEMBER_CACHE(jm_getPrinterName, sjc_CPrinterJob, "getPrinterName", "()Ljava/lang/String;");
 510     static JNF_MEMBER_CACHE(jm_getPageable, sjc_CPrinterJob, "getPageable", "()Ljava/awt/print/Pageable;");
 511 
 512     jboolean retVal = JNI_FALSE;
 513 
 514 JNF_COCOA_ENTER(env);
 515     // Get the first page's PageFormat for setting things up (This introduces
 516     //  and is a facet of the same problem in Radar 2818593/2708932).
 517     jobject page = JNFCallObjectMethod(env, jthis, jm_getPageFormat, 0); // AWT_THREADING Safe (!appKit)
 518     if (page != NULL) {
 519         jobject pageFormatArea = JNFCallObjectMethod(env, jthis, jm_getPageFormatArea, page); // AWT_THREADING Safe (!appKit)
 520 
 521         PrinterView* printerView = [[PrinterView alloc] initWithFrame:JavaToNSRect(env, pageFormatArea) withEnv:env withPrinterJob:jthis];
 522         [printerView setFirstPage:firstPage lastPage:lastPage];
 523 
 524         NSPrintInfo* printInfo = (NSPrintInfo*)jlong_to_ptr(JNFCallLongMethod(env, jthis, sjm_getNSPrintInfo)); // AWT_THREADING Safe (known object)
 525 
 526         // <rdar://problem/4367998> JTable.print attributes are ignored
 527         jobject pageable = JNFCallObjectMethod(env, jthis, jm_getPageable); // AWT_THREADING Safe (!appKit)
 528         javaPrinterJobToNSPrintInfo(env, jthis, pageable, printInfo);
 529 
 530         // <rdar://problem/4156975> passing jthis CPrinterJob as well, so we can extract the printer name from the current job
 531         javaPageFormatToNSPrintInfo(env, jthis, page, printInfo);
 532 
 533         // <rdar://problem/4093799> NSPrinterInfo is not correctly set to the selected printer
 534         // from the Java side of CPrinterJob. Had always assumed the default printer was the one we wanted.
 535         jobject printerNameObj = JNFCallObjectMethod(env, jthis, jm_getPrinterName);
 536         if (printerNameObj != NULL) {
 537             NSString *printerName = JNFJavaToNSString(env, printerNameObj);
 538             if (printerName != nil) {
 539                 NSPrinter *printer = [NSPrinter printerWithName:printerName];
 540                 if (printer != nil) [printInfo setPrinter:printer];
 541             }
 542         }
 543 
 544         PrintModel* printModel = [[PrintModel alloc] initWithPrintInfo:printInfo];
 545 
 546         (void)[printModel runPrintLoopWithView:printerView waitUntilDone:blocks withEnv:env];
 547 
 548         // Only set this if we got far enough to call runPrintLoopWithView, or we will spin CPrinterJob.print() forever!
 549         retVal = JNI_TRUE;
 550 
 551         [printModel release];
 552         [printerView release];
 553 
 554         if (page != NULL)
 555         {
 556             (*env)->DeleteLocalRef(env, page);
 557         }
 558 
 559         if (pageFormatArea != NULL)
 560         {
 561             (*env)->DeleteLocalRef(env, pageFormatArea);
 562         }
 563     }
 564 JNF_COCOA_EXIT(env);
 565     return retVal;
 566 }
 567 
 568 /*
 569  * Class:     sun_lwawt_macosx_CPrinterPageDialog
 570  * Method:    showDialog
 571  * Signature: ()Z
 572  */
 573 JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_CPrinterPageDialog_showDialog
 574   (JNIEnv *env, jobject jthis)
 575 {
 576 
 577     static JNF_CLASS_CACHE(jc_CPrinterPageDialog, "sun/lwawt/macosx/CPrinterPageDialog");
 578     static JNF_MEMBER_CACHE(jm_page, jc_CPrinterPageDialog, "fPage", "Ljava/awt/print/PageFormat;");
 579 
 580     jboolean result = JNI_FALSE;
 581 JNF_COCOA_ENTER(env);
 582     jobject printerJob = JNFGetObjectField(env, jthis, sjm_printerJob);
 583     NSPrintInfo* printInfo = (NSPrintInfo*)jlong_to_ptr(JNFCallLongMethod(env, printerJob, sjm_getNSPrintInfo)); // AWT_THREADING Safe (known object)
 584 
 585     jobject page = JNFGetObjectField(env, jthis, jm_page);
 586 
 587     // <rdar://problem/4156975> passing NULL, because only a CPrinterJob has a real printer associated with it
 588     javaPageFormatToNSPrintInfo(env, NULL, page, printInfo);
 589 
 590     PrintModel* printModel = [[PrintModel alloc] initWithPrintInfo:printInfo];
 591     result = [printModel runPageSetup];
 592     [printModel release];
 593 
 594     if (result)
 595     {
 596         nsPrintInfoToJavaPageFormat(env, printInfo, page);
 597     }
 598 
 599     if (printerJob != NULL)
 600     {
 601         (*env)->DeleteLocalRef(env, printerJob);
 602     }
 603 
 604     if (page != NULL)
 605     {
 606         (*env)->DeleteLocalRef(env, page);
 607     }
 608 
 609 JNF_COCOA_EXIT(env);
 610     return result;
 611 }
 612 
 613 /*
 614  * Class:     sun_lwawt_macosx_CPrinterJobDialog
 615  * Method:    showDialog
 616  * Signature: ()Z
 617  */
 618 JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_CPrinterJobDialog_showDialog
 619   (JNIEnv *env, jobject jthis)
 620 {
 621     static JNF_CLASS_CACHE(jc_CPrinterJobDialog, "sun/lwawt/macosx/CPrinterJobDialog");
 622     static JNF_MEMBER_CACHE(jm_pageable, jc_CPrinterJobDialog, "fPageable", "Ljava/awt/print/Pageable;");
 623 
 624     jboolean result = JNI_FALSE;
 625 JNF_COCOA_ENTER(env);
 626     jobject printerJob = JNFGetObjectField(env, jthis, sjm_printerJob);
 627     NSPrintInfo* printInfo = (NSPrintInfo*)jlong_to_ptr(JNFCallLongMethod(env, printerJob, sjm_getNSPrintInfo)); // AWT_THREADING Safe (known object)
 628 
 629     jobject pageable = JNFGetObjectField(env, jthis, jm_pageable);
 630 
 631     javaPrinterJobToNSPrintInfo(env, printerJob, pageable, printInfo);
 632 
 633     PrintModel* printModel = [[PrintModel alloc] initWithPrintInfo:printInfo];
 634     result = [printModel runJobSetup];
 635     [printModel release];
 636 
 637     if (result)
 638     {
 639         nsPrintInfoToJavaPrinterJob(env, printInfo, printerJob, pageable);
 640     }
 641 
 642     if (printerJob != NULL)
 643     {
 644         (*env)->DeleteLocalRef(env, printerJob);
 645     }
 646 
 647     if (pageable != NULL)
 648     {
 649         (*env)->DeleteLocalRef(env, pageable);
 650     }
 651 
 652 JNF_COCOA_EXIT(env);
 653     return result;
 654 }