JOGL v2.6.0-rc-20250712
JOGL, High-Performance Graphics Binding for Java™ (public API).
OffscreenPrintable.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 */
28package com.jogamp.opengl.test.junit.jogl.tile;
29
30import java.awt.Container;
31import java.awt.Graphics;
32import java.awt.Graphics2D;
33import java.awt.Insets;
34import java.awt.RenderingHints;
35import java.awt.image.BufferedImage;
36import java.awt.print.PageFormat;
37import java.awt.print.Paper;
38import java.awt.print.Printable;
39import java.awt.print.PrinterException;
40import java.awt.print.PrinterJob;
41import java.io.File;
42import java.io.IOException;
43
44import javax.imageio.ImageIO;
45
46import com.jogamp.common.util.awt.AWTEDTExecutor;
47import com.jogamp.nativewindow.awt.DirectDataBufferInt;
48import com.jogamp.opengl.util.TileRenderer;
49
50/**
51 * {@link Printable} implementation using NIO {@link DirectDataBufferInt} {@link BufferedImage}
52 * for offscreen rendered printing.
53 *
54 * @see OnscreenPrintable
55 * @see PrintableBase
56 */
57public class OffscreenPrintable extends PrintableBase implements Printable {
58
59 public final int imageType;
60 public final String pngFilename;
61
62 /**
63 *
64 * @param job
65 * @param printContainer
66 * @param printDPI
67 * @param numSamples multisampling value: < 0 turns off, == 0 leaves as-is, > 0 enables using given num samples
68 * @param tileWidth custom tile width for {@link TileRenderer#setTileSize(int, int, int) tile renderer}, pass -1 for default.
69 * @param tileHeight custom tile height for {@link TileRenderer#setTileSize(int, int, int) tile renderer}, pass -1 for default.
70 * @param imageType AWT BufferedImage type (must be one of the integer types)
71 * @param pngFilename TODO
72 */
73 public OffscreenPrintable(final PrinterJob job, final Container printContainer, final int printDPI, final int numSamples, final int tileWidth, final int tileHeight, final int imageType, final String pngFilename) {
74 super(job, printContainer, printDPI, numSamples, tileWidth, tileHeight);
75 this.imageType = imageType;
76 this.pngFilename = pngFilename;
77 }
78
79 @Override
80 public int print(final Graphics g, final PageFormat pf, final int page) throws PrinterException {
81 if (page > 0) { // We have only one page, and 'page' is zero-based
82 return NO_SUCH_PAGE;
83 }
84
85 lockPrinting.lock();
86 try {
87 final Paper paper = pf.getPaper();
88 final double paperWWidthInch = paper.getWidth() / 72.0;
89 final double paperWHeightInch = paper.getHeight() / 72.0;
90 final double paperIWidthInch = paper.getImageableWidth() / 72.0;
91 final double paperIHeightInch = paper.getImageableHeight() / 72.0;
92 final double paperWWidthMM = paperWWidthInch * MM_PER_INCH;
93 final double paperWHeightMM = paperWHeightInch * MM_PER_INCH;
94 final double paperIWidthMM = paperIWidthInch * MM_PER_INCH;
95 final double paperIHeightMM = paperIHeightInch * MM_PER_INCH;
96
97 final double pfWWidthInch = pf.getWidth() / 72.0;
98 final double pfWHeightInch = pf.getHeight() / 72.0;
99 final double pfIWidthInch = pf.getImageableWidth() / 72.0;
100 final double pfIHeightInch = pf.getImageableHeight() / 72.0;
101 final double pfWWidthMM = pfWWidthInch * MM_PER_INCH;
102 final double pfWHeightMM = pfWHeightInch * MM_PER_INCH;
103 final double pfIWidthMM = pfIWidthInch * MM_PER_INCH;
104 final double pfIHeightMM = pfIHeightInch * MM_PER_INCH;
105
106 System.err.println("PF: Paper whole size "+
107 Math.round(paperWWidthMM)+" x "+Math.round(paperWHeightMM)+" mm, "+
108 Math.round(paperWWidthInch)+" x "+Math.round(paperWHeightInch)+" inch");
109
110 System.err.println("PF: Paper image size "+paper.getImageableX()+" / "+paper.getImageableY()+" "+
111 Math.round(paperIWidthMM)+" x "+Math.round(paperIHeightMM)+" mm, "+
112 Math.round(paperIWidthInch)+" x "+Math.round(paperIHeightInch)+" inch, "+
113 Math.round(paper.getImageableWidth())+"x"+Math.round(paper.getImageableHeight())+" 72dpi dots");
114
115 System.err.println("PF: Page whole size "+
116 Math.round(pfWWidthMM)+" x "+Math.round(pfWHeightMM)+" mm, "+
117 Math.round(pfWWidthInch)+" x "+Math.round(pfWHeightInch)+" inch");
118
119 System.err.println("PF: Page image size "+pf.getImageableX()+" / "+pf.getImageableY()+" "+
120 Math.round(pfIWidthMM)+" x "+Math.round(pfIHeightMM)+" mm, "+
121 Math.round(pfIWidthInch)+" x "+Math.round(pfIHeightInch)+" inch, "+
122 Math.round(pf.getImageableWidth())+"x"+Math.round(pf.getImageableHeight())+" 72dpi dots");
123
124 System.err.println("PF: Page orientation "+pf.getOrientation());
125
126 /**
127 * See: 'Scaling of Frame and GL content' in Class description!
128 * Note: Frame size contains the frame border (i.e. insets)!
129 */
130 final Insets frameInsets = cont.getInsets();
131 final int frameWidth = cont.getWidth();
132 final int frameHeight= cont.getHeight();
133 final double scaleGraphics = dpi / 72.0;
134 final int frameSWidth = (int) ( frameWidth * scaleGraphics );
135 final int frameSHeight = (int) ( frameHeight * scaleGraphics );
136 final double scaleComp72;
137 {
138 final double sx = pf.getImageableWidth() / frameSWidth;
139 final double sy = pf.getImageableHeight() / frameSHeight;
140 scaleComp72 = Math.min(sx, sy);
141 }
142
143 System.err.println("PRINT.offscrn thread "+Thread.currentThread().getName());
144 System.err.println("PRINT.offscrn DPI: scaleGraphics "+scaleGraphics+", scaleComp72 "+scaleComp72);
145 System.err.println("PRINT.offscrn DPI: frame: border "+frameInsets+", size "+frameWidth+"x"+frameHeight+
146 " -> scaled "+frameSWidth+ "x" + frameSHeight);
147
148 final BufferedImage image = DirectDataBufferInt.createBufferedImage(frameSWidth, frameSHeight, imageType, null /* location */, null /* properties */);
149 {
150 System.err.println("PRINT.offscrn image "+image);
151 final Graphics2D g2d = (Graphics2D) image.getGraphics();
152 g2d.setClip(0, 0, frameSWidth, frameSHeight);
153 g2d.scale(scaleGraphics, scaleGraphics);
154 // g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
155 g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
156 AWTEDTExecutor.singleton.invoke(true, new Runnable() {
157 public void run() {
158 cont.printAll(g2d);
159 }
160 });
161 }
162 if( null != pngFilename ) {
163 final File fout = new File(pngFilename);
164 try {
165 ImageIO.write(image, "png", fout);
166 } catch (final IOException e) {
167 e.printStackTrace();
168 }
169 }
170
171 final Graphics2D g2d = (Graphics2D)g;
172 g2d.translate(pf.getImageableX(), pf.getImageableY());
173 g2d.scale(scaleComp72, scaleComp72);
174 g2d.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null); // Null ImageObserver since image data is ready.
175
176 /* tell the caller that this page is part of the printed document */
177 return PAGE_EXISTS;
178 } finally {
179 lockPrinting.unlock();
180 }
181 }
182}
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.
Printable implementation using NIO DirectDataBufferInt BufferedImage for offscreen rendered printing.
OffscreenPrintable(final PrinterJob job, final Container printContainer, final int printDPI, final int numSamples, final int tileWidth, final int tileHeight, final int imageType, final String pngFilename)
int print(final Graphics g, final PageFormat pf, final int page)