diff options
author | Keiron Liddle <keiron@apache.org> | 2002-09-09 05:58:15 +0000 |
---|---|---|
committer | Keiron Liddle <keiron@apache.org> | 2002-09-09 05:58:15 +0000 |
commit | 08b77b1cd5556d549c0778401508ef09f88013e6 (patch) | |
tree | a8b38bdf8c26d911aaf1c4b04ba08f26fec892a0 /src/org/apache/fop/area | |
parent | cf02e02cc3e1d392b9abfd2eabba9054bb5f5ddc (diff) | |
download | xmlgraphics-fop-08b77b1cd5556d549c0778401508ef09f88013e6.tar.gz xmlgraphics-fop-08b77b1cd5556d549c0778401508ef09f88013e6.zip |
implemented render pages model with a simple cached impl
depending on the renderer it can prepare pages for later rendering
or queue pages until resolved
pages are properly serialized so that resolvers also serialize
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@195156 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/org/apache/fop/area')
-rw-r--r-- | src/org/apache/fop/area/AreaTree.java | 72 | ||||
-rw-r--r-- | src/org/apache/fop/area/CachedRenderPagesModel.java | 107 | ||||
-rw-r--r-- | src/org/apache/fop/area/Page.java | 22 | ||||
-rw-r--r-- | src/org/apache/fop/area/PageViewport.java | 155 | ||||
-rw-r--r-- | src/org/apache/fop/area/Resolveable.java | 3 |
5 files changed, 334 insertions, 25 deletions
diff --git a/src/org/apache/fop/area/AreaTree.java b/src/org/apache/fop/area/AreaTree.java index 5958b6390..4046c6afd 100644 --- a/src/org/apache/fop/area/AreaTree.java +++ b/src/org/apache/fop/area/AreaTree.java @@ -47,7 +47,7 @@ public class AreaTree { * @param rend the renderer that will be used * @return RenderPagesModel the new area tree model */ - public RenderPagesModel createRenderPagesModel(Renderer rend) { + public static RenderPagesModel createRenderPagesModel(Renderer rend) { return new RenderPagesModel(rend); } @@ -354,8 +354,14 @@ public class AreaTree { * contents but the PageViewport is retained. */ public static class RenderPagesModel extends StorePagesModel { - private Renderer renderer; - private ArrayList prepared = new ArrayList(); + /** + * The renderer that will render the pages. + */ + protected Renderer renderer; + /** + * Pages that have been prepared but not rendered yet. + */ + protected ArrayList prepared = new ArrayList(); private ArrayList pendingExt = new ArrayList(); private ArrayList endDocExt = new ArrayList(); @@ -388,19 +394,63 @@ public class AreaTree { */ public void addPage(PageViewport page) { super.addPage(page); + + // check prepared pages + boolean cont = checkPreparedPages(); + // if page finished - try { - renderer.renderPage(page); - } catch (Exception e) { - // use error handler to handle this FOP or IO Exception + if (cont && page.isResolved()) { + try { + renderer.renderPage(page); + } catch (Exception e) { + // use error handler to handle this FOP or IO Exception + } + page.clear(); + } else { + preparePage(page); } - page.clear(); renderExtensions(pendingExt); pendingExt.clear(); + } + + /** + * Check prepared pages + * @return true if the current page should be rendered + * false if the renderer doesn't support out of order + * rendering and there are pending pages + */ + protected boolean checkPreparedPages() { + for (Iterator iter = prepared.iterator(); iter.hasNext();) { + PageViewport p = (PageViewport)iter.next(); + if (p.isResolved()) { + try { + renderer.renderPage(p); + } catch (Exception e) { + // use error handler to handle this FOP or IO Exception + } + p.clear(); + iter.remove(); + } else { + // if keeping order then stop at first page not resolved + if (!renderer.supportsOutOfOrder()) { + break; + } + } + } + return renderer.supportsOutOfOrder() || prepared.isEmpty(); + } - // else prepare - //renderer.preparePage(page); + /** + * Prepare a page. + * An unresolved page can be prepared if the renderer supports + * it and the page will be rendered later. + * @param page the page to prepare + */ + protected void preparePage(PageViewport page) { + if (renderer.supportsOutOfOrder()) { + renderer.preparePage(page); + } prepared.add(page); } @@ -438,6 +488,8 @@ public class AreaTree { * End the document. Render any end document extensions. */ public void endDocument() { + // render any pages that had unresolved ids + checkPreparedPages(); renderExtensions(endDocExt); } } diff --git a/src/org/apache/fop/area/CachedRenderPagesModel.java b/src/org/apache/fop/area/CachedRenderPagesModel.java new file mode 100644 index 000000000..f706a8de4 --- /dev/null +++ b/src/org/apache/fop/area/CachedRenderPagesModel.java @@ -0,0 +1,107 @@ +/* + * $Id$ + * Copyright (C) 2002 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources. + */ + +package org.apache.fop.area; + +import org.apache.fop.render.Renderer; + +import java.util.HashMap; +import java.util.Iterator; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileInputStream; +import java.io.ObjectOutputStream; +import java.io.ObjectInputStream; +import java.io.BufferedOutputStream; +import java.io.BufferedInputStream; + +/** + * A simple cached render pages model. + * If the page is prepared for later rendering then this saves + * the page contents to a file and once the page is resolved + * the contents a reloaded. + */ +public class CachedRenderPagesModel extends AreaTree.RenderPagesModel { + private HashMap pageMap = new HashMap(); + + /** + * Create a new render pages model with the given renderer. + * @param rend the renderer to render pages to + */ + public CachedRenderPagesModel(Renderer rend) { + super(rend); + } + + /** + * Check prepared pages + * If a page is resolved it loads the page contents from + * the file. + * @return true if the current page should be rendered + * false if the renderer doesn't support out of order + * rendering and there are pending pages + */ + protected boolean checkPreparedPages() { + for (Iterator iter = prepared.iterator(); iter.hasNext();) { + PageViewport p = (PageViewport)iter.next(); + if (p.isResolved()) { + try { + // load page from cache + String name = (String)pageMap.get(p); + File temp = new File(name); + System.out.println("page serialized to: " + temp.length()); + ObjectInputStream in = new ObjectInputStream( + new BufferedInputStream( + new FileInputStream(temp))); + p.loadPage(in); + in.close(); + temp.delete(); + pageMap.remove(p); + } catch (Exception e) { + e.printStackTrace(); + } + + try { + renderer.renderPage(p); + } catch (Exception e) { + // use error handler to handle this FOP or IO Exception + } + p.clear(); + iter.remove(); + } else { + if (!renderer.supportsOutOfOrder()) { + break; + } + } + } + return renderer.supportsOutOfOrder() || prepared.isEmpty(); + } + + /** + * Prepare a page. + * This uses the parent to prepare the page. + * It then saves the contents of the page to a file. + * @param page the page to prepare + */ + protected void preparePage(PageViewport page) { + super.preparePage(page); + + try { + // save page to cache + ObjectOutputStream tempstream; + String fname = "page" + page.toString() + ".ser"; + tempstream = new ObjectOutputStream(new BufferedOutputStream( + new FileOutputStream(fname))); + page.savePage(tempstream); + tempstream.close(); + pageMap.put(page, fname); + } catch (Exception e) { + e.printStackTrace(); + } + } +} + diff --git a/src/org/apache/fop/area/Page.java b/src/org/apache/fop/area/Page.java index 3289fdaf3..41b72f8c2 100644 --- a/src/org/apache/fop/area/Page.java +++ b/src/org/apache/fop/area/Page.java @@ -10,6 +10,17 @@ package org.apache.fop.area; import java.io.Serializable; import java.util.HashMap; +/** + * The page. + * This holds the contents of the page. Each region is added. + * The unresolved references area added so that if the page is + * serialized then it will handle the resolving properly after + * being reloaded. + * This is serializable so it can be saved to cache to save + * memory if there are forward references. + * The page is cloneable so the page master can make copies of + * the top level page and regions. + */ public class Page implements Serializable, Cloneable { // contains before, start, body, end and after regions RegionViewport regionBefore = null; @@ -23,6 +34,8 @@ public class Page implements Serializable, Cloneable { HashMap markerStart = null; HashMap markerEnd = null; + private HashMap unresolved = null; + public void setRegion(int areaclass, RegionViewport port) { if (areaclass == RegionReference.BEFORE) { regionBefore = port; @@ -67,4 +80,13 @@ public class Page implements Serializable, Cloneable { return p; } + + public void setUnresolvedReferences(HashMap unres) { + unresolved = unres; + } + + public HashMap getUnresolvedReferences() { + return unresolved; + } } + diff --git a/src/org/apache/fop/area/PageViewport.java b/src/org/apache/fop/area/PageViewport.java index b09048808..e5422658b 100644 --- a/src/org/apache/fop/area/PageViewport.java +++ b/src/org/apache/fop/area/PageViewport.java @@ -1,6 +1,6 @@ /* * $Id$ - * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. + * Copyright (C) 2001-2002 The Apache Software Foundation. All rights reserved. * For details on use and redistribution please refer to the * LICENSE file included with these sources. */ @@ -11,59 +11,188 @@ import java.awt.geom.Rectangle2D; import java.io.ObjectOutputStream; import java.io.ObjectInputStream; import java.util.ArrayList; +import java.util.List; +import java.util.HashMap; +import java.util.Iterator; -// this is the level that creates the page -// the page (reference area) is then rendered inside the page object -public class PageViewport implements Cloneable { - Page page; - Rectangle2D viewArea; - boolean clip = false; - String pageNumber = null; +/** + * Page viewport that specifies the viewport area and holds the page contents. + * This is the top level object for a page and remains valid for the life + * of the document and the area tree. + * This object may be used as a key to reference a page. + * This is the level that creates the page + * The page (reference area) is then rendered inside the page object + */ +public class PageViewport implements Resolveable, Cloneable { + private Page page; + private Rectangle2D viewArea; + private boolean clip = false; + private String pageNumber = null; - // this list is only used when the page is discarded - // the information is kept for future reference - ArrayList idReferences = null; + // list of id references and the rectangle on the page + private HashMap idReferences = null; // this keeps a list of currently unresolved areas or extensions // once the thing is resolved it is removed // when this is empty the page can be rendered - ArrayList unresolved = null; + private HashMap unresolved = null; + + private HashMap pendingResolved = null; + /** + * Create a page viewport. + * @param p the page reference area that holds the contents + * @param bounds the bounds of this viewport + */ public PageViewport(Page p, Rectangle2D bounds) { page = p; viewArea = bounds; } + /** + * Set if this viewport should clip. + * @param c true if this viewport should clip + */ public void setClip(boolean c) { clip = c; } + /** + * Get the view area rectangle of this viewport. + * @return the rectangle for this viewport + */ public Rectangle2D getViewArea() { return viewArea; } - // a viewport area for page and reference areas + /** + * Get the page reference area with the contents. + * @return the page reference area + */ public Page getPage() { return page; } + /** + * Set the page number for this page. + * @param num the string representing the page number + */ public void setPageNumber(String num) { pageNumber = num; } + /** + * Get the page number of this page. + * @return the string that represents this page + */ public String getPageNumber() { return pageNumber; } + /** + * Add an unresolved id to this page. + * All unresolved ids for the contents of this page are + * added to this page. This is so that the resolvers can be + * serialized with the page to preserve the proper function. + * @param id the id of the reference + * @param res the resolver of the reference + */ + public void addUnresolvedID(String id, Resolveable res) { + if (unresolved == null) { + unresolved = new HashMap(); + } + List list = (List)unresolved.get(id); + if (list == null) { + list = new ArrayList(); + unresolved.put(id, list); + } + list.add(res); + } + + /** + * Check if this page has been fully resolved. + * @return true if the page is resolved and can be rendered + */ + public boolean isResolved() { + return unresolved == null; + } + + /** + * Get the id references for this page. + * @return always null + */ + public String[] getIDs() { + return null; + } + + /** + * This resolves reference with a list of pages. + * The pages (PageViewport) contain the rectangle of the area. + * @param id the id to resolve + * @param pages the list of pages with the id area + * may be null if not found + */ + public void resolve(String id, List pages) { + if (page == null) { + if (pendingResolved == null) { + pendingResolved = new HashMap(); + } + pendingResolved.put(id, pages); + } else { + List todo = (List)unresolved.get(id); + if (todo != null) { + for (int count = 0; count < todo.size(); count++) { + Resolveable res = (Resolveable)todo.get(count); + res.resolve(id, pages); + } + } + } + unresolved.remove(id); + if (unresolved.isEmpty()) { + unresolved = null; + } + } + + /** + * Save the page contents to an object stream. + * The map of unresolved references are set on the page so that + * the resolvers can be properly serialized and reloaded. + * @param out the object output stream to write the contents + * @throws Exception if there is a problem saving the page + */ public void savePage(ObjectOutputStream out) throws Exception { + // set the unresolved references so they are serialized + page.setUnresolvedReferences(unresolved); out.writeObject(page); page = null; } + /** + * Load the page contents from an object stream. + * This loads the page contents from the stream and + * if there are any unresolved references that were resolved + * while saved they will be resolved on the page contents. + * @param in the object input stream to read the page from + * @throws Exception if there is an error loading the page + */ public void loadPage(ObjectInputStream in) throws Exception { page = (Page) in.readObject(); + unresolved = page.getUnresolvedReferences(); + if (unresolved != null && pendingResolved != null) { + for (Iterator iter = pendingResolved.keySet().iterator(); + iter.hasNext();) { + String id = (String) iter.next(); + resolve(id, (List)pendingResolved.get(id)); + } + pendingResolved = null; + } } + /** + * Clone this page. + * Used by the page master to create a copy of an original page. + * @return a copy of this page and associated viewports + */ public Object clone() { Page p = (Page)page.clone(); PageViewport ret = new PageViewport(p, (Rectangle2D)viewArea.clone()); diff --git a/src/org/apache/fop/area/Resolveable.java b/src/org/apache/fop/area/Resolveable.java index c40fc5329..edfcce6b8 100644 --- a/src/org/apache/fop/area/Resolveable.java +++ b/src/org/apache/fop/area/Resolveable.java @@ -8,14 +8,13 @@ package org.apache.fop.area; import java.util.List; -import java.io.Serializable; /** * Resolveable Interface. * Classes that implement this can be resolved when * an id is added to the area tree. */ -public interface Resolveable extends Serializable { +public interface Resolveable { public boolean isResolved(); |