JOGL v2.6.0-rc-20250706
JOGL, High-Performance Graphics Binding for Java™ (public API).
TestTiledPrintingNIOImageSwingAWT.java
Go to the documentation of this file.
1/**
2 * Copyright 2013 JogAmp Community. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification, are
5 * permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this list of
8 * conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
15 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * The views and conclusions contained in the software and documentation are those of the
25 * authors and should not be interpreted as representing official policies, either expressed
26 * or implied, of JogAmp Community.
27 */
28
29package com.jogamp.opengl.test.junit.jogl.tile;
30
31import java.awt.BorderLayout;
32import java.awt.Button;
33import java.awt.Container;
34import java.awt.Dimension;
35import java.awt.Frame;
36import java.awt.Graphics2D;
37import java.awt.Insets;
38import java.awt.Label;
39import java.awt.RenderingHints;
40import java.awt.image.BufferedImage;
41import java.io.BufferedReader;
42import java.io.File;
43import java.io.IOException;
44import java.io.InputStreamReader;
45import java.lang.reflect.InvocationTargetException;
46
47import javax.imageio.ImageIO;
48import com.jogamp.opengl.GLCapabilities;
49import com.jogamp.opengl.GLProfile;
50import com.jogamp.opengl.awt.GLJPanel;
51import javax.swing.BorderFactory;
52import javax.swing.JButton;
53import javax.swing.JComponent;
54import javax.swing.JFrame;
55import javax.swing.JLayeredPane;
56import javax.swing.JPanel;
57import javax.swing.SwingUtilities;
58
59import org.junit.AfterClass;
60import org.junit.Assert;
61import org.junit.BeforeClass;
62import org.junit.FixMethodOrder;
63import org.junit.Test;
64import org.junit.runners.MethodSorters;
65
66import com.jogamp.common.util.awt.AWTEDTExecutor;
67import com.jogamp.nativewindow.awt.AWTPrintLifecycle;
68import com.jogamp.nativewindow.awt.DirectDataBufferInt;
69import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
70import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears;
71import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
72import com.jogamp.opengl.test.junit.util.UITestCase;
73import com.jogamp.opengl.util.texture.TextureIO;
74
75@FixMethodOrder(MethodSorters.NAME_ASCENDING)
77
78 static boolean waitForKey = false;
79 /** only when run manually .. */
80 static boolean allow600dpi = false;
81 static GLProfile glp;
82 static int width, height;
83
84 @BeforeClass
85 public static void initClass() {
88 Assert.assertNotNull(glp);
89 width = 640;
90 height = 480;
91 } else {
92 setTestSupported(false);
93 }
94 // Runtime.getRuntime().traceInstructions(true);
95 // Runtime.getRuntime().traceMethodCalls(true);
96 }
97
98 @AfterClass
99 public static void releaseClass() {
100 }
101
102 protected void printOffscreenToFile(final BufferedImage image, final Frame frame, final GLCapabilities caps, final int num, final String detail) {
103 final Insets frameInsets = frame.getInsets();
104 final int frameWidth = frame.getWidth();
105 final int frameHeight= frame.getHeight();
106 final int imageWidth = image.getWidth();
107 final int imageHeight= image.getHeight();
108 final double scaleComp72;
109 // Note: Frame size contains the frame border (i.e. insets)!
110 {
111 final double sx = (double)imageWidth / frameWidth;
112 final double sy = (double)imageHeight / frameHeight;
113 scaleComp72 = Math.min(sx, sy);
114 }
115 System.err.println("PRINT DPI: scaleComp72 "+scaleComp72+", image-size "+imageWidth+"x"+imageHeight+", frame[border "+frameInsets+", size "+frameWidth+"x"+frameHeight+"]");
116
117 System.err.println("XXX: image "+image);
118 System.err.println("XXX: cm "+image.getColorModel());
119 System.err.println("XXX: raster "+image.getRaster());
120 System.err.println("XXX: dataBuffer "+image.getRaster().getDataBuffer());
121
122 AWTEDTExecutor.singleton.invoke(true, new Runnable() {
123 public void run() {
124 final Graphics2D g2d = (Graphics2D) image.getGraphics();
125 g2d.setClip(0, 0, image.getWidth(), image.getHeight());
126 g2d.scale(scaleComp72, scaleComp72);
127 // g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
128 g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
129
130 // frame.paintAll(g2d);
131 final AWTPrintLifecycle.Context ctx = AWTPrintLifecycle.Context.setupPrint(frame, 1.0/scaleComp72, 1.0/scaleComp72, 0, -1, -1);
132 try {
133 frame.printAll(g2d);
134 } finally {
135 ctx.releasePrint();
136 }
137 // to file
138 final String fname = getSnapshotFilename(num, detail, caps, image.getWidth(), image.getHeight(), false, TextureIO.PNG, null);
139 System.err.println("XXX file "+fname);
140 final File fout = new File(fname);
141 try {
142 ImageIO.write(image, "png", fout);
143 } catch (final IOException e) {
144 e.printStackTrace();
145 }
146 } });
147 }
148
149 protected void runTestGL(final GLCapabilities caps, final boolean layered) throws InterruptedException, InvocationTargetException {
150 final int layerStepX = width/6, layerStepY = height/6;
151 final Dimension glc_sz = new Dimension(layered ? width - 2*layerStepX : width/2, layered ? height - 2*layerStepY : height);
152 final GLJPanel glJPanel1 = new GLJPanel(caps);
153 Assert.assertNotNull(glJPanel1);
154 glJPanel1.setMinimumSize(glc_sz);
155 glJPanel1.setPreferredSize(glc_sz);
156 if( layered ) {
157 glJPanel1.setBounds(layerStepX/2, layerStepY/2, glc_sz.width, glc_sz.height);
158 } else {
159 glJPanel1.setBounds(0, 0, glc_sz.width, glc_sz.height);
160 }
161 glJPanel1.addGLEventListener(new Gears());
162
163 final GLJPanel glJPanel2 = new GLJPanel(caps);
164 Assert.assertNotNull(glJPanel2);
165 glJPanel2.setMinimumSize(glc_sz);
166 glJPanel2.setPreferredSize(glc_sz);
167 if( layered ) {
168 glJPanel2.setBounds(3*layerStepY, 2*layerStepY, glc_sz.width, glc_sz.height);
169 } else {
170 glJPanel2.setBounds(0, 0, glc_sz.width, glc_sz.height);
171 }
172 glJPanel2.addGLEventListener(new RedSquareES2());
173 // glJPanel2.addGLEventListener(new Gears());
174
175 final JComponent demoPanel;
176 if( layered ) {
177 glJPanel1.setOpaque(true);
178 glJPanel2.setOpaque(false);
179 final Dimension lsz = new Dimension(width, height);
180 demoPanel = new JLayeredPane();
181 demoPanel.setMinimumSize(lsz);
182 demoPanel.setPreferredSize(lsz);
183 demoPanel.setBounds(0, 0, lsz.width, lsz.height);
184 demoPanel.setBorder(BorderFactory.createTitledBorder("Layered Pane"));
185 demoPanel.add(glJPanel1, JLayeredPane.DEFAULT_LAYER);
186 demoPanel.add(glJPanel2, Integer.valueOf(1));
187 final JButton tb = new JButton("On Top");
188 tb.setBounds(4*layerStepY, 3*layerStepY, 100, 50);
189 demoPanel.add(tb, Integer.valueOf(2));
190 } else {
191 demoPanel = new JPanel();
192 demoPanel.add(glJPanel1);
193 demoPanel.add(glJPanel2);
194 }
195
196 final JFrame frame = new JFrame("Swing Print");
197 Assert.assertNotNull(frame);
198
199 final Button print72DPIButton = new Button("72dpi"); // dummy
200 final Button print300DPIButton = new Button("300dpi"); // dummy
201 final Button print600DPIButton = new Button("600dpi"); // dummy
202
203 final JPanel printPanel = new JPanel();
204 printPanel.add(print72DPIButton);
205 printPanel.add(print300DPIButton);
206 printPanel.add(print600DPIButton);
207 final JPanel southPanel = new JPanel();
208 southPanel.add(new Label("South"));
209 final JPanel eastPanel = new JPanel();
210 eastPanel.add(new Label("East"));
211 final JPanel westPanel = new JPanel();
212 westPanel.add(new Label("West"));
213
214 SwingUtilities.invokeAndWait(new Runnable() {
215 public void run() {
216 final Container fcont = frame.getContentPane();
217 fcont.setLayout(new BorderLayout());
218 fcont.add(printPanel, BorderLayout.NORTH);
219 fcont.add(demoPanel, BorderLayout.CENTER);
220 fcont.add(southPanel, BorderLayout.SOUTH);
221 fcont.add(eastPanel, BorderLayout.EAST);
222 fcont.add(westPanel, BorderLayout.WEST);
223 fcont.validate();
224 frame.pack();
225 frame.setVisible(true);
226 } } ) ;
227
228 Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true, null));
229 Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glJPanel1, true, null));
230 Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glJPanel2, true, null));
231
232 // paint offscreen: array 72dpi ARGB
233 {
234 final BufferedImage image = new BufferedImage(frame.getWidth(), frame.getHeight(), BufferedImage.TYPE_INT_ARGB);
235 printOffscreenToFile(image, frame, caps, 0, "array_072dpi_argb");
236 }
237 // paint offscreen: NIO 72dpi ARGB
238 {
239 final BufferedImage image = DirectDataBufferInt.createBufferedImage(frame.getWidth(), frame.getHeight(), BufferedImage.TYPE_INT_ARGB, null /* location */, null /* properties */);
240 printOffscreenToFile(image, frame, caps, 1, "newio_072dpi_argb");
241 }
242 // paint offscreen: NIO 150dpi ARGB
243 {
244 final int scale = (int) ( 150.0 / 72.0 + 0.5 );
245 final BufferedImage image = DirectDataBufferInt.createBufferedImage(frame.getWidth()*scale, frame.getHeight()*scale, BufferedImage.TYPE_INT_ARGB, null /* location */, null /* properties */);
246 printOffscreenToFile(image, frame, caps, 2, "newio_150dpi_argb");
247 }
248 // paint offscreen: NIO 150dpi ARGB_PRE
249 {
250 final int scale = (int) ( 150.0 / 72.0 + 0.5 );
251 final BufferedImage image = DirectDataBufferInt.createBufferedImage(frame.getWidth()*scale, frame.getHeight()*scale, BufferedImage.TYPE_INT_ARGB_PRE, null /* location */, null /* properties */);
252 printOffscreenToFile(image, frame, caps, 2, "newio_150dpi_argbp");
253 }
254 // paint offscreen: NIO 150dpi RGB
255 {
256 final int scale = (int) ( 150.0 / 72.0 + 0.5 );
257 final BufferedImage image = DirectDataBufferInt.createBufferedImage(frame.getWidth()*scale, frame.getHeight()*scale, BufferedImage.TYPE_INT_RGB, null /* location */, null /* properties */);
258 printOffscreenToFile(image, frame, caps, 2, "newio_150dpi_rgb");
259 }
260 // paint offscreen: NIO 150dpi BGR
261 {
262 final int scale = (int) ( 150.0 / 72.0 + 0.5 );
263 final BufferedImage image = DirectDataBufferInt.createBufferedImage(frame.getWidth()*scale, frame.getHeight()*scale, BufferedImage.TYPE_INT_BGR, null /* location */, null /* properties */);
264 printOffscreenToFile(image, frame, caps, 2, "newio_150dpi_bgr");
265 }
266
267 Assert.assertNotNull(frame);
268 Assert.assertNotNull(glJPanel1);
269 Assert.assertNotNull(glJPanel2);
270
271 javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
272 public void run() {
273 frame.setVisible(false);
274 }});
275 Assert.assertEquals(false, frame.isVisible());
276 javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
277 public void run() {
278 final Frame _frame = frame;
279 _frame.remove(demoPanel);
280 _frame.dispose();
281 }});
282 }
283
284 @Test
285 public void test01_Offscreen_aa0() throws InterruptedException, InvocationTargetException {
286 final GLCapabilities caps = new GLCapabilities(glp);
287 runTestGL(caps, false);
288 }
289
290 @Test
291 public void test01_Offscreen_aa0_layered() throws InterruptedException, InvocationTargetException {
292 final GLCapabilities caps = new GLCapabilities(glp);
293 runTestGL(caps, true);
294 }
295
296 static long duration = 500; // ms
297
298 public static void main(final String args[]) {
299 for(int i=0; i<args.length; i++) {
300 if(args[i].equals("-time")) {
301 i++;
302 try {
303 duration = Integer.parseInt(args[i]);
304 } catch (final Exception ex) { ex.printStackTrace(); }
305 } else if(args[i].equals("-600dpi")) {
306 allow600dpi = true;
307 } else if(args[i].equals("-wait")) {
308 waitForKey = true;
309 }
310 }
311 if(waitForKey) {
312 final BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
313 System.err.println("Press enter to continue");
314 try {
315 System.err.println(stdin.readLine());
316 } catch (final IOException e) { }
317 }
318 org.junit.runner.JUnitCore.main(TestTiledPrintingNIOImageSwingAWT.class.getName());
319 }
320}
Convenient AWTPrintLifecycle context simplifying calling setupPrint(..) and AWTPrintLifecycle#release...
static Context setupPrint(final Container c, final double scaleMatX, final double scaleMatY, final int numSamples, final int tileWidth, final int tileHeight)
DataBuffer specialization using NIO direct buffer of type DataBuffer#TYPE_INT as storage.
static BufferedImageInt createBufferedImage(final int width, final int height, final int imageType, Point location, final Hashtable<?,?> properties)
Creates a BufferedImageInt using a direct color model in sRGB color space.
Specifies a set of OpenGL capabilities.
Specifies the the OpenGL profile.
Definition: GLProfile.java:77
static boolean isAvailable(final AbstractGraphicsDevice device, final String profile)
Returns the availability of a profile on a device.
Definition: GLProfile.java:305
static GLProfile get(final AbstractGraphicsDevice device, String profile)
Returns a GLProfile object.
static final String GL2
The desktop OpenGL profile 1.x up to 3.0.
Definition: GLProfile.java:579
A lightweight Swing component which provides OpenGL rendering support.
Definition: GLJPanel.java:189
void setOpaque(final boolean opaque)
Definition: GLJPanel.java:981
void addGLEventListener(final GLEventListener listener)
Adds the given listener to the end of this drawable queue.
Definition: GLJPanel.java:989
Gears.java author: Brian Paul (converted to Java by Ron Cemer and Sven Gothel)
Definition: Gears.java:34
void printOffscreenToFile(final BufferedImage image, final Frame frame, final GLCapabilities caps, final int num, final String detail)
static boolean waitForRealized(final java.awt.Component comp, final boolean realized, final Runnable waitAction)
static boolean waitForVisible(final java.awt.Component comp, final boolean visible, final Runnable waitAction)
static final String PNG
Constant which can be used as a file suffix to indicate a PNG file, value {@value}.
Definition: TextureIO.java:171
Interface describing print lifecycle to support AWT printing, e.g.