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-ffa450edef68pull/30/head
@@ -17,6 +17,7 @@ import org.xml.sax.SAXException; | |||
import org.apache.fop.layout.FontInfo; | |||
import org.apache.fop.area.PageViewport; | |||
import org.apache.fop.area.AreaTree; | |||
import org.apache.fop.area.CachedRenderPagesModel; | |||
import org.apache.fop.area.Title; | |||
import org.apache.fop.area.TreeExt; | |||
import org.apache.fop.render.Renderer; | |||
@@ -76,7 +77,7 @@ public class LayoutHandler extends StructureHandler { | |||
* The current AreaTree for the PageSequence being rendered. | |||
*/ | |||
private AreaTree areaTree; | |||
private AreaTree.StorePagesModel atModel; | |||
private AreaTree.AreaTreeModel atModel; | |||
/** | |||
* @param outputStream the stream that the result is rendered to | |||
@@ -90,7 +91,8 @@ public class LayoutHandler extends StructureHandler { | |||
this.renderer = renderer; | |||
this.areaTree = new AreaTree(); | |||
this.atModel = AreaTree.createStorePagesModel(); | |||
this.atModel = AreaTree.createRenderPagesModel(renderer); | |||
//this.atModel = new CachedRenderPagesModel(renderer); | |||
areaTree.setTreeModel(atModel); | |||
} | |||
@@ -120,18 +122,11 @@ public class LayoutHandler extends StructureHandler { | |||
} | |||
public void endDocument() throws SAXException { | |||
/* | |||
Force the processing of any more queue elements, | |||
even if they are not resolved. | |||
*/ | |||
try { | |||
processAreaTree(); | |||
//processAreaTree(atModel); | |||
areaTree.endDocument(); | |||
renderer.stopRenderer(); | |||
} catch (FOPException e) { | |||
throw new SAXException(e); | |||
} | |||
catch (IOException e) { | |||
} catch (Exception e) { | |||
throw new SAXException(e); | |||
} | |||
@@ -190,16 +185,16 @@ public class LayoutHandler extends StructureHandler { | |||
} | |||
private void processAreaTree() throws FOPException { | |||
private void processAreaTree(AreaTree.StorePagesModel model) throws FOPException { | |||
int count = 0; | |||
int seqc = atModel.getPageSequenceCount(); | |||
int seqc = model.getPageSequenceCount(); | |||
while (count < seqc) { | |||
Title title = atModel.getTitle(count); | |||
Title title = model.getTitle(count); | |||
renderer.startPageSequence(title); | |||
int pagec = atModel.getPageCount(count); | |||
int pagec = model.getPageCount(count); | |||
for (int c = 0; c < pagec; c++) { | |||
try { | |||
renderer.renderPage(atModel.getPage(count, c)); | |||
renderer.renderPage(model.getPage(count, c)); | |||
} catch (java.io.IOException ioex) { | |||
throw new FOPException("I/O Error rendering page", | |||
ioex); | |||
@@ -207,7 +202,7 @@ public class LayoutHandler extends StructureHandler { | |||
} | |||
count++; | |||
} | |||
List list = atModel.getEndExtensions(); | |||
List list = model.getEndExtensions(); | |||
for(count = 0; count < list.size(); count++) { | |||
TreeExt ext = (TreeExt)list.get(count); | |||
renderer.renderExtension(ext); |
@@ -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); | |||
} | |||
} |
@@ -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(); | |||
} | |||
} | |||
} | |||
@@ -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; | |||
} | |||
} | |||
@@ -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()); |
@@ -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(); | |||
@@ -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. | |||
*/ | |||
@@ -8,11 +8,13 @@ | |||
package org.apache.fop.fo.flow; | |||
// FOP | |||
import org.apache.fop.fo.*; | |||
import org.apache.fop.apps.FOPException; | |||
import org.apache.fop.fo.properties.*; | |||
import org.apache.fop.layout.*; | |||
import org.apache.fop.datatypes.ColorType; | |||
import org.apache.fop.fo.FONode; | |||
import org.apache.fop.layout.AccessibilityProps; | |||
import org.apache.fop.layout.AuralProps; | |||
import org.apache.fop.layout.BorderAndPadding; | |||
import org.apache.fop.layout.BackgroundProps; | |||
import org.apache.fop.layout.MarginInlineProps; | |||
import org.apache.fop.layout.RelativePositionProps; | |||
import org.apache.fop.area.inline.InlineParent; | |||
import org.apache.fop.area.Trait; | |||
import org.apache.fop.area.Resolveable; | |||
@@ -23,11 +25,14 @@ import org.apache.fop.layoutmgr.LMiter; | |||
import org.apache.fop.layoutmgr.LayoutManager; | |||
// Java | |||
import java.util.Enumeration; | |||
import java.awt.Rectangle; | |||
import java.util.List; | |||
import java.util.ArrayList; | |||
import java.io.Serializable; | |||
/** | |||
* The basic link. | |||
* This sets the basic link trait on the inline parent areas | |||
* that are created by the fo element. | |||
*/ | |||
public class BasicLink extends Inline { | |||
String link = null; | |||
boolean external = false; | |||
@@ -50,14 +55,14 @@ public class BasicLink extends Inline { | |||
} | |||
protected void setupLinkArea(LayoutManager parentLM, InlineParent area) { | |||
if(link == null) { | |||
if (link == null) { | |||
return; | |||
} | |||
if(external) { | |||
if (external) { | |||
area.addTrait(Trait.EXTERNAL_LINK, link); | |||
} else { | |||
PageViewport page = parentLM.resolveRefID(link); | |||
if(page != null) { | |||
if (page != null) { | |||
area.addTrait(Trait.INTERNAL_LINK, page); | |||
} else { | |||
LinkResolver res = new LinkResolver(link, area); | |||
@@ -95,10 +100,10 @@ public class BasicLink extends Inline { | |||
setupID(); | |||
// this.properties.get("indicate-destination"); | |||
String internal = properties.get("internal-destination").getString(); | |||
if(ext.length() > 0) { | |||
if (ext.length() > 0) { | |||
link = ext; | |||
external = true; | |||
} else if(internal.length() > 0) { | |||
} else if (internal.length() > 0) { | |||
link = internal; | |||
} else { | |||
getLogger().error("basic-link requires an internal or external destination"); | |||
@@ -115,10 +120,12 @@ public class BasicLink extends Inline { | |||
} | |||
protected static class LinkResolver implements Resolveable { | |||
/** | |||
* Link resolving for resolving internal links. | |||
*/ | |||
protected static class LinkResolver implements Resolveable, Serializable { | |||
private boolean resolved = false; | |||
private String idRef; | |||
// NOTE: there will be a problem with serialization | |||
private Area area; | |||
public LinkResolver(String id, Area a) { | |||
@@ -135,16 +142,15 @@ public class BasicLink extends Inline { | |||
} | |||
/** | |||
* Resolve by removing the id link and replacing with | |||
* an internal link. | |||
* Resolve by adding an internal link. | |||
*/ | |||
public void resolve(String id, List pages) { | |||
if(idRef.equals(id) && pages != null) { | |||
resolved = true; | |||
if (idRef.equals(id) && pages != null) { | |||
PageViewport page = (PageViewport)pages.get(0); | |||
area.addTrait(Trait.INTERNAL_LINK, page); | |||
} | |||
} | |||
} | |||
} |
@@ -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. | |||
*/ | |||
@@ -125,7 +125,7 @@ public class PageLayoutManager extends AbstractLayoutManager implements Runnable | |||
if (!curLM.isFinished()) { | |||
bp = curLM.getNextBreakPoss(childLC); | |||
} | |||
if(bp != null) { | |||
if (bp != null) { | |||
return new BreakPoss( | |||
new BlockBreakPosition(curLM, bp)); | |||
} | |||
@@ -140,7 +140,7 @@ public class PageLayoutManager extends AbstractLayoutManager implements Runnable | |||
public PageViewport resolveRefID(String ref) { | |||
List list = areaTree.getIDReferences(ref); | |||
if(list != null && list.size() > 0) { | |||
if (list != null && list.size() > 0) { | |||
return (PageViewport)list.get(0); | |||
} | |||
return null; | |||
@@ -159,8 +159,9 @@ public class PageLayoutManager extends AbstractLayoutManager implements Runnable | |||
public void addUnresolvedArea(String id, Resolveable res) { | |||
// add unresolved to tree | |||
// should really add to the page viewport so it can serialize | |||
areaTree.addUnresolvedID(id, res); | |||
// adds to the page viewport so it can serialize | |||
curPage.addUnresolvedID(id, res); | |||
areaTree.addUnresolvedID(id, curPage); | |||
} | |||
/** | |||
@@ -430,21 +431,21 @@ public class PageLayoutManager extends AbstractLayoutManager implements Runnable | |||
*/ | |||
private boolean needNewPage(int breakValue) { | |||
return false; | |||
// if (curPage.isEmpty()) { | |||
// if (breakValue == Constants.PAGE) { | |||
// return false; | |||
// } | |||
// else if (curPage.getPageNumber()%2 != 0) { | |||
// // Current page is odd | |||
// return (breakValue == Constants.EVEN_PAGE); | |||
// } | |||
// else { | |||
// return (breakValue == Constants.ODD_PAGE); | |||
// } | |||
// } | |||
// else { | |||
// return true; | |||
// } | |||
//if (curPage.isEmpty()) { | |||
//if (breakValue == Constants.PAGE) { | |||
//return false; | |||
//} | |||
//else if (curPage.getPageNumber()%2 != 0) { | |||
//// Current page is odd | |||
//return (breakValue == Constants.EVEN_PAGE); | |||
//} | |||
//else { | |||
//return (breakValue == Constants.ODD_PAGE); | |||
//} | |||
//} | |||
//else { | |||
// return true; | |||
//} | |||
} | |||
@@ -467,15 +468,15 @@ public class PageLayoutManager extends AbstractLayoutManager implements Runnable | |||
// This determines the position of the new span area | |||
// Attention: space calculation between the span areas. | |||
// MinOptMax newpos ; | |||
// if (curSpan != null) { | |||
// newpos = curSpan.getPosition(BPD); | |||
// newpos.add(curSpan.getDimension(BPD)); | |||
// } | |||
// else newpos = new MinOptMax(); | |||
//MinOptMax newpos ; | |||
//if (curSpan != null) { | |||
//newpos = curSpan.getPosition(BPD); | |||
//newpos.add(curSpan.getDimension(BPD)); | |||
//} | |||
//else newpos = new MinOptMax(); | |||
curSpan = new Span(numCols); | |||
// get Width or Height as IPD for span | |||
curSpan.setIPD( (int) curPage.getPage(). getRegion( | |||
curSpan.setIPD((int) curPage.getPage().getRegion( | |||
RegionReference.BODY).getViewArea().getWidth()); | |||
//curSpan.setPosition(BPD, newpos); |
@@ -9,24 +9,46 @@ package org.apache.fop.render.pdf; | |||
// FOP | |||
import org.apache.fop.render.PrintRenderer; | |||
import org.apache.fop.render.XMLHandler; | |||
import org.apache.fop.render.RendererContext; | |||
import org.apache.fop.fo.FOUserAgent; | |||
import org.apache.fop.image.*; | |||
import org.apache.fop.image.FopImage; | |||
import org.apache.fop.image.XMLImage; | |||
import org.apache.fop.image.ImageFactory; | |||
import org.apache.fop.apps.FOPException; | |||
import org.apache.fop.apps.Version; | |||
import org.apache.fop.fo.properties.*; | |||
import org.apache.fop.datatypes.*; | |||
import org.apache.fop.pdf.*; | |||
import org.apache.fop.image.*; | |||
import org.apache.fop.extensions.*; | |||
import org.apache.fop.render.pdf.fonts.LazyFont; | |||
import org.apache.fop.area.*; | |||
import org.apache.fop.area.inline.*; | |||
import org.apache.fop.fo.properties.RuleStyle; | |||
//import org.apache.fop.datatypes.*; | |||
import org.apache.fop.pdf.PDFStream; | |||
import org.apache.fop.pdf.PDFDocument; | |||
import org.apache.fop.pdf.PDFInfo; | |||
import org.apache.fop.pdf.PDFResources; | |||
import org.apache.fop.pdf.PDFXObject; | |||
import org.apache.fop.pdf.PDFPage; | |||
import org.apache.fop.pdf.PDFState; | |||
import org.apache.fop.pdf.PDFLink; | |||
import org.apache.fop.pdf.PDFOutline; | |||
import org.apache.fop.pdf.PDFAnnotList; | |||
import org.apache.fop.pdf.PDFColor; | |||
import org.apache.fop.extensions.BookmarkData; | |||
import org.apache.fop.area.Trait; | |||
import org.apache.fop.area.TreeExt; | |||
import org.apache.fop.area.CTM; | |||
import org.apache.fop.area.Title; | |||
import org.apache.fop.area.PageViewport; | |||
import org.apache.fop.area.Page; | |||
import org.apache.fop.area.RegionReference; | |||
import org.apache.fop.area.Block; | |||
import org.apache.fop.area.BlockViewport; | |||
import org.apache.fop.area.LineArea; | |||
import org.apache.fop.area.inline.Character; | |||
import org.apache.fop.area.inline.Word; | |||
import org.apache.fop.area.inline.Viewport; | |||
import org.apache.fop.area.inline.ForeignObject; | |||
import org.apache.fop.area.inline.Image; | |||
import org.apache.fop.area.inline.Leader; | |||
import org.apache.fop.area.inline.InlineParent; | |||
import org.apache.fop.layout.FontState; | |||
import org.apache.fop.layout.FontInfo; | |||
import org.apache.fop.layout.FontMetric; | |||
import org.w3c.dom.Document; | |||
@@ -35,20 +57,17 @@ import org.w3c.dom.Document; | |||
import java.io.IOException; | |||
import java.io.OutputStream; | |||
import java.awt.geom.Rectangle2D; | |||
import java.awt.Rectangle; | |||
import java.awt.geom.AffineTransform; | |||
import java.util.HashMap; | |||
import java.util.List; | |||
/* | |||
TODO: | |||
todo: | |||
word rendering and optimistion | |||
pdf state optimisation | |||
line and border | |||
leader | |||
background pattern | |||
orientation | |||
writing mode | |||
text decoration | |||
@@ -59,25 +78,35 @@ text decoration | |||
* | |||
*/ | |||
public class PDFRenderer extends PrintRenderer { | |||
public static final String mimeType = "application/pdf"; | |||
/** | |||
* The mime type for pdf | |||
*/ | |||
public static final String MIME_TYPE = "application/pdf"; | |||
/** | |||
* the PDF Document being created | |||
*/ | |||
protected PDFDocument pdfDoc; | |||
// map of pages using the PageViewport as the key | |||
// this is used for prepared pages that cannot be immediately | |||
// rendered | |||
/** | |||
* 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 | |||
/** | |||
* 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; | |||
private String producer; | |||
/** | |||
* The output stream to write the document to | |||
*/ | |||
protected OutputStream ostream; | |||
/** | |||
@@ -133,7 +162,7 @@ public class PDFRenderer extends PrintRenderer { | |||
/** | |||
* reusable word area string buffer to reduce memory usage | |||
*/ | |||
private StringBuffer _wordAreaPDF = new StringBuffer(); | |||
private StringBuffer wordAreaPDF = new StringBuffer(); | |||
/** | |||
* create the PDF renderer | |||
@@ -153,9 +182,9 @@ public class PDFRenderer extends PrintRenderer { | |||
public void setUserAgent(FOUserAgent agent) { | |||
super.setUserAgent(agent); | |||
PDFXMLHandler xmlHandler = new PDFXMLHandler(); | |||
//userAgent.setDefaultXMLHandler(mimeType, xmlHandler); | |||
//userAgent.setDefaultXMLHandler(MIME_TYPE, xmlHandler); | |||
String svg = "http://www.w3.org/2000/svg"; | |||
userAgent.addXMLHandler(mimeType, svg, xmlHandler); | |||
userAgent.addXMLHandler(MIME_TYPE, svg, xmlHandler); | |||
} | |||
public void startRenderer(OutputStream stream) throws IOException { | |||
@@ -246,9 +275,12 @@ public class PDFRenderer extends PrintRenderer { | |||
*/ | |||
public void renderPage(PageViewport page) throws IOException, | |||
FOPException { | |||
if (pages != null && | |||
(currentPage = (PDFPage) pages.get(page)) != null) { | |||
if (pages != null | |||
&& (currentPage = (PDFPage) pages.get(page)) != null) { | |||
pages.remove(page); | |||
Rectangle2D bounds = page.getViewArea(); | |||
double h = bounds.getHeight(); | |||
pageHeight = (int) h; | |||
} else { | |||
this.pdfResources = this.pdfDoc.getResources(); | |||
Rectangle2D bounds = page.getViewArea(); | |||
@@ -256,18 +288,18 @@ public class PDFRenderer extends PrintRenderer { | |||
double h = bounds.getHeight(); | |||
pageHeight = (int) h; | |||
currentPage = this.pdfDoc.makePage(this.pdfResources, | |||
(int) Math.round(w / 1000), (int) Math.round(h / 1000)); | |||
(int) Math.round(w / 1000), (int) Math.round(h / 1000)); | |||
pageReferences.put(page, currentPage.referencePDF()); | |||
} | |||
currentStream = | |||
this.pdfDoc.makeStream(PDFStream.CONTENT_FILTER, false); | |||
currentState = new PDFState(); | |||
currentState.setTransform( new AffineTransform(1, 0, 0, -1, 0, | |||
currentState.setTransform(new AffineTransform(1, 0, 0, -1, 0, | |||
(int) Math.round(pageHeight / 1000))); | |||
// Transform origin at top left to origin at bottom left | |||
currentStream.add("1 0 0 -1 0 " + | |||
(int) Math.round(pageHeight / 1000) + " cm\n"); | |||
currentStream.add("1 0 0 -1 0 " | |||
+ (int) Math.round(pageHeight / 1000) + " cm\n"); | |||
//currentStream.add("BT\n"); | |||
currentFontName = ""; | |||
@@ -598,8 +630,8 @@ public class PDFRenderer extends PrintRenderer { | |||
} | |||
for (int i = 0; i < uniBytes.length; i++) { | |||
int b = (uniBytes[i] < 0) ? (int)(256 + uniBytes[i]) : | |||
(int) uniBytes[i]; | |||
int b = (uniBytes[i] < 0) ? (int)(256 + uniBytes[i]) | |||
: (int) uniBytes[i]; | |||
String hexString = Integer.toHexString(b); | |||
if (hexString.length() == 1) { | |||
@@ -618,8 +650,8 @@ public class PDFRenderer extends PrintRenderer { | |||
if (kernPair != null) { | |||
Integer width = (Integer) kernPair.get(ch2); | |||
if (width != null) { | |||
buf.append(endText).append(- | |||
(width.intValue())).append(' ').append(startText); | |||
buf.append(endText).append(-width.intValue()); | |||
buf.append(' ').append(startText); | |||
} | |||
} | |||
} | |||
@@ -664,8 +696,8 @@ public class PDFRenderer extends PrintRenderer { | |||
this.currentFontName = name; | |||
this.currentFontSize = size; | |||
pdf = pdf.append("/" + name + " " + ((float) size / 1000f) + | |||
" Tf\n"); | |||
pdf = pdf.append("/" + name + " " + ((float) size / 1000f) | |||
+ " Tf\n"); | |||
} | |||
} | |||
@@ -749,7 +781,7 @@ public class PDFRenderer extends PrintRenderer { | |||
protected void placeImage(int x, int y, int w, int h, int xobj) { | |||
currentStream.add("q\n" + ((float) w) + " 0 0 " | |||
+ ((float) - h) + " " | |||
+ ((float) -h) + " " | |||
+ (((float) currentBlockIPPosition) / 1000f + x) + " " | |||
+ (((float)(currentBPPosition + 1000 * h)) / 1000f | |||
+ y) + " cm\n" + "/Im" + xobj + " Do\nQ\n"); | |||
@@ -764,7 +796,7 @@ public class PDFRenderer extends PrintRenderer { | |||
public void renderDocument(Document doc, String ns, Rectangle2D pos) { | |||
RendererContext context; | |||
context = new RendererContext(mimeType); | |||
context = new RendererContext(MIME_TYPE); | |||
context.setUserAgent(userAgent); | |||
context.setProperty(PDFXMLHandler.PDF_DOCUMENT, pdfDoc); |