diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/XPStyle.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/XPStyle.java index 641bfed328b..0dbe039f54c 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/XPStyle.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/XPStyle.java @@ -657,7 +657,6 @@ class XPStyle { protected void paintToImage(Component c, Image image, Graphics g, int w, int h, Object[] args) { - boolean accEnabled = false; Skin skin = (Skin)args[0]; Part part = skin.part; State state = (State)args[1]; @@ -668,6 +667,8 @@ class XPStyle { c = skin.component; } BufferedImage bi = (BufferedImage)image; + w = bi.getWidth(); + h = bi.getHeight(); WritableRaster raster = bi.getRaster(); DataBufferInt dbi = (DataBufferInt)raster.getDataBuffer(); diff --git a/jdk/src/java.desktop/share/classes/sun/swing/CachedPainter.java b/jdk/src/java.desktop/share/classes/sun/swing/CachedPainter.java index 60876adae6f..818e20dbdd3 100644 --- a/jdk/src/java.desktop/share/classes/sun/swing/CachedPainter.java +++ b/jdk/src/java.desktop/share/classes/sun/swing/CachedPainter.java @@ -100,7 +100,9 @@ public abstract class CachedPainter { } } - private Image getImage(Object key, Component c, int w, int h, Object... args) { + private Image getImage(Object key, Component c, + int baseWidth, int baseHeight, + int w, int h, Object... args) { GraphicsConfiguration config = getGraphicsConfiguration(c); ImageCache cache = getCache(key); Image image = cache.getImage(key, config, w, h, args); @@ -127,8 +129,11 @@ public abstract class CachedPainter { } if (draw) { // Render to the Image - Graphics g2 = image.getGraphics(); - paintToImage(c, image, g2, w, h, args); + Graphics2D g2 = (Graphics2D) image.getGraphics(); + if (w != baseWidth || h != baseHeight) { + g2.scale((double) w / baseWidth, (double) h / baseHeight); + } + paintToImage(c, image, g2, baseWidth, baseHeight, args); g2.dispose(); } @@ -149,14 +154,7 @@ public abstract class CachedPainter { Image image = cache.getImage(key, config, w, h, args); if (image == null) { - double sx = 1; - double sy = 1; - if (g instanceof Graphics2D) { - AffineTransform tx = ((Graphics2D) g).getTransform(); - sx = tx.getScaleX(); - sy = tx.getScaleY(); - } - image = new PainterMultiResolutionCachedImage(sx, sy, w, h); + image = new PainterMultiResolutionCachedImage(w, h); cache.setImage(key, config, w, h, args, image); } @@ -238,17 +236,12 @@ public abstract class CachedPainter { class PainterMultiResolutionCachedImage extends AbstractMultiResolutionImage { - private final double scaleX; - private final double scaleY; private final int baseWidth; private final int baseHeight; private Component c; private Object[] args; - public PainterMultiResolutionCachedImage(double scaleX, double scaleY, - int baseWidth, int baseHeight) { - this.scaleX = scaleX; - this.scaleY = scaleY; + public PainterMultiResolutionCachedImage(int baseWidth, int baseHeight) { this.baseWidth = baseWidth; this.baseHeight = baseHeight; } @@ -272,7 +265,7 @@ public abstract class CachedPainter { public Image getResolutionVariant(double destWidth, double destHeight) { int w = (int) Math.ceil(destWidth); int h = (int) Math.ceil(destHeight); - return getImage(this, c, w, h, args); + return getImage(this, c, baseWidth, baseHeight, w, h, args); } @Override @@ -282,15 +275,7 @@ public abstract class CachedPainter { @Override public java.util.List getResolutionVariants() { - - if (scaleX == 1 && scaleY == 1) { - return Arrays.asList(getResolutionVariant(baseWidth, baseHeight)); - } - - return Arrays.asList( - getResolutionVariant(baseWidth, baseHeight), - getResolutionVariant(scaleX * baseWidth, scaleY * baseHeight) - ); + return Arrays.asList(getResolutionVariant(baseWidth, baseHeight)); } } } \ No newline at end of file diff --git a/jdk/test/javax/swing/JSlider/8162856/MetalHiDPISliderThumbTest.java b/jdk/test/javax/swing/JSlider/8162856/MetalHiDPISliderThumbTest.java new file mode 100644 index 00000000000..1c0701e3acd --- /dev/null +++ b/jdk/test/javax/swing/JSlider/8162856/MetalHiDPISliderThumbTest.java @@ -0,0 +1,147 @@ +/* + * 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.Dimension; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import javax.swing.JSlider; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.plaf.metal.MetalLookAndFeel; + +/* + * @test + * @bug 8162856 + * @summary Bad rendering of Swing UI controls with Metal L&F on HiDPI display + * @run main MetalHiDPISliderThumbTest + */ +public class MetalHiDPISliderThumbTest { + + public static void main(String[] args) throws Exception { + + SwingUtilities.invokeAndWait(() -> { + + try { + UIManager.setLookAndFeel(new MetalLookAndFeel()); + } catch (Exception e) { + throw new RuntimeException(e); + } + + if (!testSliderThumb(true)) { + throw new RuntimeException("Horizontal Slider Thumb is not scaled!"); + } + + if (!testSliderThumb(false)) { + throw new RuntimeException("Vertical Slider Thumb is not scaled!"); + } + }); + } + + private static boolean testSliderThumb(boolean horizontal) { + int scale = 3; + + int w = horizontal ? 100 : 20; + int h = horizontal ? 20 : 100; + + JSlider testSlider = new JSlider(); + testSlider.setSize(w, h); + Dimension size = new Dimension(w, h); + testSlider.setPreferredSize(size); + testSlider.setMinimumSize(size); + testSlider.setMaximumSize(size); + testSlider.setOrientation(horizontal ? JSlider.HORIZONTAL : JSlider.VERTICAL); + + int sw = scale * w; + int sh = scale * h; + + final BufferedImage img = new BufferedImage(sw, sh, BufferedImage.TYPE_INT_RGB); + + Graphics2D g = img.createGraphics(); + g.scale(scale, scale); + testSlider.paint(g); + g.dispose(); + + if (horizontal) { + int y = sh / 2; + + int xMin = 0; + int rgb = img.getRGB(xMin, y); + for (int i = 0; i < sw; i++) { + if (img.getRGB(i, y) != rgb) { + xMin = i; + break; + } + } + + int xMax = sw - 1; + rgb = img.getRGB(xMax, y); + for (int i = sw - 1; i > 0; i--) { + if (img.getRGB(i, y) != rgb) { + xMax = i; + break; + } + } + + int d = 3 * scale; + int xc = (xMin + xMax) / 2 - d; + rgb = img.getRGB(xc, y); + + for (int x = xMin + d; x < xc; x++) { + if (img.getRGB(x, y) != rgb) { + return true; + } + } + } else { + int x = sw / 2; + + int yMin = 0; + int rgb = img.getRGB(x, yMin); + for (int i = 0; i < sh; i++) { + if (img.getRGB(x, i) != rgb) { + yMin = i; + break; + } + } + + int yMax = sh - 1; + rgb = img.getRGB(x, yMax); + for (int i = sh - 1; i > 0; i--) { + if (img.getRGB(x, i) != rgb) { + yMax = i; + break; + } + } + + int d = 3 * scale; + int yc = (yMin + yMax) / 2 - d; + rgb = img.getRGB(x, yc); + + for (int y = yMin + d; y < yc; y++) { + if (img.getRGB(x, y) != rgb) { + return true; + } + } + } + return false; + } +}