Save This Page
Home » iText-src-2.1.3 » com.lowagie » text » pdf » [javadoc | source]
    1   /*
    2    * Copyright 2003 by Paulo Soares.
    3    *
    4    * The contents of this file are subject to the Mozilla Public License Version 1.1
    5    * (the "License"); you may not use this file except in compliance with the License.
    6    * You may obtain a copy of the License at http://www.mozilla.org/MPL/
    7    *
    8    * Software distributed under the License is distributed on an "AS IS" basis,
    9    * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
   10    * for the specific language governing rights and limitations under the License.
   11    *
   12    * The Original Code is 'iText, a free JAVA-PDF library'.
   13    *
   14    * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
   15    * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
   16    * All Rights Reserved.
   17    * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
   18    * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
   19    *
   20    * Contributor(s): all the names of the contributors are added in the source code
   21    * where applicable.
   22    *
   23    * Alternatively, the contents of this file may be used under the terms of the
   24    * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
   25    * provisions of LGPL are applicable instead of those above.  If you wish to
   26    * allow use of your version of this file only under the terms of the LGPL
   27    * License and not to allow others to use your version of this file under
   28    * the MPL, indicate your decision by deleting the provisions above and
   29    * replace them with the notice and other provisions required by the LGPL.
   30    * If you do not delete the provisions above, a recipient may use your version
   31    * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
   32    *
   33    * This library is free software; you can redistribute it and/or modify it
   34    * under the terms of the MPL as stated above or under the terms of the GNU
   35    * Library General Public License as published by the Free Software Foundation;
   36    * either version 2 of the License, or any later version.
   37    *
   38    * This library is distributed in the hope that it will be useful, but WITHOUT
   39    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   40    * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
   41    * details.
   42    *
   43    * If you didn't download this code from the following link, you should check if
   44    * you aren't using an obsolete version:
   45    * http://www.lowagie.com/iText/
   46    */
   47   package com.lowagie.text.pdf;
   48   
   49   import java.io.IOException;
   50   import java.io.OutputStream;
   51   import java.util.ArrayList;
   52   import java.util.HashMap;
   53   import java.util.HashSet;
   54   import java.util.Iterator;
   55   import java.util.Map;
   56   
   57   import com.lowagie.text.DocumentException;
   58   import com.lowagie.text.ExceptionConverter;
   59   import com.lowagie.text.Image;
   60   import com.lowagie.text.Rectangle;
   61   import com.lowagie.text.pdf.collection.PdfCollection;
   62   import com.lowagie.text.pdf.interfaces.PdfViewerPreferences;
   63   import com.lowagie.text.pdf.internal.PdfViewerPreferencesImp;
   64   import com.lowagie.text.xml.xmp.XmpReader;
   65   
   66   class PdfStamperImp extends PdfWriter {
   67       HashMap readers2intrefs = new HashMap();
   68       HashMap readers2file = new HashMap();
   69       RandomAccessFileOrArray file;
   70       PdfReader reader;
   71       IntHashtable myXref = new IntHashtable();
   72       /** Integer(page number) -> PageStamp */
   73       HashMap pagesToContent = new HashMap();
   74       boolean closed = false;
   75       /** Holds value of property rotateContents. */
   76       private boolean rotateContents = true;
   77       protected AcroFields acroFields;
   78       protected boolean flat = false;
   79       protected boolean flatFreeText = false;
   80       protected int namePtr[] = {0};
   81       protected HashSet partialFlattening = new HashSet();
   82       protected boolean useVp = false;
   83       protected PdfViewerPreferencesImp viewerPreferences = new PdfViewerPreferencesImp();
   84       protected HashMap fieldTemplates = new HashMap();
   85       protected boolean fieldsAdded = false;
   86       protected int sigFlags = 0;
   87       protected boolean append;
   88       protected IntHashtable marked;
   89       protected int initialXrefSize;
   90       protected PdfAction openAction;
   91       
   92       /** Creates new PdfStamperImp.
   93        * @param reader the read PDF
   94        * @param os the output destination
   95        * @param pdfVersion the new pdf version or '\0' to keep the same version as the original
   96        * document
   97        * @param append
   98        * @throws DocumentException on error
   99        * @throws IOException
  100        */
  101       PdfStamperImp(PdfReader reader, OutputStream os, char pdfVersion, boolean append) throws DocumentException, IOException {
  102           super(new PdfDocument(), os);
  103           if (!reader.isOpenedWithFullPermissions())
  104               throw new IllegalArgumentException("PdfReader not opened with owner password");
  105           if (reader.isTampered())
  106               throw new DocumentException("The original document was reused. Read it again from file.");
  107           reader.setTampered(true);
  108           this.reader = reader;
  109           file = reader.getSafeFile();
  110           this.append = append;
  111           if (append) {
  112               if (reader.isRebuilt())
  113                   throw new DocumentException("Append mode requires a document without errors even if recovery was possible.");
  114               if (reader.isEncrypted())
  115                   crypto = new PdfEncryption(reader.getDecrypt());
  116               pdf_version.setAppendmode(true);
  117               file.reOpen();
  118               byte buf[] = new byte[8192];
  119               int n;
  120               while ((n = file.read(buf)) > 0)
  121                   this.os.write(buf, 0, n);
  122               file.close();
  123               prevxref = reader.getLastXref();
  124               reader.setAppendable(true);
  125           }
  126           else {
  127               if (pdfVersion == 0)
  128                   super.setPdfVersion(reader.getPdfVersion());
  129               else
  130                   super.setPdfVersion(pdfVersion);
  131           }
  132           super.open();
  133           pdf.addWriter(this);
  134           if (append) {
  135               body.setRefnum(reader.getXrefSize());
  136               marked = new IntHashtable();
  137               if (reader.isNewXrefType())
  138                   fullCompression = true;
  139               if (reader.isHybridXref())
  140                   fullCompression = false;
  141           }
  142           initialXrefSize = reader.getXrefSize();
  143       }
  144       
  145       void close(HashMap moreInfo) throws IOException {
  146           if (closed)
  147               return;
  148           if (useVp) {
  149               reader.setViewerPreferences(viewerPreferences);
  150               markUsed(reader.getTrailer().get(PdfName.ROOT));
  151           }
  152           if (flat)
  153               flatFields();
  154           if (flatFreeText)
  155           	flatFreeTextFields();
  156           addFieldResources();
  157           PdfDictionary acroForm = (PdfDictionary)PdfReader.getPdfObject(reader.getCatalog().get(PdfName.ACROFORM), reader.getCatalog());
  158           if (acroFields != null && acroFields.getXfa().isChanged()) {
  159               markUsed(acroForm);
  160               if (!flat)
  161                   acroFields.getXfa().setXfa(this);
  162           }
  163           if (sigFlags != 0) {
  164               if (acroForm != null) {
  165                   acroForm.put(PdfName.SIGFLAGS, new PdfNumber(sigFlags));
  166                   markUsed(acroForm);
  167               }
  168           }
  169           closed = true;
  170           addSharedObjectsToBody();
  171           setOutlines();
  172           setJavaScript();
  173           addFileAttachments();
  174           PdfDictionary catalog = reader.getCatalog();        	
  175           if (openAction != null) {
  176               catalog.put(PdfName.OPENACTION, openAction);
  177           }
  178           if (pdf.pageLabels != null)
  179               catalog.put(PdfName.PAGELABELS, pdf.pageLabels.getDictionary(this));
  180           byte[] altMetadata = null;
  181           PdfObject xmpo = PdfReader.getPdfObject(catalog.get(PdfName.METADATA));
  182           if (xmpo != null && xmpo.isStream()) {
  183               altMetadata = PdfReader.getStreamBytesRaw((PRStream)xmpo);
  184               PdfReader.killIndirect(catalog.get(PdfName.METADATA));
  185           }
  186           if (xmpMetadata != null) {
  187           	altMetadata = xmpMetadata;
  188           }
  189           // if there is XMP data to add: add it
  190           PdfString date = new PdfDate();
  191           if (altMetadata != null) {
  192           	XmpReader xmpr = new XmpReader(altMetadata);
  193           	xmpr.replace("http://ns.adobe.com/xap/1.0/", "ModifyDate", date.toString());
  194           	xmpr.replace("http://ns.adobe.com/xap/1.0/", "MetadataDate", date.toString());
  195           	PdfStream xmp = new PdfStream(xmpr.serializeDoc());
  196           	xmp.put(PdfName.TYPE, PdfName.METADATA);
  197           	xmp.put(PdfName.SUBTYPE, PdfName.XML);
  198               if (crypto != null && !crypto.isMetadataEncrypted()) {
  199                   PdfArray ar = new PdfArray();
  200                   ar.add(PdfName.CRYPT);
  201                   xmp.put(PdfName.FILTER, ar);
  202               }
  203               if (append && xmpo != null) {
  204               	body.add(xmp, xmpo.getIndRef());
  205               }
  206               else {
  207               	catalog.put(PdfName.METADATA, body.add(xmp).getIndirectReference());
  208               	markUsed(catalog);
  209               }
  210           }
  211           if (!documentOCG.isEmpty()) {
  212           	fillOCProperties(false);
  213           	PdfDictionary ocdict = catalog.getAsDict(PdfName.OCPROPERTIES);
  214           	if (ocdict == null) {
  215           		reader.getCatalog().put(PdfName.OCPROPERTIES, OCProperties);
  216           	}
  217           	else {
  218           		ocdict.put(PdfName.OCGS, OCProperties.get(PdfName.OCGS));
  219           		PdfDictionary ddict = ocdict.getAsDict(PdfName.D);
  220           		ddict.put(PdfName.ORDER, OCProperties.getAsDict(PdfName.D).get(PdfName.ORDER));
  221           		ddict.put(PdfName.RBGROUPS, OCProperties.getAsDict(PdfName.D).get(PdfName.RBGROUPS));
  222           		ddict.put(PdfName.OFF, OCProperties.getAsDict(PdfName.D).get(PdfName.OFF));
  223           		ddict.put(PdfName.AS, OCProperties.getAsDict(PdfName.D).get(PdfName.AS));
  224               }
  225           }
  226           PRIndirectReference iInfo = null;
  227           try {
  228               file.reOpen();
  229               alterContents();
  230               iInfo = (PRIndirectReference)reader.trailer.get(PdfName.INFO);
  231               int skip = -1;
  232               if (iInfo != null)
  233                   skip = iInfo.getNumber();
  234               int rootN = ((PRIndirectReference)reader.trailer.get(PdfName.ROOT)).getNumber();
  235               if (append) {
  236                   int keys[] = marked.getKeys();
  237                   for (int k = 0; k < keys.length; ++k) {
  238                       int j = keys[k];
  239                       PdfObject obj = reader.getPdfObjectRelease(j);
  240                       if (obj != null && skip != j && j < initialXrefSize) {
  241                           addToBody(obj, j, j != rootN);
  242                       }
  243                   }
  244                   for (int k = initialXrefSize; k < reader.getXrefSize(); ++k) {
  245                       PdfObject obj = reader.getPdfObject(k);
  246                       if (obj != null) {
  247                           addToBody(obj, getNewObjectNumber(reader, k, 0));
  248                       }
  249                   }
  250               }
  251               else {
  252                   for (int k = 1; k < reader.getXrefSize(); ++k) {
  253                       PdfObject obj = reader.getPdfObjectRelease(k);
  254                       if (obj != null && skip != k) {
  255                           addToBody(obj, getNewObjectNumber(reader, k, 0), k != rootN);
  256                       }
  257                   }
  258               }
  259           }
  260           finally {
  261               try {
  262                   file.close();
  263               }
  264               catch (Exception e) {
  265                   // empty on purpose
  266               }
  267           }
  268           PdfIndirectReference encryption = null;
  269           PdfObject fileID = null;
  270           if (crypto != null) {
  271               if (append) {
  272                   encryption = reader.getCryptoRef();
  273               }
  274               else {
  275                   PdfIndirectObject encryptionObject = addToBody(crypto.getEncryptionDictionary(), false);
  276                   encryption = encryptionObject.getIndirectReference();
  277               }
  278               fileID = crypto.getFileID();
  279           }
  280           else
  281               fileID = PdfEncryption.createInfoId(PdfEncryption.createDocumentId());
  282           PRIndirectReference iRoot = (PRIndirectReference)reader.trailer.get(PdfName.ROOT);
  283           PdfIndirectReference root = new PdfIndirectReference(0, getNewObjectNumber(reader, iRoot.getNumber(), 0));
  284           PdfIndirectReference info = null;
  285           PdfDictionary oldInfo = (PdfDictionary)PdfReader.getPdfObject(iInfo);
  286           PdfDictionary newInfo = new PdfDictionary();
  287           if (oldInfo != null) {
  288               for (Iterator i = oldInfo.getKeys().iterator(); i.hasNext();) {
  289                   PdfName key = (PdfName)i.next();
  290                   PdfObject value = PdfReader.getPdfObject(oldInfo.get(key));
  291                   newInfo.put(key, value);
  292               }
  293           }
  294           if (moreInfo != null) {
  295               for (Iterator i = moreInfo.entrySet().iterator(); i.hasNext();) {
  296                   Map.Entry entry = (Map.Entry) i.next();
  297                   String key = (String) entry.getKey();
  298                   PdfName keyName = new PdfName(key);
  299                   String value = (String) entry.getValue();
  300                   if (value == null)
  301                       newInfo.remove(keyName);
  302                   else
  303                       newInfo.put(keyName, new PdfString(value, PdfObject.TEXT_UNICODE));
  304               }
  305           }
  306           newInfo.put(PdfName.MODDATE, date);
  307           if (append) {
  308               if (iInfo == null)
  309                   info = addToBody(newInfo, false).getIndirectReference();
  310               else
  311                   info = addToBody(newInfo, iInfo.getNumber(), false).getIndirectReference();
  312           }
  313           else {
  314               info = addToBody(newInfo, false).getIndirectReference();
  315           }
  316           // write the cross-reference table of the body
  317           body.writeCrossReferenceTable(os, root, info, encryption, fileID, prevxref);
  318           if (fullCompression) {
  319               os.write(getISOBytes("startxref\n"));
  320               os.write(getISOBytes(String.valueOf(body.offset())));
  321               os.write(getISOBytes("\n%%EOF\n"));
  322           }
  323           else {
  324               PdfTrailer trailer = new PdfTrailer(body.size(),
  325               body.offset(),
  326               root,
  327               info,
  328               encryption,
  329               fileID, prevxref);
  330               trailer.toPdf(this, os);
  331           }
  332           os.flush();
  333           if (isCloseStream())
  334               os.close();
  335           reader.close();
  336       }
  337       
  338       void applyRotation(PdfDictionary pageN, ByteBuffer out) {
  339           if (!rotateContents)
  340               return;
  341           Rectangle page = reader.getPageSizeWithRotation(pageN);
  342           int rotation = page.getRotation();
  343           switch (rotation) {
  344               case 90:
  345                   out.append(PdfContents.ROTATE90);
  346                   out.append(page.getTop());
  347                   out.append(' ').append('0').append(PdfContents.ROTATEFINAL);
  348                   break;
  349               case 180:
  350                   out.append(PdfContents.ROTATE180);
  351                   out.append(page.getRight());
  352                   out.append(' ');
  353                   out.append(page.getTop());
  354                   out.append(PdfContents.ROTATEFINAL);
  355                   break;
  356               case 270:
  357                   out.append(PdfContents.ROTATE270);
  358                   out.append('0').append(' ');
  359                   out.append(page.getRight());
  360                   out.append(PdfContents.ROTATEFINAL);
  361                   break;
  362           }
  363       }
  364       
  365       void alterContents() throws IOException {
  366           for (Iterator i = pagesToContent.values().iterator(); i.hasNext();) {
  367               PageStamp ps = (PageStamp)i.next();
  368               PdfDictionary pageN = ps.pageN;
  369               markUsed(pageN);
  370               PdfArray ar = null;
  371               PdfObject content = PdfReader.getPdfObject(pageN.get(PdfName.CONTENTS), pageN);
  372               if (content == null) {
  373                   ar = new PdfArray();
  374                   pageN.put(PdfName.CONTENTS, ar);
  375               }
  376               else if (content.isArray()) {
  377                   ar = (PdfArray)content;
  378                   markUsed(ar);
  379               }
  380               else if (content.isStream()) {
  381                   ar = new PdfArray();
  382                   ar.add(pageN.get(PdfName.CONTENTS));
  383                   pageN.put(PdfName.CONTENTS, ar);
  384               }
  385               else {
  386                   ar = new PdfArray();
  387                   pageN.put(PdfName.CONTENTS, ar);
  388               }
  389               ByteBuffer out = new ByteBuffer();
  390               if (ps.under != null) {
  391                   out.append(PdfContents.SAVESTATE);
  392                   applyRotation(pageN, out);
  393                   out.append(ps.under.getInternalBuffer());
  394                   out.append(PdfContents.RESTORESTATE);
  395               }
  396               if (ps.over != null)
  397                   out.append(PdfContents.SAVESTATE);
  398               PdfStream stream = new PdfStream(out.toByteArray());
  399               stream.flateCompress(compressionLevel);
  400               ar.addFirst(addToBody(stream).getIndirectReference());
  401               out.reset();
  402               if (ps.over != null) {
  403                   out.append(' ');
  404                   out.append(PdfContents.RESTORESTATE);
  405                   ByteBuffer buf = ps.over.getInternalBuffer();
  406                   out.append(buf.getBuffer(), 0, ps.replacePoint);
  407                   out.append(PdfContents.SAVESTATE);
  408                   applyRotation(pageN, out);
  409                   out.append(buf.getBuffer(), ps.replacePoint, buf.size() - ps.replacePoint);
  410                   out.append(PdfContents.RESTORESTATE);
  411                   stream = new PdfStream(out.toByteArray());
  412                   stream.flateCompress(compressionLevel);
  413                   ar.add(addToBody(stream).getIndirectReference());
  414               }
  415               alterResources(ps);
  416           }
  417       }
  418   
  419       void alterResources(PageStamp ps) {
  420           ps.pageN.put(PdfName.RESOURCES, ps.pageResources.getResources());
  421       }
  422       
  423       protected int getNewObjectNumber(PdfReader reader, int number, int generation) {
  424           IntHashtable ref = (IntHashtable)readers2intrefs.get(reader);
  425           if (ref != null) {
  426               int n = ref.get(number);
  427               if (n == 0) {
  428                   n = getIndirectReferenceNumber();
  429                   ref.put(number, n);
  430               }
  431               return n;
  432           }
  433           if (currentPdfReaderInstance == null) {
  434               if (append && number < initialXrefSize)
  435                   return number;
  436               int n = myXref.get(number);
  437               if (n == 0) {
  438                   n = getIndirectReferenceNumber();
  439                   myXref.put(number, n);
  440               }
  441               return n;
  442           }
  443           else
  444               return currentPdfReaderInstance.getNewObjectNumber(number, generation);
  445       }
  446       
  447       RandomAccessFileOrArray getReaderFile(PdfReader reader) {
  448           if (readers2intrefs.containsKey(reader)) {
  449               RandomAccessFileOrArray raf = (RandomAccessFileOrArray)readers2file.get(reader);
  450               if (raf != null)
  451                   return raf;
  452               return reader.getSafeFile();
  453           }
  454           if (currentPdfReaderInstance == null)
  455               return file;
  456           else
  457               return currentPdfReaderInstance.getReaderFile();
  458       }
  459       
  460       /**
  461        * @param reader
  462        * @param openFile
  463        * @throws IOException
  464        */
  465       public void registerReader(PdfReader reader, boolean openFile) throws IOException {
  466           if (readers2intrefs.containsKey(reader))
  467               return;
  468           readers2intrefs.put(reader, new IntHashtable());
  469           if (openFile) {
  470               RandomAccessFileOrArray raf = reader.getSafeFile();
  471               readers2file.put(reader, raf);
  472               raf.reOpen();
  473           }
  474       }
  475       
  476       /**
  477        * @param reader
  478        */
  479       public void unRegisterReader(PdfReader reader) {
  480           if (!readers2intrefs.containsKey(reader))
  481               return;
  482           readers2intrefs.remove(reader);
  483           RandomAccessFileOrArray raf = (RandomAccessFileOrArray)readers2file.get(reader);
  484           if (raf == null)
  485               return;
  486           readers2file.remove(reader);
  487           try{raf.close();}catch(Exception e){}
  488       }
  489   
  490       static void findAllObjects(PdfReader reader, PdfObject obj, IntHashtable hits) {
  491           if (obj == null)
  492               return;
  493           switch (obj.type()) {
  494               case PdfObject.INDIRECT:
  495                   PRIndirectReference iref = (PRIndirectReference)obj;
  496                   if (reader != iref.getReader())
  497                       return;
  498                   if (hits.containsKey(iref.getNumber()))
  499                       return;
  500                   hits.put(iref.getNumber(), 1);
  501                   findAllObjects(reader, PdfReader.getPdfObject(obj), hits);
  502                   return;
  503               case PdfObject.ARRAY:
  504                   ArrayList lst = ((PdfArray)obj).getArrayList();
  505                   for (int k = 0; k < lst.size(); ++k) {
  506                       findAllObjects(reader, (PdfObject)lst.get(k), hits);
  507                   }
  508                   return;
  509               case PdfObject.DICTIONARY:
  510               case PdfObject.STREAM:
  511                   PdfDictionary dic = (PdfDictionary)obj;
  512                   for (Iterator it = dic.getKeys().iterator(); it.hasNext();) {
  513                       PdfName name = (PdfName)it.next();
  514                       findAllObjects(reader, dic.get(name), hits);
  515                   }
  516                   return;
  517           }
  518       }
  519       
  520       /**
  521        * @param fdf
  522        * @throws IOException
  523        */
  524       public void addComments(FdfReader fdf) throws IOException{
  525           if (readers2intrefs.containsKey(fdf))
  526               return;
  527           PdfDictionary catalog = fdf.getCatalog();
  528           catalog = (PdfDictionary)PdfReader.getPdfObject(catalog.get(PdfName.FDF));
  529           if (catalog == null)
  530               return;
  531           PdfArray annots = (PdfArray)PdfReader.getPdfObject(catalog.get(PdfName.ANNOTS));
  532           if (annots == null || annots.size() == 0)
  533               return;
  534           registerReader(fdf, false);
  535           IntHashtable hits = new IntHashtable();
  536           HashMap irt = new HashMap();
  537           ArrayList an = new ArrayList();
  538           ArrayList ar = annots.getArrayList();
  539           for (int k = 0; k < ar.size(); ++k) {
  540               PdfObject obj = (PdfObject)ar.get(k);
  541               PdfDictionary annot = (PdfDictionary)PdfReader.getPdfObject(obj);
  542               PdfNumber page = (PdfNumber)PdfReader.getPdfObject(annot.get(PdfName.PAGE));
  543               if (page == null || page.intValue() >= reader.getNumberOfPages())
  544                   continue;
  545               findAllObjects(fdf, obj, hits);
  546               an.add(obj);
  547               if (obj.type() == PdfObject.INDIRECT) {
  548                   PdfObject nm = PdfReader.getPdfObject(annot.get(PdfName.NM));
  549                   if (nm != null && nm.type() == PdfObject.STRING)
  550                       irt.put(nm.toString(), obj);
  551               }
  552           }
  553           int arhits[] = hits.getKeys();
  554           for (int k = 0; k < arhits.length; ++k) {
  555               int n = arhits[k];
  556               PdfObject obj = fdf.getPdfObject(n);
  557               if (obj.type() == PdfObject.DICTIONARY) {
  558                   PdfObject str = PdfReader.getPdfObject(((PdfDictionary)obj).get(PdfName.IRT));
  559                   if (str != null && str.type() == PdfObject.STRING) {
  560                      PdfObject i = (PdfObject)irt.get(str.toString());
  561                      if (i != null) {
  562                          PdfDictionary dic2 = new PdfDictionary();
  563                          dic2.merge((PdfDictionary)obj);
  564                          dic2.put(PdfName.IRT, i);
  565                          obj = dic2;
  566                      }
  567                   }
  568               }
  569               addToBody(obj, getNewObjectNumber(fdf, n, 0));
  570           }
  571           for (int k = 0; k < an.size(); ++k) {
  572               PdfObject obj = (PdfObject)an.get(k);
  573               PdfDictionary annot = (PdfDictionary)PdfReader.getPdfObject(obj);
  574               PdfNumber page = (PdfNumber)PdfReader.getPdfObject(annot.get(PdfName.PAGE));
  575               PdfDictionary dic = reader.getPageN(page.intValue() + 1);
  576               PdfArray annotsp = (PdfArray)PdfReader.getPdfObject(dic.get(PdfName.ANNOTS), dic);
  577               if (annotsp == null) {
  578                   annotsp = new PdfArray();
  579                   dic.put(PdfName.ANNOTS, annotsp);
  580                   markUsed(dic);
  581               }
  582               markUsed(annotsp);
  583               annotsp.add(obj);
  584           }
  585       }
  586       
  587       PageStamp getPageStamp(int pageNum) {
  588           PdfDictionary pageN = reader.getPageN(pageNum);
  589           PageStamp ps = (PageStamp)pagesToContent.get(pageN);
  590           if (ps == null) {
  591               ps = new PageStamp(this, reader, pageN);
  592               pagesToContent.put(pageN, ps);
  593           }
  594           return ps;
  595       }
  596       
  597       PdfContentByte getUnderContent(int pageNum) {
  598           if (pageNum < 1 || pageNum > reader.getNumberOfPages())
  599               return null;
  600           PageStamp ps = getPageStamp(pageNum);
  601           if (ps.under == null)
  602               ps.under = new StampContent(this, ps);
  603           return ps.under;
  604       }
  605       
  606       PdfContentByte getOverContent(int pageNum) {
  607           if (pageNum < 1 || pageNum > reader.getNumberOfPages())
  608               return null;
  609           PageStamp ps = getPageStamp(pageNum);
  610           if (ps.over == null)
  611               ps.over = new StampContent(this, ps);
  612           return ps.over;
  613       }
  614       
  615       void correctAcroFieldPages(int page) {
  616           if (acroFields == null)
  617               return;
  618           if (page > reader.getNumberOfPages())
  619               return;
  620           HashMap fields = acroFields.getFields();
  621           for (Iterator it = fields.values().iterator(); it.hasNext();) {
  622               AcroFields.Item item = (AcroFields.Item)it.next();
  623               ArrayList pages = item.page;
  624               for (int k = 0; k < pages.size(); ++k) {
  625                   int p = ((Integer)pages.get(k)).intValue();
  626                   if (p >= page)
  627                       pages.set(k, new Integer(p + 1));
  628               }
  629           }
  630       }
  631       
  632       private static void moveRectangle(PdfDictionary dic2, PdfReader r, int pageImported, PdfName key, String name) {
  633           Rectangle m = r.getBoxSize(pageImported, name);
  634           if (m == null)
  635               dic2.remove(key);
  636           else
  637               dic2.put(key, new PdfRectangle(m));
  638       }
  639       
  640       void replacePage(PdfReader r, int pageImported, int pageReplaced) {
  641           PdfDictionary pageN = reader.getPageN(pageReplaced);
  642           if (pagesToContent.containsKey(pageN))
  643               throw new IllegalStateException("This page cannot be replaced: new content was already added");
  644           PdfImportedPage p = getImportedPage(r, pageImported);
  645           PdfDictionary dic2 = reader.getPageNRelease(pageReplaced);
  646           dic2.remove(PdfName.RESOURCES);
  647           dic2.remove(PdfName.CONTENTS);
  648           moveRectangle(dic2, r, pageImported, PdfName.MEDIABOX, "media");
  649           moveRectangle(dic2, r, pageImported, PdfName.CROPBOX, "crop");
  650           moveRectangle(dic2, r, pageImported, PdfName.TRIMBOX, "trim");
  651           moveRectangle(dic2, r, pageImported, PdfName.ARTBOX, "art");
  652           moveRectangle(dic2, r, pageImported, PdfName.BLEEDBOX, "bleed");
  653           dic2.put(PdfName.ROTATE, new PdfNumber(r.getPageRotation(pageImported)));
  654           PdfContentByte cb = getOverContent(pageReplaced);
  655           cb.addTemplate(p, 0, 0);
  656           PageStamp ps = (PageStamp)pagesToContent.get(pageN);
  657           ps.replacePoint = ps.over.getInternalBuffer().size();
  658       }
  659       
  660       void insertPage(int pageNumber, Rectangle mediabox) {
  661           Rectangle media = new Rectangle(mediabox);
  662           int rotation = media.getRotation() % 360;
  663           PdfDictionary page = new PdfDictionary(PdfName.PAGE);
  664           PdfDictionary resources = new PdfDictionary();
  665           PdfArray procset = new PdfArray();
  666           procset.add(PdfName.PDF);
  667           procset.add(PdfName.TEXT);
  668           procset.add(PdfName.IMAGEB);
  669           procset.add(PdfName.IMAGEC);
  670           procset.add(PdfName.IMAGEI);
  671           resources.put(PdfName.PROCSET, procset);
  672           page.put(PdfName.RESOURCES, resources);
  673           page.put(PdfName.ROTATE, new PdfNumber(rotation));
  674           page.put(PdfName.MEDIABOX, new PdfRectangle(media, rotation));
  675           PRIndirectReference pref = reader.addPdfObject(page);
  676           PdfDictionary parent;
  677           PRIndirectReference parentRef;
  678           if (pageNumber > reader.getNumberOfPages()) {
  679               PdfDictionary lastPage = reader.getPageNRelease(reader.getNumberOfPages());
  680               parentRef = (PRIndirectReference)lastPage.get(PdfName.PARENT);
  681               parentRef = new PRIndirectReference(reader, parentRef.getNumber());
  682               parent = (PdfDictionary)PdfReader.getPdfObject(parentRef);
  683               PdfArray kids = (PdfArray)PdfReader.getPdfObject(parent.get(PdfName.KIDS), parent);
  684               kids.add(pref);
  685               markUsed(kids);
  686               reader.pageRefs.insertPage(pageNumber, pref);
  687           }
  688           else {
  689               if (pageNumber < 1)
  690                   pageNumber = 1;
  691               PdfDictionary firstPage = reader.getPageN(pageNumber);
  692               PRIndirectReference firstPageRef = reader.getPageOrigRef(pageNumber);
  693               reader.releasePage(pageNumber);
  694               parentRef = (PRIndirectReference)firstPage.get(PdfName.PARENT);
  695               parentRef = new PRIndirectReference(reader, parentRef.getNumber());
  696               parent = (PdfDictionary)PdfReader.getPdfObject(parentRef);
  697               PdfArray kids = (PdfArray)PdfReader.getPdfObject(parent.get(PdfName.KIDS), parent);
  698               ArrayList ar = kids.getArrayList();
  699               int len = ar.size();
  700               int num = firstPageRef.getNumber();
  701               for (int k = 0; k < len; ++k) {
  702                   PRIndirectReference cur = (PRIndirectReference)ar.get(k);
  703                   if (num == cur.getNumber()) {
  704                       ar.add(k, pref);
  705                       break;
  706                   }
  707               }
  708               if (len == ar.size())
  709                   throw new RuntimeException("Internal inconsistence.");
  710               markUsed(kids);
  711               reader.pageRefs.insertPage(pageNumber, pref);
  712               correctAcroFieldPages(pageNumber);
  713           }
  714           page.put(PdfName.PARENT, parentRef);
  715           while (parent != null) {
  716               markUsed(parent);
  717               PdfNumber count = (PdfNumber)PdfReader.getPdfObjectRelease(parent.get(PdfName.COUNT));
  718               parent.put(PdfName.COUNT, new PdfNumber(count.intValue() + 1));
  719               parent = (PdfDictionary)PdfReader.getPdfObject(parent.get(PdfName.PARENT));
  720           }
  721       }
  722       
  723       /** Getter for property rotateContents.
  724        * @return Value of property rotateContents.
  725        *
  726        */
  727       boolean isRotateContents() {
  728           return this.rotateContents;
  729       }
  730       
  731       /** Setter for property rotateContents.
  732        * @param rotateContents New value of property rotateContents.
  733        *
  734        */
  735       void setRotateContents(boolean rotateContents) {
  736           this.rotateContents = rotateContents;
  737       }
  738       
  739       boolean isContentWritten() {
  740           return body.size() > 1;
  741       }
  742       
  743       AcroFields getAcroFields() {
  744           if (acroFields == null) {
  745               acroFields = new AcroFields(reader, this);
  746           }
  747           return acroFields;
  748       }
  749   
  750       void setFormFlattening(boolean flat) {
  751           this.flat = flat;
  752       }
  753       
  754   	void setFreeTextFlattening(boolean flat) {
  755   		this.flatFreeText = flat;
  756       }
  757       
  758       boolean partialFormFlattening(String name) {
  759           getAcroFields();
  760           if (acroFields.getXfa().isXfaPresent())
  761               throw new UnsupportedOperationException("Partial form flattening is not supported with XFA forms.");
  762           if (!acroFields.getFields().containsKey(name))
  763               return false;
  764           partialFlattening.add(name);
  765           return true;
  766       }
  767       
  768       void flatFields() {
  769           if (append)
  770               throw new IllegalArgumentException("Field flattening is not supported in append mode.");
  771           getAcroFields();
  772           HashMap fields = acroFields.getFields();
  773           if (fieldsAdded && partialFlattening.isEmpty()) {
  774               for (Iterator i = fields.keySet().iterator(); i.hasNext();) {
  775                   partialFlattening.add(i.next());
  776               }
  777           }
  778           PdfDictionary acroForm = (PdfDictionary)PdfReader.getPdfObject(reader.getCatalog().get(PdfName.ACROFORM));
  779           ArrayList acroFds = null;
  780           if (acroForm != null) {
  781               PdfArray array = (PdfArray)PdfReader.getPdfObject(acroForm.get(PdfName.FIELDS), acroForm);
  782               if (array != null)
  783                   acroFds = array.getArrayList();
  784           }
  785           for (Iterator i = fields.entrySet().iterator(); i.hasNext();) {
  786               Map.Entry entry = (Map.Entry) i.next();
  787               String name = (String) entry.getKey();
  788               if (!partialFlattening.isEmpty() && !partialFlattening.contains(name))
  789                   continue;
  790               AcroFields.Item item = (AcroFields.Item) entry.getValue();
  791               for (int k = 0; k < item.merged.size(); ++k) {
  792                   PdfDictionary merged = (PdfDictionary)item.merged.get(k);
  793                   PdfNumber ff = (PdfNumber)PdfReader.getPdfObject(merged.get(PdfName.F));
  794                   int flags = 0;
  795                   if (ff != null)
  796                       flags = ff.intValue();
  797                   int page = ((Integer)item.page.get(k)).intValue();
  798                   PdfDictionary appDic = (PdfDictionary)PdfReader.getPdfObject(merged.get(PdfName.AP));
  799                   if (appDic != null && (flags & PdfFormField.FLAGS_PRINT) != 0 && (flags & PdfFormField.FLAGS_HIDDEN) == 0) {
  800                       PdfObject obj = appDic.get(PdfName.N);
  801                       PdfAppearance app = null;
  802                       if (obj != null) {
  803                           PdfObject objReal = PdfReader.getPdfObject(obj);
  804                           if (obj instanceof PdfIndirectReference && !obj.isIndirect())
  805                               app = new PdfAppearance((PdfIndirectReference)obj);
  806                           else if (objReal instanceof PdfStream) {
  807                               ((PdfDictionary)objReal).put(PdfName.SUBTYPE, PdfName.FORM);
  808                               app = new PdfAppearance((PdfIndirectReference)obj);
  809                           }
  810                           else {
  811                               if (objReal != null && objReal.isDictionary()) {
  812                                   PdfName as = (PdfName)PdfReader.getPdfObject(merged.get(PdfName.AS));
  813                                   if (as != null) {
  814                                       PdfIndirectReference iref = (PdfIndirectReference)((PdfDictionary)objReal).get(as);
  815                                       if (iref != null) {
  816                                           app = new PdfAppearance(iref);
  817                                           if (iref.isIndirect()) {
  818                                               objReal = PdfReader.getPdfObject(iref);
  819                                               ((PdfDictionary)objReal).put(PdfName.SUBTYPE, PdfName.FORM);
  820                                           }
  821                                       }
  822                                   }
  823                               }
  824                           }
  825                       }
  826                       if (app != null) {
  827                           Rectangle box = PdfReader.getNormalizedRectangle((PdfArray)PdfReader.getPdfObject(merged.get(PdfName.RECT)));
  828                           PdfContentByte cb = getOverContent(page);
  829                           cb.setLiteral("Q ");
  830                           cb.addTemplate(app, box.getLeft(), box.getBottom());
  831                           cb.setLiteral("q ");
  832                       }
  833                   }
  834                   if (partialFlattening.isEmpty())
  835                       continue;
  836                   PdfDictionary pageDic = reader.getPageN(page);
  837                   PdfArray annots = (PdfArray)PdfReader.getPdfObject(pageDic.get(PdfName.ANNOTS));
  838                   if (annots == null)
  839                       continue;
  840                   ArrayList ar = annots.getArrayList();
  841                   for (int idx = 0; idx < ar.size(); ++idx) {
  842                       PdfObject ran = (PdfObject)ar.get(idx);
  843                       if (!ran.isIndirect())
  844                           continue;
  845                       PdfObject ran2 = (PdfObject)item.widget_refs.get(k);
  846                       if (!ran2.isIndirect())
  847                           continue;
  848                       if (((PRIndirectReference)ran).getNumber() == ((PRIndirectReference)ran2).getNumber()) {
  849                           ar.remove(idx--);
  850                           PRIndirectReference wdref = (PRIndirectReference)ran2;
  851                           while (true) {
  852                               PdfDictionary wd = (PdfDictionary)PdfReader.getPdfObject(wdref);
  853                               PRIndirectReference parentRef = (PRIndirectReference)wd.get(PdfName.PARENT);
  854                               PdfReader.killIndirect(wdref);
  855                               if (parentRef == null) { // reached AcroForm
  856                                   for (int fr = 0; fr < acroFds.size(); ++fr) {
  857                                       PdfObject h = (PdfObject)acroFds.get(fr);
  858                                       if (h.isIndirect() && ((PRIndirectReference)h).getNumber() == wdref.getNumber()) {
  859                                           acroFds.remove(fr);
  860                                           --fr;
  861                                       }
  862                                   }
  863                                   break;
  864                               }
  865                               PdfDictionary parent = (PdfDictionary)PdfReader.getPdfObject(parentRef);
  866                               PdfArray kids = (PdfArray)PdfReader.getPdfObject(parent.get(PdfName.KIDS));
  867                               ArrayList kar = kids.getArrayList();
  868                               for (int fr = 0; fr < kar.size(); ++fr) {
  869                                   PdfObject h = (PdfObject)kar.get(fr);
  870                                   if (h.isIndirect() && ((PRIndirectReference)h).getNumber() == wdref.getNumber()) {
  871                                       kar.remove(fr);
  872                                       --fr;
  873                                   }
  874                               }
  875                               if (!kar.isEmpty())
  876                                   break;
  877                               wdref = parentRef;
  878                           }
  879                       }
  880                   }
  881                   if (ar.isEmpty()) {
  882                       PdfReader.killIndirect(pageDic.get(PdfName.ANNOTS));
  883                       pageDic.remove(PdfName.ANNOTS);
  884                   }
  885               }
  886           }
  887           if (!fieldsAdded && partialFlattening.isEmpty()) {
  888               for (int page = 1; page <= reader.getNumberOfPages(); ++page) {
  889                   PdfDictionary pageDic = reader.getPageN(page);
  890                   PdfArray annots = (PdfArray)PdfReader.getPdfObject(pageDic.get(PdfName.ANNOTS));
  891                   if (annots == null)
  892                       continue;
  893                   ArrayList ar = annots.getArrayList();
  894                   for (int idx = 0; idx < ar.size(); ++idx) {
  895                       PdfObject annoto = PdfReader.getPdfObject((PdfObject)ar.get(idx));
  896                       if ((annoto instanceof PdfIndirectReference) && !annoto.isIndirect())
  897                           continue;
  898                       if (!annoto.isDictionary() || PdfName.WIDGET.equals(((PdfDictionary)annoto).get(PdfName.SUBTYPE))) {
  899                           ar.remove(idx);
  900                           --idx;
  901                       }
  902                   }
  903                   if (ar.isEmpty()) {
  904                       PdfReader.killIndirect(pageDic.get(PdfName.ANNOTS));
  905                       pageDic.remove(PdfName.ANNOTS);
  906                   }
  907               }
  908               eliminateAcroformObjects();
  909           }
  910       }
  911   
  912       void eliminateAcroformObjects() {
  913           PdfObject acro = reader.getCatalog().get(PdfName.ACROFORM);
  914           if (acro == null)
  915               return;
  916           PdfDictionary acrodic = (PdfDictionary)PdfReader.getPdfObject(acro);
  917           reader.killXref(acrodic.get(PdfName.XFA));
  918           acrodic.remove(PdfName.XFA);
  919           PdfObject iFields = acrodic.get(PdfName.FIELDS);
  920           if (iFields != null) {
  921               PdfDictionary kids = new PdfDictionary();
  922               kids.put(PdfName.KIDS, iFields);
  923               sweepKids(kids);
  924               PdfReader.killIndirect(iFields);
  925               acrodic.put(PdfName.FIELDS, new PdfArray());
  926           }
  927   //        PdfReader.killIndirect(acro);
  928   //        reader.getCatalog().remove(PdfName.ACROFORM);
  929       }
  930       
  931       void sweepKids(PdfObject obj) {
  932           PdfObject oo = PdfReader.killIndirect(obj);
  933           if (oo == null || !oo.isDictionary())
  934               return;
  935           PdfDictionary dic = (PdfDictionary)oo;
  936           PdfArray kids = (PdfArray)PdfReader.killIndirect(dic.get(PdfName.KIDS));
  937           if (kids == null)
  938               return;
  939           ArrayList ar = kids.getArrayList();
  940           for (int k = 0; k < ar.size(); ++k) {
  941               sweepKids((PdfObject)ar.get(k));
  942           }
  943       }
  944       
  945       private void flatFreeTextFields() 
  946   	{
  947   		if (append)
  948   			throw new IllegalArgumentException("FreeText flattening is not supported in append mode.");
  949   		
  950   		for (int page = 1; page <= reader.getNumberOfPages(); ++page) 
  951   		{
  952   			PdfDictionary pageDic = reader.getPageN(page);
  953   			PdfArray annots = (PdfArray)PdfReader.getPdfObject(pageDic.get(PdfName.ANNOTS));
  954   			if (annots == null)
  955   				continue;
  956   			ArrayList ar = annots.getArrayList();
  957   			for (int idx = 0; idx < ar.size(); ++idx) 
  958   			{
  959   				PdfObject annoto = PdfReader.getPdfObject((PdfObject)ar.get(idx));
  960   				if ((annoto instanceof PdfIndirectReference) && !annoto.isIndirect())
  961   					continue;
  962   				
  963   				PdfDictionary annDic = (PdfDictionary)annoto;
  964    				if (!((PdfName)annDic.get(PdfName.SUBTYPE)).equals(PdfName.FREETEXT)) 
  965   					continue;
  966   				PdfNumber ff = (PdfNumber)PdfReader.getPdfObject(annDic.get(PdfName.F));
  967                   int flags = (ff != null) ? ff.intValue() : 0;
  968   			
  969   				if ( (flags & PdfFormField.FLAGS_PRINT) != 0 && (flags & PdfFormField.FLAGS_HIDDEN) == 0) 
  970   				{
  971   					PdfObject obj1 = annDic.get(PdfName.AP);
  972   					if (obj1 == null) 
  973   						continue;
  974   					PdfDictionary appDic = (obj1 instanceof PdfIndirectReference) ?
  975   							(PdfDictionary) PdfReader.getPdfObject(obj1) : (PdfDictionary) obj1;			
  976   					PdfObject obj = appDic.get(PdfName.N);
  977   					PdfAppearance app = null;
  978   					PdfObject objReal = PdfReader.getPdfObject(obj);
  979   					
  980   					if (obj instanceof PdfIndirectReference && !obj.isIndirect())
  981   						app = new PdfAppearance((PdfIndirectReference)obj);
  982   					else if (objReal instanceof PdfStream) 
  983   					{
  984   						((PdfDictionary)objReal).put(PdfName.SUBTYPE, PdfName.FORM);
  985   						app = new PdfAppearance((PdfIndirectReference)obj);
  986   					}
  987   					else 
  988   					{
  989   						if (objReal.isDictionary()) 
  990   						{
  991   							PdfName as_p = (PdfName)PdfReader.getPdfObject(appDic.get(PdfName.AS));
  992   							if (as_p != null) 
  993   							{
  994   								PdfIndirectReference iref = (PdfIndirectReference)((PdfDictionary)objReal).get(as_p);
  995   								if (iref != null) 
  996   								{
  997   									app = new PdfAppearance(iref);
  998   									if (iref.isIndirect()) 
  999   									{
 1000   										objReal = PdfReader.getPdfObject(iref);
 1001   										((PdfDictionary)objReal).put(PdfName.SUBTYPE, PdfName.FORM);
 1002   									}
 1003   								}
 1004   							}
 1005   						}
 1006   					}
 1007   					if (app != null) 
 1008   					{
 1009   						Rectangle box = PdfReader.getNormalizedRectangle((PdfArray)PdfReader.getPdfObject(annDic.get(PdfName.RECT)));
 1010   						PdfContentByte cb = getOverContent(page);
 1011   						cb.setLiteral("Q ");
 1012   						cb.addTemplate(app, box.getLeft(), box.getBottom());
 1013   						cb.setLiteral("q ");
 1014   					}
 1015   				}
 1016   			}
 1017   			for (int idx = 0; idx < ar.size(); ++idx) 
 1018   			{
 1019   				PdfObject annoto = PdfReader.getPdfObject((PdfObject)ar.get(idx));
 1020   				if (annoto != null && annoto.isDictionary())
 1021   				{
 1022   					PdfDictionary annot = (PdfDictionary)annoto;
 1023   					if (PdfName.FREETEXT.equals(annot.get(PdfName.SUBTYPE)))
 1024   					{
 1025   						ar.remove(idx);
 1026   						--idx;
 1027   					}
 1028   				}
 1029   			}
 1030   			if (ar.isEmpty()) 
 1031   			{
 1032   				PdfReader.killIndirect(pageDic.get(PdfName.ANNOTS));
 1033   				pageDic.remove(PdfName.ANNOTS);
 1034   			}
 1035   		}
 1036   	}
 1037       
 1038       /**
 1039        * @see com.lowagie.text.pdf.PdfWriter#getPageReference(int)
 1040        */
 1041       public PdfIndirectReference getPageReference(int page) {
 1042           PdfIndirectReference ref = reader.getPageOrigRef(page);
 1043           if (ref == null)
 1044               throw new IllegalArgumentException("Invalid page number " + page);
 1045           return ref;
 1046       }
 1047       
 1048       /**
 1049        * @see com.lowagie.text.pdf.PdfWriter#addAnnotation(com.lowagie.text.pdf.PdfAnnotation)
 1050        */
 1051       public void addAnnotation(PdfAnnotation annot) {
 1052           throw new RuntimeException("Unsupported in this context. Use PdfStamper.addAnnotation()");
 1053       }
 1054       
 1055       void addDocumentField(PdfIndirectReference ref) {
 1056           PdfDictionary catalog = reader.getCatalog();
 1057           PdfDictionary acroForm = (PdfDictionary)PdfReader.getPdfObject(catalog.get(PdfName.ACROFORM), catalog);
 1058           if (acroForm == null) {
 1059               acroForm = new PdfDictionary();
 1060               catalog.put(PdfName.ACROFORM, acroForm);
 1061               markUsed(catalog);
 1062           }
 1063           PdfArray fields = (PdfArray)PdfReader.getPdfObject(acroForm.get(PdfName.FIELDS), acroForm);
 1064           if (fields == null) {
 1065               fields = new PdfArray();
 1066               acroForm.put(PdfName.FIELDS, fields);
 1067               markUsed(acroForm);
 1068           }
 1069           if (!acroForm.contains(PdfName.DA)) {
 1070               acroForm.put(PdfName.DA, new PdfString("/Helv 0 Tf 0 g "));
 1071               markUsed(acroForm);
 1072           }
 1073           fields.add(ref);
 1074           markUsed(fields);
 1075       }
 1076       
 1077       void addFieldResources() throws IOException {
 1078           if (fieldTemplates.isEmpty())
 1079               return;
 1080           PdfDictionary catalog = reader.getCatalog();
 1081           PdfDictionary acroForm = (PdfDictionary)PdfReader.getPdfObject(catalog.get(PdfName.ACROFORM), catalog);
 1082           if (acroForm == null) {
 1083               acroForm = new PdfDictionary();
 1084               catalog.put(PdfName.ACROFORM, acroForm);
 1085               markUsed(catalog);
 1086           }
 1087           PdfDictionary dr = (PdfDictionary)PdfReader.getPdfObject(acroForm.get(PdfName.DR), acroForm);
 1088           if (dr == null) {
 1089               dr = new PdfDictionary();
 1090               acroForm.put(PdfName.DR, dr);
 1091               markUsed(acroForm);
 1092           }
 1093           markUsed(dr);
 1094           for (Iterator it = fieldTemplates.keySet().iterator(); it.hasNext();) {
 1095               PdfTemplate template = (PdfTemplate)it.next();
 1096               PdfFormField.mergeResources(dr, (PdfDictionary)template.getResources(), this);
 1097           }
 1098           if (dr.get(PdfName.ENCODING) == null)
 1099               dr.put(PdfName.ENCODING, PdfName.WIN_ANSI_ENCODING);
 1100           PdfDictionary fonts = (PdfDictionary)PdfReader.getPdfObject(dr.get(PdfName.FONT));
 1101           if (fonts == null) {
 1102               fonts = new PdfDictionary();
 1103               dr.put(PdfName.FONT, fonts);
 1104           }
 1105           if (!fonts.contains(PdfName.HELV)) {
 1106               PdfDictionary dic = new PdfDictionary(PdfName.FONT);
 1107               dic.put(PdfName.BASEFONT, PdfName.HELVETICA);
 1108               dic.put(PdfName.ENCODING, PdfName.WIN_ANSI_ENCODING);
 1109               dic.put(PdfName.NAME, PdfName.HELV);
 1110               dic.put(PdfName.SUBTYPE, PdfName.TYPE1);
 1111               fonts.put(PdfName.HELV, addToBody(dic).getIndirectReference());
 1112           }
 1113           if (!fonts.contains(PdfName.ZADB)) {
 1114               PdfDictionary dic = new PdfDictionary(PdfName.FONT);
 1115               dic.put(PdfName.BASEFONT, PdfName.ZAPFDINGBATS);
 1116               dic.put(PdfName.NAME, PdfName.ZADB);
 1117               dic.put(PdfName.SUBTYPE, PdfName.TYPE1);
 1118               fonts.put(PdfName.ZADB, addToBody(dic).getIndirectReference());
 1119           }
 1120           if (acroForm.get(PdfName.DA) == null) {
 1121               acroForm.put(PdfName.DA, new PdfString("/Helv 0 Tf 0 g "));
 1122               markUsed(acroForm);
 1123           }
 1124       }
 1125       
 1126       void expandFields(PdfFormField field, ArrayList allAnnots) {
 1127           allAnnots.add(field);
 1128           ArrayList kids = field.getKids();
 1129           if (kids != null) {
 1130               for (int k = 0; k < kids.size(); ++k)
 1131                   expandFields((PdfFormField)kids.get(k), allAnnots);
 1132           }
 1133       }
 1134   
 1135       void addAnnotation(PdfAnnotation annot, PdfDictionary pageN) {
 1136           try {
 1137               ArrayList allAnnots = new ArrayList();
 1138               if (annot.isForm()) {
 1139                   fieldsAdded = true;
 1140                   getAcroFields();
 1141                   PdfFormField field = (PdfFormField)annot;
 1142                   if (field.getParent() != null)
 1143                       return;
 1144                   expandFields(field, allAnnots);
 1145               }
 1146               else
 1147                   allAnnots.add(annot);
 1148               for (int k = 0; k < allAnnots.size(); ++k) {
 1149                   annot = (PdfAnnotation)allAnnots.get(k);
 1150                   if (annot.getPlaceInPage() > 0)
 1151                       pageN = reader.getPageN(annot.getPlaceInPage());
 1152                   if (annot.isForm()) {
 1153                       if (!annot.isUsed()) {
 1154                           HashMap templates = annot.getTemplates();
 1155                           if (templates != null)
 1156                               fieldTemplates.putAll(templates);
 1157                       }
 1158                       PdfFormField field = (PdfFormField)annot;
 1159                       if (field.getParent() == null)
 1160                           addDocumentField(field.getIndirectReference());
 1161                   }
 1162                   if (annot.isAnnotation()) {
 1163                       PdfObject pdfobj = PdfReader.getPdfObject(pageN.get(PdfName.ANNOTS), pageN);
 1164                       PdfArray annots = null;
 1165                       if (pdfobj == null || !pdfobj.isArray()) {
 1166                           annots = new PdfArray();
 1167                           pageN.put(PdfName.ANNOTS, annots);
 1168                           markUsed(pageN);
 1169                       }
 1170                       else 
 1171                          annots = (PdfArray)pdfobj;
 1172                       annots.add(annot.getIndirectReference());
 1173                       markUsed(annots);
 1174                       if (!annot.isUsed()) {
 1175                           PdfRectangle rect = (PdfRectangle)annot.get(PdfName.RECT);
 1176                           if (rect != null && (rect.left() != 0 || rect.right() != 0 || rect.top() != 0 || rect.bottom() != 0)) {
 1177                               int rotation = reader.getPageRotation(pageN);
 1178                               Rectangle pageSize = reader.getPageSizeWithRotation(pageN);
 1179                               switch (rotation) {
 1180                                   case 90:
 1181                                       annot.put(PdfName.RECT, new PdfRectangle(
 1182                                       pageSize.getTop() - rect.bottom(),
 1183                                       rect.left(),
 1184                                       pageSize.getTop() - rect.top(),
 1185                                       rect.right()));
 1186                                       break;
 1187                                   case 180:
 1188                                       annot.put(PdfName.RECT, new PdfRectangle(
 1189                                       pageSize.getRight() - rect.left(),
 1190                                       pageSize.getTop() - rect.bottom(),
 1191                                       pageSize.getRight() - rect.right(),
 1192                                       pageSize.getTop() - rect.top()));
 1193                                       break;
 1194                                   case 270:
 1195                                       annot.put(PdfName.RECT, new PdfRectangle(
 1196                                       rect.bottom(),
 1197                                       pageSize.getRight() - rect.left(),
 1198                                       rect.top(),
 1199                                       pageSize.getRight() - rect.right()));
 1200                                       break;
 1201                               }
 1202                           }
 1203                       }
 1204                   }
 1205                   if (!annot.isUsed()) {
 1206                       annot.setUsed();
 1207                       addToBody(annot, annot.getIndirectReference());
 1208                   }
 1209               }
 1210           }
 1211           catch (IOException e) {
 1212               throw new ExceptionConverter(e);
 1213           }
 1214       }
 1215       
 1216       void addAnnotation(PdfAnnotation annot, int page) {
 1217           addAnnotation(annot, reader.getPageN(page));
 1218       }
 1219   
 1220       private void outlineTravel(PRIndirectReference outline) {
 1221           while (outline != null) {
 1222               PdfDictionary outlineR = (PdfDictionary)PdfReader.getPdfObjectRelease(outline);
 1223               PRIndirectReference first = (PRIndirectReference)outlineR.get(PdfName.FIRST);
 1224               if (first != null) {
 1225                   outlineTravel(first);
 1226               }
 1227               PdfReader.killIndirect(outlineR.get(PdfName.DEST));
 1228               PdfReader.killIndirect(outlineR.get(PdfName.A));
 1229               PdfReader.killIndirect(outline);
 1230               outline = (PRIndirectReference)outlineR.get(PdfName.NEXT);
 1231           }
 1232       }
 1233   
 1234       void deleteOutlines() {
 1235           PdfDictionary catalog = reader.getCatalog();
 1236           PRIndirectReference outlines = (PRIndirectReference)catalog.get(PdfName.OUTLINES);
 1237           if (outlines == null)
 1238               return;
 1239           outlineTravel(outlines);
 1240           PdfReader.killIndirect(outlines);
 1241           catalog.remove(PdfName.OUTLINES);
 1242           markUsed(catalog);
 1243       }
 1244       
 1245       void setJavaScript() throws IOException {
 1246           HashMap djs = pdf.getDocumentLevelJS();
 1247           if (djs.isEmpty())
 1248               return;
 1249           PdfDictionary catalog = reader.getCatalog();
 1250           PdfDictionary names = (PdfDictionary)PdfReader.getPdfObject(catalog.get(PdfName.NAMES), catalog);
 1251           if (names == null) {
 1252               names = new PdfDictionary();
 1253               catalog.put(PdfName.NAMES, names);
 1254               markUsed(catalog);
 1255           }
 1256           markUsed(names);
 1257           PdfDictionary tree = PdfNameTree.writeTree(djs, this);
 1258           names.put(PdfName.JAVASCRIPT, addToBody(tree).getIndirectReference());
 1259       }
 1260   
 1261       void addFileAttachments() throws IOException {
 1262           HashMap fs = pdf.getDocumentFileAttachment();
 1263           if (fs.isEmpty())
 1264               return;
 1265           PdfDictionary catalog = reader.getCatalog();
 1266           PdfDictionary names = (PdfDictionary)PdfReader.getPdfObject(catalog.get(PdfName.NAMES), catalog);
 1267           if (names == null) {
 1268               names = new PdfDictionary();
 1269               catalog.put(PdfName.NAMES, names);
 1270               markUsed(catalog);
 1271           }
 1272           markUsed(names);
 1273           HashMap old = PdfNameTree.readTree((PdfDictionary)PdfReader.getPdfObjectRelease(names.get(PdfName.EMBEDDEDFILES)));
 1274           for (Iterator it = fs.entrySet().iterator(); it.hasNext();) {
 1275               Map.Entry entry = (Map.Entry) it.next();
 1276               String name = (String) entry.getKey();
 1277               int k = 0;
 1278               String nn = name;
 1279               while (old.containsKey(nn)) {
 1280                   ++k;
 1281                   nn += " " + k;
 1282               }
 1283               old.put(nn, entry.getValue());
 1284           }
 1285           PdfDictionary tree = PdfNameTree.writeTree(old, this);
 1286           names.put(PdfName.EMBEDDEDFILES, addToBody(tree).getIndirectReference());
 1287       }
 1288   
 1289       /**
 1290        * Adds or replaces the Collection Dictionary in the Catalog.
 1291        * @param	collection	the new collection dictionary.
 1292        */
 1293       void makePackage( PdfCollection collection ) {
 1294           PdfDictionary catalog = reader.getCatalog();
 1295          	catalog.put( PdfName.COLLECTION, collection );
 1296       }
 1297    
 1298       void setOutlines() throws IOException {
 1299           if (newBookmarks == null)
 1300               return;
 1301           deleteOutlines();
 1302           if (newBookmarks.isEmpty())
 1303               return;
 1304           PdfDictionary catalog = reader.getCatalog();
 1305           boolean namedAsNames = (catalog.get(PdfName.DESTS) != null);
 1306           writeOutlines(catalog, namedAsNames);
 1307           markUsed(catalog);
 1308       }
 1309           
 1310       /**
 1311        * Sets the viewer preferences.
 1312        * @param preferences the viewer preferences
 1313        * @see PdfWriter#setViewerPreferences(int)
 1314        */
 1315       public void setViewerPreferences(int preferences) {
 1316           useVp = true;
 1317           this.viewerPreferences.setViewerPreferences(preferences);
 1318       }
 1319       
 1320       /** Adds a viewer preference
 1321        * @param key a key for a viewer preference
 1322        * @param value the value for the viewer preference
 1323        * @see PdfViewerPreferences#addViewerPreference
 1324        */
 1325       public void addViewerPreference(PdfName key, PdfObject value) {
 1326       	useVp = true;
 1327       	this.viewerPreferences.addViewerPreference(key, value);
 1328       }
 1329       
 1330       /**
 1331        * Set the signature flags.
 1332        * @param f the flags. This flags are ORed with current ones
 1333        */
 1334       public void setSigFlags(int f) {
 1335           sigFlags |= f;
 1336       }
 1337       
 1338       /** Always throws an <code>UnsupportedOperationException</code>.
 1339        * @param actionType ignore
 1340        * @param action ignore
 1341        * @throws PdfException ignore
 1342        * @see PdfStamper#setPageAction(PdfName, PdfAction, int)
 1343        */    
 1344       public void setPageAction(PdfName actionType, PdfAction action) throws PdfException {
 1345           throw new UnsupportedOperationException("Use setPageAction(PdfName actionType, PdfAction action, int page)");
 1346       }
 1347   
 1348       /**
 1349        * Sets the open and close page additional action.
 1350        * @param actionType the action type. It can be <CODE>PdfWriter.PAGE_OPEN</CODE>
 1351        * or <CODE>PdfWriter.PAGE_CLOSE</CODE>
 1352        * @param action the action to perform
 1353        * @param page the page where the action will be applied. The first page is 1
 1354        * @throws PdfException if the action type is invalid
 1355        */    
 1356       void setPageAction(PdfName actionType, PdfAction action, int page) throws PdfException {
 1357           if (!actionType.equals(PAGE_OPEN) && !actionType.equals(PAGE_CLOSE))
 1358               throw new PdfException("Invalid page additional action type: " + actionType.toString());
 1359           PdfDictionary pg = reader.getPageN(page);
 1360           PdfDictionary aa = (PdfDictionary)PdfReader.getPdfObject(pg.get(PdfName.AA), pg);
 1361           if (aa == null) {
 1362               aa = new PdfDictionary();
 1363               pg.put(PdfName.AA, aa);
 1364               markUsed(pg);
 1365           }
 1366           aa.put(actionType, action);
 1367           markUsed(aa);
 1368       }
 1369   
 1370       /**
 1371        * Always throws an <code>UnsupportedOperationException</code>.
 1372        * @param seconds ignore
 1373        */
 1374       public void setDuration(int seconds) {
 1375           throw new UnsupportedOperationException("Use setPageAction(PdfName actionType, PdfAction action, int page)");
 1376       }
 1377       
 1378       /**
 1379        * Always throws an <code>UnsupportedOperationException</code>.
 1380        * @param transition ignore
 1381        */
 1382       public void setTransition(PdfTransition transition) {
 1383           throw new UnsupportedOperationException("Use setPageAction(PdfName actionType, PdfAction action, int page)");
 1384       }
 1385   
 1386       /**
 1387        * Sets the display duration for the page (for presentations)
 1388        * @param seconds   the number of seconds to display the page. A negative value removes the entry
 1389        * @param page the page where the duration will be applied. The first page is 1
 1390        */
 1391       void setDuration(int seconds, int page) {
 1392           PdfDictionary pg = reader.getPageN(page);
 1393           if (seconds < 0)
 1394               pg.remove(PdfName.DUR);
 1395           else
 1396               pg.put(PdfName.DUR, new PdfNumber(seconds));
 1397           markUsed(pg);
 1398       }
 1399       
 1400       /**
 1401        * Sets the transition for the page
 1402        * @param transition   the transition object. A <code>null</code> removes the transition
 1403        * @param page the page where the transition will be applied. The first page is 1
 1404        */
 1405       void setTransition(PdfTransition transition, int page) {
 1406           PdfDictionary pg = reader.getPageN(page);
 1407           if (transition == null)
 1408               pg.remove(PdfName.TRANS);
 1409           else
 1410               pg.put(PdfName.TRANS, transition.getTransitionDictionary());
 1411           markUsed(pg);
 1412       }
 1413   
 1414       protected void markUsed(PdfObject obj) {
 1415           if (append && obj != null) {
 1416               PRIndirectReference ref = null;
 1417               if (obj.type() == PdfObject.INDIRECT)
 1418                   ref = (PRIndirectReference)obj;
 1419               else
 1420                   ref = obj.getIndRef();
 1421               if (ref != null)
 1422                   marked.put(ref.getNumber(), 1);
 1423           }
 1424       }
 1425       
 1426       protected void markUsed(int num) {
 1427           if (append)
 1428               marked.put(num, 1);
 1429       }
 1430       
 1431       /**
 1432        * Getter for property append.
 1433        * @return Value of property append.
 1434        */
 1435       boolean isAppend() {
 1436           return append;
 1437       }
 1438           
 1439       /** Additional-actions defining the actions to be taken in
 1440        * response to various trigger events affecting the document
 1441        * as a whole. The actions types allowed are: <CODE>DOCUMENT_CLOSE</CODE>,
 1442        * <CODE>WILL_SAVE</CODE>, <CODE>DID_SAVE</CODE>, <CODE>WILL_PRINT</CODE>
 1443        * and <CODE>DID_PRINT</CODE>.
 1444        *
 1445        * @param actionType the action type
 1446        * @param action the action to execute in response to the trigger
 1447        * @throws PdfException on invalid action type
 1448        */
 1449       public void setAdditionalAction(PdfName actionType, PdfAction action) throws PdfException {
 1450           if (!(actionType.equals(DOCUMENT_CLOSE) ||
 1451           actionType.equals(WILL_SAVE) ||
 1452           actionType.equals(DID_SAVE) ||
 1453           actionType.equals(WILL_PRINT) ||
 1454           actionType.equals(DID_PRINT))) {
 1455               throw new PdfException("Invalid additional action type: " + actionType.toString());
 1456           }
 1457           PdfDictionary aa = (PdfDictionary)PdfReader.getPdfObject(reader.getCatalog().get(PdfName.AA));
 1458           if (aa == null) {
 1459               if (action == null)
 1460                   return;
 1461               aa = new PdfDictionary();
 1462               reader.getCatalog().put(PdfName.AA, aa);
 1463           }
 1464           markUsed(aa);
 1465           if (action == null)
 1466               aa.remove(actionType);
 1467           else
 1468               aa.put(actionType, action);
 1469       }
 1470   
 1471       /**
 1472        * @see com.lowagie.text.pdf.PdfWriter#setOpenAction(com.lowagie.text.pdf.PdfAction)
 1473        */
 1474       public void setOpenAction(PdfAction action) {
 1475           openAction = action;
 1476       }
 1477       
 1478       /**
 1479        * @see com.lowagie.text.pdf.PdfWriter#setOpenAction(java.lang.String)
 1480        */
 1481       public void setOpenAction(String name) {
 1482           throw new UnsupportedOperationException("Open actions by name are not supported.");
 1483       }
 1484       
 1485       /**
 1486        * @see com.lowagie.text.pdf.PdfWriter#setThumbnail(com.lowagie.text.Image)
 1487        */
 1488       public void setThumbnail(com.lowagie.text.Image image) {
 1489           throw new UnsupportedOperationException("Use PdfStamper.setThumbnail().");
 1490       }
 1491       
 1492       void setThumbnail(Image image, int page) throws PdfException, DocumentException {
 1493           PdfIndirectReference thumb = getImageReference(addDirectImageSimple(image));
 1494           reader.resetReleasePage();
 1495           PdfDictionary dic = reader.getPageN(page);
 1496           dic.put(PdfName.THUMB, thumb);
 1497           reader.resetReleasePage();
 1498       }
 1499   
 1500       public PdfContentByte getDirectContentUnder() {
 1501           throw new UnsupportedOperationException("Use PdfStamper.getUnderContent() or PdfStamper.getOverContent()");
 1502       }
 1503   
 1504       public PdfContentByte getDirectContent() {
 1505           throw new UnsupportedOperationException("Use PdfStamper.getUnderContent() or PdfStamper.getOverContent()");
 1506       }
 1507       
 1508       /**
 1509        * Reads the OCProperties dictionary from the catalog of the existing document
 1510        * and fills the documentOCG, documentOCGorder and OCGRadioGroup variables in PdfWriter.
 1511        * Note that the original OCProperties of the existing document can contain more information.
 1512        * @since	2.1.2
 1513        */
 1514       protected void readOCProperties() {
 1515       	if (!documentOCG.isEmpty()) {
 1516       		return;
 1517       	}
 1518       	PdfDictionary dict = reader.getCatalog().getAsDict(PdfName.OCPROPERTIES);
 1519       	if (dict == null) {
 1520       		return;
 1521       	}
 1522       	PdfArray ocgs = dict.getAsArray(PdfName.OCGS);
 1523       	PdfIndirectReference ref;
 1524       	PdfLayer layer;
 1525       	HashMap ocgmap = new HashMap();
 1526       	for (Iterator i = ocgs.listIterator(); i.hasNext(); ) {
 1527       		ref = (PdfIndirectReference)i.next();
 1528       		layer = new PdfLayer(null);
 1529       		layer.setRef(ref);
 1530       		layer.setOnPanel(false);
 1531   			layer.merge((PdfDictionary)PdfReader.getPdfObject(ref));
 1532       		ocgmap.put(ref.toString(), layer);
 1533       	}
 1534       	PdfDictionary d = dict.getAsDict(PdfName.D);
 1535       	PdfArray off = d.getAsArray(PdfName.OFF);
 1536       	if (off != null) {
 1537       		for (Iterator i = off.listIterator(); i.hasNext(); ) {
 1538       			ref = (PdfIndirectReference)i.next();
 1539       			layer = (PdfLayer)ocgmap.get(ref.toString());
 1540       			layer.setOn(false);
 1541       		}
 1542       	}
 1543       	PdfArray order = d.getAsArray(PdfName.ORDER);
 1544       	if (order != null) {
 1545       		addOrder(null, order, ocgmap);
 1546       	}
 1547       	documentOCG.addAll(ocgmap.values());
 1548       	OCGRadioGroup = d.getAsArray(PdfName.RBGROUPS);
 1549       	OCGLocked = d.getAsArray(PdfName.LOCKED);
 1550       }
 1551       
 1552       /**
 1553        * Recursive method to reconstruct the documentOCGorder variable in the writer.
 1554        * @param	parent	a parent PdfLayer (can be null)
 1555        * @param	arr		an array possibly containing children for the parent PdfLayer
 1556        * @param	ocgmap	a HashMap with indirect reference Strings as keys and PdfLayer objects as values.
 1557        * @since	2.1.2
 1558        */
 1559       private void addOrder(PdfLayer parent, PdfArray arr, Map ocgmap) {
 1560       	PdfObject obj;
 1561       	PdfLayer layer;
 1562       	for (int i = 0; i < arr.size(); i++) {
 1563       		obj = arr.getPdfObject(i);
 1564       		if (obj.isIndirect()) {
 1565       			layer = (PdfLayer)ocgmap.get(obj.toString());
 1566       			layer.setOnPanel(true);
 1567       			registerLayer(layer);
 1568       			if (parent != null) {
 1569       				parent.addChild(layer);
 1570       			}
 1571       			if (arr.size() > i + 1 && arr.getPdfObject(i + 1).isArray()) {
 1572       				i++;
 1573       				addOrder(layer, (PdfArray)arr.getPdfObject(i), ocgmap);
 1574       			}
 1575       		}
 1576       		else if (obj.isArray()) {
 1577       			ArrayList sub = ((PdfArray)obj).getArrayList();
 1578       			if (sub.isEmpty()) return;
 1579       			obj = (PdfObject)sub.get(0);
 1580       			if (obj.isString()) {
 1581       				layer = new PdfLayer(sub.get(0).toString());
 1582       				layer.setOnPanel(true);
 1583       				registerLayer(layer);
 1584       				if (parent != null) {
 1585       					parent.addChild(layer);
 1586       				}
 1587       				PdfArray array = new PdfArray();
 1588       				for (Iterator j = sub.iterator(); j.hasNext(); ) {
 1589       					array.add((PdfObject)j.next());
 1590       				}
 1591       				addOrder(layer, array, ocgmap);
 1592       			}
 1593       			else {
 1594       				addOrder(parent, (PdfArray)obj, ocgmap);
 1595       			}
 1596       		}
 1597       	}
 1598       }
 1599       
 1600       /**
 1601        * Gets the PdfLayer objects in an existing document as a Map
 1602        * with the names/titles of the layers as keys.
 1603        * @return	a Map with all the PdfLayers in the document (and the name/title of the layer as key)
 1604        * @since	2.1.2
 1605        */
 1606       public Map getPdfLayers() {
 1607       	if (documentOCG.isEmpty()) {
 1608       		readOCProperties();
 1609       	}
 1610       	HashMap map = new HashMap();
 1611       	PdfLayer layer;
 1612       	String key;
 1613       	for (Iterator i = documentOCG.iterator(); i.hasNext(); ) {
 1614       		layer = (PdfLayer)i.next();
 1615       		if (layer.getTitle() == null) {
 1616       			key = layer.getAsString(PdfName.NAME).toString();
 1617       		}
 1618       		else {
 1619       			key = layer.getTitle();
 1620       		}
 1621       		if (map.containsKey(key)) {
 1622       			int seq = 2;
 1623       			String tmp = key + "(" + seq + ")";
 1624       			while (map.containsKey(tmp)) {
 1625       				seq++;
 1626       				tmp = key + "(" + seq + ")";
 1627       			}
 1628       			key = tmp;
 1629       		}
 1630   			map.put(key, layer);
 1631       	}
 1632       	return map;
 1633       }
 1634       
 1635       static class PageStamp {
 1636           
 1637           PdfDictionary pageN;
 1638           StampContent under;
 1639           StampContent over;
 1640           PageResources pageResources;
 1641           int replacePoint = 0;
 1642           
 1643           PageStamp(PdfStamperImp stamper, PdfReader reader, PdfDictionary pageN) {
 1644               this.pageN = pageN;
 1645               pageResources = new PageResources();
 1646               PdfDictionary resources = (PdfDictionary)PdfReader.getPdfObject(pageN.get(PdfName.RESOURCES));
 1647               pageResources.setOriginalResources(resources, stamper.namePtr);
 1648           }
 1649       }
 1650   }

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