📄 pdfwriter.java
字号:
xrefs.add(new PdfCrossReference(n, 0, 65536));
return n;
}
/**
* 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>
* @throws IOException
*/
PdfIndirectObject add(PdfObject object, PdfIndirectReference ref) throws IOException {
return add(object, ref.getNumber());
}
PdfIndirectObject add(PdfObject object, PdfIndirectReference ref, boolean inObjStm) throws IOException {
return add(object, ref.getNumber(), inObjStm);
}
PdfIndirectObject add(PdfObject object, int refNumber) throws IOException {
return add(object, refNumber, true); // to false
}
PdfIndirectObject add(PdfObject object, int refNumber, boolean inObjStm) throws IOException {
if (inObjStm && object.canBeInObjStm() && writer.isFullCompression()) {
PdfCrossReference pxref = addToObjStm(object, refNumber);
PdfIndirectObject indirect = new PdfIndirectObject(refNumber, object, writer);
if (!xrefs.add(pxref)) {
xrefs.remove(pxref);
xrefs.add(pxref);
}
return indirect;
}
else {
PdfIndirectObject indirect = new PdfIndirectObject(refNumber, object, writer);
PdfCrossReference pxref = new PdfCrossReference(refNumber, position);
if (!xrefs.add(pxref)) {
xrefs.remove(pxref);
xrefs.add(pxref);
}
indirect.writeTo(writer.getOs());
position = writer.getOs().getCounter();
return indirect;
}
}
/**
* Returns the offset of the Cross-Reference table.
*
* @return an offset
*/
int offset() {
return position;
}
/**
* Returns the total number of objects contained in the CrossReferenceTable of this <CODE>Body</CODE>.
*
* @return a number of objects
*/
int size() {
return Math.max(((PdfCrossReference)xrefs.last()).getRefnum() + 1, refnum);
}
/**
* Returns the CrossReferenceTable of the <CODE>Body</CODE>.
* @param os
* @param root
* @param info
* @param encryption
* @param fileID
* @param prevxref
* @throws IOException
*/
void writeCrossReferenceTable(OutputStream os, PdfIndirectReference root, PdfIndirectReference info, PdfIndirectReference encryption, PdfObject fileID, int prevxref) throws IOException {
int refNumber = 0;
if (writer.isFullCompression()) {
flushObjStm();
refNumber = getIndirectReferenceNumber();
xrefs.add(new PdfCrossReference(refNumber, position));
}
PdfCrossReference entry = (PdfCrossReference)xrefs.first();
int first = entry.getRefnum();
int len = 0;
ArrayList sections = new ArrayList();
for (Iterator i = xrefs.iterator(); i.hasNext(); ) {
entry = (PdfCrossReference)i.next();
if (first + len == entry.getRefnum())
++len;
else {
sections.add(new Integer(first));
sections.add(new Integer(len));
first = entry.getRefnum();
len = 1;
}
}
sections.add(new Integer(first));
sections.add(new Integer(len));
if (writer.isFullCompression()) {
int mid = 4;
int mask = 0xff000000;
for (; mid > 1; --mid) {
if ((mask & position) != 0)
break;
mask >>>= 8;
}
ByteBuffer buf = new ByteBuffer();
for (Iterator i = xrefs.iterator(); i.hasNext(); ) {
entry = (PdfCrossReference) i.next();
entry.toPdf(mid, buf);
}
PdfStream xr = new PdfStream(buf.toByteArray());
buf = null;
xr.flateCompress();
xr.put(PdfName.SIZE, new PdfNumber(size()));
xr.put(PdfName.ROOT, root);
if (info != null) {
xr.put(PdfName.INFO, info);
}
if (encryption != null)
xr.put(PdfName.ENCRYPT, encryption);
if (fileID != null)
xr.put(PdfName.ID, fileID);
xr.put(PdfName.W, new PdfArray(new int[]{1, mid, 2}));
xr.put(PdfName.TYPE, PdfName.XREF);
PdfArray idx = new PdfArray();
for (int k = 0; k < sections.size(); ++k)
idx.add(new PdfNumber(((Integer)sections.get(k)).intValue()));
xr.put(PdfName.INDEX, idx);
if (prevxref > 0)
xr.put(PdfName.PREV, new PdfNumber(prevxref));
PdfEncryption enc = writer.crypto;
writer.crypto = null;
PdfIndirectObject indirect = new PdfIndirectObject(refNumber, xr, writer);
indirect.writeTo(writer.getOs());
writer.crypto = enc;
}
else {
os.write(getISOBytes("xref\n"));
Iterator i = xrefs.iterator();
for (int k = 0; k < sections.size(); k += 2) {
first = ((Integer)sections.get(k)).intValue();
len = ((Integer)sections.get(k + 1)).intValue();
os.write(getISOBytes(String.valueOf(first)));
os.write(getISOBytes(" "));
os.write(getISOBytes(String.valueOf(len)));
os.write('\n');
while (len-- > 0) {
entry = (PdfCrossReference) i.next();
entry.toPdf(os);
}
}
}
}
}
/**
* <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).
*/
static class PdfTrailer extends PdfDictionary {
// membervariables
int offset;
// 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
* @param encryption
* @param fileID
* @param prevxref
*/
PdfTrailer(int size, int offset, PdfIndirectReference root, PdfIndirectReference info, PdfIndirectReference encryption, PdfObject fileID, int prevxref) {
this.offset = offset;
put(PdfName.SIZE, new PdfNumber(size));
put(PdfName.ROOT, root);
if (info != null) {
put(PdfName.INFO, info);
}
if (encryption != null)
put(PdfName.ENCRYPT, encryption);
if (fileID != null)
put(PdfName.ID, fileID);
if (prevxref > 0)
put(PdfName.PREV, new PdfNumber(prevxref));
}
/**
* Returns the PDF representation of this <CODE>PdfObject</CODE>.
* @param writer
* @param os
* @throws IOException
*/
public void toPdf(PdfWriter writer, OutputStream os) throws IOException {
os.write(getISOBytes("trailer\n"));
super.toPdf(null, os);
os.write(getISOBytes("\nstartxref\n"));
os.write(getISOBytes(String.valueOf(offset)));
os.write(getISOBytes("\n%%EOF\n"));
}
}
// ESSENTIALS
// Construct a PdfWriter instance
/**
* Constructs a <CODE>PdfWriter</CODE>.
*/
protected PdfWriter() {
}
/**
* Constructs a <CODE>PdfWriter</CODE>.
* <P>
* Remark: a PdfWriter can only be constructed by calling the method
* <CODE>getInstance(Document document, OutputStream os)</CODE>.
*
* @param document The <CODE>PdfDocument</CODE> that has to be written
* @param os The <CODE>OutputStream</CODE> the writer has to write to.
*/
protected PdfWriter(PdfDocument document, OutputStream os) {
super(document, os);
pdf = document;
directContent = new PdfContentByte(this);
directContentUnder = new PdfContentByte(this);
}
/**
* Use this method to get an instance of the <CODE>PdfWriter</CODE>.
*
* @param document The <CODE>Document</CODE> that has to be written
* @param os The <CODE>OutputStream</CODE> the writer has to write to.
* @return a new <CODE>PdfWriter</CODE>
*
* @throws DocumentException on error
*/
public static PdfWriter getInstance(Document document, OutputStream os)
throws DocumentException {
PdfDocument pdf = new PdfDocument();
document.addDocListener(pdf);
PdfWriter writer = new PdfWriter(pdf, os);
pdf.addWriter(writer);
return writer;
}
/**
* Use this method to get an instance of the <CODE>PdfWriter</CODE>.
*
* @return a new <CODE>PdfWriter</CODE>
* @param document The <CODE>Document</CODE> that has to be written
* @param os The <CODE>OutputStream</CODE> the writer has to write to.
* @param listener A <CODE>DocListener</CODE> to pass to the PdfDocument.
* @throws DocumentException on error
*/
public static PdfWriter getInstance(Document document, OutputStream os, DocListener listener)
throws DocumentException {
PdfDocument pdf = new PdfDocument();
pdf.addDocListener(listener);
document.addDocListener(pdf);
PdfWriter writer = new PdfWriter(pdf, os);
pdf.addWriter(writer);
return writer;
}
// the PdfDocument instance
/** the pdfdocument object. */
protected PdfDocument pdf;
/**
* Gets the <CODE>PdfDocument</CODE> associated with this writer.
* @return the <CODE>PdfDocument</CODE>
*/
PdfDocument getPdfDocument() {
return pdf;
}
/**
* Use this method to get the info dictionary if you want to
* change it directly (add keys and values to the info dictionary).
* @return the info dictionary
*/
public PdfDictionary getInfo() {
return pdf.getInfo();
}
/**
* Use this method to get the current vertical page position.
* @param ensureNewLine Tells whether a new line shall be enforced. This may cause side effects
* for elements that do not terminate the lines they've started because those lines will get
* terminated.
* @return The current vertical page position.
*/
public float getVerticalPosition(boolean ensureNewLine) {
return pdf.getVerticalPosition(ensureNewLine);
}
// the PdfDirectContentByte instances
/*
* You should see Direct Content as a canvas on which you can draw
* graphics and text. One canvas goes on top of the page (getDirectContent),
* the other goes underneath (getDirectContentUnder).
* You can always the same object throughout your document,
* even if you have moved to a new page. Whatever you add on
* the canvas will be displayed on top or under the current page.
*/
/** The direct content in this document. */
protected PdfContentByte directContent;
/** The direct content under in this document. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -