001/* 002 * $Id: PdfAnnotationsImp.java 4784 2011-03-15 08:33:00Z blowagie $ 003 * 004 * This file is part of the iText (R) project. 005 * Copyright (c) 1998-2011 1T3XT BVBA 006 * Authors: Bruno Lowagie, Paulo Soares, et al. 007 * 008 * This program is free software; you can redistribute it and/or modify 009 * it under the terms of the GNU Affero General Public License version 3 010 * as published by the Free Software Foundation with the addition of the 011 * following permission added to Section 15 as permitted in Section 7(a): 012 * FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY 1T3XT, 013 * 1T3XT DISCLAIMS THE WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. 014 * 015 * This program is distributed in the hope that it will be useful, but 016 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 017 * or FITNESS FOR A PARTICULAR PURPOSE. 018 * See the GNU Affero General Public License for more details. 019 * You should have received a copy of the GNU Affero General Public License 020 * along with this program; if not, see http://www.gnu.org/licenses or write to 021 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 022 * Boston, MA, 02110-1301 USA, or download the license from the following URL: 023 * http://itextpdf.com/terms-of-use/ 024 * 025 * The interactive user interfaces in modified source and object code versions 026 * of this program must display Appropriate Legal Notices, as required under 027 * Section 5 of the GNU Affero General Public License. 028 * 029 * In accordance with Section 7(b) of the GNU Affero General Public License, 030 * a covered work must retain the producer line in every PDF that is created 031 * or manipulated using iText. 032 * 033 * You can be released from the requirements of the license by purchasing 034 * a commercial license. Buying such a license is mandatory as soon as you 035 * develop commercial activities involving the iText software without 036 * disclosing the source code of your own applications. 037 * These activities include: offering paid services to customers as an ASP, 038 * serving PDFs on the fly in a web application, shipping iText with a closed 039 * source product. 040 * 041 * For more information, please contact iText Software Corp. at this 042 * address: sales@itextpdf.com 043 */ 044package com.itextpdf.text.pdf.internal; 045 046import java.io.IOException; 047import java.net.URL; 048import java.util.ArrayList; 049import java.util.HashSet; 050 051import com.itextpdf.text.Annotation; 052import com.itextpdf.text.ExceptionConverter; 053import com.itextpdf.text.Rectangle; 054import com.itextpdf.text.pdf.PdfAcroForm; 055import com.itextpdf.text.pdf.PdfAction; 056import com.itextpdf.text.pdf.PdfAnnotation; 057import com.itextpdf.text.pdf.PdfArray; 058import com.itextpdf.text.pdf.PdfFileSpecification; 059import com.itextpdf.text.pdf.PdfFormField; 060import com.itextpdf.text.pdf.PdfName; 061import com.itextpdf.text.pdf.PdfObject; 062import com.itextpdf.text.pdf.PdfRectangle; 063import com.itextpdf.text.pdf.PdfString; 064import com.itextpdf.text.pdf.PdfTemplate; 065import com.itextpdf.text.pdf.PdfWriter; 066 067public class PdfAnnotationsImp { 068 069 /** 070 * This is the AcroForm object for the complete document. 071 */ 072 protected PdfAcroForm acroForm; 073 074 /** 075 * This is the array containing the references to annotations 076 * that were added to the document. 077 */ 078 protected ArrayList<PdfAnnotation> annotations; 079 080 /** 081 * This is an array containing references to some delayed annotations 082 * (that were added for a page that doesn't exist yet). 083 */ 084 protected ArrayList<PdfAnnotation> delayedAnnotations = new ArrayList<PdfAnnotation>(); 085 086 087 public PdfAnnotationsImp(PdfWriter writer) { 088 acroForm = new PdfAcroForm(writer); 089 } 090 091 /** 092 * Checks if the AcroForm is valid. 093 */ 094 public boolean hasValidAcroForm() { 095 return acroForm.isValid(); 096 } 097 098 /** 099 * Gets the AcroForm object. 100 * @return the PdfAcroform object of the PdfDocument 101 */ 102 public PdfAcroForm getAcroForm() { 103 return acroForm; 104 } 105 106 public void setSigFlags(int f) { 107 acroForm.setSigFlags(f); 108 } 109 110 public void addCalculationOrder(PdfFormField formField) { 111 acroForm.addCalculationOrder(formField); 112 } 113 114 public void addAnnotation(PdfAnnotation annot) { 115 if (annot.isForm()) { 116 PdfFormField field = (PdfFormField)annot; 117 if (field.getParent() == null) 118 addFormFieldRaw(field); 119 } 120 else 121 annotations.add(annot); 122 } 123 124 public void addPlainAnnotation(PdfAnnotation annot) { 125 annotations.add(annot); 126 } 127 128 void addFormFieldRaw(PdfFormField field) { 129 annotations.add(field); 130 ArrayList<PdfFormField> kids = field.getKids(); 131 if (kids != null) { 132 for (int k = 0; k < kids.size(); ++k) 133 addFormFieldRaw(kids.get(k)); 134 } 135 } 136 137 public boolean hasUnusedAnnotations() { 138 return !annotations.isEmpty(); 139 } 140 141 public void resetAnnotations() { 142 annotations = delayedAnnotations; 143 delayedAnnotations = new ArrayList<PdfAnnotation>(); 144 } 145 146 public PdfArray rotateAnnotations(PdfWriter writer, Rectangle pageSize) { 147 PdfArray array = new PdfArray(); 148 int rotation = pageSize.getRotation() % 360; 149 int currentPage = writer.getCurrentPageNumber(); 150 for (int k = 0; k < annotations.size(); ++k) { 151 PdfAnnotation dic = annotations.get(k); 152 int page = dic.getPlaceInPage(); 153 if (page > currentPage) { 154 delayedAnnotations.add(dic); 155 continue; 156 } 157 if (dic.isForm()) { 158 if (!dic.isUsed()) { 159 HashSet<PdfTemplate> templates = dic.getTemplates(); 160 if (templates != null) 161 acroForm.addFieldTemplates(templates); 162 } 163 PdfFormField field = (PdfFormField)dic; 164 if (field.getParent() == null) 165 acroForm.addDocumentField(field.getIndirectReference()); 166 } 167 if (dic.isAnnotation()) { 168 array.add(dic.getIndirectReference()); 169 if (!dic.isUsed()) { 170 PdfRectangle rect = (PdfRectangle)dic.get(PdfName.RECT); 171 if (rect != null) { 172 switch (rotation) { 173 case 90: 174 dic.put(PdfName.RECT, new PdfRectangle( 175 pageSize.getTop() - rect.bottom(), 176 rect.left(), 177 pageSize.getTop() - rect.top(), 178 rect.right())); 179 break; 180 case 180: 181 dic.put(PdfName.RECT, new PdfRectangle( 182 pageSize.getRight() - rect.left(), 183 pageSize.getTop() - rect.bottom(), 184 pageSize.getRight() - rect.right(), 185 pageSize.getTop() - rect.top())); 186 break; 187 case 270: 188 dic.put(PdfName.RECT, new PdfRectangle( 189 rect.bottom(), 190 pageSize.getRight() - rect.left(), 191 rect.top(), 192 pageSize.getRight() - rect.right())); 193 break; 194 } 195 } 196 } 197 } 198 if (!dic.isUsed()) { 199 dic.setUsed(); 200 try { 201 writer.addToBody(dic, dic.getIndirectReference()); 202 } 203 catch (IOException e) { 204 throw new ExceptionConverter(e); 205 } 206 } 207 } 208 return array; 209 } 210 211 public static PdfAnnotation convertAnnotation(PdfWriter writer, Annotation annot, Rectangle defaultRect) throws IOException { 212 switch(annot.annotationType()) { 213 case Annotation.URL_NET: 214 return new PdfAnnotation(writer, annot.llx(), annot.lly(), annot.urx(), annot.ury(), new PdfAction((URL) annot.attributes().get(Annotation.URL))); 215 case Annotation.URL_AS_STRING: 216 return new PdfAnnotation(writer, annot.llx(), annot.lly(), annot.urx(), annot.ury(), new PdfAction((String) annot.attributes().get(Annotation.FILE))); 217 case Annotation.FILE_DEST: 218 return new PdfAnnotation(writer, annot.llx(), annot.lly(), annot.urx(), annot.ury(), new PdfAction((String) annot.attributes().get(Annotation.FILE), (String) annot.attributes().get(Annotation.DESTINATION))); 219 case Annotation.SCREEN: 220 boolean sparams[] = (boolean[])annot.attributes().get(Annotation.PARAMETERS); 221 String fname = (String) annot.attributes().get(Annotation.FILE); 222 String mimetype = (String) annot.attributes().get(Annotation.MIMETYPE); 223 PdfFileSpecification fs; 224 if (sparams[0]) 225 fs = PdfFileSpecification.fileEmbedded(writer, fname, fname, null); 226 else 227 fs = PdfFileSpecification.fileExtern(writer, fname); 228 PdfAnnotation ann = PdfAnnotation.createScreen(writer, new Rectangle(annot.llx(), annot.lly(), annot.urx(), annot.ury()), 229 fname, fs, mimetype, sparams[1]); 230 return ann; 231 case Annotation.FILE_PAGE: 232 return new PdfAnnotation(writer, annot.llx(), annot.lly(), annot.urx(), annot.ury(), new PdfAction((String) annot.attributes().get(Annotation.FILE), ((Integer) annot.attributes().get(Annotation.PAGE)).intValue())); 233 case Annotation.NAMED_DEST: 234 return new PdfAnnotation(writer, annot.llx(), annot.lly(), annot.urx(), annot.ury(), new PdfAction(((Integer) annot.attributes().get(Annotation.NAMED)).intValue())); 235 case Annotation.LAUNCH: 236 return new PdfAnnotation(writer, annot.llx(), annot.lly(), annot.urx(), annot.ury(), new PdfAction((String) annot.attributes().get(Annotation.APPLICATION),(String) annot.attributes().get(Annotation.PARAMETERS),(String) annot.attributes().get(Annotation.OPERATION),(String) annot.attributes().get(Annotation.DEFAULTDIR))); 237 default: 238 return new PdfAnnotation(writer, defaultRect.getLeft(), defaultRect.getBottom(), defaultRect.getRight(), defaultRect.getTop(), new PdfString(annot.title(), PdfObject.TEXT_UNICODE), new PdfString(annot.content(), PdfObject.TEXT_UNICODE)); 239 } 240 } 241}