KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > lowagie > text > pdf > PdfStamperImp


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 JavaDoc;
50 import java.io.OutputStream JavaDoc;
51 import java.util.ArrayList JavaDoc;
52 import java.util.HashMap JavaDoc;
53 import java.util.HashSet JavaDoc;
54 import java.util.Iterator JavaDoc;
55 import java.util.List JavaDoc;
56 import java.util.Map JavaDoc;
57
58 import com.lowagie.text.DocumentException;
59 import com.lowagie.text.ExceptionConverter;
60 import com.lowagie.text.Image;
61 import com.lowagie.text.Rectangle;
62 import com.lowagie.text.pdf.collection.PdfCollection;
63 import com.lowagie.text.pdf.interfaces.PdfViewerPreferences;
64 import com.lowagie.text.pdf.internal.PdfViewerPreferencesImp;
65
66 class PdfStamperImp extends PdfWriter {
67     HashMap JavaDoc readers2intrefs = new HashMap JavaDoc();
68     HashMap JavaDoc readers2file = new HashMap JavaDoc();
69     RandomAccessFileOrArray file;
70     PdfReader reader;
71     IntHashtable myXref = new IntHashtable();
72     /** Integer(page number) -> PageStamp */
73     HashMap JavaDoc pagesToContent = new HashMap JavaDoc();
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 boolean namedAsNames;
82     protected List JavaDoc newBookmarks;
83     protected HashSet JavaDoc partialFlattening = new HashSet JavaDoc();
84     protected boolean useVp = false;
85     protected PdfViewerPreferencesImp viewerPreferences = new PdfViewerPreferencesImp();
86     protected HashMap JavaDoc fieldTemplates = new HashMap JavaDoc();
87     protected boolean fieldsAdded = false;
88     protected int sigFlags = 0;
89     protected boolean append;
90     protected IntHashtable marked;
91     protected int initialXrefSize;
92     protected PdfAction openAction;
93     
94     /** Creates new PdfStamperImp.
95      * @param reader the read PDF
96      * @param os the output destination
97      * @param pdfVersion the new pdf version or '\0' to keep the same version as the original
98      * document
99      * @param append
100      * @throws DocumentException on error
101      * @throws IOException
102      */

103     PdfStamperImp(PdfReader reader, OutputStream JavaDoc os, char pdfVersion, boolean append) throws DocumentException, IOException JavaDoc {
104         super(new PdfDocument(), os);
105         if (!reader.isOpenedWithFullPermissions())
106             throw new IllegalArgumentException JavaDoc("PdfReader not opened with owner password");
107         if (reader.isTampered())
108             throw new DocumentException("The original document was reused. Read it again from file.");
109         reader.setTampered(true);
110         this.reader = reader;
111         file = reader.getSafeFile();
112         this.append = append;
113         if (append) {
114             if (reader.isRebuilt())
115                 throw new DocumentException("Append mode requires a document without errors even if recovery was possible.");
116             if (reader.isEncrypted())
117                 crypto = new PdfEncryption(reader.getDecrypt());
118             pdf_version.setAppendmode(true);
119             file.reOpen();
120             byte buf[] = new byte[8192];
121             int n;
122             while ((n = file.read(buf)) > 0)
123                 this.os.write(buf, 0, n);
124             file.close();
125             prevxref = reader.getLastXref();
126             reader.setAppendable(true);
127         }
128         else {
129             if (pdfVersion == 0)
130                 super.setPdfVersion(reader.getPdfVersion());
131             else
132                 super.setPdfVersion(pdfVersion);
133         }
134         super.open();
135         pdf.addWriter(this);
136         if (append) {
137             body.setRefnum(reader.getXrefSize());
138             marked = new IntHashtable();
139             if (reader.isNewXrefType())
140                 fullCompression = true;
141             if (reader.isHybridXref())
142                 fullCompression = false;
143         }
144         initialXrefSize = reader.getXrefSize();
145     }
146     
147     void close(HashMap JavaDoc moreInfo) throws IOException JavaDoc {
148         if (closed)
149             return;
150         if (useVp) {
151             reader.setViewerPreferences(viewerPreferences);
152             markUsed(reader.getTrailer().get(PdfName.ROOT));
153         }
154         if (flat)
155             flatFields();
156         if (flatFreeText)
157             flatFreeTextFields();
158         addFieldResources();
159         PdfDictionary acroForm = (PdfDictionary)PdfReader.getPdfObject(reader.getCatalog().get(PdfName.ACROFORM), reader.getCatalog());
160         if (acroFields != null && acroFields.getXfa().isChanged()) {
161             markUsed(acroForm);
162             if (!flat)
163                 acroFields.getXfa().setXfa(this);
164         }
165         if (sigFlags != 0) {
166             if (acroForm != null) {
167                 acroForm.put(PdfName.SIGFLAGS, new PdfNumber(sigFlags));
168                 markUsed(acroForm);
169             }
170         }
171         closed = true;
172         addSharedObjectsToBody();
173         setOutlines();
174         setJavaScript();
175         addFileAttachments();
176         PdfDictionary catalog = reader.getCatalog();
177         if (openAction != null) {
178             catalog.put(PdfName.OPENACTION, openAction);
179         }
180         byte[] altMetadata = xmpMetadata;
181         if (altMetadata == null) {
182             PdfObject xmpo = PdfReader.getPdfObject(catalog.get(PdfName.METADATA));
183             if (xmpo != null && xmpo.isStream()) {
184                 altMetadata = PdfReader.getStreamBytesRaw((PRStream)xmpo);
185                 PdfReader.killIndirect(xmpo);
186             }
187         }
188         // if there is XMP data to add: add it
189
if (altMetadata != null) {
190             PdfStream xmp = new PdfStream(altMetadata);
191             xmp.put(PdfName.TYPE, PdfName.METADATA);
192             xmp.put(PdfName.SUBTYPE, PdfName.XML);
193             if (crypto != null && !crypto.isMetadataEncrypted()) {
194                 PdfArray ar = new PdfArray();
195                 ar.add(PdfName.CRYPT);
196                 xmp.put(PdfName.FILTER, ar);
197             }
198             catalog.put(PdfName.METADATA, body.add(xmp).getIndirectReference());
199             markUsed(catalog);
200         }
201         PRIndirectReference iInfo = null;
202         try {
203             file.reOpen();
204             alterContents();
205             iInfo = (PRIndirectReference)reader.trailer.get(PdfName.INFO);
206             int skip = -1;
207             if (iInfo != null)
208                 skip = iInfo.getNumber();
209             int rootN = ((PRIndirectReference)reader.trailer.get(PdfName.ROOT)).getNumber();
210             if (append) {
211                 int keys[] = marked.getKeys();
212                 for (int k = 0; k < keys.length; ++k) {
213                     int j = keys[k];
214                     PdfObject obj = reader.getPdfObjectRelease(j);
215                     if (obj != null && skip != j && j < initialXrefSize) {
216                         addToBody(obj, j, j != rootN);
217                     }
218                 }
219                 for (int k = initialXrefSize; k < reader.getXrefSize(); ++k) {
220                     PdfObject obj = reader.getPdfObject(k);
221                     if (obj != null) {
222                         addToBody(obj, getNewObjectNumber(reader, k, 0));
223                     }
224                 }
225             }
226             else {
227                 for (int k = 1; k < reader.getXrefSize(); ++k) {
228                     PdfObject obj = reader.getPdfObjectRelease(k);
229                     if (obj != null && skip != k) {
230                         addToBody(obj, getNewObjectNumber(reader, k, 0), k != rootN);
231                     }
232                 }
233             }
234         }
235         finally {
236             try {
237                 file.close();
238             }
239             catch (Exception JavaDoc e) {
240                 // empty on purpose
241
}
242         }
243         PdfIndirectReference encryption = null;
244         PdfObject fileID = null;
245         if (crypto != null) {
246             if (append) {
247                 encryption = reader.getCryptoRef();
248             }
249             else {
250                 PdfIndirectObject encryptionObject = addToBody(crypto.getEncryptionDictionary(), false);
251                 encryption = encryptionObject.getIndirectReference();
252             }
253             fileID = crypto.getFileID();
254         }
255         else
256             fileID = PdfEncryption.createInfoId(PdfEncryption.createDocumentId());
257         PRIndirectReference iRoot = (PRIndirectReference)reader.trailer.get(PdfName.ROOT);
258         PdfIndirectReference root = new PdfIndirectReference(0, getNewObjectNumber(reader, iRoot.getNumber(), 0));
259         PdfIndirectReference info = null;
260         PdfDictionary oldInfo = (PdfDictionary)PdfReader.getPdfObject(iInfo);
261         PdfDictionary newInfo = new PdfDictionary();
262         if (oldInfo != null) {
263             for (Iterator JavaDoc i = oldInfo.getKeys().iterator(); i.hasNext();) {
264                 PdfName key = (PdfName)i.next();
265                 PdfObject value = PdfReader.getPdfObject(oldInfo.get(key));
266                 newInfo.put(key, value);
267             }
268         }
269         if (moreInfo != null) {
270             for (Iterator JavaDoc i = moreInfo.entrySet().iterator(); i.hasNext();) {
271                 Map.Entry JavaDoc entry = (Map.Entry JavaDoc) i.next();
272                 String JavaDoc key = (String JavaDoc) entry.getKey();
273                 PdfName keyName = new PdfName(key);
274                 String JavaDoc value = (String JavaDoc) entry.getValue();
275                 if (value == null)
276                     newInfo.remove(keyName);
277                 else
278                     newInfo.put(keyName, new PdfString(value, PdfObject.TEXT_UNICODE));
279             }
280         }
281         if (append) {
282             if (iInfo == null)
283                 info = addToBody(newInfo, false).getIndirectReference();
284             else
285                 info = addToBody(newInfo, iInfo.getNumber(), false).getIndirectReference();
286         }
287         else {
288             if (!newInfo.getKeys().isEmpty())
289                 info = addToBody(newInfo, false).getIndirectReference();
290         }
291         // write the cross-reference table of the body
292
body.writeCrossReferenceTable(os, root, info, encryption, fileID, prevxref);
293         if (fullCompression) {
294             os.write(getISOBytes("startxref\n"));
295             os.write(getISOBytes(String.valueOf(body.offset())));
296             os.write(getISOBytes("\n%%EOF\n"));
297         }
298         else {
299             PdfTrailer trailer = new PdfTrailer(body.size(),
300             body.offset(),
301             root,
302             info,
303             encryption,
304             fileID, prevxref);
305             trailer.toPdf(this, os);
306         }
307         os.flush();
308         if (isCloseStream())
309             os.close();
310         reader.close();
311     }
312     
313     void applyRotation(PdfDictionary pageN, ByteBuffer out) {
314         if (!rotateContents)
315             return;
316         Rectangle page = reader.getPageSizeWithRotation(pageN);
317         int rotation = page.getRotation();
318         switch (rotation) {
319             case 90:
320                 out.append(PdfContents.ROTATE90);
321                 out.append(page.getTop());
322                 out.append(' ').append('0').append(PdfContents.ROTATEFINAL);
323                 break;
324             case 180:
325                 out.append(PdfContents.ROTATE180);
326                 out.append(page.getRight());
327                 out.append(' ');
328                 out.append(page.getTop());
329                 out.append(PdfContents.ROTATEFINAL);
330                 break;
331             case 270:
332                 out.append(PdfContents.ROTATE270);
333                 out.append('0').append(' ');
334                 out.append(page.getRight());
335                 out.append(PdfContents.ROTATEFINAL);
336                 break;
337         }
338     }
339     
340     void alterContents() throws IOException JavaDoc {
341         for (Iterator JavaDoc i = pagesToContent.values().iterator(); i.hasNext();) {
342             PageStamp ps = (PageStamp)i.next();
343             PdfDictionary pageN = ps.pageN;
344             markUsed(pageN);
345             PdfArray ar = null;
346             PdfObject content = PdfReader.getPdfObject(pageN.get(PdfName.CONTENTS), pageN);
347             if (content == null) {
348                 ar = new PdfArray();
349                 pageN.put(PdfName.CONTENTS, ar);
350             }
351             else if (content.isArray()) {
352                 ar = (PdfArray)content;
353                 markUsed(ar);
354             }
355             else if (content.isStream()) {
356                 ar = new PdfArray();
357                 ar.add(pageN.get(PdfName.CONTENTS));
358                 pageN.put(PdfName.CONTENTS, ar);
359             }
360             else {
361                 ar = new PdfArray();
362                 pageN.put(PdfName.CONTENTS, ar);
363             }
364             ByteBuffer out = new ByteBuffer();
365             if (ps.under != null) {
366                 out.append(PdfContents.SAVESTATE);
367                 applyRotation(pageN, out);
368                 out.append(ps.under.getInternalBuffer());
369                 out.append(PdfContents.RESTORESTATE);
370             }
371             if (ps.over != null)
372                 out.append(PdfContents.SAVESTATE);
373             PdfStream stream = new PdfStream(out.toByteArray());
374             try{stream.flateCompress();}catch(Exception JavaDoc e){throw new ExceptionConverter(e);}
375             ar.addFirst(addToBody(stream).getIndirectReference());
376             out.reset();
377             if (ps.over != null) {
378                 out.append(' ');
379                 out.append(PdfContents.RESTORESTATE);
380                 out.append(PdfContents.SAVESTATE);
381                 applyRotation(pageN, out);
382                 out.append(ps.over.getInternalBuffer());
383                 out.append(PdfContents.RESTORESTATE);
384                 stream = new PdfStream(out.toByteArray());
385                 try{stream.flateCompress();}catch(Exception JavaDoc e){throw new ExceptionConverter(e);}
386                 ar.add(addToBody(stream).getIndirectReference());
387             }
388             alterResources(ps);
389         }
390     }
391
392     void alterResources(PageStamp ps) {
393         ps.pageN.put(PdfName.RESOURCES, ps.pageResources.getResources());
394     }
395     
396     protected int getNewObjectNumber(PdfReader reader, int number, int generation) {
397         IntHashtable ref = (IntHashtable)readers2intrefs.get(reader);
398         if (ref != null) {
399             int n = ref.get(number);
400             if (n == 0) {
401                 n = getIndirectReferenceNumber();
402                 ref.put(number, n);
403             }
404             return n;
405         }
406         if (currentPdfReaderInstance == null) {
407             if (append && number < initialXrefSize)
408                 return number;
409             int n = myXref.get(number);
410             if (n == 0) {
411                 n = getIndirectReferenceNumber();
412                 myXref.put(number, n);
413             }
414             return n;
415         }
416         else
417             return currentPdfReaderInstance.getNewObjectNumber(number, generation);
418     }
419     
420     RandomAccessFileOrArray getReaderFile(PdfReader reader) {
421         if (readers2intrefs.containsKey(reader)) {
422             RandomAccessFileOrArray raf = (RandomAccessFileOrArray)readers2file.get(reader);
423             if (raf != null)
424                 return raf;
425             return reader.getSafeFile();
426         }
427         if (currentPdfReaderInstance == null)
428             return file;
429         else
430             return currentPdfReaderInstance.getReaderFile();
431     }
432     
433     /**
434      * @param reader
435      * @param openFile
436      * @throws IOException
437      */

438     public void registerReader(PdfReader reader, boolean openFile) throws IOException JavaDoc {
439         if (readers2intrefs.containsKey(reader))
440             return;
441         readers2intrefs.put(reader, new IntHashtable());
442         if (openFile) {
443             RandomAccessFileOrArray raf = reader.getSafeFile();
444             readers2file.put(reader, raf);
445             raf.reOpen();
446         }
447     }
448     
449     /**
450      * @param reader
451      */

452     public void unRegisterReader(PdfReader reader) {
453         if (!readers2intrefs.containsKey(reader))
454             return;
455         readers2intrefs.remove(reader);
456         RandomAccessFileOrArray raf = (RandomAccessFileOrArray)readers2file.get(reader);
457         if (raf == null)
458             return;
459         readers2file.remove(reader);
460         try{raf.close();}catch(Exception JavaDoc e){}
461     }
462
463     static void findAllObjects(PdfReader reader, PdfObject obj, IntHashtable hits) {
464         if (obj == null)
465             return;
466         switch (obj.type()) {
467             case PdfObject.INDIRECT:
468                 PRIndirectReference iref = (PRIndirectReference)obj;
469                 if (reader != iref.getReader())
470                     return;
471                 if (hits.containsKey(iref.getNumber()))
472                     return;
473                 hits.put(iref.getNumber(), 1);
474                 findAllObjects(reader, PdfReader.getPdfObject(obj), hits);
475                 return;
476             case PdfObject.ARRAY:
477                 ArrayList JavaDoc lst = ((PdfArray)obj).getArrayList();
478                 for (int k = 0; k < lst.size(); ++k) {
479                     findAllObjects(reader, (PdfObject)lst.get(k), hits);
480                 }
481                 return;
482             case PdfObject.DICTIONARY:
483             case PdfObject.STREAM:
484                 PdfDictionary dic = (PdfDictionary)obj;
485                 for (Iterator JavaDoc it = dic.getKeys().iterator(); it.hasNext();) {
486                     PdfName name = (PdfName)it.next();
487                     findAllObjects(reader, dic.get(name), hits);
488                 }
489                 return;
490         }
491     }
492     
493     /**
494      * @param fdf
495      * @throws IOException
496      */

497     public void addComments(FdfReader fdf) throws IOException JavaDoc{
498         if (readers2intrefs.containsKey(fdf))
499             return;
500         PdfDictionary catalog = fdf.getCatalog();
501         catalog = (PdfDictionary)PdfReader.getPdfObject(catalog.get(PdfName.FDF));
502         if (catalog == null)
503             return;
504         PdfArray annots = (PdfArray)PdfReader.getPdfObject(catalog.get(PdfName.ANNOTS));
505         if (annots == null || annots.size() == 0)
506             return;
507         registerReader(fdf, false);
508         IntHashtable hits = new IntHashtable();
509         HashMap JavaDoc irt = new HashMap JavaDoc();
510         ArrayList JavaDoc an = new ArrayList JavaDoc();
511         ArrayList JavaDoc ar = annots.getArrayList();
512         for (int k = 0; k < ar.size(); ++k) {
513             PdfObject obj = (PdfObject)ar.get(k);
514             PdfDictionary annot = (PdfDictionary)PdfReader.getPdfObject(obj);
515             PdfNumber page = (PdfNumber)PdfReader.getPdfObject(annot.get(PdfName.PAGE));
516             if (page == null || page.intValue() >= reader.getNumberOfPages())
517                 continue;
518             findAllObjects(fdf, obj, hits);
519             an.add(obj);
520             if (obj.type() == PdfObject.INDIRECT) {
521                 PdfObject nm = PdfReader.getPdfObject(annot.get(PdfName.NM));
522                 if (nm != null && nm.type() == PdfObject.STRING)
523                     irt.put(nm.toString(), obj);
524             }
525         }
526         int arhits[] = hits.getKeys();
527         for (int k = 0; k < arhits.length; ++k) {
528             int n = arhits[k];
529             PdfObject obj = fdf.getPdfObject(n);
530             if (obj.type() == PdfObject.DICTIONARY) {
531                 PdfObject str = PdfReader.getPdfObject(((PdfDictionary)obj).get(PdfName.IRT));
532                 if (str != null && str.type() == PdfObject.STRING) {
533                    PdfObject i = (PdfObject)irt.get(str.toString());
534                    if (i != null) {
535                        PdfDictionary dic2 = new PdfDictionary();
536                        dic2.merge((PdfDictionary)obj);
537                        dic2.put(PdfName.IRT, i);
538                        obj = dic2;
539                    }
540                 }
541             }
542             addToBody(obj, getNewObjectNumber(fdf, n, 0));
543         }
544         for (int k = 0; k < an.size(); ++k) {
545             PdfObject obj = (PdfObject)an.get(k);
546             PdfDictionary annot = (PdfDictionary)PdfReader.getPdfObject(obj);
547             PdfNumber page = (PdfNumber)PdfReader.getPdfObject(annot.get(PdfName.PAGE));
548             PdfDictionary dic = reader.getPageN(page.intValue() + 1);
549             PdfArray annotsp = (PdfArray)PdfReader.getPdfObject(dic.get(PdfName.ANNOTS), dic);
550             if (annotsp == null) {
551                 annotsp = new PdfArray();
552                 dic.put(PdfName.ANNOTS, annotsp);
553                 markUsed(dic);
554             }
555             markUsed(annotsp);
556             annotsp.add(obj);
557         }
558     }
559     
560     PageStamp getPageStamp(int pageNum) {
561         PdfDictionary pageN = reader.getPageN(pageNum);
562         PageStamp ps = (PageStamp)pagesToContent.get(pageN);
563         if (ps == null) {
564             ps = new PageStamp(this, reader, pageN);
565             pagesToContent.put(pageN, ps);
566         }
567         return ps;
568     }
569     
570     PdfContentByte getUnderContent(int pageNum) {
571         if (pageNum < 1 || pageNum > reader.getNumberOfPages())
572             return null;
573         PageStamp ps = getPageStamp(pageNum);
574         if (ps.under == null)
575             ps.under = new StampContent(this, ps);
576         return ps.under;
577     }
578     
579     PdfContentByte getOverContent(int pageNum) {
580         if (pageNum < 1 || pageNum > reader.getNumberOfPages())
581             return null;
582         PageStamp ps = getPageStamp(pageNum);
583         if (ps.over == null)
584             ps.over = new StampContent(this, ps);
585         return ps.over;
586     }
587     
588     void correctAcroFieldPages(int page) {
589         if (acroFields == null)
590             return;
591         if (page > reader.getNumberOfPages())
592             return;
593         HashMap JavaDoc fields = acroFields.getFields();
594         for (Iterator JavaDoc it = fields.values().iterator(); it.hasNext();) {
595             AcroFields.Item item = (AcroFields.Item)it.next();
596             ArrayList JavaDoc pages = item.page;
597             for (int k = 0; k < pages.size(); ++k) {
598                 int p = ((Integer JavaDoc)pages.get(k)).intValue();
599                 if (p >= page)
600                     pages.set(k, new Integer JavaDoc(p + 1));
601             }
602         }
603     }
604     
605     void insertPage(int pageNumber, Rectangle mediabox) {
606         Rectangle media = new Rectangle(mediabox);
607         int rotation = media.getRotation() % 360;
608         PdfDictionary page = new PdfDictionary(PdfName.PAGE);
609         PdfDictionary resources = new PdfDictionary();
610         PdfArray procset = new PdfArray();
611         procset.add(PdfName.PDF);
612         procset.add(PdfName.TEXT);
613         procset.add(PdfName.IMAGEB);
614         procset.add(PdfName.IMAGEC);
615         procset.add(PdfName.IMAGEI);
616         resources.put(PdfName.PROCSET, procset);
617         page.put(PdfName.RESOURCES, resources);
618         page.put(PdfName.ROTATE, new PdfNumber(rotation));
619         page.put(PdfName.MEDIABOX, new PdfRectangle(media, rotation));
620         PRIndirectReference pref = reader.addPdfObject(page);
621         PdfDictionary parent;
622         PRIndirectReference parentRef;
623         if (pageNumber > reader.getNumberOfPages()) {
624             PdfDictionary lastPage = reader.getPageNRelease(reader.getNumberOfPages());
625             parentRef = (PRIndirectReference)lastPage.get(PdfName.PARENT);
626             parentRef = new PRIndirectReference(reader, parentRef.getNumber());
627             parent = (PdfDictionary)PdfReader.getPdfObject(parentRef);
628             PdfArray kids = (PdfArray)PdfReader.getPdfObject(parent.get(PdfName.KIDS), parent);
629             kids.add(pref);
630             markUsed(kids);
631             reader.pageRefs.insertPage(pageNumber, pref);
632         }
633         else {
634             if (pageNumber < 1)
635                 pageNumber = 1;
636             PdfDictionary firstPage = reader.getPageN(pageNumber);
637             PRIndirectReference firstPageRef = reader.getPageOrigRef(pageNumber);
638             reader.releasePage(pageNumber);
639             parentRef = (PRIndirectReference)firstPage.get(PdfName.PARENT);
640             parentRef = new PRIndirectReference(reader, parentRef.getNumber());
641             parent = (PdfDictionary)PdfReader.getPdfObject(parentRef);
642             PdfArray kids = (PdfArray)PdfReader.getPdfObject(parent.get(PdfName.KIDS), parent);
643             ArrayList JavaDoc ar = kids.getArrayList();
644             int len = ar.size();
645             int num = firstPageRef.getNumber();
646             for (int k = 0; k < len; ++k) {
647                 PRIndirectReference cur = (PRIndirectReference)ar.get(k);
648                 if (num == cur.getNumber()) {
649                     ar.add(k, pref);
650                     break;
651                 }
652             }
653             if (len == ar.size())
654                 throw new RuntimeException JavaDoc("Internal inconsistence.");
655             markUsed(kids);
656             reader.pageRefs.insertPage(pageNumber, pref);
657             correctAcroFieldPages(pageNumber);
658         }
659         page.put(PdfName.PARENT, parentRef);
660         while (parent != null) {
661             markUsed(parent);
662             PdfNumber count = (PdfNumber)PdfReader.getPdfObjectRelease(parent.get(PdfName.COUNT));
663             parent.put(PdfName.COUNT, new PdfNumber(count.intValue() + 1));
664             parent = (PdfDictionary)PdfReader.getPdfObject(parent.get(PdfName.PARENT));
665         }
666     }
667     
668     /** Getter for property rotateContents.
669      * @return Value of property rotateContents.
670      *
671      */

672     boolean isRotateContents() {
673         return this.rotateContents;
674     }
675     
676     /** Setter for property rotateContents.
677      * @param rotateContents New value of property rotateContents.
678      *
679      */

680     void setRotateContents(boolean rotateContents) {
681         this.rotateContents = rotateContents;
682     }
683     
684     boolean isContentWritten() {
685         return body.size() > 1;
686     }
687     
688     AcroFields getAcroFields() {
689         if (acroFields == null) {
690             acroFields = new AcroFields(reader, this);
691         }
692         return acroFields;
693     }
694
695     void setFormFlattening(boolean flat) {
696         this.flat = flat;
697     }
698     
699     void setFreeTextFlattening(boolean flat) {
700         this.flatFreeText = flat;
701     }
702     
703     boolean partialFormFlattening(String JavaDoc name) {
704         getAcroFields();
705         if (acroFields.getXfa().isXfaPresent())
706             throw new UnsupportedOperationException JavaDoc("Partial form flattening is not supported with XFA forms.");
707         if (!acroFields.getFields().containsKey(name))
708             return false;
709         partialFlattening.add(name);
710         return true;
711     }
712     
713     void flatFields() {
714         if (append)
715             throw new IllegalArgumentException JavaDoc("Field flattening is not supported in append mode.");
716         getAcroFields();
717         HashMap JavaDoc fields = acroFields.getFields();
718         if (fieldsAdded && partialFlattening.isEmpty()) {
719             for (Iterator JavaDoc i = fields.keySet().iterator(); i.hasNext();) {
720                 partialFlattening.add(i.next());
721             }
722         }
723         PdfDictionary acroForm = (PdfDictionary)PdfReader.getPdfObject(reader.getCatalog().get(PdfName.ACROFORM));
724         ArrayList JavaDoc acroFds = null;
725         if (acroForm != null) {
726             PdfArray array = (PdfArray)PdfReader.getPdfObject(acroForm.get(PdfName.FIELDS), acroForm);
727             if (array != null)
728                 acroFds = array.getArrayList();
729         }
730         for (Iterator JavaDoc i = fields.entrySet().iterator(); i.hasNext();) {
731             Map.Entry JavaDoc entry = (Map.Entry JavaDoc) i.next();
732             String JavaDoc name = (String JavaDoc) entry.getKey();
733             if (!partialFlattening.isEmpty() && !partialFlattening.contains(name))
734                 continue;
735             AcroFields.Item item = (AcroFields.Item) entry.getValue();
736             for (int k = 0; k < item.merged.size(); ++k) {
737                 PdfDictionary merged = (PdfDictionary)item.merged.get(k);
738                 PdfNumber ff = (PdfNumber)PdfReader.getPdfObject(merged.get(PdfName.F));
739                 int flags = 0;
740                 if (ff != null)
741                     flags = ff.intValue();
742                 int page = ((Integer JavaDoc)item.page.get(k)).intValue();
743                 PdfDictionary appDic = (PdfDictionary)PdfReader.getPdfObject(merged.get(PdfName.AP));
744                 if (appDic != null && (flags & PdfFormField.FLAGS_PRINT) != 0 && (flags & PdfFormField.FLAGS_HIDDEN) == 0) {
745                     PdfObject obj = appDic.get(PdfName.N);
746                     PdfAppearance app = null;
747                     if (obj != null) {
748                         PdfObject objReal = PdfReader.getPdfObject(obj);
749                         if (obj instanceof PdfIndirectReference && !obj.isIndirect())
750                             app = new PdfAppearance((PdfIndirectReference)obj);
751                         else if (objReal instanceof PdfStream) {
752                             ((PdfDictionary)objReal).put(PdfName.SUBTYPE, PdfName.FORM);
753                             app = new PdfAppearance((PdfIndirectReference)obj);
754                         }
755                         else {
756                             if (objReal != null && objReal.isDictionary()) {
757                                 PdfName as = (PdfName)PdfReader.getPdfObject(merged.get(PdfName.AS));
758                                 if (as != null) {
759                                     PdfIndirectReference iref = (PdfIndirectReference)((PdfDictionary)objReal).get(as);
760                                     if (iref != null) {
761                                         app = new PdfAppearance(iref);
762                                         if (iref.isIndirect()) {
763                                             objReal = PdfReader.getPdfObject(iref);
764                                             ((PdfDictionary)objReal).put(PdfName.SUBTYPE, PdfName.FORM);
765                                         }
766                                     }
767                                 }
768                             }
769                         }
770                     }
771                     if (app != null) {
772                         Rectangle box = PdfReader.getNormalizedRectangle((PdfArray)PdfReader.getPdfObject(merged.get(PdfName.RECT)));
773                         PdfContentByte cb = getOverContent(page);
774                         cb.setLiteral("Q ");
775                         cb.addTemplate(app, box.getLeft(), box.getBottom());
776                         cb.setLiteral("q ");
777                     }
778                 }
779                 if (partialFlattening.isEmpty())
780                     continue;
781                 PdfDictionary pageDic = reader.getPageN(page);
782                 PdfArray annots = (PdfArray)PdfReader.getPdfObject(pageDic.get(PdfName.ANNOTS));
783                 if (annots == null)
784                     continue;
785                 ArrayList JavaDoc ar = annots.getArrayList();
786                 for (int idx = 0; idx < ar.size(); ++idx) {
787                     PdfObject ran = (PdfObject)ar.get(idx);
788                     if (!ran.isIndirect())
789                         continue;
790                     PdfObject ran2 = (PdfObject)item.widget_refs.get(k);
791                     if (!ran2.isIndirect())
792                         continue;
793                     if (((PRIndirectReference)ran).getNumber() == ((PRIndirectReference)ran2).getNumber()) {
794                         ar.remove(idx--);
795                         PRIndirectReference wdref = (PRIndirectReference)ran2;
796                         while (true) {
797                             PdfDictionary wd = (PdfDictionary)PdfReader.getPdfObject(wdref);
798                             PRIndirectReference parentRef = (PRIndirectReference)wd.get(PdfName.PARENT);
799                             PdfReader.killIndirect(wdref);
800                             if (parentRef == null) { // reached AcroForm
801
for (int fr = 0; fr < acroFds.size(); ++fr) {
802                                     PdfObject h = (PdfObject)acroFds.get(fr);
803                                     if (h.isIndirect() && ((PRIndirectReference)h).getNumber() == wdref.getNumber()) {
804                                         acroFds.remove(fr);
805                                         --fr;
806                                     }
807                                 }
808                                 break;
809                             }
810                             PdfDictionary parent = (PdfDictionary)PdfReader.getPdfObject(parentRef);
811                             PdfArray kids = (PdfArray)PdfReader.getPdfObject(parent.get(PdfName.KIDS));
812                             ArrayList JavaDoc kar = kids.getArrayList();
813                             for (int fr = 0; fr < kar.size(); ++fr) {
814                                 PdfObject h = (PdfObject)kar.get(fr);
815                                 if (h.isIndirect() && ((PRIndirectReference)h).getNumber() == wdref.getNumber()) {
816                                     kar.remove(fr);
817                                     --fr;
818                                 }
819                             }
820                             if (!kar.isEmpty())
821                                 break;
822                             wdref = parentRef;
823                         }
824                     }
825                 }
826                 if (ar.isEmpty()) {
827                     PdfReader.killIndirect(pageDic.get(PdfName.ANNOTS));
828                     pageDic.remove(PdfName.ANNOTS);
829                 }
830             }
831         }
832         if (!fieldsAdded && partialFlattening.isEmpty()) {
833             for (int page = 1; page <= reader.getNumberOfPages(); ++page) {
834                 PdfDictionary pageDic = reader.getPageN(page);
835                 PdfArray annots = (PdfArray)PdfReader.getPdfObject(pageDic.get(PdfName.ANNOTS));
836                 if (annots == null)
837                     continue;
838                 ArrayList JavaDoc ar = annots.getArrayList();
839                 for (int idx = 0; idx < ar.size(); ++idx) {
840                     PdfObject annoto = PdfReader.getPdfObject((PdfObject)ar.get(idx));
841                         if ((annoto instanceof PdfIndirectReference) && !annoto.isIndirect())
842                             continue;
843                     PdfDictionary annot = (PdfDictionary)annoto;
844                     if (PdfName.WIDGET.equals(annot.get(PdfName.SUBTYPE))) {
845                         ar.remove(idx);
846                         --idx;
847                     }
848                 }
849                 if (ar.isEmpty()) {
850                     PdfReader.killIndirect(pageDic.get(PdfName.ANNOTS));
851                     pageDic.remove(PdfName.ANNOTS);
852                 }
853             }
854             eliminateAcroformObjects();
855         }
856     }
857
858     void eliminateAcroformObjects() {
859         PdfObject acro = reader.getCatalog().get(PdfName.ACROFORM);
860         if (acro == null)
861             return;
862         PdfDictionary acrodic = (PdfDictionary)PdfReader.getPdfObject(acro);
863         reader.killXref(acrodic.get(PdfName.XFA));
864         acrodic.remove(PdfName.XFA);
865         PdfObject iFields = acrodic.get(PdfName.FIELDS);
866         if (iFields != null) {
867             PdfDictionary kids = new PdfDictionary();
868             kids.put(PdfName.KIDS, iFields);
869             sweepKids(kids);
870             PdfReader.killIndirect(iFields);
871             acrodic.put(PdfName.FIELDS, new PdfArray());
872         }
873 // PdfReader.killIndirect(acro);
874
// reader.getCatalog().remove(PdfName.ACROFORM);
875
}
876     
877     void sweepKids(PdfObject obj) {
878         PdfObject oo = PdfReader.killIndirect(obj);
879         if (oo == null || !oo.isDictionary())
880             return;
881         PdfDictionary dic = (PdfDictionary)oo;
882         PdfArray kids = (PdfArray)PdfReader.killIndirect(dic.get(PdfName.KIDS));
883         if (kids == null)
884             return;
885         ArrayList JavaDoc ar = kids.getArrayList();
886         for (int k = 0; k < ar.size(); ++k) {
887             sweepKids((PdfObject)ar.get(k));
888         }
889     }
890     
891     private void flatFreeTextFields()
892     {
893         if (append)
894             throw new IllegalArgumentException JavaDoc("FreeText flattening is not supported in append mode.");
895         
896         for (int page = 1; page <= reader.getNumberOfPages(); ++page)
897         {
898             PdfDictionary pageDic = reader.getPageN(page);
899             PdfArray annots = (PdfArray)PdfReader.getPdfObject(pageDic.get(PdfName.ANNOTS));
900             if (annots == null)
901                 continue;
902             ArrayList JavaDoc ar = annots.getArrayList();
903             for (int idx = 0; idx < ar.size(); ++idx)
904             {
905                 PdfObject annoto = PdfReader.getPdfObject((PdfObject)ar.get(idx));
906                 if ((annoto instanceof PdfIndirectReference) && !annoto.isIndirect())
907                     continue;
908                 
909                 PdfDictionary annDic = (PdfDictionary)annoto;
910                 if (!((PdfName)annDic.get(PdfName.SUBTYPE)).equals(PdfName.FREETEXT))
911                     continue;
912                 PdfNumber ff = (PdfNumber)PdfReader.getPdfObject(annDic.get(PdfName.F));
913                 int flags = (ff != null) ? ff.intValue() : 0;
914             
915                 if ( (flags & PdfFormField.FLAGS_PRINT) != 0 && (flags & PdfFormField.FLAGS_HIDDEN) == 0)
916                 {
917                     PdfObject obj1 = annDic.get(PdfName.AP);
918                     if (obj1 == null)
919                         continue;
920                     PdfDictionary appDic = (obj1 instanceof PdfIndirectReference) ?
921                             (PdfDictionary) PdfReader.getPdfObject(obj1) : (PdfDictionary) obj1;
922                     PdfObject obj = appDic.get(PdfName.N);
923                     PdfAppearance app = null;
924                     PdfObject objReal = PdfReader.getPdfObject(obj);
925                     
926                     if (obj instanceof PdfIndirectReference && !obj.isIndirect())
927                         app = new PdfAppearance((PdfIndirectReference)obj);
928                     else if (objReal instanceof PdfStream)
929                     {
930                         ((PdfDictionary)objReal).put(PdfName.SUBTYPE, PdfName.FORM);
931                         app = new PdfAppearance((PdfIndirectReference)obj);
932                     }
933                     else
934                     {
935                         if (objReal.isDictionary())
936                         {
937                             PdfName as_p = (PdfName)PdfReader.getPdfObject(appDic.get(PdfName.AS));
938                             if (as_p != null)
939                             {
940                                 PdfIndirectReference iref = (PdfIndirectReference)((PdfDictionary)objReal).get(as_p);
941                                 if (iref != null)
942                                 {
943                                     app = new PdfAppearance(iref);
944                                     if (iref.isIndirect())
945                                     {
946                                         objReal = PdfReader.getPdfObject(iref);
947                                         ((PdfDictionary)objReal).put(PdfName.SUBTYPE, PdfName.FORM);
948                                     }
949                                 }
950                             }
951                         }
952                     }
953                     if (app != null)
954                     {
955                         Rectangle box = PdfReader.getNormalizedRectangle((PdfArray)PdfReader.getPdfObject(annDic.get(PdfName.RECT)));
956                         PdfContentByte cb = getOverContent(page);
957                         cb.setLiteral("Q ");
958                         cb.addTemplate(app, box.getLeft(), box.getBottom());
959                         cb.setLiteral("q ");
960                     }
961                 }
962             }
963             for (int idx = 0; idx < ar.size(); ++idx)
964             {
965                 PdfObject annoto = PdfReader.getPdfObject((PdfObject)ar.get(idx));
966                 if (annoto != null && annoto.isDictionary())
967                 {
968                     PdfDictionary annot = (PdfDictionary)annoto;
969                     if (PdfName.FREETEXT.equals(annot.get(PdfName.SUBTYPE)))
970                     {
971                         ar.remove(idx);
972                         --idx;
973                     }
974                 }
975             }
976             if (ar.isEmpty())
977             {
978                 PdfReader.killIndirect(pageDic.get(PdfName.ANNOTS));
979                 pageDic.remove(PdfName.ANNOTS);
980             }
981         }
982     }
983     
984     /**
985      * @see com.lowagie.text.pdf.PdfWriter#getPageReference(int)
986      */

987     public PdfIndirectReference getPageReference(int page) {
988         PdfIndirectReference ref = reader.getPageOrigRef(page);
989         if (ref == null)
990             throw new IllegalArgumentException JavaDoc("Invalid page number " + page);
991         return ref;
992     }
993     
994     /**
995      * @see com.lowagie.text.pdf.PdfWriter#addAnnotation(com.lowagie.text.pdf.PdfAnnotation)
996      */

997     public void addAnnotation(PdfAnnotation annot) {
998         throw new RuntimeException JavaDoc("Unsupported in this context. Use PdfStamper.addAnnotation()");
999     }
1000    
1001    void addDocumentField(PdfIndirectReference ref) {
1002        PdfDictionary catalog = reader.getCatalog();
1003        PdfDictionary acroForm = (PdfDictionary)PdfReader.getPdfObject(catalog.get(PdfName.ACROFORM), catalog);
1004        if (acroForm == null) {
1005            acroForm = new PdfDictionary();
1006            catalog.put(PdfName.ACROFORM, acroForm);
1007            markUsed(catalog);
1008        }
1009        PdfArray fields = (PdfArray)PdfReader.getPdfObject(acroForm.get(PdfName.FIELDS), acroForm);
1010        if (fields == null) {
1011            fields = new PdfArray();
1012            acroForm.put(PdfName.FIELDS, fields);
1013            markUsed(acroForm);
1014        }
1015        if (!acroForm.contains(PdfName.DA)) {
1016            acroForm.put(PdfName.DA, new PdfString("/Helv 0 Tf 0 g "));
1017            markUsed(acroForm);
1018        }
1019        fields.add(ref);
1020        markUsed(fields);
1021    }
1022    
1023    void addFieldResources() throws IOException JavaDoc {
1024        if (fieldTemplates.isEmpty())
1025            return;
1026        PdfDictionary catalog = reader.getCatalog();
1027        PdfDictionary acroForm = (PdfDictionary)PdfReader.getPdfObject(catalog.get(PdfName.ACROFORM), catalog);
1028        if (acroForm == null) {
1029            acroForm = new PdfDictionary();
1030            catalog.put(PdfName.ACROFORM, acroForm);
1031            markUsed(catalog);
1032        }
1033        PdfDictionary dr = (PdfDictionary)PdfReader.getPdfObject(acroForm.get(PdfName.DR), acroForm);
1034        if (dr == null) {
1035            dr = new PdfDictionary();
1036            acroForm.put(PdfName.DR, dr);
1037            markUsed(acroForm);
1038        }
1039        markUsed(dr);
1040        for (Iterator JavaDoc it = fieldTemplates.keySet().iterator(); it.hasNext();) {
1041            PdfTemplate template = (PdfTemplate)it.next();
1042            PdfFormField.mergeResources(dr, (PdfDictionary)template.getResources(), this);
1043        }
1044        if (dr.get(PdfName.ENCODING) == null)
1045            dr.put(PdfName.ENCODING, PdfName.WIN_ANSI_ENCODING);
1046        PdfDictionary fonts = (PdfDictionary)PdfReader.getPdfObject(dr.get(PdfName.FONT));
1047        if (fonts == null) {
1048            fonts = new PdfDictionary();
1049            dr.put(PdfName.FONT, fonts);
1050        }
1051        if (!fonts.contains(PdfName.HELV)) {
1052            PdfDictionary dic = new PdfDictionary(PdfName.FONT);
1053            dic.put(PdfName.BASEFONT, PdfName.HELVETICA);
1054            dic.put(PdfName.ENCODING, PdfName.WIN_ANSI_ENCODING);
1055            dic.put(PdfName.NAME, PdfName.HELV);
1056            dic.put(PdfName.SUBTYPE, PdfName.TYPE1);
1057            fonts.put(PdfName.HELV, addToBody(dic).getIndirectReference());
1058        }
1059        if (!fonts.contains(PdfName.ZADB)) {
1060            PdfDictionary dic = new PdfDictionary(PdfName.FONT);
1061            dic.put(PdfName.BASEFONT, PdfName.ZAPFDINGBATS);
1062            dic.put(PdfName.NAME, PdfName.ZADB);
1063            dic.put(PdfName.SUBTYPE, PdfName.TYPE1);
1064            fonts.put(PdfName.ZADB, addToBody(dic).getIndirectReference());
1065        }
1066        if (acroForm.get(PdfName.DA) == null) {
1067            acroForm.put(PdfName.DA, new PdfString("/Helv 0 Tf 0 g "));
1068            markUsed(acroForm);
1069        }
1070    }
1071    
1072    void expandFields(PdfFormField field, ArrayList JavaDoc allAnnots) {
1073        allAnnots.add(field);
1074        ArrayList JavaDoc kids = field.getKids();
1075        if (kids != null) {
1076            for (int k = 0; k < kids.size(); ++k)
1077                expandFields((PdfFormField)kids.get(k), allAnnots);
1078        }
1079    }
1080
1081    void addAnnotation(PdfAnnotation annot, PdfDictionary pageN) {
1082        try {
1083            ArrayList JavaDoc allAnnots = new ArrayList JavaDoc();
1084            if (annot.isForm()) {
1085                fieldsAdded = true;
1086                getAcroFields();
1087                PdfFormField field = (PdfFormField)annot;
1088                if (field.getParent() != null)
1089                    return;
1090                expandFields(field, allAnnots);
1091            }
1092            else
1093                allAnnots.add(annot);
1094            for (int k = 0; k < allAnnots.size(); ++k) {
1095                annot = (PdfAnnotation)allAnnots.get(k);
1096                if (annot.getPlaceInPage() > 0)
1097                    pageN = reader.getPageN(annot.getPlaceInPage());
1098                if (annot.isForm()) {
1099                    if (!annot.isUsed()) {
1100                        HashMap JavaDoc templates = annot.getTemplates();
1101                        if (templates != null)
1102                            fieldTemplates.putAll(templates);
1103                    }
1104                    PdfFormField field = (PdfFormField)annot;
1105                    if (field.getParent() == null)
1106                        addDocumentField(field.getIndirectReference());
1107                }
1108                if (annot.isAnnotation()) {
1109                    PdfObject pdfobj = PdfReader.getPdfObject(pageN.get(PdfName.ANNOTS), pageN);
1110                    PdfArray annots = null;
1111                    if (pdfobj == null || !pdfobj.isArray()) {
1112                        annots = new PdfArray();
1113                        pageN.put(PdfName.ANNOTS, annots);
1114                        markUsed(pageN);
1115                    }
1116                    else
1117                       annots = (PdfArray)pdfobj;
1118                    annots.add(annot.getIndirectReference());
1119                    markUsed(annots);
1120                    if (!annot.isUsed()) {
1121                        PdfRectangle rect = (PdfRectangle)annot.get(PdfName.RECT);
1122                        if (rect != null && (rect.left() != 0 || rect.right() != 0 || rect.top() != 0 || rect.bottom() != 0)) {
1123                            int rotation = reader.getPageRotation(pageN);
1124                            Rectangle pageSize = reader.getPageSizeWithRotation(pageN);
1125                            switch (rotation) {
1126                                case 90:
1127                                    annot.put(PdfName.RECT, new PdfRectangle(
1128                                    pageSize.getTop() - rect.bottom(),
1129                                    rect.left(),
1130                                    pageSize.getTop() - rect.top(),
1131                                    rect.right()));
1132                                    break;
1133                                case 180:
1134                                    annot.put(PdfName.RECT, new PdfRectangle(
1135                                    pageSize.getRight() - rect.left(),
1136                                    pageSize.getTop() - rect.bottom(),
1137                                    pageSize.getRight() - rect.right(),
1138                                    pageSize.getTop() - rect.top()));
1139                                    break;
1140                                case 270:
1141                                    annot.put(PdfName.RECT, new PdfRectangle(
1142                                    rect.bottom(),
1143                                    pageSize.getRight() - rect.left(),
1144                                    rect.top(),
1145                                    pageSize.getRight() - rect.right()));
1146                                    break;
1147                            }
1148                        }
1149                    }
1150                }
1151                if (!annot.isUsed()) {
1152                    annot.setUsed();
1153                    addToBody(annot, annot.getIndirectReference());
1154                }
1155            }
1156        }
1157        catch (IOException JavaDoc e) {
1158            throw new ExceptionConverter(e);
1159        }
1160    }
1161    
1162    void addAnnotation(PdfAnnotation annot, int page) {
1163        addAnnotation(annot, reader.getPageN(page));
1164    }
1165
1166    private void outlineTravel(PRIndirectReference outline) {
1167        while (outline != null) {
1168            PdfDictionary outlineR = (PdfDictionary)PdfReader.getPdfObjectRelease(outline);
1169            PRIndirectReference first = (PRIndirectReference)outlineR.get(PdfName.FIRST);
1170            if (first != null) {
1171                outlineTravel(first);
1172            }
1173            PdfReader.killIndirect(outlineR.get(PdfName.DEST));
1174            PdfReader.killIndirect(outlineR.get(PdfName.A));
1175            PdfReader.killIndirect(outline);
1176            outline = (PRIndirectReference)outlineR.get(PdfName.NEXT);
1177        }
1178    }
1179
1180    void deleteOutlines() {
1181        PdfDictionary catalog = reader.getCatalog();
1182        PRIndirectReference outlines = (PRIndirectReference)catalog.get(PdfName.OUTLINES);
1183        if (outlines == null)
1184            return;
1185        outlineTravel(outlines);
1186        PdfReader.killIndirect(outlines);
1187        catalog.remove(PdfName.OUTLINES);
1188        markUsed(catalog);
1189    }
1190    
1191    void setJavaScript() throws IOException JavaDoc {
1192        ArrayList JavaDoc djs = pdf.getDocumentJavaScript();
1193        if (djs.isEmpty())
1194            return;
1195        PdfDictionary catalog = reader.getCatalog();
1196        PdfDictionary names = (PdfDictionary)PdfReader.getPdfObject(catalog.get(PdfName.NAMES), catalog);
1197        if (names == null) {
1198            names = new PdfDictionary();
1199            catalog.put(PdfName.NAMES, names);
1200            markUsed(catalog);
1201        }
1202        markUsed(names);
1203        String JavaDoc s = String.valueOf(djs.size() - 1);
1204        int n = s.length();
1205        String JavaDoc pad = "000000000000000";
1206        HashMap JavaDoc maptree = new HashMap JavaDoc();
1207        for (int k = 0; k < djs.size(); ++k) {
1208            s = String.valueOf(k);
1209            s = pad.substring(0, n - s.length()) + s;
1210            maptree.put(s, djs.get(k));
1211        }
1212        PdfDictionary tree = PdfNameTree.writeTree(maptree, this);
1213        names.put(PdfName.JAVASCRIPT, addToBody(tree).getIndirectReference());
1214    }
1215
1216    void addFileAttachments() throws IOException JavaDoc {
1217        HashMap JavaDoc fs = pdf.getDocumentFileAttachment();
1218        if (fs.isEmpty())
1219            return;
1220        PdfDictionary catalog = reader.getCatalog();
1221        PdfDictionary names = (PdfDictionary)PdfReader.getPdfObject(catalog.get(PdfName.NAMES), catalog);
1222        if (names == null) {
1223            names = new PdfDictionary();
1224            catalog.put(PdfName.NAMES, names);
1225            markUsed(catalog);
1226        }
1227        markUsed(names);
1228        HashMap JavaDoc old = PdfNameTree.readTree((PdfDictionary)PdfReader.getPdfObjectRelease(names.get(PdfName.EMBEDDEDFILES)));
1229        for (Iterator JavaDoc it = fs.entrySet().iterator(); it.hasNext();) {
1230            Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
1231            String JavaDoc name = (String JavaDoc) entry.getKey();
1232            int k = 0;
1233            String JavaDoc nn = name;
1234            while (old.containsKey(nn)) {
1235                ++k;
1236                nn += " " + k;
1237            }
1238            old.put(nn, entry.getValue());
1239        }
1240        PdfDictionary tree = PdfNameTree.writeTree(old, this);
1241        names.put(PdfName.EMBEDDEDFILES, addToBody(tree).getIndirectReference());
1242    }
1243
1244    /**
1245     * Adds or replaces the Collection Dictionary in the Catalog.
1246     * @param collection the new collection dictionary.
1247     */

1248    void makePackage( PdfCollection collection ) {
1249        PdfDictionary catalog = reader.getCatalog();
1250        catalog.put( PdfName.COLLECTION, collection );
1251    }
1252 
1253    void setOutlines() throws IOException JavaDoc {
1254        if (newBookmarks == null)
1255            return;
1256        deleteOutlines();
1257        if (newBookmarks.isEmpty())
1258            return;
1259        namedAsNames = (reader.getCatalog().get(PdfName.DESTS) != null);
1260        PdfDictionary top = new PdfDictionary();
1261        PdfIndirectReference topRef = getPdfIndirectReference();
1262        Object JavaDoc kids[] = SimpleBookmark.iterateOutlines(this, topRef, newBookmarks, namedAsNames);
1263        top.put(PdfName.FIRST, (PdfIndirectReference)kids[0]);
1264        top.put(PdfName.LAST, (PdfIndirectReference)kids[1]);
1265        top.put(PdfName.COUNT, new PdfNumber(((Integer JavaDoc)kids[2]).intValue()));
1266        addToBody(top, topRef);
1267        reader.getCatalog().put(PdfName.OUTLINES, topRef);
1268        markUsed(reader.getCatalog());
1269    }
1270    
1271    void setOutlines(List JavaDoc outlines) {
1272        newBookmarks = outlines;
1273    }
1274    
1275    /**
1276     * Sets the viewer preferences.
1277     * @param preferences the viewer preferences
1278     * @see PdfWriter#setViewerPreferences(int)
1279     */

1280    public void setViewerPreferences(int preferences) {
1281        useVp = true;
1282        this.viewerPreferences.setViewerPreferences(preferences);
1283    }
1284    
1285    /** Adds a viewer preference
1286     * @param key a key for a viewer preference
1287     * @param value the value for the viewer preference
1288     * @see PdfViewerPreferences#addViewerPreference
1289     */

1290    public void addViewerPreference(PdfName key, PdfObject value) {
1291        useVp = true;
1292        this.viewerPreferences.addViewerPreference(key, value);
1293    }
1294    
1295    /**
1296     * Set the signature flags.
1297     * @param f the flags. This flags are ORed with current ones
1298     */

1299    public void setSigFlags(int f) {
1300        sigFlags |= f;
1301    }
1302    
1303    /** Always throws an <code>UnsupportedOperationException</code>.
1304     * @param actionType ignore
1305     * @param action ignore
1306     * @throws PdfException ignore
1307     * @see PdfStamper#setPageAction(PdfName, PdfAction, int)
1308     */

1309    public void setPageAction(PdfName actionType, PdfAction action) throws PdfException {
1310        throw new UnsupportedOperationException JavaDoc("Use setPageAction(PdfName actionType, PdfAction action, int page)");
1311    }
1312
1313    /**
1314     * Sets the open and close page additional action.
1315     * @param actionType the action type. It can be <CODE>PdfWriter.PAGE_OPEN</CODE>
1316     * or <CODE>PdfWriter.PAGE_CLOSE</CODE>
1317     * @param action the action to perform
1318     * @param page the page where the action will be applied. The first page is 1
1319     * @throws PdfException if the action type is invalid
1320     */

1321    void setPageAction(PdfName actionType, PdfAction action, int page) throws PdfException {
1322        if (!actionType.equals(PAGE_OPEN) && !actionType.equals(PAGE_CLOSE))
1323            throw new PdfException("Invalid page additional action type: " + actionType.toString());
1324        PdfDictionary pg = reader.getPageN(page);
1325        PdfDictionary aa = (PdfDictionary)PdfReader.getPdfObject(pg.get(PdfName.AA), pg);
1326        if (aa == null) {
1327            aa = new PdfDictionary();
1328            pg.put(PdfName.AA, aa);
1329            markUsed(pg);
1330        }
1331        aa.put(actionType, action);
1332        markUsed(aa);
1333    }
1334
1335    /**
1336     * Always throws an <code>UnsupportedOperationException</code>.
1337     * @param seconds ignore
1338     */

1339    public void setDuration(int seconds) {
1340        throw new UnsupportedOperationException JavaDoc("Use setPageAction(PdfName actionType, PdfAction action, int page)");
1341    }
1342    
1343    /**
1344     * Always throws an <code>UnsupportedOperationException</code>.
1345     * @param transition ignore
1346     */

1347    public void setTransition(PdfTransition transition) {
1348        throw new UnsupportedOperationException JavaDoc("Use setPageAction(PdfName actionType, PdfAction action, int page)");
1349    }
1350
1351    /**
1352     * Sets the display duration for the page (for presentations)
1353     * @param seconds the number of seconds to display the page. A negative value removes the entry
1354     * @param page the page where the duration will be applied. The first page is 1
1355     */

1356    void setDuration(int seconds, int page) {
1357        PdfDictionary pg = reader.getPageN(page);
1358        if (seconds < 0)
1359            pg.remove(PdfName.DUR);
1360        else
1361            pg.put(PdfName.DUR, new PdfNumber(seconds));
1362        markUsed(pg);
1363    }
1364    
1365    /**
1366     * Sets the transition for the page
1367     * @param transition the transition object. A <code>null</code> removes the transition
1368     * @param page the page where the transition will be applied. The first page is 1
1369     */

1370    void setTransition(PdfTransition transition, int page) {
1371        PdfDictionary pg = reader.getPageN(page);
1372        if (transition == null)
1373            pg.remove(PdfName.TRANS);
1374        else
1375            pg.put(PdfName.TRANS, transition.getTransitionDictionary());
1376        markUsed(pg);
1377    }
1378
1379    protected void markUsed(PdfObject obj) {
1380        if (append && obj != null) {
1381            PRIndirectReference ref = null;
1382            if (obj.type() == PdfObject.INDIRECT)
1383                ref = (PRIndirectReference)obj;
1384            else
1385                ref = obj.getIndRef();
1386            if (ref != null)
1387                marked.put(ref.getNumber(), 1);
1388        }
1389    }
1390    
1391    protected void markUsed(int num) {
1392        if (append)
1393            marked.put(num, 1);
1394    }
1395    
1396    /**
1397     * Getter for property append.
1398     * @return Value of property append.
1399     */

1400    boolean isAppend() {
1401        return append;
1402    }
1403        
1404    /** Additional-actions defining the actions to be taken in
1405     * response to various trigger events affecting the document
1406     * as a whole. The actions types allowed are: <CODE>DOCUMENT_CLOSE</CODE>,
1407     * <CODE>WILL_SAVE</CODE>, <CODE>DID_SAVE</CODE>, <CODE>WILL_PRINT</CODE>
1408     * and <CODE>DID_PRINT</CODE>.
1409     *
1410     * @param actionType the action type
1411     * @param action the action to execute in response to the trigger
1412     * @throws PdfException on invalid action type
1413     */

1414    public void setAdditionalAction(PdfName actionType, PdfAction action) throws PdfException {
1415        if (!(actionType.equals(DOCUMENT_CLOSE) ||
1416        actionType.equals(WILL_SAVE) ||
1417        actionType.equals(DID_SAVE) ||
1418        actionType.equals(WILL_PRINT) ||
1419        actionType.equals(DID_PRINT))) {
1420            throw new PdfException("Invalid additional action type: " + actionType.toString());
1421        }
1422        PdfDictionary aa = (PdfDictionary)PdfReader.getPdfObject(reader.getCatalog().get(PdfName.AA));
1423        if (aa == null) {
1424            if (action == null)
1425                return;
1426            aa = new PdfDictionary();
1427            reader.getCatalog().put(PdfName.AA, aa);
1428        }
1429        markUsed(aa);
1430        if (action == null)
1431            aa.remove(actionType);
1432        else
1433            aa.put(actionType, action);
1434    }
1435
1436    /**
1437     * @see com.lowagie.text.pdf.PdfWriter#setOpenAction(com.lowagie.text.pdf.PdfAction)
1438     */

1439    public void setOpenAction(PdfAction action) {
1440        openAction = action;
1441    }
1442    
1443    /**
1444     * @see com.lowagie.text.pdf.PdfWriter#setOpenAction(java.lang.String)
1445     */

1446    public void setOpenAction(String JavaDoc name) {
1447        throw new UnsupportedOperationException JavaDoc("Open actions by name are not supported.");
1448    }
1449    
1450    /**
1451     * @see com.lowagie.text.pdf.PdfWriter#setThumbnail(com.lowagie.text.Image)
1452     */

1453    public void setThumbnail(com.lowagie.text.Image image) {
1454        throw new UnsupportedOperationException JavaDoc("Use PdfStamper.setThumbnail().");
1455    }
1456    
1457    void setThumbnail(Image image, int page) throws PdfException, DocumentException {
1458        PdfIndirectReference thumb = getImageReference(addDirectImageSimple(image));
1459        reader.resetReleasePage();
1460        PdfDictionary dic = reader.getPageN(page);
1461        dic.put(PdfName.THUMB, thumb);
1462        reader.resetReleasePage();
1463    }
1464
1465    public PdfContentByte getDirectContentUnder() {
1466        throw new UnsupportedOperationException JavaDoc("Use PdfStamper.getUnderContent() or PdfStamper.getOverContent()");
1467    }
1468
1469    public PdfContentByte getDirectContent() {
1470        throw new UnsupportedOperationException JavaDoc("Use PdfStamper.getUnderContent() or PdfStamper.getOverContent()");
1471    }
1472    
1473    static class PageStamp {
1474        
1475        PdfDictionary pageN;
1476        StampContent under;
1477        StampContent over;
1478        PageResources pageResources;
1479        
1480        PageStamp(PdfStamperImp stamper, PdfReader reader, PdfDictionary pageN) {
1481            this.pageN = pageN;
1482            pageResources = new PageResources();
1483            PdfDictionary resources = (PdfDictionary)PdfReader.getPdfObject(pageN.get(PdfName.RESOURCES));
1484            pageResources.setOriginalResources(resources, stamper.namePtr);
1485        }
1486    }
1487}
1488
Popular Tags