aboutsummaryrefslogtreecommitdiffstats
path: root/src/org
diff options
context:
space:
mode:
Diffstat (limited to 'src/org')
-rw-r--r--src/org/apache/fop/apps/Driver.java4
-rw-r--r--src/org/apache/fop/area/Footnote.java3
-rw-r--r--src/org/apache/fop/area/Property.java10
-rw-r--r--src/org/apache/fop/area/inline/Container.java9
-rw-r--r--src/org/apache/fop/area/inline/InlineArea.java8
-rw-r--r--src/org/apache/fop/area/inline/Word.java8
-rw-r--r--src/org/apache/fop/datatypes/IDReferences.java2
-rw-r--r--src/org/apache/fop/fo/FOTreeBuilder.java19
-rw-r--r--src/org/apache/fop/fo/FOUserAgent.java2
-rw-r--r--src/org/apache/fop/fo/pagination/PageSequence.java6
-rw-r--r--src/org/apache/fop/messaging/DefaultMessageListener.java4
-rw-r--r--src/org/apache/fop/messaging/MessageEvent.java3
-rw-r--r--src/org/apache/fop/render/AbstractRenderer.java43
-rw-r--r--src/org/apache/fop/render/svg/SVGRenderer.java291
-rw-r--r--src/org/apache/fop/render/xml/XMLRenderer.java6
-rw-r--r--src/org/apache/fop/svg/SVGElementMapping.java140
-rw-r--r--src/org/apache/fop/tools/AreaTreeBuilder.java63
17 files changed, 498 insertions, 123 deletions
diff --git a/src/org/apache/fop/apps/Driver.java b/src/org/apache/fop/apps/Driver.java
index e885fafb5..7cb5579c5 100644
--- a/src/org/apache/fop/apps/Driver.java
+++ b/src/org/apache/fop/apps/Driver.java
@@ -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);
diff --git a/src/org/apache/fop/area/Footnote.java b/src/org/apache/fop/area/Footnote.java
index dcd62ecdf..d36a769bc 100644
--- a/src/org/apache/fop/area/Footnote.java
+++ b/src/org/apache/fop/area/Footnote.java
@@ -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
diff --git a/src/org/apache/fop/area/Property.java b/src/org/apache/fop/area/Property.java
index 3b9a836e0..4c6d5914c 100644
--- a/src/org/apache/fop/area/Property.java
+++ b/src/org/apache/fop/area/Property.java
@@ -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;
+ }
}
diff --git a/src/org/apache/fop/area/inline/Container.java b/src/org/apache/fop/area/inline/Container.java
index 76c987e21..daf347fff 100644
--- a/src/org/apache/fop/area/inline/Container.java
+++ b/src/org/apache/fop/area/inline/Container.java
@@ -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;
+ }
+
}
diff --git a/src/org/apache/fop/area/inline/InlineArea.java b/src/org/apache/fop/area/inline/InlineArea.java
index aa229316f..d688ae038 100644
--- a/src/org/apache/fop/area/inline/InlineArea.java
+++ b/src/org/apache/fop/area/inline/InlineArea.java
@@ -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();
diff --git a/src/org/apache/fop/area/inline/Word.java b/src/org/apache/fop/area/inline/Word.java
index 070af40ff..51b009b28 100644
--- a/src/org/apache/fop/area/inline/Word.java
+++ b/src/org/apache/fop/area/inline/Word.java
@@ -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;
+ }
}
diff --git a/src/org/apache/fop/datatypes/IDReferences.java b/src/org/apache/fop/datatypes/IDReferences.java
index 3701c6662..8f157cc81 100644
--- a/src/org/apache/fop/datatypes/IDReferences.java
+++ b/src/org/apache/fop/datatypes/IDReferences.java
@@ -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);
diff --git a/src/org/apache/fop/fo/FOTreeBuilder.java b/src/org/apache/fop/fo/FOTreeBuilder.java
index 4e4cefafe..e4ac25758 100644
--- a/src/org/apache/fop/fo/FOTreeBuilder.java
+++ b/src/org/apache/fop/fo/FOTreeBuilder.java
@@ -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;
diff --git a/src/org/apache/fop/fo/FOUserAgent.java b/src/org/apache/fop/fo/FOUserAgent.java
index 05ae93456..d89f308e4 100644
--- a/src/org/apache/fop/fo/FOUserAgent.java
+++ b/src/org/apache/fop/fo/FOUserAgent.java
@@ -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
diff --git a/src/org/apache/fop/fo/pagination/PageSequence.java b/src/org/apache/fop/fo/pagination/PageSequence.java
index 290f19454..5b957d8a8 100644
--- a/src/org/apache/fop/fo/pagination/PageSequence.java
+++ b/src/org/apache/fop/fo/pagination/PageSequence.java
@@ -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 {
//
diff --git a/src/org/apache/fop/messaging/DefaultMessageListener.java b/src/org/apache/fop/messaging/DefaultMessageListener.java
index 55e6e70f4..081bd6032 100644
--- a/src/org/apache/fop/messaging/DefaultMessageListener.java
+++ b/src/org/apache/fop/messaging/DefaultMessageListener.java
@@ -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 {
/**
diff --git a/src/org/apache/fop/messaging/MessageEvent.java b/src/org/apache/fop/messaging/MessageEvent.java
index ac4c6f683..92a742aaa 100644
--- a/src/org/apache/fop/messaging/MessageEvent.java
+++ b/src/org/apache/fop/messaging/MessageEvent.java
@@ -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;
diff --git a/src/org/apache/fop/render/AbstractRenderer.java b/src/org/apache/fop/render/AbstractRenderer.java
index a76a32f5e..d2bebb77c 100644
--- a/src/org/apache/fop/render/AbstractRenderer.java
+++ b/src/org/apache/fop/render/AbstractRenderer.java
@@ -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();
}
diff --git a/src/org/apache/fop/render/svg/SVGRenderer.java b/src/org/apache/fop/render/svg/SVGRenderer.java
index 46458f420..b47a832fd 100644
--- a/src/org/apache/fop/render/svg/SVGRenderer.java
+++ b/src/org/apache/fop/render/svg/SVGRenderer.java
@@ -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);
}
}
+
diff --git a/src/org/apache/fop/render/xml/XMLRenderer.java b/src/org/apache/fop/render/xml/XMLRenderer.java
index 33fa2ed9a..e0a35fd36 100644
--- a/src/org/apache/fop/render/xml/XMLRenderer.java
+++ b/src/org/apache/fop/render/xml/XMLRenderer.java
@@ -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);
}
diff --git a/src/org/apache/fop/svg/SVGElementMapping.java b/src/org/apache/fop/svg/SVGElementMapping.java
index 012cd9b89..dc7df3dfb 100644
--- a/src/org/apache/fop/svg/SVGElementMapping.java
+++ b/src/org/apache/fop/svg/SVGElementMapping.java
@@ -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());
}
}
diff --git a/src/org/apache/fop/tools/AreaTreeBuilder.java b/src/org/apache/fop/tools/AreaTreeBuilder.java
index e77713da8..63fac5c91 100644
--- a/src/org/apache/fop/tools/AreaTreeBuilder.java
+++ b/src/org/apache/fop/tools/AreaTreeBuilder.java
@@ -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;
}