1 /* 2 * Copyright (c) 2011, 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 #import "PrinterView.h" 27 28 #import "java_awt_print_Pageable.h" 29 #import "java_awt_print_Printable.h" 30 #import "java_awt_print_PageFormat.h" 31 32 #import <JavaNativeFoundation/JavaNativeFoundation.h> 33 34 #import "ThreadUtilities.h" 35 #import "GeomUtilities.h" 36 37 38 static JNF_CLASS_CACHE(sjc_CPrinterJob, "sun/lwawt/macosx/CPrinterJob"); 39 static JNF_CLASS_CACHE(sjc_PageFormat, "java/awt/print/PageFormat"); 40 41 @implementation PrinterView 42 43 - (id)initWithFrame:(NSRect)aRect withEnv:(JNIEnv*)env withPrinterJob:(jobject)printerJob 44 { 45 self = [super initWithFrame:aRect]; 46 if (self) 47 { 48 fPrinterJob = JNFNewGlobalRef(env, printerJob); 49 fCurPageFormat = NULL; 50 fCurPainter = NULL; 51 fCurPeekGraphics = NULL; 52 } 53 return self; 54 } 55 56 - (void)releaseReferences:(JNIEnv*)env 57 { 58 if (fCurPageFormat != NULL) 59 { 60 JNFDeleteGlobalRef(env, fCurPageFormat); 61 fCurPageFormat = NULL; 62 } 63 if (fCurPainter != NULL) 64 { 65 JNFDeleteGlobalRef(env, fCurPainter); 66 fCurPainter = NULL; 67 } 68 if (fCurPeekGraphics != NULL) 69 { 70 JNFDeleteGlobalRef(env, fCurPeekGraphics); 71 fCurPeekGraphics = NULL; 72 } 73 } 74 75 - (void)setFirstPage:(jint)firstPage lastPage:(jint)lastPage { 76 fFirstPage = firstPage; 77 fLastPage = lastPage; 78 } 79 80 - (void)drawRect:(NSRect)aRect 81 { 82 AWT_ASSERT_NOT_APPKIT_THREAD; 83 84 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"); 85 86 // Create and draw into a new CPrinterGraphics with the current Context. 87 assert(fCurPageFormat != NULL); 88 assert(fCurPainter != NULL); 89 assert(fCurPeekGraphics != NULL); 90 91 JNIEnv* env = [ThreadUtilities getJNIEnvUncached]; 92 93 if ([self cancelCheck:env]) 94 { 95 [self releaseReferences:env]; 96 return; 97 } 98 99 NSPrintOperation* printLoop = [NSPrintOperation currentOperation]; 100 jint jPageIndex = [printLoop currentPage] - 1; 101 102 jlong context = ptr_to_jlong([printLoop context]); 103 CGContextRef cgRef = (CGContextRef)[[printLoop context] graphicsPort]; 104 CGContextSaveGState(cgRef); //04/28/2004: state needs to be saved here due to addition of lazy state management 105 106 JNFCallVoidMethod(env, fPrinterJob, jm_printToPathGraphics, fCurPeekGraphics, fPrinterJob, fCurPainter, fCurPageFormat, jPageIndex, context); // AWT_THREADING Safe (AWTRunLoop) 107 108 CGContextRestoreGState(cgRef); 109 110 [self releaseReferences:env]; 111 } 112 113 - (NSString*)printJobTitle 114 { 115 AWT_ASSERT_NOT_APPKIT_THREAD; 116 117 static JNF_MEMBER_CACHE(jm_getJobName, sjc_CPrinterJob, "getJobName", "()Ljava/lang/String;"); 118 119 JNIEnv* env = [ThreadUtilities getJNIEnvUncached]; 120 121 jobject o = JNFCallObjectMethod(env, fPrinterJob, jm_getJobName); // AWT_THREADING Safe (known object) 122 id result = JNFJavaToNSString(env, o); 123 (*env)->DeleteLocalRef(env, o); 124 return result; 125 } 126 127 - (BOOL)knowsPageRange:(NSRangePointer)aRange 128 { 129 AWT_ASSERT_NOT_APPKIT_THREAD; 130 131 JNIEnv* env = [ThreadUtilities getJNIEnvUncached]; 132 if ([self cancelCheck:env]) 133 { 134 return NO; 135 } 136 137 aRange->location = fFirstPage + 1; 138 139 if (fLastPage == java_awt_print_Pageable_UNKNOWN_NUMBER_OF_PAGES) 140 { 141 aRange->length = NSIntegerMax; 142 } 143 else 144 { 145 aRange->length = (fLastPage + 1) - fFirstPage; 146 } 147 148 return YES; 149 } 150 151 - (NSRect)rectForPage:(NSInteger)pageNumber 152 { 153 AWT_ASSERT_NOT_APPKIT_THREAD; 154 155 static JNF_MEMBER_CACHE(jm_getPageformatPrintablePeekgraphics, sjc_CPrinterJob, "getPageformatPrintablePeekgraphics", "(I)[Ljava/lang/Object;"); 156 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;"); 157 static JNF_MEMBER_CACHE(jm_getOrientation, sjc_PageFormat, "getOrientation", "()I"); 158 159 // Assertions removed, and corresponding JNFDeleteGlobalRefs added, for radr://3962543 160 // Actual fix that will keep these assertions from being true is radr://3205462 , 161 // which will hopefully be fixed by the blocking AppKit bug radr://3056694 162 //assert(fCurPageFormat == NULL); 163 //assert(fCurPainter == NULL); 164 //assert(fCurPeekGraphics == NULL); 165 166 JNIEnv* env = [ThreadUtilities getJNIEnvUncached]; 167 if(fCurPageFormat != NULL) { 168 JNFDeleteGlobalRef(env, fCurPageFormat); 169 } 170 if(fCurPainter != NULL) { 171 JNFDeleteGlobalRef(env, fCurPainter); 172 } 173 if(fCurPeekGraphics != NULL) { 174 JNFDeleteGlobalRef(env, fCurPeekGraphics); 175 } 176 177 //+++gdb Check the pageNumber for validity (PageAttrs) 178 179 jint jPageNumber = pageNumber - 1; 180 181 NSRect result; 182 183 if ([self cancelCheck:env]) 184 { 185 return NSZeroRect; 186 } 187 188 jobjectArray objectArray = JNFCallObjectMethod(env, fPrinterJob, jm_getPageformatPrintablePeekgraphics, jPageNumber); // AWT_THREADING Safe (AWTRunLoopMode) 189 if (objectArray != NULL) { 190 // Get references to the return objects -> PageFormat, Printable, PeekGraphics 191 // Cheat - we know we either got NULL or a 3 element array 192 jobject pageFormat = (*env)->GetObjectArrayElement(env, objectArray, 0); 193 fCurPageFormat = JNFNewGlobalRef(env, pageFormat); 194 (*env)->DeleteLocalRef(env, pageFormat); 195 196 jobject painter = (*env)->GetObjectArrayElement(env, objectArray, 1); 197 fCurPainter = JNFNewGlobalRef(env, painter); 198 (*env)->DeleteLocalRef(env, painter); 199 200 jobject peekGraphics = (*env)->GetObjectArrayElement(env, objectArray, 2); 201 fCurPeekGraphics = JNFNewGlobalRef(env, peekGraphics); 202 (*env)->DeleteLocalRef(env, peekGraphics); 203 204 // Actually print and get the PageFormatArea 205 jobject pageFormatArea = JNFCallObjectMethod(env, fPrinterJob, jm_printAndGetPageFormatArea, fCurPainter, fCurPeekGraphics, fCurPageFormat, jPageNumber); // AWT_THREADING Safe (AWTRunLoopMode) 206 if (pageFormatArea != NULL) { 207 NSPrintingOrientation currentOrientation = 208 [[[NSPrintOperation currentOperation] printInfo] orientation]; 209 // set page orientation 210 switch (JNFCallIntMethod(env, fCurPageFormat, jm_getOrientation)) { 211 case java_awt_print_PageFormat_PORTRAIT: 212 default: 213 if (currentOrientation != NSPortraitOrientation) { 214 [[[NSPrintOperation currentOperation] printInfo] 215 setOrientation:NSPortraitOrientation]; 216 } 217 break; 218 219 case java_awt_print_PageFormat_LANDSCAPE: 220 case java_awt_print_PageFormat_REVERSE_LANDSCAPE: 221 if (currentOrientation != NSLandscapeOrientation) { 222 [[[NSPrintOperation currentOperation] printInfo] 223 setOrientation:NSLandscapeOrientation]; 224 } 225 break; 226 } 227 result = JavaToNSRect(env, pageFormatArea); 228 (*env)->DeleteLocalRef(env, pageFormatArea); 229 } else { 230 [self releaseReferences:env]; 231 result = NSZeroRect; 232 } 233 234 (*env)->DeleteLocalRef(env, objectArray); 235 } else { 236 [self releaseReferences:env]; 237 result = NSZeroRect; 238 } 239 240 return result; 241 } 242 243 - (BOOL)cancelCheck:(JNIEnv*)env 244 { 245 AWT_ASSERT_NOT_APPKIT_THREAD; 246 247 static JNF_MEMBER_CACHE(jm_cancelCheck, sjc_CPrinterJob, "cancelCheck", "()Z"); 248 249 return JNFCallBooleanMethod(env, fPrinterJob, jm_cancelCheck); // AWT_THREADING Safe (known object) 250 } 251 252 // This is called by -[PrintModel safePrintLoop] 253 - (void)complete:(JNIEnv*)env 254 { 255 AWT_ASSERT_NOT_APPKIT_THREAD; 256 257 static JNF_MEMBER_CACHE(jf_completePrintLoop, sjc_CPrinterJob, "completePrintLoop", "()V"); 258 JNFCallVoidMethod(env, fPrinterJob, jf_completePrintLoop); 259 260 // Clean up after ourselves 261 // Can't put these into -dealloc since that happens (potentially) after the JNIEnv is stale 262 [self releaseReferences:env]; 263 if (fPrinterJob != NULL) 264 { 265 JNFDeleteGlobalRef(env, fPrinterJob); 266 fPrinterJob = NULL; 267 } 268 } 269 270 - (BOOL)isFlipped 271 { 272 return TRUE; 273 } 274 275 @end