From 9b5cee85c299e72735bebbfea5c23d3c71bc704e Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Sat, 7 Sep 2013 19:59:15 +0200 Subject: TiledPrintingAWTBase: Fix scaling - Fit frame to page, add MSAA RenderingHints test; setupPrint(Graphics2D): Query RenderingHints to use MSAA rendering - AWTPrintLifecycle.setupPrint(Graphics2D): Query RenderingHints to use MSAA rendering - Impl. in GLCanvas - TODO GLJPanel (would need a new offscreen buffer) - TiledPrintingAWTBase: - Fix scaling - Fit frame to page - add MSAA RenderingHints test - GLCanvas: Remove dumpStack() DEBUG output --- make/scripts/tests.sh | 6 +- .../javax/media/opengl/awt/AWTPrintLifecycle.java | 12 +- .../classes/javax/media/opengl/awt/GLCanvas.java | 62 +-- .../classes/javax/media/opengl/awt/GLJPanel.java | 6 +- .../classes/jogamp/opengl/GLFBODrawableImpl.java | 2 +- .../junit/jogl/demos/gl2/awt/TestGearsAWT.java | 12 +- .../junit/jogl/tile/TestTiledPrintingGearsAWT.java | 42 ++- .../jogl/tile/TestTiledPrintingGearsSwingAWT.java | 29 +- .../test/junit/jogl/tile/TiledPrintingAWTBase.java | 415 ++++++++++++--------- 9 files changed, 348 insertions(+), 238 deletions(-) diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh index 65ec1d992..fee4b3ec0 100644 --- a/make/scripts/tests.sh +++ b/make/scripts/tests.sh @@ -216,7 +216,7 @@ function jrun() { #D_ARGS="-Djogl.debug.GLContext -Dnewt.debug=all -Djogamp.debug.Lock -Djogamp.common.utils.locks.Lock.timeout=10000" #D_ARGS="-Djogl.debug.GLContext -Dnewt.debug=all" #D_ARGS="-Dnewt.debug=all" - #D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.GLJPanel" + D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.GLJPanel -Djogl.debug.TileRenderer" #D_ARGS="-Djogl.debug.PNGImage" #D_ARGS="-Djogl.debug.JPEGImage" #D_ARGS="-Djogl.debug.GLDrawable -Dnativewindow.debug.GraphicsConfiguration -Djogl.debug.CapabilitiesChooser" @@ -326,11 +326,11 @@ function testawtswt() { # tile rendring / printing w/ & w/o AWT # #testnoawt com.jogamp.opengl.test.junit.jogl.tile.TestTiledRendering1GL2NEWT $* -#testnoawt com.jogamp.opengl.test.junit.jogl.tile.TestTiledRendering2GL2NEWT $* +#testnoawt com.jogamp.opengl.test.junit.jogl.tile.TestTiledRendering2NEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.tile.TestRandomTiledRendering2GL2NEWT $* #testawt com.jogamp.opengl.test.junit.jogl.tile.TestRandomTiledRendering3GL2AWT $* testawt com.jogamp.opengl.test.junit.jogl.tile.TestTiledPrintingGearsAWT $* -testawt com.jogamp.opengl.test.junit.jogl.tile.TestTiledPrintingGearsSwingAWT $* +#testawt com.jogamp.opengl.test.junit.jogl.tile.TestTiledPrintingGearsSwingAWT $* # # core/newt (testnoawt and testawt) diff --git a/src/jogl/classes/javax/media/opengl/awt/AWTPrintLifecycle.java b/src/jogl/classes/javax/media/opengl/awt/AWTPrintLifecycle.java index afa27dbd8..077ee42a9 100644 --- a/src/jogl/classes/javax/media/opengl/awt/AWTPrintLifecycle.java +++ b/src/jogl/classes/javax/media/opengl/awt/AWTPrintLifecycle.java @@ -1,5 +1,3 @@ -package javax.media.opengl.awt; - /** * Copyright 2013 JogAmp Community. All rights reserved. * @@ -27,9 +25,12 @@ package javax.media.opengl.awt; * authors and should not be interpreted as representing official policies, either expressed * or implied, of JogAmp Community. */ +package javax.media.opengl.awt; import javax.media.opengl.GLAutoDrawable; import java.awt.Component; +import java.awt.Graphics; +import java.awt.Graphics2D; /** * Interface describing print lifecycle to support AWT printing @@ -38,12 +39,13 @@ import java.awt.Component; public interface AWTPrintLifecycle { /** - * Shall be called before {@link Component#print(java.awt.Graphics)}. + * Shall be called before {@link Component#print(Graphics)}. + * @param g2d the {@link Graphics2D} instance, which will be used for printing. */ - void setupPrint(); + void setupPrint(Graphics2D g2d); /** - * Shall be called after very last {@link Component#print(java.awt.Graphics)}. + * Shall be called after very last {@link Component#print(Graphics)}. */ void releasePrint(); } diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java index 5ada2d80f..8f9684db1 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java @@ -375,7 +375,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing System.err.println("Created Config (n): HAVE CF "+awtConfig); System.err.println("Created Config (n): Choosen CF "+config); System.err.println("Created Config (n): EQUALS CAPS "+equalCaps); - Thread.dumpStack(); + // Thread.dumpStack(); } if (compatible != null) { @@ -565,7 +565,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing if(DEBUG) { System.err.println(getThreadName()+": Info: addNotify - start, bounds: "+this.getBounds()+", isBeansDesignTime "+isBeansDesignTime); - Thread.dumpStack(); + // Thread.dumpStack(); } if( isBeansDesignTime ) { @@ -642,7 +642,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing final boolean res = _drawable.isRealized(); if(DEBUG) { System.err.println(getThreadName()+": Realized Drawable: isRealized "+res+", "+_drawable.toString()); - Thread.dumpStack(); + // Thread.dumpStack(); } return res; } @@ -662,7 +662,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing public void removeNotify() { if(DEBUG) { System.err.println(getThreadName()+": Info: removeNotify - start"); - Thread.dumpStack(); + // Thread.dumpStack(); } awtWindowClosingProtocol.removeClosingListener(); @@ -731,12 +731,13 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing private static final int PRINT_TILE_SIZE = 512; private volatile boolean printActive = false; + private boolean printUseAA = false; private GLAnimatorControl printAnimator = null; private GLOffscreenAutoDrawable printGLAD = null; private AWTTilePainter printAWTTiles = null; @Override - public void setupPrint() { + public void setupPrint(Graphics2D g2d) { if( !validateGLDrawable() ) { if(DEBUG) { System.err.println(getThreadName()+": Info: GLCanvas setupPrint - skipped GL render, drawable not valid yet"); @@ -751,6 +752,25 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing } printActive = true; sendReshape = false; // clear reshape flag + final RenderingHints rHints = g2d.getRenderingHints(); + { + final Object _useAA = rHints.get(RenderingHints.KEY_ANTIALIASING); + printUseAA = null != _useAA && ( _useAA == RenderingHints.VALUE_ANTIALIAS_DEFAULT || _useAA == RenderingHints.VALUE_ANTIALIAS_ON ); + } + if( DEBUG ) { + System.err.println("AWT print.setup: canvasSize "+getWidth()+"x"+getWidth()+", useAA "+printUseAA+", printAnimator "+printAnimator); + { + final Set> rEntries = rHints.entrySet(); + int count = 0; + for(Iterator> rEntryIter = rEntries.iterator(); rEntryIter.hasNext(); count++) { + final Entry rEntry = rEntryIter.next(); + System.err.println("Hint["+count+"]: "+rEntry.getKey()+" -> "+rEntry.getValue()); + } + } + final AffineTransform aTrans = g2d.getTransform(); + System.err.println(" scale "+aTrans.getScaleX()+" x "+aTrans.getScaleY()); + System.err.println(" move "+aTrans.getTranslateX()+" x "+aTrans.getTranslateY()); + } AWTEDTExecutor.singleton.invoke(getTreeLock(), true /* allowOnNonEDT */, true /* wait */, setupPrintOnEDT); } private final Runnable setupPrintOnEDT = new Runnable() { @@ -762,6 +782,19 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing printAnimator.remove(GLCanvas.this); } final GLCapabilities caps = (GLCapabilities)getChosenGLCapabilities().cloneMutable(); + caps.setDoubleBuffered(false); + final GLProfile glp = caps.getGLProfile(); + if( printUseAA && !caps.getSampleBuffers() ) { + if ( !glp.isGL2ES3() ) { + if( DEBUG ) { + System.err.println("Ignore MSAA due to gl-profile < GL2ES3"); + } + printUseAA = false; + } else { + caps.setSampleBuffers(true); + caps.setNumSamples(8); // FIXME + } + } caps.setOnscreen(false); final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); printGLAD = factory.createOffscreenAutoDrawable(null, caps, null, PRINT_TILE_SIZE, PRINT_TILE_SIZE, null); @@ -775,6 +808,8 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing printAWTTiles = new AWTTilePainter(printRenderer, componentCount, DEBUG); if( DEBUG ) { System.err.println("AWT print.setup "+printAWTTiles); + System.err.println("AWT print.setup AA "+printUseAA+", "+caps); + System.err.println("AWT print.setup "+printGLAD); } } }; @@ -820,21 +855,6 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing } sendReshape = false; // clear reshape flag final Graphics2D printGraphics = (Graphics2D)graphics; - if( DEBUG ) { - System.err.println("AWT print.0: canvasSize "+getWidth()+"x"+getWidth()+", printAnimator "+printAnimator); - { - final RenderingHints rHints = printGraphics.getRenderingHints(); - final Set> rEntries = rHints.entrySet(); - int count = 0; - for(Iterator> rEntryIter = rEntries.iterator(); rEntryIter.hasNext(); count++) { - final Entry rEntry = rEntryIter.next(); - System.err.println("Hint["+count+"]: "+rEntry.getKey()+" -> "+rEntry.getValue()); - } - } - final AffineTransform aTrans = printGraphics.getTransform(); - System.err.println(" scale "+aTrans.getScaleX()+" x "+aTrans.getScaleY()); - System.err.println(" move "+aTrans.getTranslateX()+" x "+aTrans.getTranslateY()); - } printAWTTiles.updateGraphics2DAndClipBounds(printGraphics); final TileRenderer tileRenderer = printAWTTiles.getTileRenderer(); if( DEBUG ) { @@ -1070,7 +1090,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing if(DEBUG) { System.err.println(getThreadName()+": Info: destroyOnEDTAction() - START, hasContext " + (null!=context) + ", hasDrawable " + (null!=drawable)+", "+animator); - Thread.dumpStack(); + // Thread.dumpStack(); } final boolean animatorPaused; diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java index 1f9e65a7d..2488bd443 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java @@ -505,7 +505,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing private AWTTilePainter printAWTTiles = null; @Override - public void setupPrint() { + public void setupPrint(Graphics2D g2d) { if (!isInitialized) { if(DEBUG) { System.err.println(getThreadName()+": Info: GLJPanel setupPrint - skipped GL render, drawable not valid yet"); @@ -1200,8 +1200,8 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing OffscreenBackend(GLProfile glp, AWTGLPixelBufferProvider custom) { if(null == custom) { - pixelBufferProvider = ( glp.isGL2GL3() || glp.isGL3ES3() ) ? getSingleAWTGLPixelBufferProvider() : - new AWTGLPixelBufferProvider( false /* allowRowStride */ ) ; + pixelBufferProvider = glp.isGL2ES3() ? getSingleAWTGLPixelBufferProvider() : + new AWTGLPixelBufferProvider( false /* allowRowStride */ ) ; } else { pixelBufferProvider = custom; } diff --git a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java index d7979efdb..f2248b388 100644 --- a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java @@ -43,7 +43,7 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable { static { Debug.initSingleton(); DEBUG = GLDrawableImpl.DEBUG || Debug.debug("FBObject"); - DEBUG_SWAP = Debug.isPropertyDefined("jogl.debug.FBObject.Swap", true); + DEBUG_SWAP = DEBUG || Debug.isPropertyDefined("jogl.debug.FBObject.Swap", true); } private final GLDrawableImpl parent; diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsAWT.java index d23130d36..24a6d578c 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsAWT.java @@ -60,6 +60,7 @@ public class TestGearsAWT extends UITestCase { static GLProfile glp; static int width, height; static boolean waitForKey = false; + static int msaaCount = 0; @BeforeClass public static void initClass() { @@ -132,6 +133,10 @@ public class TestGearsAWT extends UITestCase { @Test public void test01() throws InterruptedException, InvocationTargetException { GLCapabilities caps = new GLCapabilities(glp); + if( msaaCount > 0 ) { + caps.setSampleBuffers(true); + caps.setNumSamples(msaaCount); + } runTestGL(caps); } @@ -144,9 +149,14 @@ public class TestGearsAWT extends UITestCase { try { duration = Integer.parseInt(args[i]); } catch (Exception ex) { ex.printStackTrace(); } + } else if(args[i].equals("-msaa")) { + i++; + try { + msaaCount = Integer.parseInt(args[i]); + } catch (Exception ex) { ex.printStackTrace(); } } else if(args[i].equals("-wait")) { waitForKey = true; - } + } } if(waitForKey) { BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsAWT.java index 511880a0d..86c06247f 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsAWT.java @@ -103,20 +103,27 @@ public class TestTiledPrintingGearsAWT extends TiledPrintingAWTBase { final ActionListener print72DPIAction = new ActionListener() { public void actionPerformed(ActionEvent e) { - doPrintManual(frame, glCanvas, TestTiledPrintingGearsAWT.this, offscreenPrinting, 72); + doPrintManual(frame, glCanvas, TestTiledPrintingGearsAWT.this, offscreenPrinting, 72, false); + } }; + final ActionListener print150DPIAction = new ActionListener() { + public void actionPerformed(ActionEvent e) { + doPrintManual(frame, glCanvas, TestTiledPrintingGearsAWT.this, offscreenPrinting, 150, false); } }; final ActionListener print300DPIAction = new ActionListener() { public void actionPerformed(ActionEvent e) { - doPrintManual(frame, glCanvas, TestTiledPrintingGearsAWT.this, offscreenPrinting, 300); + doPrintManual(frame, glCanvas, TestTiledPrintingGearsAWT.this, offscreenPrinting, 300, false); } }; final Button print72DPIButton = new Button("72dpi"); print72DPIButton.addActionListener(print72DPIAction); + final Button print150DPIButton = new Button("150dpi"); + print150DPIButton.addActionListener(print150DPIAction); final Button print300DPIButton = new Button("300dpi"); print300DPIButton.addActionListener(print300DPIAction); frame.setLayout(new BorderLayout()); Panel printPanel = new Panel(); printPanel.add(print72DPIButton); + printPanel.add(print150DPIButton); printPanel.add(print300DPIButton); Panel southPanel = new Panel(); southPanel.add(new Label("South")); @@ -149,18 +156,24 @@ public class TestTiledPrintingGearsAWT extends TiledPrintingAWTBase { animator.start(); boolean dpi72Done = false; - boolean dpi300Done = false; + boolean dpi150Done = false; while(!quitAdapter.shouldQuit() && animator.isAnimating() && ( 0 == duration || animator.getTotalFPSDuration() 0) { // We have only one page, and 'page' is zero-based - return NO_SUCH_PAGE; - } - - final Paper paper = pf.getPaper(); - final double paperWWidthInch = paper.getWidth() / 72.0; - final double paperWHeightInch = paper.getHeight() / 72.0; - final double paperIWidthInch = paper.getImageableWidth() / 72.0; - final double paperIHeightInch = paper.getImageableHeight() / 72.0; - final double paperWWidthMM = paperWWidthInch * mmPerInch; - final double paperWHeightMM = paperWHeightInch * mmPerInch; - final double paperIWidthMM = paperIWidthInch * mmPerInch; - final double paperIHeightMM = paperIHeightInch * mmPerInch; - - final double pfWWidthInch = pf.getWidth() / 72.0; - final double pfWHeightInch = pf.getHeight() / 72.0; - final double pfIWidthInch = pf.getImageableWidth() / 72.0;; - final double pfIHeightInch = pf.getImageableHeight() / 72.0; - final double pfWWidthMM = pfWWidthInch * mmPerInch; - final double pfWHeightMM = pfWHeightInch * mmPerInch; - final double pfIWidthMM = pfIWidthInch * mmPerInch; - final double pfIHeightMM = pfIHeightInch * mmPerInch; - - System.err.println("PF: Paper whole size "+Math.round(paperWWidthMM)+" x "+Math.round(paperWHeightMM)+" mm, "+Math.round(paperWWidthInch)+" x "+Math.round(paperWHeightInch)+" inch"); - System.err.println("PF: Paper image size "+paper.getImageableX()+" / "+paper.getImageableY()+" "+Math.round(paperIWidthMM)+" x "+Math.round(paperIHeightMM)+" mm, "+Math.round(paperIWidthInch)+" x "+Math.round(paperIHeightInch)+" inch"); - System.err.println("PF: Page whole size "+Math.round(pfWWidthMM)+" x "+Math.round(pfWHeightMM)+" mm, "+Math.round(pfWWidthInch)+" x "+Math.round(pfWHeightInch)+" inch"); - System.err.println("PF: Page image size "+pf.getImageableX()+" / "+pf.getImageableY()+" "+Math.round(pfIWidthMM)+" x "+Math.round(pfIHeightMM)+" mm, "+Math.round(pfIWidthInch)+" x "+Math.round(pfIHeightInch)+" inch"); - System.err.println("PF: Page orientation "+pf.getOrientation()); - - /** - * User (0,0) is typically outside the imageable area, so we must - * translate by the X and Y values in the PageFormat to avoid clipping - */ - - final int scaleComp; - { - final int xScaleComp = (int) Math.round(printDPI/72.0); - final int yScaleComp = (int) Math.round(printDPI/72.0); - scaleComp = Math.min(xScaleComp, yScaleComp); - } - final double scale; - { - final double xScale = 72.0/printDPI; - final double yScale = 72.0/printDPI; - scale = Math.min(xScale, yScale); - } + public int print(Graphics g, PageFormat pf, int page) throws PrinterException { + if (page > 0) { // We have only one page, and 'page' is zero-based + return NO_SUCH_PAGE; + } + + lockPrinting.lock(); + try { + final Paper paper = pf.getPaper(); + final double paperWWidthInch = paper.getWidth() / 72.0; + final double paperWHeightInch = paper.getHeight() / 72.0; + final double paperIWidthInch = paper.getImageableWidth() / 72.0; + final double paperIHeightInch = paper.getImageableHeight() / 72.0; + final double paperWWidthMM = paperWWidthInch * MM_PER_INCH; + final double paperWHeightMM = paperWHeightInch * MM_PER_INCH; + final double paperIWidthMM = paperIWidthInch * MM_PER_INCH; + final double paperIHeightMM = paperIHeightInch * MM_PER_INCH; - System.err.println("PRINT offscreen: "+printOffscreen+", thread "+Thread.currentThread().getName()); - System.err.println("PRINT DPI: "+printDPI+", scaleComp "+scaleComp); - awtPrintObject.setupPrint(); - - final int frameWidth = frame.getWidth(); - final int frameHeight= frame.getHeight(); - - final double moveX, moveY; - - if( scaleComp != 1 ) { - final int frameWidthS = frameWidth*(scaleComp-1); - final int frameHeightS = frameHeight*(scaleComp-1); - - double xMargin = (pf.getImageableWidth() - frameWidthS*scale)/2; - double yMargin = (pf.getImageableHeight() - frameHeightS*scale)/2; - moveX = pf.getImageableX() + xMargin; - moveY = pf.getImageableY() + yMargin; - System.err.println("PRINT DPI: "+printDPI+", scale "+scale+", margin "+xMargin+"/"+yMargin+", move "+moveX+"/"+moveY+ - ", frame: "+frameWidth+"x"+frameHeight+" -> "+frameWidthS+"x"+frameHeightS); - - AWTEDTExecutor.singleton.invoke(true, new Runnable() { - public void run() { - frame.setSize(frameWidthS, frameHeightS); - frame.invalidate(); - frame.validate(); - } - }); - } else { - moveX = pf.getImageableX(); - moveY = pf.getImageableY(); - System.err.println("PRINT DPI: "+printDPI+", scale "+scale+", move "+moveX+"/"+moveY+ - ", frame: "+frameWidth+"x"+frameHeight); - } - - final Graphics2D printG2D = (Graphics2D)g; - - final Graphics2D offscreenG2D; - final BufferedImage offscreenImage; - if( printOffscreen ) { - final int w = frame.getWidth(); - final int h = frame.getHeight(); - offscreenImage = new BufferedImage(w, h, BufferedImage.TYPE_4BYTE_ABGR); - offscreenG2D = (Graphics2D) offscreenImage.getGraphics(); - offscreenG2D.setClip(0, 0, w, h); + final double pfWWidthInch = pf.getWidth() / 72.0; + final double pfWHeightInch = pf.getHeight() / 72.0; + final double pfIWidthInch = pf.getImageableWidth() / 72.0; + final double pfIHeightInch = pf.getImageableHeight() / 72.0; + final double pfWWidthMM = pfWWidthInch * MM_PER_INCH; + final double pfWHeightMM = pfWHeightInch * MM_PER_INCH; + final double pfIWidthMM = pfIWidthInch * MM_PER_INCH; + final double pfIHeightMM = pfIHeightInch * MM_PER_INCH; + + System.err.println("PF: Paper whole size "+ + Math.round(paperWWidthMM)+" x "+Math.round(paperWHeightMM)+" mm, "+ + Math.round(paperWWidthInch)+" x "+Math.round(paperWHeightInch)+" inch"); + + System.err.println("PF: Paper image size "+paper.getImageableX()+" / "+paper.getImageableY()+" "+ + Math.round(paperIWidthMM)+" x "+Math.round(paperIHeightMM)+" mm, "+ + Math.round(paperIWidthInch)+" x "+Math.round(paperIHeightInch)+" inch, "+ + Math.round(paper.getImageableWidth())+"x"+Math.round(paper.getImageableHeight())+" 72dpi dots"); + + System.err.println("PF: Page whole size "+ + Math.round(pfWWidthMM)+" x "+Math.round(pfWHeightMM)+" mm, "+ + Math.round(pfWWidthInch)+" x "+Math.round(pfWHeightInch)+" inch"); + + System.err.println("PF: Page image size "+pf.getImageableX()+" / "+pf.getImageableY()+" "+ + Math.round(pfIWidthMM)+" x "+Math.round(pfIHeightMM)+" mm, "+ + Math.round(pfIWidthInch)+" x "+Math.round(pfIHeightInch)+" inch, "+ + Math.round(pf.getImageableWidth())+"x"+Math.round(pf.getImageableHeight())+" 72dpi dots"); + + System.err.println("PF: Page orientation "+pf.getOrientation()); + + /** + * We fit the frame into the imageable area with the desired DPI. + *

+ * We assume AWT painting happens w/ 72 dpi! + *

+ *

+ * The frame borders are considered. + *

+ */ + final Insets frameInsets = frame.getInsets(); + final int frameWidth = frame.getWidth(); + final int frameHeight= frame.getHeight(); + final int frameWidthS; + final int frameHeightS; + final double scaleComp; + { + final int frameBorderW = frameInsets.left + frameInsets.right; + final int frameBorderH = frameInsets.top + frameInsets.bottom; + final double sx = pf.getImageableWidth() / ( frameWidth + frameBorderW ); + final double sy = pf.getImageableHeight() / ( frameHeight + frameBorderH ); + scaleComp = Math.min(sx, sy) * ( printDPI/72.0 ); + if( 0f < scaleComp ) { + frameWidthS = (int) ( frameWidth*scaleComp ); // cut off FIXME + frameHeightS = (int) ( frameHeight*scaleComp ); // cut off FIXME } else { - offscreenG2D = null; - offscreenImage = null; - } - - final Graphics2D g2d = null != offscreenG2D ? offscreenG2D : printG2D; - - if( g2d != offscreenG2D ) { - g2d.translate(moveX, moveY); - g2d.scale(scale , scale ); + frameWidthS = frameWidth; + frameHeightS = frameHeight; } + } + // Since we fit the frame size into the imageable size respecting the DPI, + // we simply can scale the print graphics matrix to the DPI + // w/o the need to fiddle w/ the margins (matrix translation). + final double scaleGraphics = 72.0 / printDPI; + + System.err.println("PRINT offscreen: "+printOffscreen+", thread "+Thread.currentThread().getName()); + System.err.println("PRINT DPI: "+printDPI+", AA "+printAA+", scaleGraphics "+scaleGraphics+", scaleComp "+scaleComp+ + ", frame: border "+frameInsets+", size "+frameWidth+"x"+frameHeight+" -> "+frameWidthS+"x"+frameHeightS); + + final Graphics2D printG2D = (Graphics2D)g; + final Graphics2D offscreenG2D; + final BufferedImage offscreenImage; + final Graphics2D g2d; + if( printOffscreen ) { + offscreenImage = new BufferedImage(frameWidthS, frameHeightS, BufferedImage.TYPE_4BYTE_ABGR); + offscreenG2D = (Graphics2D) offscreenImage.getGraphics(); + offscreenG2D.setClip(0, 0, frameWidthS, frameHeightS); + g2d = offscreenG2D; + } else { + offscreenG2D = null; + offscreenImage = null; + g2d = printG2D; + g2d.translate(pf.getImageableX(), pf.getImageableY()); + g2d.scale(scaleGraphics, scaleGraphics); + } + if( printAA ) { + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + } + awtPrintObject.setupPrint(g2d); + try { + AWTEDTExecutor.singleton.invoke(true, new Runnable() { + public void run() { + frame.setSize(frameWidthS, frameHeightS); + frame.invalidate(); + frame.validate(); + } + }); + AWTEDTExecutor.singleton.invoke(true, new Runnable() { public void run() { frame.printAll(g2d); } } ); - if( scaleComp != 1 ) { - System.err.println("PRINT DPI: reset frame size "+frameWidth+"x"+frameHeight); - AWTEDTExecutor.singleton.invoke(true, new Runnable() { - public void run() { - frame.setSize(frameWidth, frameHeight); - frame.invalidate(); - frame.validate(); - } - }); - } + System.err.println("PRINT DPI: reset frame size "+frameWidth+"x"+frameHeight); + AWTEDTExecutor.singleton.invoke(true, new Runnable() { + public void run() { + frame.setSize(frameWidth, frameHeight); + frame.invalidate(); + frame.validate(); + } + }); + } finally { awtPrintObject.releasePrint(); - - if( g2d == offscreenG2D ) { - printG2D.translate(moveX, moveY); - printG2D.scale(scale , scale ); - printG2D.drawImage(offscreenImage, 0, 0, offscreenImage.getWidth(), offscreenImage.getHeight(), null); // Null ImageObserver since image data is ready. - } - - /* tell the caller that this page is part of the printed document */ - return PAGE_EXISTS; } + + if( printOffscreen ) { + printG2D.translate(pf.getImageableX(), pf.getImageableY()); + printG2D.scale(scaleGraphics, scaleGraphics); + printG2D.drawImage(offscreenImage, 0, 0, offscreenImage.getWidth(), offscreenImage.getHeight(), null); // Null ImageObserver since image data is ready. + } + + /* tell the caller that this page is part of the printed document */ + return PAGE_EXISTS; + } finally { + lockPrinting.unlock(); + } + } + private RecursiveLock lock = LockFactory.createRecursiveLock(); private int printCount = 0; public TiledPrintingAWTBase() { super(); } - protected void doPrintAuto(Frame frame, AWTPrintLifecycle awtPrintObject, - Printable printable, int pOrientation, Paper paper, boolean offscreen, int dpi) { - final PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet(); - aset.add(MediaSizeName.ISO_A1); // 594 × 841 mm - aset.add(MediaSizeName.ISO_A2); // 420 × 594 mm - aset.add(MediaSizeName.ISO_A3); // 297 × 420 mm - aset.add(MediaSizeName.ISO_A4); // 210 × 297 mm - - printCount++; - - final String psMimeType = "application/postscript"; - final String pdfMimeType = "application/pdf"; - final PrinterJob pj = PrinterJob.getPrinterJob(); - - StreamPrintServiceFactory[] factories = PrinterJob.lookupStreamPrintServices(pdfMimeType); - if (factories.length > 0) { - final String fname = getPrintFilename(dpi, "pdf"); - System.err.println("doPrint: dpi "+dpi+", "+fname); - FileOutputStream outstream; - try { - outstream = new FileOutputStream(fname); - Assert.assertTrue(doPrintAutoImpl(frame, awtPrintObject, printable, pj, factories[0].getPrintService(outstream), pOrientation, paper, offscreen, dpi)); - } catch (FileNotFoundException e) { - Assert.assertNull("Unexpected exception", e); - } - return; - } - System.err.println("No PDF"); + public void doPrintAuto(Frame frame, AWTPrintLifecycle awtPrintObject, + Printable printable, int pOrientation, Paper paper, boolean offscreen, int dpi, boolean antialiasing) { + lock.lock(); + try { + final PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet(); + aset.add(MediaSizeName.ISO_A1); // 594 × 841 mm + aset.add(MediaSizeName.ISO_A2); // 420 × 594 mm + aset.add(MediaSizeName.ISO_A3); // 297 × 420 mm + aset.add(MediaSizeName.ISO_A4); // 210 × 297 mm + + printCount++; + + final String psMimeType = "application/postscript"; + final String pdfMimeType = "application/pdf"; + final PrinterJob pj = PrinterJob.getPrinterJob(); - factories = PrinterJob.lookupStreamPrintServices(psMimeType); - if (factories.length > 0) { - final String fname = getPrintFilename(dpi, "ps"); - System.err.println("doPrint: dpi "+dpi+", "+fname); - FileOutputStream outstream; - try { - outstream = new FileOutputStream(fname); - Assert.assertTrue(doPrintAutoImpl(frame, awtPrintObject, printable, pj, factories[0].getPrintService(outstream), pOrientation, paper, offscreen, dpi)); - } catch (FileNotFoundException e) { - Assert.assertNull("Unexpected exception", e); - } - return; - } - System.err.println("No PS"); + StreamPrintServiceFactory[] factories = PrinterJob.lookupStreamPrintServices(pdfMimeType); + if (factories.length > 0) { + final String fname = getPrintFilename(dpi, antialiasing, "pdf"); + System.err.println("doPrint: dpi "+dpi+", "+fname); + FileOutputStream outstream; + try { + outstream = new FileOutputStream(fname); + Assert.assertTrue(doPrintAutoImpl(frame, awtPrintObject, printable, pj, factories[0].getPrintService(outstream), pOrientation, paper, offscreen, dpi, antialiasing)); + } catch (FileNotFoundException e) { + Assert.assertNull("Unexpected exception", e); + } + return; + } + System.err.println("No PDF"); + + factories = PrinterJob.lookupStreamPrintServices(psMimeType); + if (factories.length > 0) { + final String fname = getPrintFilename(dpi, antialiasing, "ps"); + System.err.println("doPrint: dpi "+dpi+", "+fname); + FileOutputStream outstream; + try { + outstream = new FileOutputStream(fname); + Assert.assertTrue(doPrintAutoImpl(frame, awtPrintObject, printable, pj, factories[0].getPrintService(outstream), pOrientation, paper, offscreen, dpi, antialiasing)); + } catch (FileNotFoundException e) { + Assert.assertNull("Unexpected exception", e); + } + return; + } + System.err.println("No PS"); + } finally { + lock.unlock(); + } } - - private String getPrintFilename(int dpi, String suffix) { + private String getPrintFilename(int dpi, boolean antialiasing, String suffix) { final int maxSimpleTestNameLen = getMaxTestNameLen()+getClass().getSimpleName().length()+1; final String simpleTestName = getSimpleTestName("."); - return String.format("%-"+maxSimpleTestNameLen+"s-n%04d-dpi%03d.%s", simpleTestName, printCount, dpi, suffix).replace(' ', '_'); + final String sAA = antialiasing ? "aa_" : "raw"; + return String.format("%-"+maxSimpleTestNameLen+"s-n%04d-dpi%03d-%s.%s", simpleTestName, printCount, dpi, sAA, suffix).replace(' ', '_'); } - private boolean doPrintAutoImpl(Frame frame, AWTPrintLifecycle awtPrintObject, Printable printable, PrinterJob job, StreamPrintService ps, int pOrientation, - Paper paper, boolean offscreen, int dpi) { + Paper paper, boolean offscreen, int dpi, boolean antialiasing) { this.awtPrintObject = awtPrintObject; this.frame = frame; printOffscreen = offscreen; printDPI = dpi; + printAA = antialiasing; boolean ok = true; try { PageFormat pageFormat = job.defaultPage(); @@ -287,21 +314,37 @@ public abstract class TiledPrintingAWTBase extends UITestCase implements Printab return ok; } - protected void doPrintManual(Frame frame, AWTPrintLifecycle awtPrintObject, Printable printable, boolean offscreen, int dpi) { - this.awtPrintObject = awtPrintObject; - this.frame = frame; - printOffscreen = offscreen; - printDPI = dpi; - PrinterJob job = PrinterJob.getPrinterJob(); - job.setPrintable(printable); - boolean ok = job.printDialog(); - if (ok) { - try { - job.print(); - } catch (PrinterException ex) { - ex.printStackTrace(); + public void doPrintManual(Frame frame, AWTPrintLifecycle awtPrintObject, Printable printable, boolean offscreen, int dpi, boolean antialiasing) { + lock.lock(); + try { + this.awtPrintObject = awtPrintObject; + this.frame = frame; + printOffscreen = offscreen; + printDPI = dpi; + printAA = antialiasing; + PrinterJob job = PrinterJob.getPrinterJob(); + job.setPrintable(printable); + boolean ok = job.printDialog(); + if (ok) { + try { + job.print(); + } catch (PrinterException ex) { + ex.printStackTrace(); + } } - } + } finally { + lock.unlock(); + } } + /** Wait for idle .. simply acquiring all locks and releasing them. */ + public void waitUntilPrintJobsIdle() { + lock.lock(); + try { + lockPrinting.lock(); + lockPrinting.unlock(); + } finally { + lock.unlock(); + } + } } \ No newline at end of file -- cgit v1.2.3