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