001: /*
002: * $Id: PDFJob.java,v 1.2 2001/11/15 20:18:11 ezb Exp $
003: *
004: * $Date: 2001/11/15 20:18:11 $
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2.1 of the License, or (at your option) any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: */
020: package gnu.jpdf;
021:
022: import java.awt.*;
023: import java.io.*;
024: import java.util.*;
025:
026: /**
027: * <p>This class extends awt's PrintJob, to provide a simple method of writing
028: * PDF documents.</p>
029: *
030: * <p>You can use this with any code that uses Java's printing mechanism. It
031: * does include a few extra methods to provide access to some of PDF's features
032: * like annotations, or outlines.</p>
033: *
034: *
035: * @author Peter T Mount, http://www.retep.org.uk/pdf/
036: * @author Eric Z. Beard, ericzbeard@hotmail.com
037: * @author $Author: ezb $
038: * @version $Revision: 1.2 $, $Date: 2001/11/15 20:18:11 $
039: */
040: public class PDFJob extends PrintJob implements Serializable {
041: /*
042: * NOTE: The original class is the work of Peter T. Mount, who released it
043: * in the uk.org.retep.pdf package. It was modified by Eric Z. Beard as
044: * follows:
045: * The package name was changed to gnu.jpdf
046: * The formatting was changed a little bit.
047: * This used to subclass an abstract class with the same name in
048: * another package to support jdk1.1. Now it's one concrete class,
049: * with no jdk1.1 support
050: * Instances of PDFJob come directly from constructors, not
051: * static methods in PDFDocument (which used to be PDF)
052: * It is still licensed under the LGPL.
053: */
054:
055: /**
056: * This is the OutputStream the PDF file will be written to when complete
057: * Note: This is transient, as it's not valid after being Serialized.
058: */
059: protected transient OutputStream os;
060:
061: /**
062: * This is the PDF file being constructed
063: */
064: protected PDFDocument pdfDocument;
065:
066: /**
067: * This is the current page being constructed by the last getGraphics()
068: * call
069: */
070: protected PDFPage page;
071:
072: /**
073: * This is the page number of the current page
074: */
075: protected int pagenum;
076:
077: // Constructors
078:
079: /**
080: * <p>This constructs the job. This method must be used when creating a
081: * template pdf file, ie one that is Serialised by one application, and
082: * then restored by another.</p>
083: *
084: * <p>ezb 20011115 - Haven't done anything with templates yet, don't know
085: * how/if they are implemented</p>
086: */
087: public PDFJob() {
088: this (null);
089: }
090:
091: /**
092: * <p>This constructs the job. This is the primary constructor that
093: * will be used for creating pdf documents with this package. The
094: * specified output stream is a handle to the .pdf file you wish to
095: * create.</p>
096: *
097: * @param os - <code>OutputStream</code> to use for the pdf output
098: */
099: public PDFJob(OutputStream os) {
100: this (os, "PDF Doc");
101: }
102:
103: /**
104: * <p>This constructs the job. This is the primary constructor that
105: * will be used for creating pdf documents with this package. The
106: * specified output stream is a handle to the .pdf file you wish to
107: * create.</p>
108: *
109: * <p>Use this constructor if you want to give the pdf document a name
110: * other than the default of "PDF Doc"</p>
111: *
112: * @param os - <code>OutputStream</code> to use for the pdf output
113: * @param title a <code>String</code> value
114: */
115: public PDFJob(OutputStream os, String title) {
116: this .os = os;
117: this .pdfDocument = new PDFDocument();
118: pagenum = 0;
119: pdfDocument.getPDFInfo().setTitle(title);
120: }
121:
122: /**
123: * <p>This returns a graphics object that can be used to draw on a page.
124: * In PDF, this will be a new page within the document.</p>
125: *
126: * @param orient - the <code>int</code> Orientation of the new page,
127: * as defined in <code>PDFPage</code>
128: * @return Graphics object to draw.
129: * @see gnu.jpdf.PDFPage#PORTRAIT
130: * @see gnu.jpdf.PDFPage#LANDSCAPE
131: * @see gnu.jpdf.PDFPage#INVERTEDPORTRAIT
132: * @see gnu.jpdf.PDFPage#SEASCAPE
133: */
134: public Graphics getGraphics(int orient) {
135: // create a new page
136: page = new PDFPage(orient);
137: pdfDocument.add(page);
138: pagenum++;
139:
140: // Now create a Graphics object to draw onto the page
141: return new graphic(page, this );
142: }
143:
144: /**
145: * <p>This writes the PDF document to the OutputStream, finishing the
146: * document.</p>
147: */
148: public void end() {
149: try {
150: pdfDocument.write(os);
151: } catch (IOException ioe) {
152: // Ideally we should throw this. However, PrintJob doesn't throw
153: // anything, so we will print the Stack Trace instead.
154: ioe.printStackTrace();
155: }
156:
157: // This should mark us as dead
158: os = null;
159: pdfDocument = null;
160: }
161:
162: /**
163: * <p>This returns a graphics object that can be used to draw on a page.
164: * In PDF, this will be a new page within the document.</p>
165: *
166: * <p>This new page will by default be oriented as a portrait</p>
167: *
168: * @return a <code>Graphics</code> object to draw to.
169: */
170: public Graphics getGraphics() {
171: return getGraphics(PDFPage.PORTRAIT);
172: }
173:
174: /**
175: * <p>Returns the page dimension</p>
176: *
177: * @return a <code>Dimension</code> instance, the size of the page
178: */
179: public Dimension getPageDimension() {
180: if (page == null) {
181: System.err
182: .println("PDFJob.getPageDimension(), page is null");
183: }
184: Rectangle r = page.getMedia();
185:
186: // if landscape or seascape, then we swap the dimensions which
187: // should fool existing code.
188: int rot = page.getOrientation();
189: if (rot == 90 || rot == 270) {
190: return new Dimension(r.height - r.y, r.width - r.x);
191: }
192: return new Dimension(r.width - r.x, r.height - r.y);
193: }
194:
195: /**
196: * <p>How about a setPageDimension(Rectangle media) ?? </p>
197: */
198:
199: /**
200: * This returns the page resolution.
201: *
202: * <p>This is the PDF (and Postscript) device resolution of 72 dpi
203: * (equivalent to 1 point).</p>
204: *
205: * @return an <code>int</code>, the resolution in pixels per inch
206: */
207: public int getPageResolution() {
208: return 72;
209: }
210:
211: /**
212: * <p>In AWT's PrintJob, this would return true if the user requested that the
213: * file is printed in reverse order. For PDF's this is not applicable, so
214: * it will always return false.</p>
215: *
216: * @return false
217: */
218: public boolean lastPageFirst() {
219: return false;
220: }
221:
222: //======== END OF PrintJob extension ==========
223:
224: /**
225: * Returns the PDFDocument object for this document.
226: * Useful for gaining access to
227: * the internals of PDFDocument.
228: * @return the PDF object
229: */
230: public PDFDocument getPDFDocument() {
231: return pdfDocument;
232: }
233:
234: /**
235: * <p>Returns the current PDFPage being worked on. Useful for working on
236: * Annotations (like links), etc.</p>
237: *
238: * @return the <code>PDFPage</code> currently being constructed
239: */
240: public PDFPage getCurrentPage() {
241: return page;
242: }
243:
244: /**
245: * <p>Returns the current page number.
246: * Useful if you need to include one in the document</p>
247: *
248: * @return the <code>int</code> current page number
249: */
250: public int getCurrentPageNumber() {
251: return pagenum;
252: }
253:
254: /**
255: * <p>This method attaches an outline to the current page being generated.
256: * When selected, the outline displays the top of the page.</p>
257: *
258: * @param title a <code>String</code>, the title of the Outline
259: * @return a <code>PDFOutline</code> object that was created,
260: * for adding sub-outline's if required.
261: */
262: public PDFOutline addOutline(String title) {
263: return page.addOutline(title);
264: }
265:
266: /**
267: * <p>This method attaches an outline to the current page being generated.
268: * When selected, the outline displays the specified region.</p>
269: *
270: * @param title Outline title to attach
271: * @param x Left coordinate of region
272: * @param y Top coordinate of region
273: * @param w width of region
274: * @param h height of region
275: * @return the <code>PDFOutline</code> object created,
276: * for adding sub-outline's if required.
277: */
278: public PDFOutline addOutline(String title, int x, int y, int w,
279: int h) {
280: return page.addOutline(title, x, y, w, h);
281: }
282:
283: /**
284: * Convenience method: Adds a text note to the document.
285: * @param note Text of the note
286: * @param x Coordinate of note
287: * @param y Coordinate of note
288: * @param w Width of the note
289: * @param h Height of the note
290: * @return Returns the annotation, so other settings can be changed.
291: */
292: public PDFAnnot addNote(String note, int x, int y, int w, int h) {
293: return page.addNote(note, x, y, w, h);
294: }
295:
296: /**
297: * <p>This inner class extends PDFGraphics for the PrintJob.</p>
298: *
299: * <p>Like with java.awt, Graphics instances created with PrintJob implement
300: * the PrintGraphics interface. Here we implement that method, and overide
301: * PDFGraphics.create() method, so all instances have this interface.</p>
302: */
303: class graphic extends PDFGraphics implements PrintGraphics {
304: /**
305: * The PDFJob we are linked with
306: */
307: private PDFJob job;
308:
309: /**
310: * @param page to attach to
311: * @param job PDFJob containing this graphic
312: */
313: graphic(PDFPage page, PDFJob job) {
314: super ();
315: this .init(page);
316: this .job = job;
317: }
318:
319: /**
320: * This is used by our version of create()
321: */
322: graphic(PDFPage page, PDFJob job, PrintWriter pw) {
323: super ();
324: this .init(page, pw);
325: this .job = job;
326: }
327:
328: /**
329: * This returns a child instance of this Graphics object. As with AWT,
330: * the affects of using the parent instance while the child exists,
331: * is not determined.
332: *
333: * <p>This method is used to make a new Graphics object without
334: * going to a new page</p>
335: *
336: * <p>Once complete, the child should be released with it's dispose()
337: * method which will restore the graphics state to it's parent.
338: *
339: * @return Graphics object
340: */
341: public Graphics create() {
342: closeBlock();
343: graphic g = new graphic(getPage(), job, getWriter());
344:
345: // The new instance inherits a few items
346: g.clipRectangle = new Rectangle(clipRectangle);
347:
348: return (Graphics) g;
349: }
350:
351: /**
352: * This is the PrintGraphics interface
353: * @return PrintJob for this object
354: */
355: public PrintJob getPrintJob() {
356: return (PrintJob) job;
357: }
358:
359: } // end inner class graphic
360:
361: } // end class PDFJob
|