package org.apache.fop.area;
-import java.util.ArrayList;
+import org.apache.fop.render.Renderer;
+import java.util.ArrayList;
/**
* Area tree for formatting objects.
// in different situations
AreaTreeModel model;
- public void createRenderPageModel(PageRenderListener listener) {
-
+ public RenderPagesModel createRenderPagesModel(Renderer rend) {
+ return new RenderPagesModel(rend);
}
public static StorePagesModel createStorePagesModel() {
model = m;
}
- public void startPageSequence(Area title) {
+ public void startPageSequence(Title title) {
model.startPageSequence(title);
}
// this is the model for the area tree object
public static abstract class AreaTreeModel {
- public abstract void startPageSequence(Area title);
+ public abstract void startPageSequence(Title title);
public abstract void addPage(PageViewport page);
}
public StorePagesModel() {}
- public void startPageSequence(Area title) {
+ public void startPageSequence(Title title) {
titles.add(title);
if (pageSequence == null) {
pageSequence = new ArrayList();
}
}
- // this queues pages and will call the render listener
- // when the page is ready to be rendered
- // if the render supports out of order rendering
- // then a ready page is rendered immediately
+ // this uses the store pages model to store the pages
+ // each page is either rendered if ready or prepared
+ // for later rendering
public static class RenderPagesModel extends StorePagesModel {
- public void startPageSequence(Area title) {}
- public void addPage(PageViewport page) {}
- }
+ Renderer renderer;
+ ArrayList prepared = new ArrayList();
+
+ public RenderPagesModel(Renderer rend) {
+ renderer = rend;
+ }
+
+ public void startPageSequence(Title title) {
+ super.startPageSequence(title);
+ renderer.startPageSequence(title);
+ }
- public static abstract class PageRenderListener {
- public abstract void renderPage(RenderPagesModel model,
- int pageseq, int count);
+ public void addPage(PageViewport page) {
+ super.addPage(page);
+ // if page finished
+ //renderer.renderPage(page);
+ page.clear();
+ // else prepare
+ //renderer.preparePage(page);
+ prepared.add(page);
+ }
}
}
public void loadPage(ObjectInputStream in) throws Exception {
page = (Page) in.readObject();
}
+
+ /**
+ * Clear the page contents to save memory.
+ * THis objects is kept for the life of the area tree since
+ * it holds id information and is used as a key.
+ */
+ public void clear() {
+ page = null;
+ }
}
import org.apache.fop.render.pdf.fonts.LazyFont;
import org.apache.fop.datatypes.IDReferences;
-import org.apache.fop.layout.Page;
import org.apache.fop.layout.FontMetric;
import org.apache.fop.layout.FontDescriptor;
// Java
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
-import java.util.Hashtable;
-import java.util.Enumeration;
+import java.util.HashMap;
import java.awt.Rectangle;
/**
* the XObjects Map.
* Should be modified (works only for image subtype)
*/
- protected Hashtable xObjectsMap = new Hashtable();
+ protected HashMap xObjectsMap = new HashMap();
/**
* the objects themselves
*
* @return the created /Page object
*/
- public PDFPage makePage(PDFResources resources, PDFStream contents,
+ public PDFPage makePage(PDFResources resources,
int pagewidth, int pageheight) {
/*
* create a PDFPage with the next object number, the given
* resources, contents and dimensions
*/
- PDFPage page = new PDFPage(++this.objectcount, resources, contents,
+ PDFPage page = new PDFPage(++this.objectcount, resources,
pagewidth, pageheight);
- if(pendingLinks != null) {
- for(int count = 0; count < pendingLinks.size(); count++) {
- PendingLink pl = (PendingLink)pendingLinks.get(count);
- PDFGoTo gt = new PDFGoTo(++this.objectcount,
- page.referencePDF());
- gt.setDestination(pl.dest);
- addTrailerObject(gt);
- PDFInternalLink internalLink =
- new PDFInternalLink(gt.referencePDF());
- pl.link.setAction(internalLink);
- }
- pendingLinks = null;
- }
-/*
- if (currentPage != null) {
- Enumeration enum = currentPage.getIDList().elements();
- while (enum.hasMoreElements()) {
- String id = enum.nextElement().toString();
- idReferences.setInternalGoToPageReference(id,
- page.referencePDF());
- }
- }
-*/
/* add it to the list of objects */
this.objects.add(page);
- /* add the page to the Root */
- this.root.addPage(page);
-
return page;
}
+ public void addPage(PDFPage page) {
+ /* add it to the list of objects */
+ this.objects.add(page);
+ }
+
/**
* make a link object
*
package org.apache.fop.pdf;
-// Java
-import java.io.IOException;
-import java.io.PrintWriter;
+import java.util.Date;
+import java.text.SimpleDateFormat;
/**
* class representing an /Info object
*/
protected String producer;
+ protected String title = null;
+ protected String author = null;
+ protected String subject = null;
+ protected String keywords = null;
+
+ // the name of the application that created the
+ // original document before converting to PDF
+ protected String creator;
+
/**
* create an Info object
*
this.producer = producer;
}
+ public void setTitle(String t) {
+ this.title = t;
+ }
+
+ public void setAuthor(String a) {
+ this.author = a;
+ }
+
+ public void setSubject(String s) {
+ this.subject = s;
+ }
+
+ public void setKeywords(String k) {
+ this.keywords = k;
+ }
+
/**
* produce the PDF representation of the object
*
*/
public byte[] toPDF() {
String p = this.number + " " + this.generation
- + " obj\n<< /Type /Info\n/Producer (" + this.producer
- + ") >>\nendobj\n";
+ + " obj\n<< /Type /Info\n";
+ if(title != null) {
+ p += "/Title (" + this.title + ")\n";
+ }
+ if(author != null) {
+ p += "/Author (" + this.author + ")\n";
+ }
+ if(subject != null) {
+ p += "/Subject (" + this.subject + ")\n";
+ }
+ if(keywords != null) {
+ p += "/Keywords (" + this.keywords + ")\n";
+ }
+
+ p += "/Producer (" + this.producer + ")\n";
+
+ // creation date in form (D:YYYYMMDDHHmmSSOHH'mm')
+ Date date = new Date();
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddhhmmss");
+ String str = sdf.format(date) + "+00'00'";
+ p += "/CreationDate (D:" + str + ")";
+ p += " >>\nendobj\n";
return p.getBytes();
}
-
}
+
this.annotList = null;
}
+ /**
+ * create a /Page object
+ *
+ * @param number the object's number
+ * @param resources the /Resources object
+ * @param pagewidth the page's width in points
+ * @param pageheight the page's height in points
+ */
+ public PDFPage(int number, PDFResources resources,
+ int pagewidth, int pageheight) {
+
+ /* generic creation of object */
+ super(number);
+
+ /* set fields using parameters */
+ this.resources = resources;
+ this.pagewidth = pagewidth;
+ this.pageheight = pageheight;
+
+ this.annotList = null;
+ }
+
+ /**
+ * set this page contents
+ *
+ * @param contents the contents of the page
+ */
+ public void setContents(PDFStream contents) {
+ this.contents = contents;
+ }
+
/**
* set this page's parent
*
}
byte[] toPDF() {
- /*
- * Not used any more
- * String p = this.number + " " + this.generation + " obj\n";
- * p = p + "<</Type /XObject\n";
- * p = p + "/Subtype /Image\n";
- * p = p + "/Name /Im"+Xnum+"\n";
- * p = p + "/Width "+fopimage.getpixelwidth()+"\n";
- * p = p + "/Height "+fopimage.getpixelheight()+"\n";
- * p = p + "/BitsPerComponent 8\n";
- * if (fopimage.getcolor())
- * p = p + "/ColorSpace /DeviceRGB\n";
- * else
- * p = p + "/ColorSpace /DeviceGray\n";
- * p = p + "/Filter /ASCIIHexDecode\n";
- * p = p + "/Length ";
- * return p;
- */
return null;
}
-
}
options = opt;
}
+ /**
+ * Check if this renderer supports out of order rendering.
+ * If this renderer supports out of order rendering then it
+ * means that the pages that are not ready will be prepared
+ * and a future page will be rendered.
+ */
+ public boolean supportsOutOfOrder() {
+ return false;
+ }
+
+ /**
+ * Prepare a page for rendering.
+ * This is called if the renderer supports out of order rendering.
+ * The renderer should prepare the page so that a page further on
+ * in the set of pages can be rendered. The body of the page should
+ * not be rendered. The page will be rendered at a later time
+ * by the call to render page.
+ */
+ public void preparePage(PageViewport page) {
+ }
+
/**
* Utility method to convert a page sequence title to a string.
* Some renderers may only be able to use a string title.
*/
public void setProducer(String producer);
+ public boolean supportsOutOfOrder();
+
+ public void preparePage(PageViewport page);
+
public void startPageSequence(Title seqTitle);
public void renderPage(PageViewport page) throws IOException, FOPException;
// Java
import java.io.IOException;
import java.io.OutputStream;
-
import java.awt.geom.Rectangle2D;
+import java.util.HashMap;
/*
TODO:
viewport clipping
word rendering and optimistion
-pdf state optimistation
+pdf state optimisation
line and border
leader
background pattern
*/
protected PDFDocument pdfDoc;
+ // map of pages using the PageViewport as the key
+ // this is used for prepared pages that cannot be immediately
+ // rendered
+ protected HashMap pages = null;
+
+ // page references are stored using the PageViewport as the key
+ // when a reference is made the PageViewport is used
+ // for pdf this means we need the pdf page reference
+ protected HashMap pageReferences = new HashMap();
+
protected String producer;
protected OutputStream ostream;
ostream = null;
}
+ public boolean supportsOutOfOrder() {
+ return true;
+ }
+
+ /**
+ * The pdf page is prepared by making the page.
+ * The page is made in the pdf document without any contents
+ * and then stored to add the contents later.
+ * The page objects is stored using the area tree PageViewport
+ * as a key.
+ */
+ public void preparePage(PageViewport page) {
+ this.pdfResources = this.pdfDoc.getResources();
+
+ Rectangle2D bounds = page.getViewArea();
+ double w = bounds.getWidth();
+ double h = bounds.getHeight();
+ currentPage = this.pdfDoc.makePage(this.pdfResources,
+ (int) Math.round(w / 1000), (int) Math.round(h / 1000));
+ if(pages == null) {
+ pages = new HashMap();
+ }
+ pages.put(page, currentPage);
+ pageReferences.put(page, currentPage.referencePDF());
+ }
+
/**
* This method creates a pdf stream for the current page
- * uses it as the contents of a new page. The page is wriiten
+ * uses it as the contents of a new page. The page is written
* immediately to the output stream.
*/
public void renderPage(PageViewport page) throws IOException,
FOPException {
-
- this.pdfResources = this.pdfDoc.getResources();
-
+ if(pages != null && (currentPage = (PDFPage)pages.get(page)) != null) {
+ pages.remove(page);
+ } else {
+ this.pdfResources = this.pdfDoc.getResources();
+ Rectangle2D bounds = page.getViewArea();
+ double w = bounds.getWidth();
+ double h = bounds.getHeight();
+ currentPage = this.pdfDoc.makePage(this.pdfResources,
+ (int) Math.round(w / 1000), (int) Math.round(h / 1000));
+ pageReferences.put(page, currentPage.referencePDF());
+ }
currentStream = this.pdfDoc.makeStream();
currentStream.add("BT\n");
currentStream.add("ET\n");
- Rectangle2D bounds = page.getViewArea();
- double w = bounds.getWidth();
- double h = bounds.getHeight();
- currentPage = this.pdfDoc.makePage(this.pdfResources, currentStream,
- (int) Math.round(w / 1000), (int) Math.round(h / 1000));
-
+ currentPage.setContents(currentStream);
+ this.pdfDoc.addPage(currentPage);
this.pdfDoc.output(ostream);
-
}
-
}
public class PDFDocumentGraphics2D extends PDFGraphics2D {
OutputStream stream;
+ PDFPage currentPage;
PDFStream pdfStream;
int width;
int height;
currentFontSize = 0;
currentYPosition = 0;
currentXPosition = 0;
+
+ PDFResources pdfResources = this.pdfDoc.getResources();
+ currentPage = this.pdfDoc.makePage(pdfResources,
+ width, height);
}
void setupDocument(OutputStream stream, int width, int height) {
public void finish() throws IOException {
pdfStream.add(getString());
PDFResources pdfResources = this.pdfDoc.getResources();
- PDFPage currentPage = this.pdfDoc.makePage(pdfResources, pdfStream,
- width, height);
+ currentPage.setContents(pdfStream);
+ this.pdfDoc.addPage(currentPage);
if(currentAnnotList != null) {
currentPage.setAnnotList(currentAnnotList);
}