mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-14 04:15:04 +00:00
8032667: [macosx] Components cannot be rendered in HiDPI to BufferedImage
Reviewed-by: serb, pchelko
This commit is contained in:
parent
a6cae47698
commit
b355da0052
@ -148,34 +148,44 @@ abstract class AquaPainter <T extends JRSUIState> {
|
||||
return;
|
||||
}
|
||||
|
||||
int scale = 1;
|
||||
if (g instanceof SunGraphics2D) {
|
||||
scale = ((SunGraphics2D) g).surfaceData.getDefaultScale();
|
||||
}
|
||||
final GraphicsConfiguration config = g.getDeviceConfiguration();
|
||||
final ImageCache cache = ImageCache.getInstance();
|
||||
final int imgW = bounds.width * scale;
|
||||
final int imgH = bounds.height * scale;
|
||||
final int width = bounds.width;
|
||||
final int height = bounds.height;
|
||||
AquaPixelsKey key = new AquaPixelsKey(config,
|
||||
imgW, imgH, scale, controlState);
|
||||
BufferedImage img = (BufferedImage) cache.getImage(key);
|
||||
width, height, bounds, controlState);
|
||||
Image img = (BufferedImage) cache.getImage(key);
|
||||
if (img == null) {
|
||||
img = new BufferedImage(imgW, imgH, BufferedImage.TYPE_INT_ARGB_PRE);
|
||||
|
||||
Image baseImage = createImage(width, height, bounds, control,
|
||||
controlState);
|
||||
|
||||
img = new MultiResolutionBufferedImage(baseImage,
|
||||
(rvWidth, rvHeight) -> createImage(rvWidth, rvHeight,
|
||||
bounds, control, controlState));
|
||||
|
||||
if (!controlState.is(JRSUIConstants.Animating.YES)) {
|
||||
cache.setImage(key, img);
|
||||
}
|
||||
|
||||
final WritableRaster raster = img.getRaster();
|
||||
final DataBufferInt buffer = (DataBufferInt) raster.getDataBuffer();
|
||||
|
||||
control.set(controlState);
|
||||
control.paint(SunWritableRaster.stealData(buffer, 0),
|
||||
imgW, imgH, 0, 0, bounds.width, bounds.height);
|
||||
SunWritableRaster.markDirty(buffer);
|
||||
}
|
||||
|
||||
g.drawImage(img, bounds.x, bounds.y, bounds.width, bounds.height, null);
|
||||
}
|
||||
|
||||
private static Image createImage(int imgW, int imgH, final Rectangle bounds,
|
||||
final JRSUIControl control, JRSUIState controlState) {
|
||||
BufferedImage img = new BufferedImage(imgW, imgH,
|
||||
BufferedImage.TYPE_INT_ARGB_PRE);
|
||||
|
||||
final WritableRaster raster = img.getRaster();
|
||||
final DataBufferInt buffer = (DataBufferInt) raster.getDataBuffer();
|
||||
|
||||
control.set(controlState);
|
||||
control.paint(SunWritableRaster.stealData(buffer, 0),
|
||||
imgW, imgH, 0, 0, bounds.width, bounds.height);
|
||||
SunWritableRaster.markDirty(buffer);
|
||||
return img;
|
||||
}
|
||||
}
|
||||
|
||||
private static class AquaPixelsKey implements ImageCache.PixelsKey {
|
||||
@ -187,17 +197,17 @@ abstract class AquaPainter <T extends JRSUIState> {
|
||||
private final GraphicsConfiguration config;
|
||||
private final int w;
|
||||
private final int h;
|
||||
private final int scale;
|
||||
private final Rectangle bounds;
|
||||
private final JRSUIState state;
|
||||
|
||||
AquaPixelsKey(final GraphicsConfiguration config,
|
||||
final int w, final int h, final int scale,
|
||||
final int w, final int h, final Rectangle bounds,
|
||||
final JRSUIState state) {
|
||||
this.pixelCount = w * h;
|
||||
this.config = config;
|
||||
this.w = w;
|
||||
this.h = h;
|
||||
this.scale = scale;
|
||||
this.bounds = bounds;
|
||||
this.state = state;
|
||||
this.hash = hash();
|
||||
}
|
||||
@ -210,7 +220,7 @@ abstract class AquaPainter <T extends JRSUIState> {
|
||||
int hash = config != null ? config.hashCode() : 0;
|
||||
hash = 31 * hash + w;
|
||||
hash = 31 * hash + h;
|
||||
hash = 31 * hash + scale;
|
||||
hash = 31 * hash + bounds.hashCode();
|
||||
hash = 31 * hash + state.hashCode();
|
||||
return hash;
|
||||
}
|
||||
@ -225,7 +235,7 @@ abstract class AquaPainter <T extends JRSUIState> {
|
||||
if (obj instanceof AquaPixelsKey) {
|
||||
AquaPixelsKey key = (AquaPixelsKey) obj;
|
||||
return config == key.config && w == key.w && h == key.h
|
||||
&& scale == key.scale && state.equals(key.state);
|
||||
&& bounds.equals(key.bounds) && state.equals(key.state);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
*/
|
||||
package sun.awt.image;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Image;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.geom.Dimension2D;
|
||||
@ -42,6 +43,13 @@ public class MultiResolutionBufferedImage extends BufferedImage
|
||||
private final Dimension2D[] sizes;
|
||||
private int availableInfo;
|
||||
|
||||
public MultiResolutionBufferedImage(Image baseImage,
|
||||
BiFunction<Integer, Integer, Image> mapper) {
|
||||
this(baseImage, new Dimension[]{new Dimension(
|
||||
baseImage.getWidth(null), baseImage.getHeight(null))
|
||||
}, mapper);
|
||||
}
|
||||
|
||||
public MultiResolutionBufferedImage(Image baseImage,
|
||||
Dimension2D[] sizes, BiFunction<Integer, Integer, Image> mapper) {
|
||||
super(baseImage.getWidth(null), baseImage.getHeight(null),
|
||||
@ -115,7 +123,7 @@ public class MultiResolutionBufferedImage extends BufferedImage
|
||||
}
|
||||
|
||||
private static void preload(Image image, int availableInfo) {
|
||||
if (image instanceof ToolkitImage) {
|
||||
if (availableInfo != 0 && image instanceof ToolkitImage) {
|
||||
((ToolkitImage) image).preload(new ImageObserver() {
|
||||
int flags = availableInfo;
|
||||
|
||||
|
||||
36
jdk/test/javax/swing/JCheckBox/8032667/bug8032667.html
Normal file
36
jdk/test/javax/swing/JCheckBox/8032667/bug8032667.html
Normal file
@ -0,0 +1,36 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<html>
|
||||
<body>
|
||||
|
||||
Verify that scaled components are rendered smoothly to image.
|
||||
|
||||
1. Run the test.
|
||||
2. Check that Selected and Deselected JCheckBox icons are drawn smoothly.
|
||||
If so, press PASS, else press FAIL.
|
||||
|
||||
<applet code="bug8032667.class" width=400 height=400></applet>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
91
jdk/test/javax/swing/JCheckBox/8032667/bug8032667.java
Normal file
91
jdk/test/javax/swing/JCheckBox/8032667/bug8032667.java
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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.BorderLayout;
|
||||
import java.awt.Canvas;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
import java.awt.image.BufferedImage;
|
||||
import javax.swing.JApplet;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
/* @test
|
||||
* @bug 8032667
|
||||
* @summary [macosx] Components cannot be rendered in HiDPI to BufferedImage
|
||||
* @run applet/manual=yesno bug8032667.html
|
||||
*/
|
||||
public class bug8032667 extends JApplet {
|
||||
|
||||
static final int scale = 2;
|
||||
static final int width = 130;
|
||||
static final int height = 50;
|
||||
static final int scaledWidth = scale * width;
|
||||
static final int scaledHeight = scale * height;
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
final Image image1 = getImage(getCheckBox("Deselected", false));
|
||||
final Image image2 = getImage(getCheckBox("Selected", true));
|
||||
|
||||
Canvas canvas = new Canvas() {
|
||||
|
||||
@Override
|
||||
public void paint(Graphics g) {
|
||||
super.paint(g);
|
||||
g.drawImage(image1, 0, 0, scaledWidth, scaledHeight, this);
|
||||
g.drawImage(image2, 0, scaledHeight + 5,
|
||||
scaledWidth, scaledHeight, this);
|
||||
}
|
||||
};
|
||||
|
||||
getContentPane().add(canvas, BorderLayout.CENTER);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static JCheckBox getCheckBox(String text, boolean selected) {
|
||||
JCheckBox checkBox = new JCheckBox(text);
|
||||
checkBox.setSelected(selected);
|
||||
checkBox.setSize(new Dimension(width, height));
|
||||
return checkBox;
|
||||
}
|
||||
|
||||
static Image getImage(JComponent component) {
|
||||
final BufferedImage image = new BufferedImage(
|
||||
scaledWidth, scaledHeight, BufferedImage.TYPE_INT_ARGB);
|
||||
final Graphics g = image.getGraphics();
|
||||
((Graphics2D) g).scale(scale, scale);
|
||||
component.paint(g);
|
||||
g.dispose();
|
||||
|
||||
return image;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* 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.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
import java.awt.image.BufferedImage;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.SwingUtilities;
|
||||
import sun.awt.OSInfo;
|
||||
|
||||
/* @test
|
||||
* @bug 8032667
|
||||
* @summary [macosx] Components cannot be rendered in HiDPI to BufferedImage
|
||||
* @run main bug8032667_image_diff
|
||||
*/
|
||||
public class bug8032667_image_diff {
|
||||
|
||||
static final int IMAGE_WIDTH = 130;
|
||||
static final int IMAGE_HEIGHT = 50;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
if(!OSInfo.OSType.MACOSX.equals(OSInfo.getOSType())){
|
||||
return;
|
||||
}
|
||||
|
||||
SwingUtilities.invokeAndWait(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
JCheckBox checkBox = new JCheckBox();
|
||||
checkBox.setSelected(true);
|
||||
checkBox.setSize(new Dimension(IMAGE_WIDTH, IMAGE_HEIGHT));
|
||||
|
||||
final BufferedImage image1 = getHiDPIImage(checkBox);
|
||||
final BufferedImage image2 = getScaledImage(checkBox);
|
||||
|
||||
if(equal(image1, image2)){
|
||||
throw new RuntimeException("2x image equals to non smooth image");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static boolean equal(BufferedImage image1, BufferedImage image2) {
|
||||
|
||||
int w = image1.getWidth();
|
||||
int h = image1.getHeight();
|
||||
|
||||
if (w != image2.getWidth() || h != image2.getHeight()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < w; i++) {
|
||||
for (int j = 0; j < h; j++) {
|
||||
int color1 = image1.getRGB(i, j);
|
||||
int color2 = image2.getRGB(i, j);
|
||||
|
||||
if (color1 != color2) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static BufferedImage getHiDPIImage(JComponent component) {
|
||||
return getImage(component, 2, IMAGE_WIDTH, IMAGE_HEIGHT);
|
||||
}
|
||||
|
||||
static BufferedImage getScaledImage(JComponent component) {
|
||||
Image image1x = getImage(component, 1, IMAGE_WIDTH, IMAGE_HEIGHT);
|
||||
final BufferedImage image2x = new BufferedImage(
|
||||
2 * IMAGE_WIDTH, 2 * IMAGE_HEIGHT, BufferedImage.TYPE_INT_ARGB);
|
||||
final Graphics g = image2x.getGraphics();
|
||||
((Graphics2D) g).scale(2, 2);
|
||||
g.drawImage(image1x, 0, 0, null);
|
||||
g.dispose();
|
||||
return image2x;
|
||||
}
|
||||
|
||||
static BufferedImage getImage(JComponent component, int scale, int width, int height) {
|
||||
final BufferedImage image = new BufferedImage(
|
||||
scale * width, scale * height, BufferedImage.TYPE_INT_ARGB);
|
||||
final Graphics g = image.getGraphics();
|
||||
((Graphics2D) g).scale(scale, scale);
|
||||
component.paint(g);
|
||||
g.dispose();
|
||||
return image;
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user