/* * $Id: PDFDocument.java,v 1.4 2007/09/22 12:58:40 gil1 Exp $ * * $Date: 2007/09/22 12:58:40 $ * * 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.FontFormatException; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Vector; import java.util.logging.Level; import java.util.logging.Logger; /** *
This class is the base of the PDF generator. A PDFDocument class is * created for a document, and each page, object, annotation, * etc is added to the document. * Once complete, the document can be written to an OutputStream, and the PDF * document's internal structures are kept in sync.
* *Note that most programmers using this package will NEVER access
* one of these objects directly. Most everything can be done using
* PDFJob and PDFGraphics, so you don't need
* to directly instantiate a PDFDocument
ezb - 20011115 - Wondering if the constructors should even be public. * When would someone want to make one of these and manipulate it outside * the context of a job and graphics object?
* * @author Peter T Mount, http://www.retep.org.uk/pdf/ * @author Eric Z. Beard, ericzbeard@hotmail.com * @author Gilbert DeLeeuw, gil1@users.sourceforge.net * @version $Revision: 1.4 $, $Date: 2007/09/22 12:58:40 $ */ public class PDFDocument implements Serializable { /* * NOTE: This class originated in uk.org.retep.pdf, by Peter T. Mount, and it * has been modified by Eric Z. Beard, ericzbeard@hotmail.com. The * package name was changed to gnu.jpdf and several inner classes were * moved out into their own files. */ /** * This is used to allocate objects a unique serial number in the document. */ protected int objser; /** * This vector contains each indirect object within the document. */ protected VectorThis page mode indicates that the document * should be opened just with the page visible. This is the default
*/ public static final int USENONE = 0; /** *This page mode indicates that the Outlines * should also be displayed when the document is opened.
*/ public static final int USEOUTLINES = 1; /** *This page mode indicates that the Thumbnails should be visible when the * document first opens.
*/ public static final int USETHUMBS = 2; /** ** This page mode indicates that when the document is opened, it is displayed * in full-screen-mode. There is no menu bar, window controls nor any other * window present.
*/ public static final int FULLSCREEN = 3; /** ** These map the page modes just defined to the pagemodes setting of PDF. *
*/ public static final String PDF_PAGE_MODES[] = { "/UseNone", "/UseOutlines", "/UseThumbs", "/FullScreen" }; /** * This is used to provide a unique name for a font */ private int fontid = 0; /** *This is used to provide a unique name for an image
*/ private int imageid = 0; /** * This holds the current fonts */ private VectorThis creates a PDF document with the default pagemode
*/ public PDFDocument() { this(USENONE); } /** *This creates a PDF document
* @param pagemode an int, determines how the document will present itself to * the viewer when it first opens. */ public PDFDocument(int pagemode) { objser = 1; objects = new VectorOnce added, it is allocated a unique serial number. * *
Note: Not all object are added directly using this method. * Some objects which have Kids (in PDF sub-objects or children are * called Kids) will have their own add() method, which will call this * one internally. * * @param obj The PDFObject to add to the document * @return the unique serial number for this object. */ public synchronized int add(PDFObject obj) { objects.addElement(obj); obj.objser=objser++; // create a new serial number obj.pdfDocument = this; // so they can find the document they belong to // If its a page, then add it to the pages collection if(obj instanceof PDFPage) pdfPageList.add((PDFPage)obj); return obj.objser; } /** *
This returns a specific page. It's used mainly when using a * Serialized template file.
* * ?? How does a serialized template file work ??? * * @param page page number to return * @return PDFPage at that position */ public PDFPage getPage(int page) { return pdfPageList.getPage(page); } /** * @return the root outline */ public PDFOutline getOutline() { if(outline==null) { outline = new PDFOutline(); catalog.setOutline(outline); } return outline; } /** * This returns a font of the specified type and font. If the font has * not been defined, it creates a new font in the PDF document, and * returns it. * * @param type PDF Font Type - usually "/Type1" * @param font Java font name * @param style java.awt.Font style (NORMAL, BOLD etc) * @return PDFFont defining this font */ public PDFFont getFont(String type,String font,int style) { for(PDFFont ft : fonts) { if(ft.equals(type,font,style)) return ft; } // the font wasn't found, so create it fontid++; PDFFont ft = new PDFFont("/F"+fontid,type,font,style); add(ft); fonts.addElement(ft); return ft; } public PDFFont getEmbeddedFont(String font, int style, File file) throws FileNotFoundException, IOException { for (PDFFont ft : fonts) { if (ft.equals("/TrueType", font, style)) { return ft; } } PDFStream fontFile2 = new PDFStream() { @Override public void write(OutputStream os) throws IOException { writeStart(os); os.write("/Length1 ".getBytes()); os.write(Integer.toString(buf.size()).getBytes()); os.write("\n".getBytes()); writeStream(os); } }; fontFile2.setDeflate(true); OutputStream ff2Os = fontFile2.getOutputStream(); InputStream is = new FileInputStream(file); byte buf[] = new byte[1024]; int cnt = 0; while ((cnt = is.read(buf)) > 0) { ff2Os.write(buf, 0, cnt); } is.close(); //ff2Os.write("AHOJ".getBytes()); add(fontFile2); // the font wasn't found, so create it fontid++; TtfParser par = new TtfParser(); try { par.loadFromTTF(file, 1024); } catch (FontFormatException ex) { Logger.getLogger(PDFDocument.class.getName()).log(Level.SEVERE, null, ex); } PDFFontDescriptor fontDescriptor = new PDFFontDescriptor(font, par.getAscent(), par.getDescent(), par.getCapHeight(), 80/*?*/, "" + fontFile2.getSerialID() + " 0 R"); add(fontDescriptor); final ListSet the PDFInfo object, which contains author, title, * keywords, etc
* @param info a PDFInof object */ public void setPDFInfo(PDFInfo info) { this.info = info; } /** *Get the PDFInfo object, which contains author, title, keywords, * etc
* @return the PDFInfo object for this document. */ public PDFInfo getPDFInfo() { return this.info; } /** * This writes the document to an OutputStream. * *Note: You can call this as many times as you wish, as long as * the calls are not running at the same time. * *
Also, objects can be added or amended between these calls. * *
Also, the OutputStream is not closed, but will be flushed on * completion. It is up to the caller to close the stream. * * @param os OutputStream to write the document to * @exception IOException on error */ public void write(OutputStream os) throws IOException { PDFOutput pos = new PDFOutput(os); // Write each object to the OutputStream. We call via the output // as that builds the xref table for(PDFObject o : objects) { pos.write(o); } // Finally close the output, which writes the xref table. pos.close(); // and flush the output stream to ensure everything is written. os.flush(); } } // end class PDFDocument