8040291: [macosx] Http-Images are not fully loaded when using ImageIcon
authoralexsch
Mon, 26 May 2014 14:33:49 +0400
changeset 25107 9a16a601de25
parent 25106 2c5983def8f1
child 25108 cbf21a81a738
8040291: [macosx] Http-Images are not fully loaded when using ImageIcon Reviewed-by: serb, pchelko
jdk/src/share/classes/java/awt/MediaTracker.java
jdk/src/share/classes/sun/awt/SunToolkit.java
jdk/src/share/classes/sun/awt/image/MultiResolutionToolkitImage.java
jdk/test/java/awt/image/multiresolution/MultiResolutionToolkitImageTest.java
--- a/jdk/src/share/classes/java/awt/MediaTracker.java	Fri May 23 11:13:54 2014 -0700
+++ b/jdk/src/share/classes/java/awt/MediaTracker.java	Mon May 26 14:33:49 2014 +0400
@@ -226,7 +226,9 @@
         addImageImpl(image, id, w, h);
         Image rvImage = getResolutionVariant(image);
         if (rvImage != null) {
-            addImageImpl(rvImage, id, 2 * w, 2 * h);
+            addImageImpl(rvImage, id,
+                    w == -1 ? -1 : 2 * w,
+                    h == -1 ? -1 : 2 * h);
         }
     }
 
@@ -810,8 +812,9 @@
         removeImageImpl(image, id, width, height);
         Image rvImage = getResolutionVariant(image);
         if (rvImage != null) {
-            removeImageImpl(rvImage, id, 2 * width, 2 * height);
-
+            removeImageImpl(rvImage, id,
+                    width == -1 ? -1 : 2 * width,
+                    height == -1 ? -1 : 2 * height);
         }
         notifyAll();    // Notify in case remaining images are "done".
     }
--- a/jdk/src/share/classes/sun/awt/SunToolkit.java	Fri May 23 11:13:54 2014 -0700
+++ b/jdk/src/share/classes/sun/awt/SunToolkit.java	Mon May 26 14:33:49 2014 +0400
@@ -850,22 +850,30 @@
 
     private int checkResolutionVariant(Image img, int w, int h, ImageObserver o) {
         ToolkitImage rvImage = getResolutionVariant(img);
+        int rvw = getRVSize(w);
+        int rvh = getRVSize(h);
         // Ignore the resolution variant in case of error
         return (rvImage == null || rvImage.hasError()) ? 0xFFFF :
-                checkImage(rvImage, 2 * w, 2 * h, MultiResolutionToolkitImage.
+                checkImage(rvImage, rvw, rvh, MultiResolutionToolkitImage.
                                 getResolutionVariantObserver(
-                                        img, o, w, h, 2 * w, 2 * h));
+                                        img, o, w, h, rvw, rvh, true));
     }
 
     private boolean prepareResolutionVariant(Image img, int w, int h,
             ImageObserver o) {
 
         ToolkitImage rvImage = getResolutionVariant(img);
+        int rvw = getRVSize(w);
+        int rvh = getRVSize(h);
         // Ignore the resolution variant in case of error
         return rvImage == null || rvImage.hasError() || prepareImage(
-                rvImage, 2 * w, 2 * h,
+                rvImage, rvw, rvh,
                 MultiResolutionToolkitImage.getResolutionVariantObserver(
-                        img, o, w, h, 2 * w, 2 * h));
+                        img, o, w, h, rvw, rvh, true));
+    }
+
+    private static int getRVSize(int size){
+        return size == -1 ? -1 : 2 * size;
     }
 
     private static ToolkitImage getResolutionVariant(Image image) {
--- a/jdk/src/share/classes/sun/awt/image/MultiResolutionToolkitImage.java	Fri May 23 11:13:54 2014 -0700
+++ b/jdk/src/share/classes/sun/awt/image/MultiResolutionToolkitImage.java	Mon May 26 14:33:49 2014 +0400
@@ -66,6 +66,14 @@
             final Image image, final ImageObserver observer,
             final int imgWidth, final int imgHeight,
             final int rvWidth, final int rvHeight) {
+        return getResolutionVariantObserver(image, observer,
+                imgWidth, imgHeight, rvWidth, rvHeight, false);
+    }
+
+    public static ImageObserver getResolutionVariantObserver(
+            final Image image, final ImageObserver observer,
+            final int imgWidth, final int imgHeight,
+            final int rvWidth, final int rvHeight, boolean concatenateInfo) {
 
         if (observer == null) {
             return null;
@@ -92,6 +100,11 @@
                                 y /= 2;
                             }
 
+                            if(concatenateInfo){
+                                flags &= ((ToolkitImage) image).
+                                        getImageRep().check(null);
+                            }
+
                             return observer.imageUpdate(
                                     image, flags, x, y, width, height);
                         };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/image/multiresolution/MultiResolutionToolkitImageTest.java	Mon May 26 14:33:49 2014 +0400
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.Toolkit;
+import java.awt.image.BufferedImage;
+import java.awt.image.ImageObserver;
+import static java.awt.image.ImageObserver.ALLBITS;
+import java.io.File;
+import javax.imageio.ImageIO;
+import sun.awt.OSInfo;
+import sun.awt.SunToolkit;
+import sun.awt.image.MultiResolutionToolkitImage;
+
+/**
+ * @test
+ * @bug 8040291
+ * @author Alexander Scherbatiy
+ * @summary [macosx] Http-Images are not fully loaded when using ImageIcon
+ * @run main MultiResolutionToolkitImageTest
+ */
+public class MultiResolutionToolkitImageTest {
+
+    private static final int IMAGE_WIDTH = 300;
+    private static final int IMAGE_HEIGHT = 200;
+    private static final Color COLOR_1X = Color.GREEN;
+    private static final Color COLOR_2X = Color.BLUE;
+    private static final String IMAGE_NAME_1X = "image.png";
+    private static final String IMAGE_NAME_2X = "image@2x.png";
+    private static final int WAIT_TIME = 400;
+    private static volatile boolean isImageLoaded = false;
+    private static volatile boolean isRVObserverCalled = false;
+
+    public static void main(String[] args) throws Exception {
+
+        if (!checkOS()) {
+            return;
+        }
+        generateImages();
+        testToolkitMultiResolutionImageLoad();
+    }
+
+    static void testToolkitMultiResolutionImageLoad() throws Exception {
+        File imageFile = new File(IMAGE_NAME_1X);
+        String fileName = imageFile.getAbsolutePath();
+        Image image = Toolkit.getDefaultToolkit().getImage(fileName);
+        SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit();
+        toolkit.prepareImage(image, -1, -1, new LoadImageObserver());
+
+        final long time = WAIT_TIME + System.currentTimeMillis();
+        while ((!isImageLoaded || !isRVObserverCalled)
+                && System.currentTimeMillis() < time) {
+            Thread.sleep(50);
+        }
+
+        if(!isImageLoaded){
+            throw new RuntimeException("Image is not loaded!");
+        }
+
+        if(!isRVObserverCalled){
+            throw new RuntimeException("Resolution Variant observer is not called!");
+        }
+    }
+
+    static void generateImages() throws Exception {
+        if (!new File(IMAGE_NAME_1X).exists()) {
+            generateImage(1);
+        }
+
+        if (!new File(IMAGE_NAME_2X).exists()) {
+            generateImage(2);
+        }
+    }
+
+    static void generateImage(int scale) throws Exception {
+        BufferedImage image = new BufferedImage(scale * IMAGE_WIDTH, scale * IMAGE_HEIGHT,
+                BufferedImage.TYPE_INT_RGB);
+        Graphics g = image.getGraphics();
+        g.setColor(scale == 1 ? COLOR_1X : COLOR_2X);
+        g.fillRect(0, 0, scale * IMAGE_WIDTH, scale * IMAGE_HEIGHT);
+        File file = new File(scale == 1 ? IMAGE_NAME_1X : IMAGE_NAME_2X);
+        ImageIO.write(image, "png", file);
+    }
+
+    static boolean checkOS() {
+        return OSInfo.getOSType() == OSInfo.OSType.MACOSX;
+    }
+
+    static class LoadImageObserver implements ImageObserver {
+
+        @Override
+        public boolean imageUpdate(Image img, int infoflags, int x, int y,
+                int width, int height) {
+
+            if (isRVObserver()) {
+                isRVObserverCalled = true;
+                SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit();
+                Image resolutionVariant = getResolutionVariant(img);
+                int rvFlags = toolkit.checkImage(resolutionVariant, width, height,
+                        new IdleImageObserver());
+                if (rvFlags < infoflags) {
+                    throw new RuntimeException("Info flags are greater than"
+                            + " resolution varint info flags");
+                }
+            } else if ((infoflags & ALLBITS) != 0) {
+                isImageLoaded = true;
+            }
+
+            return (infoflags & ALLBITS) == 0;
+        }
+    }
+
+    static boolean isRVObserver() {
+        Exception e = new Exception();
+
+        for (StackTraceElement elem : e.getStackTrace()) {
+            if (elem.getClassName().endsWith("MultiResolutionToolkitImage")) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    static class IdleImageObserver implements ImageObserver {
+
+        @Override
+        public boolean imageUpdate(Image img, int infoflags, int x, int y,
+                int width, int height) {
+            return false;
+        }
+    }
+
+    static Image getResolutionVariant(Image image) {
+        return ((MultiResolutionToolkitImage) image).getResolutionVariant();
+    }
+}