1 /* 2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 import java.awt.Color; 25 import java.awt.Frame; 26 import java.awt.Graphics; 27 import java.awt.GraphicsConfiguration; 28 import java.awt.GraphicsDevice; 29 import java.awt.Image; 30 import java.awt.Rectangle; 31 import java.awt.image.BufferedImage; 32 import java.awt.image.BaseMultiResolutionImage; 33 import static java.awt.RenderingHints.KEY_RESOLUTION_VARIANT; 34 import static java.awt.RenderingHints.VALUE_RESOLUTION_VARIANT_SIZE_FIT; 35 import java.awt.geom.AffineTransform; 36 import java.awt.image.ColorModel; 37 import java.awt.image.Raster; 38 import sun.java2d.StateTrackable; 39 import sun.java2d.SunGraphics2D; 40 import sun.java2d.SurfaceData; 41 import sun.java2d.loops.SurfaceType; 42 43 /** 44 * @test 45 * @bug 8073320 46 * @author Alexander Scherbatiy 47 * @summary Windows HiDPI support 48 * @modules java.desktop/sun.java2d java.desktop/sun.java2d.loops 49 * @run main MultiResolutionDrawImageWithTransformTest 50 */ 51 public class MultiResolutionDrawImageWithTransformTest { 52 53 private static final int SCREEN_SIZE = 400; 54 private static final int IMAGE_SIZE = SCREEN_SIZE / 4; 55 private static final Color BACKGROUND_COLOR = Color.PINK; 56 private static final Color[] COLORS = { 57 Color.CYAN, Color.GREEN, Color.BLUE, Color.ORANGE 58 }; 59 60 public static void main(String[] args) throws Exception { 61 62 int length = COLORS.length; 63 BufferedImage[] resolutionVariants = new BufferedImage[length]; 64 for (int i = 0; i < length; i++) { 65 resolutionVariants[i] = createRVImage(getSize(i), COLORS[i]); 66 } 67 68 BaseMultiResolutionImage mrImage = new BaseMultiResolutionImage( 69 resolutionVariants); 70 71 // scale 1, transform 1, resolution variant 1 72 Color color = getImageColor(mrImage, 1, 1); 73 if (!getColorForScale(1).equals(color)) { 74 throw new RuntimeException("Wrong resolution variant!"); 75 } 76 77 // scale 1, transform 2, resolution variant 2 78 color = getImageColor(mrImage, 1, 2); 79 if (!getColorForScale(2).equals(color)) { 80 throw new RuntimeException("Wrong resolution variant!"); 81 } 82 83 // scale 2, transform 1, resolution variant 2 84 color = getImageColor(mrImage, 2, 1); 85 if (!getColorForScale(2).equals(color)) { 86 throw new RuntimeException("Wrong resolution variant!"); 87 } 88 89 // scale 2, transform 2, resolution variant 4 90 color = getImageColor(mrImage, 2, 2); 91 if (!getColorForScale(4).equals(color)) { 92 throw new RuntimeException("Wrong resolution variant!"); 93 } 94 } 95 96 private static Color getColorForScale(int scale) { 97 return COLORS[scale - 1]; 98 } 99 100 private static Color getImageColor(Image image, double configScale, 101 double transformScale) { 102 103 TestSurfaceData surface = new TestSurfaceData(SCREEN_SIZE, SCREEN_SIZE, 104 configScale); 105 SunGraphics2D g2d = new SunGraphics2D(surface, 106 Color.BLACK, Color.BLACK, null); 107 g2d.setRenderingHint(KEY_RESOLUTION_VARIANT, 108 VALUE_RESOLUTION_VARIANT_SIZE_FIT); 109 AffineTransform tx = AffineTransform.getScaleInstance(transformScale, 110 transformScale); 111 g2d.drawImage(image, tx, null); 112 g2d.dispose(); 113 114 int backgroundX = (int) (1.5 * image.getWidth(null) * transformScale); 115 int backgroundY = (int) (1.5 * image.getHeight(null) * transformScale); 116 Color backgroundColor = surface.getColor(backgroundX, backgroundY); 117 //surface.show(String.format("Config: %f, transform: %f", configScale, transformScale)); 118 if (!BACKGROUND_COLOR.equals(backgroundColor)) { 119 throw new RuntimeException("Wrong background color!"); 120 } 121 return surface.getColor(IMAGE_SIZE / 4, IMAGE_SIZE / 4); 122 } 123 124 private static int getSize(int i) { 125 return (i + 1) * IMAGE_SIZE; 126 } 127 128 private static BufferedImage createRVImage(int size, Color color) { 129 BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_INT_RGB); 130 Graphics g = image.createGraphics(); 131 g.setColor(color); 132 g.fillRect(0, 0, size, size); 133 g.dispose(); 134 return image; 135 } 136 137 static class TestGraphicsConfig extends GraphicsConfiguration { 138 139 private final double scale; 140 141 TestGraphicsConfig(double scale) { 142 this.scale = scale; 143 } 144 145 @Override 146 public GraphicsDevice getDevice() { 147 throw new UnsupportedOperationException("Not supported yet."); 148 } 149 150 @Override 151 public ColorModel getColorModel() { 152 throw new UnsupportedOperationException("Not supported yet."); 153 } 154 155 @Override 156 public ColorModel getColorModel(int transparency) { 157 throw new UnsupportedOperationException("Not supported yet."); 158 } 159 160 @Override 161 public AffineTransform getDefaultTransform() { 162 return AffineTransform.getScaleInstance(scale, scale); 163 } 164 165 @Override 166 public AffineTransform getNormalizingTransform() { 167 throw new UnsupportedOperationException("Not supported yet."); 168 } 169 170 @Override 171 public Rectangle getBounds() { 172 throw new UnsupportedOperationException("Not supported yet."); 173 } 174 } 175 176 static class TestSurfaceData extends SurfaceData { 177 178 private final int width; 179 private final int height; 180 private final GraphicsConfiguration gc; 181 private final BufferedImage buffImage; 182 private final double scale; 183 184 public TestSurfaceData(int width, int height, double scale) { 185 super(StateTrackable.State.DYNAMIC, SurfaceType.Custom, ColorModel.getRGBdefault()); 186 this.scale = scale; 187 gc = new TestGraphicsConfig(scale); 188 this.width = (int) Math.ceil(scale * width); 189 this.height = (int) Math.ceil(scale * height); 190 buffImage = new BufferedImage(this.width, this.height, 191 BufferedImage.TYPE_INT_RGB); 192 193 Graphics imageGraphics = buffImage.createGraphics(); 194 imageGraphics.setColor(BACKGROUND_COLOR); 195 imageGraphics.fillRect(0, 0, this.width, this.height); 196 imageGraphics.dispose(); 197 } 198 199 Color getColor(int x, int y) { 200 int sx = (int) Math.ceil(x * scale); 201 int sy = (int) Math.ceil(y * scale); 202 return new Color(buffImage.getRGB(sx, sy)); 203 } 204 205 @Override 206 public SurfaceData getReplacement() { 207 throw new UnsupportedOperationException("Not supported yet."); 208 } 209 210 @Override 211 public GraphicsConfiguration getDeviceConfiguration() { 212 return gc; 213 } 214 215 @Override 216 public Raster getRaster(int x, int y, int w, int h) { 217 return buffImage.getRaster(); 218 } 219 220 @Override 221 public Rectangle getBounds() { 222 return new Rectangle(0, 0, width, height); 223 } 224 225 @Override 226 public Object getDestination() { 227 throw new UnsupportedOperationException("Not supported yet."); 228 } 229 230 private void show(String title) { 231 Frame frame = new Frame() { 232 233 @Override 234 public void paint(Graphics g) { 235 super.paint(g); 236 g.drawImage(buffImage, 0, 0, this); 237 g.setColor(Color.GRAY); 238 g.drawRect(0, 0, width, height); 239 g.drawRect(0, height / 2, width, height / 2); 240 g.drawRect(width / 2, 0, width / 2, height); 241 } 242 }; 243 frame.setTitle(title); 244 frame.setSize(width, height); 245 frame.setVisible(true); 246 } 247 } 248 }