Save This Page
Home » iText-2.1.7 » com.lowagie » text » pdf » [javadoc | source]
    1   /*
    2    * $Id: PdfCopy.java 3912 2009-04-26 08:38:15Z 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.listIterator(); 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        * Adds a blank page.
  368        * @param	rect The page dimension
  369        * @param	rotation The rotation angle in degrees
  370        * @since	2.1.5
  371        */
  372       public void addPage(Rectangle rect, int rotation) {
  373       	PdfRectangle mediabox = new PdfRectangle(rect, rotation);
  374       	PageResources resources = new PageResources();
  375       	PdfPage page = new PdfPage(mediabox, new HashMap(), resources.getResources(), 0);
  376       	page.put(PdfName.TABS, getTabs());
  377       	root.addPage(page);
  378       	++currentPageNumber;
  379       }
  380       
  381       /**
  382        * Copy the acroform for an input document. Note that you can only have one,
  383        * we make no effort to merge them.
  384        * @param reader The reader of the input file that is being copied
  385        * @throws IOException, BadPdfFormatException
  386        */
  387       public void copyAcroForm(PdfReader reader) throws IOException, BadPdfFormatException {
  388           setFromReader(reader);
  389           
  390           PdfDictionary catalog = reader.getCatalog();
  391           PRIndirectReference hisRef = null;
  392           PdfObject o = catalog.get(PdfName.ACROFORM);
  393           if (o != null && o.type() == PdfObject.INDIRECT)
  394               hisRef = (PRIndirectReference)o;
  395           if (hisRef == null) return; // bugfix by John Englar
  396           RefKey key = new RefKey(hisRef);
  397           PdfIndirectReference myRef;
  398           IndirectReferences iRef = (IndirectReferences)indirects.get(key);
  399           if (iRef != null) {
  400               acroForm = myRef = iRef.getRef();
  401           }
  402           else {
  403               acroForm = myRef = body.getPdfIndirectReference();
  404               iRef = new IndirectReferences(myRef);
  405               indirects.put(key, iRef);
  406           }
  407           if (! iRef.getCopied()) {
  408               iRef.setCopied();
  409               PdfDictionary theForm = copyDictionary((PdfDictionary)PdfReader.getPdfObject(hisRef));
  410               addToBody(theForm, myRef);
  411           }
  412       }
  413       
  414       /*
  415        * the getCatalog method is part of PdfWriter.
  416        * we wrap this so that we can extend it
  417        */
  418       protected PdfDictionary getCatalog(PdfIndirectReference rootObj) {
  419           try {
  420               PdfDictionary theCat = pdf.getCatalog(rootObj);
  421               if (fieldArray == null) {
  422                   if (acroForm != null) theCat.put(PdfName.ACROFORM, acroForm);
  423               }
  424               else
  425                   addFieldResources(theCat);
  426               return theCat;
  427           }
  428           catch (IOException e) {
  429               throw new ExceptionConverter(e);
  430           }
  431       }
  432       
  433       private void addFieldResources(PdfDictionary catalog) throws IOException {
  434           if (fieldArray == null)
  435               return;
  436           PdfDictionary acroForm = new PdfDictionary();
  437           catalog.put(PdfName.ACROFORM, acroForm);
  438           acroForm.put(PdfName.FIELDS, fieldArray);
  439           acroForm.put(PdfName.DA, new PdfString("/Helv 0 Tf 0 g "));
  440           if (fieldTemplates.isEmpty())
  441               return;
  442           PdfDictionary dr = new PdfDictionary();
  443           acroForm.put(PdfName.DR, dr);
  444           for (Iterator it = fieldTemplates.keySet().iterator(); it.hasNext();) {
  445               PdfTemplate template = (PdfTemplate)it.next();
  446               PdfFormField.mergeResources(dr, (PdfDictionary)template.getResources());
  447           }
  448           // if (dr.get(PdfName.ENCODING) == null) dr.put(PdfName.ENCODING, PdfName.WIN_ANSI_ENCODING);
  449           PdfDictionary fonts = dr.getAsDict(PdfName.FONT);
  450           if (fonts == null) {
  451               fonts = new PdfDictionary();
  452               dr.put(PdfName.FONT, fonts);
  453           }
  454           if (!fonts.contains(PdfName.HELV)) {
  455               PdfDictionary dic = new PdfDictionary(PdfName.FONT);
  456               dic.put(PdfName.BASEFONT, PdfName.HELVETICA);
  457               dic.put(PdfName.ENCODING, PdfName.WIN_ANSI_ENCODING);
  458               dic.put(PdfName.NAME, PdfName.HELV);
  459               dic.put(PdfName.SUBTYPE, PdfName.TYPE1);
  460               fonts.put(PdfName.HELV, addToBody(dic).getIndirectReference());
  461           }
  462           if (!fonts.contains(PdfName.ZADB)) {
  463               PdfDictionary dic = new PdfDictionary(PdfName.FONT);
  464               dic.put(PdfName.BASEFONT, PdfName.ZAPFDINGBATS);
  465               dic.put(PdfName.NAME, PdfName.ZADB);
  466               dic.put(PdfName.SUBTYPE, PdfName.TYPE1);
  467               fonts.put(PdfName.ZADB, addToBody(dic).getIndirectReference());
  468           }
  469       }
  470       
  471       /**
  472        * Signals that the <CODE>Document</CODE> was closed and that no other
  473        * <CODE>Elements</CODE> will be added.
  474        * <P>
  475        * The pages-tree is built and written to the outputstream.
  476        * A Catalog is constructed, as well as an Info-object,
  477        * the reference table is composed and everything is written
  478        * to the outputstream embedded in a Trailer.
  479        */
  480       
  481       public void close() {
  482           if (open) {
  483               PdfReaderInstance ri = currentPdfReaderInstance;
  484               pdf.close();
  485               super.close();
  486               if (ri != null) {
  487                   try {
  488                       ri.getReader().close();
  489                       ri.getReaderFile().close();
  490                   }
  491                   catch (IOException ioe) {
  492                       // empty on purpose
  493                   }
  494               }
  495           }
  496       }
  497       public PdfIndirectReference add(PdfOutline outline) { return null; }
  498       public void addAnnotation(PdfAnnotation annot) {  }
  499       PdfIndirectReference add(PdfPage page, PdfContents contents) throws PdfException { return null; }
  500   
  501       public void freeReader(PdfReader reader) throws IOException {
  502           indirectMap.remove(reader);
  503           if (currentPdfReaderInstance != null) {
  504               if (currentPdfReaderInstance.getReader() == reader) {
  505                   try {
  506                       currentPdfReaderInstance.getReader().close();
  507                       currentPdfReaderInstance.getReaderFile().close();
  508                   }
  509                   catch (IOException ioe) {
  510                       // empty on purpose
  511                   }
  512                   currentPdfReaderInstance = null;
  513               }
  514           }
  515       }
  516       
  517       /**
  518        * Create a page stamp. New content and annotations, including new fields, are allowed.
  519        * The fields added cannot have parents in another pages. This method modifies the PdfReader instance.<p>
  520        * The general usage to stamp something in a page is:
  521        * <p>
  522        * <pre>
  523        * PdfImportedPage page = copy.getImportedPage(reader, 1);
  524        * PdfCopy.PageStamp ps = copy.createPageStamp(page);
  525        * ps.addAnnotation(PdfAnnotation.createText(copy, new Rectangle(50, 180, 70, 200), "Hello", "No Thanks", true, "Comment"));
  526        * PdfContentByte under = ps.getUnderContent();
  527        * under.addImage(img);
  528        * PdfContentByte over = ps.getOverContent();
  529        * over.beginText();
  530        * over.setFontAndSize(bf, 18);
  531        * over.setTextMatrix(30, 30);
  532        * over.showText("total page " + totalPage);
  533        * over.endText();
  534        * ps.alterContents();
  535        * copy.addPage(page);
  536        * </pre>
  537        * @param iPage an imported page
  538        * @return the <CODE>PageStamp</CODE>
  539        */
  540       public PageStamp createPageStamp(PdfImportedPage iPage) {
  541           int pageNum = iPage.getPageNumber();
  542           PdfReader reader = iPage.getPdfReaderInstance().getReader();
  543           PdfDictionary pageN = reader.getPageN(pageNum);
  544           return new PageStamp(reader, pageN, this);
  545       }
  546       
  547       public static class PageStamp {
  548           
  549           PdfDictionary pageN;
  550           PdfCopy.StampContent under;
  551           PdfCopy.StampContent over;
  552           PageResources pageResources;
  553           PdfReader reader;
  554           PdfCopy cstp;
  555           
  556           PageStamp(PdfReader reader, PdfDictionary pageN, PdfCopy cstp) {
  557               this.pageN = pageN;
  558               this.reader = reader;
  559               this.cstp = cstp;
  560           }
  561           
  562           public PdfContentByte getUnderContent(){
  563               if (under == null) {
  564                   if (pageResources == null) {
  565                       pageResources = new PageResources();
  566                       PdfDictionary resources = pageN.getAsDict(PdfName.RESOURCES);
  567                       pageResources.setOriginalResources(resources, cstp.namePtr);
  568                   }
  569                   under = new PdfCopy.StampContent(cstp, pageResources);
  570               }
  571               return under;
  572           }
  573           
  574           public PdfContentByte getOverContent(){
  575               if (over == null) {
  576                   if (pageResources == null) {
  577                       pageResources = new PageResources();
  578                       PdfDictionary resources = pageN.getAsDict(PdfName.RESOURCES);
  579                       pageResources.setOriginalResources(resources, cstp.namePtr);
  580                   }
  581                   over = new PdfCopy.StampContent(cstp, pageResources);
  582               }
  583               return over;
  584           }
  585           
  586           public void alterContents() throws IOException {
  587               if (over == null && under == null)
  588                   return;
  589               PdfArray ar = null;
  590               PdfObject content = PdfReader.getPdfObject(pageN.get(PdfName.CONTENTS), pageN);
  591               if (content == null) {
  592                   ar = new PdfArray();
  593                   pageN.put(PdfName.CONTENTS, ar);
  594               } else if (content.isArray()) {
  595                   ar = (PdfArray)content;
  596               } else if (content.isStream()) {
  597                   ar = new PdfArray();
  598                   ar.add(pageN.get(PdfName.CONTENTS));
  599                   pageN.put(PdfName.CONTENTS, ar);
  600               } else {
  601                   ar = new PdfArray();
  602                   pageN.put(PdfName.CONTENTS, ar);
  603               }
  604               ByteBuffer out = new ByteBuffer();
  605               if (under != null) {
  606                   out.append(PdfContents.SAVESTATE);
  607                   applyRotation(pageN, out);
  608                   out.append(under.getInternalBuffer());
  609                   out.append(PdfContents.RESTORESTATE);
  610               }
  611               if (over != null)
  612                   out.append(PdfContents.SAVESTATE);
  613               PdfStream stream = new PdfStream(out.toByteArray());
  614               stream.flateCompress(cstp.getCompressionLevel());
  615               PdfIndirectReference ref1 = cstp.addToBody(stream).getIndirectReference();
  616               ar.addFirst(ref1);
  617               out.reset();
  618               if (over != null) {
  619                   out.append(' ');
  620                   out.append(PdfContents.RESTORESTATE);
  621                   out.append(PdfContents.SAVESTATE);
  622                   applyRotation(pageN, out);
  623                   out.append(over.getInternalBuffer());
  624                   out.append(PdfContents.RESTORESTATE);
  625                   stream = new PdfStream(out.toByteArray());
  626                   stream.flateCompress(cstp.getCompressionLevel());
  627                   ar.add(cstp.addToBody(stream).getIndirectReference());
  628               }
  629               pageN.put(PdfName.RESOURCES, pageResources.getResources());
  630           }
  631           
  632           void applyRotation(PdfDictionary pageN, ByteBuffer out) {
  633               if (!cstp.rotateContents)
  634                   return;
  635               Rectangle page = reader.getPageSizeWithRotation(pageN);
  636               int rotation = page.getRotation();
  637               switch (rotation) {
  638                   case 90:
  639                       out.append(PdfContents.ROTATE90);
  640                       out.append(page.getTop());
  641                       out.append(' ').append('0').append(PdfContents.ROTATEFINAL);
  642                       break;
  643                   case 180:
  644                       out.append(PdfContents.ROTATE180);
  645                       out.append(page.getRight());
  646                       out.append(' ');
  647                       out.append(page.getTop());
  648                       out.append(PdfContents.ROTATEFINAL);
  649                       break;
  650                   case 270:
  651                       out.append(PdfContents.ROTATE270);
  652                       out.append('0').append(' ');
  653                       out.append(page.getRight());
  654                       out.append(PdfContents.ROTATEFINAL);
  655                       break;
  656               }
  657           }
  658           
  659           private void addDocumentField(PdfIndirectReference ref) {
  660               if (cstp.fieldArray == null)
  661                   cstp.fieldArray = new PdfArray();
  662               cstp.fieldArray.add(ref);
  663           }
  664   
  665           private void expandFields(PdfFormField field, ArrayList allAnnots) {
  666               allAnnots.add(field);
  667               ArrayList kids = field.getKids();
  668               if (kids != null) {
  669                   for (int k = 0; k < kids.size(); ++k)
  670                       expandFields((PdfFormField)kids.get(k), allAnnots);
  671               }
  672           }
  673   
  674           public void addAnnotation(PdfAnnotation annot) {
  675               try {
  676                   ArrayList allAnnots = new ArrayList();
  677                   if (annot.isForm()) {
  678                       PdfFormField field = (PdfFormField)annot;
  679                       if (field.getParent() != null)
  680                           return;
  681                       expandFields(field, allAnnots);
  682                       if (cstp.fieldTemplates == null)
  683                           cstp.fieldTemplates = new HashMap();
  684                   }
  685                   else
  686                       allAnnots.add(annot);
  687                   for (int k = 0; k < allAnnots.size(); ++k) {
  688                       annot = (PdfAnnotation)allAnnots.get(k);
  689                       if (annot.isForm()) {
  690                           if (!annot.isUsed()) {
  691                               HashMap templates = annot.getTemplates();
  692                               if (templates != null)
  693                                   cstp.fieldTemplates.putAll(templates);
  694                           }
  695                           PdfFormField field = (PdfFormField)annot;
  696                           if (field.getParent() == null)
  697                               addDocumentField(field.getIndirectReference());
  698                       }
  699                       if (annot.isAnnotation()) {
  700                           PdfObject pdfobj = PdfReader.getPdfObject(pageN.get(PdfName.ANNOTS), pageN);
  701                           PdfArray annots = null;
  702                           if (pdfobj == null || !pdfobj.isArray()) {
  703                               annots = new PdfArray();
  704                               pageN.put(PdfName.ANNOTS, annots);
  705                           }
  706                           else 
  707                               annots = (PdfArray)pdfobj;
  708                           annots.add(annot.getIndirectReference());
  709                           if (!annot.isUsed()) {
  710                               PdfRectangle rect = (PdfRectangle)annot.get(PdfName.RECT);
  711                               if (rect != null && (rect.left() != 0 || rect.right() != 0 || rect.top() != 0 || rect.bottom() != 0)) {
  712                                   int rotation = reader.getPageRotation(pageN);
  713                                   Rectangle pageSize = reader.getPageSizeWithRotation(pageN);
  714                                   switch (rotation) {
  715                                       case 90:
  716                                           annot.put(PdfName.RECT, new PdfRectangle(
  717                                           pageSize.getTop() - rect.bottom(),
  718                                           rect.left(),
  719                                           pageSize.getTop() - rect.top(),
  720                                           rect.right()));
  721                                           break;
  722                                       case 180:
  723                                           annot.put(PdfName.RECT, new PdfRectangle(
  724                                           pageSize.getRight() - rect.left(),
  725                                           pageSize.getTop() - rect.bottom(),
  726                                           pageSize.getRight() - rect.right(),
  727                                           pageSize.getTop() - rect.top()));
  728                                           break;
  729                                       case 270:
  730                                           annot.put(PdfName.RECT, new PdfRectangle(
  731                                           rect.bottom(),
  732                                           pageSize.getRight() - rect.left(),
  733                                           rect.top(),
  734                                           pageSize.getRight() - rect.right()));
  735                                           break;
  736                                   }
  737                               }
  738                           }
  739                       }
  740                       if (!annot.isUsed()) {
  741                           annot.setUsed();
  742                           cstp.addToBody(annot, annot.getIndirectReference());
  743                       }
  744                   }
  745               }
  746               catch (IOException e) {
  747                   throw new ExceptionConverter(e);
  748               }
  749           }
  750       }
  751       
  752       public static class StampContent extends PdfContentByte {
  753           PageResources pageResources;
  754           
  755           /** Creates a new instance of StampContent */
  756           StampContent(PdfWriter writer, PageResources pageResources) {
  757               super(writer);
  758               this.pageResources = pageResources;
  759           }
  760           
  761           /**
  762            * Gets a duplicate of this <CODE>PdfContentByte</CODE>. All
  763            * the members are copied by reference but the buffer stays different.
  764            *
  765            * @return a copy of this <CODE>PdfContentByte</CODE>
  766            */
  767           public PdfContentByte getDuplicate() {
  768               return new PdfCopy.StampContent(writer, pageResources);
  769           }
  770           
  771           PageResources getPageResources() {
  772               return pageResources;
  773           }
  774       }
  775   }

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