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 <Cocoa/Cocoa.h> 27 #import <JavaNativeFoundation/JavaNativeFoundation.h> 28 29 #import "GeomUtilities.h" 30 #import "ThreadUtilities.h" 31 32 #import "sun_lwawt_macosx_CImage.h" 33 34 35 static void CImage_CopyArrayIntoNSImageRep 36 (jint *srcPixels, jint *dstPixels, int width, int height) 37 { 38 int x, y; 39 // TODO: test this on big endian systems (not sure if its correct)... 40 for (y = 0; y < height; y++) { 41 for (x = 0; x < width; x++) { 42 jint pix = srcPixels[x]; 43 jint a = (pix >> 24) & 0xff; 44 jint r = (pix >> 16) & 0xff; 45 jint g = (pix >> 8) & 0xff; 46 jint b = (pix ) & 0xff; 47 dstPixels[x] = (b << 24) | (g << 16) | (r << 8) | a; 48 } 49 srcPixels += width; // TODO: use explicit scanStride 50 dstPixels += width; 51 } 52 } 53 54 static void CImage_CopyNSImageIntoArray 55 (NSImage *srcImage, jint *dstPixels, int width, int height) 56 { 57 CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); 58 CGContextRef cgRef = CGBitmapContextCreate(dstPixels, width, height, 8, width * 4, colorspace, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host); 59 CGColorSpaceRelease(colorspace); 60 NSGraphicsContext *context = [NSGraphicsContext graphicsContextWithGraphicsPort:cgRef flipped:NO]; 61 CGContextRelease(cgRef); 62 NSGraphicsContext *oldContext = [[NSGraphicsContext currentContext] retain]; 63 [NSGraphicsContext setCurrentContext:context]; 64 NSRect rect = NSMakeRect(0, 0, width, height); 65 [srcImage drawInRect:rect 66 fromRect:rect 67 operation:NSCompositeSourceOver 68 fraction:1.0]; 69 [NSGraphicsContext setCurrentContext:oldContext]; 70 [oldContext release]; 71 } 72 73 static NSBitmapImageRep* CImage_CreateImageRep(JNIEnv *env, jintArray buffer, jint width, jint height) 74 { 75 NSBitmapImageRep* imageRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL 76 pixelsWide:width 77 pixelsHigh:height 78 bitsPerSample:8 79 samplesPerPixel:4 80 hasAlpha:YES 81 isPlanar:NO 82 colorSpaceName:NSDeviceRGBColorSpace 83 bitmapFormat:NSAlphaFirstBitmapFormat 84 bytesPerRow:width*4 // TODO: use explicit scanStride 85 bitsPerPixel:32]; 86 87 jint *imgData = (jint *)[imageRep bitmapData]; 88 if (imgData == NULL) return 0L; 89 90 jint *src = (*env)->GetPrimitiveArrayCritical(env, buffer, NULL); 91 if (src == NULL) return 0L; 92 93 CImage_CopyArrayIntoNSImageRep(src, imgData, width, height); 94 95 (*env)->ReleasePrimitiveArrayCritical(env, buffer, src, JNI_ABORT); 96 97 return imageRep; 98 } 99 100 /* 101 * Class: sun_lwawt_macosx_CImage 102 * Method: nativeCreateNSImageFromArray 103 * Signature: ([III)J 104 */ 105 JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CImage_nativeCreateNSImageFromArray 106 (JNIEnv *env, jclass klass, jintArray buffer, jint width, jint height) 107 { 108 jlong result = 0L; 109 110 JNF_COCOA_ENTER(env); 111 AWT_ASSERT_ANY_THREAD; 112 113 NSBitmapImageRep* imageRep = CImage_CreateImageRep(env, buffer, width, height); 114 if (imageRep) { 115 NSImage *nsImage = [[NSImage alloc] initWithSize:NSMakeSize(width, height)]; 116 [nsImage addRepresentation:imageRep]; 117 [imageRep release]; 118 119 if (nsImage != nil) { 120 CFRetain(nsImage); // GC 121 } 122 123 result = ptr_to_jlong(nsImage); 124 } 125 126 JNF_COCOA_EXIT(env); 127 128 return result; 129 } 130 131 /* 132 * Class: sun_lwawt_macosx_CImage 133 * Method: nativeCreateNSImageFromArrays 134 * Signature: ([[I[I[I)J 135 */ 136 JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CImage_nativeCreateNSImageFromArrays 137 (JNIEnv *env, jclass klass, jobjectArray buffers, jintArray widths, jintArray heights) 138 { 139 jlong result = 0L; 140 141 JNF_COCOA_ENTER(env); 142 AWT_ASSERT_ANY_THREAD; 143 144 jsize num = (*env)->GetArrayLength(env, buffers); 145 NSMutableArray * reps = [NSMutableArray arrayWithCapacity: num]; 146 147 jint * ws = (*env)->GetIntArrayElements(env, widths, NULL); 148 jint * hs = (*env)->GetIntArrayElements(env, heights, NULL); 149 150 jsize i; 151 for (i = 0; i < num; i++) { 152 jintArray buffer = (*env)->GetObjectArrayElement(env, buffers, i); 153 154 NSBitmapImageRep* imageRep = CImage_CreateImageRep(env, buffer, ws[i], hs[i]); 155 if (imageRep) { 156 [reps addObject: imageRep]; 157 } 158 } 159 160 (*env)->ReleaseIntArrayElements(env, heights, hs, JNI_ABORT); 161 (*env)->ReleaseIntArrayElements(env, widths, ws, JNI_ABORT); 162 163 if ([reps count]) { 164 NSImage *nsImage = [[NSImage alloc] initWithSize:NSMakeSize(0, 0)]; 165 [nsImage addRepresentations: reps]; 166 167 if (nsImage != nil) { 168 CFRetain(nsImage); // GC 169 } 170 171 result = ptr_to_jlong(nsImage); 172 } 173 174 JNF_COCOA_EXIT(env); 175 176 return result; 177 } 178 179 /* 180 * Class: sun_lwawt_macosx_CImage 181 * Method: nativeCreateNSImageFromIconSelector 182 * Signature: (I)J 183 */ 184 JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CImage_nativeCreateNSImageFromIconSelector 185 (JNIEnv *env, jclass klass, jint selector) 186 { 187 NSImage *image = nil; 188 189 JNF_COCOA_ENTER(env); 190 AWT_ASSERT_ANY_THREAD; 191 192 IconRef iconRef; 193 if (noErr == GetIconRef(kOnSystemDisk, kSystemIconsCreator, selector, &iconRef)) { 194 image = [[NSImage alloc] initWithIconRef:iconRef]; 195 if (image) CFRetain(image); // GC 196 ReleaseIconRef(iconRef); 197 } 198 199 JNF_COCOA_EXIT(env); 200 201 return ptr_to_jlong(image); 202 } 203 204 /* 205 * Class: sun_lwawt_macosx_CImage 206 * Method: nativeCreateNSImageFromFileContents 207 * Signature: (Ljava/lang/String;)J 208 */ 209 JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CImage_nativeCreateNSImageFromFileContents 210 (JNIEnv *env, jclass klass, jstring file) 211 { 212 NSImage *image = nil; 213 214 JNF_COCOA_ENTER(env); 215 AWT_ASSERT_ANY_THREAD; 216 217 NSString *path = JNFNormalizedNSStringForPath(env, file); 218 image = [[NSImage alloc] initByReferencingFile:path]; 219 if (image) CFRetain(image); // GC 220 221 JNF_COCOA_EXIT(env); 222 223 return ptr_to_jlong(image); 224 } 225 226 /* 227 * Class: sun_lwawt_macosx_CImage 228 * Method: nativeCreateNSImageOfFileFromLaunchServices 229 * Signature: (Ljava/lang/String;)J 230 */ 231 JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CImage_nativeCreateNSImageOfFileFromLaunchServices 232 (JNIEnv *env, jclass klass, jstring file) 233 { 234 __block NSImage *image = nil; 235 236 JNF_COCOA_ENTER(env); 237 AWT_ASSERT_ANY_THREAD; 238 239 NSString *path = JNFNormalizedNSStringForPath(env, file); 240 [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){ 241 image = [[NSWorkspace sharedWorkspace] iconForFile:path]; 242 [image setScalesWhenResized:TRUE]; 243 if (image) CFRetain(image); // GC 244 }]; 245 246 JNF_COCOA_EXIT(env); 247 248 return ptr_to_jlong(image); 249 } 250 251 /* 252 * Class: sun_lwawt_macosx_CImage 253 * Method: nativeCreateNSImageFromImageName 254 * Signature: (Ljava/lang/String;)J 255 */ 256 JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CImage_nativeCreateNSImageFromImageName 257 (JNIEnv *env, jclass klass, jstring name) 258 { 259 NSImage *image = nil; 260 261 JNF_COCOA_ENTER(env); 262 AWT_ASSERT_ANY_THREAD; 263 264 image = [NSImage imageNamed:JNFJavaToNSString(env, name)]; 265 if (image) CFRetain(image); // GC 266 267 JNF_COCOA_EXIT(env); 268 269 return ptr_to_jlong(image); 270 } 271 272 /* 273 * Class: sun_lwawt_macosx_CImage 274 * Method: nativeCopyNSImageIntoArray 275 * Signature: (J[III)V 276 */ 277 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CImage_nativeCopyNSImageIntoArray 278 (JNIEnv *env, jclass klass, jlong nsImgPtr, jintArray buffer, jint w, jint h) 279 { 280 JNF_COCOA_ENTER(env); 281 AWT_ASSERT_ANY_THREAD; 282 283 NSImage *img = (NSImage *)jlong_to_ptr(nsImgPtr); 284 jint *dst = (*env)->GetPrimitiveArrayCritical(env, buffer, NULL); 285 if (dst) { 286 CImage_CopyNSImageIntoArray(img, dst, w, h); 287 (*env)->ReleasePrimitiveArrayCritical(env, buffer, dst, JNI_ABORT); 288 } 289 290 JNF_COCOA_EXIT(env); 291 } 292 293 /* 294 * Class: sun_lwawt_macosx_CImage 295 * Method: nativeGetNSImageSize 296 * Signature: (J)Ljava/awt/geom/Dimension2D; 297 */ 298 JNIEXPORT jobject JNICALL Java_sun_lwawt_macosx_CImage_nativeGetNSImageSize 299 (JNIEnv *env, jclass klass, jlong nsImgPtr) 300 { 301 jobject size = NULL; 302 303 JNF_COCOA_ENTER(env); 304 AWT_ASSERT_ANY_THREAD; 305 306 size = NSToJavaSize(env, [(NSImage *)jlong_to_ptr(nsImgPtr) size]); 307 308 JNF_COCOA_EXIT(env); 309 310 return size; 311 } 312 313 /* 314 * Class: sun_lwawt_macosx_CImage 315 * Method: nativeSetNSImageSize 316 * Signature: (JDD)V 317 */ 318 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CImage_nativeSetNSImageSize 319 (JNIEnv *env, jclass clazz, jlong image, jdouble w, jdouble h) 320 { 321 if (!image) return; 322 NSImage *i = (NSImage *)jlong_to_ptr(image); 323 324 JNF_COCOA_ENTER(env); 325 326 [i setScalesWhenResized:TRUE]; 327 [i setSize:NSMakeSize(w, h)]; 328 329 JNF_COCOA_EXIT(env); 330 }