Browse Source

svg renderer now basically works, pages, text, leader, svg

some other misc updates to areas


git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@194534 13f79535-47bb-0310-9956-ffa450edef68
pull/30/head
Keiron Liddle 22 years ago
parent
commit
9590d98f56

+ 4
- 0
src/org/apache/fop/apps/Driver.java View File

@@ -566,6 +566,10 @@ class Service {

public static synchronized Enumeration providers(Class cls) {
ClassLoader cl = cls.getClassLoader();
// null if loaded by bootstrap class loader
if(cl == null) {
cl = ClassLoader.getSystemClassLoader();
}
String serviceFile = "META-INF/services/" + cls.getName();

// System.out.println("File: " + serviceFile);

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

@@ -7,11 +7,12 @@

package org.apache.fop.area;

import java.io.Serializable;
import java.util.List;
import java.util.ArrayList;

// may combine with before float into a conditional area
public class Footnote {
public class Footnote implements Serializable {
Block separator = null;

// footnote has an optional separator

+ 10
- 0
src/org/apache/fop/area/Property.java View File

@@ -7,6 +7,8 @@

package org.apache.fop.area;

import org.apache.fop.datatypes.ColorType;

import java.io.Serializable;

// properties should be serialized by the holder
@@ -26,8 +28,16 @@ public class Property implements Serializable {
public static final int LINETHROUGH = 12;
public static final int OFFSET = 13;
public static final int SHADOW = 14;

public int propType;
public Object data;

public static class Background {
ColorType color;
String url;
int repeat;
int horiz;
int vertical;
}
}


+ 8
- 1
src/org/apache/fop/area/inline/Container.java View File

@@ -14,10 +14,13 @@ import org.apache.fop.render.Renderer;
import java.util.List;
import java.util.ArrayList;

// this is an inline area that can have blocks as children
public class Container extends Area {
ArrayList blocks = new ArrayList();
int width;

// this is an inline area that can have blocks as children
public Container() {
}

public void render(Renderer renderer) {
renderer.renderContainer(this);
@@ -31,4 +34,8 @@ public class Container extends Area {
return blocks;
}

public int getWidth() {
return width;
}

}

+ 8
- 0
src/org/apache/fop/area/inline/InlineArea.java View File

@@ -45,6 +45,14 @@ public class InlineArea extends Area {
return width;
}

public void setOffset(int v) {
verticalPosition = v;
}

public int getOffset() {
return verticalPosition;
}

public void addProperty(Property prop) {
if (props == null) {
props = new ArrayList();

+ 8
- 0
src/org/apache/fop/area/inline/Word.java View File

@@ -17,4 +17,12 @@ public class Word extends InlineArea {
public void render(Renderer renderer) {
renderer.renderWord(this);
}

public void setWord(String w) {
word = w;
}

public String getWord() {
return word;
}
}

+ 0
- 2
src/org/apache/fop/datatypes/IDReferences.java View File

@@ -91,7 +91,6 @@ public class IDReferences {
* Creates id entry that hasn't been validated
*
* @param id The id to create
* @exception FOPException
*/
public void createUnvalidatedID(String id) {
if (id != null &&!id.equals("")) {
@@ -178,7 +177,6 @@ public class IDReferences {
* Removes id from IDReferences
*
* @param id The id to remove
* @exception FOPException
*/
public void removeID(String id) {
idReferences.remove(id);

+ 3
- 16
src/org/apache/fop/fo/FOTreeBuilder.java View File

@@ -27,7 +27,7 @@ import org.xml.sax.Attributes;
// Java
import java.util.HashMap;
import java.util.Stack;
import java.util.Vector;
import java.util.ArrayList;
import java.io.IOException;

/**
@@ -49,7 +49,7 @@ public class FOTreeBuilder extends DefaultHandler implements TreeBuilder {
*/
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
@@ -101,7 +101,7 @@ public class FOTreeBuilder extends DefaultHandler implements TreeBuilder {
*/
public void addMapping(String namespaceURI, HashMap table) {
this.fobjTable.put(namespaceURI, table);
this.namespaces.addElement(namespaceURI.intern());
this.namespaces.add(namespaceURI.intern());
}

/**
@@ -212,8 +212,6 @@ public class FOTreeBuilder extends DefaultHandler implements TreeBuilder {
/* the maker for the formatting object started */
FObj.Maker fobjMaker = null;

// String fullName = mapName(rawName);
//String fullName = uri + "^" + localName;
HashMap table = (HashMap)fobjTable.get(uri);
if(table != null) {
fobjMaker = (FObj.Maker)table.get(localName);
@@ -275,17 +273,6 @@ public class FOTreeBuilder extends DefaultHandler implements TreeBuilder {
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() {
currentFObj = null;
rootFObj = null;

+ 1
- 1
src/org/apache/fop/fo/FOUserAgent.java View File

@@ -73,7 +73,7 @@ public class FOUserAgent {
handler.handleXML(ctx, doc, namespace);
} catch (Throwable t) {
// could not handle document
//t.printStackTrace();
t.printStackTrace();
}
} else {
// no handler found for document

+ 3
- 3
src/org/apache/fop/fo/pagination/PageSequence.java View File

@@ -28,10 +28,10 @@ import org.apache.fop.apps.FOPException;
// Java
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 {
//

+ 0
- 4
src/org/apache/fop/messaging/DefaultMessageListener.java View File

@@ -7,14 +7,10 @@

package org.apache.fop.messaging;


/**
* A trivial implementation of a MessageListener
* For further explanation
* @see MessageListener
*/


public class DefaultMessageListener implements MessageListener {

/**

+ 0
- 3
src/org/apache/fop/messaging/MessageEvent.java View File

@@ -13,10 +13,7 @@ import java.util.EventObject;
* a container for the text and the type of a message
* MessageEvents are created by MessageHandler and can be received by any
* MessageListener, which is added to MessageHandler;
* @see org.apache.fop.MessageListener MessageListener
*
*/

public class MessageEvent extends EventObject {
public static final int LOG = 0;
public static final int ERROR = 1;

+ 42
- 1
src/org/apache/fop/render/AbstractRenderer.java View File

@@ -13,12 +13,14 @@ import org.apache.fop.apps.FOPException;
import org.apache.fop.area.*;
import org.apache.fop.area.Span;
import org.apache.fop.area.inline.*;
import org.apache.fop.area.inline.Character;
import org.apache.fop.area.inline.Space;
import org.apache.fop.fo.FOUserAgent;

import org.apache.log.Logger;

// Java
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
@@ -56,6 +58,29 @@ public abstract class AbstractRenderer implements Renderer {
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) {
}

@@ -87,6 +112,11 @@ public abstract class AbstractRenderer implements Renderer {
// a position from where the region is placed
protected void renderRegionViewport(RegionViewport port) {
if (port != null) {
Rectangle2D view = port.getViewArea();
currentBPPosition = (int) view.getY();
currentIPPosition = (int) view.getX();
currentBlockIPPosition = currentIPPosition;

Region region = port.getRegion();
if (region.getRegionClass() == Region.BODY) {
renderBodyRegion((BodyRegion) region);
@@ -185,7 +215,9 @@ public abstract class AbstractRenderer implements Renderer {
// of the line, each inline object is offset from there
for (int count = 0; count < children.size(); count++) {
LineArea line = (LineArea) children.get(count);
currentBlockIPPosition = currentIPPosition;
renderLineArea(line);
currentBPPosition += line.getHeight();
}

}
@@ -213,21 +245,30 @@ public abstract class AbstractRenderer implements Renderer {
} else if (content instanceof ForeignObject) {
renderForeignObject((ForeignObject) content);
}
currentBlockIPPosition += viewport.getWidth();
}

public void renderImage(Image image) {
}

public void renderContainer(Container cont) {
int saveIP = currentIPPosition;
currentIPPosition = currentBlockIPPosition;
int saveBlockIP = currentBlockIPPosition;
int saveBP = currentBPPosition;

List blocks = cont.getBlocks();
renderBlocks(blocks);
currentIPPosition = saveIP;
currentBlockIPPosition = saveBlockIP;
currentBPPosition = saveBP;
}

public void renderForeignObject(ForeignObject fo) {

}

public void renderCharacter(org.apache.fop.area.inline.Character ch) {
public void renderCharacter(Character ch) {
currentBlockIPPosition += ch.getWidth();
}


+ 277
- 14
src/org/apache/fop/render/svg/SVGRenderer.java View File

@@ -7,13 +7,16 @@

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.ColorType;
import org.apache.fop.image.*;
import org.apache.fop.svg.SVGArea;
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.ProcessingInstruction;
@@ -22,6 +25,7 @@ import org.w3c.dom.svg.SVGDocument;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Text;

import org.apache.batik.dom.svg.SVGDOMImplementation;
import org.apache.batik.dom.svg.SVGOMElement;
@@ -30,12 +34,13 @@ import org.apache.batik.transcoder.svg2svg.SVGTranscoder;
import org.apache.batik.transcoder.TranscoderInput;
import org.apache.batik.transcoder.TranscoderOutput;
import org.apache.batik.transcoder.TranscoderException;
import org.apache.batik.dom.util.DOMUtilities;

import java.awt.Color;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.geom.Rectangle2D;
import java.util.Hashtable;
import java.util.HashMap;
import java.net.URL;
import java.net.MalformedURLException;
import java.io.OutputStream;
@@ -44,23 +49,40 @@ import java.io.OutputStreamWriter;
import javax.swing.ImageIcon;

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;
Document svgDocument;
Element svgRoot;
Element currentPageG = 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 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 Hashtable fontNames = new Hashtable();
protected Hashtable fontStyles = new Hashtable();
protected HashMap fontNames = new HashMap();
protected HashMap fontStyles = new HashMap();
protected Color saveColor = null;

protected IDReferences idReferences = null;
@@ -83,26 +105,267 @@ public class SVGRenderer extends AbstractRenderer {
protected float currentBlue = 0;

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) {
// create a temp Image to test font metrics on
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 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);
}
}


+ 5
- 1
src/org/apache/fop/render/xml/XMLRenderer.java View File

@@ -37,6 +37,10 @@ import org.w3c.dom.Document;

/**
* 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 static final String mimeType = "text/xml";
@@ -353,7 +357,7 @@ public class XMLRenderer extends AbstractRenderer {
style = "ridge";
break;
}
writeElement("<leader ruleStyle=\"" + style +
writeElement("<leader width=\"" + area.getWidth() + "\" ruleStyle=\"" + style +
"\" ruleThickness=\"" + area.getRuleThickness() + "\"/>");
super.renderLeader(area);
}

+ 73
- 67
src/org/apache/fop/svg/SVGElementMapping.java View File

@@ -17,78 +17,84 @@ import org.apache.fop.fo.ElementMapping;
import org.apache.fop.apps.Driver;

import org.apache.batik.util.XMLResourceDescriptor;
import org.apache.batik.dom.svg.SVGDOMImplementation;

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

}

+ 54
- 9
src/org/apache/fop/tools/AreaTreeBuilder.java View File

@@ -17,6 +17,7 @@ import org.apache.fop.render.pdf.*;
import org.apache.fop.render.svg.*;
import org.apache.fop.render.xml.*;
import org.apache.fop.layout.FontInfo;
import org.apache.fop.layout.FontState;
import org.apache.fop.fo.FOUserAgent;

import org.apache.log.*;
@@ -30,6 +31,8 @@ import java.util.*;
import java.awt.geom.Rectangle2D;
import java.util.StringTokenizer;

import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.*;

import org.apache.batik.dom.svg.SVGDOMImplementation;
@@ -41,12 +44,14 @@ import org.apache.batik.dom.util.DOMUtilities;
* for the purpose of testing the area tree and rendering.
* This covers the set of possible properties that can be set
* 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
* out of order rendering
*/
public class AreaTreeBuilder {
private Logger log;
//String baseName = "temp";

/**
*/
@@ -129,6 +134,7 @@ public class AreaTreeBuilder {
while (c < pagec) {
PageViewport page = sm.getPage(count, c);
c++;
// save the page to a stream for testing
ObjectOutputStream tempstream = new ObjectOutputStream(
new BufferedOutputStream(
new FileOutputStream("temp.ser")));
@@ -142,6 +148,7 @@ public class AreaTreeBuilder {
new FileInputStream("temp.ser")));
page.loadPage(in);
in.close();

rend.renderPage(page);
}
count++;
@@ -163,6 +170,7 @@ class TreeLoader {
AreaTree areaTree;
AreaTree.AreaTreeModel model;
FontInfo fontInfo;
FontState currentFontState;

TreeLoader(FontInfo fi) {
fontInfo = fi;
@@ -175,8 +183,10 @@ class TreeLoader {
public void buildAreaTree(InputStream is) {
Document doc = null;
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) {
e.printStackTrace();
}
@@ -475,6 +485,16 @@ class TreeLoader {
Character ch =
new Character(getString((Element) obj).charAt(0));
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);
} else if (obj.getNodeName().equals("space")) {
Space space = new Space();
@@ -520,6 +540,11 @@ class TreeLoader {
return null;
}
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;
}

@@ -544,15 +569,19 @@ class TreeLoader {
//System.out.println(obj.getNodeName());
Element rootEle = (Element) obj;
String space = rootEle.getAttribute("xmlns");
if (space.equals(svgNS)) {
if (svgNS.equals(space)) {
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);
doc.appendChild(node);
DOMImplementation impl =
SVGDOMImplementation.getDOMImplementation();
// due to namespace problem attributes are not cloned
// serializing causes an npe
//doc = DOMUtilities.deepCloneDocument(doc, impl);

ForeignObject fo = new ForeignObject(doc, svgNS);
@@ -562,8 +591,10 @@ class TreeLoader {
}
} else {
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);
doc.appendChild(node);
ForeignObject fo = new ForeignObject(doc, space);
@@ -602,14 +633,28 @@ class TreeLoader {
String rt = root.getAttribute("ruleThickness");
int thick = Integer.parseInt(rt);
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);
return leader;
}

Word getWord(Element root) {
String url = root.getAttribute("url");
String str = getString(root);
Word word = new Word();
word.setWord(str);
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;
}


Loading…
Cancel
Save