undefect. CWE-407 — 63 sites patched across 27 ecosystems

Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com

Patches, unit tests, benchmarks, whitepaper, and outreach briefs.
Public domain — no copyright claimed. Use freely.
This commit is contained in:
russell@unturf.com 2026-03-26 17:11:57 -04:00
commit 0a580b313d
70422 changed files with 17213626 additions and 0 deletions

View file

@ -0,0 +1,215 @@
/*
* Copyright (c) 2015, 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.Dimension;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.BaseMultiResolutionImage;
import java.awt.image.MultiResolutionImage;
import java.util.List;
/**
* @test
* @bug 8029339
* @author Alexander Scherbatiy
* @summary Custom MultiResolution image support on HiDPI displays
* @run main BaseMultiResolutionImageTest
*/
public class BaseMultiResolutionImageTest {
public static void main(String[] args) {
testZeroRVIMages();
testNullRVIMages();
testNullRVIMage();
testIOOBException();
testRVSizes();
testBaseMRImage();
}
static void testZeroRVIMages() {
try {
new BaseMultiResolutionImage();
} catch (IllegalArgumentException ignored) {
return;
}
throw new RuntimeException("IllegalArgumentException is not thrown!");
}
static void testNullRVIMages() {
try {
new BaseMultiResolutionImage(null);
} catch (IllegalArgumentException ignored) {
return;
}
throw new RuntimeException("IllegalArgumentException is not thrown!");
}
static void testNullRVIMage() {
Image baseImage = new BufferedImage(10, 10, BufferedImage.TYPE_INT_RGB);
try {
new BaseMultiResolutionImage(baseImage, null);
} catch (NullPointerException ignored) {
return;
}
throw new RuntimeException("NullPointerException is not thrown!");
}
static void testIOOBException() {
for (int baseImageIndex : new int[]{-3, 2, 4}) {
try {
new BaseMultiResolutionImage(baseImageIndex,
createRVImage(0), createRVImage(1));
} catch (IndexOutOfBoundsException ignored) {
continue;
}
throw new RuntimeException("IndexOutOfBoundsException is not thrown!");
}
}
static void testRVSizes() {
int imageSize = getSize(1);
double[][] sizeArray = {
{-imageSize, imageSize},
{2 * imageSize, -2 * imageSize},
{Double.POSITIVE_INFINITY, imageSize},
{Double.POSITIVE_INFINITY, -imageSize},
{imageSize, Double.NEGATIVE_INFINITY},
{-imageSize, Double.NEGATIVE_INFINITY},
{Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY},
{Double.NaN, imageSize},
{imageSize, Double.NaN},
{Double.NaN, Double.NaN},
{Double.POSITIVE_INFINITY, Double.NaN}
};
for (double[] sizes : sizeArray) {
try {
MultiResolutionImage mrImage = new BaseMultiResolutionImage(
0, createRVImage(0), createRVImage(1));
mrImage.getResolutionVariant(sizes[0], sizes[1]);
} catch (IllegalArgumentException ignored) {
continue;
}
throw new RuntimeException("IllegalArgumentException is not thrown!");
}
}
static void testBaseMRImage() {
int baseIndex = 1;
int length = 3;
BufferedImage[] resolutionVariants = new BufferedImage[length];
for (int i = 0; i < length; i++) {
resolutionVariants[i] = createRVImage(i);
}
BaseMultiResolutionImage mrImage = new BaseMultiResolutionImage(baseIndex,
resolutionVariants);
List<Image> rvImageList = mrImage.getResolutionVariants();
if (rvImageList.size() != length) {
throw new RuntimeException("Wrong size of resolution variants list!");
}
for (int i = 0; i < length; i++) {
int imageSize = getSize(i);
Image testRVImage = mrImage.getResolutionVariant(imageSize, imageSize);
if (testRVImage != resolutionVariants[i]) {
throw new RuntimeException("Wrong resolution variant!");
}
if (rvImageList.get(i) != resolutionVariants[i]) {
throw new RuntimeException("Wrong resolution variant!");
}
}
BufferedImage baseImage = resolutionVariants[baseIndex];
if (baseImage.getWidth() != mrImage.getWidth(null)
|| baseImage.getHeight() != mrImage.getHeight(null)) {
throw new RuntimeException("Base image is wrong!");
}
boolean passed = false;
try {
rvImageList.set(0, createRVImage(10));
} catch (Exception e) {
passed = true;
}
if (!passed) {
throw new RuntimeException("Resolution variants list is modifiable!");
}
passed = false;
try {
rvImageList.remove(0);
} catch (Exception e) {
passed = true;
}
if (!passed) {
throw new RuntimeException("Resolution variants list is modifiable!");
}
passed = false;
try {
rvImageList.add(0, createRVImage(10));
} catch (Exception e) {
passed = true;
}
if (!passed) {
throw new RuntimeException("Resolution variants list is modifiable!");
}
passed = false;
try {
mrImage.getGraphics();
} catch (UnsupportedOperationException e) {
passed = true;
}
if (!passed) {
throw new RuntimeException("getGraphics() method shouldn't be supported!");
}
}
private static int getSize(int i) {
return 8 * (i + 1);
}
private static BufferedImage createRVImage(int i) {
return new BufferedImage(getSize(i), getSize(i),
BufferedImage.TYPE_INT_RGB);
}
}

View file

@ -0,0 +1,126 @@
/*
* Copyright (c) 2016, 2017, 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.
*/
/**
* @test
* @key headful
* @bug 8142406
* @author a.stepanov
* @summary [HiDPI] [macosx] check that for a pair of images
* (image.ext, image@2x.ext) the 1st one is loaded
* in case if the 2nd is corrupted
*
* @requires (os.family == "mac")
*
* @library /lib/client/
* @build ExtendedRobot
* @run main Corrupted2XImageTest
*/
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import javax.imageio.ImageIO;
public class Corrupted2XImageTest extends Frame {
private static final int SZ = 200;
private static final Color C = Color.BLUE;
private final String format, name1x, name2x;
public Corrupted2XImageTest(String format) throws IOException {
this.format = format;
name1x = "test." + format;
name2x = "test@2x." + format;
createFiles();
}
private void UI() {
setTitle(format);
setSize(SZ, SZ);
setResizable(false);
setLocation(50, 50);
setVisible(true);
}
@Override
public void paint(Graphics g) {
Image img = Toolkit.getDefaultToolkit().getImage(
new File(name1x).getAbsolutePath());
g.drawImage(img, 0, 0, this);
}
private void createFiles() throws IOException {
BufferedImage img =
new BufferedImage(SZ, SZ, BufferedImage.TYPE_INT_RGB);
Graphics g = img.getGraphics();
g.setColor(C);
g.fillRect(0, 0, SZ, SZ);
ImageIO.write(img, format, new File(name1x));
// corrupted @2x "image" - just a text file
Writer writer = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(new File(name2x)), "utf-8"));
writer.write("corrupted \"image\"");
writer.close();
}
// need this for jpg
private static boolean cmpColors(Color c1, Color c2) {
int tol = 10;
return (
Math.abs(c2.getRed() - c1.getRed() ) < tol &&
Math.abs(c2.getGreen() - c1.getGreen()) < tol &&
Math.abs(c2.getBlue() - c1.getBlue() ) < tol);
}
private void doTest() throws Exception {
ExtendedRobot r = new ExtendedRobot();
System.out.println("format: " + format);
r.waitForIdle(1000);
EventQueue.invokeAndWait(this::UI);
r.waitForIdle(1000);
Point loc = getLocationOnScreen();
Color c = r.getPixelColor(loc.x + SZ / 2, loc.y + SZ / 2);
if (!cmpColors(c, C)) {
throw new RuntimeException("test failed, color = " + c); }
System.out.println("ok");
dispose();
}
public static void main(String[] args) throws Exception {
// formats supported by Toolkit.getImage()
for (String format : new String[]{"gif", "jpg", "png"}) {
(new Corrupted2XImageTest(format)).doTest();
}
}
}

View file

@ -0,0 +1,69 @@
/*
* Copyright (c) 2021, 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.Graphics2D;
import java.awt.Image;
import java.awt.image.BaseMultiResolutionImage;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import static java.awt.image.BufferedImage.TYPE_INT_RGB;
/**
* @test
* @bug 8257500
* @summary Drawing MultiResolutionImage with ImageObserver may "leaks" memory
*/
public final class ImageObserverLeak {
public static void main(String[] args) throws Exception {
Reference<ImageObserver> ref = test();
while (!ref.refersTo(null)) {
Thread.sleep(500);
// Cannot generate OOM here, it will clear the SoftRefs as well
System.gc();
}
}
private static Reference<ImageObserver> test() throws Exception {
BufferedImage src = new BufferedImage(200, 200, TYPE_INT_RGB);
Image mri = new BaseMultiResolutionImage(src);
ImageObserver observer = new ImageObserver() {
@Override
public boolean imageUpdate(Image img, int infoflags, int x, int y,
int width, int height) {
return false;
}
};
Reference<ImageObserver> ref = new WeakReference<>(observer);
BufferedImage dst = new BufferedImage(200, 300, TYPE_INT_RGB);
Graphics2D g2d = dst.createGraphics();
g2d.drawImage(mri, 0, 0, observer);
g2d.dispose();
return ref;
}
}

View file

@ -0,0 +1,177 @@
/*
* Copyright (c) 2016, 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.
*/
/*
* @test
* @key headful
* @bug 8150258
* @author a.stepanov
* @summary Check that correct resolution variants are chosen for menu icons
* when multiresolution image is used for their construction.
*
* @library /lib/client/
* @build ExtendedRobot
* @run main/othervm -Dsun.java2d.uiScale=1 MenuMultiresolutionIconTest
* @run main/othervm -Dsun.java2d.uiScale=2 MenuMultiresolutionIconTest
*/
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
public class MenuMultiresolutionIconTest extends JPanel {
private final static int DELAY = 1000;
private final static int SZ = 50;
private final static String SCALE = "sun.java2d.uiScale";
private final static Color C1X = Color.RED, C2X = Color.BLUE;
private final ExtendedRobot r;
private static BufferedImage generateImage(int scale, Color c) {
int x = SZ * scale;
BufferedImage img = new BufferedImage(x, x, BufferedImage.TYPE_INT_RGB);
Graphics g = img.getGraphics();
g.setColor(c);
g.fillRect(0, 0, x, x);
return img;
}
private static BaseMultiResolutionImage createIcon() {
return new BaseMultiResolutionImage(new BufferedImage[] {
generateImage(1, C1X), generateImage(2, C2X)});
}
private JFrame frame;
private JPopupMenu popup;
private JMenuItem popupItem;
private JMenu menu;
public MenuMultiresolutionIconTest() throws Exception {
r = new ExtendedRobot();
SwingUtilities.invokeAndWait(this::createUI);
}
private void createUI() {
ImageIcon ii = new ImageIcon(createIcon());
popup = new JPopupMenu();
popupItem = new JMenuItem("test", ii);
popup.add(popupItem);
popupItem.setHorizontalTextPosition(JMenuItem.RIGHT);
addMouseListener(new MousePopupListener());
frame = new JFrame();
JMenuBar menuBar = new JMenuBar();
menu = new JMenu("test");
menuBar.add(menu);
menu.add(new JMenuItem("test", ii));
menu.add(new JRadioButtonMenuItem("test", ii, true));
menu.add(new JCheckBoxMenuItem("test", ii, true));
frame.setJMenuBar(menuBar);
frame.setContentPane(this);
frame.setSize(300, 300);
frame.setVisible(true);
}
private class MousePopupListener extends MouseAdapter {
@Override
public void mousePressed(MouseEvent e) { showPopup(e); }
@Override
public void mouseClicked(MouseEvent e) { showPopup(e); }
@Override
public void mouseReleased(MouseEvent e) { showPopup(e); }
private void showPopup(MouseEvent e) {
if (e.isPopupTrigger()) {
popup.show(MenuMultiresolutionIconTest.this, e.getX(), e.getY());
}
}
}
private boolean eqColors(Color c1, Color c2) {
int tol = 15;
return (
Math.abs(c2.getRed() - c1.getRed() ) < tol &&
Math.abs(c2.getGreen() - c1.getGreen()) < tol &&
Math.abs(c2.getBlue() - c1.getBlue() ) < tol);
}
private void checkIconColor(Point p, String what) {
String scale = System.getProperty(SCALE);
Color expected = "2".equals(scale) ? C2X : C1X;
Color c = r.getPixelColor(p.x + SZ / 2, p.y + SZ / 2);
if (!eqColors(c, expected)) {
frame.dispose();
throw new RuntimeException("invalid " + what + "menu item icon " +
"color, expected: " + expected + ", got: " + c);
}
System.out.println(what + "item icon check passed");
}
private void doTest() {
r.waitForIdle(2 * DELAY);
Point p = getLocationOnScreen();
r.mouseMove(p.x + getWidth() / 4, p.y + getHeight() / 4);
r.waitForIdle(DELAY);
r.click(InputEvent.BUTTON3_DOWN_MASK);
r.waitForIdle(DELAY);
p = popupItem.getLocationOnScreen();
checkIconColor(p, "popup ");
r.waitForIdle(DELAY);
p = menu.getLocationOnScreen();
r.mouseMove(p.x + menu.getWidth() / 2, p.y + menu.getHeight() / 2);
r.waitForIdle(DELAY);
r.click();
p = menu.getItem(0).getLocationOnScreen();
checkIconColor(p, "");
r.waitForIdle(DELAY);
p = menu.getItem(1).getLocationOnScreen();
checkIconColor(p, "radiobutton ");
r.waitForIdle(DELAY);
p = menu.getItem(2).getLocationOnScreen();
checkIconColor(p, "checkbox ");
r.waitForIdle(DELAY);
frame.dispose();
}
public static void main(String s[]) throws Exception {
(new MenuMultiresolutionIconTest()).doTest();
}
}

View file

@ -0,0 +1,169 @@
/*
* Copyright (c) 2016, 2024, 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.Dialog;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BaseMultiResolutionImage;
import java.awt.image.BufferedImage;
import javax.swing.JButton;
import jdk.test.lib.Platform;
import jtreg.SkippedException;
/*
* @test
* @bug 8142861 8143062 8147016
* @library /java/awt/regtesthelpers /test/lib
* @build PassFailJFrame jdk.test.lib.Platform
* @requires (os.family == "windows" | os.family == "mac")
* @summary Check if multiresolution image behaves properly
* on HiDPI + non-HiDPI display pair.
* @run main/manual MultiDisplayTest
*/
public class MultiDisplayTest {
private static final String INSTRUCTIONS =
"""
The test requires two-display configuration, where
- 1st display is operating in HiDPI mode;
- 2nd display is non-HiDPI.
In other cases please simply push "Pass".
To run test please push "Start".
Then drag parent / child to different displays and check
that the proper image is shown for every window
(must be "black 1x" for non-HiDPI and "blue 2x" for HiDPI).
Please try to drag both parent and child,
do it fast several times and check if no artefacts occur.
Try to switch display resolution (high to low and back).
For Mac OS X please check also the behavior for
translucent windows appearing on the 2nd (non-active) display
and Mission Control behavior.
Close the Child & Parent windows.
In case if no issues occur please push "Pass", otherwise "Fail".
""";
private static final int W = 200;
private static final int H = 200;
private static final BaseMultiResolutionImage IMG =
new BaseMultiResolutionImage(new BufferedImage[]{
generateImage(1, Color.BLACK), generateImage(2, Color.BLUE)});
public static void main(String[] args) throws Exception {
if (!checkOS()) {
throw new SkippedException("Invalid OS." +
"Please run test on either Windows or MacOS");
}
PassFailJFrame
.builder()
.title("MultiDisplayTest Instructions")
.instructions(INSTRUCTIONS)
.rows((int) INSTRUCTIONS.lines().count() + 2)
.columns(40)
.splitUIBottom(MultiDisplayTest::createAndShowGUI)
.build()
.awaitAndCheck();
}
public static JButton createAndShowGUI() {
JButton b = new JButton("Start");
b.addActionListener(e -> {
ParentFrame p = new ParentFrame();
new ChildDialog(p);
});
return b;
}
private static boolean checkOS() {
return Platform.isWindows() || Platform.isOSX();
}
private static BufferedImage generateImage(int scale, Color c) {
BufferedImage image = new BufferedImage(
scale * W, scale * H, BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
g.setColor(c);
g.fillRect(0, 0, scale * W, scale * H);
g.setColor(Color.WHITE);
Font f = g.getFont();
g.setFont(new Font(f.getName(), Font.BOLD, scale * 48));
g.drawChars((scale + "X").toCharArray(), 0, 2,
scale * W / 2, scale * H / 2);
return image;
}
private static class ParentFrame extends Frame {
public ParentFrame() {
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) { dispose(); }
});
setSize(W, H);
setLocation(50, 50);
setTitle("parent");
setResizable(false);
setVisible(true);
}
@Override
public void paint(Graphics gr) {
gr.drawImage(IMG, 0, 0, this);
}
}
private static class ChildDialog extends Dialog {
public ChildDialog(Frame f) {
super(f);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) { dispose(); }
});
setSize(W, H);
setTitle("child");
setResizable(false);
setModal(true);
setVisible(true);
}
@Override
public void paint(Graphics gr) {
gr.drawImage(IMG, 0, 0, this);
}
}
}

View file

@ -0,0 +1,113 @@
/*
* Copyright (c) 2015, 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.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.geom.Dimension2D;
import java.awt.image.BufferedImage;
import sun.awt.image.MultiResolutionCachedImage;
/**
* @test
* @bug 8132123
* @author Alexander Scherbatiy
* @summary MultiResolutionCachedImage unnecessarily creates base image to get
* its size
* @modules java.desktop/sun.awt.image
* @run main MultiResolutionCachedImageTest
*/
public class MultiResolutionCachedImageTest {
private static final Color TEST_COLOR = Color.BLUE;
public static void main(String[] args) {
Image image = new TestMultiResolutionCachedImage(100);
image.getWidth(null);
image.getHeight(null);
image.getProperty("comment", null);
int scaledSize = 50;
Image scaledImage = image.getScaledInstance(scaledSize, scaledSize,
Image.SCALE_SMOOTH);
if (!(scaledImage instanceof BufferedImage)) {
throw new RuntimeException("Wrong scaled image!");
}
BufferedImage buffScaledImage = (BufferedImage) scaledImage;
if (buffScaledImage.getWidth() != scaledSize
|| buffScaledImage.getHeight() != scaledSize) {
throw new RuntimeException("Wrong scaled image!");
}
if (buffScaledImage.getRGB(scaledSize / 2, scaledSize / 2) != TEST_COLOR.getRGB()) {
throw new RuntimeException("Wrong scaled image!");
}
}
private static Dimension2D getDimension(int size) {
return new Dimension(size, size);
}
private static Dimension2D[] getSizes(int size) {
return new Dimension2D[]{getDimension(size), getDimension(2 * size)};
}
private static Image createImage(int width, int height) {
BufferedImage buffImage = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
Graphics g = buffImage.createGraphics();
g.setColor(TEST_COLOR);
g.fillRect(0, 0, width, height);
return buffImage;
}
private static class TestMultiResolutionCachedImage
extends MultiResolutionCachedImage {
private final int size;
public TestMultiResolutionCachedImage(int size) {
super(size, size, getSizes(size), (w, h) -> createImage(w, h));
this.size = size;
}
@Override
public Image getResolutionVariant(double width, double height) {
if (width == size || height == size) {
throw new RuntimeException("Base image is requested!");
}
return super.getResolutionVariant(width, height);
}
@Override
protected Image getBaseImage() {
throw new RuntimeException("Base image is used");
}
}
}

View file

@ -0,0 +1,169 @@
/*
* Copyright (c) 2021, 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.
*/
/*
* @test
* @bug 8147648 8163160
* @summary [hidpi] multiresolution image: wrong resolution variant is used as
* icon in the Unity panel
* @requires os.family == "linux"
* @run main/manual/othervm -Dsun.java2d.uiScale=2 IconTest
*/
import java.awt.Color;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BaseMultiResolutionImage;
import java.awt.image.BufferedImage;
import java.util.concurrent.CountDownLatch;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class IconTest {
private final static int SZ = 8;
private static GridBagLayout layout;
private static JPanel mainControlPanel;
private static JPanel resultButtonPanel;
private static JLabel instructionText;
private static JButton passButton;
private static JButton failButton;
private static JButton testButton;
private static JFrame f;
private static CountDownLatch latch;
private static volatile boolean failed;
private static BufferedImage generateImage(int scale, Color c) {
int x = SZ * scale;
BufferedImage img = new BufferedImage(x, x, BufferedImage.TYPE_INT_RGB);
Graphics g = img.getGraphics();
try {
if (g != null) {
g.setColor(c);
g.fillRect(0, 0, x, x);
g.setColor(Color.GREEN);
g.drawRect(0, 0, x-1, x-1);
}
} finally {
g.dispose();
}
return img;
}
private static void createUI() throws Exception {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
f = new JFrame("TrayIcon Test");
final BaseMultiResolutionImage IMG = new BaseMultiResolutionImage(
new BufferedImage[]{generateImage(1, Color.RED), generateImage(2, Color.BLUE)});
layout = new GridBagLayout();
mainControlPanel = new JPanel(layout);
resultButtonPanel = new JPanel(layout);
f.setIconImage(IMG);
GridBagConstraints gbc = new GridBagConstraints();
String instructions
= "<html>INSTRUCTIONS:<br>"
+ "Check if test button icon and unity icon<br>"
+ "(icon in a side dock, if present)<br>"
+ "are both blue with green border.<br><br>"
+ "NB: Icon in the top bar may be presented in grayscale.<br><br>"
+ "If Icon color is blue press pass"
+ " else press fail.<br><br></html>";
instructionText = new JLabel();
instructionText.setText(instructions);
gbc.gridx = 0;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
mainControlPanel.add(instructionText, gbc);
testButton = new JButton("Test");
testButton.setActionCommand("Test");
mainControlPanel.add(testButton, gbc);
testButton.setIcon(new ImageIcon(IMG));
gbc.gridx = 0;
gbc.gridy = 0;
resultButtonPanel.add(testButton, gbc);
passButton = new JButton("Pass");
passButton.setActionCommand("Pass");
passButton.addActionListener((ActionEvent e) -> {
latch.countDown();
f.dispose();
});
failButton = new JButton("Fail");
failButton.setActionCommand("Fail");
failButton.addActionListener(e -> {
failed = true;
latch.countDown();
f.dispose();
});
gbc.gridx = 1;
gbc.gridy = 0;
resultButtonPanel.add(passButton, gbc);
gbc.gridx = 2;
gbc.gridy = 0;
resultButtonPanel.add(failButton, gbc);
gbc.gridx = 0;
gbc.gridy = 1;
mainControlPanel.add(resultButtonPanel, gbc);
f.add(mainControlPanel);
f.setSize(400, 200);
f.setLocationRelativeTo(null);
f.setVisible(true);
f.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
latch.countDown();
f.dispose();
}
});
}
});
}
public static void main(String[] args) throws Exception {
latch = new CountDownLatch(1);
createUI();
latch.await();
if (failed) {
throw new RuntimeException("Test Failed");
}
}
}

View file

@ -0,0 +1,207 @@
/*
* Copyright (c) 2016, 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.
*/
/**
* @test
* @key headful
* @bug 8149371 8169043
* @summary multi-res. image: -Dsun.java2d.uiScale does not work for Window
* icons (some ambiguity for Window.setIconImages()?)
* @requires (os.family == "windows")
* @run main/othervm/manual -Dsun.java2d.uiScale=2 MultiResIconTest
*/
import java.awt.Color;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BaseMultiResolutionImage;
import java.awt.image.BufferedImage;
import java.util.concurrent.CountDownLatch;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class MultiResIconTest {
private static GridBagLayout layout;
private static JPanel mainControlPanel;
private static JPanel resultButtonPanel;
private static JLabel instructionText;
private static JButton passButton;
private static JButton failButton;
private static JDialog f;
private static CountDownLatch latch;
private static TestFrame frame;
private static boolean testPassed;
private static BufferedImage generateImage(int x, Color c) {
BufferedImage img = new BufferedImage(x, x, BufferedImage.TYPE_INT_RGB);
Graphics g = img.getGraphics();
g.setColor(c);
g.fillRect(0, 0, x, x);
g.setColor(Color.WHITE);
g.fillRect(x / 3, x / 3, x / 3, x / 3);
return img;
}
public MultiResIconTest() throws Exception {
latch = new CountDownLatch(1);
createUI();
latch.await();
if (!testPassed) {
throw new RuntimeException("User Pressed Failed Button");
}
}
private static void createUI() throws Exception {
SwingUtilities.invokeAndWait(() -> {
frame = new TestFrame();
f = new JDialog(frame);
f.setTitle("Instruction Dialog");
layout = new GridBagLayout();
mainControlPanel = new JPanel(layout);
resultButtonPanel = new JPanel(layout);
GridBagConstraints gbc = new GridBagConstraints();
String instructions
= "<html> INSTRUCTIONS:<br>"
+ "This test is for Windows OS only.<br>"
+ "Make sure that 'Use Small Icons' setting is not set<br>"
+ "on Windows Taskbar Properties <br>"
+ "1) Test frame title icon and frame color should be green."
+ "<br>"
+ "2) Test frame task bar icon should be blue<br>"
+ "3) If color are same as mentioned in 1 and 2 press pass<br>"
+ " else press fail.<br><br></html>";
instructionText = new JLabel();
instructionText.setText(instructions);
gbc.gridx = 0;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
mainControlPanel.add(instructionText, gbc);
passButton = new JButton("Pass");
passButton.setActionCommand("Pass");
passButton.addActionListener((ActionEvent e) -> {
testPassed = true;
latch.countDown();
f.dispose();
frame.dispose();
});
failButton = new JButton("Fail");
failButton.setActionCommand("Fail");
failButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
testPassed = false;
latch.countDown();
f.dispose();
frame.dispose();
throw new RuntimeException("Test Failed");
}
});
gbc.gridx = 1;
gbc.gridy = 0;
resultButtonPanel.add(passButton, gbc);
gbc.gridx = 2;
gbc.gridy = 0;
resultButtonPanel.add(failButton, gbc);
gbc.gridx = 0;
gbc.gridy = 1;
mainControlPanel.add(resultButtonPanel, gbc);
f.add(mainControlPanel);
f.setSize(400, 200);
f.setLocationRelativeTo(null);
f.setVisible(true);
f.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
testPassed = false;
latch.countDown();
f.dispose();
frame.dispose();
}
});
});
}
private static class TestFrame extends JFrame {
private static final int W = 200;
private static final BaseMultiResolutionImage IMG
= new BaseMultiResolutionImage(
new BufferedImage[]{generateImage(W, Color.RED),
generateImage(2 * W, Color.GREEN),
generateImage(4 * W, Color.BLUE)});
private static final BaseMultiResolutionImage ICON
= new BaseMultiResolutionImage(
new BufferedImage[]{generateImage(16, Color.RED),
generateImage(32, Color.GREEN),
generateImage(64, Color.BLUE),
generateImage(128, Color.BLACK),
generateImage(256, Color.GRAY)});
public TestFrame() {
createUI();
}
private void createUI() {
setTitle("Test Frame");
setIconImage(ICON);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
dispose();
}
});
setSize(W, W);
setLocation(50, 50);
setResizable(false);
setVisible(true);
}
@Override
public void paint(Graphics gr) {
gr.drawImage(IMG, 0, 0, this);
}
}
public static void main(String[] args) throws Exception {
new MultiResIconTest();
}
}

View file

@ -0,0 +1,216 @@
/*
* Copyright (c) 2016, 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.*;
import java.awt.image.*;
import java.util.*;
/* @test
* @bug 8147966
* @summary test multiresolution image properties
* @author a.stepanov
*
* @run main MultiResolutionImagePropertiesTest
*/
public class MultiResolutionImagePropertiesTest {
private final static Map<String, String> PROPS;
static {
PROPS = new HashMap<>();
PROPS.put("one", "ONE");
PROPS.put("two", "TWO");
PROPS.put("three", "THREE");
PROPS.put("other", "OTHER");
PROPS.put("test", "TEST");
}
private final static int SZ = 100;
private final static Object UNDEF = Image.UndefinedProperty;
private static BufferedImage generateImage(int scale, Properties p) {
int x = (int) (SZ * scale);
BufferedImage tmp = new BufferedImage(x, x, BufferedImage.TYPE_INT_RGB);
return new BufferedImage(tmp.getColorModel(),
tmp.getRaster(),
tmp.isAlphaPremultiplied(),
p);
}
private static void checkProperties(BufferedImage img,
String keys[],
String undefined[]) {
boolean numOK = true;
if (keys.length == 0) {
numOK = (img.getPropertyNames() == null);
} else {
numOK = (img.getPropertyNames().length == keys.length);
}
if (!numOK) {
throw new RuntimeException("invalid number of properties");
}
for (String k: keys) {
if (!img.getProperty(k).equals(PROPS.get(k))) {
throw new RuntimeException("invalid property for name " + k);
}
}
for (String k: undefined) {
if (!img.getProperty(k).equals(UNDEF)) {
throw new RuntimeException("property for name " + k +
" must be undefined");
}
}
}
private static void checkProperties(BaseMultiResolutionImage img,
String keys[],
String undefined[]) {
for (String k: keys) {
if (!img.getProperty(k, null).equals(PROPS.get(k))) {
throw new RuntimeException("invalid property for name " + k);
}
}
for (String k: undefined) {
if (!img.getProperty(k, null).equals(UNDEF)) {
throw new RuntimeException("property for name " + k +
" must be undefined");
}
}
}
public static void main(String[] args) throws Exception {
String keys[] = new String[]{"one", "two", "three"};
String otherKeys[] = new String[]{"other", "test"};
String empty[] = new String[]{};
Properties props = new Properties();
for (String k: keys) { props.setProperty(k, PROPS.get(k)); }
Properties otherProps = new Properties();
for (String k: otherKeys) { otherProps.setProperty(k, PROPS.get(k)); }
Properties defaultProps = new Properties();
// === check the default state ===
BaseMultiResolutionImage image =
new BaseMultiResolutionImage(new BufferedImage[]{
generateImage(1, defaultProps),
generateImage(2, defaultProps),
generateImage(3, defaultProps)
});
for (Image var: image.getResolutionVariants()) {
if (((BufferedImage) var).getPropertyNames() != null) {
throw new RuntimeException("PropertyNames should be null");
}
}
// === default: base image is the 1st one ===
image =
new BaseMultiResolutionImage(new BufferedImage[]{
generateImage(1, props),
generateImage(2, otherProps),
generateImage(3, defaultProps)
});
checkProperties(image, keys, otherKeys);
BufferedImage var = (BufferedImage) image.getResolutionVariant(SZ, SZ);
checkProperties(var, keys, otherKeys);
var = (BufferedImage) image.getResolutionVariant(2 * SZ, 2 * SZ);
checkProperties(var, otherKeys, keys);
var = (BufferedImage) image.getResolutionVariant(3 * SZ, 3 * SZ);
checkProperties(var, empty, keys);
checkProperties(var, empty, otherKeys);
// === let the 2nd image be a base one ===
image =
new BaseMultiResolutionImage(1, new BufferedImage[]{
generateImage(1, props),
generateImage(2, otherProps),
generateImage(3, defaultProps)
});
checkProperties(image, otherKeys, keys);
var = (BufferedImage) image.getResolutionVariant(SZ, SZ);
checkProperties(var, keys, otherKeys);
var = (BufferedImage) image.getResolutionVariant(2 * SZ, 2 * SZ);
checkProperties(var, otherKeys, keys);
var = (BufferedImage) image.getResolutionVariant(3 * SZ, 3 * SZ);
checkProperties(var, empty, keys);
checkProperties(var, empty, otherKeys);
// === let the 3rd image be a base one ===
image =
new BaseMultiResolutionImage(2, new BufferedImage[]{
generateImage(1, defaultProps),
generateImage(2, defaultProps),
generateImage(3, props)
});
checkProperties(image, keys, otherKeys);
var = (BufferedImage) image.getResolutionVariant(SZ, SZ);
checkProperties(var, empty, keys);
checkProperties(var, empty, otherKeys);
var = (BufferedImage) image.getResolutionVariant(2 * SZ, 2 * SZ);
checkProperties(var, empty, keys);
checkProperties(var, empty, otherKeys);
var = (BufferedImage) image.getResolutionVariant(3 * SZ, 3 * SZ);
checkProperties(var, keys, otherKeys);
// === check the other properties don't affect base ===
checkProperties(
new BaseMultiResolutionImage(new BufferedImage[]{
generateImage(1, defaultProps),
generateImage(2, props),
generateImage(3, props)
}),
empty, keys);
checkProperties(
new BaseMultiResolutionImage(2, new BufferedImage[]{
generateImage(1, props),
generateImage(2, props),
generateImage(3, defaultProps)
}),
empty, keys);
}
}

View file

@ -0,0 +1,112 @@
/*
* Copyright (c) 2020, 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.
*/
/*
* @test
* @bug 8212226
* @summary Check that base image gets selected during painting
* if other resolution variants are not ready
* @run main MultiResolutionImageSelectionTest
*/
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.AbstractMultiResolutionImage;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
import java.awt.image.MultiResolutionImage;
import java.util.Arrays;
import java.util.List;
import static java.awt.image.BufferedImage.TYPE_INT_RGB;
public class MultiResolutionImageSelectionTest {
final static BufferedImage GOOD_IMAGE = new BufferedImage(200, 200,
TYPE_INT_RGB);
final static Image BAD_IMAGE= new Image() {
@Override
public int getWidth(ImageObserver observer) {
return -1;
}
@Override
public int getHeight(ImageObserver observer) {
return 1;
}
@Override
public ImageProducer getSource() {
return null;
}
@Override
public Graphics getGraphics() {
return null;
}
@Override
public Object getProperty(String name, ImageObserver observer) {
return null;
}
};
public static void main(String[] args) {
Graphics g = GOOD_IMAGE.createGraphics();
g.setColor(Color.RED);
g.fillRect(0, 0, GOOD_IMAGE.getWidth(), GOOD_IMAGE.getHeight());
g.dispose();
MultiResolutionImage mri = new AbstractMultiResolutionImage() {
@Override
protected Image getBaseImage() {
return GOOD_IMAGE;
}
@Override
public Image getResolutionVariant(double destImageWidth, double destImageHeight) {
if ((int)destImageHeight == 200) {
return GOOD_IMAGE;
} else {
return BAD_IMAGE;
}
}
@Override
public List<Image> getResolutionVariants() {
return Arrays.asList(BAD_IMAGE, GOOD_IMAGE, BAD_IMAGE);
}
};
BufferedImage target = new BufferedImage(500, 500, TYPE_INT_RGB);
Graphics2D g2d = target.createGraphics();
g2d.drawImage((Image) mri, 0, 0, 500, 500, null);
g2d.dispose();
if (Color.RED.getRGB() != target.getRGB(1, 1)) {
throw new RuntimeException("Wrong resolution variant was used");
}
}
}

View file

@ -0,0 +1,182 @@
/*
* Copyright (c) 2016, 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.
*/
/*
@test
@key headful
@bug 8150176 8150844
@author a.stepanov
@summary Check if correct resolution variant is used
for JOptionPane dialog / internal frame icons.
@library /lib/client/
@build ExtendedRobot
@run main/othervm/timeout=300 -Dsun.java2d.uiScale=1 MultiResolutionJOptionPaneIconTest
@run main/othervm/timeout=300 -Dsun.java2d.uiScale=2 MultiResolutionJOptionPaneIconTest
*/
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
public class MultiResolutionJOptionPaneIconTest implements ActionListener {
private final static Color C1X = Color.ORANGE, C2X = Color.CYAN;
private final boolean isInternal;
private volatile JFrame test;
private volatile JDialog dialog;
private volatile JInternalFrame frame;
private final JDesktopPane parentPane = new JDesktopPane();
private final JButton run = new JButton("run");
private final ExtendedRobot robot = new ExtendedRobot();
private static BufferedImage getSquare(int sz, Color c) {
BufferedImage img = new BufferedImage(sz, sz, BufferedImage.TYPE_INT_RGB);
Graphics g = img.getGraphics();
g.setColor(c);
g.fillRect(0, 0, sz, sz);
return img;
}
private static Icon getIcon() {
BaseMultiResolutionImage mri = new BaseMultiResolutionImage(
new BufferedImage[]{getSquare(16, C1X), getSquare(32, C2X)});
return new ImageIcon(mri);
}
public MultiResolutionJOptionPaneIconTest(boolean internal,
UIManager.LookAndFeelInfo lf) throws Exception {
UIManager.setLookAndFeel(lf.getClassName());
isInternal = internal;
robot.setAutoDelay(50);
SwingUtilities.invokeAndWait(this::UI);
}
private void UI() {
test = new JFrame();
test.setLayout(new BorderLayout());
test.add(parentPane, BorderLayout.CENTER);
run.addActionListener(this);
test.add(run, BorderLayout.SOUTH);
test.setUndecorated(true);
test.setSize(400, 300);
test.setLocation(50, 50);
test.setVisible(true);
}
private void disposeAll() {
if (dialog != null) { dialog.dispose(); }
if (frame != null) { frame.dispose(); }
if (test != null) { test.dispose(); }
}
public void doTest() throws Exception {
robot.waitForIdle(1000);
clickButton(robot);
robot.waitForIdle(2000);
Component c = isInternal ?
frame.getContentPane() : dialog.getContentPane();
System.out.println("\ncheck " + (isInternal ? "internal frame" :
"dialog") + " icon:");
Point pt = c.getLocationOnScreen();
checkColors(pt.x, c.getWidth(), pt.y, c.getHeight());
System.out.println("ok");
robot.waitForIdle();
SwingUtilities.invokeAndWait(this::disposeAll);
robot.waitForIdle();
}
private void checkColors(int x0, int w, int y0, int h) {
boolean is2x = "2".equals(System.getProperty("sun.java2d.uiScale"));
Color
expected = is2x ? C2X : C1X,
unexpected = is2x ? C1X : C2X;
for (int y = y0; y < y0 + h; y += 5) {
for (int x = x0; x < x0 + w; x += 5) {
Color c = robot.getPixelColor(x, y);
if (c.equals(unexpected)) {
throw new RuntimeException(
"invalid color was found, test failed");
} else if (c.equals(expected)) { return; }
}
}
// no icon found at all
throw new RuntimeException("the icon wasn't found");
}
private void showDialogOrFrame() {
JOptionPane pane = new JOptionPane("",
JOptionPane.DEFAULT_OPTION,
JOptionPane.INFORMATION_MESSAGE,
getIcon());
pane.setOptions(new Object[]{}); // no buttons
if (isInternal) {
frame = pane.createInternalFrame(parentPane, "");
frame.setLocation(0, 0);
frame.setVisible(true);
} else {
dialog = pane.createDialog(parentPane, "");
dialog.setVisible(true);
}
}
public void clickButton(ExtendedRobot robot) {
Point pt = run.getLocationOnScreen();
robot.mouseMove(pt.x + run.getWidth() / 2, pt.y + run.getHeight() / 2);
robot.waitForIdle();
robot.click();
}
@Override
public void actionPerformed(ActionEvent event) { showDialogOrFrame(); }
public static void main(String[] args) throws Exception {
for (UIManager.LookAndFeelInfo LF: UIManager.getInstalledLookAndFeels()) {
System.out.println("\nL&F: " + LF.getName());
(new MultiResolutionJOptionPaneIconTest(false, LF)).doTest();
(new MultiResolutionJOptionPaneIconTest(true , LF)).doTest();
}
}
}

View file

@ -0,0 +1,219 @@
/*
* Copyright (c) 2015, 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.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.awt.image.BaseMultiResolutionImage;
import static java.awt.RenderingHints.KEY_RESOLUTION_VARIANT;
import static java.awt.RenderingHints.VALUE_RESOLUTION_VARIANT_BASE;
import static java.awt.RenderingHints.VALUE_RESOLUTION_VARIANT_DPI_FIT;
import static java.awt.RenderingHints.VALUE_RESOLUTION_VARIANT_SIZE_FIT;
import static java.awt.RenderingHints.VALUE_RESOLUTION_VARIANT_DEFAULT;
import java.awt.geom.AffineTransform;
import java.awt.image.ColorModel;
import java.awt.image.Raster;
import sun.java2d.StateTrackable;
import sun.java2d.SunGraphics2D;
import sun.java2d.SurfaceData;
import sun.java2d.loops.SurfaceType;
/**
* @test
* @bug 8029339
* @author Alexander Scherbatiy
* @summary Custom MultiResolution image support on HiDPI displays
* @modules java.desktop/sun.java2d
* @modules java.desktop/sun.java2d.loops
* @run main MultiResolutionRenderingHintsTest
*/
public class MultiResolutionRenderingHintsTest {
private static final int BASE_SIZE = 200;
private static final Color[] COLORS = {
Color.CYAN, Color.GREEN, Color.BLUE, Color.ORANGE, Color.RED, Color.PINK
};
public static void main(String[] args) throws Exception {
int length = COLORS.length;
BufferedImage[] resolutionVariants = new BufferedImage[length];
for (int i = 0; i < length; i++) {
resolutionVariants[i] = createRVImage(getSize(i), COLORS[i]);
}
BaseMultiResolutionImage mrImage = new BaseMultiResolutionImage(
resolutionVariants);
// base
Color color = getImageColor(VALUE_RESOLUTION_VARIANT_BASE, mrImage, 2, 3);
if (!getColorForScale(1).equals(color)) {
throw new RuntimeException("Wrong base resolution variant!");
}
// dpi fit
color = getImageColor(VALUE_RESOLUTION_VARIANT_DPI_FIT, mrImage, 2, 3);
if (!getColorForScale(2).equals(color)) {
throw new RuntimeException("Resolution variant is not based on dpi!");
}
// size fit
color = getImageColor(VALUE_RESOLUTION_VARIANT_SIZE_FIT, mrImage, 2, 3);
if (!getColorForScale(6).equals(color)) {
throw new RuntimeException("Resolution variant is not based on"
+ " rendered size!");
}
// default
// depends on the policies of the platform
// just check that exception is not thrown
getImageColor(VALUE_RESOLUTION_VARIANT_DEFAULT, mrImage, 2, 3);
}
private static Color getColorForScale(int scale) {
return COLORS[scale - 1];
}
private static Color getImageColor(final Object renderingHint, Image image,
double configScale, double graphicsScale) {
int width = image.getWidth(null);
int height = image.getHeight(null);
TestSurfaceData surface = new TestSurfaceData(width, height, configScale);
SunGraphics2D g2d = new SunGraphics2D(surface,
Color.BLACK, Color.BLACK, null);
g2d.setRenderingHint(KEY_RESOLUTION_VARIANT, renderingHint);
g2d.scale(graphicsScale, graphicsScale);
g2d.drawImage(image, 0, 0, null);
g2d.dispose();
return surface.getColor(width / 2, height / 2);
}
private static int getSize(int i) {
return (i + 1) * BASE_SIZE;
}
private static BufferedImage createRVImage(int size, Color color) {
BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_INT_RGB);
Graphics g = image.createGraphics();
g.setColor(Color.BLACK);
g.fillRect(0, 0, size, size);
g.setColor(color);
g.fillOval(0, 0, size, size);
g.dispose();
return image;
}
static class TestGraphicsConfig extends GraphicsConfiguration {
private final double scale;
TestGraphicsConfig(double scale) {
this.scale = scale;
}
@Override
public GraphicsDevice getDevice() {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public ColorModel getColorModel() {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public ColorModel getColorModel(int transparency) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public AffineTransform getDefaultTransform() {
return AffineTransform.getScaleInstance(scale, scale);
}
@Override
public AffineTransform getNormalizingTransform() {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public Rectangle getBounds() {
throw new UnsupportedOperationException("Not supported yet.");
}
}
static class TestSurfaceData extends SurfaceData {
private final int width;
private final int height;
private final GraphicsConfiguration gc;
private final BufferedImage buffImage;
private final double scale;
public TestSurfaceData(int width, int height, double scale) {
super(StateTrackable.State.DYNAMIC, SurfaceType.Custom, ColorModel.getRGBdefault());
this.scale = scale;
gc = new TestGraphicsConfig(scale);
this.width = (int) Math.ceil(scale * width);
this.height = (int) Math.ceil(scale * height);
buffImage = new BufferedImage(this.width, this.height,
BufferedImage.TYPE_INT_RGB);
}
Color getColor(int x, int y) {
int sx = (int) Math.ceil(x * scale);
int sy = (int) Math.ceil(y * scale);
return new Color(buffImage.getRGB(sx, sy));
}
@Override
public SurfaceData getReplacement() {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public GraphicsConfiguration getDeviceConfiguration() {
return gc;
}
@Override
public Raster getRaster(int x, int y, int w, int h) {
return buffImage.getRaster();
}
@Override
public Rectangle getBounds() {
return new Rectangle(0, 0, width, height);
}
@Override
public Object getDestination() {
throw new UnsupportedOperationException("Not supported yet.");
}
}
}

View file

@ -0,0 +1,160 @@
/*
* Copyright (c) 2014, 2021, 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 java.io.File;
import javax.imageio.ImageIO;
import sun.awt.OSInfo;
import sun.awt.SunToolkit;
import sun.awt.image.MultiResolutionToolkitImage;
/**
* @test
* @key headful
* @bug 8040291 8257500
* @requires os.family == "mac"
* @summary [macosx] Http-Images are not fully loaded when using ImageIcon
* @modules java.desktop/sun.awt
* java.desktop/sun.awt.image
* @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("ObserverCache")) {
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();
}
}

View file

@ -0,0 +1,194 @@
/*
* Copyright (c) 2016, 2020, 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.
*/
/**
* @test
* @key headful
* @bug 8150176 8151773 8150176 8241791
* @summary Check if correct resolution variant is used for tray icon.
* @run main/manual/othervm -Dsun.java2d.uiScale=2 MultiResolutionTrayIconTest
*/
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.SystemTray;
import java.awt.TrayIcon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BaseMultiResolutionImage;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public class MultiResolutionTrayIconTest {
private static SystemTray tray;
private static TrayIcon icon;
private static GridBagLayout layout;
private static JPanel mainControlPanel;
private static JPanel resultButtonPanel;
private static JLabel instructionText;
private static JButton passButton;
private static JButton failButton;
private static JButton startButton;
private static JFrame mainFrame;
private static CountDownLatch latch;
public static void main(String[] args) throws Exception {
latch = new CountDownLatch(1);
createUI();
latch.await(200, TimeUnit.SECONDS);
}
public static void createUI() throws Exception {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
mainFrame = new JFrame("TrayIcon Test");
if (!SystemTray.isSupported()) {
System.out.println("system tray is not supported");
latch.countDown();
return;
}
tray = SystemTray.getSystemTray();
Dimension d = tray.getTrayIconSize();
icon = new TrayIcon(createIcon(d.width, d.height));
icon.setImageAutoSize(true);
layout = new GridBagLayout();
mainControlPanel = new JPanel(layout);
resultButtonPanel = new JPanel(layout);
GridBagConstraints gbc = new GridBagConstraints();
String instructions
= "<html>INSTRUCTIONS:<br>"
+ "Press start button to add icon to system tray.<br><br>"
+ "If Icon color is green test"
+ " passes else failed.<br><br></html>";
instructionText = new JLabel();
instructionText.setText(instructions);
gbc.gridx = 0;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
mainControlPanel.add(instructionText, gbc);
startButton = new JButton("Start");
startButton.setActionCommand("Start");
startButton.addActionListener((ActionEvent e) -> {
doTest();
});
gbc.gridx = 0;
gbc.gridy = 0;
resultButtonPanel.add(startButton, gbc);
passButton = new JButton("Pass");
passButton.setActionCommand("Pass");
passButton.addActionListener((ActionEvent e) -> {
latch.countDown();
removeIcon();
mainFrame.dispose();
});
failButton = new JButton("Fail");
failButton.setActionCommand("Fail");
failButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
removeIcon();
latch.countDown();
mainFrame.dispose();
throw new RuntimeException("Test Failed");
}
});
gbc.gridx = 1;
gbc.gridy = 0;
resultButtonPanel.add(passButton, gbc);
gbc.gridx = 2;
gbc.gridy = 0;
resultButtonPanel.add(failButton, gbc);
gbc.gridx = 0;
gbc.gridy = 1;
mainControlPanel.add(resultButtonPanel, gbc);
mainFrame.add(mainControlPanel);
mainFrame.setSize(400, 200);
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible(true);
mainFrame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
removeIcon();
latch.countDown();
mainFrame.dispose();
}
});
}
});
}
private static BaseMultiResolutionImage createIcon(int w, int h) {
return new BaseMultiResolutionImage(
new BufferedImage[]{generateImage(w, h, 1, Color.RED),
generateImage(w, h, 2, Color.GREEN)});
}
private static BufferedImage generateImage(int w, int h, int scale, Color c) {
int x = w * scale, y = h * scale;
BufferedImage img = new BufferedImage(x, y, BufferedImage.TYPE_INT_RGB);
Graphics g = img.getGraphics();
g.setColor(c);
g.fillRect(0, 0, x, y);
g.setColor(Color.WHITE);
g.fillRect(x / 3, y / 3, x / 3, y / 3);
return img;
}
private static void doTest() {
if (tray.getTrayIcons().length > 0) {
return;
}
try {
tray.add(icon);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static void removeIcon() {
if (tray != null) {
tray.remove(icon);
}
}
}

View file

@ -0,0 +1,228 @@
/*
* Copyright (c) 2016, 2022, 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.
*/
/*
* @test
* @key headful
* @bug 8150724 8151303
* @author a.stepanov
* @summary Check that correct resolution variants are chosen for icons
* when multiresolution image is used for their construction.
*
* @library /lib/client/
* @build ExtendedRobot
* @run main/othervm/timeout=240 -Dsun.java2d.uiScale=1 MultiresolutionIconTest
* @run main/othervm/timeout=240 -Dsun.java2d.uiScale=2 MultiresolutionIconTest
*/
// TODO: please remove the "@requires" tag after 8151303 fix
import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.image.BaseMultiResolutionImage;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class MultiresolutionIconTest extends JFrame {
private final static int SZ = 100;
private final static int N = 5; // number of components
private final static String SCALE = "sun.java2d.uiScale";
private final static Color C1X = Color.RED;
private final static Color C2X = Color.BLUE;
private JLabel lbl;
private JTabbedPane tabbedPane;
private final ExtendedRobot r;
private static BufferedImage generateImage(int sz, Color c) {
BufferedImage img = new BufferedImage(sz, sz, BufferedImage.TYPE_INT_RGB);
Graphics g = img.getGraphics();
g.setColor(c);
g.fillRect(0, 0, sz, sz);
return img;
}
public MultiresolutionIconTest(UIManager.LookAndFeelInfo lf) throws Exception {
UIManager.setLookAndFeel(lf.getClassName());
r = new ExtendedRobot();
SwingUtilities.invokeAndWait(this::UI);
}
private void UI() {
setUndecorated(true);
BufferedImage img1x = generateImage(SZ / 2, C1X);
BufferedImage img2x = generateImage(SZ, C2X);
BaseMultiResolutionImage mri = new BaseMultiResolutionImage(
new BufferedImage[]{img1x, img2x});
Icon icon = new ImageIcon(mri);
// hardcoded icon size for OS X (Mac OS X L&F) - see JDK-8151060
BufferedImage tab1x = generateImage(16, C1X);
BufferedImage tab2x = generateImage(32, C2X);
BaseMultiResolutionImage tabMRI = new BaseMultiResolutionImage(
new BufferedImage[]{tab1x, tab2x});
Icon tabIcon = new ImageIcon(tabMRI);
setSize((N + 1) * SZ, SZ);
setLocation(50, 50);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().setLayout(new GridLayout(1, 1));
JPanel p = new JPanel();
p.setLayout(new GridLayout(1, N));
JButton btn = new JButton(icon);
p.add(btn);
JToggleButton tbn = new JToggleButton(icon);
p.add(tbn);
JRadioButton rbn = new JRadioButton(icon);
rbn.setHorizontalAlignment(SwingConstants.CENTER);
p.add(rbn);
JCheckBox cbx = new JCheckBox(icon);
cbx.setHorizontalAlignment(SwingConstants.CENTER);
p.add(cbx);
lbl = new JLabel(icon);
p.add(lbl);
tabbedPane = new JTabbedPane(JTabbedPane.LEFT);
tabbedPane.addTab("", tabIcon, p);
getContentPane().add(tabbedPane);
setResizable(false);
setVisible(true);
}
private boolean checkPressedColor(int x, int y, Color ok) {
r.mouseMove(x+5, y+5);
r.waitForIdle();
r.mousePress(InputEvent.BUTTON1_DOWN_MASK);
r.waitForIdle(100);
Color c = r.getPixelColor(x, y);
r.waitForIdle(100);
r.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
r.waitForIdle(100);
if (!c.equals(ok)) { return false; }
// check the icon's color hasn't changed
// after the mouse was released
c = r.getPixelColor(x, y);
return c.equals(ok);
}
private boolean checkTabIcon(
int xStart, int xEnd, int yStart, int yEnd, Color ok, Color nok) {
for (int y = yStart; y < yEnd; y += 2) {
for (int x = xStart; x < xEnd; x += 2) {
Color c = r.getPixelColor(x, y);
if (c.equals(nok)) { return false; }
else if (c.equals(ok)) {
// shift a bit to avoid the selection effects
return checkPressedColor(x + 5, y + 5, ok);
}
}
}
return false; // didn't find the icon
}
private void doTest() {
r.waitForIdle(2000);
String scale = System.getProperty(SCALE);
boolean is2x = "2".equals(scale);
Color expected = is2x ? C2X : C1X;
Color unexpected = is2x ? C1X : C2X;
Point p = lbl.getLocationOnScreen();
int x = p.x + lbl.getWidth() / 2;
int y = p.y + lbl.getHeight() / 2;
int w = lbl.getWidth();
boolean ok = true, curr;
Color c;
String components[] = new String[]{
"JLabel", "JCheckBox", "JRadioButton", "JToggleButton", "JButton"};
for (int i = 0; i < N; i++) {
curr = true;
int t = x - i * w;
// check icon color
c = r.getPixelColor(t, y);
System.out.print(components[i] + " icon: ");
if (!c.equals(expected)) {
curr = false;
} else {
// check icon color when mouse button pressed - see JDK-8151303
curr = checkPressedColor(t, y, expected);
}
System.out.println(curr ? "ok" : "nok");
ok = ok && curr;
r.waitForIdle();
}
int x0 = tabbedPane.getLocationOnScreen().x;
int x1 = x - ((N - 1) * w + w / 2);
int y0 = getLocationOnScreen().y;
int y1 = y0 + getHeight();
curr = checkTabIcon(x0, x1, y0, y1, expected, unexpected);
System.out.println("JTabbedPane icon: " + (curr ? "ok" : "nok"));
ok = ok && curr;
if (!ok) { throw new RuntimeException("test failed"); }
r.waitForIdle();
dispose();
}
public static void main(String[] args) throws Exception {
for (UIManager.LookAndFeelInfo LF: UIManager.getInstalledLookAndFeels()) {
// skip AquaL&F because Aqua icon darkening fails the test
if (LF.getName().equalsIgnoreCase("Mac OS X")) {
continue;
}
System.out.println("\nL&F: " + LF.getName());
(new MultiresolutionIconTest(LF)).doTest();
}
}
}

View file

@ -0,0 +1,169 @@
/*
* Copyright (c) 2016, 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.
*/
/*
* @test
* @bug 8151269
* @author a.stepanov
* @summary Multiresolution image: check that the base resolution variant
* source is passed to the corresponding ImageConsumer
* @run main MultiresolutionSourceTest
*/
import java.awt.*;
import java.awt.image.*;
public class MultiresolutionSourceTest {
private static class Checker implements ImageConsumer {
private final int refW, refH, refType;
private final boolean refHasAlpha;
private final Color refColor;
public Checker(int w,
int h,
Color c,
boolean hasAlpha,
int transferType) {
refW = w;
refH = h;
refColor = c;
refHasAlpha = hasAlpha;
refType = transferType;
}
@Override
public void imageComplete(int status) {}
@Override
public void setColorModel(ColorModel model) {
boolean a = model.hasAlpha();
if (a != refHasAlpha) {
throw new RuntimeException("invalid hasAlpha: " + a);
}
int tt = model.getTransferType();
if (tt != refType) {
throw new RuntimeException("invalid transfer type: " + tt);
}
}
@Override
public void setDimensions(int w, int h) {
if (w != refW) { throw new RuntimeException("invalid width: " + w +
", expected: " + refW); }
if (h != refH) { throw new RuntimeException("invalid height: " + h +
", expected: " + refH); }
}
@Override
public void setHints(int flags) {}
@Override
public void setPixels(int x, int y, int w, int h, ColorModel model,
byte pixels[], int offset, int scansize) {
for (int i = 0; i < pixels.length; i++) {
int p = pixels[i];
// just in case...
Color c = model.hasAlpha() ?
new Color(model.getRed (p),
model.getGreen(p),
model.getBlue (p),
model.getAlpha(p)) :
new Color(model.getRGB(p));
if (!c.equals(refColor)) {
throw new RuntimeException("invalid color: " + c +
", expected: " + refColor);
}
}
}
@Override
public void setPixels(int x, int y, int w, int h, ColorModel model,
int pixels[], int offset, int scansize) {
for (int i = 0; i < pixels.length; i++) {
int p = pixels[i];
Color c = model.hasAlpha() ?
new Color(model.getRed (p),
model.getGreen(p),
model.getBlue (p),
model.getAlpha(p)) :
new Color(model.getRGB(p));
if (!c.equals(refColor)) {
throw new RuntimeException("invalid color: " + c +
", expected: " + refColor);
}
}
}
@Override
public void setProperties(java.util.Hashtable props) {}
}
private static BufferedImage generateImage(int w, int h, Color c, int type) {
BufferedImage img = new BufferedImage(w, h, type);
Graphics g = img.getGraphics();
g.setColor(c);
g.fillRect(0, 0, w, h);
return img;
}
public static void main(String[] args) {
final int w1 = 20, w2 = 100, h1 = 30, h2 = 50;
final Color
c1 = new Color(255, 0, 0, 100), c2 = Color.BLACK, gray = Color.GRAY;
BufferedImage img1 =
generateImage(w1, h1, c1, BufferedImage.TYPE_INT_ARGB);
BufferedImage dummy =
generateImage(w1 + 5, h1 + 5, gray, BufferedImage.TYPE_BYTE_GRAY);
BufferedImage img2 =
generateImage(w2, h2, c2, BufferedImage.TYPE_BYTE_BINARY);
BufferedImage vars[] = new BufferedImage[] {img1, dummy, img2};
// default base image index (zero)
BaseMultiResolutionImage mri1 = new BaseMultiResolutionImage(vars);
// base image index = 2
BaseMultiResolutionImage mri2 = new BaseMultiResolutionImage(2, vars);
// do checks
mri1.getSource().startProduction(
new Checker(w1, h1, c1, true, DataBuffer.TYPE_INT));
mri2.getSource().startProduction(
new Checker(w2, h2, c2, false, DataBuffer.TYPE_BYTE));
}
}