/**
* This is an abstract base class for PDF streams.
*/
-public abstract class AbstractPDFStream extends PDFDictionary {
+public abstract class AbstractPDFStream extends PDFObject {
+
+ private final PDFDictionary dictionary;
/** The filters that should be applied */
private PDFFilterList filters;
+ private final boolean encodeOnTheFly;
+
+ protected AbstractPDFStream() {
+ this(true);
+ }
+
+ protected AbstractPDFStream(PDFDictionary dictionary) {
+ this(dictionary, true);
+ }
+
+ protected AbstractPDFStream(boolean encodeOnTheFly) {
+ this(new PDFDictionary(), encodeOnTheFly);
+ }
+
+ protected AbstractPDFStream(PDFDictionary dictionary, boolean encodeOnTheFly) {
+ this.dictionary = dictionary;
+ this.encodeOnTheFly = encodeOnTheFly;
+ }
+
+ protected final PDFDictionary getDictionary() {
+ return dictionary;
+ }
+
+ protected Object get(String key) {
+ return dictionary.get(key);
+ }
+
/**
- * Constructor for AbstractPDFStream.
+ * Puts the given object in the dictionary associated to this stream.
+ *
+ * @param key the key in the dictionary
+ * @param value the value to store
*/
- public AbstractPDFStream() {
- super();
+ public void put(String key, Object value) {
+ dictionary.put(key, value);
}
/**
* {@inheritDoc}
*/
@Override
- protected int output(OutputStream stream) throws IOException {
+ public int output(OutputStream stream) throws IOException {
setupFilterList();
CountingOutputStream cout = new CountingOutputStream(stream);
StringBuilder textBuffer = new StringBuilder(64);
- textBuffer.append(getObjectID());
StreamCache encodedStream = null;
PDFNumber refLength = null;
final Object lengthEntry;
- if (isEncodingOnTheFly()) {
+ if (encodeOnTheFly) {
refLength = new PDFNumber();
getDocumentSafely().registerObject(refLength);
lengthEntry = refLength;
}
populateStreamDict(lengthEntry);
- writeDictionary(cout, textBuffer);
+ dictionary.writeDictionary(cout, textBuffer);
//Send encoded stream to target OutputStream
PDFDocument.flushTextBuffer(textBuffer, cout);
encodedStream.clear(); //Encoded stream can now be discarded
}
- textBuffer.append("\nendobj\n");
PDFDocument.flushTextBuffer(textBuffer, cout);
return cout.getCount();
}
- /**
- * Indicates whether encoding may happen without buffering the encoded data. If this method
- * returns true, the /Length entry will be an indirect object, a direct object otherwise.
- * @return true if encoding should happen "on the fly"
- */
- protected boolean isEncodingOnTheFly() {
- return getDocument().isEncodingOnTheFly();
+ @Override
+ public void setDocument(PDFDocument doc) {
+ dictionary.setDocument(doc);
+ super.setDocument(doc);
}
/**
protected void populateStreamDict(Object lengthEntry) {
put("Length", lengthEntry);
if (!getFilterList().isDisableAllFilters()) {
- getFilterList().putFilterDictEntries(this);
+ getFilterList().putFilterDictEntries(dictionary);
}
}
--- /dev/null
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.pdf;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Represents a PDF object that may appear in an object stream. An object stream is a PDF
+ * stream whose content is a sequence of PDF objects. See Section 3.4.6 of the PDF 1.5
+ * Reference.
+ */
+interface CompressedObject {
+
+ /**
+ * Returns the object number of this indirect object. Note that a compressed object
+ * must have a generation number of 0.
+ *
+ * @return the object number.
+ */
+ int getObjectNumber();
+
+ /**
+ * Outputs this object's content into the given stream.
+ *
+ * @param outputStream a stream, likely to be provided by the containing object stream
+ * @return the number of bytes written to the stream
+ * @throws IOException
+ */
+ int output(OutputStream outputStream) throws IOException;
+
+}
--- /dev/null
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.pdf;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.fop.pdf.xref.CompressedObjectReference;
+
+/**
+ * An object stream, as described in section 3.4.6 of the PDF 1.5 Reference.
+ */
+public class ObjectStream extends PDFStream {
+
+ private static final PDFName OBJ_STM = new PDFName("ObjStm");
+
+ private List<CompressedObject> objects = new ArrayList<CompressedObject>();
+
+ private int firstObjectOffset;
+
+ ObjectStream() {
+ super(false);
+ }
+
+ ObjectStream(ObjectStream previous) {
+ this();
+ put("Extends", previous);
+ }
+
+ CompressedObjectReference addObject(CompressedObject obj) {
+ if (obj == null) {
+ throw new NullPointerException("obj must not be null");
+ }
+ CompressedObjectReference reference = new CompressedObjectReference(obj.getObjectNumber(),
+ getObjectNumber(), objects.size());
+ objects.add(obj);
+ return reference;
+ }
+
+ @Override
+ protected void outputRawStreamData(OutputStream out) throws IOException {
+ int currentOffset = 0;
+ StringBuilder offsetsPart = new StringBuilder();
+ ByteArrayOutputStream streamContent = new ByteArrayOutputStream();
+ for (CompressedObject object : objects) {
+ offsetsPart.append(object.getObjectNumber())
+ .append(' ')
+ .append(currentOffset)
+ .append('\n');
+ currentOffset += object.output(streamContent);
+ }
+ byte[] offsets = PDFDocument.encode(offsetsPart.toString());
+ firstObjectOffset = offsets.length;
+ out.write(offsets);
+ streamContent.writeTo(out);
+ }
+
+ @Override
+ protected void populateStreamDict(Object lengthEntry) {
+ put("Type", OBJ_STM);
+ put("N", objects.size());
+ put("First", firstObjectOffset);
+ super.populateStreamDict(lengthEntry);
+ }
+}
--- /dev/null
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.pdf;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.fop.pdf.xref.CompressedObjectReference;
+
+/**
+ * Manages a collection of object streams, creating new streams as necessary to keep the
+ * number of objects in each stream at the recommended value. Streams are related to each
+ * other through the use of the Extends entry in the stream dictionary.
+ */
+class ObjectStreamManager {
+
+ private static final int OBJECT_STREAM_CAPACITY = 100;
+
+ private final PDFDocument pdfDocument;
+
+ private final List<CompressedObjectReference> compressedObjectReferences;
+
+ private int numObjectsInStream;
+
+ private ObjectStream currentObjectStream;
+
+ ObjectStreamManager(PDFDocument pdfDocument) {
+ this.pdfDocument = pdfDocument;
+ createObjectStream();
+ compressedObjectReferences = new ArrayList<CompressedObjectReference>();
+ }
+
+ void add(CompressedObject compressedObject) {
+ if (numObjectsInStream++ == OBJECT_STREAM_CAPACITY) {
+ createObjectStream();
+ numObjectsInStream = 1;
+ }
+ compressedObjectReferences.add(currentObjectStream.addObject(compressedObject));
+ }
+
+ private void createObjectStream() {
+ currentObjectStream = currentObjectStream == null
+ ? new ObjectStream()
+ : new ObjectStream(currentObjectStream);
+ pdfDocument.assignObjectNumber(currentObjectStream);
+ pdfDocument.addTrailerObject(currentObjectStream);
+ }
+
+ List<CompressedObjectReference> getCompressedObjectReferences() {
+ return compressedObjectReferences;
+ }
+}
*/
public String toPDFString() {
StringBuffer p = new StringBuffer(128);
- p.append(getObjectID());
p.append("[\n");
for (int i = 0; i < getCount(); i++) {
p.append(((PDFObject)links.get(i)).referencePDF());
p.append("\n");
}
- p.append("]\nendobj\n");
+ p.append("]");
return p.toString();
}
/*
* example
- * 20 0 obj
* [
* 19 0 R
* ]
- * endobj
*/
}
import java.io.IOException;
import java.io.OutputStream;
-import java.util.Collection;
import java.util.List;
import org.apache.commons.io.output.CountingOutputStream;
* Create a new, empty array object with no parent.
*/
public PDFArray() {
- this(null);
+ this((PDFObject) null);
}
/**
* @param parent the array's parent if any
* @param values the actual values wrapped by this object
*/
- public PDFArray(PDFObject parent, Collection<Object> values) {
+ public PDFArray(PDFObject parent, List<?> values) {
/* generic creation of PDF object */
super(parent);
this.values.addAll(values);
}
+ /**
+ * Creates an array object made of the given elements.
+ *
+ * @param elements the array content
+ */
+ public PDFArray(Object... elements) {
+ this(null, elements);
+ }
+
/**
* Create the array object
* @param parent the array's parent if any
/** {@inheritDoc} */
@Override
- protected int output(OutputStream stream) throws IOException {
+ public int output(OutputStream stream) throws IOException {
CountingOutputStream cout = new CountingOutputStream(stream);
StringBuilder textBuffer = new StringBuilder(64);
- if (hasObjectNumber()) {
- textBuffer.append(getObjectID());
- }
-
textBuffer.append('[');
for (int i = 0; i < values.size(); i++) {
if (i > 0) {
formatObject(obj, cout, textBuffer);
}
textBuffer.append(']');
-
- if (hasObjectNumber()) {
- textBuffer.append("\nendobj\n");
- }
-
PDFDocument.flushTextBuffer(textBuffer, cout);
return cout.getCount();
}
*/
public String toPDFString() {
StringBuffer p = new StringBuffer(128);
- p.append(getObjectID());
p.append("<< /Type /Font");
p.append("\n/BaseFont /");
p.append(this.basefont);
p.append("\n/DW2 ["); // always two values, see p 211
p.append(this.dw2[0]);
p.append(this.dw2[1]);
- p.append("] \n>>\nendobj\n");
+ p.append("]");
}
if (w2 != null) {
p.append("\n/W2 ");
p.append(w2.toPDFString());
- p.append(" \n>>\nendobj\n");
}
- p.append(" \n>>\nendobj\n");
+ p.append("\n>>");
return p.toString();
}
}
/** {@inheritDoc} */
- protected int output(OutputStream stream) throws IOException {
+ public int output(OutputStream stream) throws IOException {
CMapBuilder builder = createCMapBuilder(getBufferWriter());
builder.writeCMap();
return super.output(stream);
this.idRef = idRef;
}
- /** {@inheritDoc} */
@Override
- protected int output(OutputStream stream) throws IOException {
+ public int output(OutputStream stream) throws IOException {
CountingOutputStream cout = new CountingOutputStream(stream);
StringBuilder textBuffer = new StringBuilder(64);
/** {@inheritDoc} */
@Override
- protected int output(OutputStream stream) throws IOException {
+ public int output(OutputStream stream) throws IOException {
CountingOutputStream cout = new CountingOutputStream(stream);
StringBuilder textBuffer = new StringBuilder(64);
- if (hasObjectNumber()) {
- textBuffer.append(getObjectID());
- }
-
writeDictionary(cout, textBuffer);
-
- if (hasObjectNumber()) {
- textBuffer.append("\nendobj\n");
- }
-
PDFDocument.flushTextBuffer(textBuffer, cout);
return cout.getCount();
}
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.fop.pdf.xref.CrossReferenceStream;
+import org.apache.fop.pdf.xref.CrossReferenceTable;
+import org.apache.fop.pdf.xref.TrailerDictionary;
+
/* image support modified from work of BoBoGi */
/* font support based on work by Takayuki Takeuchi */
*/
public class PDFDocument {
- private static final Long LOCATION_PLACEHOLDER = new Long(0);
-
/** the encoding to use when converting strings to PDF commands */
public static final String ENCODING = "ISO-8859-1";
/** the counter for object numbering */
- protected int objectcount = 0;
+ protected int objectcount;
/** the logger instance */
private Log log = LogFactory.getLog("org.apache.fop.pdf");
/** the current character position */
- private long position = 0;
-
- /** character position of xref table */
- private long xref;
+ private long position;
/** the character position of each object */
- private List<Long> location = new ArrayList<Long>();
+ private List<Long> indirectObjectOffsets = new ArrayList<Long>();
+
+ private Collection<PDFStructElem> structureTreeElements;
/** List of objects to write in the trailer */
- private List trailerObjects = new ArrayList();
+ private List<PDFObject> trailerObjects = new ArrayList<PDFObject>();
/** the objects themselves */
- private List objects = new LinkedList();
+ private List<PDFObject> objects = new LinkedList<PDFObject>();
/** Controls the PDF version of this document */
private VersionController versionController;
private PDFRoot root;
/** The root outline object */
- private PDFOutline outlineRoot = null;
+ private PDFOutline outlineRoot;
/** The /Pages object (mark-fop@inomial.com) */
private PDFPages pages;
= new PDFDeviceColorSpace(PDFDeviceColorSpace.DEVICE_RGB);
/** the counter for Pattern name numbering (e.g. 'Pattern1') */
- private int patternCount = 0;
+ private int patternCount;
/** the counter for Shading name numbering */
- private int shadingCount = 0;
+ private int shadingCount;
/** the counter for XObject numbering */
- private int xObjectCount = 0;
+ private int xObjectCount;
- /** the {@link PDFXObject}s map */
/* TODO: Should be modified (works only for image subtype) */
- private Map xObjectsMap = new HashMap();
-
- /** The {@link PDFFont} map */
- private Map fontMap = new HashMap();
+ private Map<String, PDFXObject> xObjectsMap = new HashMap<String, PDFXObject>();
- /** The {@link PDFFilter} map */
- private Map filterMap = new HashMap();
+ private Map<String, PDFFont> fontMap = new HashMap<String, PDFFont>();
- /** List of {@link PDFGState}s. */
- private List gstates = new ArrayList();
+ private Map<String, List<String>> filterMap = new HashMap<String, List<String>>();
- /** List of {@link PDFFunction}s. */
- private List functions = new ArrayList();
+ private List<PDFGState> gstates = new ArrayList<PDFGState>();
- /** List of {@link PDFShading}s. */
- private List shadings = new ArrayList();
+ private List<PDFFunction> functions = new ArrayList<PDFFunction>();
- /** List of {@link PDFPattern}s. */
- private List patterns = new ArrayList();
+ private List<PDFShading> shadings = new ArrayList<PDFShading>();
- /** List of {@link PDFLink}s. */
- private List links = new ArrayList();
+ private List<PDFPattern> patterns = new ArrayList<PDFPattern>();
- /** List of {@link PDFDestination}s. */
- private List destinations;
+ private List<PDFLink> links = new ArrayList<PDFLink>();
- /** List of {@link PDFFileSpec}s. */
- private List filespecs = new ArrayList();
+ private List<PDFDestination> destinations;
- /** List of {@link PDFGoToRemote}s. */
- private List gotoremotes = new ArrayList();
+ private List<PDFFileSpec> filespecs = new ArrayList<PDFFileSpec>();
- /** List of {@link PDFGoTo}s. */
- private List gotos = new ArrayList();
+ private List<PDFGoToRemote> gotoremotes = new ArrayList<PDFGoToRemote>();
- /** List of {@link PDFLaunch}es. */
- private List launches = new ArrayList();
+ private List<PDFGoTo> gotos = new ArrayList<PDFGoTo>();
- /**
- * The PDFDests object for the name dictionary.
- * Note: This object is not a list.
- */
- private PDFDests dests;
+ private List<PDFLaunch> launches = new ArrayList<PDFLaunch>();
private PDFFactory factory;
- private boolean encodingOnTheFly = true;
-
private FileIDGenerator fileIDGenerator;
+ private boolean accessibilityEnabled;
+
/**
* Creates an empty PDF document.
*
return this.factory;
}
- /**
- * Indicates whether stream encoding on-the-fly is enabled. If enabled
- * stream can be serialized without the need for a buffer to merely
- * calculate the stream length.
- *
- * @return <code>true</code> if on-the-fly encoding is enabled
- */
- public boolean isEncodingOnTheFly() {
- return this.encodingOnTheFly;
- }
-
/**
* Converts text to a byte array for writing to a PDF file.
*
*
* @param map the map of filter lists for each stream type
*/
- public void setFilterMap(Map map) {
+ public void setFilterMap(Map<String, List<String>> map) {
this.filterMap = map;
}
*
* @return the map of filters being used
*/
- public Map getFilterMap() {
+ public Map<String, List<String>> getFilterMap() {
return this.filterMap;
}
return this.root;
}
+ /**
+ * Creates and returns a StructTreeRoot object.
+ *
+ * @param parentTree the value of the ParenTree entry
+ * @return the structure tree root
+ */
+ public PDFStructTreeRoot makeStructTreeRoot(PDFParentTree parentTree) {
+ PDFStructTreeRoot structTreeRoot = new PDFStructTreeRoot(parentTree);
+ assignObjectNumber(structTreeRoot);
+ addTrailerObject(structTreeRoot);
+ root.setStructTreeRoot(structTreeRoot);
+ structureTreeElements = new ArrayList<PDFStructElem>();
+ return structTreeRoot;
+ }
+
+ /**
+ * Creates and returns a structure element.
+ *
+ * @param structureType the structure type of the new element (value for the
+ * S entry)
+ * @param parent the parent of the new structure element in the structure
+ * hierarchy
+ * @return a dictionary of type StructElem
+ */
+ public PDFStructElem makeStructureElement(PDFName structureType, PDFObject parent) {
+ PDFStructElem structElem = new PDFStructElem(parent, structureType);
+ assignObjectNumber(structElem);
+ structureTreeElements.add(structElem);
+ return structElem;
+ }
+
/**
* Get the {@link PDFInfo} object for this document.
*
//Add object to special lists where necessary
if (obj instanceof PDFFunction) {
- this.functions.add(obj);
+ this.functions.add((PDFFunction) obj);
}
if (obj instanceof PDFShading) {
final String shadingName = "Sh" + (++this.shadingCount);
((PDFShading)obj).setName(shadingName);
- this.shadings.add(obj);
+ this.shadings.add((PDFShading) obj);
}
if (obj instanceof PDFPattern) {
final String patternName = "Pa" + (++this.patternCount);
((PDFPattern)obj).setName(patternName);
- this.patterns.add(obj);
+ this.patterns.add((PDFPattern) obj);
}
if (obj instanceof PDFFont) {
final PDFFont font = (PDFFont)obj;
this.fontMap.put(font.getName(), font);
}
if (obj instanceof PDFGState) {
- this.gstates.add(obj);
+ this.gstates.add((PDFGState) obj);
}
if (obj instanceof PDFPage) {
this.pages.notifyKidRegistered((PDFPage)obj);
}
if (obj instanceof PDFLaunch) {
- this.launches.add(obj);
+ this.launches.add((PDFLaunch) obj);
}
if (obj instanceof PDFLink) {
- this.links.add(obj);
+ this.links.add((PDFLink) obj);
}
if (obj instanceof PDFFileSpec) {
- this.filespecs.add(obj);
+ this.filespecs.add((PDFFileSpec) obj);
}
if (obj instanceof PDFGoToRemote) {
- this.gotoremotes.add(obj);
+ this.gotoremotes.add((PDFGoToRemote) obj);
}
}
this.trailerObjects.add(obj);
if (obj instanceof PDFGoTo) {
- this.gotos.add(obj);
+ this.gotos.add((PDFGoTo) obj);
}
}
return this.encryption;
}
- private Object findPDFObject(List list, PDFObject compare) {
- for (Iterator iter = list.iterator(); iter.hasNext();) {
- PDFObject obj = (PDFObject) iter.next();
+ private Object findPDFObject(List<? extends PDFObject> list, PDFObject compare) {
+ for (PDFObject obj : list) {
if (compare.contentEquals(obj)) {
return obj;
}
* @return PDFFont the requested font, null if it wasn't found
*/
protected PDFFont findFont(String fontname) {
- return (PDFFont)this.fontMap.get(fontname);
+ return this.fontMap.get(fontname);
}
/**
protected PDFDestination findDestination(PDFDestination compare) {
int index = getDestinationList().indexOf(compare);
if (index >= 0) {
- return (PDFDestination)getDestinationList().get(index);
+ return getDestinationList().get(index);
} else {
return null;
}
*/
protected PDFGState findGState(PDFGState wanted, PDFGState current) {
PDFGState poss;
- Iterator iter = this.gstates.iterator();
+ Iterator<PDFGState> iter = this.gstates.iterator();
while (iter.hasNext()) {
- PDFGState avail = (PDFGState)iter.next();
+ PDFGState avail = iter.next();
poss = new PDFGState();
poss.addValues(current);
poss.addValues(avail);
*
* @return the map of fonts used in this document
*/
- public Map getFontMap() {
+ public Map<String, PDFFont> getFontMap() {
return this.fontMap;
}
* @return the PDFXObject for the key if found
*/
public PDFXObject getXObject(String key) {
- return (PDFXObject)this.xObjectsMap.get(key);
- }
-
- /**
- * Gets the PDFDests object (which represents the /Dests entry).
- *
- * @return the PDFDests object (which represents the /Dests entry).
- */
- public PDFDests getDests() {
- return this.dests;
+ return this.xObjectsMap.get(key);
}
/**
*/
public void addDestination(PDFDestination destination) {
if (this.destinations == null) {
- this.destinations = new ArrayList();
+ this.destinations = new ArrayList<PDFDestination>();
}
this.destinations.add(destination);
}
*
* @return the list of named destinations.
*/
- public List getDestinationList() {
+ public List<PDFDestination> getDestinationList() {
if (hasDestinations()) {
return this.destinations;
} else {
- return Collections.EMPTY_LIST;
+ return Collections.emptyList();
}
}
return this.resources;
}
- /**
- * Ensure there is room in the locations xref for the number of
- * objects that have been created.
- * @param objidx the object's index
- * @param position the position
- */
- private void setLocation(int objidx, long position) {
- while (this.location.size() <= objidx) {
- this.location.add(LOCATION_PLACEHOLDER);
- }
- this.location.set(objidx, position);
+ public void enableAccessibility(boolean enableAccessibility) {
+ this.accessibilityEnabled = enableAccessibility;
}
/**
//LinkedList) allows for output() methods to create and register objects
//on the fly even during serialization.
while (this.objects.size() > 0) {
- /* Retrieve first */
- PDFObject object = (PDFObject)this.objects.remove(0);
- /*
- * add the position of this object to the list of object
- * locations
- */
- setLocation(object.getObjectNumber() - 1, this.position);
-
- /*
- * output the object and increment the character position
- * by the object's length
- */
- this.position += object.output(stream);
+ PDFObject object = this.objects.remove(0);
+ streamIndirectObject(object, stream);
}
+ }
- //Clear all objects written to the file
- //this.objects.clear();
+ private void streamIndirectObject(PDFObject o, OutputStream stream) throws IOException {
+ recordObjectOffset(o);
+ this.position += outputIndirectObject(o, stream);
+ }
+
+ private void streamIndirectObjects(Collection<? extends PDFObject> objects, OutputStream stream)
+ throws IOException {
+ for (PDFObject o : objects) {
+ streamIndirectObject(o, stream);
+ }
+ }
+
+ private void recordObjectOffset(PDFObject object) {
+ int index = object.getObjectNumber() - 1;
+ while (indirectObjectOffsets.size() <= index) {
+ indirectObjectOffsets.add(null);
+ }
+ indirectObjectOffsets.set(index, position);
+ }
+
+ /**
+ * Outputs the given object, wrapped by obj/endobj, to the given stream.
+ *
+ * @param object an indirect object, as described in Section 3.2.9 of the PDF 1.5
+ * Reference.
+ * @param stream the stream to which the object must be output
+ * @throws IllegalArgumentException if the object is not an indirect object
+ */
+ public static int outputIndirectObject(PDFObject object, OutputStream stream)
+ throws IOException {
+ if (!object.hasObjectNumber()) {
+ throw new IllegalArgumentException("Not an indirect object");
+ }
+ byte[] obj = encode(object.getObjectID());
+ stream.write(obj);
+ int length = object.output(stream);
+ byte[] endobj = encode("\nendobj\n");
+ stream.write(endobj);
+ return obj.length + length + endobj.length;
}
/**
* @throws IOException if there is an exception writing to the output stream
*/
public void outputTrailer(OutputStream stream) throws IOException {
+ createDestinations();
+ output(stream);
+ outputTrailerObjectsAndXref(stream);
+ }
+
+ private void createDestinations() {
if (hasDestinations()) {
Collections.sort(this.destinations, new DestinationComparator());
- this.dests = getFactory().makeDests(this.destinations);
+ PDFDests dests = getFactory().makeDests(this.destinations);
if (this.root.getNames() == null) {
this.root.setNames(getFactory().makeNames());
}
this.root.getNames().setDests(dests);
}
- output(stream);
- for (int count = 0; count < this.trailerObjects.size(); count++) {
- PDFObject o = (PDFObject)this.trailerObjects.get(count);
- setLocation(o.getObjectNumber() - 1, this.position);
- this.position += o.output(stream);
+ }
+
+ private void outputTrailerObjectsAndXref(OutputStream stream) throws IOException {
+ TrailerOutputHelper trailerOutputHelper = mayCompressStructureTreeElements()
+ ? new CompressedTrailerOutputHelper()
+ : new UncompressedTrailerOutputHelper();
+ if (structureTreeElements != null) {
+ trailerOutputHelper.outputStructureTreeElements(stream);
}
- /* output the xref table and increment the character position
- by the table's length */
- this.position += outputXref(stream);
-
- /* construct the trailer */
- StringBuffer pdf = new StringBuffer(128);
- pdf.append("trailer\n<<\n/Size ")
- .append(this.objectcount + 1)
- .append("\n/Root ")
- .append(this.root.referencePDF())
- .append("\n/Info ")
- .append(this.info.referencePDF())
- .append('\n');
-
- if (this.isEncryptionActive()) {
- pdf.append(this.encryption.getTrailerEntry());
- } else {
- byte[] fileID = getFileIDGenerator().getOriginalFileID();
- String fileIDAsString = PDFText.toHex(fileID);
- pdf.append("/ID [" + fileIDAsString + " " + fileIDAsString + "]");
+ streamIndirectObjects(trailerObjects, stream);
+ TrailerDictionary trailerDictionary = createTrailerDictionary();
+ long startxref = trailerOutputHelper.outputCrossReferenceObject(stream, trailerDictionary);
+ String trailer = "startxref\n" + startxref + "\n%%EOF\n";
+ stream.write(encode(trailer));
+ }
+
+ private boolean mayCompressStructureTreeElements() {
+ return accessibilityEnabled
+ && versionController.getPDFVersion().compareTo(Version.V1_5) >= 0;
+ }
+
+ private TrailerDictionary createTrailerDictionary() {
+ FileIDGenerator gen = getFileIDGenerator();
+ TrailerDictionary trailerDictionary = new TrailerDictionary(this)
+ .setRoot(root)
+ .setInfo(info)
+ .setFileID(gen.getOriginalFileID(), gen.getUpdatedFileID());
+ if (isEncryptionActive()) {
+ trailerDictionary.setEncryption(encryption);
}
+ return trailerDictionary;
+ }
- pdf.append("\n>>\nstartxref\n")
- .append(this.xref)
- .append("\n%%EOF\n");
+ private interface TrailerOutputHelper {
- /* write the trailer */
- stream.write(encode(pdf.toString()));
+ void outputStructureTreeElements(OutputStream stream) throws IOException;
+
+ /**
+ * @return the offset of the cross-reference object (the value of startxref)
+ */
+ long outputCrossReferenceObject(OutputStream stream, TrailerDictionary trailerDictionary)
+ throws IOException;
}
- /**
- * Write the xref table
- *
- * @param stream the OutputStream to write the xref table to
- * @return the number of characters written
- * @throws IOException in case of an error writing the result to
- * the parameter stream
- */
- private int outputXref(OutputStream stream) throws IOException {
-
- /* remember position of xref table */
- this.xref = this.position;
-
- /* construct initial part of xref */
- StringBuffer pdf = new StringBuffer(128);
- pdf.append("xref\n0 ");
- pdf.append(this.objectcount + 1);
- pdf.append("\n0000000000 65535 f \n");
-
- String s;
- String loc;
- for (int count = 0; count < this.location.size(); count++) {
- final String padding = "0000000000";
- s = this.location.get(count).toString();
- if (s.length() > 10) {
- throw new IOException("PDF file too large. PDF cannot grow beyond approx. 9.3GB.");
- }
+ private class UncompressedTrailerOutputHelper implements TrailerOutputHelper {
- /* contruct xref entry for object */
- loc = padding.substring(s.length()) + s;
+ public void outputStructureTreeElements(OutputStream stream)
+ throws IOException {
+ streamIndirectObjects(structureTreeElements, stream);
+ }
- /* append to xref table */
- pdf = pdf.append(loc).append(" 00000 n \n");
+ public long outputCrossReferenceObject(OutputStream stream,
+ TrailerDictionary trailerDictionary) throws IOException {
+ new CrossReferenceTable(trailerDictionary, position,
+ indirectObjectOffsets).output(stream);
+ return position;
}
+ }
+
+ private class CompressedTrailerOutputHelper implements TrailerOutputHelper {
+
+ private ObjectStreamManager structureTreeObjectStreams;
- /* write the xref table and return the character length */
- byte[] pdfBytes = encode(pdf.toString());
- stream.write(pdfBytes);
- return pdfBytes.length;
+ public void outputStructureTreeElements(OutputStream stream)
+ throws IOException {
+ assert structureTreeElements.size() > 0;
+ structureTreeObjectStreams = new ObjectStreamManager(PDFDocument.this);
+ for (PDFStructElem structElem : structureTreeElements) {
+ structureTreeObjectStreams.add(structElem);
+ }
+ }
+
+ public long outputCrossReferenceObject(OutputStream stream,
+ TrailerDictionary trailerDictionary) throws IOException {
+ // Outputting the object streams should not have created new indirect objects
+ assert objects.isEmpty();
+ new CrossReferenceStream(PDFDocument.this, ++objectcount, trailerDictionary, position,
+ indirectObjectOffsets,
+ structureTreeObjectStreams.getCompressedObjectReferences())
+ .output(stream);
+ return position;
+ }
}
long getCurrentFileSize() {
byte[] encrypt(byte[] data, PDFObject refObj);
/**
- * Returns the trailer entry for encryption.
- * @return the trailer entry
+ * Returns the /Encrypt entry in the file trailer dictionary.
+ *
+ * @return the string "/Encrypt n g R\n" where n and g are the number and generation
+ * of the document's encryption dictionary
*/
String getTrailerEntry();
}
? new Rev2Engine(encryptionSettings)
: new Rev3Engine(encryptionSettings);
initializationEngine.run();
- encryptionDictionary = createEncryptionDictionary(getObjectID(), permissions,
- initializationEngine.oValue, initializationEngine.uValue);
+ encryptionDictionary = createEncryptionDictionary(permissions,
+ initializationEngine.oValue,
+ initializationEngine.uValue);
}
private void determineEncryptionAlgorithm() {
&& encryptionParams.isAllowPrintHq();
}
- private String createEncryptionDictionary(final String objectId, final int permissions,
- final byte[] oValue, final byte[] uValue) {
- return objectId
- + "<< /Filter /Standard\n"
+ private String createEncryptionDictionary(final int permissions, final byte[] oValue,
+ final byte[] uValue) {
+ return "<< /Filter /Standard\n"
+ "/V " + version + "\n"
+ "/R " + revision + "\n"
+ "/Length " + encryptionLength + "\n"
+ "/P " + permissions + "\n"
+ "/O " + PDFText.toHex(oValue) + "\n"
+ "/U " + PDFText.toHex(uValue) + "\n"
- + ">>\n"
- + "endobj\n";
+ + ">>";
}
}
/** {@inheritDoc} */
public String getTrailerEntry() {
- PDFDocument doc = getDocumentSafely();
- FileIDGenerator gen = doc.getFileIDGenerator();
- return "/Encrypt " + getObjectNumber() + " "
- + getGeneration() + " R\n"
- + "/ID["
- + PDFText.toHex(gen.getOriginalFileID())
- + PDFText.toHex(gen.getUpdatedFileID())
- + "]\n";
+ return "/Encrypt " + getObjectNumber() + " " + getGeneration() + " R\n";
}
private static byte[] encryptWithKey(byte[] key, byte[] data) {
return pageLabels;
}
- /**
- * Creates and returns a StructTreeRoot object. Used for accessibility.
- * @param parentTree the value of the ParenTree entry
- * @return structure Tree Root element
- */
- public PDFStructTreeRoot makeStructTreeRoot(PDFParentTree parentTree) {
- PDFStructTreeRoot structTreeRoot = new PDFStructTreeRoot(parentTree);
- getDocument().assignObjectNumber(structTreeRoot);
- getDocument().addTrailerObject(structTreeRoot);
- getDocument().getRoot().setStructTreeRoot(structTreeRoot);
- return structTreeRoot;
- }
-
- /**
- * Creates and returns a StructElem object.
- *
- * @param structureType the structure type of the new element (value for the
- * S entry)
- * @param parent the parent of the new structure element in the structure
- * hierarchy
- * @return the newly created element
- */
- public PDFStructElem makeStructureElement(PDFName structureType, PDFObject parent) {
- PDFStructElem structElem = new PDFStructElem(parent, structureType);
- getDocument().assignObjectNumber(structElem);
- getDocument().addTrailerObject(structElem);
- return structElem;
- }
-
/**
* Make a the head object of the name dictionary (the /Dests object).
*
import java.io.IOException;
import java.io.OutputStream;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
/** Key for the filter used for metadata */
public static final String METADATA_FILTER = "metadata";
- private List filters = new java.util.ArrayList();
+ private List<PDFFilter> filters = new java.util.ArrayList<PDFFilter>();
private boolean ignoreASCIIFilters = false;
}
}
+ List<PDFFilter> getFilters() {
+ return Collections.unmodifiableList(filters);
+ }
+
/**
* Apply the filters to the data
* in the order given and return the /Filter and /DecodeParms
* @return a String representing the filter list
*/
protected String buildFilterDictEntries() {
- if (filters != null && filters.size() > 0) {
+ if (filters.size() > 0) {
List names = new java.util.ArrayList();
List parms = new java.util.ArrayList();
* @param dict the PDFDictionary to set the entries on
*/
protected void putFilterDictEntries(PDFDictionary dict) {
- if (filters != null && filters.size() > 0) {
+ if (filters.size() > 0) {
List names = new java.util.ArrayList();
List parms = new java.util.ArrayList();
*/
public OutputStream applyFilters(OutputStream stream) throws IOException {
OutputStream out = stream;
- if (filters != null && !isDisableAllFilters()) {
+ if (!isDisableAllFilters()) {
for (int count = filters.size() - 1; count >= 0; count--) {
PDFFilter filter = (PDFFilter)filters.get(count);
out = filter.applyFilter(out);
}
/** {@inheritDoc} */
- protected int output(OutputStream stream) throws IOException {
+ public int output(OutputStream stream) throws IOException {
validate();
return super.output(stream);
}
* @param resources the resource PDF reference
*/
public PDFFormXObject(int xnumber, PDFStream contents, PDFReference resources) {
- super();
+ super(contents.getDictionary());
put("Name", new PDFName("Form" + xnumber));
this.contents = contents;
}
/** {@inheritDoc} */
- protected int output(OutputStream stream) throws IOException {
+ public int output(OutputStream stream) throws IOException {
final int len = super.output(stream);
//Now that the data has been written, it can be discarded.
int numberOfFunctions = 0;
int tempInt = 0;
StringBuffer p = new StringBuffer(256);
- p.append(getObjectID()
- + "<< \n/FunctionType " + this.functionType + " \n");
+ p.append("<< \n/FunctionType " + this.functionType + " \n");
// FunctionType 0
if (this.functionType == 0) {
p.append("] \n");
}
}
- p.append(">> \n");
+ p.append(">>");
// stream representing the function
if (this.functionDataStream != null) {
- p.append("stream\n" + this.functionDataStream
- + "\nendstream\n");
+ p.append("\nstream\n" + this.functionDataStream
+ + "\nendstream");
}
- p.append("endobj\n");
// end of if FunctionType 0
} else if (this.functionType == 2) {
+ PDFNumber.doubleOut(new Double(this.interpolationExponentN))
+ " \n");
- p.append(">> \nendobj\n");
+ p.append(">>");
} else if (this.functionType
== 3) { // fix this up when my eyes uncross
}
}
- p.append("] \n");
-
-
- p.append(">> \nendobj\n");
+ p.append("]\n>>");
} else if (this.functionType
== 4) { // fix this up when my eyes uncross
// DOMAIN
+ " \n");
}
- p.append(">> \n");
+ p.append(">>");
// stream representing the function
if (this.functionDataStream != null) {
- p.append("stream\n{ " + this.functionDataStream
- + " } \nendstream\n");
+ p.append("\nstream\n{ " + this.functionDataStream
+ + " }\nendstream");
}
- p.append("endobj\n");
}
*/
public String toPDFString() {
StringBuffer sb = new StringBuffer(64);
- sb.append(getObjectID());
sb.append("<<\n/Type /ExtGState\n");
appendVal(sb, GSTATE_ALPHA_NONSTROKE);
appendVal(sb, GSTATE_ALPHA_STROKE);
-
- sb.append(">>\nendobj\n");
+ sb.append(">>");
return sb.toString();
}
} else {
dest = "/D [" + this.pageReference + " " + destination + "]\n";
}
- return getObjectID()
- + "<< /Type /Action\n/S /GoTo\n" + dest
- + ">>\nendobj\n";
+ return "<< /Type /Action\n/S /GoTo\n" + dest + ">>";
}
/*
*/
public String toPDFString() {
StringBuffer sb = new StringBuffer(64);
- sb.append(getObjectID());
sb.append("<<\n/S /GoToR\n/F ");
sb.append(pdfFileSpec.toString());
sb.append("\n");
sb.append("/NewWindow true");
}
- sb.append(" \n>>\nendobj\n");
+ sb.append("\n>>");
return sb.toString();
}
@Override
protected String toPDFString() {
StringBuffer sb = new StringBuffer(64);
- sb.append(getObjectID());
sb.append("[/ICCBased ").append(getICCStream().referencePDF()).append("]");
- sb.append("\nendobj\n");
return sb.toString();
}
* {@inheritDoc}
*/
@Override
- protected int output(java.io.OutputStream stream)
+ public int output(java.io.OutputStream stream)
throws java.io.IOException {
int length = super.output(stream);
this.cp = null; //Free ICC stream when it's not used anymore
* @throws IOException if there is an error writing the data
* @return the length of the data written
*/
- protected int output(OutputStream stream) throws IOException {
+ public int output(OutputStream stream) throws IOException {
int length = super.output(stream);
// let it gc
put("SMask", ref);
}
//Important: do this at the end so previous values can be overwritten.
- pdfimage.populateXObjectDictionary(this);
+ pdfimage.populateXObjectDictionary(getDictionary());
}
/** {@inheritDoc} */
PDFProfile profile = getDocumentSafely().getProfile();
ByteArrayOutputStream bout = new ByteArrayOutputStream(128);
try {
- bout.write(encode(getObjectID()));
bout.write(encode("<<\n"));
if (title != null && title.length() > 0) {
bout.write(encode("/Title "));
bout.write(encode("/Trapped /False\n"));
}
- bout.write(encode(">>\nendobj\n"));
+ bout.write(encode(">>"));
} catch (IOException ioe) {
log.error("Ignored I/O exception", ioe);
}
/** {@inheritDoc} */
public String toPDFString() {
StringBuffer sb = new StringBuffer(64);
- sb.append(getObjectID());
sb.append("<<\n/S /Launch\n/F ");
sb.append(externalFileSpec.toString());
- sb.append(" \n>>\nendobj\n");
+ sb.append("\n>>");
return sb.toString();
}
f |= 1 << (5 - 1); //NoRotate, bit 5
fFlag = "/F " + f;
}
- String s = getObjectID()
- + "<< /Type /Annot\n" + "/Subtype /Link\n" + "/Rect [ "
+ String s = "<< /Type /Annot\n" + "/Subtype /Link\n" + "/Rect [ "
+ (ulx) + " " + (uly) + " "
+ (brx) + " " + (bry) + " ]\n" + "/C [ "
+ this.color + " ]\n" + "/Border [ 0 0 0 ]\n" + "/A "
+ this.action.getAction() + "\n" + "/H /I\n"
+ (this.structParent != null
? "/StructParent " + this.structParent.toString() + "\n" : "")
- + fFlag + "\n>>\nendobj\n";
+ + fFlag + "\n>>";
return s;
}
* byte arrays around so much
* {@inheritDoc}
*/
- protected int output(java.io.OutputStream stream)
+ public int output(java.io.OutputStream stream)
throws java.io.IOException {
int length = super.output(stream);
this.xmpMetadata = null; //Release DOM when it's not used anymore
return name.hashCode();
}
-
- /** {@inheritDoc} */
@Override
- protected int output(OutputStream stream) throws IOException {
+ public int output(OutputStream stream) throws IOException {
CountingOutputStream cout = new CountingOutputStream(stream);
StringBuilder textBuffer = new StringBuilder(64);
- if (hasObjectNumber()) {
- textBuffer.append(getObjectID());
- }
-
textBuffer.append(toString());
-
- if (hasObjectNumber()) {
- textBuffer.append("\nendobj\n");
- }
-
PDFDocument.flushTextBuffer(textBuffer, cout);
return cout.getCount();
}
"The number of this PDFNumber must not be empty");
}
StringBuffer sb = new StringBuffer(64);
- if (hasObjectNumber()) {
- sb.append(getObjectID());
- }
sb.append(doubleOut(getNumber().doubleValue(), 10));
- if (hasObjectNumber()) {
- sb.append("\nendobj\n");
- }
return sb.toString();
}
/** {@inheritDoc} */
@Override
- protected int output(OutputStream stream) throws IOException {
+ public int output(OutputStream stream) throws IOException {
CountingOutputStream cout = new CountingOutputStream(stream);
StringBuilder textBuffer = new StringBuilder(64);
- if (hasObjectNumber()) {
- textBuffer.append(getObjectID());
- }
-
textBuffer.append('[');
boolean first = true;
for (Map.Entry<Integer, Object> entry : this.map.entrySet()) {
formatObject(entry.getValue(), cout, textBuffer);
}
textBuffer.append(']');
-
- if (hasObjectNumber()) {
- textBuffer.append("\nendobj\n");
- }
-
PDFDocument.flushTextBuffer(textBuffer, cout);
return cout.getCount();
}
* @throws IOException if there is an error writing to the stream
* @return the number of bytes written
*/
- protected int output(OutputStream stream) throws IOException {
+ public int output(OutputStream stream) throws IOException {
byte[] pdf = this.toPDF();
stream.write(pdf);
return pdf.length;
protected byte[] toPDF() {
ByteArrayOutputStream bout = new ByteArrayOutputStream(128);
try {
- bout.write(encode(getObjectID()));
bout.write(encode("<<"));
if (parent == null) {
// root Outlines object
bout.write(encode(" /A " + actionRef + "\n"));
}
}
- bout.write(encode(">> endobj\n"));
+ bout.write(encode(">>"));
} catch (IOException ioe) {
log.error("Ignored I/O exception", ioe);
}
public byte[] toPDF() {
ByteArrayOutputStream bout = new ByteArrayOutputStream(128);
try {
- bout.write(encode(getObjectID()));
bout.write(encode("<<\n"));
bout.write(encode("/Type /OutputIntent\n"));
bout.write(encode("/DestOutputProfile " + destOutputProfile.referencePDF() + "\n"));
}
- bout.write(encode(">>\nendobj\n"));
+ bout.write(encode(">>"));
} catch (IOException ioe) {
log.error("Ignored I/O exception", ioe);
}
*/
public String toPDFString() {
StringBuffer sb = new StringBuffer(64);
- sb.append(getObjectID())
- .append("<< /Type /Pages\n/Count ")
- .append(this.getCount())
- .append("\n/Kids [");
+ sb.append("<< /Type /Pages\n/Count ")
+ .append(this.getCount())
+ .append("\n/Kids [");
for (int i = 0; i < kids.size(); i++) {
Object kid = kids.get(i);
if (kid == null) {
}
sb.append(kid).append(" ");
}
- sb.append("] >>\nendobj\n");
+ sb.append("] >>");
return sb.toString();
}
* @throws IOException if there is an error writing to the stream
* @return the PDF string.
*/
- protected int output(OutputStream stream) throws IOException {
+ public int output(OutputStream stream) throws IOException {
int vectorSize = 0;
int tempInt = 0;
byte[] buffer;
StringBuffer p = new StringBuffer(64);
- p.append(getObjectID());
p.append("<< \n/Type /Pattern \n");
if (this.resources != null) {
length += pdfStream.outputStreamData(encodedStream, stream);
}
- buffer = encode("\nendobj\n");
- stream.write(buffer);
- length += buffer.length;
-
return length;
}
return cs;
}
- /** {@inheritDoc} */
- protected int output(OutputStream stream) throws IOException {
+ @Override
+ public int output(OutputStream stream) throws IOException {
populateDictionary();
return super.output(stream);
}
}
/** {@inheritDoc} */
- protected int output(OutputStream stream) throws IOException {
+ public int output(OutputStream stream) throws IOException {
getDocument().getProfile().verifyTaggedPDF();
return super.output(stream);
}
int vectorSize;
int tempInt;
StringBuffer p = new StringBuffer(128);
- p.append(getObjectID()
- + "<< \n/ShadingType " + this.shadingType + " \n");
+ p.append("<<\n/ShadingType " + this.shadingType + " \n");
if (this.colorSpace != null) {
p.append("/ColorSpace /"
+ this.colorSpace.getName() + " \n");
}
- p.append(">> \nendobj\n");
+ p.append(">>");
return (p.toString());
}
import java.io.IOException;
import java.io.OutputStream;
+import java.io.OutputStreamWriter;
import java.io.Writer;
/**
* Create an empty stream object
*/
public PDFStream() {
- super();
+ setUp();
+ }
+
+ public PDFStream(PDFDictionary dictionary) {
+ super(dictionary);
+ setUp();
+ }
+
+ public PDFStream(PDFDictionary dictionary, boolean encodeOnTheFly) {
+ super(dictionary, encodeOnTheFly);
+ setUp();
+ }
+
+ public PDFStream(boolean encodeOnTheFly) {
+ super(encodeOnTheFly);
+ setUp();
+ }
+
+ private void setUp() {
try {
data = StreamCacheFactory.getInstance().createStreamCache();
- this.streamWriter = new java.io.OutputStreamWriter(
+ this.streamWriter = new OutputStreamWriter(
getBufferOutputStream(), PDFDocument.ENCODING);
//Buffer to minimize calls to the converter
this.streamWriter = new java.io.BufferedWriter(this.streamWriter);
- } catch (IOException ex) {
- //TODO throw the exception and catch it elsewhere
- ex.printStackTrace();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
}
}
/**
* {@inheritDoc}
*/
- protected int output(OutputStream stream) throws IOException {
+ public int output(OutputStream stream) throws IOException {
final int len = super.output(stream);
//Now that the data has been written, it can be discarded.
/**
* Class representing a PDF Structure Element.
*/
-public class PDFStructElem extends PDFDictionary implements StructureTreeElement {
+public class PDFStructElem extends PDFDictionary implements StructureTreeElement, CompressedObject {
private PDFStructElem parentElement;
* byte arrays around so much
* {@inheritDoc}
*/
- protected int output(java.io.OutputStream stream)
+ public int output(java.io.OutputStream stream)
throws java.io.IOException {
if (pfb == null) {
throw new IllegalStateException("pfb must not be null at this point");
* byte arrays around so much
* {@inheritDoc}
*/
- protected int output(java.io.OutputStream stream)
+ public int output(java.io.OutputStream stream)
throws java.io.IOException {
if (log.isDebugEnabled()) {
log.debug("Writing " + origLength + " bytes of TTF font data");
"The text of this PDFText must not be empty");
}
StringBuffer sb = new StringBuffer(64);
- sb.append(getObjectID());
sb.append("(");
sb.append(escapeText(getText()));
sb.append(")");
- sb.append("\nendobj\n");
return sb.toString();
}
/** {@inheritDoc} */
public String toPDFString() {
//TODO Convert this class into a dictionary
- return getObjectID() + getDictString() + "\nendobj\n";
- //throw new UnsupportedOperationException("This method should not be called");
+ return getDictString();
}
}
super();
}
+ protected PDFXObject(PDFDictionary dictionary) {
+ super(dictionary);
+ }
+
/**
* Returns the XObject's name.
* @return the name of the XObject
}
/**
- * Given the PDF version as a String, returns the corresponding enumerated type. The String
- * should be in the format "1.x" for PDF v1.x.
+ * Given the PDF version as a String, returns the corresponding enumerated type. The
+ * String should be in the format "1.x" for PDF v1.x.
*
* @param version a version number
* @return the corresponding Version instance
- * @throws IllegalArgumentException if the argument does not correspond to any existing PDF version
+ * @throws IllegalArgumentException if the argument does not correspond to any
+ * existing PDF version
*/
public static Version getValueOf(String version) {
for (Version pdfVersion : Version.values()) {
--- /dev/null
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.pdf.xref;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+/**
+ * A reference to an indirect object stored in an object stream. Contains the relevant
+ * information to add to a cross-reference stream.
+ */
+public class CompressedObjectReference implements ObjectReference {
+
+ private final int objectNumber;
+
+ private final int objectStreamNumber;
+
+ private final int index;
+
+ /**
+ * Creates a new reference.
+ *
+ * @param objectNumber the number of the compressed object being referenced
+ * @param objectStreamNumber the number of the object stream in which the compressed
+ * object is to be found
+ * @param index the index of the compressed object in the object stream
+ */
+ public CompressedObjectReference(int objectNumber, int objectStreamNumber, int index) {
+ this.objectNumber = objectNumber;
+ this.objectStreamNumber = objectStreamNumber;
+ this.index = index;
+ }
+
+ public void output(DataOutputStream out) throws IOException {
+ out.write(2);
+ out.writeLong(objectStreamNumber);
+ out.write(0);
+ out.write(index);
+ }
+
+ public int getObjectNumber() {
+ return objectNumber;
+ }
+
+ public int getObjectStreamNumber() {
+ return objectStreamNumber;
+ }
+
+}
--- /dev/null
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.pdf.xref;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * A representation of the cross-reference data to be output at the end of a PDF file.
+ */
+public abstract class CrossReferenceObject {
+
+ protected final TrailerDictionary trailerDictionary;
+
+ protected final long startxref;
+
+ CrossReferenceObject(TrailerDictionary trailerDictionary, long startxref) {
+ this.trailerDictionary = trailerDictionary;
+ this.startxref = startxref;
+ }
+
+ /**
+ * Writes the cross reference data to a PDF stream
+ *
+ * @param stream the stream to write the cross reference to
+ * @throws IOException if an I/O exception occurs while writing the data
+ */
+ public abstract void output(OutputStream stream) throws IOException;
+}
--- /dev/null
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+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.PDFStream;
+
+/**
+ * A cross-reference stream, as described in Section 3.4.7 of the PDF 1.5 Reference.
+ */
+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) {
+ this.objectReferences.set(ref.getObjectNumber() - 1, ref);
+ }
+ }
+
+ /** {@inheritDoc} */
+ 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(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});
+ }
+
+}
--- /dev/null
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.pdf.xref;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.List;
+
+import org.apache.fop.pdf.PDFDictionary;
+import org.apache.fop.pdf.PDFDocument;
+
+/**
+ * A cross-reference table, as described in Section 3.4.3 of the PDF 1.5 Reference.
+ */
+public class CrossReferenceTable extends CrossReferenceObject {
+
+ private final List<Long> objectReferences;
+
+ private final StringBuilder pdf = new StringBuilder(256);
+
+ public CrossReferenceTable(TrailerDictionary trailerDictionary, long startxref,
+ List<Long> location) {
+ super(trailerDictionary, startxref);
+ this.objectReferences = location;
+ }
+
+ public void output(OutputStream stream) throws IOException {
+ outputXref();
+ writeTrailer(stream);
+ }
+
+ private void outputXref() throws IOException {
+ pdf.append("xref\n0 ");
+ pdf.append(objectReferences.size() + 1);
+ pdf.append("\n0000000000 65535 f \n");
+ for (Long objectReference : objectReferences) {
+ final String padding = "0000000000";
+ String s = String.valueOf(objectReference);
+ if (s.length() > 10) {
+ throw new IOException("PDF file too large."
+ + " PDF 1.4 cannot grow beyond approx. 9.3GB.");
+ }
+ String loc = padding.substring(s.length()) + s;
+ pdf.append(loc).append(" 00000 n \n");
+ }
+ }
+
+ private void writeTrailer(OutputStream stream) throws IOException {
+ pdf.append("trailer\n");
+ stream.write(PDFDocument.encode(pdf.toString()));
+ PDFDictionary dictionary = trailerDictionary.getDictionary();
+ dictionary.put("/Size", objectReferences.size() + 1);
+ dictionary.output(stream);
+ }
+
+}
--- /dev/null
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.pdf.xref;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+/**
+ * A reference to an indirect object.
+ */
+interface ObjectReference {
+
+ /**
+ * Outputs this reference to the given stream, in the cross-reference stream format.
+ * For example, a object may output the bytes 01 00 00 00 00 00 00 01 ff 00 to
+ * indicate a non-compressed object (01), at offset 511 from the beginning of the file
+ * (00 00 00 00 00 00 01 ff), of generation number 0 (00).
+ *
+ * @param out the stream to which to output the reference
+ */
+ void output(DataOutputStream out) throws IOException;
+}
--- /dev/null
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.pdf.xref;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.pdf.PDFArray;
+import org.apache.fop.pdf.PDFDictionary;
+import org.apache.fop.pdf.PDFDocument;
+import org.apache.fop.pdf.PDFEncryption;
+import org.apache.fop.pdf.PDFInfo;
+import org.apache.fop.pdf.PDFRoot;
+import org.apache.fop.pdf.PDFText;
+import org.apache.fop.pdf.PDFWritable;
+
+/**
+ * A data class representing entries of the file trailer dictionary.
+ */
+public class TrailerDictionary {
+
+ private final PDFDictionary dictionary;
+
+ public TrailerDictionary(PDFDocument pdfDocument) {
+ this.dictionary = new PDFDictionary();
+ this.dictionary.setDocument(pdfDocument);
+ }
+
+ /** Sets the value of the Root entry. */
+ public TrailerDictionary setRoot(PDFRoot root) {
+ dictionary.put("/Root", root);
+ return this;
+ }
+
+ /** Sets the value of the Info entry. */
+ public TrailerDictionary setInfo(PDFInfo info) {
+ dictionary.put("/Info", info);
+ return this;
+ }
+
+ /** Sets the value of the Encrypt entry. */
+ public TrailerDictionary setEncryption(PDFEncryption encryption) {
+ dictionary.put("/Encrypt", encryption);
+ return this;
+ }
+
+ /** Sets the value of the ID entry. */
+ public TrailerDictionary setFileID(byte[] originalFileID, byte[] updatedFileID) {
+ // TODO this is ugly! Used to circumvent the fact that the file ID will be
+ // encrypted if directly stored as a byte array
+ class FileID implements PDFWritable {
+
+ private final byte[] fileID;
+
+ FileID(byte[] id) {
+ fileID = id;
+ }
+
+ public void outputInline(OutputStream out, StringBuilder textBuffer)
+ throws IOException {
+ PDFDocument.flushTextBuffer(textBuffer, out);
+ String hex = PDFText.toHex(fileID, true);
+ byte[] encoded = hex.getBytes("US-ASCII");
+ out.write(encoded);
+ }
+
+ }
+ PDFArray fileID = new PDFArray(new FileID(originalFileID), new FileID(updatedFileID));
+ dictionary.put("/ID", fileID);
+ return this;
+ }
+
+ PDFDictionary getDictionary() {
+ return dictionary;
+ }
+
+}
--- /dev/null
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.pdf.xref;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+/**
+ * A reference to an indirect object that is not stored in an object stream.
+ */
+class UncompressedObjectReference implements ObjectReference {
+
+ final long offset;
+
+ /**
+ * Creates a new reference.
+ *
+ * @param offset offset of the object from the beginning of the PDF file
+ */
+ UncompressedObjectReference(long offset) {
+ this.offset = offset;
+ }
+
+ public void output(DataOutputStream out) throws IOException {
+ out.write(1);
+ out.writeLong(offset);
+ out.write(0);
+ out.write(0);
+ }
+
+}
*/
PDFLogicalStructureHandler(PDFDocument pdfDoc) {
this.pdfDoc = pdfDoc;
- PDFStructTreeRoot structTreeRoot = pdfDoc.getFactory().makeStructTreeRoot(parentTree);
- rootStructureElement = pdfDoc.getFactory().makeStructureElement(
+ PDFStructTreeRoot structTreeRoot = pdfDoc.makeStructTreeRoot(parentTree);
+ rootStructureElement = pdfDoc.makeStructureElement(
FOToPDFRoleMap.mapFormattingObject("root", structTreeRoot), structTreeRoot);
structTreeRoot.addKid(rootStructureElement);
}
PDFStructElem createPageSequence(Locale language) {
- PDFStructElem structElemPart = pdfDoc.getFactory().makeStructureElement(
+ PDFStructElem structElemPart = pdfDoc.makeStructureElement(
FOToPDFRoleMap.mapFormattingObject("page-sequence", rootStructureElement),
rootStructureElement);
rootStructureElement.addKid(structElemPart);
if (maxPDFVersion == null) {
this.pdfDoc = new PDFDocument(producer);
} else {
- VersionController controller =
- VersionController.getFixedVersionController(maxPDFVersion);
+ VersionController controller
+ = VersionController.getFixedVersionController(maxPDFVersion);
this.pdfDoc = new PDFDocument(producer, controller);
}
updateInfo();
log.debug("PDF/A is active. Conformance Level: " + pdfAMode);
addPDFA1OutputIntent();
}
+
+ this.pdfDoc.enableAccessibility(userAgent.isAccessibilityEnabled());
+
return this.pdfDoc;
}
PDFStructElem parent = ancestors.getFirst();
String role = attributes.getValue("role");
PDFStructElem created;
- created = pdfFactory.makeStructureElement(
+ created = pdfFactory.getDocument().makeStructureElement(
FOToPDFRoleMap.mapFormattingObject(name, role, parent, eventBroadcaster), parent);
parent.addKid(created);
ancestors.addFirst(created);
PDFStructElem parent = ancestors.getFirst();
String role = attributes.getValue("role");
PDFStructElem created;
- created = pdfFactory.makeStructureElement(
+ created = pdfFactory.getDocument().makeStructureElement(
FOToPDFRoleMap.mapFormattingObject(name, role, parent, eventBroadcaster), parent);
parent.addKid(created);
String altTextNode = attributes.getValue(ExtensionElementMapping.URI, "alt-text");
if ("#PCDATA".equals(name)) {
created = new PDFStructElem.Placeholder(parent, name);
} else {
- created = pdfFactory.makeStructureElement(
+ created = pdfFactory.getDocument().makeStructureElement(
FOToPDFRoleMap.mapFormattingObject(name, role, parent,
eventBroadcaster), parent);
}
+++ /dev/null
-This directory contains sample FO files for testing the accessibility features
-of FOP.
-
-Every FO file in this directory has a corresponding PDF file in the pdf/
-sub-directory. The fop.xconf configuration file was used.
-
-The PDF files have been checked with Adobe Acrobat Professional 9, using both
-the full accessibility checker and the read-aloud feature. The checker reports
-no error /and/ the entire document can be read aloud.
-
-
-!! DO NOT MODIFY THOSE FILES, NEITHER THE FO NOR THE PDF !!
-
-
-... Or at least, know what you are doing
-If the FO files are modified, the resulting PDFs must be checked again, both
-with the checker and the read-aloud feature. (Sometimes the checker reports no
-problem yet part or all of the document cannot be read aloud.)
-
-The purpose of this infrastructure is to be able to quickly re-test the
-accessibility processing chain when any change has been made to it. The
-configuration file disables the compression of the PDF streams, so it is
-possible to compare a re-generated PDF with the original one by using a simple
-diff tool. The files will not be identical because of the different creation
-dates (and the ID key in the trailer), but apart from that there should be no
-difference.
-
-The rationale is that using a diff tool is much quicker and less tedious than
-running Acrobat's accessibility checker and read-aloud feature every time.
-
-
-To re-generate the PDF files:
- ../../fop -c fop.xconf text_1.fo pdf/text_1.new.pdf
- diff pdf/text_1_painter.pdf pdf/text_1.new.pdf
-Or, going through the intermediate format:
- ../../fop -c fop.xconf text_1.fo -if application/pdf text_1_if.xml
- ../../fop -c fop.xconf -ifin text_1_if.xml pdf/text_1.new.pdf
- diff pdf/text_1.pdf pdf/text_1.new.pdf
-
-
-$Id$
+++ /dev/null
-<?xml version="1.0"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (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.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<!-- $Id$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
- <fo:layout-master-set>
- <fo:simple-page-master master-name="page"
- page-height="220pt" page-width="320pt" margin="10pt">
- <fo:region-body background-image="../resources/images/bgimg72dpi.jpg"/>
- </fo:simple-page-master>
- </fo:layout-master-set>
- <fo:page-sequence master-reference="page">
- <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
- <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL
- formatting objects (XSL-FO) and an output independent formatter. It is a Java application
- that reads a formatting object (FO) tree and renders the resulting pages to a specified
- output.</fo:block>
- </fo:flow>
- </fo:page-sequence>
-</fo:root>
+++ /dev/null
-<?xml version="1.0"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (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.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<!-- $Id$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
- <fo:layout-master-set>
- <fo:simple-page-master master-name="page"
- page-height="220pt" page-width="320pt" margin="10pt">
- <fo:region-body background-image="../resources/images/bgimg72dpi.jpg"
- background-repeat="no-repeat" background-position-horizontal="50%"
- background-position-vertical="50%"/>
- </fo:simple-page-master>
- </fo:layout-master-set>
- <fo:page-sequence master-reference="page">
- <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
- <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL
- formatting objects (XSL-FO) and an output independent formatter. It is a Java application
- that reads a formatting object (FO) tree and renders the resulting pages to a specified
- output.</fo:block>
- </fo:flow>
- </fo:page-sequence>
-</fo:root>
+++ /dev/null
-<?xml version="1.0"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (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.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<!-- $Id$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
- <fo:layout-master-set>
- <fo:simple-page-master master-name="page"
- page-height="220pt" page-width="320pt" margin="10pt">
- <fo:region-body background-image="../resources/images/bgimg72dpi.png"/>
- </fo:simple-page-master>
- </fo:layout-master-set>
- <fo:page-sequence master-reference="page">
- <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
- <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL
- formatting objects (XSL-FO) and an output independent formatter. It is a Java application
- that reads a formatting object (FO) tree and renders the resulting pages to a specified
- output.</fo:block>
- </fo:flow>
- </fo:page-sequence>
-</fo:root>
+++ /dev/null
-<?xml version="1.0"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (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.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<!-- $Id$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
- <fo:layout-master-set>
- <fo:simple-page-master master-name="page"
- page-height="220pt" page-width="320pt" margin="10pt">
- <fo:region-body background-image="../resources/images/fop-logo-color-24bit.png"
- background-repeat="no-repeat" background-position-horizontal="50%"
- background-position-vertical="50%"/>
- </fo:simple-page-master>
- </fo:layout-master-set>
- <fo:page-sequence master-reference="page">
- <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
- <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL
- formatting objects (XSL-FO) and an output independent formatter. It is a Java application
- that reads a formatting object (FO) tree and renders the resulting pages to a specified
- output.</fo:block>
- </fo:flow>
- </fo:page-sequence>
-</fo:root>
+++ /dev/null
-<?xml version="1.0"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (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.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<!-- $Id$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
- <fo:layout-master-set>
- <fo:simple-page-master master-name="page"
- page-height="220pt" page-width="320pt" margin="10pt">
- <fo:region-body background-image="../resources/images/rgb-circles.svg"/>
- </fo:simple-page-master>
- </fo:layout-master-set>
- <fo:page-sequence master-reference="page">
- <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
- <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL
- formatting objects (XSL-FO) and an output independent formatter. It is a Java application
- that reads a formatting object (FO) tree and renders the resulting pages to a specified
- output.</fo:block>
- </fo:flow>
- </fo:page-sequence>
-</fo:root>
+++ /dev/null
-<?xml version="1.0"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (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.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<!-- $Id$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
- <fo:layout-master-set>
- <fo:simple-page-master master-name="page"
- page-height="220pt" page-width="320pt" margin="10pt">
- <fo:region-body background-image="../resources/images/rgb-circles.svg"
- background-repeat="no-repeat" background-position-horizontal="50%"
- background-position-vertical="50%"/>
- </fo:simple-page-master>
- </fo:layout-master-set>
- <fo:page-sequence master-reference="page">
- <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
- <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL
- formatting objects (XSL-FO) and an output independent formatter. It is a Java application
- that reads a formatting object (FO) tree and renders the resulting pages to a specified
- output.</fo:block>
- </fo:flow>
- </fo:page-sequence>
-</fo:root>
+++ /dev/null
-<?xml version="1.0" standalone="no"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (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.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<!-- $Id$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
- xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" language="en" country="GB">
- <fo:layout-master-set>
- <fo:simple-page-master master-name="page"
- page-height="220pt" page-width="320pt" margin="10pt">
- <fo:region-body column-count="2" margin-top="15pt"/>
- <fo:region-before extent="12pt"/>
- </fo:simple-page-master>
- </fo:layout-master-set>
- <fo:page-sequence master-reference="page">
- <fo:static-content flow-name="xsl-region-before">
- <fo:block font-size="8pt" text-align-last="justify">This is the page header<fo:leader/>Page
- <fo:page-number/></fo:block>
- </fo:static-content>
- <fo:static-content flow-name="xsl-footnote-separator">
- <fo:block><fo:leader leader-length="100pt" leader-pattern="rule"/></fo:block>
- </fo:static-content>
- <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
- <fo:block>(There’s another page sequence <fo:wrapper color="blue"><fo:basic-link
- internal-destination="second">below</fo:basic-link></fo:wrapper>.)</fo:block>
- <fo:block font-family="sans-serif" font-weight="bold" space-before="1em" space-after="0.2em"
- role="H1"><fo:block>About Apache FOP</fo:block></fo:block>
- <fo:block>It is a print formatter driven by XSL formatting objects (XSL-FO) and an output
- independent formatter<fo:footnote><fo:inline baseline-shift="super"
- font-size="70%">1</fo:inline><fo:footnote-body><fo:block>See the <fo:wrapper
- color="blue"><fo:basic-link
- external-destination="http://xmlgraphics.apache.org/fop/">FOP
- website</fo:basic-link></fo:wrapper> for more
- information</fo:block></fo:footnote-body></fo:footnote>. FOP has a nice logo:
- <fo:external-graphic src="../resources/images/fop-logo-color-24bit.png"
- inline-progression-dimension.maximum="100%" content-width="scale-to-fit"
- fox:alt-text="FOP Logo"/></fo:block>
- <fo:table space-before="10pt" space-after="10pt" width="100%" table-layout="fixed">
- <fo:table-header>
- <fo:table-row>
- <fo:table-cell border="2pt solid black" padding="2pt 2pt 0">
- <fo:block>Header 1.1</fo:block>
- </fo:table-cell>
- <fo:table-cell border="2pt solid black" padding="2pt 2pt 0">
- <fo:block>Header 1.2</fo:block>
- </fo:table-cell>
- </fo:table-row>
- </fo:table-header>
- <fo:table-body>
- <fo:table-row>
- <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
- <fo:block>Cell 1.1</fo:block>
- </fo:table-cell>
- <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
- <fo:block>Cell 1.2</fo:block>
- </fo:table-cell>
- </fo:table-row>
- <fo:table-row>
- <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
- <fo:block>Cell 2.1</fo:block>
- </fo:table-cell>
- <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
- <fo:block>Cell 2.2</fo:block>
- </fo:table-cell>
- </fo:table-row>
- </fo:table-body>
- </fo:table>
- <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL
- formatting objects (XSL-FO) and an output independent formatter. It is a Java application
- that reads a formatting object (FO) tree and renders the resulting pages to a specified
- output.</fo:block>
- <fo:block span="all" border-top="1pt solid black" border-bottom="1pt solid black"
- padding-before="2pt" padding-after="2pt">This fo:block element spans all the columns of the
- document. This is intended to test the abilities of the text-to-speech program.</fo:block>
- <fo:block>And now we are back to normal content flowing in two columns. Let’s start a numbered
- list:</fo:block>
- <fo:list-block provisional-distance-between-starts="15pt" provisional-label-separation="0mm"
- keep-with-previous="auto">
- <fo:list-item keep-with-previous="always">
- <fo:list-item-label end-indent="label-end()">
- <fo:block>1.</fo:block>
- </fo:list-item-label>
- <fo:list-item-body start-indent="body-start()">
- <fo:block>
- <fo:block>Line 1 of item 1</fo:block>
- <fo:block>Line 2 of item 1</fo:block>
- <fo:block>Line 3 of item 1</fo:block>
- </fo:block>
- </fo:list-item-body>
- </fo:list-item>
- <fo:list-item keep-with-previous="always">
- <fo:list-item-label end-indent="label-end()">
- <fo:block>2.</fo:block>
- </fo:list-item-label>
- <fo:list-item-body start-indent="body-start()">
- <fo:block>
- <fo:block>Line 1 of item 2</fo:block>
- <fo:block>Line 2 of item 2</fo:block>
- <fo:block>Line 3 of item 2</fo:block>
- </fo:block>
- </fo:list-item-body>
- </fo:list-item>
- </fo:list-block>
- <fo:block>And now we are going to see how a second page sequence is handled.</fo:block>
- </fo:flow>
- </fo:page-sequence>
- <fo:page-sequence master-reference="page">
- <fo:static-content flow-name="xsl-region-before">
- <fo:block font-size="8pt" text-align-last="justify">This is the page header<fo:leader/>Page
- <fo:page-number/></fo:block>
- </fo:static-content>
- <fo:static-content flow-name="xsl-footnote-separator">
- <fo:block><fo:leader leader-length="100pt" leader-pattern="rule"/></fo:block>
- </fo:static-content>
- <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
- <fo:block id="second">Apache FOP (Formatting Objects Processor) is a print formatter driven by
- XSL formatting objects (XSL-FO) and an output independent formatter<fo:footnote><fo:inline
- baseline-shift="super" font-size="70%">1</fo:inline><fo:footnote-body><fo:block>See the
- <fo:wrapper color="blue"><fo:basic-link
- external-destination="http://xmlgraphics.apache.org/fop/">FOP
- website</fo:basic-link></fo:wrapper> for more
- information</fo:block></fo:footnote-body></fo:footnote>. It is a Java application that
- reads a formatting object (FO) tree and renders the resulting pages to a specified
- output.</fo:block>
- <fo:table space-before="10pt" space-after="10pt" width="100%" table-layout="fixed">
- <fo:table-header>
- <fo:table-row>
- <fo:table-cell border="2pt solid black" padding="2pt 2pt 0">
- <fo:block>Header 1.1</fo:block>
- </fo:table-cell>
- <fo:table-cell border="2pt solid black" padding="2pt 2pt 0">
- <fo:block>Header 1.2</fo:block>
- </fo:table-cell>
- </fo:table-row>
- </fo:table-header>
- <fo:table-body>
- <fo:table-row>
- <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
- <fo:block>Cell 1.1</fo:block>
- </fo:table-cell>
- <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
- <fo:block>Cell 1.2</fo:block>
- </fo:table-cell>
- </fo:table-row>
- <fo:table-row>
- <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
- <fo:block>Cell 2.1</fo:block>
- </fo:table-cell>
- <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
- <fo:block>Cell 2.2</fo:block>
- </fo:table-cell>
- </fo:table-row>
- </fo:table-body>
- </fo:table>
- <fo:block language="fr" country="FR">Apache FOP (Formatting Objects Processor) est une
- application de mise en page de documents respectant le standard XSL-FO. À partir d’un
- document au format XSL-FO, cette application écrite en Java effectue une mise en page et
- renvoie un document prêt pour impression.</fo:block>
- <fo:block span="all" border-top="1pt solid black" border-bottom="1pt solid black"
- padding-before="2pt" padding-after="2pt">This fo:block element spans all the columns of the
- document. This is intended to test the abilities of the text-to-speech program.</fo:block>
- <fo:block>And now we are back to normal content flowing in two columns. Let’s start a numbered
- list:</fo:block>
- <fo:list-block provisional-distance-between-starts="15pt" provisional-label-separation="0mm"
- keep-with-previous="auto">
- <fo:list-item keep-with-previous="always">
- <fo:list-item-label end-indent="label-end()">
- <fo:block>1.</fo:block>
- </fo:list-item-label>
- <fo:list-item-body start-indent="body-start()">
- <fo:block>
- <fo:block>Line 1 of item 1</fo:block>
- <fo:block>Line 2 of item 1</fo:block>
- <fo:block>Line 3 of item 1</fo:block>
- </fo:block>
- </fo:list-item-body>
- </fo:list-item>
- <fo:list-item keep-with-previous="always">
- <fo:list-item-label end-indent="label-end()">
- <fo:block>2.</fo:block>
- </fo:list-item-label>
- <fo:list-item-body start-indent="body-start()">
- <fo:block>
- <fo:block>Line 1 of item 2</fo:block>
- <fo:block>Line 2 of item 2</fo:block>
- <fo:block>Line 3 of item 2</fo:block>
- </fo:block>
- </fo:list-item-body>
- </fo:list-item>
- </fo:list-block>
- <fo:block>The end of the document has now been reached.</fo:block>
- </fo:flow>
- </fo:page-sequence>
-</fo:root>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<fop version="1.0">
- <accessibility>true</accessibility>
- <source-resolution>144</source-resolution>
- <use-cache>false</use-cache>
- <font-base>../resources/fonts/</font-base>
- <renderers>
- <renderer mime="application/pdf">
- <filterList>
- <value>null</value>
- </filterList>
- <filterList type="image">
- <value>flate</value>
- <value>ascii-85</value>
- </filterList>
- <fonts>
- <font embed-url="DejaVuLGCSerif.ttf">
- <font-triplet name="DejaVu" style="normal" weight="normal"/>
- </font>
- </fonts>
- </renderer>
- </renderers>
-</fop>
+++ /dev/null
-<?xml version="1.0" standalone="no"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (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.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<!-- $Id$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
- xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" language="en" country="GB">
- <fo:layout-master-set>
- <fo:simple-page-master master-name="page"
- page-height="220pt" page-width="320pt" margin="10pt">
- <fo:region-body/>
- </fo:simple-page-master>
- </fo:layout-master-set>
- <fo:page-sequence master-reference="page">
- <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
- <fo:block>This document contains an image in the JPEG format: <fo:external-graphic
- src="../resources/images/cmyk.jpg"
- inline-progression-dimension.maximum="100%" content-width="scale-to-fit"
- fox:alt-text="CMYK colours"/>. Here is the end of the text.</fo:block>
- </fo:flow>
- </fo:page-sequence>
-</fo:root>
+++ /dev/null
-<?xml version="1.0" standalone="no"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (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.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<!-- $Id$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
- xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" language="en" country="GB">
- <fo:layout-master-set>
- <fo:simple-page-master master-name="page"
- page-height="220pt" page-width="320pt" margin="10pt">
- <fo:region-body/>
- </fo:simple-page-master>
- </fo:layout-master-set>
- <fo:page-sequence master-reference="page">
- <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
- <fo:block>This document contains an image in the PNG format: <fo:external-graphic
- src="../resources/images/fop-logo-color-24bit.png"
- inline-progression-dimension.maximum="100%" content-width="scale-to-fit"
- fox:alt-text="FOP Logo"/>. Here is the end of the text.</fo:block>
- </fo:flow>
- </fo:page-sequence>
-</fo:root>
+++ /dev/null
-<?xml version="1.0" standalone="no"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (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.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<!-- $Id$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
- xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" language="en" country="GB">
- <fo:layout-master-set>
- <fo:simple-page-master master-name="page"
- page-height="220pt" page-width="320pt" margin="10pt">
- <fo:region-body/>
- </fo:simple-page-master>
- </fo:layout-master-set>
- <fo:page-sequence master-reference="page">
- <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
- <fo:block>This document contains an image in the SVG format: <fo:external-graphic
- src="../resources/images/circles.svg"
- inline-progression-dimension.maximum="75pt" content-width="scale-to-fit"
- fox:alt-text="Nice circles"/>. And here is the same image as an instream-foreign-object:
- <fo:instream-foreign-object inline-progression-dimension.maximum="75pt"
- content-width="scale-down-to-fit" fox:alt-text="The same nice circles">
-<svg xmlns="http://www.w3.org/2000/svg" width="12cm" height="12cm">
- <g style="fill-opacity:0.7; stroke:black; stroke-width:0.1cm;">
- <circle cx="6cm" cy="2cm" r="100" style="fill:red;" transform="translate(0,50)" />
- <circle cx="6cm" cy="2cm" r="100" style="fill:blue;" transform="translate(70,150)" />
- <circle cx="6cm" cy="2cm" r="100" style="fill:green;" transform="translate(-70,150)"/>
- </g>
-</svg>
- </fo:instream-foreign-object>.</fo:block>
- </fo:flow>
- </fo:page-sequence>
-</fo:root>
+++ /dev/null
-<?xml version="1.0" standalone="no"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (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.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<!-- $Id$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
- xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" language="en" country="GB">
- <fo:layout-master-set>
- <fo:simple-page-master master-name="page"
- page-height="320pt" page-width="320pt" margin="10pt">
- <fo:region-body/>
- </fo:simple-page-master>
- </fo:layout-master-set>
- <fo:page-sequence master-reference="page">
- <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
- <fo:block>This document contains an image in the WMF format: <fo:external-graphic
- src="../resources/images/testChart.wmf"
- inline-progression-dimension.maximum="100%" content-width="scale-to-fit"
- fox:alt-text="Metafile Companion Test Chart"/> Here is the end of the text.</fo:block>
- </fo:flow>
- </fo:page-sequence>
-</fo:root>
+++ /dev/null
-<?xml version="1.0"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (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.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<!-- $Id$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
- <fo:layout-master-set>
- <fo:simple-page-master master-name="page"
- page-height="220pt" page-width="320pt" margin="10pt">
- <fo:region-body/>
- </fo:simple-page-master>
- </fo:layout-master-set>
- <fo:page-sequence master-reference="page">
- <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify"
- text-align-last="justify">
- <fo:block>This is a text followed by a leader with leader-pattern="use-content", the
- content being text:<fo:leader leader-pattern="use-content"><fo:inline> •
- </fo:inline></fo:leader>1</fo:block>
- <fo:block space-before="10pt">This is a text followed by a leader with
- leader-pattern="use-content", the content being images:<fo:leader
- leader-pattern="use-content"><fo:external-graphic
- src="../resources/images/list-item.png"/></fo:leader>1</fo:block>
- </fo:flow>
- </fo:page-sequence>
-</fo:root>
+++ /dev/null
-<?xml version="1.0" standalone="no"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (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.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<!-- $Id$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
- xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" language="en" country="GB">
- <fo:layout-master-set>
- <fo:simple-page-master master-name="page"
- page-height="220pt" page-width="320pt" margin="10pt">
- <fo:region-body/>
- </fo:simple-page-master>
- </fo:layout-master-set>
- <fo:page-sequence master-reference="page">
- <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
- <fo:block>This is a <fo:wrapper color="blue"><fo:basic-link
- internal-destination="FOP">link</fo:basic-link></fo:wrapper> to the next
- paragraph.</fo:block>
- <fo:block id="FOP">Apache FOP (Formatting Objects Processor) is a print formatter driven by
- XSL formatting objects (XSL-FO) and an output independent formatter. It is a Java
- application that reads a formatting object (FO) tree and renders the resulting pages to a
- specified output.</fo:block>
- <fo:block>For more information, see the <fo:wrapper color="blue"><fo:basic-link
- external-destination="http://xmlgraphics.apache.org/fop/">FOP
- website</fo:basic-link></fo:wrapper>.</fo:block>
- </fo:flow>
- </fo:page-sequence>
-</fo:root>
+++ /dev/null
-<?xml version="1.0"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (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.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<!-- $Id$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
- <fo:layout-master-set>
- <fo:simple-page-master master-name="page"
- page-height="220pt" page-width="320pt" margin="10pt">
- <fo:region-body/>
- </fo:simple-page-master>
- </fo:layout-master-set>
- <fo:page-sequence master-reference="page">
- <fo:flow flow-name="xsl-region-body" hyphenate="true" font-family="sans-serif">
- <fo:block role="H1" font-weight="bold" font-size="150%"
- space-before.minimum="1.5em"
- space-before.optimum="2em"
- space-before.maximum="3em"
- space-before.precedence="1000"
- space-after.minimum="0.2em"
- space-after.optimum="0.2em"
- space-after.maximum="0.5em"
- space-after.precedence="1000">Title 1: To Start With</fo:block>
- <fo:block role="H2" font-weight="bold" font-size="120%"
- space-before.minimum="1.2em"
- space-before.optimum="1.5em"
- space-before.maximum="2em"
- space-before.precedence="900"
- space-after.minimum="0.2em"
- space-after.optimum="0.2em"
- space-after.maximum="0.5em"
- space-after.precedence="900">Title 2: A Sub-Title</fo:block>
- <fo:block text-align="justify">Apache FOP (Formatting Objects Processor) is a print formatter
- driven by XSL formatting objects (XSL-FO) and an output independent formatter. It is a Java
- application that reads a formatting object (FO) tree and renders the resulting pages to a
- specified output.</fo:block>
- <fo:block role="H2" font-weight="bold" font-size="120%"
- space-before.minimum="1.2em"
- space-before.optimum="1.5em"
- space-before.maximum="2em"
- space-before.precedence="900"
- space-after.minimum="0.2em"
- space-after.optimum="0.2em"
- space-after.maximum="0.5em"
- space-after.precedence="900">Title 2: Another Sub-Title</fo:block>
- <fo:block text-align="justify">Apache FOP (Formatting Objects Processor) is a print formatter
- driven by XSL formatting objects (XSL-FO) and an output independent formatter. It is a Java
- application that reads a formatting object (FO) tree and renders the resulting pages to a
- specified output.</fo:block>
- <fo:block role="H1" font-weight="bold" font-size="150%"
- space-before.minimum="1.5em"
- space-before.optimum="2em"
- space-before.maximum="3em"
- space-before.precedence="1000"
- space-after.minimum="0.2em"
- space-after.optimum="0.2em"
- space-after.maximum="0.5em"
- space-after.precedence="1000">Title 1: Second Title</fo:block>
- <fo:block role="H2" font-weight="bold" font-size="120%"
- space-before.minimum="1.2em"
- space-before.optimum="1.5em"
- space-before.maximum="2em"
- space-before.precedence="900"
- space-after.minimum="0.2em"
- space-after.optimum="0.2em"
- space-after.maximum="0.5em"
- space-after.precedence="900">Title 2: A Sample Table</fo:block>
- <fo:block>See data below:</fo:block>
- <fo:table table-layout="fixed" width="70%" start-indent="15%" border="0.5pt solid black">
- <fo:table-header start-indent="0" font-weight="bold">
- <fo:table-row>
- <fo:table-cell border="0.5pt solid black" padding="2pt">
- <fo:block>Header 1</fo:block>
- </fo:table-cell>
- <fo:table-cell border="0.5pt solid black" padding="2pt">
- <fo:block>Header 2</fo:block>
- </fo:table-cell>
- </fo:table-row>
- </fo:table-header>
- <fo:table-footer start-indent="0" font-weight="bold">
- <fo:table-row>
- <fo:table-cell border="0.5pt solid black" padding="2pt">
- <fo:block>Footer 1</fo:block>
- </fo:table-cell>
- <fo:table-cell border="0.5pt solid black" padding="2pt">
- <fo:block>Footer 2</fo:block>
- </fo:table-cell>
- </fo:table-row>
- </fo:table-footer>
- <fo:table-body start-indent="0">
- <fo:table-row>
- <fo:table-cell border="0.5pt solid black" padding="2pt">
- <fo:block>Cell 1.1</fo:block>
- </fo:table-cell>
- <fo:table-cell border="0.5pt solid black" padding="2pt">
- <fo:block>Cell 1.2</fo:block>
- </fo:table-cell>
- </fo:table-row>
- <fo:table-row>
- <fo:table-cell border="0.5pt solid black" padding="2pt">
- <fo:block>Cell 2.1</fo:block>
- </fo:table-cell>
- <fo:table-cell border="0.5pt solid black" padding="2pt">
- <fo:block>Cell 2.2</fo:block>
- </fo:table-cell>
- </fo:table-row>
- </fo:table-body>
- </fo:table>
- <fo:block text-align="justify" space-before="0.5em">That’s all folks.</fo:block>
- </fo:flow>
- </fo:page-sequence>
-</fo:root>
+++ /dev/null
-<?xml version="1.0"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (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.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<!-- $Id$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
- <fo:layout-master-set>
- <fo:simple-page-master master-name="page"
- page-height="220pt" page-width="320pt" margin="10pt">
- <fo:region-body/>
- </fo:simple-page-master>
- </fo:layout-master-set>
- <fo:page-sequence master-reference="page">
- <fo:flow flow-name="xsl-region-body" hyphenate="true" font-family="sans-serif">
- <fo:block role="H1" font-weight="bold" font-size="150%"
- space-before.minimum="1.5em"
- space-before.optimum="2em"
- space-before.maximum="3em"
- space-before.precedence="1000"
- space-after.minimum="0.2em"
- space-after.optimum="0.2em"
- space-after.maximum="0.5em"
- space-after.precedence="1000">Title 1: To Start With</fo:block>
- <fo:block role="Header2" font-weight="bold" font-size="120%"
- space-before.minimum="1.2em"
- space-before.optimum="1.5em"
- space-before.maximum="2em"
- space-before.precedence="900"
- space-after.minimum="0.2em"
- space-after.optimum="0.2em"
- space-after.maximum="0.5em"
- space-after.precedence="900">A Sub-Title With a Non-Standard Role</fo:block>
- <fo:block text-align="justify">Apache FOP (Formatting Objects Processor) is a print formatter
- driven by XSL formatting objects (XSL-FO) and an output independent formatter. It is a Java
- application that reads a formatting object (FO) tree and renders the resulting pages to a
- specified output.</fo:block>
- <fo:block role="H2" font-weight="bold" font-size="120%"
- space-before.minimum="1.2em"
- space-before.optimum="1.5em"
- space-before.maximum="2em"
- space-before.precedence="900"
- space-after.minimum="0.2em"
- space-after.optimum="0.2em"
- space-after.maximum="0.5em"
- space-after.precedence="900">Title 2: Another Sub-Title</fo:block>
- <fo:block text-align="justify">Apache FOP (Formatting Objects Processor) is a print formatter
- driven by XSL formatting objects (XSL-FO) and an output independent formatter. It is a Java
- application that reads a formatting object (FO) tree and renders the resulting pages to a
- specified output.</fo:block>
- <fo:block role="H1" font-weight="bold" font-size="150%"
- space-before.minimum="1.5em"
- space-before.optimum="2em"
- space-before.maximum="3em"
- space-before.precedence="1000"
- space-after.minimum="0.2em"
- space-after.optimum="0.2em"
- space-after.maximum="0.5em"
- space-after.precedence="1000">Title 1: Second Title</fo:block>
- <fo:block role="H2" font-weight="bold" font-size="120%"
- space-before.minimum="1.2em"
- space-before.optimum="1.5em"
- space-before.maximum="2em"
- space-before.precedence="900"
- space-after.minimum="0.2em"
- space-after.optimum="0.2em"
- space-after.maximum="0.5em"
- space-after.precedence="900">Title 2: A Sample Table</fo:block>
- <fo:block>See data below:</fo:block>
- <fo:table table-layout="fixed" width="70%" start-indent="15%" border="0.5pt solid black">
- <fo:table-header start-indent="0" font-weight="bold" role="TableHeader">
- <fo:table-row>
- <fo:table-cell border="0.5pt solid black" padding="2pt">
- <fo:block>Header 1</fo:block>
- </fo:table-cell>
- <fo:table-cell border="0.5pt solid black" padding="2pt">
- <fo:block>Header 2</fo:block>
- </fo:table-cell>
- </fo:table-row>
- </fo:table-header>
- <fo:table-footer start-indent="0" font-weight="bold">
- <fo:table-row>
- <fo:table-cell border="0.5pt solid black" padding="2pt">
- <fo:block>Footer 1</fo:block>
- </fo:table-cell>
- <fo:table-cell border="0.5pt solid black" padding="2pt">
- <fo:block>Footer 2</fo:block>
- </fo:table-cell>
- </fo:table-row>
- </fo:table-footer>
- <fo:table-body start-indent="0">
- <fo:table-row>
- <fo:table-cell border="0.5pt solid black" padding="2pt">
- <fo:block>Cell 1.1</fo:block>
- </fo:table-cell>
- <fo:table-cell border="0.5pt solid black" padding="2pt">
- <fo:block>Cell 1.2</fo:block>
- </fo:table-cell>
- </fo:table-row>
- <fo:table-row>
- <fo:table-cell border="0.5pt solid black" padding="2pt">
- <fo:block>Cell 2.1</fo:block>
- </fo:table-cell>
- <fo:table-cell border="0.5pt solid black" padding="2pt">
- <fo:block>Cell 2.2</fo:block>
- </fo:table-cell>
- </fo:table-row>
- </fo:table-body>
- </fo:table>
- <fo:block text-align="justify" space-before="0.5em">That’s all folks.</fo:block>
- </fo:flow>
- </fo:page-sequence>
-</fo:root>
+++ /dev/null
-<?xml version="1.0"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (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.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<!-- $Id$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
- <fo:layout-master-set>
- <fo:simple-page-master master-name="page"
- page-height="220pt" page-width="320pt" margin="10pt">
- <fo:region-body/>
- </fo:simple-page-master>
- </fo:layout-master-set>
- <fo:page-sequence master-reference="page">
- <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
- <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL
- formatting objects (XSL-FO) and an output independent formatter. It is a Java application
- that reads a formatting object (FO) tree and renders the resulting pages to a specified
- output.</fo:block>
- </fo:flow>
- </fo:page-sequence>
-</fo:root>
+++ /dev/null
-<?xml version="1.0"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (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.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<!-- $Id$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
- <fo:layout-master-set>
- <fo:simple-page-master master-name="page"
- page-height="220pt" page-width="320pt" margin="10pt">
- <fo:region-body/>
- </fo:simple-page-master>
- </fo:layout-master-set>
- <fo:page-sequence master-reference="page">
- <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
- <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL
- formatting objects (XSL-FO) and an output independent formatter. It is a Java application
- that reads a formatting object (FO) tree and renders the resulting pages to a specified
- output.</fo:block>
- <fo:block language="fr" country="FR">Apache FOP (Formatting Objects Processor) est une
- application de mise en page de documents respectant le standard XSL-FO. À partir d’un
- document au format XSL-FO, cette application écrite en Java effectue une mise en page et
- renvoie un document prêt pour impression.</fo:block>
- <fo:block>Back to English and let’s say it again: Apache FOP (Formatting Objects Processor) is
- a print formatter driven by XSL formatting objects (XSL-FO) and an output independent
- formatter.</fo:block>
- </fo:flow>
- </fo:page-sequence>
-</fo:root>
+++ /dev/null
-<?xml version="1.0"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (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.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<!-- $Id$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
- <fo:layout-master-set>
- <fo:simple-page-master master-name="page"
- page-height="220pt" page-width="320pt" margin="10pt">
- <fo:region-body/>
- </fo:simple-page-master>
- </fo:layout-master-set>
- <fo:page-sequence master-reference="page">
- <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify" font-family="DejaVu">
- <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL
- formatting objects (XSL-FO) and an output independent formatter. It is a Java application
- that reads a formatting object (FO) tree and renders the resulting pages to a specified
- output.</fo:block>
- </fo:flow>
- </fo:page-sequence>
-</fo:root>
import org.apache.fop.image.loader.batik.ImageLoaderTestCase;
import org.apache.fop.image.loader.batik.ImagePreloaderTestCase;
import org.apache.fop.intermediate.IFMimickingTestCase;
+import org.apache.fop.layoutmgr.PageSequenceLayoutManagerTestCase;
+import org.apache.fop.pdf.PDFLibraryTestSuite;
import org.apache.fop.render.extensions.prepress.PageBoundariesTestCase;
import org.apache.fop.render.extensions.prepress.PageScaleTestCase;
-import org.apache.fop.layoutmgr.PageSequenceLayoutManagerTestCase;
import org.apache.fop.render.pdf.PDFAConformanceTestCase;
import org.apache.fop.render.pdf.PDFCMapTestCase;
import org.apache.fop.render.pdf.PDFEncodingTestCase;
import org.apache.fop.render.ps.PSTestSuite;
import org.apache.fop.render.rtf.RichTextFormatTestSuite;
import org.apache.fop.traits.MinOptMaxTestCase;
-import org.apache.fop.pdf.PDFLibraryTestSuite;
/**
* Test suite for basic functionality of FOP.
encodedBytes[i++] = (byte) (in & 0xff);
}
}
- private String startStream = "1 0 obj\n" +
- "<< /Length 5 0 R /Filter /FlateDecode >>\n" +
- "stream\n";
- private String endStream = "endstream\nendobj\n";
+ private String startStream = "<< /Length 5 0 R /Filter /FlateDecode >>\n"
+ + "stream\n";
+
+ private String endStream = "endstream";
@Before
public void setUp() {
--- /dev/null
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.pdf;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.List;
+
+import org.junit.Test;
+
+import org.apache.fop.pdf.xref.CompressedObjectReference;
+
+public class ObjectStreamManagerTestCase {
+
+ private List<CompressedObjectReference> compressedObjectReferences;
+
+ private MockPdfDocument pdfDocument;
+
+ @Test
+ public void add() {
+ final int expectedCapacity = 100;
+ final int numCompressedObjects = expectedCapacity * 2 + 1;
+ createCompressObjectReferences(numCompressedObjects);
+ assertEquals(numCompressedObjects, compressedObjectReferences.size());
+ int objectStreamNumber1 = assertSameObjectStream(0, expectedCapacity);
+ int objectStreamNumber2 = assertSameObjectStream(expectedCapacity, expectedCapacity * 2);
+ int objectStreamNumber3 = assertSameObjectStream(expectedCapacity * 2, numCompressedObjects);
+ assertDifferent(objectStreamNumber1, objectStreamNumber2, objectStreamNumber3);
+ assertEquals(objectStreamNumber3, pdfDocument.previous.getObjectNumber());
+ }
+
+ private void createCompressObjectReferences(int numObjects) {
+ pdfDocument = new MockPdfDocument();
+ ObjectStreamManager sut = new ObjectStreamManager(pdfDocument);
+ for (int obNum = 1; obNum <= numObjects; obNum++) {
+ sut.add(createCompressedObject(obNum));
+ }
+ compressedObjectReferences = sut.getCompressedObjectReferences();
+ }
+
+ private static class MockPdfDocument extends PDFDocument {
+
+ private ObjectStream previous;
+
+ public MockPdfDocument() {
+ super("");
+ }
+
+ public void assignObjectNumber(PDFObject obj) {
+ super.assignObjectNumber(obj);
+ if (obj instanceof ObjectStream) {
+ ObjectStream objStream = (ObjectStream) obj;
+ ObjectStream previous = (ObjectStream) objStream.get("Extends");
+ if (previous == null) {
+ assertEquals(this.previous, previous);
+ }
+ this.previous = objStream;
+ }
+ }
+ }
+
+ private CompressedObject createCompressedObject(final int objectNumber) {
+ return new CompressedObject() {
+
+ public int getObjectNumber() {
+ return objectNumber;
+ }
+
+ public int output(OutputStream outputStream) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+
+ private int assertSameObjectStream(int from, int to) {
+ int objectStreamNumber = getObjectStreamNumber(from);
+ for (int i = from + 1; i < to; i++) {
+ assertEquals(objectStreamNumber, getObjectStreamNumber(i));
+ }
+ return objectStreamNumber;
+ }
+
+ private int getObjectStreamNumber(int index) {
+ return compressedObjectReferences.get(index).getObjectStreamNumber();
+ }
+
+ private void assertDifferent(int objectStreamNumber1, int objectStreamNumber2,
+ int objectStreamNumber3) {
+ assertTrue(objectStreamNumber1 != objectStreamNumber2);
+ assertTrue(objectStreamNumber1 != objectStreamNumber3);
+ assertTrue(objectStreamNumber2 != objectStreamNumber3);
+ }
+}
--- /dev/null
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.pdf;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class ObjectStreamTestCase {
+
+ private static final String OBJECT_CONTENT = "<<\n /Foo True\n /Bar False\n>>\n";
+
+ private PDFDocument pdfDocument;
+
+ private ObjectStream objectStream;
+
+ private List<MockCompressedObject> compressedObjects;
+
+ @Before
+ public void setUp() throws Exception {
+ pdfDocument = new PDFDocument("PDFObjectStreamTestCase");
+ objectStream = new ObjectStream();
+ pdfDocument.assignObjectNumber(objectStream);
+ compressedObjects = Arrays.asList(new MockCompressedObject(), new MockCompressedObject());
+ }
+
+ @Test
+ public void testSingleObjectStream() throws IOException {
+ populateObjectStream();
+ testOutput();
+ }
+
+ @Test
+ public void testObjectStreamCollection() throws IOException {
+ objectStream = new ObjectStream(objectStream);
+ pdfDocument.assignObjectNumber(objectStream);
+ populateObjectStream();
+ testOutput();
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void directObjectsAreNotAllowed() throws Exception {
+ objectStream.addObject(new MockCompressedObject());
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void nullObjectsAreNotAllowed() throws Exception {
+ objectStream.addObject(null);
+ }
+
+ private void testOutput() throws IOException {
+ String expected = getExpectedOutput();
+ String actual = getActualOutput();
+ assertEquals(expected, actual);
+ }
+
+ private void populateObjectStream() {
+ for (MockCompressedObject obj : compressedObjects) {
+ pdfDocument.assignObjectNumber(obj);
+ objectStream.addObject(obj);
+ }
+ }
+
+ private String getExpectedOutput() {
+ int numObs = compressedObjects.size();
+ int objectStreamNumber = objectStream.getObjectNumber();
+ int offsetsLength = 9;
+ StringBuilder expected = new StringBuilder();
+ expected.append("<<\n");
+ ObjectStream previous = (ObjectStream) objectStream.get("Extends");
+ if (previous != null) {
+ expected.append(" /Extends ").append(previous.getObjectNumber()).append(" 0 R\n");
+ }
+ expected.append(" /Type /ObjStm\n")
+ .append(" /N ").append(numObs).append("\n")
+ .append(" /First ").append(offsetsLength).append('\n')
+ .append(" /Length ").append(OBJECT_CONTENT.length() * 2 + offsetsLength + 1).append('\n')
+ .append(">>\n")
+ .append("stream\n");
+ int offset = 0;
+ int num = 1;
+ for (PDFObject ob : compressedObjects) {
+ expected.append(objectStreamNumber + num++).append(' ').append(offset).append('\n');
+ offset += ob.toPDFString().length();
+ }
+ for (PDFObject ob : compressedObjects) {
+ expected.append(ob.toPDFString());
+ }
+ expected.append("\nendstream");
+ return expected.toString();
+ }
+
+ private String getActualOutput() throws IOException {
+ ByteArrayOutputStream actual = new ByteArrayOutputStream();
+ objectStream.getFilterList().setDisableAllFilters(true);
+ objectStream.output(actual);
+ return actual.toString("US-ASCII");
+ }
+
+ private static class MockCompressedObject extends PDFObject implements CompressedObject {
+
+ @Override
+ protected String toPDFString() {
+ return OBJECT_CONTENT;
+ }
+ }
+
+}
final String digits = "\\d+";
final String hexDigits = "\\p{XDigit}+";
- dictionary.mustContain("1" + whitespace + "0" + whitespace + "obj");
-
dictionary.mustContain("/Filter" + whitespace + "/Standard\\b");
dictionary.mustContain("/V" + whitespace + "(" + digits + ")")
--- /dev/null
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.pdf;
+
+import static org.junit.Assert.assertFalse;
+
+import org.junit.Test;
+
+public class PDFFilterListTestCase {
+
+ @Test
+ public void testFilterList() {
+ PDFFilterList filterList = new PDFFilterList();
+ assertFalse(filterList.isInitialized());
+ }
+}
PDFNullTestCase.class,
PDFNumsArrayTestCase.class,
PDFRectangleTestCase.class,
- PDFReferenceTestCase.class
+ PDFReferenceTestCase.class,
+ VersionTestCase.class,
+ VersionControllerTestCase.class
})
public class PDFLibraryTestSuite {
}
protected final PDFObject parent = new DummyPDFObject();
/** The test subject */
protected PDFObject pdfObjectUnderTest;
- /** The string to begin describing the object <code>"1 0 obj\n"</code> */
- protected final String beginObj = "1 0 obj\n";
- /** The string to end describing the object <code>"\nendobj\n"</code> */
- protected final String endObj = "\nendobj\n";
private static class DummyPDFObject extends PDFObject {
outStream.reset();
object.setObjectNumber(1);
// Test the length of the output string is returned correctly.
- String string = beginObj + expectedString + endObj;
- assertEquals(string.length(), object.output(outStream));
- assertEquals(string, outStream.toString());
+ assertEquals(expectedString.length(), object.output(outStream));
+ assertEquals(expectedString, outStream.toString());
}
}
--- /dev/null
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.pdf;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class PDFStreamTestCase {
+
+ private PDFStream stream;
+
+ @Before
+ public void createStream() {
+ stream = new PDFStream();
+ stream.setObjectNumber(1);
+ PDFDocument pdfDocument = new PDFDocument("Apache FOP");
+ stream.setDocument(pdfDocument);
+ }
+
+ @Test
+ public void testFilterSetup() {
+ testGetFilterList();
+ testSetupFilterList();
+ }
+
+ private void testGetFilterList() {
+ PDFFilterList filterList = stream.getFilterList();
+ assertFalse(filterList.isInitialized());
+ assertEquals(0, filterList.getFilters().size());
+ }
+
+ private void testSetupFilterList() {
+ stream.setupFilterList();
+ PDFFilterList filterList = stream.getFilterList();
+ assertTrue(filterList.isInitialized());
+ assertEquals(1, filterList.getFilters().size());
+ PDFFilter filter = filterList.getFilters().get(0);
+ assertEquals("/FlateDecode", filter.getName());
+ }
+
+ @Test
+ public void customFilter() {
+ PDFFilterList filters = stream.getFilterList();
+ filters.addFilter("null");
+ assertTrue(filters.isInitialized());
+ assertEquals(1, filters.getFilters().size());
+ PDFFilter filter = filters.getFilters().get(0);
+ assertEquals("", filter.getName());
+ }
+
+ @Test
+ public void testStream() throws IOException {
+ PDFFilterList filters = stream.getFilterList();
+ filters.addFilter("null");
+ byte[] bytes = createSampleData();
+ stream.setData(bytes);
+ ByteArrayOutputStream actual = new ByteArrayOutputStream();
+ stream.outputRawStreamData(actual);
+ assertArrayEquals(bytes, actual.toByteArray());
+ }
+
+ @Test
+ public void testEncodeStream() throws IOException {
+ PDFFilterList filters = stream.getFilterList();
+ filters.addFilter("null");
+ byte[] bytes = createSampleData();
+ stream.setData(bytes);
+ ByteArrayOutputStream actual = new ByteArrayOutputStream();
+ StreamCache streamCache = stream.encodeStream();
+ streamCache.outputContents(actual);
+ assertArrayEquals(bytes, actual.toByteArray());
+ }
+
+ @Test
+ public void testEncodeAndWriteStream() throws IOException {
+ PDFFilterList filters = stream.getFilterList();
+ filters.addFilter("null");
+ byte[] bytes = createSampleData();
+ stream.setData(bytes);
+ ByteArrayOutputStream actual = new ByteArrayOutputStream();
+ PDFNumber number = new PDFNumber();
+ stream.encodeAndWriteStream(actual, number);
+ assertArrayEquals(createSampleStreamData(), actual.toByteArray());
+ }
+
+ private byte[] createSampleData() {
+ byte[] bytes = new byte[10];
+ for (int i = 0; i < 10; i++) {
+ bytes[i] = (byte) i;
+ }
+ return bytes;
+ }
+
+ private byte[] createSampleStreamData() throws IOException {
+ ByteArrayOutputStream stream = new ByteArrayOutputStream();
+ stream.write("stream\n".getBytes("US-ASCII"));
+ stream.write(createSampleData());
+ stream.write("\nendstream".getBytes("US-ASCII"));
+ return stream.toByteArray();
+ }
+}
--- /dev/null
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.pdf.xref;
+
+import static org.junit.Assert.assertArrayEquals;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+
+public class CompressedObjectReferenceTestCase extends ObjectReferenceTest {
+
+ @Test
+ public void testOutput() throws IOException {
+ runTest(Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0), 0);
+ runTest(Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0x1), 4);
+ runTest(Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0xf3), 16);
+ runTest(Arrays.asList(0, 0, 0, 0, 0, 0, 0x5, 0xf7), 128);
+ runTest(Arrays.asList(0, 0, 0, 0, 0, 0x9, 0xfb, 0xd), 0xae);
+ runTest(Arrays.asList(0, 0, 0, 0, 0x11, 0xff, 0x15, 0xe9), 0xff);
+ }
+
+ private void runTest(List<Integer> expectedObjectStreamBytes, int index) throws IOException {
+ int objectStreamNumber = (int) computeNumberFromBytes(expectedObjectStreamBytes);
+ sut = new CompressedObjectReference(0, objectStreamNumber, index);
+ byte[] expected = createExpectedOutput((byte) 2, expectedObjectStreamBytes, index);
+ byte[] actual = getActualOutput();
+ assertArrayEquals(expected, actual);
+ }
+
+}
--- /dev/null
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.pdf.xref;
+
+import static org.junit.Assert.assertArrayEquals;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Before;
+
+import org.apache.fop.pdf.PDFDocument;
+import org.apache.fop.pdf.PDFInfo;
+import org.apache.fop.pdf.PDFPages;
+import org.apache.fop.pdf.PDFRoot;
+
+public abstract class CrossReferenceObjectTest {
+
+ protected static final int STARTXREF = 12345;
+
+ protected PDFDocument pdfDocument;
+
+ protected TrailerDictionary trailerDictionary;
+
+ private CrossReferenceObject crossReferenceObject;
+
+ @Before
+ public void setUp() throws UnsupportedEncodingException {
+ pdfDocument = new PDFDocument("Apache FOP");
+ Map<String, List<String>> filterMap = pdfDocument.getFilterMap();
+ filterMap.put("default", Arrays.asList("null"));
+ PDFRoot root = new PDFRoot(1, new PDFPages(10));
+ PDFInfo info = new PDFInfo();
+ info.setObjectNumber(2);
+ byte[] fileID =
+ new byte[] {0x01, 0x23, 0x45, 0x67, (byte) 0x89, (byte) 0xab, (byte) 0xcd, (byte) 0xef};
+ trailerDictionary = new TrailerDictionary(pdfDocument)
+ .setRoot(root)
+ .setInfo(info)
+ .setFileID(fileID, fileID);
+ }
+
+ protected void runTest() throws IOException {
+ crossReferenceObject = createCrossReferenceObject();
+ byte[] expected = createExpectedCrossReferenceData();
+ byte[] actual = createActualCrossReferenceData();
+ assertArrayEquals(expected, actual);
+ }
+
+ protected abstract CrossReferenceObject createCrossReferenceObject();
+
+ protected abstract byte[] createExpectedCrossReferenceData() throws IOException;
+
+ protected byte[] createActualCrossReferenceData() throws IOException {
+ ByteArrayOutputStream pdf = new ByteArrayOutputStream();
+ crossReferenceObject.output(pdf);
+ pdf.close();
+ return pdf.toByteArray();
+ }
+
+ protected byte[] getBytes(StringBuilder stringBuilder) {
+ return getBytes(stringBuilder.toString());
+ }
+
+ protected byte[] getBytes(String string) {
+ try {
+ return string.getBytes("US-ASCII");
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Outputs the given byte array to a file with the given name. Use for debugging
+ * purpose.
+ */
+ protected void streamToFile(byte[] bytes, String filename) throws IOException {
+ OutputStream output = new FileOutputStream(filename);
+ output.write(bytes);
+ output.close();
+ }
+
+}
--- /dev/null
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.pdf.xref;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.Test;
+
+public class CrossReferenceStreamTestCase extends CrossReferenceObjectTest {
+
+ private List<Long> uncompressedObjectOffsets;
+
+ private List<CompressedObjectReference> compressedObjectReferences;
+
+ @Test
+ public void testWithNoOffset() throws IOException {
+ List<Long> emptyList = Collections.emptyList();
+ test(emptyList);
+ }
+
+ @Test
+ public void testWithOffsets() throws IOException {
+ test(new ArrayList<Long>(Arrays.asList(0L, 1L, 2L, 3L, 4L)));
+ }
+
+ @Test
+ public void testWithBigOffsets() throws IOException {
+ test(new ArrayList<Long>(Arrays.asList(0xffL, 0xffffL, 0xffffffffL, 0xffffffffffffffffL)));
+ }
+
+ @Test
+ public void testWithObjectStreams1() throws IOException {
+ List<CompressedObjectReference> compressedObjectReferences =
+ Arrays.asList(new CompressedObjectReference(2, 1, 0));
+ test(Arrays.asList(0L, null), compressedObjectReferences);
+ }
+
+ @Test
+ public void testWithObjectStreams2() throws IOException {
+ int numIndirectObjects = 2;
+ int numCompressedObjects = 1;
+ List<Long> indirectObjectOffsets
+ = new ArrayList<Long>(numIndirectObjects + numCompressedObjects);
+ for (long i = 0; i < numIndirectObjects; i++) {
+ indirectObjectOffsets.add(i);
+ }
+ List<CompressedObjectReference> compressedObjectReferences
+ = new ArrayList<CompressedObjectReference>();
+ for (int index = 0; index < numCompressedObjects; index++) {
+ indirectObjectOffsets.add(null);
+ int obNum = numIndirectObjects + index + 1;
+ compressedObjectReferences.add(new CompressedObjectReference(obNum,
+ numIndirectObjects, index));
+ }
+ test(indirectObjectOffsets, compressedObjectReferences);
+ }
+
+ private void test(List<Long> indirectObjectOffsets) throws IOException {
+ List<CompressedObjectReference> compressedObjectReferences = Collections.emptyList();
+ test(indirectObjectOffsets, compressedObjectReferences);
+ }
+
+ private void test(List<Long> indirectObjectOffsets,
+ List<CompressedObjectReference> compressedObjectReferences) throws IOException {
+ this.uncompressedObjectOffsets = indirectObjectOffsets;
+ this.compressedObjectReferences = compressedObjectReferences;
+ runTest();
+ }
+
+ @Override
+ protected CrossReferenceObject createCrossReferenceObject() {
+ return new CrossReferenceStream(pdfDocument,
+ uncompressedObjectOffsets.size() + 1,
+ trailerDictionary,
+ STARTXREF,
+ uncompressedObjectOffsets,
+ compressedObjectReferences);
+ }
+
+ @Override
+ protected byte[] createExpectedCrossReferenceData() throws IOException {
+ List<ObjectReference> objectReferences
+ = new ArrayList<ObjectReference>(uncompressedObjectOffsets.size());
+ for (Long offset : uncompressedObjectOffsets) {
+ objectReferences.add(offset == null ? null : new UncompressedObjectReference(offset));
+ }
+ for (CompressedObjectReference ref : compressedObjectReferences) {
+ objectReferences.set(ref.getObjectNumber() - 1, ref);
+ }
+ int maxObjectNumber = objectReferences.size() + 1;
+ ByteArrayOutputStream stream = new ByteArrayOutputStream();
+ StringBuilder expected = new StringBuilder(256);
+ expected.append(maxObjectNumber + " 0 obj\n")
+ .append("<<\n")
+ .append(" /Root 1 0 R\n")
+ .append(" /Info 2 0 R\n")
+ .append(" /ID [<0123456789ABCDEF> <0123456789ABCDEF>]\n")
+ .append(" /Type /XRef\n")
+ .append(" /Size ").append(Integer.toString(maxObjectNumber + 1)).append('\n')
+ .append(" /W [1 8 2]\n")
+ .append(" /Length ").append(Integer.toString((maxObjectNumber + 1) * 11 + 1)).append('\n')
+ .append(">>\n")
+ .append("stream\n");
+ stream.write(getBytes(expected));
+ DataOutputStream data = new DataOutputStream(stream);
+ data.write(new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, (byte) 0xff, (byte) 0xff});
+ for (ObjectReference objectReference : objectReferences) {
+ objectReference.output(data);
+ }
+ data.write(1);
+ data.writeLong(STARTXREF);
+ data.write(0);
+ data.write(0);
+ data.close();
+ stream.write(getBytes("\nendstream\nendobj\n"));
+ return stream.toByteArray();
+ }
+
+}
--- /dev/null
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.pdf.xref;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.Test;
+
+public class CrossReferenceTableTestCase extends CrossReferenceObjectTest {
+
+ private List<Long> offsets;
+
+ @Test
+ public void testWithNoOffset() throws IOException {
+ List<Long> emptyList = Collections.emptyList();
+ runTest(emptyList);
+ }
+
+ @Test
+ public void testWithOffsets() throws IOException {
+ runTest(Arrays.asList(0L, 1L, 2L, 3L, 4L));
+ }
+
+ @Test
+ public void testWithBigOffsets() throws IOException {
+ runTest(Arrays.asList(0xffL, 0xffffL, 0x7fffffffL));
+ }
+
+ private void runTest(List<Long> offsets) throws IOException {
+ this.offsets = offsets;
+ runTest();
+ }
+
+ @Override
+ protected CrossReferenceObject createCrossReferenceObject() {
+ return new CrossReferenceTable(trailerDictionary, STARTXREF, offsets);
+ }
+
+ @Override
+ protected byte[] createExpectedCrossReferenceData() throws IOException {
+ StringBuilder expected = new StringBuilder(256);
+ expected.append("xref\n0 ")
+ .append(offsets.size() + 1)
+ .append("\n0000000000 65535 f \n");
+ for (Long objectReference : offsets) {
+ final String padding = "0000000000";
+ String s = String.valueOf(objectReference).toString();
+ String loc = padding.substring(s.length()) + s;
+ expected.append(loc).append(" 00000 n \n");
+ }
+ expected.append("trailer\n<<\n")
+ .append(" /Root 1 0 R\n")
+ .append(" /Info 2 0 R\n")
+ .append(" /ID [<0123456789ABCDEF> <0123456789ABCDEF>]\n")
+ .append(" /Size ").append(Integer.toString(offsets.size() + 1)).append('\n')
+ .append(">>\n");
+ return getBytes(expected);
+ }
+
+}
--- /dev/null
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.pdf.xref;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.List;
+
+abstract class ObjectReferenceTest {
+
+ protected ObjectReference sut;
+
+ protected long computeNumberFromBytes(List<Integer> expectedOffsetBytes) {
+ assert expectedOffsetBytes.size() <= 8;
+ long offset = 0;
+ for (int b : expectedOffsetBytes) {
+ offset = offset << 8 | b;
+ }
+ return offset;
+ }
+
+ protected byte[] createExpectedOutput(byte field1, List<Integer> field2, int field3) {
+ assert field2.size() == 8;
+ assert (field3 & 0xffff) == field3;
+ byte[] expected = new byte[11];
+ int index = 0;
+ expected[index++] = field1;
+ for (Integer b : field2) {
+ expected[index++] = b.byteValue();
+ }
+ expected[index++] = (byte) ((field3 & 0xff00) >> 8);
+ expected[index++] = (byte) (field3 & 0xff);
+ return expected;
+ }
+
+ protected byte[] getActualOutput() throws IOException {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ DataOutputStream dataOutputStream = new DataOutputStream(out);
+ sut.output(dataOutputStream);
+ dataOutputStream.close();
+ return out.toByteArray();
+ }
+
+}
--- /dev/null
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.pdf.xref;
+
+import static org.junit.Assert.assertArrayEquals;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+
+public class UncompressedObjectReferenceTestCase extends ObjectReferenceTest {
+
+ @Test
+ public void test1ByteOffsets() throws IOException {
+ run1ByteOffsetTest(0x0);
+ run1ByteOffsetTest(0xf);
+ run1ByteOffsetTest(0x10);
+ run1ByteOffsetTest(0xff);
+ }
+
+ private void run1ByteOffsetTest(int offset) throws IOException {
+ runIntegerOffsetTest(Arrays.asList(0, 0, 0, offset));
+ }
+
+ @Test
+ public void test2ByteOffsets() throws IOException {
+ runIntegerOffsetTest(Arrays.asList(0, 0, 1, 0xff));
+ runIntegerOffsetTest(Arrays.asList(0, 0, 0xa0, 0xff));
+ }
+
+ @Test
+ public void test3ByteOffsets() throws IOException {
+ runIntegerOffsetTest(Arrays.asList(0, 2, 0x12, 0x34));
+ runIntegerOffsetTest(Arrays.asList(0, 0xee, 0x56, 0x78));
+ }
+
+ @Test
+ public void test4ByteOffsets() throws IOException {
+ runIntegerOffsetTest(Arrays.asList(0x6, 0x12, 0x34, 0x56));
+ runIntegerOffsetTest(Arrays.asList(0xf1, 0x9a, 0xbc, 0xde));
+ }
+
+ @Test
+ public void test5ByteOffsets() throws IOException {
+ runTest(Arrays.asList(0, 0, 0, 0x7, 0x78, 0x9a, 0xbc, 0xde));
+ runTest(Arrays.asList(0, 0, 0, 0xbf, 0xf0, 0, 0x1, 0x2));
+ }
+
+ @Test
+ public void test8ByteOffsets() throws IOException {
+ runTest(Arrays.asList(0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8));
+ runTest(Arrays.asList(0xf9, 0xe8, 0xd7, 0xc6, 0xb5, 0xa4, 0x93, 0x82));
+ }
+
+ private void runIntegerOffsetTest(List<Integer> expectedOffsetBytes) throws IOException {
+ List<Integer> expectedLongOffset = new ArrayList<Integer>(8);
+ expectedLongOffset.addAll(Arrays.asList(0, 0, 0, 0));
+ expectedLongOffset.addAll(expectedOffsetBytes);
+ runTest(expectedLongOffset);
+ }
+
+ private void runTest(List<Integer> expectedOffsetBytes) throws IOException {
+ long offset = computeNumberFromBytes(expectedOffsetBytes);
+ sut = new UncompressedObjectReference(offset);
+ byte[] expected = createExpectedOutput((byte) 1, expectedOffsetBytes, (byte) 0);
+ byte[] actual = getActualOutput();
+ assertArrayEquals(expected, actual);
+ }
+
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<fop version="1.0">
+ <accessibility>true</accessibility>
+ <source-resolution>144</source-resolution>
+ <use-cache>false</use-cache>
+ <font-base>../../resources/fonts/ttf/</font-base>
+ <renderers>
+ <renderer mime="application/pdf">
+ <version>1.5</version>
+ <filterList>
+ <value>null</value>
+ </filterList>
+ <filterList type="image">
+ <value>flate</value>
+ <value>ascii-85</value>
+ </filterList>
+ <fonts>
+ <font embed-url="DejaVuLGCSerif.ttf">
+ <font-triplet name="DejaVu" style="normal" weight="normal"/>
+ </font>
+ </fonts>
+ </renderer>
+ </renderers>
+</fop>
--- /dev/null
+<?xml version="1.0" standalone="no"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (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.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!-- $Id$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
+ xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" language="en" country="GB">
+ <fo:layout-master-set>
+ <fo:simple-page-master master-name="page"
+ page-height="220pt" page-width="320pt" margin="10pt">
+ <fo:region-body column-count="2" margin-top="15pt"/>
+ <fo:region-before extent="12pt"/>
+ </fo:simple-page-master>
+ </fo:layout-master-set>
+ <fo:page-sequence master-reference="page">
+ <fo:static-content flow-name="xsl-region-before">
+ <fo:block font-size="8pt" text-align-last="justify">This is the page header<fo:leader/>Page
+ <fo:page-number/></fo:block>
+ </fo:static-content>
+ <fo:static-content flow-name="xsl-footnote-separator">
+ <fo:block><fo:leader leader-length="100pt" leader-pattern="rule"/></fo:block>
+ </fo:static-content>
+ <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
+ <fo:block>(There’s another page sequence <fo:wrapper color="blue"><fo:basic-link
+ internal-destination="second">below</fo:basic-link></fo:wrapper>.)</fo:block>
+ <fo:block font-family="sans-serif" font-weight="bold" space-before="1em" space-after="0.2em"
+ role="H1"><fo:block>About Apache FOP</fo:block></fo:block>
+ <fo:block>It is a print formatter driven by XSL formatting objects (XSL-FO) and an output
+ independent formatter<fo:footnote><fo:inline baseline-shift="super"
+ font-size="70%">1</fo:inline><fo:footnote-body><fo:block>See the <fo:wrapper
+ color="blue"><fo:basic-link
+ external-destination="http://xmlgraphics.apache.org/fop/">FOP
+ website</fo:basic-link></fo:wrapper> for more
+ information</fo:block></fo:footnote-body></fo:footnote>. FOP has a nice logo:
+ <fo:external-graphic src="../../resources/images/fop-logo-color-24bit.png"
+ inline-progression-dimension.maximum="100%" content-width="scale-to-fit"
+ fox:alt-text="FOP Logo"/></fo:block>
+ <fo:table space-before="10pt" space-after="10pt" width="100%" table-layout="fixed">
+ <fo:table-header>
+ <fo:table-row>
+ <fo:table-cell border="2pt solid black" padding="2pt 2pt 0">
+ <fo:block>Header 1.1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell border="2pt solid black" padding="2pt 2pt 0">
+ <fo:block>Header 1.2</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-header>
+ <fo:table-body>
+ <fo:table-row>
+ <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
+ <fo:block>Cell 1.1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
+ <fo:block>Cell 1.2</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ <fo:table-row>
+ <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
+ <fo:block>Cell 2.1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
+ <fo:block>Cell 2.2</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-body>
+ </fo:table>
+ <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL
+ formatting objects (XSL-FO) and an output independent formatter. It is a Java application
+ that reads a formatting object (FO) tree and renders the resulting pages to a specified
+ output.</fo:block>
+ <fo:block span="all" border-top="1pt solid black" border-bottom="1pt solid black"
+ padding-before="2pt" padding-after="2pt">This fo:block element spans all the columns of the
+ document. This is intended to test the abilities of the text-to-speech program.</fo:block>
+ <fo:block>And now we are back to normal content flowing in two columns. Let’s start a numbered
+ list:</fo:block>
+ <fo:list-block provisional-distance-between-starts="15pt" provisional-label-separation="0mm"
+ keep-with-previous="auto">
+ <fo:list-item keep-with-previous="always">
+ <fo:list-item-label end-indent="label-end()">
+ <fo:block>1.</fo:block>
+ </fo:list-item-label>
+ <fo:list-item-body start-indent="body-start()">
+ <fo:block>
+ <fo:block>Line 1 of item 1</fo:block>
+ <fo:block>Line 2 of item 1</fo:block>
+ <fo:block>Line 3 of item 1</fo:block>
+ </fo:block>
+ </fo:list-item-body>
+ </fo:list-item>
+ <fo:list-item keep-with-previous="always">
+ <fo:list-item-label end-indent="label-end()">
+ <fo:block>2.</fo:block>
+ </fo:list-item-label>
+ <fo:list-item-body start-indent="body-start()">
+ <fo:block>
+ <fo:block>Line 1 of item 2</fo:block>
+ <fo:block>Line 2 of item 2</fo:block>
+ <fo:block>Line 3 of item 2</fo:block>
+ </fo:block>
+ </fo:list-item-body>
+ </fo:list-item>
+ </fo:list-block>
+ <fo:block>And now we are going to see how a second page sequence is handled.</fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+ <fo:page-sequence master-reference="page">
+ <fo:static-content flow-name="xsl-region-before">
+ <fo:block font-size="8pt" text-align-last="justify">This is the page header<fo:leader/>Page
+ <fo:page-number/></fo:block>
+ </fo:static-content>
+ <fo:static-content flow-name="xsl-footnote-separator">
+ <fo:block><fo:leader leader-length="100pt" leader-pattern="rule"/></fo:block>
+ </fo:static-content>
+ <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
+ <fo:block id="second">Apache FOP (Formatting Objects Processor) is a print formatter driven by
+ XSL formatting objects (XSL-FO) and an output independent formatter<fo:footnote><fo:inline
+ baseline-shift="super" font-size="70%">1</fo:inline><fo:footnote-body><fo:block>See the
+ <fo:wrapper color="blue"><fo:basic-link
+ external-destination="http://xmlgraphics.apache.org/fop/">FOP
+ website</fo:basic-link></fo:wrapper> for more
+ information</fo:block></fo:footnote-body></fo:footnote>. It is a Java application that
+ reads a formatting object (FO) tree and renders the resulting pages to a specified
+ output.</fo:block>
+ <fo:table space-before="10pt" space-after="10pt" width="100%" table-layout="fixed">
+ <fo:table-header>
+ <fo:table-row>
+ <fo:table-cell border="2pt solid black" padding="2pt 2pt 0">
+ <fo:block>Header 1.1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell border="2pt solid black" padding="2pt 2pt 0">
+ <fo:block>Header 1.2</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-header>
+ <fo:table-body>
+ <fo:table-row>
+ <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
+ <fo:block>Cell 1.1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
+ <fo:block>Cell 1.2</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ <fo:table-row>
+ <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
+ <fo:block>Cell 2.1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
+ <fo:block>Cell 2.2</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-body>
+ </fo:table>
+ <fo:block language="fr" country="FR">Apache FOP (Formatting Objects Processor) est une
+ application de mise en page de documents respectant le standard XSL-FO. À partir d’un
+ document au format XSL-FO, cette application écrite en Java effectue une mise en page et
+ renvoie un document prêt pour impression.</fo:block>
+ <fo:block span="all" border-top="1pt solid black" border-bottom="1pt solid black"
+ padding-before="2pt" padding-after="2pt">This fo:block element spans all the columns of the
+ document. This is intended to test the abilities of the text-to-speech program.</fo:block>
+ <fo:block>And now we are back to normal content flowing in two columns. Let’s start a numbered
+ list:</fo:block>
+ <fo:list-block provisional-distance-between-starts="15pt" provisional-label-separation="0mm"
+ keep-with-previous="auto">
+ <fo:list-item keep-with-previous="always">
+ <fo:list-item-label end-indent="label-end()">
+ <fo:block>1.</fo:block>
+ </fo:list-item-label>
+ <fo:list-item-body start-indent="body-start()">
+ <fo:block>
+ <fo:block>Line 1 of item 1</fo:block>
+ <fo:block>Line 2 of item 1</fo:block>
+ <fo:block>Line 3 of item 1</fo:block>
+ </fo:block>
+ </fo:list-item-body>
+ </fo:list-item>
+ <fo:list-item keep-with-previous="always">
+ <fo:list-item-label end-indent="label-end()">
+ <fo:block>2.</fo:block>
+ </fo:list-item-label>
+ <fo:list-item-body start-indent="body-start()">
+ <fo:block>
+ <fo:block>Line 1 of item 2</fo:block>
+ <fo:block>Line 2 of item 2</fo:block>
+ <fo:block>Line 3 of item 2</fo:block>
+ </fo:block>
+ </fo:list-item-body>
+ </fo:list-item>
+ </fo:list-block>
+ <fo:block>The end of the document has now been reached.</fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+</fo:root>
--- /dev/null
+This directory contains sample FO files for testing the accessibility features
+of FOP.
+
+Every FO file in this directory has a corresponding PDF file in the pdf/
+sub-directory. The fop.xconf configuration file was used.
+
+The PDF files have been checked with Adobe Acrobat Professional 9, using both
+the full accessibility checker and the read-aloud feature. The checker reports
+no error /and/ the entire document can be read aloud.
+
+
+!! DO NOT MODIFY THOSE FILES, NEITHER THE FO NOR THE PDF !!
+
+
+... Or at least, know what you are doing
+If the FO files are modified, the resulting PDFs must be checked again, both
+with the checker and the read-aloud feature. (Sometimes the checker reports no
+problem yet part or all of the document cannot be read aloud.)
+
+The purpose of this infrastructure is to be able to quickly re-test the
+accessibility processing chain when any change has been made to it. The
+configuration file disables the compression of the PDF streams, so it is
+possible to compare a re-generated PDF with the original one by using a simple
+diff tool. The files will not be identical because of the different creation
+dates (and the ID key in the trailer), but apart from that there should be no
+difference.
+
+The rationale is that using a diff tool is much quicker and less tedious than
+running Acrobat's accessibility checker and read-aloud feature every time.
+
+
+To re-generate the PDF files:
+ ../../fop -c fop.xconf text_1.fo pdf/text_1.new.pdf
+ diff pdf/text_1_painter.pdf pdf/text_1.new.pdf
+Or, going through the intermediate format:
+ ../../fop -c fop.xconf text_1.fo -if application/pdf text_1_if.xml
+ ../../fop -c fop.xconf -ifin text_1_if.xml pdf/text_1.new.pdf
+ diff pdf/text_1.pdf pdf/text_1.new.pdf
+
+
+$Id$
--- /dev/null
+<?xml version="1.0"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (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.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!-- $Id$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
+ <fo:layout-master-set>
+ <fo:simple-page-master master-name="page"
+ page-height="220pt" page-width="320pt" margin="10pt">
+ <fo:region-body background-image="../../resources/images/bgimg72dpi.jpg"/>
+ </fo:simple-page-master>
+ </fo:layout-master-set>
+ <fo:page-sequence master-reference="page">
+ <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
+ <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL
+ formatting objects (XSL-FO) and an output independent formatter. It is a Java application
+ that reads a formatting object (FO) tree and renders the resulting pages to a specified
+ output.</fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+</fo:root>
--- /dev/null
+<?xml version="1.0"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (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.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!-- $Id$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
+ <fo:layout-master-set>
+ <fo:simple-page-master master-name="page"
+ page-height="220pt" page-width="320pt" margin="10pt">
+ <fo:region-body background-image="../../resources/images/bgimg72dpi.jpg"
+ background-repeat="no-repeat" background-position-horizontal="50%"
+ background-position-vertical="50%"/>
+ </fo:simple-page-master>
+ </fo:layout-master-set>
+ <fo:page-sequence master-reference="page">
+ <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
+ <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL
+ formatting objects (XSL-FO) and an output independent formatter. It is a Java application
+ that reads a formatting object (FO) tree and renders the resulting pages to a specified
+ output.</fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+</fo:root>
--- /dev/null
+<?xml version="1.0"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (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.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!-- $Id$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
+ <fo:layout-master-set>
+ <fo:simple-page-master master-name="page"
+ page-height="220pt" page-width="320pt" margin="10pt">
+ <fo:region-body background-image="../../resources/images/bgimg72dpi.png"/>
+ </fo:simple-page-master>
+ </fo:layout-master-set>
+ <fo:page-sequence master-reference="page">
+ <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
+ <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL
+ formatting objects (XSL-FO) and an output independent formatter. It is a Java application
+ that reads a formatting object (FO) tree and renders the resulting pages to a specified
+ output.</fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+</fo:root>
--- /dev/null
+<?xml version="1.0"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (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.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!-- $Id$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
+ <fo:layout-master-set>
+ <fo:simple-page-master master-name="page"
+ page-height="220pt" page-width="320pt" margin="10pt">
+ <fo:region-body background-image="../../resources/images/fop-logo-color-24bit.png"
+ background-repeat="no-repeat" background-position-horizontal="50%"
+ background-position-vertical="50%"/>
+ </fo:simple-page-master>
+ </fo:layout-master-set>
+ <fo:page-sequence master-reference="page">
+ <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
+ <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL
+ formatting objects (XSL-FO) and an output independent formatter. It is a Java application
+ that reads a formatting object (FO) tree and renders the resulting pages to a specified
+ output.</fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+</fo:root>
--- /dev/null
+<?xml version="1.0"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (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.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!-- $Id$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
+ <fo:layout-master-set>
+ <fo:simple-page-master master-name="page"
+ page-height="220pt" page-width="320pt" margin="10pt">
+ <fo:region-body background-image="../../resources/images/rgb-circles.svg"/>
+ </fo:simple-page-master>
+ </fo:layout-master-set>
+ <fo:page-sequence master-reference="page">
+ <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
+ <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL
+ formatting objects (XSL-FO) and an output independent formatter. It is a Java application
+ that reads a formatting object (FO) tree and renders the resulting pages to a specified
+ output.</fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+</fo:root>
--- /dev/null
+<?xml version="1.0"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (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.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!-- $Id$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
+ <fo:layout-master-set>
+ <fo:simple-page-master master-name="page"
+ page-height="220pt" page-width="320pt" margin="10pt">
+ <fo:region-body background-image="../../resources/images/rgb-circles.svg"
+ background-repeat="no-repeat" background-position-horizontal="50%"
+ background-position-vertical="50%"/>
+ </fo:simple-page-master>
+ </fo:layout-master-set>
+ <fo:page-sequence master-reference="page">
+ <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
+ <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL
+ formatting objects (XSL-FO) and an output independent formatter. It is a Java application
+ that reads a formatting object (FO) tree and renders the resulting pages to a specified
+ output.</fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+</fo:root>
--- /dev/null
+<?xml version="1.0" standalone="no"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (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.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!-- $Id$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
+ xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" language="en" country="GB">
+ <fo:layout-master-set>
+ <fo:simple-page-master master-name="page"
+ page-height="220pt" page-width="320pt" margin="10pt">
+ <fo:region-body column-count="2" margin-top="15pt"/>
+ <fo:region-before extent="12pt"/>
+ </fo:simple-page-master>
+ </fo:layout-master-set>
+ <fo:page-sequence master-reference="page">
+ <fo:static-content flow-name="xsl-region-before">
+ <fo:block font-size="8pt" text-align-last="justify">This is the page header<fo:leader/>Page
+ <fo:page-number/></fo:block>
+ </fo:static-content>
+ <fo:static-content flow-name="xsl-footnote-separator">
+ <fo:block><fo:leader leader-length="100pt" leader-pattern="rule"/></fo:block>
+ </fo:static-content>
+ <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
+ <fo:block>(There’s another page sequence <fo:wrapper color="blue"><fo:basic-link
+ internal-destination="second">below</fo:basic-link></fo:wrapper>.)</fo:block>
+ <fo:block font-family="sans-serif" font-weight="bold" space-before="1em" space-after="0.2em"
+ role="H1"><fo:block>About Apache FOP</fo:block></fo:block>
+ <fo:block>It is a print formatter driven by XSL formatting objects (XSL-FO) and an output
+ independent formatter<fo:footnote><fo:inline baseline-shift="super"
+ font-size="70%">1</fo:inline><fo:footnote-body><fo:block>See the <fo:wrapper
+ color="blue"><fo:basic-link
+ external-destination="http://xmlgraphics.apache.org/fop/">FOP
+ website</fo:basic-link></fo:wrapper> for more
+ information</fo:block></fo:footnote-body></fo:footnote>. FOP has a nice logo:
+ <fo:external-graphic src="../../resources/images/fop-logo-color-24bit.png"
+ inline-progression-dimension.maximum="100%" content-width="scale-to-fit"
+ fox:alt-text="FOP Logo"/></fo:block>
+ <fo:table space-before="10pt" space-after="10pt" width="100%" table-layout="fixed">
+ <fo:table-header>
+ <fo:table-row>
+ <fo:table-cell border="2pt solid black" padding="2pt 2pt 0">
+ <fo:block>Header 1.1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell border="2pt solid black" padding="2pt 2pt 0">
+ <fo:block>Header 1.2</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-header>
+ <fo:table-body>
+ <fo:table-row>
+ <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
+ <fo:block>Cell 1.1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
+ <fo:block>Cell 1.2</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ <fo:table-row>
+ <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
+ <fo:block>Cell 2.1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
+ <fo:block>Cell 2.2</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-body>
+ </fo:table>
+ <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL
+ formatting objects (XSL-FO) and an output independent formatter. It is a Java application
+ that reads a formatting object (FO) tree and renders the resulting pages to a specified
+ output.</fo:block>
+ <fo:block span="all" border-top="1pt solid black" border-bottom="1pt solid black"
+ padding-before="2pt" padding-after="2pt">This fo:block element spans all the columns of the
+ document. This is intended to test the abilities of the text-to-speech program.</fo:block>
+ <fo:block>And now we are back to normal content flowing in two columns. Let’s start a numbered
+ list:</fo:block>
+ <fo:list-block provisional-distance-between-starts="15pt" provisional-label-separation="0mm"
+ keep-with-previous="auto">
+ <fo:list-item keep-with-previous="always">
+ <fo:list-item-label end-indent="label-end()">
+ <fo:block>1.</fo:block>
+ </fo:list-item-label>
+ <fo:list-item-body start-indent="body-start()">
+ <fo:block>
+ <fo:block>Line 1 of item 1</fo:block>
+ <fo:block>Line 2 of item 1</fo:block>
+ <fo:block>Line 3 of item 1</fo:block>
+ </fo:block>
+ </fo:list-item-body>
+ </fo:list-item>
+ <fo:list-item keep-with-previous="always">
+ <fo:list-item-label end-indent="label-end()">
+ <fo:block>2.</fo:block>
+ </fo:list-item-label>
+ <fo:list-item-body start-indent="body-start()">
+ <fo:block>
+ <fo:block>Line 1 of item 2</fo:block>
+ <fo:block>Line 2 of item 2</fo:block>
+ <fo:block>Line 3 of item 2</fo:block>
+ </fo:block>
+ </fo:list-item-body>
+ </fo:list-item>
+ </fo:list-block>
+ <fo:block>And now we are going to see how a second page sequence is handled.</fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+ <fo:page-sequence master-reference="page">
+ <fo:static-content flow-name="xsl-region-before">
+ <fo:block font-size="8pt" text-align-last="justify">This is the page header<fo:leader/>Page
+ <fo:page-number/></fo:block>
+ </fo:static-content>
+ <fo:static-content flow-name="xsl-footnote-separator">
+ <fo:block><fo:leader leader-length="100pt" leader-pattern="rule"/></fo:block>
+ </fo:static-content>
+ <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
+ <fo:block id="second">Apache FOP (Formatting Objects Processor) is a print formatter driven by
+ XSL formatting objects (XSL-FO) and an output independent formatter<fo:footnote><fo:inline
+ baseline-shift="super" font-size="70%">1</fo:inline><fo:footnote-body><fo:block>See the
+ <fo:wrapper color="blue"><fo:basic-link
+ external-destination="http://xmlgraphics.apache.org/fop/">FOP
+ website</fo:basic-link></fo:wrapper> for more
+ information</fo:block></fo:footnote-body></fo:footnote>. It is a Java application that
+ reads a formatting object (FO) tree and renders the resulting pages to a specified
+ output.</fo:block>
+ <fo:table space-before="10pt" space-after="10pt" width="100%" table-layout="fixed">
+ <fo:table-header>
+ <fo:table-row>
+ <fo:table-cell border="2pt solid black" padding="2pt 2pt 0">
+ <fo:block>Header 1.1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell border="2pt solid black" padding="2pt 2pt 0">
+ <fo:block>Header 1.2</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-header>
+ <fo:table-body>
+ <fo:table-row>
+ <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
+ <fo:block>Cell 1.1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
+ <fo:block>Cell 1.2</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ <fo:table-row>
+ <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
+ <fo:block>Cell 2.1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
+ <fo:block>Cell 2.2</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-body>
+ </fo:table>
+ <fo:block language="fr" country="FR">Apache FOP (Formatting Objects Processor) est une
+ application de mise en page de documents respectant le standard XSL-FO. À partir d’un
+ document au format XSL-FO, cette application écrite en Java effectue une mise en page et
+ renvoie un document prêt pour impression.</fo:block>
+ <fo:block span="all" border-top="1pt solid black" border-bottom="1pt solid black"
+ padding-before="2pt" padding-after="2pt">This fo:block element spans all the columns of the
+ document. This is intended to test the abilities of the text-to-speech program.</fo:block>
+ <fo:block>And now we are back to normal content flowing in two columns. Let’s start a numbered
+ list:</fo:block>
+ <fo:list-block provisional-distance-between-starts="15pt" provisional-label-separation="0mm"
+ keep-with-previous="auto">
+ <fo:list-item keep-with-previous="always">
+ <fo:list-item-label end-indent="label-end()">
+ <fo:block>1.</fo:block>
+ </fo:list-item-label>
+ <fo:list-item-body start-indent="body-start()">
+ <fo:block>
+ <fo:block>Line 1 of item 1</fo:block>
+ <fo:block>Line 2 of item 1</fo:block>
+ <fo:block>Line 3 of item 1</fo:block>
+ </fo:block>
+ </fo:list-item-body>
+ </fo:list-item>
+ <fo:list-item keep-with-previous="always">
+ <fo:list-item-label end-indent="label-end()">
+ <fo:block>2.</fo:block>
+ </fo:list-item-label>
+ <fo:list-item-body start-indent="body-start()">
+ <fo:block>
+ <fo:block>Line 1 of item 2</fo:block>
+ <fo:block>Line 2 of item 2</fo:block>
+ <fo:block>Line 3 of item 2</fo:block>
+ </fo:block>
+ </fo:list-item-body>
+ </fo:list-item>
+ </fo:list-block>
+ <fo:block>The end of the document has now been reached.</fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+</fo:root>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<fop version="1.0">
+ <accessibility>true</accessibility>
+ <source-resolution>144</source-resolution>
+ <use-cache>false</use-cache>
+ <font-base>../../resources/fonts/ttf/</font-base>
+ <renderers>
+ <renderer mime="application/pdf">
+ <filterList>
+ <value>null</value>
+ </filterList>
+ <filterList type="image">
+ <value>flate</value>
+ <value>ascii-85</value>
+ </filterList>
+ <fonts>
+ <font embed-url="DejaVuLGCSerif.ttf">
+ <font-triplet name="DejaVu" style="normal" weight="normal"/>
+ </font>
+ </fonts>
+ </renderer>
+ </renderers>
+</fop>
--- /dev/null
+<?xml version="1.0" standalone="no"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (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.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!-- $Id$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
+ xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" language="en" country="GB">
+ <fo:layout-master-set>
+ <fo:simple-page-master master-name="page"
+ page-height="220pt" page-width="320pt" margin="10pt">
+ <fo:region-body/>
+ </fo:simple-page-master>
+ </fo:layout-master-set>
+ <fo:page-sequence master-reference="page">
+ <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
+ <fo:block>This document contains an image in the JPEG format: <fo:external-graphic
+ src="../../resources/images/cmyk.jpg"
+ inline-progression-dimension.maximum="100%" content-width="scale-to-fit"
+ fox:alt-text="CMYK colours"/>. Here is the end of the text.</fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+</fo:root>
--- /dev/null
+<?xml version="1.0" standalone="no"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (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.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!-- $Id$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
+ xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" language="en" country="GB">
+ <fo:layout-master-set>
+ <fo:simple-page-master master-name="page"
+ page-height="220pt" page-width="320pt" margin="10pt">
+ <fo:region-body/>
+ </fo:simple-page-master>
+ </fo:layout-master-set>
+ <fo:page-sequence master-reference="page">
+ <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
+ <fo:block>This document contains an image in the PNG format: <fo:external-graphic
+ src="../../resources/images/fop-logo-color-24bit.png"
+ inline-progression-dimension.maximum="100%" content-width="scale-to-fit"
+ fox:alt-text="FOP Logo"/>. Here is the end of the text.</fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+</fo:root>
--- /dev/null
+<?xml version="1.0" standalone="no"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (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.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!-- $Id$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
+ xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" language="en" country="GB">
+ <fo:layout-master-set>
+ <fo:simple-page-master master-name="page"
+ page-height="220pt" page-width="320pt" margin="10pt">
+ <fo:region-body/>
+ </fo:simple-page-master>
+ </fo:layout-master-set>
+ <fo:page-sequence master-reference="page">
+ <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
+ <fo:block>This document contains an image in the SVG format: <fo:external-graphic
+ src="../../resources/images/circles.svg"
+ inline-progression-dimension.maximum="75pt" content-width="scale-to-fit"
+ fox:alt-text="Nice circles"/>. And here is the same image as an instream-foreign-object:
+ <fo:instream-foreign-object inline-progression-dimension.maximum="75pt"
+ content-width="scale-down-to-fit" fox:alt-text="The same nice circles">
+<svg xmlns="http://www.w3.org/2000/svg" width="12cm" height="12cm">
+ <g style="fill-opacity:0.7; stroke:black; stroke-width:0.1cm;">
+ <circle cx="6cm" cy="2cm" r="100" style="fill:red;" transform="translate(0,50)" />
+ <circle cx="6cm" cy="2cm" r="100" style="fill:blue;" transform="translate(70,150)" />
+ <circle cx="6cm" cy="2cm" r="100" style="fill:green;" transform="translate(-70,150)"/>
+ </g>
+</svg>
+ </fo:instream-foreign-object>.</fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+</fo:root>
--- /dev/null
+<?xml version="1.0" standalone="no"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (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.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!-- $Id$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
+ xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" language="en" country="GB">
+ <fo:layout-master-set>
+ <fo:simple-page-master master-name="page"
+ page-height="320pt" page-width="320pt" margin="10pt">
+ <fo:region-body/>
+ </fo:simple-page-master>
+ </fo:layout-master-set>
+ <fo:page-sequence master-reference="page">
+ <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
+ <fo:block>This document contains an image in the WMF format: <fo:external-graphic
+ src="../../resources/images/testChart.wmf"
+ inline-progression-dimension.maximum="100%" content-width="scale-to-fit"
+ fox:alt-text="Metafile Companion Test Chart"/> Here is the end of the text.</fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+</fo:root>
--- /dev/null
+<?xml version="1.0"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (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.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!-- $Id$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
+ <fo:layout-master-set>
+ <fo:simple-page-master master-name="page"
+ page-height="220pt" page-width="320pt" margin="10pt">
+ <fo:region-body/>
+ </fo:simple-page-master>
+ </fo:layout-master-set>
+ <fo:page-sequence master-reference="page">
+ <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify"
+ text-align-last="justify">
+ <fo:block>This is a text followed by a leader with leader-pattern="use-content", the
+ content being text:<fo:leader leader-pattern="use-content"><fo:inline> •
+ </fo:inline></fo:leader>1</fo:block>
+ <fo:block space-before="10pt">This is a text followed by a leader with
+ leader-pattern="use-content", the content being images:<fo:leader
+ leader-pattern="use-content"><fo:external-graphic
+ src="../../resources/images/list-item.png"/></fo:leader>1</fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+</fo:root>
--- /dev/null
+<?xml version="1.0" standalone="no"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (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.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!-- $Id$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
+ xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" language="en" country="GB">
+ <fo:layout-master-set>
+ <fo:simple-page-master master-name="page"
+ page-height="220pt" page-width="320pt" margin="10pt">
+ <fo:region-body/>
+ </fo:simple-page-master>
+ </fo:layout-master-set>
+ <fo:page-sequence master-reference="page">
+ <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
+ <fo:block>This is a <fo:wrapper color="blue"><fo:basic-link
+ internal-destination="FOP">link</fo:basic-link></fo:wrapper> to the next
+ paragraph.</fo:block>
+ <fo:block id="FOP">Apache FOP (Formatting Objects Processor) is a print formatter driven by
+ XSL formatting objects (XSL-FO) and an output independent formatter. It is a Java
+ application that reads a formatting object (FO) tree and renders the resulting pages to a
+ specified output.</fo:block>
+ <fo:block>For more information, see the <fo:wrapper color="blue"><fo:basic-link
+ external-destination="http://xmlgraphics.apache.org/fop/">FOP
+ website</fo:basic-link></fo:wrapper>.</fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+</fo:root>
--- /dev/null
+<?xml version="1.0"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (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.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!-- $Id$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
+ <fo:layout-master-set>
+ <fo:simple-page-master master-name="page"
+ page-height="220pt" page-width="320pt" margin="10pt">
+ <fo:region-body/>
+ </fo:simple-page-master>
+ </fo:layout-master-set>
+ <fo:page-sequence master-reference="page">
+ <fo:flow flow-name="xsl-region-body" hyphenate="true" font-family="sans-serif">
+ <fo:block role="H1" font-weight="bold" font-size="150%"
+ space-before.minimum="1.5em"
+ space-before.optimum="2em"
+ space-before.maximum="3em"
+ space-before.precedence="1000"
+ space-after.minimum="0.2em"
+ space-after.optimum="0.2em"
+ space-after.maximum="0.5em"
+ space-after.precedence="1000">Title 1: To Start With</fo:block>
+ <fo:block role="H2" font-weight="bold" font-size="120%"
+ space-before.minimum="1.2em"
+ space-before.optimum="1.5em"
+ space-before.maximum="2em"
+ space-before.precedence="900"
+ space-after.minimum="0.2em"
+ space-after.optimum="0.2em"
+ space-after.maximum="0.5em"
+ space-after.precedence="900">Title 2: A Sub-Title</fo:block>
+ <fo:block text-align="justify">Apache FOP (Formatting Objects Processor) is a print formatter
+ driven by XSL formatting objects (XSL-FO) and an output independent formatter. It is a Java
+ application that reads a formatting object (FO) tree and renders the resulting pages to a
+ specified output.</fo:block>
+ <fo:block role="H2" font-weight="bold" font-size="120%"
+ space-before.minimum="1.2em"
+ space-before.optimum="1.5em"
+ space-before.maximum="2em"
+ space-before.precedence="900"
+ space-after.minimum="0.2em"
+ space-after.optimum="0.2em"
+ space-after.maximum="0.5em"
+ space-after.precedence="900">Title 2: Another Sub-Title</fo:block>
+ <fo:block text-align="justify">Apache FOP (Formatting Objects Processor) is a print formatter
+ driven by XSL formatting objects (XSL-FO) and an output independent formatter. It is a Java
+ application that reads a formatting object (FO) tree and renders the resulting pages to a
+ specified output.</fo:block>
+ <fo:block role="H1" font-weight="bold" font-size="150%"
+ space-before.minimum="1.5em"
+ space-before.optimum="2em"
+ space-before.maximum="3em"
+ space-before.precedence="1000"
+ space-after.minimum="0.2em"
+ space-after.optimum="0.2em"
+ space-after.maximum="0.5em"
+ space-after.precedence="1000">Title 1: Second Title</fo:block>
+ <fo:block role="H2" font-weight="bold" font-size="120%"
+ space-before.minimum="1.2em"
+ space-before.optimum="1.5em"
+ space-before.maximum="2em"
+ space-before.precedence="900"
+ space-after.minimum="0.2em"
+ space-after.optimum="0.2em"
+ space-after.maximum="0.5em"
+ space-after.precedence="900">Title 2: A Sample Table</fo:block>
+ <fo:block>See data below:</fo:block>
+ <fo:table table-layout="fixed" width="70%" start-indent="15%" border="0.5pt solid black">
+ <fo:table-header start-indent="0" font-weight="bold">
+ <fo:table-row>
+ <fo:table-cell border="0.5pt solid black" padding="2pt">
+ <fo:block>Header 1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell border="0.5pt solid black" padding="2pt">
+ <fo:block>Header 2</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-header>
+ <fo:table-footer start-indent="0" font-weight="bold">
+ <fo:table-row>
+ <fo:table-cell border="0.5pt solid black" padding="2pt">
+ <fo:block>Footer 1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell border="0.5pt solid black" padding="2pt">
+ <fo:block>Footer 2</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-footer>
+ <fo:table-body start-indent="0">
+ <fo:table-row>
+ <fo:table-cell border="0.5pt solid black" padding="2pt">
+ <fo:block>Cell 1.1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell border="0.5pt solid black" padding="2pt">
+ <fo:block>Cell 1.2</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ <fo:table-row>
+ <fo:table-cell border="0.5pt solid black" padding="2pt">
+ <fo:block>Cell 2.1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell border="0.5pt solid black" padding="2pt">
+ <fo:block>Cell 2.2</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-body>
+ </fo:table>
+ <fo:block text-align="justify" space-before="0.5em">That’s all folks.</fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+</fo:root>
--- /dev/null
+<?xml version="1.0"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (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.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!-- $Id$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
+ <fo:layout-master-set>
+ <fo:simple-page-master master-name="page"
+ page-height="220pt" page-width="320pt" margin="10pt">
+ <fo:region-body/>
+ </fo:simple-page-master>
+ </fo:layout-master-set>
+ <fo:page-sequence master-reference="page">
+ <fo:flow flow-name="xsl-region-body" hyphenate="true" font-family="sans-serif">
+ <fo:block role="H1" font-weight="bold" font-size="150%"
+ space-before.minimum="1.5em"
+ space-before.optimum="2em"
+ space-before.maximum="3em"
+ space-before.precedence="1000"
+ space-after.minimum="0.2em"
+ space-after.optimum="0.2em"
+ space-after.maximum="0.5em"
+ space-after.precedence="1000">Title 1: To Start With</fo:block>
+ <fo:block role="Header2" font-weight="bold" font-size="120%"
+ space-before.minimum="1.2em"
+ space-before.optimum="1.5em"
+ space-before.maximum="2em"
+ space-before.precedence="900"
+ space-after.minimum="0.2em"
+ space-after.optimum="0.2em"
+ space-after.maximum="0.5em"
+ space-after.precedence="900">A Sub-Title With a Non-Standard Role</fo:block>
+ <fo:block text-align="justify">Apache FOP (Formatting Objects Processor) is a print formatter
+ driven by XSL formatting objects (XSL-FO) and an output independent formatter. It is a Java
+ application that reads a formatting object (FO) tree and renders the resulting pages to a
+ specified output.</fo:block>
+ <fo:block role="H2" font-weight="bold" font-size="120%"
+ space-before.minimum="1.2em"
+ space-before.optimum="1.5em"
+ space-before.maximum="2em"
+ space-before.precedence="900"
+ space-after.minimum="0.2em"
+ space-after.optimum="0.2em"
+ space-after.maximum="0.5em"
+ space-after.precedence="900">Title 2: Another Sub-Title</fo:block>
+ <fo:block text-align="justify">Apache FOP (Formatting Objects Processor) is a print formatter
+ driven by XSL formatting objects (XSL-FO) and an output independent formatter. It is a Java
+ application that reads a formatting object (FO) tree and renders the resulting pages to a
+ specified output.</fo:block>
+ <fo:block role="H1" font-weight="bold" font-size="150%"
+ space-before.minimum="1.5em"
+ space-before.optimum="2em"
+ space-before.maximum="3em"
+ space-before.precedence="1000"
+ space-after.minimum="0.2em"
+ space-after.optimum="0.2em"
+ space-after.maximum="0.5em"
+ space-after.precedence="1000">Title 1: Second Title</fo:block>
+ <fo:block role="H2" font-weight="bold" font-size="120%"
+ space-before.minimum="1.2em"
+ space-before.optimum="1.5em"
+ space-before.maximum="2em"
+ space-before.precedence="900"
+ space-after.minimum="0.2em"
+ space-after.optimum="0.2em"
+ space-after.maximum="0.5em"
+ space-after.precedence="900">Title 2: A Sample Table</fo:block>
+ <fo:block>See data below:</fo:block>
+ <fo:table table-layout="fixed" width="70%" start-indent="15%" border="0.5pt solid black">
+ <fo:table-header start-indent="0" font-weight="bold" role="TableHeader">
+ <fo:table-row>
+ <fo:table-cell border="0.5pt solid black" padding="2pt">
+ <fo:block>Header 1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell border="0.5pt solid black" padding="2pt">
+ <fo:block>Header 2</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-header>
+ <fo:table-footer start-indent="0" font-weight="bold">
+ <fo:table-row>
+ <fo:table-cell border="0.5pt solid black" padding="2pt">
+ <fo:block>Footer 1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell border="0.5pt solid black" padding="2pt">
+ <fo:block>Footer 2</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-footer>
+ <fo:table-body start-indent="0">
+ <fo:table-row>
+ <fo:table-cell border="0.5pt solid black" padding="2pt">
+ <fo:block>Cell 1.1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell border="0.5pt solid black" padding="2pt">
+ <fo:block>Cell 1.2</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ <fo:table-row>
+ <fo:table-cell border="0.5pt solid black" padding="2pt">
+ <fo:block>Cell 2.1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell border="0.5pt solid black" padding="2pt">
+ <fo:block>Cell 2.2</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-body>
+ </fo:table>
+ <fo:block text-align="justify" space-before="0.5em">That’s all folks.</fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+</fo:root>
--- /dev/null
+<?xml version="1.0"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (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.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!-- $Id$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
+ <fo:layout-master-set>
+ <fo:simple-page-master master-name="page"
+ page-height="220pt" page-width="320pt" margin="10pt">
+ <fo:region-body/>
+ </fo:simple-page-master>
+ </fo:layout-master-set>
+ <fo:page-sequence master-reference="page">
+ <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
+ <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL
+ formatting objects (XSL-FO) and an output independent formatter. It is a Java application
+ that reads a formatting object (FO) tree and renders the resulting pages to a specified
+ output.</fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+</fo:root>
--- /dev/null
+<?xml version="1.0"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (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.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!-- $Id$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
+ <fo:layout-master-set>
+ <fo:simple-page-master master-name="page"
+ page-height="220pt" page-width="320pt" margin="10pt">
+ <fo:region-body/>
+ </fo:simple-page-master>
+ </fo:layout-master-set>
+ <fo:page-sequence master-reference="page">
+ <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
+ <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL
+ formatting objects (XSL-FO) and an output independent formatter. It is a Java application
+ that reads a formatting object (FO) tree and renders the resulting pages to a specified
+ output.</fo:block>
+ <fo:block language="fr" country="FR">Apache FOP (Formatting Objects Processor) est une
+ application de mise en page de documents respectant le standard XSL-FO. À partir d’un
+ document au format XSL-FO, cette application écrite en Java effectue une mise en page et
+ renvoie un document prêt pour impression.</fo:block>
+ <fo:block>Back to English and let’s say it again: Apache FOP (Formatting Objects Processor) is
+ a print formatter driven by XSL formatting objects (XSL-FO) and an output independent
+ formatter.</fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+</fo:root>
--- /dev/null
+<?xml version="1.0"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (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.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!-- $Id$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
+ <fo:layout-master-set>
+ <fo:simple-page-master master-name="page"
+ page-height="220pt" page-width="320pt" margin="10pt">
+ <fo:region-body/>
+ </fo:simple-page-master>
+ </fo:layout-master-set>
+ <fo:page-sequence master-reference="page">
+ <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify" font-family="DejaVu">
+ <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL
+ formatting objects (XSL-FO) and an output independent formatter. It is a Java application
+ that reads a formatting object (FO) tree and renders the resulting pages to a specified
+ output.</fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+</fo:root>