Browse Source

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
pull/30/head
Keiron Liddle 22 years ago
parent
commit
c95deb06e2

+ 12
- 17
src/org/apache/fop/apps/LayoutHandler.java View File

@@ -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);

+ 62
- 10
src/org/apache/fop/area/AreaTree.java View File

@@ -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);
}
}

+ 107
- 0
src/org/apache/fop/area/CachedRenderPagesModel.java View File

@@ -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();
}
}
}


+ 22
- 0
src/org/apache/fop/area/Page.java View File

@@ -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;
}
}


+ 142
- 13
src/org/apache/fop/area/PageViewport.java View File

@@ -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());

+ 1
- 2
src/org/apache/fop/area/Resolveable.java View File

@@ -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();


+ 26
- 20
src/org/apache/fop/fo/flow/BasicLink.java View File

@@ -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);
}
}

}

}

+ 28
- 27
src/org/apache/fop/layoutmgr/PageLayoutManager.java View File

@@ -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);

+ 73
- 41
src/org/apache/fop/render/pdf/PDFRenderer.java View File

@@ -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);

Loading…
Cancel
Save