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 }