提交 e6e654b9 编写于 作者: A alexsch

8040279: [macosx] Do not use the base image in the MultiResolutionBufferedImage

Reviewed-by: serb, pchelko
上级 717c5e10
......@@ -46,10 +46,8 @@ import com.apple.laf.AquaIcon.JRSUIControlSpec;
import com.apple.laf.AquaIcon.SystemIcon;
import com.apple.laf.AquaUtils.RecyclableObject;
import com.apple.laf.AquaUtils.RecyclableSingleton;
import java.util.Arrays;
import java.util.List;
import sun.awt.image.MultiResolutionBufferedImage;
import sun.awt.image.MultiResolutionImage;
import sun.awt.image.MultiResolutionCachedImage;
public class AquaImageFactory {
public static IconUIResource getConfirmImageIcon() {
......@@ -107,9 +105,9 @@ public class AquaImageFactory {
private static final int kAlertIconSize = 64;
static IconUIResource getAppIconCompositedOn(final Image background) {
if (background instanceof MultiResolutionBufferedImage) {
if (background instanceof MultiResolutionCachedImage) {
int width = background.getWidth(null);
Image mrIconImage = ((MultiResolutionBufferedImage) background).map(
Image mrIconImage = ((MultiResolutionCachedImage) background).map(
rv -> getAppIconImageCompositedOn(rv, rv.getWidth(null) / width));
return new IconUIResource(new ImageIcon(mrIconImage));
}
......@@ -287,23 +285,9 @@ public class AquaImageFactory {
private static Image getNSIcon(String imageName) {
Image icon = Toolkit.getDefaultToolkit()
.getImage("NSImage://" + imageName);
if (icon instanceof MultiResolutionImage) {
return icon;
}
int w = icon.getWidth(null);
int h = icon.getHeight(null);
Dimension[] sizes = new Dimension[]{
new Dimension(w, h), new Dimension(2 * w, 2 * h)
};
return new MultiResolutionBufferedImage(icon, sizes, (width, height) ->
AquaUtils.getCImageCreator().createImageFromName(
imageName, width, height));
}
public static class NineSliceMetrics {
public final int wCut, eCut, nCut, sCut;
public final int minW, minH;
......
......@@ -174,11 +174,7 @@ abstract class AquaPainter <T extends JRSUIState> {
bounds, controlState);
Image img = cache.getImage(key);
if (img == null) {
Image baseImage = createImage(imgX, imgY, imgW, imgH, bounds,
control, controlState);
img = new MultiResolutionBufferedImage(baseImage,
img = new MultiResolutionCachedImage(imgW, imgH,
(rvWidth, rvHeight) -> createImage(imgX, imgY,
rvWidth, rvHeight, bounds, control, controlState));
......
......@@ -48,7 +48,7 @@ import sun.security.action.GetPropertyAction;
import sun.swing.SwingUtilities2;
import com.apple.laf.AquaImageFactory.SlicedImageControl;
import sun.awt.image.MultiResolutionBufferedImage;
import sun.awt.image.MultiResolutionCachedImage;
final class AquaUtils {
......@@ -124,8 +124,8 @@ final class AquaUtils {
static Image generateLightenedImage(final Image image, final int percent) {
final GrayFilter filter = new GrayFilter(true, percent);
return (image instanceof MultiResolutionBufferedImage)
? ((MultiResolutionBufferedImage) image).map(
return (image instanceof MultiResolutionCachedImage)
? ((MultiResolutionCachedImage) image).map(
rv -> generateLightenedImage(rv, filter))
: generateLightenedImage(image, filter);
}
......
......@@ -32,7 +32,7 @@ import java.awt.image.*;
import java.util.Arrays;
import java.util.List;
import sun.awt.image.MultiResolutionImage;
import sun.awt.image.MultiResolutionBufferedImage;
import sun.awt.image.MultiResolutionCachedImage;
import sun.awt.image.SunWritableRaster;
......@@ -60,41 +60,41 @@ public class CImage extends CFRetainedResource {
// This is used to create a CImage with an NSImage pointer. It MUST be a CFRetained
// NSImage, and the CImage takes ownership of the non-GC retain. If callers need the
// NSImage themselves, they MUST call retain on the NSImage themselves.
public BufferedImage createImageUsingNativeSize(final long image) {
public Image createImageUsingNativeSize(final long image) {
if (image == 0) return null;
final Dimension2D size = nativeGetNSImageSize(image);
return createBufferedImage(image, size.getWidth(), size.getHeight());
return createImage(image, size.getWidth(), size.getHeight());
}
// the width and height passed in as a parameter could differ than the width and the height of the NSImage (image), in that case, the image will be scaled
BufferedImage createBufferedImage(long image, double width, double height) {
Image createImage(long image, double width, double height) {
if (image == 0) throw new Error("Unable to instantiate CImage with null native image reference.");
return createImageWithSize(image, width, height);
}
public BufferedImage createImageWithSize(final long image, final double width, final double height) {
public Image createImageWithSize(final long image, final double width, final double height) {
final CImage img = new CImage(image);
img.resize(width, height);
return img.toImage();
}
// This is used to create a CImage that represents the icon of the given file.
public BufferedImage createImageOfFile(final String file, final int width, final int height) {
return createBufferedImage(nativeCreateNSImageOfFileFromLaunchServices(file), width, height);
public Image createImageOfFile(final String file, final int width, final int height) {
return createImage(nativeCreateNSImageOfFileFromLaunchServices(file), width, height);
}
public BufferedImage createImageFromFile(final String file, final double width, final double height) {
public Image createImageFromFile(final String file, final double width, final double height) {
final long image = nativeCreateNSImageFromFileContents(file);
nativeSetNSImageSize(image, width, height);
return createBufferedImage(image, width, height);
return createImage(image, width, height);
}
public BufferedImage createSystemImageFromSelector(final String iconSelector, final int width, final int height) {
return createBufferedImage(nativeCreateNSImageFromIconSelector(getSelectorAsInt(iconSelector)), width, height);
public Image createSystemImageFromSelector(final String iconSelector, final int width, final int height) {
return createImage(nativeCreateNSImageFromIconSelector(getSelectorAsInt(iconSelector)), width, height);
}
public Image createImageFromName(final String name, final int width, final int height) {
return createBufferedImage(nativeCreateNSImageFromImageName(name), width, height);
return createImage(nativeCreateNSImageFromImageName(name), width, height);
}
public Image createImageFromName(final String name) {
......@@ -213,7 +213,7 @@ public class CImage extends CFRetainedResource {
}
/** @return A MultiResolution image created from nsImagePtr, or null. */
private BufferedImage toImage() {
private Image toImage() {
if (ptr == 0) return null;
final Dimension2D size = nativeGetNSImageSize(ptr);
......@@ -224,11 +224,11 @@ public class CImage extends CFRetainedResource {
= nativeGetNSImageRepresentationSizes(ptr,
size.getWidth(), size.getHeight());
BufferedImage baseImage = toImage(w, h, w, h);
return sizes == null || sizes.length < 2 ? baseImage
: new MultiResolutionBufferedImage(baseImage, sizes,
(width, height) -> toImage(w, h, width, height));
return sizes == null || sizes.length < 2 ?
new MultiResolutionCachedImage(w, h, (width, height)
-> toImage(w, h, width, height))
: new MultiResolutionCachedImage(w, h, sizes, (width, height)
-> toImage(w, h, width, height));
}
private BufferedImage toImage(int srcWidth, int srcHeight, int dstWidth, int dstHeight) {
......
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.awt.image;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.*;
/**
* This class provides default implementations for the
* <code>MultiResolutionImage</code> interface. The developer needs only
* to subclass this abstract class and define the <code>getResolutionVariant</code>,
* <code>getResolutionVariants</code>, and <code>getBaseImage</code> methods.
*
*
* For example,
* {@code
* public class CustomMultiResolutionImage extends AbstractMultiResolutionImage {
*
* int baseImageIndex;
* Image[] resolutionVariants;
*
* public CustomMultiResolutionImage(int baseImageIndex,
* Image... resolutionVariants) {
* this.baseImageIndex = baseImageIndex;
* this.resolutionVariants = resolutionVariants;
* }
*
* @Override
* public Image getResolutionVariant(float logicalDPIX, float logicalDPIY,
* float baseImageWidth, float baseImageHeight,
* float destImageWidth, float destImageHeight) {
* // return a resolution variant based on the given logical DPI,
* // base image size, or destination image size
* }
*
* @Override
* public List<Image> getResolutionVariants() {
* return Arrays.asList(resolutionVariants);
* }
*
* protected Image getBaseImage() {
* return resolutionVariants[baseImageIndex];
* }
* }
* }
*
* @see java.awt.Image
* @see java.awt.image.MultiResolutionImage
*
*/
public abstract class AbstractMultiResolutionImage extends java.awt.Image
implements MultiResolutionImage {
/**
* @inheritDoc
*/
@Override
public int getWidth(ImageObserver observer) {
return getBaseImage().getWidth(null);
}
/**
* @inheritDoc
*/
@Override
public int getHeight(ImageObserver observer) {
return getBaseImage().getHeight(null);
}
/**
* @inheritDoc
*/
@Override
public ImageProducer getSource() {
return getBaseImage().getSource();
}
/**
* @inheritDoc
*/
@Override
public Graphics getGraphics() {
return getBaseImage().getGraphics();
}
/**
* @inheritDoc
*/
@Override
public Object getProperty(String name, ImageObserver observer) {
return getBaseImage().getProperty(name, observer);
}
/**
* @return base image
*/
protected abstract Image getBaseImage();
}
......@@ -26,9 +26,7 @@ package sun.awt.image;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.Graphics;
import java.awt.geom.Dimension2D;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import java.util.Arrays;
import java.util.List;
......@@ -36,50 +34,39 @@ import java.util.function.Function;
import java.util.function.BiFunction;
import java.util.stream.Collectors;
public class MultiResolutionBufferedImage extends BufferedImage
implements MultiResolutionImage {
public class MultiResolutionCachedImage extends AbstractMultiResolutionImage {
private final BiFunction<Integer, Integer, Image> mapper;
private final int baseImageWidth;
private final int baseImageHeight;
private final Dimension2D[] sizes;
private final BiFunction<Integer, Integer, Image> mapper;
private int availableInfo;
public MultiResolutionBufferedImage(Image baseImage,
public MultiResolutionCachedImage(int baseImageWidth, int baseImageHeight,
BiFunction<Integer, Integer, Image> mapper) {
this(baseImage, new Dimension[]{new Dimension(
baseImage.getWidth(null), baseImage.getHeight(null))
this(baseImageWidth, baseImageHeight, new Dimension[]{new Dimension(
baseImageWidth, baseImageHeight)
}, mapper);
}
public MultiResolutionBufferedImage(Image baseImage,
public MultiResolutionCachedImage(int baseImageWidth, int baseImageHeight,
Dimension2D[] sizes, BiFunction<Integer, Integer, Image> mapper) {
super(baseImage.getWidth(null), baseImage.getHeight(null),
BufferedImage.TYPE_INT_ARGB_PRE);
this.baseImageWidth = baseImageWidth;
this.baseImageHeight = baseImageHeight;
this.sizes = sizes;
this.mapper = mapper;
this.availableInfo = getInfo(baseImage);
Graphics g = getGraphics();
g.drawImage(baseImage, 0, 0, null);
g.dispose();
}
@Override
public Image getResolutionVariant(int width, int height) {
int baseWidth = getWidth();
int baseHeight = getHeight();
if (baseWidth == width && baseHeight == height) {
return this;
}
ImageCache cache = ImageCache.getInstance();
ImageCacheKey key = new ImageCacheKey(this, width, height);
Image resolutionVariant = cache.getImage(key);
if (resolutionVariant == null) {
resolutionVariant = mapper.apply(width, height);
cache.setImage(key, resolutionVariant);
preload(resolutionVariant, availableInfo);
}
preload(resolutionVariant, availableInfo);
return resolutionVariant;
}
......@@ -90,30 +77,39 @@ public class MultiResolutionBufferedImage extends BufferedImage
(int) size.getHeight())).collect(Collectors.toList());
}
public MultiResolutionBufferedImage map(Function<Image, Image> mapper) {
return new MultiResolutionBufferedImage(mapper.apply(this), sizes,
(width, height) ->
public MultiResolutionCachedImage map(Function<Image, Image> mapper) {
return new MultiResolutionCachedImage(baseImageWidth, baseImageHeight,
sizes, (width, height) ->
mapper.apply(getResolutionVariant(width, height)));
}
@Override
public int getWidth(ImageObserver observer) {
availableInfo |= ImageObserver.WIDTH;
updateInfo(observer, ImageObserver.WIDTH);
return super.getWidth(observer);
}
@Override
public int getHeight(ImageObserver observer) {
availableInfo |= ImageObserver.HEIGHT;
updateInfo(observer, ImageObserver.HEIGHT);
return super.getHeight(observer);
}
@Override
public Object getProperty(String name, ImageObserver observer) {
availableInfo |= ImageObserver.PROPERTIES;
updateInfo(observer, ImageObserver.PROPERTIES);
return super.getProperty(name, observer);
}
@Override
protected Image getBaseImage() {
return getResolutionVariant(baseImageWidth, baseImageHeight);
}
private void updateInfo(ImageObserver observer, int info) {
availableInfo |= (observer == null) ? ImageObserver.ALLBITS : info;
}
private static int getInfo(Image image) {
if (image instanceof ToolkitImage) {
return ((ToolkitImage) image).getImageRep().check(
......
......@@ -28,7 +28,7 @@ import javax.swing.JMenuBar;
import javax.swing.SwingUtilities;
/* @test
* @bug 8031573
* @bug 8031573 8040279
* @summary [macosx] Checkmarks of JCheckBoxMenuItems aren't rendered
* in high resolution on Retina
* @author Alexander Scherbatiy
......
......@@ -31,7 +31,7 @@ import sun.awt.OSInfo;
/**
* @test
* @bug 8024926
* @bug 8024926 8040279
* @summary [macosx] AquaIcon HiDPI support
* @author Alexander Scherbatiy
* @run applet/manual=yesno bug8024926.html
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册