make multi page sequences work properly git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@194825 13f79535-47bb-0310-9956-ffa450edef68pull/30/head
@@ -99,6 +99,10 @@ public class StreamRenderer { | |||
public StreamRenderer(OutputStream outputStream, Renderer renderer) { | |||
this.outputStream = outputStream; | |||
this.renderer = renderer; | |||
this.areaTree = new AreaTree(); | |||
this.atModel = AreaTree.createStorePagesModel(); | |||
areaTree.setTreeModel(atModel); | |||
} | |||
public void setLogger(Logger logger) { | |||
@@ -183,9 +187,6 @@ public class StreamRenderer { | |||
*/ | |||
public void render(PageSequence pageSequence) | |||
throws FOPException { | |||
this.areaTree = new AreaTree(); | |||
this.atModel = AreaTree.createStorePagesModel(); | |||
areaTree.setTreeModel(atModel); | |||
//areaTree.setFontInfo(fontInfo); | |||
// for(Enumeration e = extensions.elements(); e.hasMoreElements(); ) { |
@@ -10,6 +10,7 @@ package org.apache.fop.area; | |||
import org.apache.fop.render.Renderer; | |||
import java.util.ArrayList; | |||
import java.util.HashMap; | |||
/** | |||
* Area tree for formatting objects. | |||
@@ -33,6 +34,12 @@ public class AreaTree { | |||
// in different situations | |||
AreaTreeModel model; | |||
// hashmap of arraylists containing pages with id area | |||
HashMap idLocations = new HashMap(); | |||
// list of id's yet to be resolved and arraylists of pages | |||
HashMap resolve = new HashMap(); | |||
ArrayList treeExtensions = new ArrayList(); | |||
public RenderPagesModel createRenderPagesModel(Renderer rend) { | |||
return new RenderPagesModel(rend); | |||
} | |||
@@ -53,6 +60,28 @@ public class AreaTree { | |||
model.addPage(page); | |||
} | |||
public void addTreeExtension(TreeExt ext) { | |||
treeExtensions.add(ext); | |||
if(ext.isResolveable()) { | |||
Resolveable res = (Resolveable)ext; | |||
String[] ids = res.getIDs(); | |||
for(int count = 0; count < ids.length; count++) { | |||
if(idLocations.containsKey(ids[count])) { | |||
res.resolve(ids[count], (ArrayList)idLocations.get(ids[count])); | |||
} else { | |||
ArrayList todo = (ArrayList)resolve.get(ids[count]); | |||
if(todo == null) { | |||
todo = new ArrayList(); | |||
todo.add(ext); | |||
resolve.put(ids[count], todo); | |||
} else { | |||
todo.add(ext); | |||
} | |||
} | |||
} | |||
} | |||
} | |||
// this is the model for the area tree object | |||
public static abstract class AreaTreeModel { | |||
public abstract void startPageSequence(Title title); | |||
@@ -119,7 +148,11 @@ public class AreaTree { | |||
public void addPage(PageViewport page) { | |||
super.addPage(page); | |||
// if page finished | |||
//renderer.renderPage(page); | |||
try { | |||
renderer.renderPage(page); | |||
} catch(Exception e) { | |||
// use error handler to handle this FOP or IO Exception | |||
} | |||
page.clear(); | |||
// else prepare | |||
//renderer.preparePage(page); |
@@ -80,4 +80,13 @@ public class BodyRegion extends RegionReference { | |||
public MinOptMax getMaxBPD() { | |||
return maxBPD; | |||
} | |||
public Object clone() { | |||
BodyRegion br = new BodyRegion(); | |||
br.setCTM(getCTM()); | |||
br.setIPD(getIPD()); | |||
br.columnGap = columnGap; | |||
br.columnCount = columnCount; | |||
return br; | |||
} | |||
} |
@@ -8,8 +8,9 @@ | |||
package org.apache.fop.area; | |||
import java.io.Serializable; | |||
import java.util.HashMap; | |||
public class Page implements Serializable { | |||
public class Page implements Serializable, Cloneable { | |||
// contains before, start, body, end and after regions | |||
RegionViewport regionBefore = null; | |||
RegionViewport regionStart = null; | |||
@@ -17,6 +18,11 @@ public class Page implements Serializable { | |||
RegionViewport regionEnd = null; | |||
RegionViewport regionAfter = null; | |||
// hashmap of markers for this page | |||
// start and end are added by the fo that contains the markers | |||
HashMap markerStart = null; | |||
HashMap markerEnd = null; | |||
public void setRegion(int areaclass, RegionViewport port) { | |||
if (areaclass == RegionReference.BEFORE) { | |||
regionBefore = port; | |||
@@ -46,4 +52,19 @@ public class Page implements Serializable { | |||
return null; | |||
} | |||
public Object clone() { | |||
Page p = new Page(); | |||
if(regionBefore != null) | |||
p.regionBefore = (RegionViewport)regionBefore.clone(); | |||
if(regionStart != null) | |||
p.regionStart = (RegionViewport)regionStart.clone(); | |||
if(regionBody != null) | |||
p.regionBody = (RegionViewport)regionBody.clone(); | |||
if(regionEnd != null) | |||
p.regionEnd = (RegionViewport)regionEnd.clone(); | |||
if(regionAfter != null) | |||
p.regionAfter = (RegionViewport)regionAfter.clone(); | |||
return p; | |||
} | |||
} |
@@ -14,7 +14,7 @@ import java.util.ArrayList; | |||
// this is the level that creates the page | |||
// the page (reference area) is then rendered inside the page object | |||
public class PageViewport { | |||
public class PageViewport implements Cloneable { | |||
Page page; | |||
Rectangle2D viewArea; | |||
boolean clip = false; | |||
@@ -29,7 +29,7 @@ public class PageViewport { | |||
ArrayList idReferences = null; | |||
// this keeps a list of currently unresolved areas or extensions | |||
// once the things is resolved it is removed | |||
// once the thing is resolved it is removed | |||
// when this is empty the page can be rendered | |||
ArrayList unresolved = null; | |||
@@ -55,9 +55,15 @@ public class PageViewport { | |||
page = (Page) in.readObject(); | |||
} | |||
public Object clone() { | |||
Page p = (Page)page.clone(); | |||
PageViewport ret = new PageViewport(p, (Rectangle2D)viewArea.clone()); | |||
return ret; | |||
} | |||
/** | |||
* Clear the page contents to save memory. | |||
* THis objects is kept for the life of the area tree since | |||
* This object is kept for the life of the area tree since | |||
* it holds id information and is used as a key. | |||
*/ | |||
public void clear() { |
@@ -1,41 +0,0 @@ | |||
/* | |||
* $Id$ | |||
* Copyright (C) 2001 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 java.io.Serializable; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
public class Region implements Serializable { | |||
public static final int BEFORE = 0; | |||
public static final int START = 1; | |||
public static final int BODY = 2; | |||
public static final int END = 3; | |||
public static final int AFTER = 4; | |||
int regionClass = BEFORE; | |||
public Region(int type) { | |||
regionClass = type; | |||
} | |||
// the list of block areas from the static flow | |||
ArrayList blocks = new ArrayList(); | |||
public List getBlocks() { | |||
return blocks; | |||
} | |||
public int getRegionClass() { | |||
return regionClass; | |||
} | |||
public void addBlock(Block block) { | |||
blocks.add(block); | |||
} | |||
} |
@@ -11,7 +11,7 @@ import java.io.Serializable; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
public class RegionReference extends Area implements Serializable { | |||
public class RegionReference extends Area implements Serializable, Cloneable { | |||
public static final int BEFORE = 0; | |||
public static final int START = 1; | |||
public static final int BODY = 2; | |||
@@ -55,4 +55,10 @@ public class RegionReference extends Area implements Serializable { | |||
blocks.add(block); | |||
} | |||
public Object clone() { | |||
RegionReference rr = new RegionReference(regionClass); | |||
rr.ctm = ctm; | |||
rr.setIPD(getIPD()); | |||
return rr; | |||
} | |||
} |
@@ -11,7 +11,7 @@ import java.awt.geom.Rectangle2D; | |||
import java.io.Serializable; | |||
import java.io.IOException; | |||
public class RegionViewport extends Area implements Serializable { | |||
public class RegionViewport extends Area implements Serializable, Cloneable { | |||
// this rectangle is relative to the page | |||
RegionReference region; | |||
Rectangle2D viewArea; | |||
@@ -19,7 +19,7 @@ public class RegionViewport extends Area implements Serializable { | |||
public RegionViewport(Rectangle2D viewArea) { | |||
this.viewArea =viewArea; | |||
this.viewArea = viewArea; | |||
} | |||
public void setRegion(RegionReference reg) { | |||
@@ -57,4 +57,10 @@ public class RegionViewport extends Area implements Serializable { | |||
setRegion( (RegionReference) in.readObject()); | |||
} | |||
public Object clone() { | |||
RegionViewport rv = new RegionViewport((Rectangle2D)viewArea.clone()); | |||
rv.region = (RegionReference)region.clone(); | |||
rv.region.setParent(rv); | |||
return rv; | |||
} | |||
} |
@@ -0,0 +1,26 @@ | |||
/* | |||
* $Id$ | |||
* Copyright (C) 2001 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 java.util.ArrayList; | |||
public interface Resolveable { | |||
public boolean isResolved(); | |||
public String[] getIDs(); | |||
/** | |||
* 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, ArrayList pages); | |||
} |
@@ -0,0 +1,16 @@ | |||
/* | |||
* $Id$ | |||
* Copyright (C) 2001 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; | |||
/** | |||
*/ | |||
public interface TreeExt { | |||
public boolean isResolveable(); | |||
public String getMimeType(); | |||
public String getName(); | |||
} |
@@ -7,14 +7,13 @@ | |||
package org.apache.fop.area.inline; | |||
public class Unresolved extends InlineArea { | |||
boolean resolved = false; | |||
// id ref | |||
// resolve | |||
// resolve without area | |||
import org.apache.fop.area.Resolveable; | |||
public void resolve() { | |||
public abstract class Unresolved extends InlineArea implements Resolveable { | |||
boolean resolved = false; | |||
public boolean isResolved() { | |||
return resolved; | |||
} | |||
} |
@@ -7,10 +7,20 @@ | |||
package org.apache.fop.area.inline; | |||
import java.util.ArrayList; | |||
public class UnresolvedPageNumber extends Unresolved { | |||
String pageRefId; | |||
public UnresolvedPageNumber(String id) { | |||
pageRefId = id; | |||
} | |||
// id ref | |||
// resolve | |||
// resolve without area | |||
public String[] getIDs() { | |||
return new String[] {pageRefId}; | |||
} | |||
public void resolve(String id, ArrayList pages) { | |||
resolved = true; | |||
} | |||
} |
@@ -0,0 +1,90 @@ | |||
/* | |||
* $Id$ | |||
* Copyright (C) 2001 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.extensions; | |||
import org.apache.fop.area.PageViewport; | |||
import org.apache.fop.area.Resolveable; | |||
import org.apache.fop.area.TreeExt; | |||
import java.util.*; | |||
public class BookmarkData implements Resolveable, TreeExt { | |||
private ArrayList subData = new ArrayList(); | |||
private HashMap idRefs = new HashMap(); | |||
String idRef; | |||
PageViewport pageRef = null; | |||
String label = null; | |||
public BookmarkData() { | |||
idRef = null; | |||
} | |||
public BookmarkData(String id) { | |||
idRef = id; | |||
idRefs.put(idRef, this); | |||
} | |||
public String getID() { | |||
return idRef; | |||
} | |||
public void addSubData(BookmarkData sub) { | |||
subData.add(sub); | |||
idRefs.put(sub.getID(), sub); | |||
} | |||
public void setLabel(String l) { | |||
label = l; | |||
} | |||
public boolean isResolveable() { | |||
return true; | |||
} | |||
public String getMimeType() { | |||
return "application/pdf"; | |||
} | |||
public String getName() { | |||
return "Bookmark"; | |||
} | |||
public boolean isResolved() { | |||
return idRefs == null; | |||
} | |||
public String[] getIDs() { | |||
return (String[])idRefs.keySet().toArray(new String[] {}); | |||
} | |||
public void resolve(String id, ArrayList pages) { | |||
if(!id.equals(idRef)) { | |||
BookmarkData bd = (BookmarkData)idRefs.get(id); | |||
bd.resolve(id, pages); | |||
if(bd.isResolved()) { | |||
idRefs.remove(id); | |||
if(idRefs.size() == 0) { | |||
idRefs = null; | |||
} | |||
} | |||
} else { | |||
if(pages != null) { | |||
pageRef = (PageViewport)pages.get(0); | |||
} | |||
// TODO | |||
// get rect area of id on page | |||
idRefs.remove(idRef); | |||
if(idRefs.size() == 0) { | |||
idRefs = null; | |||
} | |||
} | |||
} | |||
} | |||
@@ -0,0 +1,44 @@ | |||
/* | |||
* $Id$ | |||
* Copyright (C) 2001 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.extensions; | |||
import org.apache.fop.fo.FONode; | |||
import java.util.*; | |||
import org.xml.sax.Attributes; | |||
public class Bookmarks extends ExtensionObj { | |||
private ArrayList outlines = new ArrayList(); | |||
private BookmarkData data; | |||
public Bookmarks(FONode parent) { | |||
super(parent); | |||
} | |||
protected void addChild(FONode obj) { | |||
if (obj instanceof Outline) { | |||
outlines.add(obj); | |||
} | |||
} | |||
public BookmarkData getData() { | |||
return data; | |||
} | |||
public void end() { | |||
log.debug("adding bookmarks to area tree"); | |||
data = new BookmarkData(); | |||
for(int count = 0; count < outlines.size(); count++) { | |||
Outline out = (Outline)outlines.get(count); | |||
data.addSubData(out.getData()); | |||
} | |||
// add data to area tree for resolving and handling | |||
} | |||
} | |||
@@ -22,16 +22,25 @@ public class ExtensionElementMapping implements ElementMapping { | |||
private static synchronized void setupExt() { | |||
if(foObjs == null) { | |||
foObjs = new HashMap(); | |||
foObjs.put("bookmarks", new B()); | |||
foObjs.put("outline", new O()); | |||
foObjs.put("label", new L()); | |||
} | |||
} | |||
public void addToBuilder(FOTreeBuilder builder) { | |||
setupExt(); | |||
if(foObjs == null) { | |||
setupExt(); | |||
} | |||
builder.addMapping(URI, foObjs); | |||
} | |||
static class B extends ElementMapping.Maker { | |||
public FONode make(FONode parent) { | |||
return new Bookmarks(parent); | |||
} | |||
} | |||
static class O extends ElementMapping.Maker { | |||
public FONode make(FONode parent) { | |||
return new Outline(parent); |
@@ -7,9 +7,8 @@ | |||
package org.apache.fop.extensions; | |||
import org.apache.fop.fo.*; | |||
import org.apache.fop.layout.*; | |||
import org.apache.fop.apps.FOPException; | |||
import org.apache.fop.fo.FONode; | |||
import org.apache.fop.fo.FObj; | |||
/** | |||
* base class for extension objects | |||
@@ -25,28 +24,5 @@ public abstract class ExtensionObj extends FObj { | |||
super(parent); | |||
} | |||
/** | |||
* Called for extensions within a page sequence or flow. These extensions | |||
* are allowed to generate visible areas within the layout. | |||
* | |||
* @param area | |||
*/ | |||
public Status layout(Area area) throws FOPException { | |||
ExtensionArea extArea = new ExtensionArea(this); | |||
area.addChild(extArea); | |||
return new Status(Status.OK); | |||
} | |||
/** | |||
* Called for root extensions. Root extensions aren't allowed to generate | |||
* any visible areas. They are used for extra items that don't show up in | |||
* the page layout itself. For example: pdf outlines | |||
* | |||
* @param areaTree | |||
*/ | |||
public void format(AreaTree areaTree) throws FOPException { | |||
ExtensionArea extArea = new ExtensionArea(this); | |||
areaTree.addExtension(this); | |||
} | |||
} | |||
@@ -7,21 +7,21 @@ | |||
package org.apache.fop.extensions; | |||
import org.apache.fop.fo.*; | |||
import org.apache.fop.fo.FONode; | |||
public class Label extends ExtensionObj { | |||
private String _label = ""; | |||
private String label = ""; | |||
public Label(FONode parent) { | |||
super(parent); | |||
} | |||
protected void addCharacters(char data[], int start, int end) { | |||
_label += new String(data, start, end - start); | |||
label += new String(data, start, end - start); | |||
} | |||
public String toString() { | |||
return _label; | |||
return label; | |||
} | |||
} |
@@ -7,10 +7,7 @@ | |||
package org.apache.fop.extensions; | |||
import org.apache.fop.fo.*; | |||
import org.apache.fop.pdf.PDFGoTo; | |||
import org.apache.fop.pdf.PDFAction; | |||
import org.apache.fop.datatypes.IDReferences; | |||
import org.apache.fop.fo.FONode; | |||
import org.apache.fop.apps.FOPException; | |||
import java.util.*; | |||
@@ -18,79 +15,51 @@ import java.util.*; | |||
import org.xml.sax.Attributes; | |||
public class Outline extends ExtensionObj { | |||
private Label _label; | |||
private ArrayList _outlines = new ArrayList(); | |||
private Label label; | |||
private ArrayList outlines = new ArrayList(); | |||
private String _internalDestination; | |||
private String _externalDestination; | |||
/** | |||
* The parent outline object if it exists | |||
*/ | |||
private Outline _parentOutline; | |||
/** | |||
* an opaque renderer context object, e.g. PDFOutline for PDFRenderer | |||
*/ | |||
private Object _rendererObject; | |||
private String internalDestination; | |||
private String externalDestination; | |||
public Outline(FONode parent) { | |||
super(parent); | |||
} | |||
public void handleAttrs(Attributes attlist) throws FOPException { | |||
_internalDestination = | |||
attlist.getValue(null, "internal-destination"); | |||
_externalDestination = | |||
attlist.getValue(null, "external-destination"); | |||
if (_externalDestination != null &&!_externalDestination.equals("")) { | |||
internalDestination = | |||
attlist.getValue("internal-destination"); | |||
externalDestination = | |||
attlist.getValue("external-destination"); | |||
if (externalDestination != null &&!externalDestination.equals("")) { | |||
log.warn("fox:outline external-destination not supported currently."); | |||
} | |||
if (_internalDestination == null || _internalDestination.equals("")) { | |||
if (internalDestination == null || internalDestination.equals("")) { | |||
log.warn("fox:outline requires an internal-destination."); | |||
} | |||
for (FONode node = getParent(); node != null; | |||
node = node.getParent()) { | |||
if (node instanceof Outline) { | |||
_parentOutline = (Outline)node; | |||
break; | |||
} | |||
} | |||
} | |||
protected void addChild(FONode obj) { | |||
if (obj instanceof Label) { | |||
_label = (Label)obj; | |||
label = (Label)obj; | |||
} else if (obj instanceof Outline) { | |||
_outlines.add(obj); | |||
outlines.add(obj); | |||
} | |||
} | |||
public void setRendererObject(Object o) { | |||
_rendererObject = o; | |||
} | |||
public Object getRendererObject() { | |||
return _rendererObject; | |||
} | |||
public Outline getParentOutline() { | |||
return _parentOutline; | |||
} | |||
public Label getLabel() { | |||
return _label == null ? new Label(this) : _label; | |||
} | |||
public ArrayList getOutlines() { | |||
return _outlines; | |||
public BookmarkData getData() { | |||
BookmarkData data = new BookmarkData(internalDestination); | |||
data.setLabel(getLabel()); | |||
for(int count = 0; count < outlines.size(); count++) { | |||
Outline out = (Outline)outlines.get(count); | |||
data.addSubData(out.getData()); | |||
} | |||
return data; | |||
} | |||
public String getInternalDestination() { | |||
return _internalDestination; | |||
public String getLabel() { | |||
return label == null ? "" : label.toString(); | |||
} | |||
} |
@@ -16,68 +16,12 @@ public class PageMaster { | |||
private PageViewport pageVP ; | |||
public PageMaster(PageViewport pageVP) { | |||
this.pageVP = pageVP; | |||
this.pageVP = pageVP; | |||
} | |||
// Use serialization to make a clone of the master | |||
// make a clone of the master | |||
public PageViewport makePage() { | |||
try { | |||
System.err.println("PageMaster.makePage"); | |||
PipedOutputStream outputStream = new PipedOutputStream(); | |||
PipedInputStream inputStream = new PipedInputStream(outputStream); | |||
//System.err.println("PageMaster.makePage made piped streams"); | |||
ObjectOutputStream objOut = | |||
new ObjectOutputStream(new BufferedOutputStream(outputStream)); | |||
/* ObjectInputStream objIn = | |||
new ObjectInputStream(new BufferedInputStream(inputStream));*/ | |||
//System.err.println("PageMaster.makePage: streams made"); | |||
PageViewport newPageVP = new PageViewport(pageVP.getPage(), | |||
pageVP.getViewArea()); | |||
//System.err.println("PageMaster.makePage: newPageVP made"); | |||
Thread reader = new Thread(new PageReader(inputStream, newPageVP)); | |||
//System.err.println("Start serialize"); | |||
reader.start(); | |||
//System.err.println("Save page"); | |||
pageVP.savePage(objOut); | |||
objOut.close(); | |||
//System.err.println("Save page done"); | |||
reader.join(); | |||
//System.err.println("join done"); | |||
// objIn.close(); | |||
return newPageVP; | |||
} catch (Exception e) { | |||
System.err.println("PageMaster.makePage(): " + e.getMessage()); | |||
return null; | |||
} | |||
} | |||
static private class PageReader implements Runnable { | |||
private InputStream is; | |||
private PageViewport pvp; | |||
PageReader(InputStream is, PageViewport pvp) { | |||
//System.err.println("PageReader object made"); | |||
this.is = is; | |||
this.pvp = pvp; | |||
} | |||
public void run() { | |||
try { | |||
//System.err.println("PageReader make ObjectInputStream"); | |||
ObjectInputStream ois = new ObjectInputStream(is); | |||
//System.err.println("Load page"); | |||
pvp.loadPage(ois); | |||
//System.err.println("Load page done"); | |||
} catch (Exception e) { | |||
System.err.println("Error copying PageViewport: " + | |||
e); | |||
} | |||
} | |||
return (PageViewport)pageVP.clone(); | |||
} | |||
} |
@@ -65,6 +65,7 @@ public class PageLayoutManager extends AbstractLayoutManager implements Runnable | |||
*/ | |||
public void run() { | |||
generateAreas(); | |||
flush(); | |||
} | |||
@@ -1132,7 +1132,7 @@ public class PDFDocument { | |||
* Make an outline object and add it to the given outline | |||
* @param parent parent PDFOutline object | |||
* @param label the title for the new outline object | |||
* @param action the PDFAction to reference | |||
* @param destination the reference string for the action to go to | |||
*/ | |||
public PDFOutline makeOutline(PDFOutline parent, String label, | |||
String destination) { |
@@ -142,7 +142,7 @@ public abstract class AbstractRenderer implements Renderer { | |||
RegionReference region = port.getRegion(); | |||
startVParea(region.getCTM()); | |||
if (region.getRegionClass() == Region.BODY) { | |||
if (region.getRegionClass() == RegionReference.BODY) { | |||
renderBodyRegion((BodyRegion) region); | |||
} else { | |||
renderRegion(region); |