1 /* 2 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 /* 24 * @test 25 * @bug 8165212 26 * @summary This manual test case displays scale values of Graphics and the 27 * underlying device configuration. Any change to host display's DPI 28 * value should reflect corresponding changes in the scale values 29 * of both Frame and Backbuffer (VolatileImage). 30 * @run main/othervm/manual -Dsun.java2d.d3d=false -Dsun.java2d.opengl=false VolatileImageConfigurationTest 31 */ 32 import java.awt.BorderLayout; 33 import java.awt.FlowLayout; 34 import java.awt.Graphics; 35 import java.awt.Graphics2D; 36 import java.awt.GraphicsConfiguration; 37 import java.awt.Color; 38 import java.awt.event.ActionEvent; 39 import java.awt.event.ActionListener; 40 import java.awt.geom.AffineTransform; 41 import java.awt.image.VolatileImage; 42 import java.awt.HeadlessException; 43 import javax.swing.JFrame; 44 import javax.swing.JPanel; 45 import javax.swing.JTextArea; 46 import javax.swing.JButton; 47 import javax.swing.SwingUtilities; 48 49 public class VolatileImageConfigurationTest 50 extends JFrame 51 implements ActionListener { 52 /* Test frame and completion status */ 53 private static JFrame testFrame; 54 private static volatile boolean testComplete = false; 55 private static volatile boolean testResult = false; 56 57 /* Main frame's dimensions */ 58 private static final int TEST_WIDTH = 600; 59 private static final int TEST_HEIGHT = 600; 60 private static final int TEST_MIN_DURATION = 3000; 61 private static final int TEST_TOTAL_DURATION = 45000; 62 63 /* 64 * Frame will display information text explaining how to run the manual 65 * test, and two buttons- Pass and Fail to determine the end-result. 66 */ 67 private JTextArea infoTextArea; 68 private JPanel buttonPanel; 69 private JPanel testPanel; 70 private JButton passButton; 71 private JButton failButton; 72 VolatileImageConfigurationTest()73 public VolatileImageConfigurationTest() { 74 /* Default constructor. Initialize the UI components */ 75 super("Volatile Image Configuration Update Test"); 76 initComponents(); 77 } 78 initComponents()79 private void initComponents() { 80 /* Create the text area with steps to execute the test */ 81 String description 82 = "\n Volatile Image Configuration Update Test.\n" 83 + " 1. The test displays scale values of component and the" 84 + " underlying graphics device configuration.\n" 85 + " 2. Kindly change the display's DPI settings from OS" 86 + " control panel and observe the application.\n" 87 + " 3. Select Pass if the scale values for both component & " 88 + "underlying device configuration are updated as per the " 89 + "\ndisplay's DPI value.\n"; 90 infoTextArea = new JTextArea(description); 91 92 /* Create the test panel where user will observe the drawing */ 93 testPanel = new DisplayPanel(); 94 95 /* Create the buttons with event listeners */ 96 passButton = new JButton("Pass"); 97 passButton.setActionCommand("Pass"); 98 passButton.setEnabled(true); 99 passButton.addActionListener(this); 100 101 failButton = new JButton("Fail"); 102 failButton.setActionCommand("Fail"); 103 failButton.setEnabled(true); 104 failButton.addActionListener(this); 105 106 /* Add the buttons to a separate panel with flowlayout */ 107 buttonPanel = new JPanel(new FlowLayout()); 108 buttonPanel.add(passButton); 109 buttonPanel.add(failButton); 110 111 /* Add all the created components to the master frame */ 112 setLayout(new BorderLayout(10, 10)); 113 add(infoTextArea, BorderLayout.NORTH); 114 add(buttonPanel, BorderLayout.SOUTH); 115 add(testPanel, BorderLayout.CENTER); 116 117 /* Set the dimensions */ 118 setSize(TEST_WIDTH, TEST_HEIGHT); 119 } 120 121 @Override actionPerformed(ActionEvent e)122 public void actionPerformed(ActionEvent e) { 123 /* Button event listener */ 124 String command = e.getActionCommand(); 125 126 if (command.equals("Pass")) { 127 /* Test has passed. Dispose the frame with success message */ 128 testComplete = true; 129 testResult = true; 130 System.out.println("Test Passed."); 131 } else if (command.equals("Fail")) { 132 /* Test has failed. Dispose the frame and throw exception */ 133 testComplete = true; 134 testResult = false; 135 } 136 } 137 constructTestUI()138 private static void constructTestUI() { 139 /* Construct the test's user interface */ 140 testFrame = new VolatileImageConfigurationTest(); 141 testFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 142 testFrame.setLocationRelativeTo(null); 143 testFrame.setVisible(true); 144 } 145 destructTestUI()146 private static void destructTestUI() { 147 /* Destroy the test's user interface */ 148 testFrame.dispose(); 149 } 150 151 static class DisplayPanel extends JPanel { 152 /* Display panel settings */ 153 private static final int PANEL_WIDTH = 600; 154 private static final int PANEL_HEIGHT = 500; 155 private static final int PANEL_X = 20; 156 private static final int PANEL_Y = 80; 157 private static final String MSG = "%s scale: [%2.2f, %2.2f]"; 158 private VolatileImage vImg; 159 DisplayPanel()160 public DisplayPanel() throws HeadlessException { 161 setSize(PANEL_WIDTH, PANEL_HEIGHT); 162 } 163 164 @Override paint(Graphics g)165 public void paint(Graphics g) { 166 super.paint(g); 167 168 g.setColor(Color.WHITE); 169 g.fillRect(0, 0, PANEL_WIDTH, PANEL_HEIGHT); 170 /* Display graphics configuration values of the component */ 171 drawInfo(g, PANEL_X, PANEL_Y, "Frame", Color.BLUE); 172 int attempts = 0; 173 do { 174 /* Display graphics configuration values of volatile image */ 175 drawBackingStoreImage(g); 176 } while (vImg.contentsLost() && ++attempts < 3); 177 } 178 drawInfo(Graphics g, int x, int y, String msg, Color color)179 private void drawInfo(Graphics g, int x, int y, 180 String msg, Color color) { 181 g.setColor(color); 182 g.setFont(g.getFont().deriveFont(24f)); 183 Graphics2D g2d = (Graphics2D) g; 184 AffineTransform tx = g2d.getTransform(); 185 186 g.drawString(msg, x, y); 187 String text = String.format(MSG, 188 "Graphics", 189 tx.getScaleX(), 190 tx.getScaleY()); 191 int dy = 20; 192 g.drawString(text, x, y + dy); 193 194 tx = g2d.getDeviceConfiguration().getDefaultTransform(); 195 text = String.format(MSG, 196 "Device Config", 197 tx.getScaleX(), 198 tx.getScaleY()); 199 g.drawString(text, x, y + 2 * dy); 200 } 201 drawBackingStoreImage(Graphics g)202 private void drawBackingStoreImage(Graphics g) { 203 Graphics2D g2d = (Graphics2D) g; 204 GraphicsConfiguration gc = g2d.getDeviceConfiguration(); 205 if (vImg == null || 206 vImg.validate(gc) == VolatileImage.IMAGE_INCOMPATIBLE) { 207 /* Create a new volatile image */ 208 vImg = createVolatileImage(PANEL_WIDTH, PANEL_HEIGHT / 3); 209 } 210 211 Graphics vImgGraphics = vImg.createGraphics(); 212 vImgGraphics.setColor(Color.WHITE); 213 vImgGraphics.fillRect(0, 0, PANEL_WIDTH, PANEL_HEIGHT / 3); 214 drawInfo(vImgGraphics, 215 PANEL_X, 216 PANEL_Y, 217 "Backbuffer", 218 Color.MAGENTA); 219 g.drawImage(vImg, 0, PANEL_Y * 2, this); 220 } 221 } 222 main(String[] args)223 public static void main(String[] args) throws Exception { 224 SwingUtilities.invokeAndWait(new Runnable() { 225 @Override 226 public void run() { 227 try { 228 /* Construct the test interface */ 229 constructTestUI(); 230 } catch (Exception ex) { 231 /* Throw an exception indicating error while creating UI */ 232 throw new RuntimeException("Test Failed. Error while " 233 + "creating the test interface."); 234 } 235 } 236 }); 237 238 try { 239 /* Provide sufficient time for user to act upon the manual test */ 240 long totalWaitDuration = 0; 241 do { 242 Thread.sleep(TEST_MIN_DURATION); 243 totalWaitDuration += TEST_MIN_DURATION; 244 } while (!testComplete && totalWaitDuration < TEST_TOTAL_DURATION); 245 } catch(InterruptedException ite) { 246 /* No-op. The thread continues execution further */ 247 } 248 249 SwingUtilities.invokeAndWait(new Runnable() { 250 @Override 251 public void run() { 252 try { 253 /* Destroy the test interface */ 254 destructTestUI(); 255 } catch (Exception ex) { 256 /* No-op */ 257 } 258 } 259 }); 260 261 /* Check for the test result and throw exception if required */ 262 if (testResult == false) { 263 throw new RuntimeException("Test Failed. Incorrect scale values " 264 + "were seen during the test execution."); 265 } 266 } 267 }