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 112 NSBitmapImageRep* imageRep = CImage_CreateImageRep(env, buffer, width, height); 113 if (imageRep) { 114 NSImage *nsImage = [[NSImage alloc] initWithSize:NSMakeSize(width, height)]; 115 [nsImage addRepresentation:imageRep]; 116 [imageRep release]; 117 118 if (nsImage != nil) { 119 CFRetain(nsImage); // GC 120 } 121 122 result = ptr_to_jlong(nsImage); 123 } 124 125 JNF_COCOA_EXIT(env); 126 127 return result; 128 } 129 130 /* 131 * Class: sun_lwawt_macosx_CImage 132 * Method: nativeCreateNSImageFromArrays 133 * Signature: ([[I[I[I)J 134 */ 135 JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CImage_nativeCreateNSImageFromArrays 136 (JNIEnv *env, jclass klass, jobjectArray buffers, jintArray widths, jintArray heights) 137 { 138 jlong result = 0L; 139 140 JNF_COCOA_ENTER(env); 141 142 jsize num = (*env)->GetArrayLength(env, buffers); 143 NSMutableArray * reps = [NSMutableArray arrayWithCapacity: num]; 144 145 jint * ws = (*env)->GetIntArrayElements(env, widths, NULL); 146 jint * hs = (*env)->GetIntArrayElements(env, heights, NULL); 147 148 jsize i; 149 for (i = 0; i < num; i++) { 150 jintArray buffer = (*env)->GetObjectArrayElement(env, buffers, i); 151 152 NSBitmapImageRep* imageRep = CImage_CreateImageRep(env, buffer, ws[i], hs[i]); 153 if (imageRep) { 154 [reps addObject: imageRep]; 155 } 156 } 157 158 (*env)->ReleaseIntArrayElements(env, heights, hs, JNI_ABORT); 159 (*env)->ReleaseIntArrayElements(env, widths, ws, JNI_ABORT); 160 161 if ([reps count]) { 162 NSImage *nsImage = [[NSImage alloc] initWithSize:NSMakeSize(0, 0)]; 163 [nsImage addRepresentations: reps]; 164 165 if (nsImage != nil) { 166 CFRetain(nsImage); // GC 167 } 168 169 result = ptr_to_jlong(nsImage); 170 } 171 172 JNF_COCOA_EXIT(env); 173 174 return result; 175 } 176 177 /* 178 * Class: sun_lwawt_macosx_CImage 179 * Method: nativeCreateNSImageFromIconSelector 180 * Signature: (I)J 181 */ 182 JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CImage_nativeCreateNSImageFromIconSelector 183 (JNIEnv *env, jclass klass, jint selector) 184 { 185 NSImage *image = nil; 186 187 JNF_COCOA_ENTER(env); 188 189 IconRef iconRef; 190 if (noErr == GetIconRef(kOnSystemDisk, kSystemIconsCreator, selector, &iconRef)) { 191 image = [[NSImage alloc] initWithIconRef:iconRef]; 192 if (image) CFRetain(image); // GC 193 ReleaseIconRef(iconRef); 194 } 195 196 JNF_COCOA_EXIT(env); 197 198 return ptr_to_jlong(image); 199 } 200 201 /* 202 * Class: sun_lwawt_macosx_CImage 203 * Method: nativeCreateNSImageFromFileContents 204 * Signature: (Ljava/lang/String;)J 205 */ 206 JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CImage_nativeCreateNSImageFromFileContents 207 (JNIEnv *env, jclass klass, jstring file) 208 { 209 NSImage *image = nil; 210 211 JNF_COCOA_ENTER(env); 212 213 NSString *path = JNFNormalizedNSStringForPath(env, file); 214 image = [[NSImage alloc] initByReferencingFile:path]; 215 if (image) CFRetain(image); // GC 216 217 JNF_COCOA_EXIT(env); 218 219 return ptr_to_jlong(image); 220 } 221 222 /* 223 * Class: sun_lwawt_macosx_CImage 224 * Method: nativeCreateNSImageOfFileFromLaunchServices 225 * Signature: (Ljava/lang/String;)J 226 */ 227 JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CImage_nativeCreateNSImageOfFileFromLaunchServices 228 (JNIEnv *env, jclass klass, jstring file) 229 { 230 __block NSImage *image = nil; 231 232 JNF_COCOA_ENTER(env); 233 234 NSString *path = JNFNormalizedNSStringForPath(env, file); 235 [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ 236 image = [[NSWorkspace sharedWorkspace] iconForFile:path]; 237 [image setScalesWhenResized:TRUE]; 238 if (image) CFRetain(image); // GC 239 }]; 240 241 JNF_COCOA_EXIT(env); 242 243 return ptr_to_jlong(image); 244 } 245 246 /* 247 * Class: sun_lwawt_macosx_CImage 248 * Method: nativeCreateNSImageFromImageName 249 * Signature: (Ljava/lang/String;)J 250 */ 251 JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CImage_nativeCreateNSImageFromImageName 252 (JNIEnv *env, jclass klass, jstring name) 253 { 254 NSImage *image = nil; 255 256 JNF_COCOA_ENTER(env); 257 258 image = [NSImage imageNamed:JNFJavaToNSString(env, name)]; 259 if (image) CFRetain(image); // GC 260 261 JNF_COCOA_EXIT(env); 262 263 return ptr_to_jlong(image); 264 } 265 266 /* 267 * Class: sun_lwawt_macosx_CImage 268 * Method: nativeCopyNSImageIntoArray 269 * Signature: (J[III)V 270 */ 271 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CImage_nativeCopyNSImageIntoArray 272 (JNIEnv *env, jclass klass, jlong nsImgPtr, jintArray buffer, jint w, jint h) 273 { 274 JNF_COCOA_ENTER(env); 275 276 NSImage *img = (NSImage *)jlong_to_ptr(nsImgPtr); 277 jint *dst = (*env)->GetPrimitiveArrayCritical(env, buffer, NULL); 278 if (dst) { 279 CImage_CopyNSImageIntoArray(img, dst, w, h); 280 (*env)->ReleasePrimitiveArrayCritical(env, buffer, dst, JNI_ABORT); 281 } 282 283 JNF_COCOA_EXIT(env); 284 } 285 286 /* 287 * Class: sun_lwawt_macosx_CImage 288 * Method: nativeGetNSImageSize 289 * Signature: (J)Ljava/awt/geom/Dimension2D; 290 */ 291 JNIEXPORT jobject JNICALL Java_sun_lwawt_macosx_CImage_nativeGetNSImageSize 292 (JNIEnv *env, jclass klass, jlong nsImgPtr) 293 { 294 jobject size = NULL; 295 296 JNF_COCOA_ENTER(env); 297 298 size = NSToJavaSize(env, [(NSImage *)jlong_to_ptr(nsImgPtr) size]); 299 300 JNF_COCOA_EXIT(env); 301 302 return size; 303 } 304 305 /* 306 * Class: sun_lwawt_macosx_CImage 307 * Method: nativeSetNSImageSize 308 * Signature: (JDD)V 309 */ 310 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CImage_nativeSetNSImageSize 311 (JNIEnv *env, jclass clazz, jlong image, jdouble w, jdouble h) 312 { 313 if (!image) return; 314 NSImage *i = (NSImage *)jlong_to_ptr(image); 315 316 JNF_COCOA_ENTER(env); 317 318 [i setScalesWhenResized:TRUE]; 319 [i setSize:NSMakeSize(w, h)]; 320 321 JNF_COCOA_EXIT(env); 322 }