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