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
  49  * @run main MultiResolutionDrawImageWithTransformTest
  50  */
  51 public class MultiResolutionDrawImageWithTransformTest {
  52 
  53     private static final int SCREEN_SIZE = 200;
  54     private static final int IMAGE_SIZE = SCREEN_SIZE / 2;
  55     private static final Color[] COLORS = {
  56         Color.CYAN, Color.GREEN, Color.BLUE, Color.ORANGE
  57     };
  58 
  59     public static void main(String[] args) throws Exception {
  60 
  61         int length = COLORS.length;
  62         BufferedImage[] resolutionVariants = new BufferedImage[length];
  63         for (int i = 0; i < length; i++) {
  64             resolutionVariants[i] = createRVImage(getSize(i), COLORS[i]);
  65         }
  66 
  67         BaseMultiResolutionImage mrImage = new BaseMultiResolutionImage(
  68                 resolutionVariants);
  69 
  70         // scale 1, transform 1, resolution variant 1
  71         Color color = getImageColor(mrImage, 1, 1);
  72         if (!getColorForScale(1).equals(color)) {
  73             throw new RuntimeException("Wrong resolution variant!");
  74         }
  75 
  76         // scale 1, transform 2, resolution variant 2
  77         color = getImageColor(mrImage, 1, 2);
  78         if (!getColorForScale(2).equals(color)) {
  79             throw new RuntimeException("Wrong resolution variant!");
  80         }
  81 
  82         // scale 2, transform 1, resolution variant 2
  83         color = getImageColor(mrImage, 1, 2);
  84         if (!getColorForScale(2).equals(color)) {
  85             throw new RuntimeException("Wrong resolution variant!");
  86         }
  87 
  88         // scale 2, transform 2, resolution variant 4
  89         color = getImageColor(mrImage, 2, 2);
  90         if (!getColorForScale(4).equals(color)) {
  91             throw new RuntimeException("Wrong resolution variant!");
  92         }
  93     }
  94 
  95     private static Color getColorForScale(int scale) {
  96         return COLORS[scale - 1];
  97     }
  98 
  99     private static Color getImageColor(Image image, double configScale,
 100             double transformScale) {
 101 
 102         TestSurfaceData surface = new TestSurfaceData(SCREEN_SIZE, SCREEN_SIZE,
 103                                                       configScale);
 104         SunGraphics2D g2d = new SunGraphics2D(surface,
 105                 Color.BLACK, Color.BLACK, null);
 106         g2d.setRenderingHint(KEY_RESOLUTION_VARIANT,
 107                 VALUE_RESOLUTION_VARIANT_SIZE_FIT);
 108         AffineTransform tx = AffineTransform.getScaleInstance(transformScale,
 109                                                               transformScale);
 110         g2d.drawImage(image, tx, null);
 111         g2d.dispose();
 112         return surface.getColor(IMAGE_SIZE / 4, IMAGE_SIZE / 4);
 113     }
 114 
 115     private static int getSize(int i) {
 116         return (i + 1) * IMAGE_SIZE;
 117     }
 118 
 119     private static BufferedImage createRVImage(int size, Color color) {
 120         BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_INT_RGB);
 121         Graphics g = image.createGraphics();
 122         g.setColor(color);
 123         g.fillRect(0, 0, size, size);
 124         g.dispose();
 125         return image;
 126     }
 127 
 128     static class TestGraphicsConfig extends GraphicsConfiguration {
 129 
 130         private final double scale;
 131 
 132         TestGraphicsConfig(double scale) {
 133             this.scale = scale;
 134         }
 135 
 136         @Override
 137         public GraphicsDevice getDevice() {
 138             throw new UnsupportedOperationException("Not supported yet.");
 139         }
 140 
 141         @Override
 142         public ColorModel getColorModel() {
 143             throw new UnsupportedOperationException("Not supported yet.");
 144         }
 145 
 146         @Override
 147         public ColorModel getColorModel(int transparency) {
 148             throw new UnsupportedOperationException("Not supported yet.");
 149         }
 150 
 151         @Override
 152         public AffineTransform getDefaultTransform() {
 153             return AffineTransform.getScaleInstance(scale, scale);
 154         }
 155 
 156         @Override
 157         public AffineTransform getNormalizingTransform() {
 158             throw new UnsupportedOperationException("Not supported yet.");
 159         }
 160 
 161         @Override
 162         public Rectangle getBounds() {
 163             throw new UnsupportedOperationException("Not supported yet.");
 164         }
 165     }
 166 
 167     static class TestSurfaceData extends SurfaceData {
 168 
 169         private final int width;
 170         private final int height;
 171         private final GraphicsConfiguration gc;
 172         private final BufferedImage buffImage;
 173         private final double scale;
 174 
 175         public TestSurfaceData(int width, int height, double scale) {
 176             super(StateTrackable.State.DYNAMIC, SurfaceType.Custom, ColorModel.getRGBdefault());
 177             this.scale = scale;
 178             gc = new TestGraphicsConfig(scale);
 179             this.width = (int) Math.ceil(scale * width);
 180             this.height = (int) Math.ceil(scale * height);
 181             buffImage = new BufferedImage(this.width, this.height,
 182                     BufferedImage.TYPE_INT_RGB);
 183         }
 184 
 185         Color getColor(int x, int y) {
 186             int sx = (int) Math.ceil(x * scale);
 187             int sy = (int) Math.ceil(y * scale);
 188             return new Color(buffImage.getRGB(sx, sy));
 189         }
 190 
 191         @Override
 192         public SurfaceData getReplacement() {
 193             throw new UnsupportedOperationException("Not supported yet.");
 194         }
 195 
 196         @Override
 197         public GraphicsConfiguration getDeviceConfiguration() {
 198             return gc;
 199         }
 200 
 201         @Override
 202         public Raster getRaster(int x, int y, int w, int h) {
 203             return buffImage.getRaster();
 204         }
 205 
 206         @Override
 207         public Rectangle getBounds() {
 208             return new Rectangle(0, 0, width, height);
 209         }
 210 
 211         @Override
 212         public Object getDestination() {
 213             throw new UnsupportedOperationException("Not supported yet.");
 214         }
 215     }
 216 }