blob: 0400f5e9cbb7fbebbcd83c4c7f99011c8bb0634a [file] [log] [blame]
/*
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#import "PrinterView.h"
#import "java_awt_print_Pageable.h"
#import "java_awt_print_PageFormat.h"
#import <JavaNativeFoundation/JavaNativeFoundation.h>
#import "ThreadUtilities.h"
#import "GeomUtilities.h"
static JNF_CLASS_CACHE(sjc_CPrinterJob, "sun/lwawt/macosx/CPrinterJob");
static JNF_CLASS_CACHE(sjc_PageFormat, "java/awt/print/PageFormat");
@implementation PrinterView
- (id)initWithFrame:(NSRect)aRect withEnv:(JNIEnv*)env withPrinterJob:(jobject)printerJob
{
self = [super initWithFrame:aRect];
if (self)
{
fPrinterJob = JNFNewGlobalRef(env, printerJob);
fCurPageFormat = NULL;
fCurPainter = NULL;
fCurPeekGraphics = NULL;
}
return self;
}
- (void)releaseReferences:(JNIEnv*)env
{
if (fCurPageFormat != NULL)
{
JNFDeleteGlobalRef(env, fCurPageFormat);
fCurPageFormat = NULL;
}
if (fCurPainter != NULL)
{
JNFDeleteGlobalRef(env, fCurPainter);
fCurPainter = NULL;
}
if (fCurPeekGraphics != NULL)
{
JNFDeleteGlobalRef(env, fCurPeekGraphics);
fCurPeekGraphics = NULL;
}
}
- (void)setFirstPage:(jint)firstPage lastPage:(jint)lastPage {
fFirstPage = firstPage;
fLastPage = lastPage;
}
- (void)drawRect:(NSRect)aRect
{
AWT_ASSERT_NOT_APPKIT_THREAD;
static JNF_MEMBER_CACHE(jm_printToPathGraphics, sjc_CPrinterJob, "printToPathGraphics", "(Lsun/print/PeekGraphics;Ljava/awt/print/PrinterJob;Ljava/awt/print/Printable;Ljava/awt/print/PageFormat;IJ)V");
// Create and draw into a new CPrinterGraphics with the current Context.
assert(fCurPageFormat != NULL);
assert(fCurPainter != NULL);
assert(fCurPeekGraphics != NULL);
JNIEnv* env = [ThreadUtilities getJNIEnvUncached];
if ([self cancelCheck:env])
{
[self releaseReferences:env];
return;
}
NSPrintOperation* printLoop = [NSPrintOperation currentOperation];
jint jPageIndex = [printLoop currentPage] - 1;
jlong context = ptr_to_jlong([printLoop context]);
CGContextRef cgRef = (CGContextRef)[[printLoop context] graphicsPort];
CGContextSaveGState(cgRef); //04/28/2004: state needs to be saved here due to addition of lazy state management
JNFCallVoidMethod(env, fPrinterJob, jm_printToPathGraphics, fCurPeekGraphics, fPrinterJob, fCurPainter, fCurPageFormat, jPageIndex, context); // AWT_THREADING Safe (AWTRunLoop)
CGContextRestoreGState(cgRef);
[self releaseReferences:env];
}
- (NSString*)printJobTitle
{
AWT_ASSERT_NOT_APPKIT_THREAD;
static JNF_MEMBER_CACHE(jm_getJobName, sjc_CPrinterJob, "getJobName", "()Ljava/lang/String;");
JNIEnv* env = [ThreadUtilities getJNIEnvUncached];
jobject o = JNFCallObjectMethod(env, fPrinterJob, jm_getJobName); // AWT_THREADING Safe (known object)
id result = JNFJavaToNSString(env, o);
(*env)->DeleteLocalRef(env, o);
return result;
}
- (BOOL)knowsPageRange:(NSRangePointer)aRange
{
AWT_ASSERT_NOT_APPKIT_THREAD;
JNIEnv* env = [ThreadUtilities getJNIEnvUncached];
if ([self cancelCheck:env])
{
return NO;
}
aRange->location = fFirstPage + 1;
if (fLastPage == java_awt_print_Pageable_UNKNOWN_NUMBER_OF_PAGES)
{
aRange->length = NSIntegerMax;
}
else
{
aRange->length = (fLastPage + 1) - fFirstPage;
}
return YES;
}
- (NSRect)rectForPage:(NSInteger)pageNumber
{
AWT_ASSERT_NOT_APPKIT_THREAD;
static JNF_MEMBER_CACHE(jm_getPageformatPrintablePeekgraphics, sjc_CPrinterJob, "getPageformatPrintablePeekgraphics", "(I)[Ljava/lang/Object;");
static JNF_MEMBER_CACHE(jm_printAndGetPageFormatArea, sjc_CPrinterJob, "printAndGetPageFormatArea", "(Ljava/awt/print/Printable;Ljava/awt/Graphics;Ljava/awt/print/PageFormat;I)Ljava/awt/geom/Rectangle2D;");
static JNF_MEMBER_CACHE(jm_getOrientation, sjc_PageFormat, "getOrientation", "()I");
// Assertions removed, and corresponding JNFDeleteGlobalRefs added, for radr://3962543
// Actual fix that will keep these assertions from being true is radr://3205462 ,
// which will hopefully be fixed by the blocking AppKit bug radr://3056694
//assert(fCurPageFormat == NULL);
//assert(fCurPainter == NULL);
//assert(fCurPeekGraphics == NULL);
JNIEnv* env = [ThreadUtilities getJNIEnvUncached];
if(fCurPageFormat != NULL) {
JNFDeleteGlobalRef(env, fCurPageFormat);
}
if(fCurPainter != NULL) {
JNFDeleteGlobalRef(env, fCurPainter);
}
if(fCurPeekGraphics != NULL) {
JNFDeleteGlobalRef(env, fCurPeekGraphics);
}
//+++gdb Check the pageNumber for validity (PageAttrs)
jint jPageNumber = pageNumber - 1;
NSRect result;
if ([self cancelCheck:env])
{
return NSZeroRect;
}
jobjectArray objectArray = JNFCallObjectMethod(env, fPrinterJob, jm_getPageformatPrintablePeekgraphics, jPageNumber); // AWT_THREADING Safe (AWTRunLoopMode)
if (objectArray != NULL) {
// Get references to the return objects -> PageFormat, Printable, PeekGraphics
// Cheat - we know we either got NULL or a 3 element array
jobject pageFormat = (*env)->GetObjectArrayElement(env, objectArray, 0);
fCurPageFormat = JNFNewGlobalRef(env, pageFormat);
(*env)->DeleteLocalRef(env, pageFormat);
jobject painter = (*env)->GetObjectArrayElement(env, objectArray, 1);
fCurPainter = JNFNewGlobalRef(env, painter);
(*env)->DeleteLocalRef(env, painter);
jobject peekGraphics = (*env)->GetObjectArrayElement(env, objectArray, 2);
fCurPeekGraphics = JNFNewGlobalRef(env, peekGraphics);
(*env)->DeleteLocalRef(env, peekGraphics);
// Actually print and get the PageFormatArea
jobject pageFormatArea = JNFCallObjectMethod(env, fPrinterJob, jm_printAndGetPageFormatArea, fCurPainter, fCurPeekGraphics, fCurPageFormat, jPageNumber); // AWT_THREADING Safe (AWTRunLoopMode)
if (pageFormatArea != NULL) {
NSPrintingOrientation currentOrientation =
[[[NSPrintOperation currentOperation] printInfo] orientation];
// set page orientation
switch (JNFCallIntMethod(env, fCurPageFormat, jm_getOrientation)) {
case java_awt_print_PageFormat_PORTRAIT:
default:
if (currentOrientation != NSPortraitOrientation) {
[[[NSPrintOperation currentOperation] printInfo]
setOrientation:NSPortraitOrientation];
}
break;
case java_awt_print_PageFormat_LANDSCAPE:
case java_awt_print_PageFormat_REVERSE_LANDSCAPE:
if (currentOrientation != NSLandscapeOrientation) {
[[[NSPrintOperation currentOperation] printInfo]
setOrientation:NSLandscapeOrientation];
}
break;
}
result = JavaToNSRect(env, pageFormatArea);
(*env)->DeleteLocalRef(env, pageFormatArea);
} else {
[self releaseReferences:env];
result = NSZeroRect;
}
(*env)->DeleteLocalRef(env, objectArray);
} else {
[self releaseReferences:env];
result = NSZeroRect;
}
return result;
}
- (BOOL)cancelCheck:(JNIEnv*)env
{
AWT_ASSERT_NOT_APPKIT_THREAD;
static JNF_MEMBER_CACHE(jm_cancelCheck, sjc_CPrinterJob, "cancelCheck", "()Z");
return JNFCallBooleanMethod(env, fPrinterJob, jm_cancelCheck); // AWT_THREADING Safe (known object)
}
// This is called by -[PrintModel safePrintLoop]
- (void)complete:(JNIEnv*)env
{
AWT_ASSERT_NOT_APPKIT_THREAD;
static JNF_MEMBER_CACHE(jf_completePrintLoop, sjc_CPrinterJob, "completePrintLoop", "()V");
JNFCallVoidMethod(env, fPrinterJob, jf_completePrintLoop);
// Clean up after ourselves
// Can't put these into -dealloc since that happens (potentially) after the JNIEnv is stale
[self releaseReferences:env];
if (fPrinterJob != NULL)
{
JNFDeleteGlobalRef(env, fPrinterJob);
fPrinterJob = NULL;
}
}
- (BOOL)isFlipped
{
return TRUE;
}
@end