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