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