--- old/src/macosx/classes/com/apple/laf/AquaPainter.java 2014-03-26 17:36:18.000000000 +0400 +++ new/src/macosx/classes/com/apple/laf/AquaPainter.java 2014-03-26 17:36:18.000000000 +0400 @@ -148,34 +148,44 @@ 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 @@ 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 @@ 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 @@ 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; } --- old/src/share/classes/sun/awt/image/MultiResolutionBufferedImage.java 2014-03-26 17:36:19.000000000 +0400 +++ new/src/share/classes/sun/awt/image/MultiResolutionBufferedImage.java 2014-03-26 17:36:19.000000000 +0400 @@ -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; @@ -43,6 +44,13 @@ private int availableInfo; public MultiResolutionBufferedImage(Image baseImage, + BiFunction mapper) { + this(baseImage, new Dimension[]{new Dimension( + baseImage.getWidth(null), baseImage.getHeight(null)) + }, mapper); + } + + public MultiResolutionBufferedImage(Image baseImage, Dimension2D[] sizes, BiFunction mapper) { super(baseImage.getWidth(null), baseImage.getHeight(null), BufferedImage.TYPE_INT_ARGB_PRE); @@ -115,7 +123,7 @@ } 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; --- /dev/null 2014-03-26 17:36:20.000000000 +0400 +++ new/test/javax/swing/JCheckBox/8032667/bug8032667.html 2014-03-26 17:36:20.000000000 +0400 @@ -0,0 +1,36 @@ + + + + + +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. + + + + + --- /dev/null 2014-03-26 17:36:21.000000000 +0400 +++ new/test/javax/swing/JCheckBox/8032667/bug8032667.java 2014-03-26 17:36:20.000000000 +0400 @@ -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; + } +}