mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-05 13:40:18 +00:00
8151303: [macosx] [hidpi] JButton's low-res. icon is visible when clicking on it
8156182: [macosx] HiDPI/Retina icons do not work for disabled JButton/JMenuItem etc Reviewed-by: flar, prr
This commit is contained in:
parent
5390af7c2b
commit
966cbcfce3
@ -105,38 +105,44 @@ final class AquaUtils {
|
||||
}
|
||||
|
||||
static Image generateSelectedDarkImage(final Image image) {
|
||||
final ImageProducer prod = new FilteredImageSource(image.getSource(), new IconImageFilter() {
|
||||
final ImageFilter filter = new IconImageFilter() {
|
||||
@Override
|
||||
int getGreyFor(final int gray) {
|
||||
return gray * 75 / 100;
|
||||
}
|
||||
});
|
||||
return Toolkit.getDefaultToolkit().createImage(prod);
|
||||
};
|
||||
return map(image, filter);
|
||||
}
|
||||
|
||||
static Image generateDisabledImage(final Image image) {
|
||||
final ImageProducer prod = new FilteredImageSource(image.getSource(), new IconImageFilter() {
|
||||
final ImageFilter filter = new IconImageFilter() {
|
||||
@Override
|
||||
int getGreyFor(final int gray) {
|
||||
return 255 - ((255 - gray) * 65 / 100);
|
||||
}
|
||||
});
|
||||
return Toolkit.getDefaultToolkit().createImage(prod);
|
||||
};
|
||||
return map(image, filter);
|
||||
}
|
||||
|
||||
static Image generateLightenedImage(final Image image, final int percent) {
|
||||
final GrayFilter filter = new GrayFilter(true, percent);
|
||||
return (image instanceof MultiResolutionCachedImage)
|
||||
? ((MultiResolutionCachedImage) image).map(
|
||||
rv -> generateLightenedImage(rv, filter))
|
||||
: generateLightenedImage(image, filter);
|
||||
return map(image, filter);
|
||||
}
|
||||
|
||||
static Image generateLightenedImage(Image image, ImageFilter filter) {
|
||||
static Image generateFilteredImage(Image image, ImageFilter filter) {
|
||||
final ImageProducer prod = new FilteredImageSource(image.getSource(), filter);
|
||||
return Toolkit.getDefaultToolkit().createImage(prod);
|
||||
}
|
||||
|
||||
private static Image map(Image image, ImageFilter filter) {
|
||||
if (image instanceof MultiResolutionImage) {
|
||||
return MultiResolutionCachedImage
|
||||
.map((MultiResolutionImage) image,
|
||||
(img) -> generateFilteredImage(img, filter));
|
||||
}
|
||||
return generateFilteredImage(image, filter);
|
||||
}
|
||||
|
||||
private abstract static class IconImageFilter extends RGBImageFilter {
|
||||
IconImageFilter() {
|
||||
super();
|
||||
|
||||
@ -26,6 +26,7 @@ package javax.swing;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.*;
|
||||
import sun.awt.image.MultiResolutionCachedImage;
|
||||
|
||||
/**
|
||||
* An image filter that "disables" an image by turning
|
||||
@ -48,7 +49,16 @@ public class GrayFilter extends RGBImageFilter {
|
||||
* @param i an {@code Image} to be created as disabled
|
||||
* @return the new grayscale image created from {@code i}
|
||||
*/
|
||||
public static Image createDisabledImage (Image i) {
|
||||
public static Image createDisabledImage(Image i) {
|
||||
if (i instanceof MultiResolutionImage) {
|
||||
return MultiResolutionCachedImage
|
||||
.map((MultiResolutionImage) i,
|
||||
(img) -> createDisabledImageImpl(img));
|
||||
}
|
||||
return createDisabledImageImpl(i);
|
||||
}
|
||||
|
||||
private static Image createDisabledImageImpl(Image i) {
|
||||
GrayFilter filter = new GrayFilter(true, 50);
|
||||
ImageProducer prod = new FilteredImageSource(i.getSource(), filter);
|
||||
Image grayImage = Toolkit.getDefaultToolkit().createImage(prod);
|
||||
|
||||
@ -33,6 +33,7 @@ import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.stream.Collectors;
|
||||
import java.awt.image.MultiResolutionImage;
|
||||
import java.awt.image.AbstractMultiResolutionImage;
|
||||
|
||||
public class MultiResolutionCachedImage extends AbstractMultiResolutionImage {
|
||||
@ -44,17 +45,30 @@ public class MultiResolutionCachedImage extends AbstractMultiResolutionImage {
|
||||
private int availableInfo;
|
||||
|
||||
public MultiResolutionCachedImage(int baseImageWidth, int baseImageHeight,
|
||||
BiFunction<Integer, Integer, Image> mapper) {
|
||||
this(baseImageWidth, baseImageHeight, new Dimension[]{new Dimension(
|
||||
baseImageWidth, baseImageHeight)
|
||||
BiFunction<Integer, Integer, Image> mapper)
|
||||
{
|
||||
this(baseImageWidth, baseImageHeight,
|
||||
new Dimension[]{new Dimension( baseImageWidth, baseImageHeight)
|
||||
}, mapper);
|
||||
}
|
||||
|
||||
public MultiResolutionCachedImage(int baseImageWidth, int baseImageHeight,
|
||||
Dimension2D[] sizes, BiFunction<Integer, Integer, Image> mapper) {
|
||||
Dimension2D[] sizes,
|
||||
BiFunction<Integer, Integer, Image> mapper)
|
||||
{
|
||||
this(baseImageWidth, baseImageHeight, sizes, mapper, true);
|
||||
}
|
||||
|
||||
private MultiResolutionCachedImage(int baseImageWidth, int baseImageHeight,
|
||||
Dimension2D[] sizes,
|
||||
BiFunction<Integer, Integer, Image> mapper,
|
||||
boolean copySizes)
|
||||
{
|
||||
this.baseImageWidth = baseImageWidth;
|
||||
this.baseImageHeight = baseImageHeight;
|
||||
this.sizes = (sizes == null) ? null : Arrays.copyOf(sizes, sizes.length);
|
||||
this.sizes = (copySizes && sizes != null)
|
||||
? Arrays.copyOf(sizes, sizes.length)
|
||||
: sizes;
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
@ -99,6 +113,35 @@ public class MultiResolutionCachedImage extends AbstractMultiResolutionImage {
|
||||
mapper.apply(getResolutionVariant(width, height)));
|
||||
}
|
||||
|
||||
public static Image map(MultiResolutionImage mrImage,
|
||||
Function<Image, Image> mapper) {
|
||||
|
||||
if (mrImage instanceof MultiResolutionToolkitImage) {
|
||||
MultiResolutionToolkitImage mrtImage =
|
||||
(MultiResolutionToolkitImage) mrImage;
|
||||
return MultiResolutionToolkitImage.map(mrtImage, mapper);
|
||||
}
|
||||
|
||||
BiFunction<Integer, Integer, Image> sizeMapper
|
||||
= (w, h) -> mapper.apply(mrImage.getResolutionVariant(w, h));
|
||||
|
||||
if (mrImage instanceof MultiResolutionCachedImage) {
|
||||
MultiResolutionCachedImage mrcImage
|
||||
= (MultiResolutionCachedImage) mrImage;
|
||||
|
||||
return new MultiResolutionCachedImage(mrcImage.baseImageWidth,
|
||||
mrcImage.baseImageHeight,
|
||||
mrcImage.sizes,
|
||||
sizeMapper,
|
||||
false);
|
||||
}
|
||||
|
||||
Image image = (Image) mrImage;
|
||||
int width = image.getWidth(null);
|
||||
int height = image.getHeight(null);
|
||||
return new MultiResolutionCachedImage(width, height, sizeMapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWidth(ImageObserver observer) {
|
||||
updateInfo(observer, ImageObserver.WIDTH);
|
||||
|
||||
@ -29,6 +29,7 @@ import java.awt.image.ImageObserver;
|
||||
import java.awt.image.MultiResolutionImage;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import sun.awt.SoftCache;
|
||||
|
||||
public class MultiResolutionToolkitImage extends ToolkitImage implements MultiResolutionImage {
|
||||
@ -47,6 +48,13 @@ public class MultiResolutionToolkitImage extends ToolkitImage implements MultiRe
|
||||
? this : resolutionVariant;
|
||||
}
|
||||
|
||||
public static Image map(MultiResolutionToolkitImage mrImage,
|
||||
Function<Image, Image> mapper) {
|
||||
Image baseImage = mapper.apply(mrImage);
|
||||
Image rvImage = mapper.apply(mrImage.resolutionVariant);
|
||||
return new MultiResolutionToolkitImage(baseImage, rvImage);
|
||||
}
|
||||
|
||||
private static void checkSize(double width, double height) {
|
||||
if (width <= 0 || height <= 0) {
|
||||
throw new IllegalArgumentException(String.format(
|
||||
|
||||
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 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.Color;
|
||||
import java.awt.Frame;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
import java.awt.MediaTracker;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.image.BaseMultiResolutionImage;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.GrayFilter;
|
||||
import java.awt.image.MultiResolutionImage;
|
||||
import javax.swing.JLabel;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8156182
|
||||
* @summary [macosx] HiDPI/Retina icons do not work for disabled
|
||||
* JButton/JMenuItem etc.
|
||||
* @run main/othervm -Dsun.java2d.uiScale=2 MultiResolutionDisabledImageTest
|
||||
*/
|
||||
public class MultiResolutionDisabledImageTest {
|
||||
|
||||
private static final String IMAGE_NAME_1X = "image.png";
|
||||
private static final String IMAGE_NAME_2X = "image@2x.png";
|
||||
private static final int IMAGE_SIZE = 100;
|
||||
private static final Color COLOR_1X = Color.GREEN;
|
||||
private static final Color COLOR_2X = Color.BLUE;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
Image baseMRImage = new BaseMultiResolutionImage(createImage(1),
|
||||
createImage(2));
|
||||
testMRDisabledImage(baseMRImage);
|
||||
|
||||
saveImages();
|
||||
Image toolkitMRImage = Toolkit.getDefaultToolkit().getImage(IMAGE_NAME_1X);
|
||||
|
||||
if (toolkitMRImage instanceof MultiResolutionImage) {
|
||||
testMRDisabledImage(toolkitMRImage);
|
||||
}
|
||||
}
|
||||
|
||||
private static void testMRDisabledImage(Image image) throws Exception {
|
||||
|
||||
Image disabledImage = GrayFilter.createDisabledImage(image);
|
||||
MediaTracker mediaTracker = new MediaTracker(new JLabel());
|
||||
mediaTracker.addImage(disabledImage, 0);
|
||||
mediaTracker.waitForID(0);
|
||||
|
||||
BufferedImage buffImage = new BufferedImage(IMAGE_SIZE,
|
||||
IMAGE_SIZE,
|
||||
BufferedImage.TYPE_INT_RGB);
|
||||
|
||||
int x = IMAGE_SIZE / 2;
|
||||
int y = IMAGE_SIZE / 2;
|
||||
|
||||
Graphics2D g = buffImage.createGraphics();
|
||||
|
||||
g.scale(1, 1);
|
||||
g.drawImage(disabledImage, 0, 0, null);
|
||||
int rgb1x = buffImage.getRGB(x, y);
|
||||
|
||||
g.scale(2, 2);
|
||||
g.drawImage(disabledImage, 0, 0, null);
|
||||
int rgb2x = buffImage.getRGB(x, y);
|
||||
|
||||
g.dispose();
|
||||
|
||||
if (rgb1x == rgb2x) {
|
||||
throw new RuntimeException("Disabled image is the same for the base"
|
||||
+ "image and the resolution variant");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static BufferedImage createImage(int scale) throws Exception {
|
||||
BufferedImage image = new BufferedImage(scale * 200, scale * 300,
|
||||
BufferedImage.TYPE_INT_RGB);
|
||||
Graphics g = image.createGraphics();
|
||||
g.setColor(scale == 1 ? COLOR_1X : COLOR_2X);
|
||||
g.fillRect(0, 0, scale * 200, scale * 300);
|
||||
g.dispose();
|
||||
return image;
|
||||
}
|
||||
|
||||
private static void saveImages() throws Exception {
|
||||
saveImage(createImage(1), IMAGE_NAME_1X);
|
||||
saveImage(createImage(2), IMAGE_NAME_2X);
|
||||
}
|
||||
|
||||
private static void saveImage(BufferedImage image, String name) throws Exception {
|
||||
ImageIO.write(image, "png", new File(name));
|
||||
}
|
||||
}
|
||||
132
jdk/test/javax/swing/JButton/8151303/PressedIconTest.java
Normal file
132
jdk/test/javax/swing/JButton/8151303/PressedIconTest.java
Normal file
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 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.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Point;
|
||||
import java.awt.Robot;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.image.BaseMultiResolutionImage;
|
||||
import java.awt.image.BufferedImage;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JToggleButton;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8151303
|
||||
* @summary [macosx] [hidpi] JButton's low-res. icon is visible when clicking on it
|
||||
* @run main/othervm PressedIconTest
|
||||
* @run main/othervm -Dsun.java2d.uiScale=2 PressedIconTest
|
||||
*/
|
||||
public class PressedIconTest {
|
||||
|
||||
private final static int IMAGE_SIZE = 300;
|
||||
|
||||
private final static Color COLOR_1X = Color.RED;
|
||||
private final static Color COLOR_2X = Color.BLUE;
|
||||
private static JFrame frame;
|
||||
private static volatile double scale = -1;
|
||||
private static volatile int centerX;
|
||||
private static volatile int centerY;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Robot robot = new Robot();
|
||||
robot.setAutoDelay(50);
|
||||
|
||||
SwingUtilities.invokeAndWait(() -> createAndShowGUI());
|
||||
robot.waitForIdle();
|
||||
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
scale = frame.getGraphicsConfiguration().getDefaultTransform()
|
||||
.getScaleX();
|
||||
Point location = frame.getLocation();
|
||||
Dimension size = frame.getSize();
|
||||
centerX = location.x + size.width / 2;
|
||||
centerY = location.y + size.height / 2;
|
||||
});
|
||||
robot.waitForIdle();
|
||||
|
||||
robot.mouseMove(centerX, centerY);
|
||||
robot.mousePress(InputEvent.BUTTON1_MASK);
|
||||
robot.waitForIdle();
|
||||
Thread.sleep(100);
|
||||
Color color = robot.getPixelColor(centerX, centerY);
|
||||
robot.mouseRelease(InputEvent.BUTTON1_MASK);
|
||||
|
||||
SwingUtilities.invokeAndWait(() -> frame.dispose());
|
||||
|
||||
if ((scale == 1 && !similar(color, COLOR_1X))
|
||||
|| (scale == 2 && !similar(color, COLOR_2X))) {
|
||||
throw new RuntimeException("Colors are different!");
|
||||
}
|
||||
}
|
||||
|
||||
private static void createAndShowGUI() {
|
||||
frame = new JFrame();
|
||||
frame.setSize(IMAGE_SIZE, IMAGE_SIZE);
|
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
|
||||
JPanel panel = new JPanel(new BorderLayout());
|
||||
|
||||
BufferedImage img1x = generateImage(1, COLOR_1X);
|
||||
|
||||
BufferedImage img2x = generateImage(2, COLOR_2X);
|
||||
BaseMultiResolutionImage mri = new BaseMultiResolutionImage(
|
||||
new BufferedImage[]{img1x, img2x});
|
||||
Icon mrIcon = new ImageIcon(mri);
|
||||
|
||||
JToggleButton button = new JToggleButton();
|
||||
button.setIcon(mrIcon);
|
||||
panel.add(button, BorderLayout.CENTER);
|
||||
|
||||
frame.getContentPane().add(panel);
|
||||
frame.setVisible(true);
|
||||
}
|
||||
|
||||
private static boolean similar(Color c1, Color c2) {
|
||||
return similar(c1.getRed(), c2.getRed())
|
||||
&& similar(c1.getGreen(), c2.getGreen())
|
||||
&& similar(c1.getBlue(), c2.getBlue());
|
||||
}
|
||||
|
||||
private static boolean similar(int n, int m) {
|
||||
return Math.abs(n - m) <= 50;
|
||||
}
|
||||
|
||||
private static BufferedImage generateImage(int scale, Color c) {
|
||||
|
||||
int size = IMAGE_SIZE * scale;
|
||||
BufferedImage img = new BufferedImage(size, size, BufferedImage.TYPE_INT_RGB);
|
||||
Graphics g = img.createGraphics();
|
||||
g.setColor(c);
|
||||
g.fillRect(0, 0, size, size);
|
||||
g.dispose();
|
||||
return img;
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user