package org.apache.fop.pdf.xref;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import org.apache.fop.pdf.PDFArray;
import org.apache.fop.pdf.PDFDictionary;
import org.apache.fop.pdf.PDFDocument;
import org.apache.fop.pdf.PDFFilterList;
import org.apache.fop.pdf.PDFName;
import org.apache.fop.pdf.PDFObjectNumber;
import org.apache.fop.pdf.PDFStream;
public class CrossReferenceStream extends CrossReferenceObject {
private static final PDFName XREF = new PDFName("XRef");
private final PDFDocument document;
private final int objectNumber;
private final List<ObjectReference> objectReferences;
public CrossReferenceStream(PDFDocument document,
int objectNumber,
TrailerDictionary trailerDictionary,
long startxref,
List<Long> uncompressedObjectReferences,
List<CompressedObjectReference> compressedObjectReferences) {
super(trailerDictionary, startxref);
this.document = document;
this.objectNumber = objectNumber;
this.objectReferences = new ArrayList<ObjectReference>(uncompressedObjectReferences.size());
for (Long offset : uncompressedObjectReferences) {
objectReferences.add(offset == null ? null : new UncompressedObjectReference(offset));
}
for (CompressedObjectReference ref : compressedObjectReferences) {
while (ref.getObjectNumber().getNumber() > objectReferences.size()) {
objectReferences.add(null);
}
this.objectReferences.set(ref.getObjectNumber().getNumber() - 1, ref);
}
}
public void output(OutputStream stream) throws IOException {
populateDictionary();
PDFStream helperStream = new PDFStream(trailerDictionary.getDictionary(), false) {
@Override
protected void setupFilterList() {
PDFFilterList filterList = getFilterList();
assert !filterList.isInitialized();
filterList.addDefaultFilters(document.getFilterMap(), getDefaultFilterName());
}
};
helperStream.setObjectNumber(new PDFObjectNumber(objectNumber));
helperStream.setDocument(document);
ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
DataOutputStream data = new DataOutputStream(byteArray);
addFreeEntryForObject0(data);
for (ObjectReference objectReference : objectReferences) {
assert objectReference != null;
objectReference.output(data);
}
new UncompressedObjectReference(startxref).output(data);
data.close();
helperStream.setData(byteArray.toByteArray());
PDFDocument.outputIndirectObject(helperStream, stream);
}
private void populateDictionary() throws IOException {
int objectCount = objectReferences.size() + 1;
PDFDictionary dictionary = trailerDictionary.getDictionary();
dictionary.put("/Type", XREF);
dictionary.put("/Size", objectCount + 1);
dictionary.put("/W", new PDFArray(1, 8, 2));
}
private void addFreeEntryForObject0(DataOutputStream data) throws IOException {
data.write(new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, (byte) 0xff, (byte) 0xff});
}
}