📄 pdfstamperimp.java
字号:
/*
* Copyright 2003 by Paulo Soares.
*
* The contents of this file are subject to the Mozilla Public License Version 1.1
* (the "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the License.
*
* The Original Code is 'iText, a free JAVA-PDF library'.
*
* The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
* the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
* All Rights Reserved.
* Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
* are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
*
* Contributor(s): all the names of the contributors are added in the source code
* where applicable.
*
* Alternatively, the contents of this file may be used under the terms of the
* LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
* provisions of LGPL are applicable instead of those above. If you wish to
* allow use of your version of this file only under the terms of the LGPL
* License and not to allow others to use your version of this file under
* the MPL, indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by the LGPL.
* If you do not delete the provisions above, a recipient may use your version
* of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the MPL as stated above or under the terms of the GNU
* Library General Public License as published by the Free Software Foundation;
* either version 2 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
* details.
*
* If you didn't download this code from the following link, you should check if
* you aren't using an obsolete version:
* http://www.lowagie.com/iText/
*/
package com.lowagie.text.pdf;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.lowagie.text.DocumentException;
import com.lowagie.text.ExceptionConverter;
import com.lowagie.text.Image;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.collection.PdfCollection;
import com.lowagie.text.pdf.interfaces.PdfViewerPreferences;
import com.lowagie.text.pdf.internal.PdfViewerPreferencesImp;
class PdfStamperImp extends PdfWriter {
HashMap readers2intrefs = new HashMap();
HashMap readers2file = new HashMap();
RandomAccessFileOrArray file;
PdfReader reader;
IntHashtable myXref = new IntHashtable();
/** Integer(page number) -> PageStamp */
HashMap pagesToContent = new HashMap();
boolean closed = false;
/** Holds value of property rotateContents. */
private boolean rotateContents = true;
protected AcroFields acroFields;
protected boolean flat = false;
protected boolean flatFreeText = false;
protected int namePtr[] = {0};
protected boolean namedAsNames;
protected List newBookmarks;
protected HashSet partialFlattening = new HashSet();
protected boolean useVp = false;
protected PdfViewerPreferencesImp viewerPreferences = new PdfViewerPreferencesImp();
protected HashMap fieldTemplates = new HashMap();
protected boolean fieldsAdded = false;
protected int sigFlags = 0;
protected boolean append;
protected IntHashtable marked;
protected int initialXrefSize;
protected PdfAction openAction;
/** Creates new PdfStamperImp.
* @param reader the read PDF
* @param os the output destination
* @param pdfVersion the new pdf version or '\0' to keep the same version as the original
* document
* @param append
* @throws DocumentException on error
* @throws IOException
*/
PdfStamperImp(PdfReader reader, OutputStream os, char pdfVersion, boolean append) throws DocumentException, IOException {
super(new PdfDocument(), os);
if (!reader.isOpenedWithFullPermissions())
throw new IllegalArgumentException("PdfReader not opened with owner password");
if (reader.isTampered())
throw new DocumentException("The original document was reused. Read it again from file.");
reader.setTampered(true);
this.reader = reader;
file = reader.getSafeFile();
this.append = append;
if (append) {
if (reader.isRebuilt())
throw new DocumentException("Append mode requires a document without errors even if recovery was possible.");
if (reader.isEncrypted())
crypto = new PdfEncryption(reader.getDecrypt());
pdf_version.setAppendmode(true);
file.reOpen();
byte buf[] = new byte[8192];
int n;
while ((n = file.read(buf)) > 0)
this.os.write(buf, 0, n);
file.close();
prevxref = reader.getLastXref();
reader.setAppendable(true);
}
else {
if (pdfVersion == 0)
super.setPdfVersion(reader.getPdfVersion());
else
super.setPdfVersion(pdfVersion);
}
super.open();
pdf.addWriter(this);
if (append) {
body.setRefnum(reader.getXrefSize());
marked = new IntHashtable();
if (reader.isNewXrefType())
fullCompression = true;
if (reader.isHybridXref())
fullCompression = false;
}
initialXrefSize = reader.getXrefSize();
}
void close(HashMap moreInfo) throws IOException {
if (closed)
return;
if (useVp) {
reader.setViewerPreferences(viewerPreferences);
markUsed(reader.getTrailer().get(PdfName.ROOT));
}
if (flat)
flatFields();
if (flatFreeText)
flatFreeTextFields();
addFieldResources();
PdfDictionary acroForm = (PdfDictionary)PdfReader.getPdfObject(reader.getCatalog().get(PdfName.ACROFORM), reader.getCatalog());
if (acroFields != null && acroFields.getXfa().isChanged()) {
markUsed(acroForm);
if (!flat)
acroFields.getXfa().setXfa(this);
}
if (sigFlags != 0) {
if (acroForm != null) {
acroForm.put(PdfName.SIGFLAGS, new PdfNumber(sigFlags));
markUsed(acroForm);
}
}
closed = true;
addSharedObjectsToBody();
setOutlines();
setJavaScript();
addFileAttachments();
PdfDictionary catalog = reader.getCatalog();
if (openAction != null) {
catalog.put(PdfName.OPENACTION, openAction);
}
byte[] altMetadata = xmpMetadata;
if (altMetadata == null) {
PdfObject xmpo = PdfReader.getPdfObject(catalog.get(PdfName.METADATA));
if (xmpo != null && xmpo.isStream()) {
altMetadata = PdfReader.getStreamBytesRaw((PRStream)xmpo);
PdfReader.killIndirect(xmpo);
}
}
// if there is XMP data to add: add it
if (altMetadata != null) {
PdfStream xmp = new PdfStream(altMetadata);
xmp.put(PdfName.TYPE, PdfName.METADATA);
xmp.put(PdfName.SUBTYPE, PdfName.XML);
if (crypto != null && !crypto.isMetadataEncrypted()) {
PdfArray ar = new PdfArray();
ar.add(PdfName.CRYPT);
xmp.put(PdfName.FILTER, ar);
}
catalog.put(PdfName.METADATA, body.add(xmp).getIndirectReference());
markUsed(catalog);
}
PRIndirectReference iInfo = null;
try {
file.reOpen();
alterContents();
iInfo = (PRIndirectReference)reader.trailer.get(PdfName.INFO);
int skip = -1;
if (iInfo != null)
skip = iInfo.getNumber();
int rootN = ((PRIndirectReference)reader.trailer.get(PdfName.ROOT)).getNumber();
if (append) {
int keys[] = marked.getKeys();
for (int k = 0; k < keys.length; ++k) {
int j = keys[k];
PdfObject obj = reader.getPdfObjectRelease(j);
if (obj != null && skip != j && j < initialXrefSize) {
addToBody(obj, j, j != rootN);
}
}
for (int k = initialXrefSize; k < reader.getXrefSize(); ++k) {
PdfObject obj = reader.getPdfObject(k);
if (obj != null) {
addToBody(obj, getNewObjectNumber(reader, k, 0));
}
}
}
else {
for (int k = 1; k < reader.getXrefSize(); ++k) {
PdfObject obj = reader.getPdfObjectRelease(k);
if (obj != null && skip != k) {
addToBody(obj, getNewObjectNumber(reader, k, 0), k != rootN);
}
}
}
}
finally {
try {
file.close();
}
catch (Exception e) {
// empty on purpose
}
}
PdfIndirectReference encryption = null;
PdfObject fileID = null;
if (crypto != null) {
if (append) {
encryption = reader.getCryptoRef();
}
else {
PdfIndirectObject encryptionObject = addToBody(crypto.getEncryptionDictionary(), false);
encryption = encryptionObject.getIndirectReference();
}
fileID = crypto.getFileID();
}
else
fileID = PdfEncryption.createInfoId(PdfEncryption.createDocumentId());
PRIndirectReference iRoot = (PRIndirectReference)reader.trailer.get(PdfName.ROOT);
PdfIndirectReference root = new PdfIndirectReference(0, getNewObjectNumber(reader, iRoot.getNumber(), 0));
PdfIndirectReference info = null;
PdfDictionary oldInfo = (PdfDictionary)PdfReader.getPdfObject(iInfo);
PdfDictionary newInfo = new PdfDictionary();
if (oldInfo != null) {
for (Iterator i = oldInfo.getKeys().iterator(); i.hasNext();) {
PdfName key = (PdfName)i.next();
PdfObject value = PdfReader.getPdfObject(oldInfo.get(key));
newInfo.put(key, value);
}
}
if (moreInfo != null) {
for (Iterator i = moreInfo.entrySet().iterator(); i.hasNext();) {
Map.Entry entry = (Map.Entry) i.next();
String key = (String) entry.getKey();
PdfName keyName = new PdfName(key);
String value = (String) entry.getValue();
if (value == null)
newInfo.remove(keyName);
else
newInfo.put(keyName, new PdfString(value, PdfObject.TEXT_UNICODE));
}
}
if (append) {
if (iInfo == null)
info = addToBody(newInfo, false).getIndirectReference();
else
info = addToBody(newInfo, iInfo.getNumber(), false).getIndirectReference();
}
else {
if (!newInfo.getKeys().isEmpty())
info = addToBody(newInfo, false).getIndirectReference();
}
// write the cross-reference table of the body
body.writeCrossReferenceTable(os, root, info, encryption, fileID, prevxref);
if (fullCompression) {
os.write(getISOBytes("startxref\n"));
os.write(getISOBytes(String.valueOf(body.offset())));
os.write(getISOBytes("\n%%EOF\n"));
}
else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -