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