📄 pdfwriter.java
字号:
/*
* $Id: PdfWriter.java,v 1.31 2001/12/10 13:53:22 blowagie Exp $
* $Name: $
*
* Copyright 1999, 2000, 2001 by Bruno Lowagie.
*
* This library is free software; you can redistribute it and/or modify it
* 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.
*
* You should have received a copy of the GNU Library General Public License along
* with this library; if not, write to the Free Foundation, Inc., 59 Temple Place,
* Suite 330, Boston, MA 02111-1307 USA.
*
* 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/
*
* ir-arch Bruno Lowagie,
* Adolf Baeyensstraat 121
* 9040 Sint-Amandsberg
* BELGIUM
* tel. +32 (0)9 228.10.97
* bruno@lowagie.com
*
*/
package com.lowagie.text.pdf;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.HashMap;
import java.util.TreeMap;
import com.lowagie.text.Document;
import com.lowagie.text.Table;
import com.lowagie.text.DocumentException;
import com.lowagie.text.DocListener;
import com.lowagie.text.DocWriter;
import com.lowagie.text.Image;
/**
* A <CODE>DocWriter</CODE> class for PDF.
* <P>
* When this <CODE>PdfWriter</CODE> is added
* to a certain <CODE>PdfDocument</CODE>, the PDF representation of every Element
* added to this Document will be written to the outputstream.</P>
*
* @author bruno@lowagie.com
*/
public class PdfWriter extends DocWriter {
// inner classes
/**
* This class generates the structure of a PDF document.
* <P>
* This class covers the third section of Chapter 5 in the 'Portable Document Format
* Reference Manual version 1.3' (page 55-60). It contains the body of a PDF document
* (section 5.14) and it can also generate a Cross-reference Table (section 5.15).
*
* @see PdfWriter
* @see PdfObject
* @see PdfIndirectObject
*/
public class PdfBody {
// inner classes
/**
* <CODE>PdfCrossReference</CODE> is an entry in the PDF Cross-Reference table.
*/
class PdfCrossReference {
// membervariables
/** Byte offset in the PDF file. */
private int offset;
/** generation of the object. */
private int generation;
// constructors
/**
* Constructs a cross-reference element for a PdfIndirectObject.
*
* @param offset byte offset of the object
* @param generation generationnumber of the object
*/
PdfCrossReference(int offset, int generation) {
this.offset = offset;
this.generation = generation;
}
/**
* Constructs a cross-reference element for a PdfIndirectObject.
*
* @param offset byte offset of the object
*/
PdfCrossReference(int offset) {
this(offset, 0);
}
/**
* Returns the PDF representation of this <CODE>PdfObject</CODE>.
*
* @return an array of <CODE>byte</CODE>s
*/
final byte[] toPdf(PdfEncryption crypto) {
// This code makes it more difficult to port the lib to JDK1.1.x:
// StringBuffer off = new StringBuffer("0000000000").append(offset);
// off.delete(0, off.length() - 10);
// StringBuffer gen = new StringBuffer("00000").append(generation);
// gen.delete(0, gen.length() - 5);
// so it was changed into this:
String s = "0000000000" + offset;
StringBuffer off = new StringBuffer(s.substring(s.length() - 10));
s = "00000" + generation;
StringBuffer gen = new StringBuffer(s.substring(s.length() - 5));
if (generation == 65535) {
return getISOBytes(off.append(' ').append(gen).append(" f \n").toString());
}
return getISOBytes(off.append(' ').append(gen).append(" n \n").toString());
}
}
// membervariables
/** Byte offset in the PDF file of the root object. */
private int rootOffset;
/** array containing the cross-reference table of the normal objects. */
private ArrayList xrefs;
/** the current byteposition in the body. */
private int position;
private PdfEncryption crypto;
// constructors
/**
* Constructs a new <CODE>PdfBody</CODE>.
*
* @param offset the offset of the body
*/
PdfBody(int offset) {
xrefs = new ArrayList();
xrefs.add(new PdfCrossReference(0, 65535));
xrefs.add(new PdfCrossReference(0));
position = offset;
}
// methods
void setCrypto(PdfEncryption crypto) {
this.crypto = crypto;
}
/**
* Adds a <CODE>PdfObject</CODE> to the body.
* <P>
* This methods creates a <CODE>PdfIndirectObject</CODE> with a
* certain number, containing the given <CODE>PdfObject</CODE>.
* It also adds a <CODE>PdfCrossReference</CODE> for this object
* to an <CODE>ArrayList</CODE> that will be used to build the
* Cross-reference Table.
*
* @param object a <CODE>PdfObject</CODE>
* @return a <CODE>PdfIndirectObject</CODE>
*/
final PdfIndirectObject add(PdfObject object) {
PdfIndirectObject indirect = new PdfIndirectObject(size(), object, crypto);
xrefs.add(new PdfCrossReference(position));
position += indirect.length();
return indirect;
}
/**
* Gets a PdfIndirectReference for an object that will be created in the future.
* @return a PdfIndirectReference
*/
final PdfIndirectReference getPdfIndirectReference()
{
xrefs.add(new PdfCrossReference(0));
return new PdfIndirectReference(0, size() - 1);
}
/**
* Adds a <CODE>PdfObject</CODE> to the body given an already existing
* PdfIndirectReference.
* <P>
* This methods creates a <CODE>PdfIndirectObject</CODE> with the number given by
* <CODE>ref</CODE>, containing the given <CODE>PdfObject</CODE>.
* It also adds a <CODE>PdfCrossReference</CODE> for this object
* to an <CODE>ArrayList</CODE> that will be used to build the
* Cross-reference Table.
*
* @param object a <CODE>PdfObject</CODE>
* @param ref a <CODE>PdfIndirectReference</CODE>
* @return a <CODE>PdfIndirectObject</CODE>
*/
final PdfIndirectObject add(PdfObject object, PdfIndirectReference ref) {
PdfIndirectObject indirect = new PdfIndirectObject(ref.getNumber(), object, crypto);
xrefs.set(ref.getNumber(), new PdfCrossReference(position));
position += indirect.length();
return indirect;
}
/**
* Adds a <CODE>PdfResources</CODE> object to the body.
*
* @param object the <CODE>PdfResources</CODE>
* @return a <CODE>PdfIndirectObject</CODE>
*/
final PdfIndirectObject add(PdfResources object) {
return add(object);
}
/**
* Adds a <CODE>PdfPages</CODE> object to the body.
*
* @param object the root of the document
* @return a <CODE>PdfIndirectObject</CODE>
*/
final PdfIndirectObject add(PdfPages object) {
PdfIndirectObject indirect = new PdfIndirectObject(PdfWriter.ROOT, object, crypto);
rootOffset = position;
position += indirect.length();
return indirect;
}
/**
* Returns the offset of the Cross-Reference table.
*
* @return an offset
*/
final int offset() {
return position;
}
/**
* Returns the total number of objects contained in the CrossReferenceTable of this <CODE>Body</CODE>.
*
* @return a number of objects
*/
final int size() {
return xrefs.size();
}
/**
* Returns the CrossReferenceTable of the <CODE>Body</CODE>.
*
* @return an array of <CODE>byte</CODE>s
*/
final byte[] getCrossReferenceTable() {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
try {
stream.write(getISOBytes("xref\n0 "));
stream.write(getISOBytes(String.valueOf(size())));
stream.write(getISOBytes("\n"));
// we set the ROOT object
xrefs.set(PdfWriter.ROOT, new PdfCrossReference(rootOffset));
// all the other objects
PdfCrossReference entry;
for (Iterator i = xrefs.iterator(); i.hasNext(); ) {
entry = (PdfCrossReference) i.next();
stream.write(entry.toPdf(null));
}
}
catch (IOException ioe) {
throw new RuntimeException("Error in PdfIndirectObject::getBytes()! Error was: " + ioe);
}
return stream.toByteArray();
}
}
/**
* <CODE>PdfTrailer</CODE> is the PDF Trailer object.
* <P>
* This object is described in the 'Portable Document Format Reference Manual version 1.3'
* section 5.16 (page 59-60).
*/
class PdfTrailer {
// membervariables
/** content of the trailer */
private byte[] bytes;
// constructors
/**
* Constructs a PDF-Trailer.
*
* @param size the number of entries in the <CODE>PdfCrossReferenceTable</CODE>
* @param offset offset of the <CODE>PdfCrossReferenceTable</CODE>
* @param root an indirect reference to the root of the PDF document
* @param info an indirect reference to the info object of the PDF document
*/
public PdfTrailer(int size, int offset, PdfIndirectReference root, PdfIndirectReference info, PdfIndirectReference encryption, PdfObject fileID) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
try {
stream.write(getISOBytes("trailer\n"));
PdfDictionary dictionary = new PdfDictionary();
dictionary.put(PdfName.SIZE, new PdfNumber(size));
dictionary.put(PdfName.ROOT, root);
if (info != null) {
dictionary.put(PdfName.INFO, info);
}
if (encryption != null)
dictionary.put(PdfName.ENCRYPT, encryption);
if (fileID != null)
dictionary.put(PdfName.ID, fileID);
stream.write(dictionary.toPdf(null));
stream.write(getISOBytes("\nstartxref\n"));
stream.write(getISOBytes(String.valueOf(offset)));
stream.write(getISOBytes("\n%%EOF\n"));
}
catch (IOException ioe) {
throw new RuntimeException("Error in PdfTrailer! Error was: " + ioe);
}
bytes = stream.toByteArray();
}
/**
* Returns the PDF representation of this <CODE>PdfObject</CODE>.
*
* @return an array of <CODE>byte</CODE>s
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -