some other misc updates to areas git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@194534 13f79535-47bb-0310-9956-ffa450edef68pull/30/head
public static synchronized Enumeration providers(Class cls) { | public static synchronized Enumeration providers(Class cls) { | ||||
ClassLoader cl = cls.getClassLoader(); | ClassLoader cl = cls.getClassLoader(); | ||||
// null if loaded by bootstrap class loader | |||||
if(cl == null) { | |||||
cl = ClassLoader.getSystemClassLoader(); | |||||
} | |||||
String serviceFile = "META-INF/services/" + cls.getName(); | String serviceFile = "META-INF/services/" + cls.getName(); | ||||
// System.out.println("File: " + serviceFile); | // System.out.println("File: " + serviceFile); |
package org.apache.fop.area; | package org.apache.fop.area; | ||||
import java.io.Serializable; | |||||
import java.util.List; | import java.util.List; | ||||
import java.util.ArrayList; | import java.util.ArrayList; | ||||
// may combine with before float into a conditional area | // may combine with before float into a conditional area | ||||
public class Footnote { | |||||
public class Footnote implements Serializable { | |||||
Block separator = null; | Block separator = null; | ||||
// footnote has an optional separator | // footnote has an optional separator |
package org.apache.fop.area; | package org.apache.fop.area; | ||||
import org.apache.fop.datatypes.ColorType; | |||||
import java.io.Serializable; | import java.io.Serializable; | ||||
// properties should be serialized by the holder | // properties should be serialized by the holder | ||||
public static final int LINETHROUGH = 12; | public static final int LINETHROUGH = 12; | ||||
public static final int OFFSET = 13; | public static final int OFFSET = 13; | ||||
public static final int SHADOW = 14; | public static final int SHADOW = 14; | ||||
public int propType; | public int propType; | ||||
public Object data; | public Object data; | ||||
public static class Background { | |||||
ColorType color; | |||||
String url; | |||||
int repeat; | |||||
int horiz; | |||||
int vertical; | |||||
} | |||||
} | } | ||||
import java.util.List; | import java.util.List; | ||||
import java.util.ArrayList; | import java.util.ArrayList; | ||||
// this is an inline area that can have blocks as children | |||||
public class Container extends Area { | public class Container extends Area { | ||||
ArrayList blocks = new ArrayList(); | ArrayList blocks = new ArrayList(); | ||||
int width; | |||||
// this is an inline area that can have blocks as children | |||||
public Container() { | |||||
} | |||||
public void render(Renderer renderer) { | public void render(Renderer renderer) { | ||||
renderer.renderContainer(this); | renderer.renderContainer(this); | ||||
return blocks; | return blocks; | ||||
} | } | ||||
public int getWidth() { | |||||
return width; | |||||
} | |||||
} | } |
return width; | return width; | ||||
} | } | ||||
public void setOffset(int v) { | |||||
verticalPosition = v; | |||||
} | |||||
public int getOffset() { | |||||
return verticalPosition; | |||||
} | |||||
public void addProperty(Property prop) { | public void addProperty(Property prop) { | ||||
if (props == null) { | if (props == null) { | ||||
props = new ArrayList(); | props = new ArrayList(); |
public void render(Renderer renderer) { | public void render(Renderer renderer) { | ||||
renderer.renderWord(this); | renderer.renderWord(this); | ||||
} | } | ||||
public void setWord(String w) { | |||||
word = w; | |||||
} | |||||
public String getWord() { | |||||
return word; | |||||
} | |||||
} | } |
* Creates id entry that hasn't been validated | * Creates id entry that hasn't been validated | ||||
* | * | ||||
* @param id The id to create | * @param id The id to create | ||||
* @exception FOPException | |||||
*/ | */ | ||||
public void createUnvalidatedID(String id) { | public void createUnvalidatedID(String id) { | ||||
if (id != null &&!id.equals("")) { | if (id != null &&!id.equals("")) { | ||||
* Removes id from IDReferences | * Removes id from IDReferences | ||||
* | * | ||||
* @param id The id to remove | * @param id The id to remove | ||||
* @exception FOPException | |||||
*/ | */ | ||||
public void removeID(String id) { | public void removeID(String id) { | ||||
idReferences.remove(id); | idReferences.remove(id); |
// Java | // Java | ||||
import java.util.HashMap; | import java.util.HashMap; | ||||
import java.util.Stack; | import java.util.Stack; | ||||
import java.util.Vector; | |||||
import java.util.ArrayList; | |||||
import java.io.IOException; | import java.io.IOException; | ||||
/** | /** | ||||
*/ | */ | ||||
protected HashMap fobjTable = new HashMap(); | protected HashMap fobjTable = new HashMap(); | ||||
protected Vector namespaces = new Vector(); | |||||
protected ArrayList namespaces = new ArrayList(); | |||||
/** | /** | ||||
* class that builds a property list for each formatting object | * class that builds a property list for each formatting object | ||||
*/ | */ | ||||
public void addMapping(String namespaceURI, HashMap table) { | public void addMapping(String namespaceURI, HashMap table) { | ||||
this.fobjTable.put(namespaceURI, table); | this.fobjTable.put(namespaceURI, table); | ||||
this.namespaces.addElement(namespaceURI.intern()); | |||||
this.namespaces.add(namespaceURI.intern()); | |||||
} | } | ||||
/** | /** | ||||
/* the maker for the formatting object started */ | /* the maker for the formatting object started */ | ||||
FObj.Maker fobjMaker = null; | FObj.Maker fobjMaker = null; | ||||
// String fullName = mapName(rawName); | |||||
//String fullName = uri + "^" + localName; | |||||
HashMap table = (HashMap)fobjTable.get(uri); | HashMap table = (HashMap)fobjTable.get(uri); | ||||
if(table != null) { | if(table != null) { | ||||
fobjMaker = (FObj.Maker)table.get(localName); | fobjMaker = (FObj.Maker)table.get(localName); | ||||
currentFObj = fobj; | currentFObj = fobj; | ||||
} | } | ||||
/** | |||||
* format this formatting object tree | |||||
* | |||||
* @param areaTree the area tree to format into | |||||
*/ | |||||
/* public void format(AreaTree areaTree) throws FOPException { | |||||
log.info("formatting FOs into areas"); | |||||
this.bufferManager.readComplete(); | |||||
((Root)this.rootFObj).format(areaTree); | |||||
} | |||||
*/ | |||||
public void reset() { | public void reset() { | ||||
currentFObj = null; | currentFObj = null; | ||||
rootFObj = null; | rootFObj = null; |
handler.handleXML(ctx, doc, namespace); | handler.handleXML(ctx, doc, namespace); | ||||
} catch (Throwable t) { | } catch (Throwable t) { | ||||
// could not handle document | // could not handle document | ||||
//t.printStackTrace(); | |||||
t.printStackTrace(); | |||||
} | } | ||||
} else { | } else { | ||||
// no handler found for document | // no handler found for document |
// Java | // Java | ||||
import java.util.*; | import java.util.*; | ||||
/** | /** | ||||
* This provides pagination of flows onto pages. Much of the logic for paginating | |||||
* flows is contained in this class. The main entry point is the format method. | |||||
* This provides pagination of flows onto pages. Much of the | |||||
* logic for paginating flows is contained in this class. | |||||
* The main entry point is the format method. | |||||
*/ | */ | ||||
public class PageSequence extends FObj { | public class PageSequence extends FObj { | ||||
// | // |
package org.apache.fop.messaging; | package org.apache.fop.messaging; | ||||
/** | /** | ||||
* A trivial implementation of a MessageListener | * A trivial implementation of a MessageListener | ||||
* For further explanation | * For further explanation | ||||
* @see MessageListener | |||||
*/ | */ | ||||
public class DefaultMessageListener implements MessageListener { | public class DefaultMessageListener implements MessageListener { | ||||
/** | /** |
* a container for the text and the type of a message | * a container for the text and the type of a message | ||||
* MessageEvents are created by MessageHandler and can be received by any | * MessageEvents are created by MessageHandler and can be received by any | ||||
* MessageListener, which is added to MessageHandler; | * MessageListener, which is added to MessageHandler; | ||||
* @see org.apache.fop.MessageListener MessageListener | |||||
* | |||||
*/ | */ | ||||
public class MessageEvent extends EventObject { | public class MessageEvent extends EventObject { | ||||
public static final int LOG = 0; | public static final int LOG = 0; | ||||
public static final int ERROR = 1; | public static final int ERROR = 1; |
import org.apache.fop.area.*; | import org.apache.fop.area.*; | ||||
import org.apache.fop.area.Span; | import org.apache.fop.area.Span; | ||||
import org.apache.fop.area.inline.*; | import org.apache.fop.area.inline.*; | ||||
import org.apache.fop.area.inline.Character; | |||||
import org.apache.fop.area.inline.Space; | import org.apache.fop.area.inline.Space; | ||||
import org.apache.fop.fo.FOUserAgent; | import org.apache.fop.fo.FOUserAgent; | ||||
import org.apache.log.Logger; | import org.apache.log.Logger; | ||||
// Java | // Java | ||||
import java.awt.geom.Rectangle2D; | |||||
import java.io.IOException; | import java.io.IOException; | ||||
import java.io.OutputStream; | import java.io.OutputStream; | ||||
import java.util.HashMap; | import java.util.HashMap; | ||||
options = opt; | options = opt; | ||||
} | } | ||||
/** | |||||
* Utility method to convert a page sequence title to a string. | |||||
* Some renderers may only be able to use a string title. | |||||
* A title is a sequence of inline areas that this method | |||||
* attempts to convert to an equivalent string. | |||||
*/ | |||||
public String convertTitleToString(Title title) { | |||||
String str = ""; | |||||
List children = title.getInlineAreas(); | |||||
for (int count = 0; count < children.size(); count++) { | |||||
InlineArea inline = (InlineArea) children.get(count); | |||||
if (inline instanceof Character) { | |||||
str += ((Character) inline).getChar(); | |||||
} else if (inline instanceof Word) { | |||||
str += ((Word) inline).getWord(); | |||||
} else { | |||||
str += " "; | |||||
} | |||||
} | |||||
return str.trim(); | |||||
} | |||||
public void startPageSequence(Title seqTitle) { | public void startPageSequence(Title seqTitle) { | ||||
} | } | ||||
// a position from where the region is placed | // a position from where the region is placed | ||||
protected void renderRegionViewport(RegionViewport port) { | protected void renderRegionViewport(RegionViewport port) { | ||||
if (port != null) { | if (port != null) { | ||||
Rectangle2D view = port.getViewArea(); | |||||
currentBPPosition = (int) view.getY(); | |||||
currentIPPosition = (int) view.getX(); | |||||
currentBlockIPPosition = currentIPPosition; | |||||
Region region = port.getRegion(); | Region region = port.getRegion(); | ||||
if (region.getRegionClass() == Region.BODY) { | if (region.getRegionClass() == Region.BODY) { | ||||
renderBodyRegion((BodyRegion) region); | renderBodyRegion((BodyRegion) region); | ||||
// of the line, each inline object is offset from there | // of the line, each inline object is offset from there | ||||
for (int count = 0; count < children.size(); count++) { | for (int count = 0; count < children.size(); count++) { | ||||
LineArea line = (LineArea) children.get(count); | LineArea line = (LineArea) children.get(count); | ||||
currentBlockIPPosition = currentIPPosition; | |||||
renderLineArea(line); | renderLineArea(line); | ||||
currentBPPosition += line.getHeight(); | |||||
} | } | ||||
} | } | ||||
} else if (content instanceof ForeignObject) { | } else if (content instanceof ForeignObject) { | ||||
renderForeignObject((ForeignObject) content); | renderForeignObject((ForeignObject) content); | ||||
} | } | ||||
currentBlockIPPosition += viewport.getWidth(); | |||||
} | } | ||||
public void renderImage(Image image) { | public void renderImage(Image image) { | ||||
} | } | ||||
public void renderContainer(Container cont) { | public void renderContainer(Container cont) { | ||||
int saveIP = currentIPPosition; | |||||
currentIPPosition = currentBlockIPPosition; | |||||
int saveBlockIP = currentBlockIPPosition; | |||||
int saveBP = currentBPPosition; | |||||
List blocks = cont.getBlocks(); | List blocks = cont.getBlocks(); | ||||
renderBlocks(blocks); | renderBlocks(blocks); | ||||
currentIPPosition = saveIP; | |||||
currentBlockIPPosition = saveBlockIP; | |||||
currentBPPosition = saveBP; | |||||
} | } | ||||
public void renderForeignObject(ForeignObject fo) { | public void renderForeignObject(ForeignObject fo) { | ||||
} | } | ||||
public void renderCharacter(org.apache.fop.area.inline.Character ch) { | |||||
public void renderCharacter(Character ch) { | |||||
currentBlockIPPosition += ch.getWidth(); | currentBlockIPPosition += ch.getWidth(); | ||||
} | } | ||||
package org.apache.fop.render.svg; | package org.apache.fop.render.svg; | ||||
import org.apache.fop.layout.*; | |||||
import org.apache.fop.layout.inline.*; | |||||
import org.apache.fop.apps.FOPException; | |||||
import org.apache.fop.area.*; | |||||
import org.apache.fop.area.inline.*; | |||||
import org.apache.fop.datatypes.IDReferences; | import org.apache.fop.datatypes.IDReferences; | ||||
import org.apache.fop.datatypes.ColorType; | import org.apache.fop.datatypes.ColorType; | ||||
import org.apache.fop.image.*; | import org.apache.fop.image.*; | ||||
import org.apache.fop.svg.SVGArea; | import org.apache.fop.svg.SVGArea; | ||||
import org.apache.fop.svg.SVGUtilities; | import org.apache.fop.svg.SVGUtilities; | ||||
import org.apache.fop.layout.FontInfo; | |||||
import org.apache.fop.fo.FOUserAgent; | |||||
import org.w3c.dom.Node; | import org.w3c.dom.Node; | ||||
import org.w3c.dom.ProcessingInstruction; | import org.w3c.dom.ProcessingInstruction; | ||||
import org.w3c.dom.Document; | import org.w3c.dom.Document; | ||||
import org.w3c.dom.Element; | import org.w3c.dom.Element; | ||||
import org.w3c.dom.DOMImplementation; | import org.w3c.dom.DOMImplementation; | ||||
import org.w3c.dom.Text; | |||||
import org.apache.batik.dom.svg.SVGDOMImplementation; | import org.apache.batik.dom.svg.SVGDOMImplementation; | ||||
import org.apache.batik.dom.svg.SVGOMElement; | import org.apache.batik.dom.svg.SVGOMElement; | ||||
import org.apache.batik.transcoder.TranscoderInput; | import org.apache.batik.transcoder.TranscoderInput; | ||||
import org.apache.batik.transcoder.TranscoderOutput; | import org.apache.batik.transcoder.TranscoderOutput; | ||||
import org.apache.batik.transcoder.TranscoderException; | import org.apache.batik.transcoder.TranscoderException; | ||||
import org.apache.batik.dom.util.DOMUtilities; | |||||
import java.awt.Color; | import java.awt.Color; | ||||
import java.awt.Image; | import java.awt.Image; | ||||
import java.awt.image.BufferedImage; | import java.awt.image.BufferedImage; | ||||
import java.awt.geom.Rectangle2D; | import java.awt.geom.Rectangle2D; | ||||
import java.util.Hashtable; | |||||
import java.util.HashMap; | |||||
import java.net.URL; | import java.net.URL; | ||||
import java.net.MalformedURLException; | import java.net.MalformedURLException; | ||||
import java.io.OutputStream; | import java.io.OutputStream; | ||||
import javax.swing.ImageIcon; | import javax.swing.ImageIcon; | ||||
import org.apache.fop.render.AbstractRenderer; | import org.apache.fop.render.AbstractRenderer; | ||||
import org.apache.fop.render.XMLHandler; | |||||
import org.apache.fop.render.RendererContext; | |||||
public class SVGRenderer extends AbstractRenderer { | |||||
public class SVGRenderer extends AbstractRenderer implements XMLHandler { | |||||
public static final String mimeType = "image/svg+xml"; | |||||
static final String svgNS = SVGDOMImplementation.SVG_NAMESPACE_URI; | static final String svgNS = SVGDOMImplementation.SVG_NAMESPACE_URI; | ||||
Document svgDocument; | Document svgDocument; | ||||
Element svgRoot; | Element svgRoot; | ||||
Element currentPageG = null; | Element currentPageG = null; | ||||
Element lastLink = null; | Element lastLink = null; | ||||
String lastViewbox = null; | |||||
Element docDefs = null; | |||||
Element pageDefs = null; | |||||
Element pagesGroup = null; | |||||
// first sequence title | |||||
Title docTitle = null; | |||||
RendererContext context; | |||||
OutputStream ostream; | |||||
float totalWidth = 0; | float totalWidth = 0; | ||||
float totalHeight = 0; | float totalHeight = 0; | ||||
float sequenceWidth = 0; | |||||
float sequenceHeight = 0; | |||||
protected int pageWidth = 0; | |||||
protected int pageHeight = 0; | |||||
protected float pageWidth = 0; | |||||
protected float pageHeight = 0; | |||||
protected int pageNumber = 0; | protected int pageNumber = 0; | ||||
protected Hashtable fontNames = new Hashtable(); | |||||
protected Hashtable fontStyles = new Hashtable(); | |||||
protected HashMap fontNames = new HashMap(); | |||||
protected HashMap fontStyles = new HashMap(); | |||||
protected Color saveColor = null; | protected Color saveColor = null; | ||||
protected IDReferences idReferences = null; | protected IDReferences idReferences = null; | ||||
protected float currentBlue = 0; | protected float currentBlue = 0; | ||||
public SVGRenderer() { | public SVGRenderer() { | ||||
context = new RendererContext(mimeType); | |||||
} | |||||
public void setUserAgent(FOUserAgent agent) { | |||||
super.setUserAgent(agent); | |||||
userAgent.setDefaultXMLHandler(mimeType, this); | |||||
userAgent.addXMLHandler(mimeType, svgNS, this); | |||||
} | } | ||||
public void setupFontInfo(FontInfo fontInfo) { | public void setupFontInfo(FontInfo fontInfo) { | ||||
// create a temp Image to test font metrics on | // create a temp Image to test font metrics on | ||||
BufferedImage fontImage = | BufferedImage fontImage = | ||||
new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB); | |||||
org.apache.fop.render.awt.FontSetup.setup(fontInfo, fontImage.createGraphics()); | |||||
new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB); | |||||
org.apache.fop.render.awt.FontSetup.setup(fontInfo, | |||||
fontImage.createGraphics()); | |||||
} | } | ||||
public void setProducer(String producer) { | public void setProducer(String producer) { | ||||
} | } | ||||
public void startRenderer(OutputStream outputStream) | public void startRenderer(OutputStream outputStream) | ||||
throws IOException {} | |||||
throws IOException { | |||||
ostream = outputStream; | |||||
DOMImplementation impl = | |||||
SVGDOMImplementation.getDOMImplementation(); | |||||
svgDocument = impl.createDocument(svgNS, "svg", null); | |||||
ProcessingInstruction pi = | |||||
svgDocument.createProcessingInstruction("xml", " version=\"1.0\" encoding=\"ISO-8859-1\""); | |||||
svgRoot = svgDocument.getDocumentElement(); | |||||
svgDocument.insertBefore(pi, svgRoot); | |||||
docDefs = svgDocument.createElementNS(svgNS, "defs"); | |||||
svgRoot.appendChild(docDefs); | |||||
pagesGroup = svgDocument.createElementNS(svgNS, "g"); | |||||
pageDefs = svgDocument.createElementNS(svgNS, "defs"); | |||||
pagesGroup.appendChild(pageDefs); | |||||
svgRoot.appendChild(pagesGroup); | |||||
} | |||||
/** | /** | ||||
* | * | ||||
*/ | */ | ||||
public void stopRenderer() | |||||
throws IOException | |||||
{ | |||||
public void stopRenderer() throws IOException { | |||||
totalWidth += sequenceWidth; | |||||
if (sequenceHeight > totalHeight) { | |||||
totalHeight = sequenceHeight; | |||||
} | |||||
svgRoot.setAttributeNS(null, "width", "" + (totalWidth + 1)); | |||||
svgRoot.setAttributeNS(null, "height", "" + (totalHeight + 1)); | |||||
//svgRoot.setAttributeNS(null, "viewBox", "0 0 " + pageWidth + " " + pageHeight); | |||||
SVGTranscoder svgT = new SVGTranscoder(); | |||||
TranscoderInput input = new TranscoderInput(svgDocument); | |||||
TranscoderOutput output = | |||||
new TranscoderOutput(new OutputStreamWriter(ostream)); | |||||
try { | |||||
svgT.transcode(input, output); | |||||
} catch (TranscoderException e) { | |||||
log.error("could not write svg file :" + e.getMessage(), e); | |||||
} | |||||
ostream.flush(); | |||||
ostream = null; | |||||
svgDocument = null; | |||||
svgRoot = null; | |||||
currentPageG = null; | |||||
lastLink = null; | |||||
totalWidth = 0; | |||||
totalHeight = 0; | |||||
pageNumber = 0; | |||||
} | |||||
public void startPageSequence(Title seqTitle) { | |||||
totalWidth += sequenceWidth; | |||||
if (sequenceHeight > totalHeight) { | |||||
totalHeight = sequenceHeight; | |||||
} | |||||
sequenceWidth = 0; | |||||
sequenceHeight = 0; | |||||
if (seqTitle != null && docTitle == null) { | |||||
// convert first title to a string and set for svg document title | |||||
docTitle = seqTitle; | |||||
String str = convertTitleToString(seqTitle); | |||||
Element svgTitle = svgDocument.createElementNS(svgNS, "title"); | |||||
Text strNode = svgDocument.createTextNode(str); | |||||
svgTitle.appendChild(strNode); | |||||
svgRoot.insertBefore(svgTitle, svgRoot.getFirstChild()); | |||||
} | |||||
} | |||||
public void renderPage(PageViewport page) throws IOException, | |||||
FOPException { | |||||
float lastWidth = pageWidth; | |||||
float lastHeight = pageHeight; | |||||
Rectangle2D area = page.getViewArea(); | |||||
pageWidth = (float) area.getWidth() / 1000f; | |||||
pageHeight = (float) area.getHeight() / 1000f; | |||||
// if there is a link from the last page | |||||
if (lastLink != null) { | |||||
lastLink.setAttributeNS(null, "xlink:href", | |||||
"#svgView(viewBox(" + totalWidth + ", "+ | |||||
sequenceHeight + ", " + pageWidth + ", " + | |||||
pageHeight + "))"); | |||||
pagesGroup.appendChild(lastLink); | |||||
} | |||||
currentPageG = svgDocument.createElementNS(svgNS, "svg"); | |||||
currentPageG.setAttributeNS(null, "viewbox", | |||||
"0 0 " + (int) pageWidth + " " + (int) pageHeight); | |||||
currentPageG.setAttributeNS(null, "width", | |||||
"" + ((int) pageWidth + 1)); | |||||
currentPageG.setAttributeNS(null, "height", | |||||
"" + ((int) pageHeight + 1)); | |||||
currentPageG.setAttributeNS(null, "id", "Page-" + pageNumber); | |||||
currentPageG.setAttributeNS(null, "style", "font-family:sanserif;font-size:12"); | |||||
pageDefs.appendChild(currentPageG); | |||||
if (pageWidth > sequenceWidth) { | |||||
sequenceWidth = pageWidth; | |||||
} | |||||
sequenceHeight += pageHeight; | |||||
Element border = | |||||
SVGUtilities.createRect(svgDocument, 0, 0, pageWidth, | |||||
pageHeight); | |||||
border.setAttributeNS(null, "style", "fill:none;stroke:black"); | |||||
currentPageG.appendChild(border); | |||||
// render the page contents | |||||
super.renderPage(page); | |||||
Element use = svgDocument.createElementNS(svgNS, "use"); | |||||
use.setAttributeNS(null, "xlink:href", "#Page-" + pageNumber); | |||||
use.setAttributeNS(null, "x", "" + totalWidth); | |||||
use.setAttributeNS(null, "y", "" + (sequenceHeight - pageHeight)); | |||||
pagesGroup.appendChild(use); | |||||
Element lastPageLink = svgDocument.createElementNS(svgNS, "a"); | |||||
if (lastLink != null) { | |||||
lastPageLink.setAttributeNS(null, "xlink:href", lastViewbox); | |||||
} else { | |||||
lastPageLink.setAttributeNS(null, "xlink:href", | |||||
"#svgView(viewBox(" + totalWidth + ", " + | |||||
(sequenceHeight - pageHeight) + ", " + pageWidth + | |||||
", " + pageHeight + "))"); | |||||
} | |||||
pagesGroup.appendChild(lastPageLink); | |||||
// setup a link to the next page, only added when the | |||||
// next page is rendered | |||||
Element rect = SVGUtilities.createRect(svgDocument, totalWidth, | |||||
(sequenceHeight - pageHeight), pageWidth / 2, pageHeight); | |||||
rect.setAttributeNS(null, "style", "fill:blue;visibility:hidden"); | |||||
lastPageLink.appendChild(rect); | |||||
lastLink = svgDocument.createElementNS(svgNS, "a"); | |||||
rect = SVGUtilities.createRect(svgDocument, | |||||
totalWidth + pageWidth / 2, | |||||
(sequenceHeight - pageHeight), pageWidth / 2, pageHeight); | |||||
rect.setAttributeNS(null, "style", "fill:blue;visibility:hidden"); | |||||
lastLink.appendChild(rect); | |||||
lastViewbox = "#svgView(viewBox(" + totalWidth + ", " + | |||||
(sequenceHeight - pageHeight) + ", " + pageWidth + | |||||
", " + pageHeight + "))"; | |||||
pageNumber++; | |||||
} | |||||
public void renderForeignObject(ForeignObject fo) { | |||||
Document doc = fo.getDocument(); | |||||
String ns = fo.getNameSpace(); | |||||
userAgent.renderXML(context, doc, ns); | |||||
} | |||||
public void handleXML(RendererContext context, Document doc, | |||||
String ns) throws Exception { | |||||
if (svgNS.equals(ns)) { | |||||
if (!(doc instanceof SVGDocument)) { | |||||
DOMImplementation impl = | |||||
SVGDOMImplementation.getDOMImplementation(); | |||||
doc = DOMUtilities.deepCloneDocument(doc, impl); | |||||
} | |||||
SVGSVGElement svg = ((SVGDocument) doc).getRootElement(); | |||||
Element view = svgDocument.createElementNS(svgNS, "svg"); | |||||
Node newsvg = svgDocument.importNode(svg, true); | |||||
//view.setAttributeNS(null, "viewBox", "0 0 "); | |||||
view.setAttributeNS(null, "x", | |||||
"" + currentBlockIPPosition / 1000f); | |||||
view.setAttributeNS(null, "y", "" + currentBPPosition / 1000f); | |||||
// this fixes a problem where the xmlns is repeated sometimes | |||||
Element ele = (Element) newsvg; | |||||
ele.setAttributeNS(XMLSupport.XMLNS_NAMESPACE_URI, "xmlns", | |||||
svgNS); | |||||
if (ele.hasAttributeNS(null, "xmlns")) { | |||||
ele.removeAttributeNS(null, "xmlns"); | |||||
} | |||||
view.appendChild(newsvg); | |||||
currentPageG.appendChild(view); | |||||
} | |||||
} | |||||
public void renderLeader(Leader area) { | |||||
String style = "stroke:black;stroke-width:" + | |||||
(area.getRuleThickness() / 1000) + ";"; | |||||
switch (area.getRuleStyle()) { | |||||
case Leader.DOTTED: | |||||
style += "stroke-dasharray:1,1"; | |||||
break; | |||||
case Leader.DASHED: | |||||
style += "stroke-dasharray:5,1"; | |||||
break; | |||||
case Leader.SOLID: | |||||
break; | |||||
case Leader.DOUBLE: | |||||
break; | |||||
case Leader.GROOVE: | |||||
break; | |||||
case Leader.RIDGE: | |||||
break; | |||||
} | |||||
Element line = SVGUtilities.createLine(svgDocument, | |||||
currentBlockIPPosition / 1000, | |||||
(currentBPPosition + area.getOffset() - | |||||
area.getRuleThickness() / 2) / 1000, | |||||
(currentBlockIPPosition + area.getWidth()) / 1000, | |||||
(currentBPPosition + area.getOffset() - | |||||
area.getRuleThickness() / 2) / 1000); | |||||
line.setAttributeNS(null, "style", style); | |||||
currentPageG.appendChild(line); | |||||
super.renderLeader(area); | |||||
} | |||||
public void renderWord(Word word) { | |||||
Element text = SVGUtilities.createText(svgDocument, | |||||
currentBlockIPPosition / 1000, | |||||
(currentBPPosition + word.getOffset()) / 1000, | |||||
word.getWord()); | |||||
currentPageG.appendChild(text); | |||||
super.renderWord(word); | |||||
} | |||||
public void renderCharacter(org.apache.fop.area.inline.Character ch) { | |||||
Element text = SVGUtilities.createText(svgDocument, | |||||
currentBlockIPPosition / 1000, | |||||
(currentBPPosition + ch.getOffset()) / 1000, | |||||
"" + ch.getChar()); | |||||
currentPageG.appendChild(text); | |||||
super.renderCharacter(ch); | |||||
} | } | ||||
} | } | ||||
/** | /** | ||||
* Renderer that renders areas to XML for debugging purposes. | * Renderer that renders areas to XML for debugging purposes. | ||||
* This creates an xml that contains the information of the area | |||||
* tree. It does not output any state or derived information. | |||||
* The output can be used to build a new area tree (@see AreaTreeBuilder) | |||||
* which can be rendered to any renderer. | |||||
*/ | */ | ||||
public class XMLRenderer extends AbstractRenderer { | public class XMLRenderer extends AbstractRenderer { | ||||
public static final String mimeType = "text/xml"; | public static final String mimeType = "text/xml"; | ||||
style = "ridge"; | style = "ridge"; | ||||
break; | break; | ||||
} | } | ||||
writeElement("<leader ruleStyle=\"" + style + | |||||
writeElement("<leader width=\"" + area.getWidth() + "\" ruleStyle=\"" + style + | |||||
"\" ruleThickness=\"" + area.getRuleThickness() + "\"/>"); | "\" ruleThickness=\"" + area.getRuleThickness() + "\"/>"); | ||||
super.renderLeader(area); | super.renderLeader(area); | ||||
} | } |
import org.apache.fop.apps.Driver; | import org.apache.fop.apps.Driver; | ||||
import org.apache.batik.util.XMLResourceDescriptor; | import org.apache.batik.util.XMLResourceDescriptor; | ||||
import org.apache.batik.dom.svg.SVGDOMImplementation; | |||||
public class SVGElementMapping implements ElementMapping { | public class SVGElementMapping implements ElementMapping { | ||||
private static HashMap foObjs = null; | |||||
public synchronized void addToBuilder(TreeBuilder builder) { | |||||
private static HashMap foObjs = null; | |||||
if(foObjs == null) { | |||||
// this sets the parser that will be used | |||||
// by default (SVGBrokenLinkProvider) | |||||
// normally the user agent value is used | |||||
XMLResourceDescriptor.setXMLParserClassName(Driver.getParserClassName()); | |||||
foObjs = new HashMap(); | |||||
foObjs.put("svg", SVGElement.maker()); | |||||
foObjs.put("rect", SVGObj.maker("rect")); | |||||
foObjs.put("line", SVGObj.maker("line")); | |||||
foObjs.put("text", SVGObj.maker("text")); | |||||
foObjs.put("desc", SVGObj.maker("desc")); | |||||
foObjs.put("title", SVGObj.maker("title")); | |||||
foObjs.put("circle", SVGObj.maker("circle")); | |||||
foObjs.put("ellipse", SVGObj.maker("ellipse")); | |||||
foObjs.put("g", SVGObj.maker("g")); | |||||
foObjs.put("polyline", SVGObj.maker("polyline")); | |||||
foObjs.put("polygon", SVGObj.maker("polygon")); | |||||
foObjs.put("defs", SVGObj.maker("defs")); | |||||
foObjs.put("path", SVGObj.maker("path")); | |||||
foObjs.put("use", SVGObj.maker("use")); | |||||
foObjs.put("tspan", SVGObj.maker("tspan")); | |||||
foObjs.put("tref", SVGObj.maker("tref")); | |||||
foObjs.put("image", SVGObj.maker("image")); | |||||
foObjs.put("style", SVGObj.maker("style")); | |||||
foObjs.put("textPath", SVGObj.maker("textPath")); | |||||
foObjs.put("clipPath", SVGObj.maker("clipPath")); | |||||
foObjs.put("mask", SVGObj.maker("mask")); | |||||
foObjs.put("linearGradient", SVGObj.maker("linearGradient")); | |||||
foObjs.put("radialGradient", SVGObj.maker("radialGradient")); | |||||
foObjs.put("stop", SVGObj.maker("stop")); | |||||
foObjs.put("a", SVGObj.maker("a")); | |||||
foObjs.put("switch", SVGObj.maker("switch")); | |||||
foObjs.put("symbol", SVGObj.maker("symbol")); | |||||
foObjs.put("pattern", SVGObj.maker("pattern")); | |||||
foObjs.put("marker", SVGObj.maker("marker")); | |||||
foObjs.put("animate", SVGObj.maker("animate")); | |||||
foObjs.put("altGlyph", SVGObj.maker("altGlyph")); | |||||
foObjs.put("font", SVGObj.maker("font")); | |||||
foObjs.put("glyph", SVGObj.maker("glyph")); | |||||
foObjs.put("missing-glyph", SVGObj.maker("missing-glyph")); | |||||
foObjs.put("hkern", SVGObj.maker("hkern")); | |||||
foObjs.put("vkern", SVGObj.maker("vkern")); | |||||
foObjs.put("set", SVGObj.maker("set")); | |||||
foObjs.put("animateMotion", SVGObj.maker("animateMotion")); | |||||
foObjs.put("animateColor", SVGObj.maker("animateColor")); | |||||
foObjs.put("animateTransform", SVGObj.maker("animateTransform")); | |||||
foObjs.put("cursor", SVGObj.maker("cursor")); | |||||
foObjs.put("filter", SVGObj.maker("filter")); | |||||
foObjs.put("feFlood", SVGObj.maker("feFlood")); | |||||
foObjs.put("feGaussianBlur", SVGObj.maker("feGaussianBlur")); | |||||
foObjs.put("feOffset", SVGObj.maker("feOffset")); | |||||
foObjs.put("feMerge", SVGObj.maker("feMerge")); | |||||
foObjs.put("feMergeNode", SVGObj.maker("feMergeNode")); | |||||
public synchronized void addToBuilder(TreeBuilder builder) { | |||||
try { | |||||
if (foObjs == null) { | |||||
// this sets the parser that will be used | |||||
// by default (SVGBrokenLinkProvider) | |||||
// normally the user agent value is used | |||||
XMLResourceDescriptor.setXMLParserClassName( | |||||
Driver.getParserClassName()); | |||||
foObjs = new HashMap(); | |||||
foObjs.put("svg", SVGElement.maker()); | |||||
foObjs.put("rect", SVGObj.maker("rect")); | |||||
foObjs.put("line", SVGObj.maker("line")); | |||||
foObjs.put("text", SVGObj.maker("text")); | |||||
foObjs.put("desc", SVGObj.maker("desc")); | |||||
foObjs.put("title", SVGObj.maker("title")); | |||||
foObjs.put("circle", SVGObj.maker("circle")); | |||||
foObjs.put("ellipse", SVGObj.maker("ellipse")); | |||||
foObjs.put("g", SVGObj.maker("g")); | |||||
foObjs.put("polyline", SVGObj.maker("polyline")); | |||||
foObjs.put("polygon", SVGObj.maker("polygon")); | |||||
foObjs.put("defs", SVGObj.maker("defs")); | |||||
foObjs.put("path", SVGObj.maker("path")); | |||||
foObjs.put("use", SVGObj.maker("use")); | |||||
foObjs.put("tspan", SVGObj.maker("tspan")); | |||||
foObjs.put("tref", SVGObj.maker("tref")); | |||||
foObjs.put("image", SVGObj.maker("image")); | |||||
foObjs.put("style", SVGObj.maker("style")); | |||||
foObjs.put("textPath", SVGObj.maker("textPath")); | |||||
foObjs.put("clipPath", SVGObj.maker("clipPath")); | |||||
foObjs.put("mask", SVGObj.maker("mask")); | |||||
foObjs.put("linearGradient", SVGObj.maker("linearGradient")); | |||||
foObjs.put("radialGradient", SVGObj.maker("radialGradient")); | |||||
foObjs.put("stop", SVGObj.maker("stop")); | |||||
foObjs.put("a", SVGObj.maker("a")); | |||||
foObjs.put("switch", SVGObj.maker("switch")); | |||||
foObjs.put("symbol", SVGObj.maker("symbol")); | |||||
foObjs.put("pattern", SVGObj.maker("pattern")); | |||||
foObjs.put("marker", SVGObj.maker("marker")); | |||||
foObjs.put("animate", SVGObj.maker("animate")); | |||||
foObjs.put("altGlyph", SVGObj.maker("altGlyph")); | |||||
foObjs.put("font", SVGObj.maker("font")); | |||||
foObjs.put("glyph", SVGObj.maker("glyph")); | |||||
foObjs.put("missing-glyph", SVGObj.maker("missing-glyph")); | |||||
foObjs.put("hkern", SVGObj.maker("hkern")); | |||||
foObjs.put("vkern", SVGObj.maker("vkern")); | |||||
foObjs.put("set", SVGObj.maker("set")); | |||||
foObjs.put("animateMotion", SVGObj.maker("animateMotion")); | |||||
foObjs.put("animateColor", SVGObj.maker("animateColor")); | |||||
foObjs.put("animateTransform", SVGObj.maker("animateTransform")); | |||||
foObjs.put("cursor", SVGObj.maker("cursor")); | |||||
foObjs.put("filter", SVGObj.maker("filter")); | |||||
foObjs.put("feFlood", SVGObj.maker("feFlood")); | |||||
foObjs.put("feGaussianBlur", SVGObj.maker("feGaussianBlur")); | |||||
foObjs.put("feOffset", SVGObj.maker("feOffset")); | |||||
foObjs.put("feMerge", SVGObj.maker("feMerge")); | |||||
foObjs.put("feMergeNode", SVGObj.maker("feMergeNode")); | |||||
} | |||||
String svgNS = SVGDOMImplementation.SVG_NAMESPACE_URI; | |||||
builder.addMapping(svgNS, foObjs); | |||||
builder.addPropertyListBuilder(svgNS, | |||||
new DirectPropertyListBuilder()); | |||||
} catch (Throwable t) { | |||||
// if the classes are not available | |||||
} | } | ||||
String uri = "http://www.w3.org/2000/svg"; | |||||
builder.addMapping(uri, foObjs); | |||||
builder.addPropertyListBuilder(uri, new DirectPropertyListBuilder()); | |||||
} | } | ||||
} | } |
import org.apache.fop.render.svg.*; | import org.apache.fop.render.svg.*; | ||||
import org.apache.fop.render.xml.*; | import org.apache.fop.render.xml.*; | ||||
import org.apache.fop.layout.FontInfo; | import org.apache.fop.layout.FontInfo; | ||||
import org.apache.fop.layout.FontState; | |||||
import org.apache.fop.fo.FOUserAgent; | import org.apache.fop.fo.FOUserAgent; | ||||
import org.apache.log.*; | import org.apache.log.*; | ||||
import java.awt.geom.Rectangle2D; | import java.awt.geom.Rectangle2D; | ||||
import java.util.StringTokenizer; | import java.util.StringTokenizer; | ||||
import javax.xml.parsers.DocumentBuilderFactory; | |||||
import org.w3c.dom.*; | import org.w3c.dom.*; | ||||
import org.apache.batik.dom.svg.SVGDOMImplementation; | import org.apache.batik.dom.svg.SVGDOMImplementation; | ||||
* for the purpose of testing the area tree and rendering. | * for the purpose of testing the area tree and rendering. | ||||
* This covers the set of possible properties that can be set | * This covers the set of possible properties that can be set | ||||
* on the area tree for rendering. | * on the area tree for rendering. | ||||
* As this is not for general purpose there is no attempt to handle | |||||
* invalid area tree xml. | |||||
* | |||||
* Tests: different renderers, saving and loading pages with serialization | * Tests: different renderers, saving and loading pages with serialization | ||||
* out of order rendering | * out of order rendering | ||||
*/ | */ | ||||
public class AreaTreeBuilder { | public class AreaTreeBuilder { | ||||
private Logger log; | private Logger log; | ||||
//String baseName = "temp"; | |||||
/** | /** | ||||
*/ | */ | ||||
while (c < pagec) { | while (c < pagec) { | ||||
PageViewport page = sm.getPage(count, c); | PageViewport page = sm.getPage(count, c); | ||||
c++; | c++; | ||||
// save the page to a stream for testing | |||||
ObjectOutputStream tempstream = new ObjectOutputStream( | ObjectOutputStream tempstream = new ObjectOutputStream( | ||||
new BufferedOutputStream( | new BufferedOutputStream( | ||||
new FileOutputStream("temp.ser"))); | new FileOutputStream("temp.ser"))); | ||||
new FileInputStream("temp.ser"))); | new FileInputStream("temp.ser"))); | ||||
page.loadPage(in); | page.loadPage(in); | ||||
in.close(); | in.close(); | ||||
rend.renderPage(page); | rend.renderPage(page); | ||||
} | } | ||||
count++; | count++; | ||||
AreaTree areaTree; | AreaTree areaTree; | ||||
AreaTree.AreaTreeModel model; | AreaTree.AreaTreeModel model; | ||||
FontInfo fontInfo; | FontInfo fontInfo; | ||||
FontState currentFontState; | |||||
TreeLoader(FontInfo fi) { | TreeLoader(FontInfo fi) { | ||||
fontInfo = fi; | fontInfo = fi; | ||||
public void buildAreaTree(InputStream is) { | public void buildAreaTree(InputStream is) { | ||||
Document doc = null; | Document doc = null; | ||||
try { | try { | ||||
doc = javax.xml.parsers.DocumentBuilderFactory.newInstance(). | |||||
newDocumentBuilder().parse(is); | |||||
DocumentBuilderFactory fact = | |||||
DocumentBuilderFactory.newInstance(); | |||||
fact.setNamespaceAware(true); | |||||
doc = fact.newDocumentBuilder().parse(is); | |||||
} catch (Exception e) { | } catch (Exception e) { | ||||
e.printStackTrace(); | e.printStackTrace(); | ||||
} | } | ||||
Character ch = | Character ch = | ||||
new Character(getString((Element) obj).charAt(0)); | new Character(getString((Element) obj).charAt(0)); | ||||
addProperties((Element) obj, ch); | addProperties((Element) obj, ch); | ||||
try { | |||||
currentFontState = | |||||
new FontState(fontInfo, "sans-serif", "normal", | |||||
"normal", 12000, 0); | |||||
} catch (FOPException e) { | |||||
} | |||||
ch.setWidth(currentFontState.width(ch.getChar())); | |||||
ch.setOffset(currentFontState.getCapHeight()); | |||||
list.add(ch); | list.add(ch); | ||||
} else if (obj.getNodeName().equals("space")) { | } else if (obj.getNodeName().equals("space")) { | ||||
Space space = new Space(); | Space space = new Space(); | ||||
return null; | return null; | ||||
} | } | ||||
Viewport viewport = new Viewport(child); | Viewport viewport = new Viewport(child); | ||||
String str = root.getAttribute("width"); | |||||
if (str != null && !"".equals(str)) { | |||||
int width = Integer.parseInt(str); | |||||
viewport.setWidth(width); | |||||
} | |||||
return viewport; | return viewport; | ||||
} | } | ||||
//System.out.println(obj.getNodeName()); | //System.out.println(obj.getNodeName()); | ||||
Element rootEle = (Element) obj; | Element rootEle = (Element) obj; | ||||
String space = rootEle.getAttribute("xmlns"); | String space = rootEle.getAttribute("xmlns"); | ||||
if (space.equals(svgNS)) { | |||||
if (svgNS.equals(space)) { | |||||
try { | try { | ||||
doc = javax.xml.parsers.DocumentBuilderFactory.newInstance(). | |||||
newDocumentBuilder().newDocument(); | |||||
DocumentBuilderFactory fact = | |||||
DocumentBuilderFactory.newInstance(); | |||||
fact.setNamespaceAware(true); | |||||
doc = fact. newDocumentBuilder().newDocument(); | |||||
Node node = doc.importNode(obj, true); | Node node = doc.importNode(obj, true); | ||||
doc.appendChild(node); | doc.appendChild(node); | ||||
DOMImplementation impl = | DOMImplementation impl = | ||||
SVGDOMImplementation.getDOMImplementation(); | SVGDOMImplementation.getDOMImplementation(); | ||||
// due to namespace problem attributes are not cloned | // due to namespace problem attributes are not cloned | ||||
// serializing causes an npe | |||||
//doc = DOMUtilities.deepCloneDocument(doc, impl); | //doc = DOMUtilities.deepCloneDocument(doc, impl); | ||||
ForeignObject fo = new ForeignObject(doc, svgNS); | ForeignObject fo = new ForeignObject(doc, svgNS); | ||||
} | } | ||||
} else { | } else { | ||||
try { | try { | ||||
doc = javax.xml.parsers.DocumentBuilderFactory.newInstance(). | |||||
newDocumentBuilder().newDocument(); | |||||
DocumentBuilderFactory fact = | |||||
DocumentBuilderFactory.newInstance(); | |||||
fact.setNamespaceAware(true); | |||||
doc = fact. newDocumentBuilder().newDocument(); | |||||
Node node = doc.importNode(obj, true); | Node node = doc.importNode(obj, true); | ||||
doc.appendChild(node); | doc.appendChild(node); | ||||
ForeignObject fo = new ForeignObject(doc, space); | ForeignObject fo = new ForeignObject(doc, space); | ||||
String rt = root.getAttribute("ruleThickness"); | String rt = root.getAttribute("ruleThickness"); | ||||
int thick = Integer.parseInt(rt); | int thick = Integer.parseInt(rt); | ||||
leader.setRuleThickness(thick); | leader.setRuleThickness(thick); | ||||
rt = root.getAttribute("width"); | |||||
if (rt != null && !"".equals(rt)) { | |||||
thick = Integer.parseInt(rt); | |||||
leader.setWidth(thick); | |||||
} | |||||
leader.setOffset(currentFontState.getCapHeight()); | |||||
addProperties(root, leader); | addProperties(root, leader); | ||||
return leader; | return leader; | ||||
} | } | ||||
Word getWord(Element root) { | Word getWord(Element root) { | ||||
String url = root.getAttribute("url"); | |||||
String str = getString(root); | |||||
Word word = new Word(); | Word word = new Word(); | ||||
word.setWord(str); | |||||
addProperties(root, word); | addProperties(root, word); | ||||
int width = 0; | |||||
for (int count = 0; count < str.length(); count++) { | |||||
width += currentFontState.width(str.charAt(count)); | |||||
} | |||||
word.setWidth(width); | |||||
word.setOffset(currentFontState.getCapHeight()); | |||||
return word; | return word; | ||||
} | } | ||||