/* * $Id: PDFJob.java,v 1.3 2007/08/26 18:56:35 gil1 Exp $ * * $Date: 2007/08/26 18:56:35 $ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package gnu.jpdf; import java.awt.Dimension; import java.awt.Graphics; import java.awt.PrintGraphics; import java.awt.PrintJob; import java.awt.Rectangle; import java.awt.print.PageFormat; import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; import java.io.Serializable; /** * <p>This class extends awt's PrintJob, to provide a simple method of writing * PDF documents.</p> * * <p>You can use this with any code that uses Java's printing mechanism. It * does include a few extra methods to provide access to some of PDF's features * like annotations, or outlines.</p> * * * @author Peter T Mount, http://www.retep.org.uk/pdf/ * @author Eric Z. Beard, ericzbeard@hotmail.com * @version $Revision: 1.3 $, $Date: 2007/08/26 18:56:35 $ */ public class PDFJob extends PrintJob implements Serializable { /* * NOTE: The original class is the work of Peter T. Mount, who released it * in the uk.org.retep.pdf package. It was modified by Eric Z. Beard as * follows: * The package name was changed to gnu.jpdf * The formatting was changed a little bit. * This used to subclass an abstract class with the same name in * another package to support jdk1.1. Now it's one concrete class, * with no jdk1.1 support * Instances of PDFJob come directly from constructors, not * static methods in PDFDocument (which used to be PDF) * It is still licensed under the LGPL. */ /** * This is the OutputStream the PDF file will be written to when complete * Note: This is transient, as it's not valid after being Serialized. */ protected transient OutputStream os; /** * This is the PDF file being constructed */ protected PDFDocument pdfDocument; /** * This is the current page being constructed by the last getGraphics() * call */ protected PDFPage page; /** * This is the page number of the current page */ protected int pagenum; // Constructors /** * <p>This constructs the job. This method must be used when creating a * template pdf file, ie one that is Serialised by one application, and * then restored by another.</p> * * <p>ezb 20011115 - Haven't done anything with templates yet, don't know * how/if they are implemented</p> */ public PDFJob() { this(null); } /** * <p>This constructs the job. This is the primary constructor that * will be used for creating pdf documents with this package. The * specified output stream is a handle to the .pdf file you wish to * create.</p> * * @param os - <code>OutputStream</code> to use for the pdf output */ public PDFJob(OutputStream os) { this(os, "PDF Doc"); } /** * <p>This constructs the job. This is the primary constructor that * will be used for creating pdf documents with this package. The * specified output stream is a handle to the .pdf file you wish to * create.</p> * * <p>Use this constructor if you want to give the pdf document a name * other than the default of "PDF Doc"</p> * * @param os - <code>OutputStream</code> to use for the pdf output * @param title a <code>String</code> value */ public PDFJob(OutputStream os, String title) { this.os = os; this.pdfDocument = new PDFDocument(); pagenum = 0; pdfDocument.getPDFInfo().setTitle(title); } /** * <p>This returns a graphics object that can be used to draw on a page. * In PDF, this will be a new page within the document.</p> * * @param orient - the <code>int</code> Orientation of the new page, * as defined in <code>PDFPage</code> * @return Graphics object to draw. * @see PageFormat#PORTRAIT * @see PageFormat#LANDSCAPE * @see PageFormat#REVERSE_LANDSCAPE */ public Graphics getGraphics(int orient) { // create a new page page = new PDFPage(orient); pdfDocument.add(page); pagenum++; // Now create a Graphics object to draw onto the page return new graphic(page,this); } /** * <p>This returns a graphics object that can be used to draw on a page. * In PDF, this will be a new page within the document.</p> * * @param pageFormat PageFormat describing the page size * @return Graphics object to draw. */ public Graphics getGraphics(PageFormat pageFormat) { // create a new page page = new PDFPage(pageFormat); pdfDocument.add(page); pagenum++; // Now create a Graphics object to draw onto the page return new graphic(page,this); } /** * <p>This writes the PDF document to the OutputStream, finishing the * document.</p> */ public void end() { try { pdfDocument.write(os); } catch(IOException ioe) { // Ideally we should throw this. However, PrintJob doesn't throw // anything, so we will print the Stack Trace instead. ioe.printStackTrace(); } finally { try { if (os != null) { os.close(); } } catch (Exception e) { e.printStackTrace(); } } // This should mark us as dead os = null; pdfDocument = null; } /** * <p>This returns a graphics object that can be used to draw on a page. * In PDF, this will be a new page within the document.</p> * * <p>This new page will by default be oriented as a portrait</p> * * @return a <code>Graphics</code> object to draw to. */ public Graphics getGraphics() { return getGraphics(PageFormat.PORTRAIT); } /** * <p>Returns the page dimension</p> * * @return a <code>Dimension</code> instance, the size of the page */ public Dimension getPageDimension() { if (page == null) { System.err.println("PDFJob.getPageDimension(), page is null"); } return page.getDimension(); } /** * <p>How about a setPageDimension(Rectangle media) ?? </p> */ /** * This returns the page resolution. * * <p>This is the PDF (and Postscript) device resolution of 72 dpi * (equivalent to 1 point).</p> * * @return an <code>int</code>, the resolution in pixels per inch */ public int getPageResolution() { return 72; } /** * <p>In AWT's PrintJob, this would return true if the user requested that the * file is printed in reverse order. For PDF's this is not applicable, so * it will always return false.</p> * * @return false */ public boolean lastPageFirst() { return false; } //======== END OF PrintJob extension ========== /** * Returns the PDFDocument object for this document. * Useful for gaining access to * the internals of PDFDocument. * @return the PDF object */ public PDFDocument getPDFDocument() { return pdfDocument; } /** * <p>Returns the current PDFPage being worked on. Useful for working on * Annotations (like links), etc.</p> * * @return the <code>PDFPage</code> currently being constructed */ public PDFPage getCurrentPage() { return page; } /** * <p>Returns the current page number. * Useful if you need to include one in the document</p> * * @return the <code>int</code> current page number */ public int getCurrentPageNumber() { return pagenum; } /** * <p>This method attaches an outline to the current page being generated. * When selected, the outline displays the top of the page.</p> * * @param title a <code>String</code>, the title of the Outline * @return a <code>PDFOutline</code> object that was created, * for adding sub-outline's if required. */ public PDFOutline addOutline(String title) { return page.addOutline(title); } /** * <p>This method attaches an outline to the current page being generated. * When selected, the outline displays the specified region.</p> * * @param title Outline title to attach * @param x Left coordinate of region * @param y Top coordinate of region * @param w width of region * @param h height of region * @return the <code>PDFOutline</code> object created, * for adding sub-outline's if required. */ public PDFOutline addOutline(String title,int x,int y,int w,int h) { return page.addOutline(title,x,y,w,h); } /** * Convenience method: Adds a text note to the document. * @param note Text of the note * @param x Coordinate of note * @param y Coordinate of note * @param w Width of the note * @param h Height of the note * @return Returns the annotation, so other settings can be changed. */ public PDFAnnot addNote(String note,int x,int y,int w,int h) { return page.addNote(note,x,y,w,h); } /** * <p>This inner class extends PDFGraphics for the PrintJob.</p> * * <p>Like with java.awt, Graphics instances created with PrintJob implement * the PrintGraphics interface. Here we implement that method, and overide * PDFGraphics.create() method, so all instances have this interface.</p> */ class graphic extends PDFGraphics implements PrintGraphics { /** * The PDFJob we are linked with */ private PDFJob job; /** * @param page to attach to * @param job PDFJob containing this graphic */ graphic(PDFPage page,PDFJob job) { super(); this.init(page); this.job = job; } /** * This is used by our version of create() */ graphic(PDFPage page,PDFJob job,PrintWriter pw) { super(); this.init(page,pw); this.job = job; } /** * This returns a child instance of this Graphics object. As with AWT, * the affects of using the parent instance while the child exists, * is not determined. * * <p>This method is used to make a new Graphics object without * going to a new page</p> * * <p>Once complete, the child should be released with it's dispose() * method which will restore the graphics state to it's parent. * * @return Graphics object */ public Graphics create() { closeBlock(); graphic g = new graphic(getPage(),job,getWriter()); // The new instance inherits a few items g.clipRectangle = new Rectangle(clipRectangle); return (Graphics) g; } /** * This is the PrintGraphics interface * @return PrintJob for this object */ public PrintJob getPrintJob() { return (PrintJob)job; } } // end inner class graphic } // end class PDFJob