Path: blob/master/src/java.desktop/macosx/native/libawt_lwawt/awt/CImage.m
41152 views
/*1* Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/24#import "jni_util.h"2526#import <Cocoa/Cocoa.h>2728#import "GeomUtilities.h"29#import "ThreadUtilities.h"3031#import "sun_lwawt_macosx_CImage.h"323334static void CImage_CopyArrayIntoNSImageRep35(jint *srcPixels, jint *dstPixels, int width, int height)36{37int x, y;38// TODO: test this on big endian systems (not sure if its correct)...39for (y = 0; y < height; y++) {40for (x = 0; x < width; x++) {41jint pix = srcPixels[x];42jint a = (pix >> 24) & 0xff;43jint r = (pix >> 16) & 0xff;44jint g = (pix >> 8) & 0xff;45jint b = (pix ) & 0xff;46dstPixels[x] = (b << 24) | (g << 16) | (r << 8) | a;47}48srcPixels += width; // TODO: use explicit scanStride49dstPixels += width;50}51}5253static void CImage_CopyNSImageIntoArray54(NSImage *srcImage, jint *dstPixels, NSRect fromRect, NSRect toRect)55{56int width = toRect.size.width;57int height = toRect.size.height;58CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();59CGContextRef cgRef = CGBitmapContextCreate(dstPixels, width, height,608, width * 4, colorspace,61kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host);62CGColorSpaceRelease(colorspace);63NSGraphicsContext *context = [NSGraphicsContext graphicsContextWithGraphicsPort:cgRef flipped:NO];64CGContextRelease(cgRef);65NSGraphicsContext *oldContext = [[NSGraphicsContext currentContext] retain];66[NSGraphicsContext setCurrentContext:context];67[srcImage drawInRect:toRect68fromRect:fromRect69operation:NSCompositeSourceOver70fraction:1.0];71[NSGraphicsContext setCurrentContext:oldContext];72[oldContext release];73}7475static NSBitmapImageRep* CImage_CreateImageRep(JNIEnv *env, jintArray buffer, jint width, jint height)76{77NSBitmapImageRep* imageRep = [[[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL78pixelsWide:width79pixelsHigh:height80bitsPerSample:881samplesPerPixel:482hasAlpha:YES83isPlanar:NO84colorSpaceName:NSDeviceRGBColorSpace85bitmapFormat:NSAlphaFirstBitmapFormat86bytesPerRow:width*4 // TODO: use explicit scanStride87bitsPerPixel:32] autorelease];8889jint *imgData = (jint *)[imageRep bitmapData];90if (imgData == NULL) return 0L;9192jint *src = (*env)->GetPrimitiveArrayCritical(env, buffer, NULL);93if (src == NULL) return 0L;9495CImage_CopyArrayIntoNSImageRep(src, imgData, width, height);9697(*env)->ReleasePrimitiveArrayCritical(env, buffer, src, JNI_ABORT);9899return imageRep;100}101102/*103* Class: sun_lwawt_macosx_CImage104* Method: nativeCreateNSImageFromArray105* Signature: ([III)J106*/107JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CImage_nativeCreateNSImageFromArray108(JNIEnv *env, jclass klass, jintArray buffer, jint width, jint height)109{110jlong result = 0L;111112JNI_COCOA_ENTER(env);113114NSBitmapImageRep* imageRep = CImage_CreateImageRep(env, buffer, width, height);115if (imageRep) {116NSImage *nsImage = [[NSImage alloc] initWithSize:NSMakeSize(width, height)];117[nsImage addRepresentation:imageRep];118result = ptr_to_jlong(nsImage);119}120121JNI_COCOA_EXIT(env);122123return result;124}125126/*127* Class: sun_lwawt_macosx_CImage128* Method: nativeCreateNSImageFromArrays129* Signature: ([[I[I[I)J130*/131JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CImage_nativeCreateNSImageFromArrays132(JNIEnv *env, jclass klass, jobjectArray buffers, jintArray widths, jintArray heights)133{134jlong result = 0L;135136JNI_COCOA_ENTER(env);137138jsize num = (*env)->GetArrayLength(env, buffers);139NSMutableArray * reps = [NSMutableArray arrayWithCapacity: num];140141jint * ws = (*env)->GetIntArrayElements(env, widths, NULL);142if (ws != NULL) {143jint * hs = (*env)->GetIntArrayElements(env, heights, NULL);144if (hs != NULL) {145jsize i;146for (i = 0; i < num; i++) {147jintArray buffer = (*env)->GetObjectArrayElement(env, buffers, i);148149NSBitmapImageRep* imageRep = CImage_CreateImageRep(env, buffer, ws[i], hs[i]);150if (imageRep) {151[reps addObject: imageRep];152}153}154155(*env)->ReleaseIntArrayElements(env, heights, hs, JNI_ABORT);156}157(*env)->ReleaseIntArrayElements(env, widths, ws, JNI_ABORT);158}159if ([reps count]) {160NSImage *nsImage = [[NSImage alloc] initWithSize:NSMakeSize(0, 0)];161[nsImage addRepresentations: reps];162result = ptr_to_jlong(nsImage);163}164165JNI_COCOA_EXIT(env);166167return result;168}169170/*171* Class: sun_lwawt_macosx_CImage172* Method: nativeCreateNSImageFromIconSelector173* Signature: (I)J174*/175JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CImage_nativeCreateNSImageFromIconSelector176(JNIEnv *env, jclass klass, jint selector)177{178NSImage *image = nil;179180JNI_COCOA_ENTER(env);181182IconRef iconRef;183if (noErr == GetIconRef(kOnSystemDisk, kSystemIconsCreator, selector, &iconRef)) {184image = [[NSImage alloc] initWithIconRef:iconRef];185ReleaseIconRef(iconRef);186}187188JNI_COCOA_EXIT(env);189190return ptr_to_jlong(image);191}192193/*194* Class: sun_lwawt_macosx_CImage195* Method: nativeCreateNSImageFromFileContents196* Signature: (Ljava/lang/String;)J197*/198JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CImage_nativeCreateNSImageFromFileContents199(JNIEnv *env, jclass klass, jstring file)200{201NSImage *image = nil;202203JNI_COCOA_ENTER(env);204205NSString *path = NormalizedPathNSStringFromJavaString(env, file);206image = [[NSImage alloc] initByReferencingFile:path];207208JNI_COCOA_EXIT(env);209210return ptr_to_jlong(image);211}212213/*214* Class: sun_lwawt_macosx_CImage215* Method: nativeCreateNSImageOfFileFromLaunchServices216* Signature: (Ljava/lang/String;)J217*/218JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CImage_nativeCreateNSImageOfFileFromLaunchServices219(JNIEnv *env, jclass klass, jstring file)220{221__block NSImage *image = nil;222223JNI_COCOA_ENTER(env);224225NSString *path = NormalizedPathNSStringFromJavaString(env, file);226[ThreadUtilities performOnMainThreadWaiting:YES block:^(){227image = [[[NSWorkspace sharedWorkspace] iconForFile:path] retain];228[image setScalesWhenResized:TRUE];229}];230231JNI_COCOA_EXIT(env);232233return ptr_to_jlong(image);234}235236/*237* Class: sun_lwawt_macosx_CImage238* Method: nativeCreateNSImageFromImageName239* Signature: (Ljava/lang/String;)J240*/241JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CImage_nativeCreateNSImageFromImageName242(JNIEnv *env, jclass klass, jstring name)243{244NSImage *image = nil;245246JNI_COCOA_ENTER(env);247248image = [[NSImage imageNamed:JavaStringToNSString(env, name)] retain];249250JNI_COCOA_EXIT(env);251252return ptr_to_jlong(image);253}254255/*256* Class: sun_lwawt_macosx_CImage257* Method: nativeCopyNSImageIntoArray258* Signature: (J[IIIII)V259*/260JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CImage_nativeCopyNSImageIntoArray261(JNIEnv *env, jclass klass, jlong nsImgPtr, jintArray buffer, jint sw, jint sh,262jint dw, jint dh)263{264JNI_COCOA_ENTER(env);265266NSImage *img = (NSImage *)jlong_to_ptr(nsImgPtr);267jint *dst = (*env)->GetPrimitiveArrayCritical(env, buffer, NULL);268if (dst) {269NSRect fromRect = NSMakeRect(0, 0, sw, sh);270NSRect toRect = NSMakeRect(0, 0, dw, dh);271CImage_CopyNSImageIntoArray(img, dst, fromRect, toRect);272(*env)->ReleasePrimitiveArrayCritical(env, buffer, dst, JNI_ABORT);273}274275JNI_COCOA_EXIT(env);276}277278/*279* Class: sun_lwawt_macosx_CImage280* Method: nativeGetNSImageSize281* Signature: (J)Ljava/awt/geom/Dimension2D;282*/283JNIEXPORT jobject JNICALL Java_sun_lwawt_macosx_CImage_nativeGetNSImageSize284(JNIEnv *env, jclass klass, jlong nsImgPtr)285{286jobject size = NULL;287288JNI_COCOA_ENTER(env);289290size = NSToJavaSize(env, [(NSImage *)jlong_to_ptr(nsImgPtr) size]);291292JNI_COCOA_EXIT(env);293294return size;295}296297/*298* Class: sun_lwawt_macosx_CImage299* Method: nativeSetNSImageSize300* Signature: (JDD)V301*/302JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CImage_nativeSetNSImageSize303(JNIEnv *env, jclass clazz, jlong image, jdouble w, jdouble h)304{305if (!image) return;306NSImage *i = (NSImage *)jlong_to_ptr(image);307308JNI_COCOA_ENTER(env);309310[i setScalesWhenResized:TRUE];311[i setSize:NSMakeSize(w, h)];312313JNI_COCOA_EXIT(env);314}315316/*317* Class: sun_lwawt_macosx_CImage318* Method: nativeResizeNSImageRepresentations319* Signature: (JDD)V320*/321JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CImage_nativeResizeNSImageRepresentations322(JNIEnv *env, jclass clazz, jlong image, jdouble w, jdouble h)323{324if (!image) return;325NSImage *i = (NSImage *)jlong_to_ptr(image);326327JNI_COCOA_ENTER(env);328329NSImageRep *imageRep = nil;330NSArray *imageRepresentations = [i representations];331NSEnumerator *imageEnumerator = [imageRepresentations objectEnumerator];332while ((imageRep = [imageEnumerator nextObject]) != nil) {333[imageRep setSize:NSMakeSize(w, h)];334}335336JNI_COCOA_EXIT(env);337}338339NSComparisonResult getOrder(BOOL order){340return (NSComparisonResult) (order ? NSOrderedAscending : NSOrderedDescending);341}342343/*344* Class: sun_lwawt_macosx_CImage345* Method: nativeGetNSImageRepresentationsCount346* Signature: (JDD)[Ljava/awt/geom/Dimension2D;347*/348JNIEXPORT jobjectArray JNICALL349Java_sun_lwawt_macosx_CImage_nativeGetNSImageRepresentationSizes350(JNIEnv *env, jclass clazz, jlong image, jdouble w, jdouble h)351{352if (!image) return NULL;353jobjectArray jreturnArray = NULL;354NSImage *img = (NSImage *)jlong_to_ptr(image);355356JNI_COCOA_ENTER(env);357358NSArray *imageRepresentations = [img representations];359if([imageRepresentations count] == 0){360return NULL;361}362363NSArray *sortedImageRepresentations = [imageRepresentations364sortedArrayUsingComparator: ^(id obj1, id obj2) {365366NSImageRep *imageRep1 = (NSImageRep *) obj1;367NSImageRep *imageRep2 = (NSImageRep *) obj2;368NSSize size1 = [imageRep1 size];369NSSize size2 = [imageRep2 size];370371if (NSEqualSizes(size1, size2)) {372return getOrder([imageRep1 pixelsWide] <= [imageRep2 pixelsWide] &&373[imageRep1 pixelsHigh] <= [imageRep2 pixelsHigh]);374}375376return getOrder(size1.width <= size2.width && size1.height <= size2.height);377}];378379NSMutableArray *sortedPixelSizes = [[[NSMutableArray alloc] init] autorelease];380NSSize lastSize = [[sortedImageRepresentations lastObject] size];381382NSUInteger i = [sortedImageRepresentations indexOfObjectPassingTest:383^BOOL(id obj, NSUInteger idx, BOOL *stop) {384NSSize imageRepSize = [obj size];385return (w <= imageRepSize.width && h <= imageRepSize.height)386|| NSEqualSizes(imageRepSize, lastSize);387}];388389NSUInteger count = [sortedImageRepresentations count];390i = (i == NSNotFound) ? count - 1 : i;391NSSize bestFitSize = [[sortedImageRepresentations objectAtIndex: i] size];392393for(; i < count; i++){394NSImageRep *imageRep = [sortedImageRepresentations objectAtIndex: i];395396if (!NSEqualSizes([imageRep size], bestFitSize)) {397break;398}399400NSSize pixelSize = NSMakeSize(401[imageRep pixelsWide], [imageRep pixelsHigh]);402[sortedPixelSizes addObject: [NSValue valueWithSize: pixelSize]];403}404405count = [sortedPixelSizes count];406DECLARE_CLASS_RETURN(jc_Dimension, "java/awt/Dimension", jreturnArray);407jreturnArray = (*env)->NewObjectArray(env, count, jc_Dimension, NULL);408CHECK_NULL_RETURN(jreturnArray, NULL);409410for(i = 0; i < count; i++){411NSSize pixelSize = [[sortedPixelSizes objectAtIndex: i] sizeValue];412413(*env)->SetObjectArrayElement(env, jreturnArray, i,414NSToJavaSize(env, pixelSize));415JNU_CHECK_EXCEPTION_RETURN(env, NULL);416}417418JNI_COCOA_EXIT(env);419420return jreturnArray;421}422423/*424* Class: sun_lwawt_macosx_CImage425* Method: nativeGetPlatformImageBytes426* Signature: ([III)[B427*/428JNIEXPORT jbyteArray JNICALL Java_sun_lwawt_macosx_CImage_nativeGetPlatformImageBytes429(JNIEnv *env, jclass klass, jintArray buffer, jint width, jint height)430{431jbyteArray result = 0L;432433JNI_COCOA_ENTER(env);434435NSBitmapImageRep* imageRep = CImage_CreateImageRep(env, buffer, width, height);436if (imageRep) {437NSData *tiffImage = [imageRep TIFFRepresentation];438jsize tiffSize = (jsize)[tiffImage length];439result = (*env)->NewByteArray(env, tiffSize);440CHECK_NULL_RETURN(result, nil);441jbyte *tiffData = (jbyte *)(*env)->GetPrimitiveArrayCritical(env, result, 0);442CHECK_NULL_RETURN(tiffData, nil);443[tiffImage getBytes:tiffData];444(*env)->ReleasePrimitiveArrayCritical(env, result, tiffData, 0);445}446447JNI_COCOA_EXIT(env);448449return result;450}451452/*453* Class: sun_lwawt_macosx_CImage454* Method: nativeCreateNSImageFromBytes455* Signature: ([B)J456*/457JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CImage_nativeCreateNSImageFromBytes458(JNIEnv *env, jclass klass, jbyteArray sourceData)459{460jlong result = 0L;461CHECK_NULL_RETURN(sourceData, 0L);462463JNI_COCOA_ENTER(env);464465jsize sourceSize = (*env)->GetArrayLength(env, sourceData);466if (sourceSize == 0) return 0L;467468jbyte *sourceBytes = (*env)->GetPrimitiveArrayCritical(env, sourceData, NULL);469CHECK_NULL_RETURN(sourceBytes, 0L);470NSData *rawData = [NSData dataWithBytes:sourceBytes length:sourceSize];471NSImage *newImage = [[NSImage alloc] initWithData:rawData];472473(*env)->ReleasePrimitiveArrayCritical(env, sourceData, sourceBytes, JNI_ABORT);474CHECK_NULL_RETURN(newImage, 0L);475476result = ptr_to_jlong(newImage);477JNI_COCOA_EXIT(env);478479return result;480}481482483