001: /*
002: * $Id: PDFDocument.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: */
021: package gnu.jpdf;
022:
023: import java.awt.*;
024: import java.io.*;
025: import java.util.*;
026:
027: /**
028: * <p>This class is the base of the PDF generator. A PDFDocument class is
029: * created for a document, and each page, object, annotation,
030: * etc is added to the document.
031: * Once complete, the document can be written to an OutputStream, and the PDF
032: * document's internal structures are kept in sync.</p>
033: *
034: * <p>Note that most programmers using this package will NEVER access
035: * one of these objects directly. Most everything can be done using
036: * <code>PDFJob</code> and <code>PDFGraphics</code>, so you don't need
037: * to directly instantiate a <code>PDFDocument</code></p>
038: *
039: * <p>ezb - 20011115 - Wondering if the constructors should even be public.
040: * When would someone want to make one of these and manipulate it outside
041: * the context of a job and graphics object?</p>
042: *
043: * @author Peter T Mount, http://www.retep.org.uk/pdf/
044: * @author Eric Z. Beard, ericzbeard@hotmail.com
045: * @author $Author: ezb $
046: * @version $Revision: 1.2 $, $Date: 2001/11/15 20:18:11 $
047: */
048: public class PDFDocument implements Serializable {
049:
050: /*
051: * NOTE: This class originated in uk.org.retep.pdf, by Peter T. Mount, and it
052: * has been modified by Eric Z. Beard, ericzbeard@hotmail.com. The
053: * package name was changed to gnu.jpdf and several inner classes were
054: * moved out into their own files.
055: */
056:
057: /**
058: * This is used to allocate objects a unique serial number in the document.
059: */
060: protected int objser;
061:
062: /**
063: * This vector contains each indirect object within the document.
064: */
065: protected Vector objects;
066:
067: /**
068: * This is the Catalog object, which is required by each PDF Document
069: */
070: private PDFCatalog catalog;
071:
072: /**
073: * This is the info object. Although this is an optional object, we
074: * include it.
075: */
076: private PDFInfo info;
077:
078: /**
079: * This is the Pages object, which is required by each PDF Document
080: */
081: private PDFPageList pdfPageList;
082:
083: /**
084: * This is the Outline object, which is optional
085: */
086: private PDFOutline outline;
087:
088: /**
089: * This holds a PDFObject describing the default border for annotations.
090: * It's only used when the document is being written.
091: */
092: protected PDFObject defaultOutlineBorder;
093:
094: /**
095: * <p>This page mode indicates that the document
096: * should be opened just with the page visible. This is the default</p>
097: */
098: public static final int USENONE = 0;
099:
100: /**
101: * <p>This page mode indicates that the Outlines
102: * should also be displayed when the document is opened.</p>
103: */
104: public static final int USEOUTLINES = 1;
105:
106: /**
107: * <p>This page mode indicates that the Thumbnails should be visible when the
108: * document first opens.</p>
109: */
110: public static final int USETHUMBS = 2;
111:
112: /**
113: * <p>
114: * This page mode indicates that when the document is opened, it is displayed
115: * in full-screen-mode. There is no menu bar, window controls nor any other
116: * window present.</p>
117: */
118: public static final int FULLSCREEN = 3;
119:
120: /**
121: * <p>
122: * These map the page modes just defined to the pagemodes setting of PDF.
123: * </p>
124: */
125: public static final String PDF_PAGE_MODES[] = { "/UseNone",
126: "/UseOutlines", "/UseThumbs", "/FullScreen" };
127:
128: /**
129: * This is used to provide a unique name for a font
130: */
131: private int fontid = 0;
132:
133: /**
134: * <p>This is used to provide a unique name for an image</p>
135: */
136: private int imageid = 0;
137:
138: /**
139: * This holds the current fonts
140: */
141: private Vector fonts;
142:
143: /**
144: * <p>This creates a PDF document with the default pagemode</p>
145: */
146: public PDFDocument() {
147: this (USENONE);
148: }
149:
150: /**
151: * <p>This creates a PDF document</p>
152: * @param pagemode an int, determines how the document will present itself to
153: * the viewer when it first opens.
154: */
155: public PDFDocument(int pagemode) {
156: objser = 1;
157: objects = new Vector();
158: fonts = new Vector();
159:
160: // Now create some standard objects
161: add(pdfPageList = new PDFPageList());
162: add(catalog = new PDFCatalog(pdfPageList, pagemode));
163: add(info = new PDFInfo());
164:
165: // Acroread on linux seems to die if there is no root outline
166: add(getOutline());
167: }
168:
169: /**
170: * This adds a top level object to the document.
171: *
172: * <p>Once added, it is allocated a unique serial number.
173: *
174: * <p><b>Note:</b> Not all object are added directly using this method.
175: * Some objects which have Kids (in PDF sub-objects or children are
176: * called Kids) will have their own add() method, which will call this
177: * one internally.
178: *
179: * @param obj The PDFObject to add to the document
180: * @return the unique serial number for this object.
181: */
182: public synchronized int add(PDFObject obj) {
183: objects.addElement(obj);
184: obj.objser = objser++; // create a new serial number
185: obj.pdfDocument = this ; // so they can find the document they belong to
186:
187: // If its a page, then add it to the pages collection
188: if (obj instanceof PDFPage)
189: pdfPageList.add((PDFPage) obj);
190:
191: return obj.objser;
192: }
193:
194: /**
195: * <p>This returns a specific page. It's used mainly when using a
196: * Serialized template file.</p>
197: *
198: * ?? How does a serialized template file work ???
199: *
200: * @param page page number to return
201: * @return PDFPage at that position
202: */
203: public PDFPage getPage(int page) {
204: return pdfPageList.getPage(page);
205: }
206:
207: /**
208: * @return the root outline
209: */
210: public PDFOutline getOutline() {
211: if (outline == null) {
212: outline = new PDFOutline();
213: catalog.setOutline(outline);
214: }
215: return outline;
216: }
217:
218: /**
219: * This returns a font of the specified type and font. If the font has
220: * not been defined, it creates a new font in the PDF document, and
221: * returns it.
222: *
223: * @param type PDF Font Type - usually "/Type1"
224: * @param font Java font name
225: * @param style java.awt.Font style (NORMAL, BOLD etc)
226: * @return PDFFont defining this font
227: */
228: public PDFFont getFont(String type, String font, int style) {
229: for (Enumeration en = fonts.elements(); en.hasMoreElements();) {
230: PDFFont ft = (PDFFont) en.nextElement();
231: if (ft.equals(type, font, style))
232: return ft;
233: }
234:
235: // the font wasn't found, so create it
236: fontid++;
237: PDFFont ft = new PDFFont("/F" + fontid, type, font, style);
238: add(ft);
239: fonts.addElement(ft);
240: return ft;
241: }
242:
243: /**
244: * Sets a unique name to a PDFImage
245: * @param img PDFImage to set the name of
246: * @return the name given to the image
247: */
248: public String setImageName(PDFImage img) {
249: imageid++;
250: img.setName("/Image" + imageid);
251: return img.getName();
252: }
253:
254: /**
255: * <p>Set the PDFInfo object, which contains author, title,
256: * keywords, etc</p>
257: */
258: public void setPDFInfo(PDFInfo info) {
259: this .info = info;
260: }
261:
262: /**
263: * <p>Get the PDFInfo object, which contains author, title, keywords,
264: * etc</p>
265: */
266: public PDFInfo getPDFInfo() {
267: return this .info;
268: }
269:
270: /**
271: * This writes the document to an OutputStream.
272: *
273: * <p><b>Note:</b> You can call this as many times as you wish, as long as
274: * the calls are not running at the same time.
275: *
276: * <p>Also, objects can be added or amended between these calls.
277: *
278: * <p>Also, the OutputStream is not closed, but will be flushed on
279: * completion. It is up to the caller to close the stream.
280: *
281: * @param os OutputStream to write the document to
282: * @exception IOException on error
283: */
284: public void write(OutputStream os) throws IOException {
285: PDFOutput pos = new PDFOutput(os);
286:
287: // Write each object to the OutputStream. We call via the output
288: // as that builds the xref table
289: for (Enumeration en = objects.elements(); en.hasMoreElements();)
290: pos.write((PDFObject) en.nextElement());
291:
292: // Finally close the output, which writes the xref table.
293: pos.close();
294:
295: // and flush the output stream to ensure everything is written.
296: os.flush();
297: }
298:
299: } // end class PDFDocument
|