--- old/src/macosx/classes/sun/lwawt/macosx/CImage.java 2014-02-26 16:05:54.000000000 +0400 +++ new/src/macosx/classes/sun/lwawt/macosx/CImage.java 2014-02-26 16:05:53.000000000 +0400 @@ -32,6 +32,7 @@ import java.util.Arrays; import java.util.List; import sun.awt.image.MultiResolutionImage; +import sun.awt.image.MultiResolutionBufferedImage; import sun.awt.image.SunWritableRaster; @@ -42,10 +43,11 @@ private static native long nativeCreateNSImageOfFileFromLaunchServices(String file); private static native long nativeCreateNSImageFromImageName(String name); private static native long nativeCreateNSImageFromIconSelector(int selector); - private static native void nativeCopyNSImageIntoArray(long image, int[] buffer, int w, int h); + private static native void nativeCopyNSImageIntoArray(long image, int[] buffer, int sw, int sh, int dw, int dh); private static native Dimension2D nativeGetNSImageSize(long image); private static native void nativeSetNSImageSize(long image, double w, double h); private static native void nativeResizeNSImageRepresentations(long image, double w, double h); + private static native Dimension2D[] nativeGetNSImageRepresentationSizes(long image, double w, double h); static Creator creator = new Creator(); static Creator getCreator() { @@ -210,18 +212,43 @@ super(nsImagePtr, true); } - /** @return A BufferedImage created from nsImagePtr, or null. */ - public BufferedImage toImage() { + /** @return A MultiResolution image created from nsImagePtr, or null. */ + private BufferedImage toImage() { if (ptr == 0) return null; final Dimension2D size = nativeGetNSImageSize(ptr); final int w = (int)size.getWidth(); final int h = (int)size.getHeight(); - final BufferedImage bimg = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB_PRE); + Dimension2D[] sizes + = nativeGetNSImageRepresentationSizes(ptr, + size.getWidth(), size.getHeight()); + + if (sizes == null || sizes.length < 2) { + return toImage(w, h, w, h); + } + + BufferedImage[] images = new BufferedImage[sizes.length]; + int currentImageIndex = 0; + + for (int i = 0; i < sizes.length; i++) { + int imageRepWidth = (int) sizes[i].getWidth(); + int imageRepHeight = (int) sizes[i].getHeight(); + + if(imageRepHeight <= w && imageRepHeight <= h){ + currentImageIndex = i; + } + images[i] = toImage(w, h, imageRepWidth, imageRepHeight); + } + return new MultiResolutionBufferedImage(BufferedImage.TYPE_INT_ARGB_PRE, + currentImageIndex, images); + } + + private BufferedImage toImage(int srcWidth, int srcHeight, int dstWidth, int dstHeight) { + final BufferedImage bimg = new BufferedImage(dstWidth, dstHeight, BufferedImage.TYPE_INT_ARGB_PRE); final DataBufferInt dbi = (DataBufferInt)bimg.getRaster().getDataBuffer(); final int[] buffer = SunWritableRaster.stealData(dbi, 0); - nativeCopyNSImageIntoArray(ptr, buffer, w, h); + nativeCopyNSImageIntoArray(ptr, buffer, srcWidth, srcHeight, dstWidth, dstHeight); SunWritableRaster.markDirty(dbi); return bimg; } --- old/src/macosx/native/sun/awt/CImage.m 2014-02-26 16:05:56.000000000 +0400 +++ new/src/macosx/native/sun/awt/CImage.m 2014-02-26 16:05:56.000000000 +0400 @@ -52,8 +52,10 @@ } static void CImage_CopyNSImageIntoArray -(NSImage *srcImage, jint *dstPixels, int width, int height) +(NSImage *srcImage, jint *dstPixels, NSRect fromRect, NSRect toRect) { + int width = toRect.size.width; + int height = toRect.size.height; CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); CGContextRef cgRef = CGBitmapContextCreate(dstPixels, width, height, 8, width * 4, colorspace, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host); CGColorSpaceRelease(colorspace); @@ -61,9 +63,8 @@ CGContextRelease(cgRef); NSGraphicsContext *oldContext = [[NSGraphicsContext currentContext] retain]; [NSGraphicsContext setCurrentContext:context]; - NSRect rect = NSMakeRect(0, 0, width, height); - [srcImage drawInRect:rect - fromRect:rect + [srcImage drawInRect:toRect + fromRect:fromRect operation:NSCompositeSourceOver fraction:1.0]; [NSGraphicsContext setCurrentContext:oldContext]; @@ -266,17 +267,19 @@ /* * Class: sun_lwawt_macosx_CImage * Method: nativeCopyNSImageIntoArray - * Signature: (J[III)V + * Signature: (J[IIIII)V */ JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CImage_nativeCopyNSImageIntoArray -(JNIEnv *env, jclass klass, jlong nsImgPtr, jintArray buffer, jint w, jint h) +(JNIEnv *env, jclass klass, jlong nsImgPtr, jintArray buffer, jint sw, jint sh, jint dw, jint dh) { JNF_COCOA_ENTER(env); NSImage *img = (NSImage *)jlong_to_ptr(nsImgPtr); jint *dst = (*env)->GetPrimitiveArrayCritical(env, buffer, NULL); if (dst) { - CImage_CopyNSImageIntoArray(img, dst, w, h); + NSRect fromRect = NSMakeRect(0, 0, sw, sh); + NSRect toRect = NSMakeRect(0, 0, dw, dh); + CImage_CopyNSImageIntoArray(img, dst, fromRect, toRect); (*env)->ReleasePrimitiveArrayCritical(env, buffer, dst, JNI_ABORT); } @@ -343,3 +346,89 @@ JNF_COCOA_EXIT(env); } + +NSComparisonResult getOrder(BOOL order){ + return (NSComparisonResult) (order ? NSOrderedAscending : NSOrderedDescending); +} + +/* + * Class: sun_lwawt_macosx_CImage + * Method: nativeGetNSImageRepresentationsCount + * Signature: (JDD)[Ljava/awt/geom/Dimension2D; + */ +JNIEXPORT jobjectArray JNICALL Java_sun_lwawt_macosx_CImage_nativeGetNSImageRepresentationSizes +(JNIEnv *env, jclass clazz, jlong image, jdouble w, jdouble h) +{ + if (!image) return 0; + jobjectArray jreturnArray = NULL; + NSImage *img = (NSImage *)jlong_to_ptr(image); + +JNF_COCOA_ENTER(env); + + NSArray *imageRepresentations = [image representations]; + if([imageRepresentations count] == 0){ + return NULL; + } + + NSArray *sortedImageRepresentations = [imageRepresentations sortedArrayUsingComparator: ^(id obj1, id obj2) { + + NSImageRep *imageRep1 = (NSImageRep *) obj1; + NSImageRep *imageRep2 = (NSImageRep *) obj2; + NSSize size1 = [imageRep1 size]; + NSSize size2 = [imageRep2 size]; + + if (NSEqualSizes(size1, size2)) { + return getOrder([imageRep1 pixelsWide] <= [imageRep2 pixelsWide] && + [imageRep1 pixelsHigh] <= [imageRep2 pixelsHigh]); + } + + return getOrder(size1.width <= size2.width && size1.height <= size2.height); + }]; + + NSMutableArray *sortedPixelSizes = [[NSMutableArray alloc] init]; + NSSize lastSize = [[sortedImageRepresentations lastObject] size]; + NSSize imageRepSize = NSZeroSize; + + jsize i; + jsize count = [sortedImageRepresentations count]; + for(i = 0; i < count; i++){ + imageRepSize = [[sortedImageRepresentations objectAtIndex: i] size]; + + if ((w <= imageRepSize.width && h <= imageRepSize.height) + || NSEqualSizes(imageRepSize, lastSize)) { + break; + } + } + + NSSize bestFitSize = imageRepSize; + + for(; i < count; i++){ + NSImageRep *imageRep = [sortedImageRepresentations objectAtIndex: i]; + + if (!NSEqualSizes([imageRep size], bestFitSize)) { + break; + } + + NSSize pixelSize = NSMakeSize([imageRep pixelsWide], [imageRep pixelsHigh]); + [sortedPixelSizes addObject: [NSValue valueWithSize: pixelSize]]; + } + + count = [sortedPixelSizes count]; + static JNF_CLASS_CACHE(jc_Dimension, "java/awt/Dimension"); + jreturnArray = JNFNewObjectArray(env, &jc_Dimension, count); + + for(i = 0; i < count; i++){ + NSSize pixelSize = [[sortedPixelSizes objectAtIndex: i] sizeValue]; + + (*env)->SetObjectArrayElement(env, jreturnArray, i, NSToJavaSize(env, pixelSize)); + if ((*env)->ExceptionOccurred(env)) { + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + continue; + } + } + +JNF_COCOA_EXIT(env); + + return jreturnArray; +} \ No newline at end of file --- /dev/null 2014-02-26 16:05:59.000000000 +0400 +++ new/test/java/awt/image/MultiResolutionImage/NSImageToMultiResolutionImageTest.java 2014-02-26 16:05:59.000000000 +0400 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Image; +import java.awt.Toolkit; +import sun.awt.OSInfo; +import sun.awt.image.MultiResolutionImage; +/* + * @test + * @bug 8033534 + * @summary [macosx] Get MultiResolution image from native system + * @author Alexander Scherbatiy + * @run main NSImageToMultiResolutionImageTest + */ + +public class NSImageToMultiResolutionImageTest { + + public static void main(String[] args) throws Exception { + + if (OSInfo.getOSType() != OSInfo.OSType.MACOSX) { + return; + } + + String icon = "NSImage://NSApplicationIcon"; + final Image image = Toolkit.getDefaultToolkit().getImage(icon); + + if (!(image instanceof MultiResolutionImage)) { + throw new RuntimeException("Icon does not have resolution variants!"); + } + + MultiResolutionImage multiResolutionImage = (MultiResolutionImage) image; + + int width = 0; + int height = 0; + + for (Image resolutionVariant : multiResolutionImage.getResolutionVariants()) { + int rvWidth = resolutionVariant.getWidth(null); + int rvHeight = resolutionVariant.getHeight(null); + if (rvWidth < width || rvHeight < height) { + throw new RuntimeException("Resolution variants are not sorted!"); + } + width = rvWidth; + height = rvHeight; + } + } +}