From 4e1d3170667d6692c484b8366d578ab830408175 Mon Sep 17 00:00:00 2001
From: Sven Gothel
+ * We fit the frame into the imageable area with for 72 dpi, + * assuming that is the default AWT painting density. + *
+ *+ * The frame borders are considered. + *
+ *+ * The frame's scale factor is used for the graphics print matrix + * of the overall print-job, hence no frame resize is required. + *
+ *+ * The GL scale factor 'scaleGLMatXY', 72dpi/glDPI, is passed to the GL object + * which locally scales the print matrix and renders the scene with 1/scaleGLMatXY pixels. + *
+ */ +public class OnscreenPrintable extends PrintableBase implements Printable { + + /** + * + * @param job + * @param printContainer + * @param printDPI + * @param numSamples multisampling value: < 0 turns off, == 0 leaves as-is, > 0 enables using given num samples + */ + public OnscreenPrintable(PrinterJob job, Container printContainer, int printDPI, int numSamples) { + super(job, printContainer, printDPI, numSamples); + } + + @Override + 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; + + 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()); + + /** + * See: 'Scaling of Frame and GL content' in Class description! + */ + final Insets frameInsets = cont.getInsets(); + final int frameWidth = cont.getWidth(); + final int frameHeight= cont.getHeight(); + final int frameWidthT = frameWidth + frameInsets.left + frameInsets.right; + final int frameHeightT = frameHeight + frameInsets.top + frameInsets.bottom; + final double scaleGraphics = dpi / 72.0; + final int frameSWidthT = (int) ( frameWidthT * scaleGraphics ); + final int frameSHeightT = (int) ( frameHeightT * scaleGraphics ); + final double scaleComp72; + { + final double sx = pf.getImageableWidth() / (double)frameWidthT; + final double sy = pf.getImageableHeight() / (double)frameHeightT; + scaleComp72 = Math.min(sx, sy); + } + System.err.println("PRINT.onscrn thread "+Thread.currentThread().getName()); + System.err.println("PRINT.onscrn DPI: scaleGraphics "+scaleGraphics+", scaleComp72 "+scaleComp72); + System.err.println("PRINT.onscrn DPI: frame: border "+frameInsets+", size "+frameWidth+"x"+frameHeight+ + " -> total "+frameWidthT+ "x" + frameHeightT+ + " -> scaled "+frameSWidthT+ "x" + frameSHeightT); + + final Graphics2D g2d = (Graphics2D)g; + System.err.println("PRINT at.pre: "+g2d.getTransform()); + g2d.translate(pf.getImageableX(), pf.getImageableY()); + g2d.scale(scaleComp72, scaleComp72); // WARNING: Produces rounding artifacts due to diff scale-factor of AWT/GL comps !!! + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + + AWTEDTExecutor.singleton.invoke(true, new Runnable() { + public void run() { + cont.printAll(g2d); + } + }); + + /* tell the caller that this page is part of the printed document */ + return PAGE_EXISTS; + } finally { + lockPrinting.unlock(); + } + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/PrintableBase.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/PrintableBase.java new file mode 100644 index 000000000..830ded960 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/PrintableBase.java @@ -0,0 +1,82 @@ +/** + * Copyright 2013 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.opengl.test.junit.jogl.tile; + +import java.awt.Container; +import java.awt.print.Printable; +import java.awt.print.PrinterJob; + +import com.jogamp.common.util.locks.LockFactory; +import com.jogamp.common.util.locks.RecursiveLock; + +/** + * Base {@link Printable} implementation class. + * + *
+ * Note, on OSX you might need to setup a dummy printer, i.e. print to file.
+ * As root:
+ *
+ cupsctl FileDevice=Yes + killall -HUP cupsd + mkdir /data/lp + chown USER /data/lp + chmod ugo+rwx /data/lp + lpadmin -p lprint -E -v file:/data/lp/out.ps -P /Library/Printers/PPDs/Contents/Resources/HP\ LaserJet\ 4\ Plus.gz + *+ */ +public abstract class PrintableBase implements Printable { + + public static final double MM_PER_INCH = 25.4; + + public final PrinterJob job; + public final Container cont; + public final int dpi; + public final int numSamples; + protected final RecursiveLock lockPrinting = LockFactory.createRecursiveLock(); + + /** + * + * @param job + * @param printContainer + * @param printDPI + * @param numSamples multisampling value: < 0 turns off, == 0 leaves as-is, > 0 enables using given num samples + */ + public PrintableBase(PrinterJob job, Container printContainer, int printDPI, int numSamples) { + this.job = job; + this.cont = printContainer; + this.dpi = printDPI; + this.numSamples = numSamples; + } + + /** Wait for idle .. simply acquiring all locks and releasing them. */ + public void waitUntilIdle() { + lockPrinting.lock(); + lockPrinting.unlock(); + } +} \ No newline at end of file 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 908a89a32..c7c04950a 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 @@ -175,21 +175,32 @@ public class TestTiledPrintingGearsAWT extends TiledPrintingAWTBase { while(!quitAdapter.shouldQuit() && animator.isAnimating() && ( 0 == duration || animator.getTotalFPSDuration()
- * We fit the frame into the imageable area with for 72 dpi, - * assuming that is the default AWT painting density. - *
- *- * The frame borders are considered. - *
- *- * The frame's scale factor is used for the graphics print matrix - * of the overall print-job, hence no frame resize is required. - *
- *- * The GL scale factor 'scaleGLMatXY', 72dpi/glDPI, is passed to the GL object - * which locally scales the print matrix and renders the scene with 1/scaleGLMatXY pixels. - *
- *
- * Note, on OSX you might need to setup a dummy printer, i.e. print to file.
- * As root:
- *
- cupsctl FileDevice=Yes - killall -HUP cupsd - mkdir /data/lp - chown USER /data/lp - chmod ugo+rwx /data/lp - lpadmin -p lprint -E -v file:/data/lp/out.ps -P /Library/Printers/PPDs/Contents/Resources/HP\ LaserJet\ 4\ Plus.gz - *+ * Base unit test class implementing + * issuing {@link PrinterJob#print()} on a {@link Printable} implementation, + * i.e. {@link OnscreenPrintable} or {@link OffscreenPrintable}. */ -public abstract class TiledPrintingAWTBase extends UITestCase implements Printable { - - public static final double MM_PER_INCH = 25.4; - /** - public static final double A0_WIDTH_MM = 841.0; - public static final double A0_HEIGHT_MM = 1189.0; - public static final double A0_WIDTH_INCH = A0_WIDTH_MM / MM_PER_INCH; - public static final double A0_HEIGHT_INCH = A0_WIDTH_MM / MM_PER_INCH; */ - - /** Helper to pass desired Frame to print! **/ - private Container printContainer; +public abstract class TiledPrintingAWTBase extends UITestCase { - private RecursiveLock lockPrinting = LockFactory.createRecursiveLock(); - - @Override - 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; - - 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()); - - /** - * See: 'Scaling of Frame and GL content' in Class description! - */ - final Insets frameInsets = printContainer.getInsets(); - final int frameWidth = printContainer.getWidth(); - final int frameHeight= printContainer.getHeight(); - final double scaleComp72; - { - final double frameBorderW = frameInsets.left + frameInsets.right; - final double frameBorderH = frameInsets.top + frameInsets.bottom; - final double sx = pf.getImageableWidth() / ( frameWidth + frameBorderW ); - final double sy = pf.getImageableHeight() / ( frameHeight + frameBorderH ); - scaleComp72 = Math.min(sx, sy); - } - - System.err.println("PRINT thread "+Thread.currentThread().getName()); - System.err.println("PRINT DPI: scaleComp72 "+scaleComp72+ - ", frame: border "+frameInsets+", size "+frameWidth+"x"+frameHeight); - final Graphics2D g2d = (Graphics2D)g; - System.err.println("PRINT at.pre: "+g2d.getTransform()); - g2d.translate(pf.getImageableX(), pf.getImageableY()); - g2d.scale(scaleComp72, scaleComp72); - System.err.println("PRINT at.post: "+g2d.getTransform()); - - AWTEDTExecutor.singleton.invoke(true, new Runnable() { - public void run() { - printContainer.printAll(g2d); - } - }); - - /* 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; @@ -196,10 +70,11 @@ public abstract class TiledPrintingAWTBase extends UITestCase implements Printab * @param cont * @param pOrientation * @param paper + * @param offscrn TODO * @param dpi * @param numSamples multisampling value: < 0 turns off, == 0 leaves as-is, > 0 enables using given num samples */ - public void doPrintAuto(Container cont, int pOrientation, Paper paper, int dpi, int numSamples) { + public PrintableBase doPrintAuto(Container cont, int pOrientation, Paper paper, boolean offscrn, int dpi, int numSamples) { lock.lock(); try { final PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet(); @@ -216,46 +91,47 @@ public abstract class TiledPrintingAWTBase extends UITestCase implements Printab StreamPrintServiceFactory[] factories = PrinterJob.lookupStreamPrintServices(pdfMimeType); if (factories.length > 0) { - final String fname = getPrintFilename(dpi, numSamples, "pdf"); + final String fname = getPrintFilename(offscrn, dpi, numSamples, "pdf"); System.err.println("doPrint: dpi "+dpi+", "+fname); FileOutputStream outstream; try { outstream = new FileOutputStream(fname); - Assert.assertTrue(doPrintAutoImpl(cont, pj, factories[0].getPrintService(outstream), pOrientation, paper, dpi, numSamples)); + return doPrintAutoImpl(cont, pj, factories[0].getPrintService(outstream), pOrientation, paper, offscrn, dpi, numSamples); } catch (FileNotFoundException e) { Assert.assertNull("Unexpected exception", e); } - return; + return null; } System.err.println("No PDF"); factories = PrinterJob.lookupStreamPrintServices(psMimeType); if (factories.length > 0) { - final String fname = getPrintFilename(dpi, numSamples, "ps"); + final String fname = getPrintFilename(offscrn, dpi, numSamples, "ps"); System.err.println("doPrint: dpi "+dpi+", "+fname); FileOutputStream outstream; try { outstream = new FileOutputStream(fname); - Assert.assertTrue(doPrintAutoImpl(cont, pj, factories[0].getPrintService(outstream), pOrientation, paper, dpi, numSamples)); + return doPrintAutoImpl(cont, pj, factories[0].getPrintService(outstream), pOrientation, paper, offscrn, dpi, numSamples); } catch (FileNotFoundException e) { Assert.assertNull("Unexpected exception", e); } - return; + return null; } System.err.println("No PS"); + return null; } finally { lock.unlock(); } } - private String getPrintFilename(int dpi, int numSamples, String suffix) { + private String getPrintFilename(boolean offscrn, int dpi, int numSamples, String suffix) { final int maxSimpleTestNameLen = getMaxTestNameLen()+getClass().getSimpleName().length()+1; final String simpleTestName = getSimpleTestName("."); - return String.format("%-"+maxSimpleTestNameLen+"s-n%04d-dpi%03d-aa%d.%s", simpleTestName, printCount, dpi, numSamples, suffix).replace(' ', '_'); + final String onoffscrn = offscrn ? "offscrn" : "on_scrn"; + return String.format("%-"+maxSimpleTestNameLen+"s-n%04d-%s-dpi%03d-aa%d.%s", simpleTestName, printCount, onoffscrn, dpi, numSamples, suffix).replace(' ', '_'); } - private boolean doPrintAutoImpl(Container cont, PrinterJob job, - StreamPrintService ps, int pOrientation, Paper paper, int dpi, - int numSamples) { - boolean ok = true; + private PrintableBase doPrintAutoImpl(Container cont, PrinterJob job, + StreamPrintService ps, int pOrientation, Paper paper, + boolean offscrn, int dpi, int numSamples) { try { PageFormat pageFormat = job.defaultPage(); if( null != paper ) { @@ -267,13 +143,15 @@ public abstract class TiledPrintingAWTBase extends UITestCase implements Printab } pageFormat.setOrientation(pOrientation); // PageFormat.LANDSCAPE or PageFormat.PORTRAIT job.setPrintService(ps); - job.setPrintable(this, pageFormat); - doPrintImpl(cont, job, dpi, numSamples); + final PrintableBase printable = offscrn ? new OffscreenPrintable(job, cont, dpi, numSamples, getPrintFilename(offscrn, dpi, numSamples, "png")) : + new OnscreenPrintable(job, cont, dpi, numSamples); + printable.job.setPrintable(printable, pageFormat); + doPrintImpl(printable); + return printable; } catch (PrinterException pe) { pe.printStackTrace(); - ok = false; + return null; } - return ok; } /** @@ -282,38 +160,32 @@ public abstract class TiledPrintingAWTBase extends UITestCase implements Printab * @param dpi * @param numSamples multisampling value: < 0 turns off, == 0 leaves as-is, > 0 enables using given num samples */ - public void doPrintManual(Container cont, int dpi, int numSamples) { + public PrintableBase doPrintManual(Container cont, int dpi, int numSamples) { lock.lock(); try { - PrinterJob job = PrinterJob.getPrinterJob(); - job.setPrintable(this); - boolean ok = job.printDialog(); + final OnscreenPrintable printable = new OnscreenPrintable(PrinterJob.getPrinterJob(), cont, dpi, numSamples); + printable.job.setPrintable(printable); + boolean ok = printable.job.printDialog(); if (ok) { - doPrintImpl(cont, job, dpi, numSamples); + doPrintImpl(printable); } + return printable; } finally { lock.unlock(); } } - /** - * - * @param cont - * @param job - * @param dpi - * @param numSamples multisampling value: < 0 turns off, == 0 leaves as-is, > 0 enables using given num samples - */ - private void doPrintImpl(final Container cont, final PrinterJob job, final int dpi, final int numSamples) { - printContainer = cont; - final double scaleGLMatXY = 72.0 / dpi; - System.err.println("PRINT DPI: "+dpi+", AA "+numSamples+", scaleGL "+scaleGLMatXY); - final AWTPrintLifecycle.Context ctx = AWTPrintLifecycle.Context.setupPrint(printContainer, scaleGLMatXY, scaleGLMatXY, numSamples); + private void doPrintImpl(final PrintableBase printable) { + final double scaleGLMatXY = 72.0 / printable.dpi; + System.err.println("PRINTable: "+printable.getClass().getSimpleName()); + System.err.println("PRINT DPI: "+printable.dpi+", AA "+printable.numSamples+", scaleGL "+scaleGLMatXY); + final AWTPrintLifecycle.Context ctx = AWTPrintLifecycle.Context.setupPrint(printable.cont, scaleGLMatXY, scaleGLMatXY, printable.numSamples); System.err.println("PRINT AWTPrintLifecycle.setup.count "+ctx.getCount()); try { AWTEDTExecutor.singleton.invoke(true, new Runnable() { public void run() { try { - job.print(); + printable.job.print(); } catch (PrinterException ex) { ex.printStackTrace(); } @@ -325,11 +197,12 @@ public abstract class TiledPrintingAWTBase extends UITestCase implements Printab } /** Wait for idle .. simply acquiring all locks and releasing them. */ - public void waitUntilPrintJobsIdle() { + public void waitUntilPrintJobsIdle(PrintableBase p) { lock.lock(); try { - lockPrinting.lock(); - lockPrinting.unlock(); + if( null != p ) { + p.waitUntilIdle(); + } } finally { lock.unlock(); } -- cgit v1.2.3