1 /*
   2  * Copyright (c) 2014, 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.Graphics;
  26 import java.awt.Image;
  27 import java.awt.Toolkit;
  28 import java.awt.image.BufferedImage;
  29 import java.awt.image.ImageObserver;
  30 import static java.awt.image.ImageObserver.ALLBITS;
  31 import java.io.File;
  32 import javax.imageio.ImageIO;
  33 import sun.awt.OSInfo;
  34 import sun.awt.SunToolkit;
  35 import sun.awt.image.MultiResolutionToolkitImage;
  36 
  37 /**
  38  * @test
  39  * @bug 8040291
  40  * @author Alexander Scherbatiy
  41  * @summary [macosx] Http-Images are not fully loaded when using ImageIcon
  42  * @run main MultiResolutionToolkitImageTest
  43  */
  44 public class MultiResolutionToolkitImageTest {
  45 
  46     private static final int IMAGE_WIDTH = 300;
  47     private static final int IMAGE_HEIGHT = 200;
  48     private static final Color COLOR_1X = Color.GREEN;
  49     private static final Color COLOR_2X = Color.BLUE;
  50     private static final String IMAGE_NAME_1X = "image.png";
  51     private static final String IMAGE_NAME_2X = "image@2x.png";
  52     private static final int WAIT_TIME = 400;
  53     private static volatile boolean isImageLoaded = false;
  54     private static volatile boolean isRVObserverCalled = false;
  55 
  56     public static void main(String[] args) throws Exception {
  57 
  58         if (!checkOS()) {
  59             return;
  60         }
  61         generateImages();
  62         testToolkitMultiResolutionImageLoad();
  63     }
  64 
  65     static void testToolkitMultiResolutionImageLoad() throws Exception {
  66         File imageFile = new File(IMAGE_NAME_1X);
  67         String fileName = imageFile.getAbsolutePath();
  68         Image image = Toolkit.getDefaultToolkit().getImage(fileName);
  69         SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit();
  70         toolkit.prepareImage(image, -1, -1, new LoadImageObserver());
  71 
  72         final long time = WAIT_TIME + System.currentTimeMillis();
  73         while ((!isImageLoaded || !isRVObserverCalled)
  74                 && System.currentTimeMillis() < time) {
  75             Thread.sleep(50);
  76         }
  77 
  78         if(!isImageLoaded){
  79             throw new RuntimeException("Image is not loaded!");
  80         }
  81 
  82         if(!isRVObserverCalled){
  83             throw new RuntimeException("Resolution Variant observer is not called!");
  84         }
  85     }
  86 
  87     static void generateImages() throws Exception {
  88         if (!new File(IMAGE_NAME_1X).exists()) {
  89             generateImage(1);
  90         }
  91 
  92         if (!new File(IMAGE_NAME_2X).exists()) {
  93             generateImage(2);
  94         }
  95     }
  96 
  97     static void generateImage(int scale) throws Exception {
  98         BufferedImage image = new BufferedImage(scale * IMAGE_WIDTH, scale * IMAGE_HEIGHT,
  99                 BufferedImage.TYPE_INT_RGB);
 100         Graphics g = image.getGraphics();
 101         g.setColor(scale == 1 ? COLOR_1X : COLOR_2X);
 102         g.fillRect(0, 0, scale * IMAGE_WIDTH, scale * IMAGE_HEIGHT);
 103         File file = new File(scale == 1 ? IMAGE_NAME_1X : IMAGE_NAME_2X);
 104         ImageIO.write(image, "png", file);
 105     }
 106 
 107     static boolean checkOS() {
 108         return OSInfo.getOSType() == OSInfo.OSType.MACOSX;
 109     }
 110 
 111     static class LoadImageObserver implements ImageObserver {
 112 
 113         @Override
 114         public boolean imageUpdate(Image img, int infoflags, int x, int y,
 115                 int width, int height) {
 116 
 117             if (isRVObserver()) {
 118                 isRVObserverCalled = true;
 119                 SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit();
 120                 Image resolutionVariant = getResolutionVariant(img);
 121                 int rvFlags = toolkit.checkImage(resolutionVariant, width, height,
 122                         new IdleImageObserver());
 123                 if (rvFlags < infoflags) {
 124                     throw new RuntimeException("Info flags are greater than"
 125                             + " resolution varint info flags");
 126                 }
 127             } else if ((infoflags & ALLBITS) != 0) {
 128                 isImageLoaded = true;
 129             }
 130 
 131             return (infoflags & ALLBITS) == 0;
 132         }
 133     }
 134 
 135     static boolean isRVObserver() {
 136         Exception e = new Exception();
 137 
 138         for (StackTraceElement elem : e.getStackTrace()) {
 139             if (elem.getClassName().endsWith("MultiResolutionToolkitImage")) {
 140                 return true;
 141             }
 142         }
 143         return false;
 144     }
 145 
 146     static class IdleImageObserver implements ImageObserver {
 147 
 148         @Override
 149         public boolean imageUpdate(Image img, int infoflags, int x, int y,
 150                 int width, int height) {
 151             return false;
 152         }
 153     }
 154 
 155     static Image getResolutionVariant(Image image) {
 156         return ((MultiResolutionToolkitImage) image).getResolutionVariant();
 157     }
 158 }