code: /*
   * $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 pdf;
  
  import java.io.IOException;
  import java.io.OutputStream;
  import java.io.Serializable;
  import java.util.Vector;
  
  
  public class PDFDocument implements Serializable
  {
  	
  
    protected int objser;
      
    /**
     * This vector contains each indirect object within the document.
     */
    protected Vector<PDFObject> objects;
      
    /**
     * This is the Catalog object, which is required by each PDF Document
     */
    private PDFCatalog catalog;
      
    /**
     * This is the info object. Although this is an optional object, we
     * include it.
     */
    private PDFInfo info;
      
    /**
     * This is the Pages object, which is required by each PDF Document
     */
    private PDFPageList pdfPageList;
      
    /**
     * This is the Outline object, which is optional
     */
    private PDFOutline outline;
      
    /**
     * This holds a PDFObject describing the default border for annotations.
     * It's only used when the document is being written.
     */
    protected PDFObject defaultOutlineBorder;
      
    /**
     * <p>This page mode indicates that the document 
     * should be opened just with the page visible.  This is the default</p>
     */
    public static final int USENONE = 0;
      
    /**
     * <p>This page mode indicates that the Outlines 
     * should also be displayed when the document is opened.</p>
     */
    public static final int USEOUTLINES = 1;
      
    /**
     * <p>This page mode indicates that the Thumbnails should be visible when the
     * document first opens.</p>
     */
    public static final int USETHUMBS = 2;
      
    /**
     * <p>
     * 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.</p>
     */
    public static final int FULLSCREEN = 3;
      
    /**
     * <p>
     * These map the page modes just defined to the pagemodes setting of PDF.
     * </p>
     */
    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;
      
    /**
     * <p>This is used to provide a unique name for an image</p>
     */
    private int imageid = 0;
      
    /**
     * This holds the current fonts
     */
    private Vector<PDFFont> fonts;
      
        
    /**
     * <p>This creates a PDF document with the default pagemode</p>
     */
    public PDFDocument() {
      this(USENONE);
    }
      
    /**
     * <p>This creates a PDF document</p>
     * @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 Vector<PDFObject>();
      fonts = new Vector<PDFFont>();
          
      // Now create some standard objects
      add(pdfPageList = new PDFPageList());
      add(catalog = new PDFCatalog(pdfPageList,pagemode));
      add(info = new PDFInfo());
          
      // Acroread on linux seems to die if there is no root outline
      add(getOutline());
    }
      
  
  
    /**
     * This adds a top level object to the document.
     *
     * <p>Once added, it is allocated a unique serial number.
     *
     * <p><b>Note:</b> 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;
    }
      
    /**
     * <p>This returns a specific page. It's used mainly when using a
     * Serialized template file.</p>
     *
     * ?? 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;
    }
      
    /**
     * Sets a unique name to a PDFImage
     * @param img PDFImage to set the name of
     * @return the name given to the image
     */
    public String setImageName(PDFImage img) {
      imageid++;
      img.setName("/Image"+imageid);
      return img.getName();
    }
  
  
    /**
     * <p>Set the PDFInfo object, which contains author, title, 
     * keywords, etc</p>
     * @param info a PDFInof object
     */
    public void setPDFInfo(PDFInfo info) {
      this.info = info;
    }
      
  
    /**
     * <p>Get the PDFInfo object, which contains author, title, keywords,
     * etc</p>
     * @return the PDFInfo object for this document.
     */
    public PDFInfo getPDFInfo() {
      return this.info;
    }
  
   
    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
  