Save This Page
Home » iText-src-2.1.3 » com.lowagie » text » pdf » [javadoc | source]
    1   /*
    2    * $Id: PdfCopy.java 3527 2008-07-06 15:34:38Z blowagie $
    3    *
    4    * Copyright (C) 2002 Mark Thompson
    5    *
    6    * The contents of this file are subject to the Mozilla Public License Version 1.1
    7    * (the "License"); you may not use this file except in compliance with the License.
    8    * You may obtain a copy of the License at http://www.mozilla.org/MPL/
    9    *
   10    * Software distributed under the License is distributed on an "AS IS" basis,
   11    * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
   12    * for the specific language governing rights and limitations under the License.
   13    *
   14    * The Original Code is 'iText, a free JAVA-PDF library'.
   15    *
   16    * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
   17    * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
   18    * All Rights Reserved.
   19    * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
   20    * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
   21    *
   22    * Contributor(s): all the names of the contributors are added in the source code
   23    * where applicable.
   24    *
   25    * Alternatively, the contents of this file may be used under the terms of the
   26    * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
   27    * provisions of LGPL are applicable instead of those above.  If you wish to
   28    * allow use of your version of this file only under the terms of the LGPL
   29    * License and not to allow others to use your version of this file under
   30    * the MPL, indicate your decision by deleting the provisions above and
   31    * replace them with the notice and other provisions required by the LGPL.
   32    * If you do not delete the provisions above, a recipient may use your version
   33    * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
   34    *
   35    * This library is free software; you can redistribute it and/or modify it
   36    * under the terms of the MPL as stated above or under the terms of the GNU
   37    * Library General Public License as published by the Free Software Foundation;
   38    * either version 2 of the License, or any later version.
   39    *
   40    * This library is distributed in the hope that it will be useful, but WITHOUT
   41    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   42    * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
   43    * details.
   44    *
   45    * If you didn't download this code from the following link, you should check if
   46    * you aren't using an obsolete version:
   47    * http://www.lowagie.com/iText/
   48    */
   49   package com.lowagie.text.pdf;
   50   
   51   import java.io.IOException;
   52   import java.io.OutputStream;
   53   import java.util.HashMap;
   54   import java.util.Iterator;
   55   
   56   import com.lowagie.text.Document;
   57   import com.lowagie.text.DocumentException;
   58   import com.lowagie.text.ExceptionConverter;
   59   import com.lowagie.text.Rectangle;
   60   import java.util.ArrayList;
   61   
   62   /**
   63    * Make copies of PDF documents. Documents can be edited after reading and
   64    * before writing them out.
   65    * @author Mark Thompson
   66    */
   67   
   68   public class PdfCopy extends PdfWriter {
   69       /**
   70        * This class holds information about indirect references, since they are
   71        * renumbered by iText.
   72        */
   73       static class IndirectReferences {
   74           PdfIndirectReference theRef;
   75           boolean hasCopied;
   76           IndirectReferences(PdfIndirectReference ref) {
   77               theRef = ref;
   78               hasCopied = false;
   79           }
   80           void setCopied() { hasCopied = true; }
   81           boolean getCopied() { return hasCopied; }
   82           PdfIndirectReference getRef() { return theRef; }
   83       };
   84       protected HashMap indirects;
   85       protected HashMap indirectMap;
   86       protected int currentObjectNum = 1;
   87       protected PdfReader reader;
   88       protected PdfIndirectReference acroForm;
   89       protected int[] namePtr = {0};
   90       /** Holds value of property rotateContents. */
   91       private boolean rotateContents = true;
   92       protected PdfArray fieldArray;
   93       protected HashMap fieldTemplates;
   94       
   95       /**
   96        * A key to allow us to hash indirect references
   97        */
   98       protected static class RefKey {
   99           int num;
  100           int gen;
  101           RefKey(int num, int gen) {
  102               this.num = num;
  103               this.gen = gen;
  104           }
  105           RefKey(PdfIndirectReference ref) {
  106               num = ref.getNumber();
  107               gen = ref.getGeneration();
  108           }
  109           RefKey(PRIndirectReference ref) {
  110               num = ref.getNumber();
  111               gen = ref.getGeneration();
  112           }
  113           public int hashCode() {
  114               return (gen<<16)+num;
  115           }
  116           public boolean equals(Object o) {
  117               if (!(o instanceof RefKey)) return false;
  118               RefKey other = (RefKey)o;
  119               return this.gen == other.gen && this.num == other.num;
  120           }
  121           public String toString() {
  122               return Integer.toString(num) + ' ' + gen;
  123           }
  124       }
  125       
  126       /**
  127        * Constructor
  128        * @param document
  129        * @param os outputstream
  130        */
  131       public PdfCopy(Document document, OutputStream os) throws DocumentException {
  132           super(new PdfDocument(), os);
  133           document.addDocListener(pdf);
  134           pdf.addWriter(this);
  135           indirectMap = new HashMap();
  136       }
  137   
  138       /** Getter for property rotateContents.
  139        * @return Value of property rotateContents.
  140        *
  141        */
  142       public boolean isRotateContents() {
  143           return this.rotateContents;
  144       }
  145       
  146       /** Setter for property rotateContents.
  147        * @param rotateContents New value of property rotateContents.
  148        *
  149        */
  150       public void setRotateContents(boolean rotateContents) {
  151           this.rotateContents = rotateContents;
  152       }
  153   
  154       /**
  155        * Grabs a page from the input document
  156        * @param reader the reader of the document
  157        * @param pageNumber which page to get
  158        * @return the page
  159        */
  160       public PdfImportedPage getImportedPage(PdfReader reader, int pageNumber) {
  161           if (currentPdfReaderInstance != null) {
  162               if (currentPdfReaderInstance.getReader() != reader) {
  163                   try {
  164                       currentPdfReaderInstance.getReader().close();
  165                       currentPdfReaderInstance.getReaderFile().close();
  166                   }
  167                   catch (IOException ioe) {
  168                       // empty on purpose
  169                   }
  170                   currentPdfReaderInstance = reader.getPdfReaderInstance(this);
  171               }
  172           }
  173           else {
  174               currentPdfReaderInstance = reader.getPdfReaderInstance(this);
  175           }
  176           return currentPdfReaderInstance.getImportedPage(pageNumber);            
  177       }
  178       
  179       
  180       /**
  181        * Translate a PRIndirectReference to a PdfIndirectReference
  182        * In addition, translates the object numbers, and copies the
  183        * referenced object to the output file.
  184        * NB: PRIndirectReferences (and PRIndirectObjects) really need to know what
  185        * file they came from, because each file has its own namespace. The translation
  186        * we do from their namespace to ours is *at best* heuristic, and guaranteed to
  187        * fail under some circumstances.
  188        */
  189       protected PdfIndirectReference copyIndirect(PRIndirectReference in) throws IOException, BadPdfFormatException {
  190           PdfIndirectReference theRef;
  191           RefKey key = new RefKey(in);
  192           IndirectReferences iRef = (IndirectReferences)indirects.get(key);
  193           if (iRef != null) {
  194               theRef = iRef.getRef();
  195               if (iRef.getCopied()) {
  196                   return theRef;
  197               }
  198           }
  199           else {
  200               theRef = body.getPdfIndirectReference();
  201               iRef = new IndirectReferences(theRef);
  202               indirects.put(key, iRef);
  203           }
  204           PdfObject obj = PdfReader.getPdfObjectRelease(in);
  205           if (obj != null && obj.isDictionary()) {
  206               PdfObject type = PdfReader.getPdfObjectRelease(((PdfDictionary)obj).get(PdfName.TYPE));
  207               if (type != null && PdfName.PAGE.equals(type)) {
  208                   return theRef;
  209               }
  210           }
  211           iRef.setCopied();
  212           obj = copyObject(obj);
  213           addToBody(obj, theRef);
  214           return theRef;
  215       }
  216       
  217       /**
  218        * Translate a PRDictionary to a PdfDictionary. Also translate all of the
  219        * objects contained in it.
  220        */
  221       protected PdfDictionary copyDictionary(PdfDictionary in)
  222       throws IOException, BadPdfFormatException {
  223           PdfDictionary out = new PdfDictionary();
  224           PdfObject type = PdfReader.getPdfObjectRelease(in.get(PdfName.TYPE));
  225           
  226           for (Iterator it = in.getKeys().iterator(); it.hasNext();) {
  227               PdfName key = (PdfName)it.next();
  228               PdfObject value = in.get(key);
  229               //	    System.out.println("Copy " + key);
  230               if (type != null && PdfName.PAGE.equals(type)) {
  231                   if (!key.equals(PdfName.B) && !key.equals(PdfName.PARENT))
  232                       out.put(key, copyObject(value));
  233               }
  234               else
  235                   out.put(key, copyObject(value));
  236           }
  237           return out;
  238       }
  239       
  240       /**
  241        * Translate a PRStream to a PdfStream. The data part copies itself.
  242        */
  243       protected PdfStream copyStream(PRStream in) throws IOException, BadPdfFormatException {
  244           PRStream out = new PRStream(in, null);
  245           
  246           for (Iterator it = in.getKeys().iterator(); it.hasNext();) {
  247               PdfName key = (PdfName) it.next();
  248               PdfObject value = in.get(key);
  249               out.put(key, copyObject(value));
  250           }
  251           
  252           return out;
  253       }
  254       
  255       
  256       /**
  257        * Translate a PRArray to a PdfArray. Also translate all of the objects contained
  258        * in it
  259        */
  260       protected PdfArray copyArray(PdfArray in) throws IOException, BadPdfFormatException {
  261           PdfArray out = new PdfArray();
  262           
  263           for (Iterator i = in.getArrayList().iterator(); i.hasNext();) {
  264               PdfObject value = (PdfObject)i.next();
  265               out.add(copyObject(value));
  266           }
  267           return out;
  268       }
  269       
  270       /**
  271        * Translate a PR-object to a Pdf-object
  272        */
  273       protected PdfObject copyObject(PdfObject in) throws IOException,BadPdfFormatException {
  274           if (in == null)
  275               return PdfNull.PDFNULL;
  276           switch (in.type) {
  277               case PdfObject.DICTIONARY:
  278                   //	        System.out.println("Dictionary: " + in.toString());
  279                   return copyDictionary((PdfDictionary)in);
  280               case PdfObject.INDIRECT:
  281                   return copyIndirect((PRIndirectReference)in);
  282               case PdfObject.ARRAY:
  283                   return copyArray((PdfArray)in);
  284               case PdfObject.NUMBER:
  285               case PdfObject.NAME:
  286               case PdfObject.STRING:
  287               case PdfObject.NULL:
  288               case PdfObject.BOOLEAN:
  289               case 0:
  290                   return in;
  291               case PdfObject.STREAM:
  292                   return copyStream((PRStream)in);
  293                   //                return in;
  294               default:
  295                   if (in.type < 0) {
  296                       String lit = ((PdfLiteral)in).toString();
  297                       if (lit.equals("true") || lit.equals("false")) {
  298                           return new PdfBoolean(lit);
  299                       }
  300                       return new PdfLiteral(lit);
  301                   }
  302                   System.out.println("CANNOT COPY type " + in.type);
  303                   return null;
  304           }
  305       }
  306       
  307       /**
  308        * convenience method. Given an imported page, set our "globals"
  309        */
  310       protected int setFromIPage(PdfImportedPage iPage) {
  311           int pageNum = iPage.getPageNumber();
  312           PdfReaderInstance inst = currentPdfReaderInstance = iPage.getPdfReaderInstance();
  313           reader = inst.getReader();
  314           setFromReader(reader);
  315           return pageNum;
  316       }
  317       
  318       /**
  319        * convenience method. Given a reader, set our "globals"
  320        */
  321       protected void setFromReader(PdfReader reader) {
  322           this.reader = reader;
  323           indirects = (HashMap)indirectMap.get(reader);
  324           if (indirects == null) {
  325               indirects = new HashMap();
  326               indirectMap.put(reader,indirects);
  327               PdfDictionary catalog = reader.getCatalog();
  328               PRIndirectReference ref = null;
  329               PdfObject o = catalog.get(PdfName.ACROFORM);
  330               if (o == null || o.type() != PdfObject.INDIRECT)
  331                   return;
  332               ref = (PRIndirectReference)o;
  333               if (acroForm == null) acroForm = body.getPdfIndirectReference();
  334               indirects.put(new RefKey(ref), new IndirectReferences(acroForm));
  335           }
  336       }
  337       /**
  338        * Add an imported page to our output
  339        * @param iPage an imported page
  340        * @throws IOException, BadPdfFormatException
  341        */
  342       public void addPage(PdfImportedPage iPage) throws IOException, BadPdfFormatException {
  343           int pageNum = setFromIPage(iPage);
  344           
  345           PdfDictionary thePage = reader.getPageN(pageNum);
  346           PRIndirectReference origRef = reader.getPageOrigRef(pageNum);
  347           reader.releasePage(pageNum);
  348           RefKey key = new RefKey(origRef);
  349           PdfIndirectReference pageRef;
  350           IndirectReferences iRef = (IndirectReferences)indirects.get(key);
  351           if (iRef != null && !iRef.getCopied()) {
  352               pageReferences.add(iRef.getRef());
  353               iRef.setCopied();
  354           }
  355           pageRef = getCurrentPage();
  356           if (iRef == null) {
  357               iRef = new IndirectReferences(pageRef);
  358               indirects.put(key, iRef);
  359           }
  360           iRef.setCopied();
  361           PdfDictionary newPage = copyDictionary(thePage);
  362           root.addPage(newPage);
  363           ++currentPageNumber;
  364       }
  365       
  366       /**
  367        * Copy the acroform for an input document. Note that you can only have one,
  368        * we make no effort to merge them.
  369        * @param reader The reader of the input file that is being copied
  370        * @throws IOException, BadPdfFormatException
  371        */
  372       public void copyAcroForm(PdfReader reader) throws IOException, BadPdfFormatException {
  373           setFromReader(reader);
  374           
  375           PdfDictionary catalog = reader.getCatalog();
  376           PRIndirectReference hisRef = null;
  377           PdfObject o = catalog.get(PdfName.ACROFORM);
  378           if (o != null && o.type() == PdfObject.INDIRECT)
  379               hisRef = (PRIndirectReference)o;
  380           if (hisRef == null) return; // bugfix by John Englar
  381           RefKey key = new RefKey(hisRef);
  382           PdfIndirectReference myRef;
  383           IndirectReferences iRef = (IndirectReferences)indirects.get(key);
  384           if (iRef != null) {
  385               acroForm = myRef = iRef.getRef();
  386           }
  387           else {
  388               acroForm = myRef = body.getPdfIndirectReference();
  389               iRef = new IndirectReferences(myRef);
  390               indirects.put(key, iRef);
  391           }
  392           if (! iRef.getCopied()) {
  393               iRef.setCopied();
  394               PdfDictionary theForm = copyDictionary((PdfDictionary)PdfReader.getPdfObject(hisRef));
  395               addToBody(theForm, myRef);
  396           }
  397       }
  398       
  399       /*
  400        * the getCatalog method is part of PdfWriter.
  401        * we wrap this so that we can extend it
  402        */
  403       protected PdfDictionary getCatalog(PdfIndirectReference rootObj) {
  404           try {
  405               PdfDictionary theCat = pdf.getCatalog(rootObj);
  406               if (fieldArray == null) {
  407                   if (acroForm != null) theCat.put(PdfName.ACROFORM, acroForm);
  408               }
  409               else
  410                   addFieldResources(theCat);
  411               writeOutlines(theCat, false);
  412               return theCat;
  413           }
  414           catch (IOException e) {
  415               throw new ExceptionConverter(e);
  416           }
  417       }
  418       
  419       private void addFieldResources(PdfDictionary catalog) throws IOException {
  420           if (fieldArray == null)
  421               return;
  422           PdfDictionary acroForm = new PdfDictionary();
  423           catalog.put(PdfName.ACROFORM, acroForm);
  424           acroForm.put(PdfName.FIELDS, fieldArray);
  425           acroForm.put(PdfName.DA, new PdfString("/Helv 0 Tf 0 g "));
  426           if (fieldTemplates.isEmpty())
  427               return;
  428           PdfDictionary dr = new PdfDictionary();
  429           acroForm.put(PdfName.DR, dr);
  430           for (Iterator it = fieldTemplates.keySet().iterator(); it.hasNext();) {
  431               PdfTemplate template = (PdfTemplate)it.next();
  432               PdfFormField.mergeResources(dr, (PdfDictionary)template.getResources());
  433           }
  434           if (dr.get(PdfName.ENCODING) == null)
  435               dr.put(PdfName.ENCODING, PdfName.WIN_ANSI_ENCODING);
  436           PdfDictionary fonts = (PdfDictionary)PdfReader.getPdfObject(dr.get(PdfName.FONT));
  437           if (fonts == null) {
  438               fonts = new PdfDictionary();
  439               dr.put(PdfName.FONT, fonts);
  440           }
  441           if (!fonts.contains(PdfName.HELV)) {
  442               PdfDictionary dic = new PdfDictionary(PdfName.FONT);
  443               dic.put(PdfName.BASEFONT, PdfName.HELVETICA);
  444               dic.put(PdfName.ENCODING, PdfName.WIN_ANSI_ENCODING);
  445               dic.put(PdfName.NAME, PdfName.HELV);
  446               dic.put(PdfName.SUBTYPE, PdfName.TYPE1);
  447               fonts.put(PdfName.HELV, addToBody(dic).getIndirectReference());
  448           }
  449           if (!fonts.contains(PdfName.ZADB)) {
  450               PdfDictionary dic = new PdfDictionary(PdfName.FONT);
  451               dic.put(PdfName.BASEFONT, PdfName.ZAPFDINGBATS);
  452               dic.put(PdfName.NAME, PdfName.ZADB);
  453               dic.put(PdfName.SUBTYPE, PdfName.TYPE1);
  454               fonts.put(PdfName.ZADB, addToBody(dic).getIndirectReference());
  455           }
  456       }
  457       
  458       /**
  459        * Signals that the <CODE>Document</CODE> was closed and that no other
  460        * <CODE>Elements</CODE> will be added.
  461        * <P>
  462        * The pages-tree is built and written to the outputstream.
  463        * A Catalog is constructed, as well as an Info-object,
  464        * the reference table is composed and everything is written
  465        * to the outputstream embedded in a Trailer.
  466        */
  467       
  468       public void close() {
  469           if (open) {
  470               PdfReaderInstance ri = currentPdfReaderInstance;
  471               pdf.close();
  472               super.close();
  473               if (ri != null) {
  474                   try {
  475                       ri.getReader().close();
  476                       ri.getReaderFile().close();
  477                   }
  478                   catch (IOException ioe) {
  479                       // empty on purpose
  480                   }
  481               }
  482           }
  483       }
  484       public PdfIndirectReference add(PdfOutline outline) { return null; }
  485       public void addAnnotation(PdfAnnotation annot) {  }
  486       PdfIndirectReference add(PdfPage page, PdfContents contents) throws PdfException { return null; }
  487   
  488       public void freeReader(PdfReader reader) throws IOException {
  489           indirectMap.remove(reader);
  490           if (currentPdfReaderInstance != null) {
  491               if (currentPdfReaderInstance.getReader() == reader) {
  492                   try {
  493                       currentPdfReaderInstance.getReader().close();
  494                       currentPdfReaderInstance.getReaderFile().close();
  495                   }
  496                   catch (IOException ioe) {
  497                       // empty on purpose
  498                   }
  499                   currentPdfReaderInstance = null;
  500               }
  501           }
  502       }
  503       
  504       /**
  505        * Create a page stamp. New content and annotations, including new fields, are allowed.
  506        * The fields added cannot have parents in another pages. This method modifies the PdfReader instance.<p>
  507        * The general usage to stamp something in a page is:
  508        * <p>
  509        * <pre>
  510        * PdfImportedPage page = copy.getImportedPage(reader, 1);
  511        * PdfCopy.PageStamp ps = copy.createPageStamp(page);
  512        * ps.addAnnotation(PdfAnnotation.createText(copy, new Rectangle(50, 180, 70, 200), "Hello", "No Thanks", true, "Comment"));
  513        * PdfContentByte under = ps.getUnderContent();
  514        * under.addImage(img);
  515        * PdfContentByte over = ps.getOverContent();
  516        * over.beginText();
  517        * over.setFontAndSize(bf, 18);
  518        * over.setTextMatrix(30, 30);
  519        * over.showText("total page " + totalPage);
  520        * over.endText();
  521        * ps.alterContents();
  522        * copy.addPage(page);
  523        * </pre>
  524        * @param iPage an imported page
  525        * @return the <CODE>PageStamp</CODE>
  526        */
  527       public PageStamp createPageStamp(PdfImportedPage iPage) {
  528           int pageNum = iPage.getPageNumber();
  529           PdfReader reader = iPage.getPdfReaderInstance().getReader();
  530           PdfDictionary pageN = reader.getPageN(pageNum);
  531           return new PageStamp(reader, pageN, this);
  532       }
  533       
  534       public static class PageStamp {
  535           
  536           PdfDictionary pageN;
  537           PdfCopy.StampContent under;
  538           PdfCopy.StampContent over;
  539           PageResources pageResources;
  540           PdfReader reader;
  541           PdfCopy cstp;
  542           
  543           PageStamp(PdfReader reader, PdfDictionary pageN, PdfCopy cstp) {
  544               this.pageN = pageN;
  545               this.reader = reader;
  546               this.cstp = cstp;
  547           }
  548           
  549           public PdfContentByte getUnderContent(){
  550               if (under == null) {
  551                   if (pageResources == null) {
  552                       pageResources = new PageResources();
  553                       PdfDictionary resources = (PdfDictionary)PdfReader.getPdfObject(pageN.get(PdfName.RESOURCES));
  554                       pageResources.setOriginalResources(resources, cstp.namePtr);
  555                   }
  556                   under = new PdfCopy.StampContent(cstp, pageResources);
  557               }
  558               return under;
  559           }
  560           
  561           public PdfContentByte getOverContent(){
  562               if (over == null) {
  563                   if (pageResources == null) {
  564                       pageResources = new PageResources();
  565                       PdfDictionary resources = (PdfDictionary)PdfReader.getPdfObject(pageN.get(PdfName.RESOURCES));
  566                       pageResources.setOriginalResources(resources, cstp.namePtr);
  567                   }
  568                   over = new PdfCopy.StampContent(cstp, pageResources);
  569               }
  570               return over;
  571           }
  572           
  573           public void alterContents() throws IOException {
  574               if (over == null && under == null)
  575                   return;
  576               PdfArray ar = null;
  577               PdfObject content = PdfReader.getPdfObject(pageN.get(PdfName.CONTENTS), pageN);
  578               if (content == null) {
  579                   ar = new PdfArray();
  580                   pageN.put(PdfName.CONTENTS, ar);
  581               } else if (content.isArray()) {
  582                   ar = (PdfArray)content;
  583               } else if (content.isStream()) {
  584                   ar = new PdfArray();
  585                   ar.add(pageN.get(PdfName.CONTENTS));
  586                   pageN.put(PdfName.CONTENTS, ar);
  587               } else {
  588                   ar = new PdfArray();
  589                   pageN.put(PdfName.CONTENTS, ar);
  590               }
  591               ByteBuffer out = new ByteBuffer();
  592               if (under != null) {
  593                   out.append(PdfContents.SAVESTATE);
  594                   applyRotation(pageN, out);
  595                   out.append(under.getInternalBuffer());
  596                   out.append(PdfContents.RESTORESTATE);
  597               }
  598               if (over != null)
  599                   out.append(PdfContents.SAVESTATE);
  600               PdfStream stream = new PdfStream(out.toByteArray());
  601               stream.flateCompress(cstp.getCompressionLevel());
  602               PdfIndirectReference ref1 = cstp.addToBody(stream).getIndirectReference();
  603               ar.addFirst(ref1);
  604               out.reset();
  605               if (over != null) {
  606                   out.append(' ');
  607                   out.append(PdfContents.RESTORESTATE);
  608                   out.append(PdfContents.SAVESTATE);
  609                   applyRotation(pageN, out);
  610                   out.append(over.getInternalBuffer());
  611                   out.append(PdfContents.RESTORESTATE);
  612                   stream = new PdfStream(out.toByteArray());
  613                   stream.flateCompress(cstp.getCompressionLevel());
  614                   ar.add(cstp.addToBody(stream).getIndirectReference());
  615               }
  616               pageN.put(PdfName.RESOURCES, pageResources.getResources());
  617           }
  618           
  619           void applyRotation(PdfDictionary pageN, ByteBuffer out) {
  620               if (!cstp.rotateContents)
  621                   return;
  622               Rectangle page = reader.getPageSizeWithRotation(pageN);
  623               int rotation = page.getRotation();
  624               switch (rotation) {
  625                   case 90:
  626                       out.append(PdfContents.ROTATE90);
  627                       out.append(page.getTop());
  628                       out.append(' ').append('0').append(PdfContents.ROTATEFINAL);
  629                       break;
  630                   case 180:
  631                       out.append(PdfContents.ROTATE180);
  632                       out.append(page.getRight());
  633                       out.append(' ');
  634                       out.append(page.getTop());
  635                       out.append(PdfContents.ROTATEFINAL);
  636                       break;
  637                   case 270:
  638                       out.append(PdfContents.ROTATE270);
  639                       out.append('0').append(' ');
  640                       out.append(page.getRight());
  641                       out.append(PdfContents.ROTATEFINAL);
  642                       break;
  643               }
  644           }
  645           
  646           private void addDocumentField(PdfIndirectReference ref) {
  647               if (cstp.fieldArray == null)
  648                   cstp.fieldArray = new PdfArray();
  649               cstp.fieldArray.add(ref);
  650           }
  651   
  652           private void expandFields(PdfFormField field, ArrayList allAnnots) {
  653               allAnnots.add(field);
  654               ArrayList kids = field.getKids();
  655               if (kids != null) {
  656                   for (int k = 0; k < kids.size(); ++k)
  657                       expandFields((PdfFormField)kids.get(k), allAnnots);
  658               }
  659           }
  660   
  661           public void addAnnotation(PdfAnnotation annot) {
  662               try {
  663                   ArrayList allAnnots = new ArrayList();
  664                   if (annot.isForm()) {
  665                       PdfFormField field = (PdfFormField)annot;
  666                       if (field.getParent() != null)
  667                           return;
  668                       expandFields(field, allAnnots);
  669                       if (cstp.fieldTemplates == null)
  670                           cstp.fieldTemplates = new HashMap();
  671                   }
  672                   else
  673                       allAnnots.add(annot);
  674                   for (int k = 0; k < allAnnots.size(); ++k) {
  675                       annot = (PdfAnnotation)allAnnots.get(k);
  676                       if (annot.isForm()) {
  677                           if (!annot.isUsed()) {
  678                               HashMap templates = annot.getTemplates();
  679                               if (templates != null)
  680                                   cstp.fieldTemplates.putAll(templates);
  681                           }
  682                           PdfFormField field = (PdfFormField)annot;
  683                           if (field.getParent() == null)
  684                               addDocumentField(field.getIndirectReference());
  685                       }
  686                       if (annot.isAnnotation()) {
  687                           PdfObject pdfobj = PdfReader.getPdfObject(pageN.get(PdfName.ANNOTS), pageN);
  688                           PdfArray annots = null;
  689                           if (pdfobj == null || !pdfobj.isArray()) {
  690                               annots = new PdfArray();
  691                               pageN.put(PdfName.ANNOTS, annots);
  692                           }
  693                           else 
  694                               annots = (PdfArray)pdfobj;
  695                           annots.add(annot.getIndirectReference());
  696                           if (!annot.isUsed()) {
  697                               PdfRectangle rect = (PdfRectangle)annot.get(PdfName.RECT);
  698                               if (rect != null && (rect.left() != 0 || rect.right() != 0 || rect.top() != 0 || rect.bottom() != 0)) {
  699                                   int rotation = reader.getPageRotation(pageN);
  700                                   Rectangle pageSize = reader.getPageSizeWithRotation(pageN);
  701                                   switch (rotation) {
  702                                       case 90:
  703                                           annot.put(PdfName.RECT, new PdfRectangle(
  704                                           pageSize.getTop() - rect.bottom(),
  705                                           rect.left(),
  706                                           pageSize.getTop() - rect.top(),
  707                                           rect.right()));
  708                                           break;
  709                                       case 180:
  710                                           annot.put(PdfName.RECT, new PdfRectangle(
  711                                           pageSize.getRight() - rect.left(),
  712                                           pageSize.getTop() - rect.bottom(),
  713                                           pageSize.getRight() - rect.right(),
  714                                           pageSize.getTop() - rect.top()));
  715                                           break;
  716                                       case 270:
  717                                           annot.put(PdfName.RECT, new PdfRectangle(
  718                                           rect.bottom(),
  719                                           pageSize.getRight() - rect.left(),
  720                                           rect.top(),
  721                                           pageSize.getRight() - rect.right()));
  722                                           break;
  723                                   }
  724                               }
  725                           }
  726                       }
  727                       if (!annot.isUsed()) {
  728                           annot.setUsed();
  729                           cstp.addToBody(annot, annot.getIndirectReference());
  730                       }
  731                   }
  732               }
  733               catch (IOException e) {
  734                   throw new ExceptionConverter(e);
  735               }
  736           }
  737       }
  738       
  739       public static class StampContent extends PdfContentByte {
  740           PageResources pageResources;
  741           
  742           /** Creates a new instance of StampContent */
  743           StampContent(PdfWriter writer, PageResources pageResources) {
  744               super(writer);
  745               this.pageResources = pageResources;
  746           }
  747           
  748           /**
  749            * Gets a duplicate of this <CODE>PdfContentByte</CODE>. All
  750            * the members are copied by reference but the buffer stays different.
  751            *
  752            * @return a copy of this <CODE>PdfContentByte</CODE>
  753            */
  754           public PdfContentByte getDuplicate() {
  755               return new PdfCopy.StampContent(writer, pageResources);
  756           }
  757           
  758           PageResources getPageResources() {
  759               return pageResources;
  760           }
  761       }
  762   }

Save This Page
Home » iText-src-2.1.3 » com.lowagie » text » pdf » [javadoc | source]