summaryrefslogtreecommitdiffstats
path: root/fop-sandbox
diff options
context:
space:
mode:
authorGlenn Adams <gadams@apache.org>2016-03-12 05:39:53 +0000
committerGlenn Adams <gadams@apache.org>2016-03-12 05:39:53 +0000
commit6a719897d6f98ba89aa08e2f97b2b801be066cbf (patch)
treebcce1bb7e9c6bde85e1167cff6218948f5be9f0a /fop-sandbox
parent2184238c210288138b6703bd63ccb2c8c40300f0 (diff)
downloadxmlgraphics-fop-6a719897d6f98ba89aa08e2f97b2b801be066cbf.tar.gz
xmlgraphics-fop-6a719897d6f98ba89aa08e2f97b2b801be066cbf.zip
Configure fop-{sandbox,servlet,transcoder}, checkstyle, findbugs; fixups for ant targets.
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/maven@1734671 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'fop-sandbox')
-rw-r--r--fop-sandbox/pom.xml142
-rw-r--r--fop-sandbox/src/main/java/org/apache/fop/render/mif/MIFElement.java131
-rw-r--r--fop-sandbox/src/main/java/org/apache/fop/render/mif/MIFFOEventHandlerMaker.java52
-rw-r--r--fop-sandbox/src/main/java/org/apache/fop/render/mif/MIFFile.java159
-rw-r--r--fop-sandbox/src/main/java/org/apache/fop/render/mif/MIFHandler.java388
-rw-r--r--fop-sandbox/src/main/java/org/apache/fop/render/mif/PGFElement.java53
-rw-r--r--fop-sandbox/src/main/java/org/apache/fop/render/mif/RefElement.java49
-rw-r--r--fop-sandbox/src/main/java/org/apache/fop/render/mif/RulingElement.java54
-rw-r--r--fop-sandbox/src/main/java/org/apache/fop/render/mif/package.html23
-rw-r--r--fop-sandbox/src/main/java/org/apache/fop/render/svg/AbstractSVGDocumentHandler.java121
-rw-r--r--fop-sandbox/src/main/java/org/apache/fop/render/svg/EmbeddedSVGImageHandler.java159
-rw-r--r--fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGConstants.java47
-rw-r--r--fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGDataUrlImageHandler.java106
-rw-r--r--fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGDocumentHandler.java275
-rw-r--r--fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGDocumentHandlerMaker.java48
-rw-r--r--fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGPainter.java418
-rw-r--r--fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGPrintDocumentHandler.java170
-rw-r--r--fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGPrintDocumentHandlerMaker.java48
-rw-r--r--fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGRenderer.java177
-rw-r--r--fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGRendererContextConstants.java35
-rw-r--r--fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGRendererMaker.java54
-rw-r--r--fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGRenderingContext.java59
-rw-r--r--fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGSVGHandler.java84
-rw-r--r--fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGUtil.java81
-rw-r--r--fop-sandbox/src/main/java/org/apache/fop/render/svg/package.html23
-rw-r--r--fop-sandbox/src/main/resources/META-INF/services/org.apache.fop.fo.ElementMapping0
-rw-r--r--fop-sandbox/src/main/resources/META-INF/services/org.apache.fop.fo.FOEventHandler1
-rw-r--r--fop-sandbox/src/main/resources/META-INF/services/org.apache.fop.render.ImageHandler2
-rw-r--r--fop-sandbox/src/main/resources/META-INF/services/org.apache.fop.render.XMLHandler0
-rw-r--r--fop-sandbox/src/main/resources/META-INF/services/org.apache.fop.render.intermediate.IFDocumentHandler2
30 files changed, 2961 insertions, 0 deletions
diff --git a/fop-sandbox/pom.xml b/fop-sandbox/pom.xml
new file mode 100644
index 000000000..8d44f1443
--- /dev/null
+++ b/fop-sandbox/pom.xml
@@ -0,0 +1,142 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.apache.xmlgraphics</groupId>
+ <artifactId>fop-sandbox</artifactId>
+ <name>Apache FOP Sandbox</name>
+ <description>XML Graphics Format Object Processor Sandbox</description>
+
+ <parent>
+ <groupId>org.apache.xmlgraphics</groupId>
+ <artifactId>fop-parent</artifactId>
+ <version>2.2.0-SNAPSHOT</version>
+ </parent>
+
+ <dependencies>
+ <!-- compile deps -->
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>fop-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <!-- test deps -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>${junit.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <!-- generate event collector models -->
+ <!--
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <version>${antrun.plugin.version}</version>
+ <executions>
+ <execution>
+ <id>codegen-events</id>
+ <phase>process-classes</phase>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ <configuration>
+ <target>
+ <taskdef name="collectEvents" classname="org.apache.fop.tools.EventProducerCollectorTask" classpathref="maven.compile.classpath"/>
+ <collectEvents destdir="${project.build.outputDirectory}">
+ <fileset dir="${project.basedir}/src/main/java">
+ <include name="**/accessibility/AccessibilityEventProducer.java"/>
+ </fileset>
+ </collectEvents>
+ </target>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ -->
+ <!-- junit testing -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <includes>
+ <include>**/*TestCase.java</include>
+ </includes>
+ <redirectTestOutputToFile>true</redirectTestOutputToFile>
+ </configuration>
+ </plugin>
+ <!-- jar packaging -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <configuration>
+ <archive>
+ <manifest>
+ <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+ <mainClass>org.apache.fop.cli.Main</mainClass>
+ </manifest>
+ <manifestEntries>
+ <SpecificationTitle>XSL-FO - Extensible Stylesheet Language</SpecificationTitle>
+ <SpecificationVersion>1.1</SpecificationVersion>
+ <SpecificationVendor>World Wide Web Consortium</SpecificationVendor>
+ <SpecificationURL>http://www.w3.org/TR/xsl</SpecificationURL>
+ </manifestEntries>
+ </archive>
+ </configuration>
+ </plugin>
+ <!-- code analysis - checkstyle -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ <version>${checkstyle.plugin.version}</version>
+ <configuration>
+ <configLocation>${project.baseUri}../fop-core/src/tools/resources/checkstyle/checkstyle.xml</configLocation>
+ <headerLocation>${project.baseUri}../fop-core/src/tools/resources/checkstyle/LICENSE.txt</headerLocation>
+ <includeResources>false</includeResources>
+ <includeTestResources>false</includeTestResources>
+ <linkXRef>false</linkXRef>
+ <logViolationsToConsole>true</logViolationsToConsole>
+ <suppressionsLocation>${project.baseUri}../fop-core/src/tools/resources/checkstyle/suppressions.xml</suppressionsLocation>
+ <violationSeverity>warning</violationSeverity>
+ </configuration>
+ </plugin>
+ <!-- code analysis - findbugs -->
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>findbugs-maven-plugin</artifactId>
+ <version>${findbugs.plugin.version}</version>
+ <configuration>
+ <excludeFilterFile>../fop-core/src/tools/resources/findbugs/exclusions.xml</excludeFilterFile>
+ <effort>Max</effort>
+ <threshold>Low</threshold>
+ </configuration>
+ </plugin>
+ </plugins>
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ </resource>
+ <resource>
+ <directory>${basedir}/..</directory>
+ <includes>
+ <include>LICENSE</include>
+ <include>NOTICE</include>
+ </includes>
+ <targetPath>META-INF</targetPath>
+ </resource>
+ </resources>
+ <testResources>
+ <testResource>
+ <directory>src/test/resources</directory>
+ <includes>
+ <include>**/*</include>
+ </includes>
+ </testResource>
+ </testResources>
+ </build>
+
+</project>
diff --git a/fop-sandbox/src/main/java/org/apache/fop/render/mif/MIFElement.java b/fop-sandbox/src/main/java/org/apache/fop/render/mif/MIFElement.java
new file mode 100644
index 000000000..098eab470
--- /dev/null
+++ b/fop-sandbox/src/main/java/org/apache/fop/render/mif/MIFElement.java
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.mif;
+
+// Java
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * The is the basis for MIF document elements.
+ * This enables the creation of the element and to write it
+ * to an output stream including sub-elements or a single value.
+ */
+public class MIFElement {
+ /** name */
+ protected String name;
+ /** value string */
+ protected String valueStr;
+ /** value elements */
+ protected List valueElements;
+ /** true if started */
+ protected boolean started;
+ /** true if finishing */
+ protected boolean finish;
+ /** true if finished */
+ protected boolean finished;
+
+ /**
+ * @param name a name
+ */
+ public MIFElement(String name) {
+ this.name = name;
+ }
+
+ /** @param str a string value */
+ public void setValue(String str) {
+ valueStr = str;
+ }
+
+ /** @param el an MIF element */
+ public void addElement(MIFElement el) {
+ if (valueElements == null) {
+ valueElements = new java.util.ArrayList();
+ }
+ valueElements.add(el);
+ }
+
+ /**
+ * Output this element to an output stream.
+ * This will output only so far as the fisrt unfinished child element.
+ * This method can be called again to continue from the previous point.
+ * An element that contains child elements will only be finished when
+ * the finish method is called.
+ * @param os output stream
+ * @param indent indentation
+ * @return true if finished
+ * @throws IOException if not caught
+ */
+ public boolean output(OutputStream os, int indent) throws IOException {
+ if (finished) {
+ return true;
+ }
+ if (valueElements == null && valueStr == null) {
+ return false;
+ }
+
+ String indentStr = "";
+ for (int c = 0; c < indent; c++) {
+ indentStr += " ";
+ }
+ if (!started) {
+ os.write((indentStr + "<" + name).getBytes());
+ if (valueElements != null) {
+ os.write(("\n").getBytes());
+ }
+ started = true;
+ }
+ if (valueElements != null) {
+ boolean done = true;
+ for (Iterator iter = valueElements.iterator(); iter.hasNext();) {
+ MIFElement el = (MIFElement)iter.next();
+ boolean d = el.output(os, indent + 1);
+ if (d) {
+ iter.remove();
+ } else {
+ done = false;
+ break;
+ }
+ }
+ if (!finish || !done) {
+ return false;
+ }
+ os.write((indentStr + "> # end of " + name + "\n").getBytes());
+ } else {
+ os.write((" " + valueStr + ">\n").getBytes());
+ }
+ finished = true;
+ return true;
+ }
+
+ /** @param deep if true, also perform finish over value elements */
+ public void finish(boolean deep) {
+ finish = true;
+ if (deep && valueElements != null) {
+ for (Iterator iter = valueElements.iterator(); iter.hasNext();) {
+ MIFElement el = (MIFElement)iter.next();
+ el.finish(deep);
+ }
+ }
+ }
+}
+
diff --git a/fop-sandbox/src/main/java/org/apache/fop/render/mif/MIFFOEventHandlerMaker.java b/fop-sandbox/src/main/java/org/apache/fop/render/mif/MIFFOEventHandlerMaker.java
new file mode 100644
index 000000000..31ce03dc3
--- /dev/null
+++ b/fop-sandbox/src/main/java/org/apache/fop/render/mif/MIFFOEventHandlerMaker.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.mif;
+
+import java.io.OutputStream;
+
+import org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.apps.MimeConstants;
+import org.apache.fop.fo.FOEventHandler;
+import org.apache.fop.render.AbstractFOEventHandlerMaker;
+
+/**
+ * Maker class for MIF support.
+ */
+public class MIFFOEventHandlerMaker extends AbstractFOEventHandlerMaker {
+
+ private static final String[] MIMES = new String[] {MimeConstants.MIME_MIF};
+
+
+ /** {@inheritDoc} */
+ public FOEventHandler makeFOEventHandler(FOUserAgent ua, OutputStream out) {
+ return new MIFHandler(ua, out);
+ }
+
+ /** {@inheritDoc} */
+ public boolean needsOutputStream() {
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ public String[] getSupportedMimeTypes() {
+ return MIMES;
+ }
+
+}
diff --git a/fop-sandbox/src/main/java/org/apache/fop/render/mif/MIFFile.java b/fop-sandbox/src/main/java/org/apache/fop/render/mif/MIFFile.java
new file mode 100644
index 000000000..9ee8a8a5f
--- /dev/null
+++ b/fop-sandbox/src/main/java/org/apache/fop/render/mif/MIFFile.java
@@ -0,0 +1,159 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.mif;
+
+// Java
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * The MIF File.
+ * This organises the MIF File and the corresponding elements.
+ * The catalog elements are used to setup the resources that
+ * are referenced.
+ */
+public class MIFFile extends MIFElement {
+
+ /** colorCatalog */
+ protected MIFElement colorCatalog;
+ /** pgfCatalog */
+ protected PGFElement pgfCatalog;
+ /** fontCatalog */
+ protected MIFElement fontCatalog;
+ /** rulingCatalog */
+ protected RulingElement rulingCatalog;
+ /** tblCatalog */
+ protected MIFElement tblCatalog;
+ /** views */
+ protected MIFElement views;
+ /** variableFormats */
+ protected MIFElement variableFormats;
+ /** xRefFormats */
+ protected MIFElement xRefFormats;
+ /** document */
+ protected MIFElement document;
+ /** bookComponent */
+ protected MIFElement bookComponent;
+ /** initialAutoNums */
+ protected MIFElement initialAutoNums;
+ /** aFrames */
+ protected MIFElement aFrames;
+ /** tbls */
+ protected MIFElement tbls;
+ /** pages */
+ protected List pages = new java.util.ArrayList();
+ /** textFlows */
+ protected List textFlows;
+
+
+ /** default constructor */
+ public MIFFile() {
+ super("");
+ valueElements = new java.util.ArrayList();
+ setup();
+ }
+
+ /**
+ * Do some setup.
+ * Currently adds some dummy values to the resources.
+ */
+ protected void setup() {
+ MIFElement unit = new MIFElement("Units");
+ unit.setValue("Ucm");
+ addElement(unit);
+
+ colorCatalog = new MIFElement("ColorCatalog");
+ MIFElement color = new MIFElement("Color");
+ MIFElement prop = new MIFElement("ColorTag");
+ prop.setValue("`Black'");
+ color.addElement(prop);
+ prop = new MIFElement("ColorCyan");
+ prop.setValue("0.000000");
+ color.addElement(prop);
+
+ prop = new MIFElement("ColorMagenta");
+ prop.setValue("0.000000");
+ color.addElement(prop);
+ prop = new MIFElement("ColorYellow");
+ prop.setValue("0.000000");
+ color.addElement(prop);
+ prop = new MIFElement("ColorBlack");
+ prop.setValue("100.000000");
+ color.addElement(prop);
+ prop = new MIFElement("ColorAttribute");
+ prop.setValue("ColorIsBlack");
+ color.addElement(prop);
+ prop = new MIFElement("ColorAttribute");
+ prop.setValue("ColorIsReserved");
+ color.addElement(prop);
+ color.finish(true);
+
+ colorCatalog.addElement(color);
+ addElement(colorCatalog);
+
+ pgfCatalog = new PGFElement();
+ pgfCatalog.lookupElement(null);
+ addElement(pgfCatalog);
+
+ rulingCatalog = new RulingElement();
+ rulingCatalog.lookupElement(null);
+ addElement(rulingCatalog);
+
+ }
+
+ /**
+ * @param os output stream
+ * @throws IOException if not caught
+ */
+ public void output(OutputStream os) throws IOException {
+ if (finished) {
+ return;
+ }
+
+ if (!started) {
+ os.write(("<MIFFile 5.00> # Generated by FOP\n"/* + getVersion()*/).getBytes());
+ started = true;
+ }
+ boolean done = true;
+
+ for (Iterator iter = valueElements.iterator(); iter.hasNext();) {
+ MIFElement el = (MIFElement)iter.next();
+ boolean d = el.output(os, 0);
+ if (d) {
+ iter.remove();
+ } else {
+ done = false;
+ break;
+ }
+ }
+ if (done && finish) {
+ os.write(("# end of MIFFile").getBytes());
+ }
+ }
+
+ /** @param p a page element to add */
+ public void addPage(MIFElement p) {
+ pages.add(p);
+ addElement(p);
+ }
+}
+
diff --git a/fop-sandbox/src/main/java/org/apache/fop/render/mif/MIFHandler.java b/fop-sandbox/src/main/java/org/apache/fop/render/mif/MIFHandler.java
new file mode 100644
index 000000000..00b9dfbfe
--- /dev/null
+++ b/fop-sandbox/src/main/java/org/apache/fop/render/mif/MIFHandler.java
@@ -0,0 +1,388 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.mif;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.xml.sax.SAXException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.fo.FOEventHandler;
+import org.apache.fop.fo.FOText;
+import org.apache.fop.fo.flow.BasicLink;
+import org.apache.fop.fo.flow.Block;
+import org.apache.fop.fo.flow.Character;
+import org.apache.fop.fo.flow.ExternalGraphic;
+import org.apache.fop.fo.flow.Footnote;
+import org.apache.fop.fo.flow.FootnoteBody;
+import org.apache.fop.fo.flow.Inline;
+import org.apache.fop.fo.flow.InstreamForeignObject;
+import org.apache.fop.fo.flow.Leader;
+import org.apache.fop.fo.flow.ListBlock;
+import org.apache.fop.fo.flow.ListItem;
+import org.apache.fop.fo.flow.ListItemBody;
+import org.apache.fop.fo.flow.ListItemLabel;
+import org.apache.fop.fo.flow.PageNumber;
+import org.apache.fop.fo.flow.table.Table;
+import org.apache.fop.fo.flow.table.TableBody;
+import org.apache.fop.fo.flow.table.TableCell;
+import org.apache.fop.fo.flow.table.TableColumn;
+import org.apache.fop.fo.flow.table.TableFooter;
+import org.apache.fop.fo.flow.table.TableHeader;
+import org.apache.fop.fo.flow.table.TableRow;
+import org.apache.fop.fo.pagination.Flow;
+import org.apache.fop.fo.pagination.PageSequence;
+import org.apache.fop.fo.pagination.PageSequenceMaster;
+import org.apache.fop.fo.pagination.SimplePageMaster;
+import org.apache.fop.fo.pagination.StaticContent;
+import org.apache.fop.fonts.FontSetup;
+
+// TODO: do we really want every method throwing a SAXException
+
+/**
+ * The MIF Handler.
+ * This generates MIF output using the structure events from
+ * the FO Tree sent to this structure handler.
+ * This builds an MIF file and writes it to the output.
+ */
+public class MIFHandler extends FOEventHandler {
+
+ /** Logger */
+ private static Log log = LogFactory.getLog(MIFHandler.class);
+
+ /** the MIFFile instance */
+ protected MIFFile mifFile;
+
+ /** the OutputStream to write to */
+ protected OutputStream outStream;
+
+ // current state elements
+ private MIFElement textFlow;
+ private MIFElement para;
+
+ /**
+ * Creates a new MIF handler on a given OutputStream.
+ * @param ua FOUserAgent instance for this process
+ * @param os OutputStream to write to
+ */
+ public MIFHandler(FOUserAgent ua, OutputStream os) {
+ super(ua);
+ outStream = os;
+ boolean base14Kerning = false; //TODO - FIXME
+ FontSetup.setup(fontInfo, null, ua.getResourceResolver(), base14Kerning);
+ }
+
+ /** {@inheritDoc} */
+ public void startDocument() throws SAXException {
+ log.fatal("The MIF Handler is non-functional at this time. Please help resurrect it!");
+ mifFile = new MIFFile();
+ try {
+ mifFile.output(outStream);
+ } catch (IOException ioe) {
+ throw new SAXException(ioe);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void endDocument() throws SAXException {
+ // finish all open elements
+ mifFile.finish(true);
+ try {
+ mifFile.output(outStream);
+ outStream.flush();
+ } catch (IOException ioe) {
+ throw new SAXException(ioe);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void startPageSequence(PageSequence pageSeq) {
+ // get the layout master set
+ // setup the pages for this sequence
+ String name = pageSeq.getMasterReference();
+ SimplePageMaster spm = pageSeq.getRoot().getLayoutMasterSet().getSimplePageMaster(name);
+ if (spm == null) {
+ PageSequenceMaster psm
+ = pageSeq.getRoot().getLayoutMasterSet().getPageSequenceMaster(name);
+ } else {
+ // create simple master with regions
+ MIFElement prop = new MIFElement("PageType");
+ prop.setValue("BodyPage");
+
+ MIFElement page = new MIFElement("Page");
+ page.addElement(prop);
+
+ prop = new MIFElement("PageBackground");
+ prop.setValue("'Default'");
+ page.addElement(prop);
+
+ // build regions
+ MIFElement textRect = new MIFElement("TextRect");
+ prop = new MIFElement("ID");
+ prop.setValue("1");
+ textRect.addElement(prop);
+ prop = new MIFElement("ShapeRect");
+ prop.setValue("0.0 841.889 453.543 0.0");
+ textRect.addElement(prop);
+ page.addElement(textRect);
+
+ textRect = new MIFElement("TextRect");
+ prop = new MIFElement("ID");
+ prop.setValue("2");
+ textRect.addElement(prop);
+ prop = new MIFElement("ShapeRect");
+ prop.setValue("0.0 841.889 453.543 187.65");
+ textRect.addElement(prop);
+ page.addElement(textRect);
+
+ mifFile.addPage(page);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void endPageSequence(PageSequence pageSeq) {
+ }
+
+ /** {@inheritDoc} */
+ public void startFlow(Flow fl) {
+ // start text flow in body region
+ textFlow = new MIFElement("TextFlow");
+ }
+
+ /** {@inheritDoc} */
+ public void endFlow(Flow fl) {
+ textFlow.finish(true);
+ mifFile.addElement(textFlow);
+ textFlow = null;
+ }
+
+ /** {@inheritDoc} */
+ public void startBlock(Block bl) {
+ para = new MIFElement("Para");
+ // get font
+ textFlow.addElement(para);
+ }
+
+ /** {@inheritDoc} */
+ public void endBlock(Block bl) {
+ para.finish(true);
+ para = null;
+ }
+
+ /** {@inheritDoc} */
+ public void startInline(Inline inl) {
+ }
+
+ /** {@inheritDoc} */
+ public void endInline(Inline inl) {
+ }
+
+ /** {@inheritDoc} */
+ public void startTable(Table tbl) {
+ }
+
+ /** {@inheritDoc} */
+ public void endTable(Table tbl) {
+ }
+
+ /** {@inheritDoc} */
+ public void startColumn(TableColumn tc) {
+ }
+
+ /** {@inheritDoc} */
+ public void endColumn(TableColumn tc) {
+ }
+
+ /** {@inheritDoc} */
+ public void startHeader(TableHeader th) {
+ }
+
+ /** {@inheritDoc} */
+ public void endHeader(TableHeader th) {
+ }
+
+ /** {@inheritDoc} */
+ public void startFooter(TableFooter tf) {
+ }
+
+ /** {@inheritDoc} */
+ public void endFooter(TableFooter tf) {
+ }
+
+ /** {@inheritDoc} */
+ public void startBody(TableBody tb) {
+ }
+
+ /** {@inheritDoc} */
+ public void endBody(TableBody tb) {
+ }
+
+ /** {@inheritDoc} */
+ public void startRow(TableRow tr) {
+ }
+
+ /** {@inheritDoc} */
+ public void endRow(TableRow tr) {
+ }
+
+ /** {@inheritDoc} */
+ public void startCell(TableCell tc) {
+ }
+
+ /** {@inheritDoc} */
+ public void endCell(TableCell tc) {
+ }
+
+ /** {@inheritDoc} */
+ public void startList(ListBlock lb) {
+ }
+
+ /** {@inheritDoc} */
+ public void endList(ListBlock lb) {
+ }
+
+ /** {@inheritDoc} */
+ public void startListItem(ListItem li) {
+ }
+
+ /** {@inheritDoc} */
+ public void endListItem(ListItem li) {
+ }
+
+ /** {@inheritDoc} */
+ public void startListLabel(ListItemLabel listItemLabel) {
+ }
+
+ /** {@inheritDoc} */
+ public void endListLabel(ListItemLabel listItemLabel) {
+ }
+
+ /** {@inheritDoc} */
+ public void startListBody(ListItemBody listItemBody) {
+ }
+
+ /** {@inheritDoc} */
+ public void endListBody(ListItemBody listItemBody) {
+ }
+
+ /** {@inheritDoc} */
+ public void startStatic(StaticContent staticContent) {
+ }
+
+ /** {@inheritDoc} */
+ public void endStatic(StaticContent staticContent) {
+ }
+
+ /** {@inheritDoc} */
+ public void startMarkup() {
+ }
+
+ /** {@inheritDoc} */
+ public void endMarkup() {
+ }
+
+ /** {@inheritDoc} */
+ public void startLink(BasicLink basicLink) {
+ }
+
+ /** {@inheritDoc} */
+ public void endLink(BasicLink basicLink) {
+ }
+
+ /** {@inheritDoc} */
+ public void image(ExternalGraphic eg) {
+ }
+
+ /** {@inheritDoc} */
+ public void pageRef() {
+ }
+
+ /** {@inheritDoc} */
+ public void startInstreamForeignObject(InstreamForeignObject ifo) {
+ }
+
+ /** {@inheritDoc} */
+ public void endInstreamForeignObject(InstreamForeignObject ifo) {
+ }
+
+ /** {@inheritDoc} */
+ public void startFootnote(Footnote footnote) {
+ }
+
+ /** {@inheritDoc} */
+ public void endFootnote(Footnote footnote) {
+ }
+
+ /** {@inheritDoc} */
+ public void startFootnoteBody(FootnoteBody body) {
+ }
+
+ /** {@inheritDoc} */
+ public void endFootnoteBody(FootnoteBody body) {
+ }
+
+ /** {@inheritDoc} */
+ public void startLeader(Leader l) {
+ }
+
+ /** {@inheritDoc} */
+ public void endLeader(Leader l) {
+ }
+
+ public void character(Character c) {
+ appendCharacters(new String(new char[] {c.getCharacter()}));
+ }
+
+ /** {@inheritDoc} */
+ public void characters(FOText foText) {
+ appendCharacters(foText.getCharSequence().toString());
+ }
+
+ /** {@inheritDoc} */
+ public void startPageNumber(PageNumber pagenum) {
+ }
+
+ /** {@inheritDoc} */
+ public void endPageNumber(PageNumber pagenum) {
+ }
+
+ private void appendCharacters(String str) {
+ if (para != null) {
+ str = str.trim();
+ // break into nice length chunks
+ if (str.length() == 0) {
+ return;
+ }
+ MIFElement line = new MIFElement("ParaLine");
+ MIFElement prop = new MIFElement("TextRectID");
+ prop.setValue("2");
+ line.addElement(prop);
+ prop = new MIFElement("String");
+ prop.setValue("\"" + str + "\"");
+ line.addElement(prop);
+ para.addElement(line);
+ }
+ }
+}
+
diff --git a/fop-sandbox/src/main/java/org/apache/fop/render/mif/PGFElement.java b/fop-sandbox/src/main/java/org/apache/fop/render/mif/PGFElement.java
new file mode 100644
index 000000000..958518fac
--- /dev/null
+++ b/fop-sandbox/src/main/java/org/apache/fop/render/mif/PGFElement.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.mif;
+
+/**
+ * Font Catalog element.
+ * This is the reference lookup element for fonts in
+ * the MIF document.
+ */
+public class PGFElement extends RefElement {
+
+ /**
+ * Creates a new font catalog element.
+ */
+ public PGFElement() {
+ super("PgfCatalog");
+ }
+
+ /**
+ * @param key an object
+ * @return an MIF element
+ */
+ public MIFElement lookupElement(Object key) {
+ if (key == null) {
+ MIFElement pgf = new MIFElement("Pgf");
+ MIFElement prop = new MIFElement("PgfTag");
+ prop.setValue("`Body'");
+ pgf.addElement(prop);
+ addElement(pgf);
+ pgf.finish(true);
+ return pgf;
+ }
+ return null;
+ }
+}
+
diff --git a/fop-sandbox/src/main/java/org/apache/fop/render/mif/RefElement.java b/fop-sandbox/src/main/java/org/apache/fop/render/mif/RefElement.java
new file mode 100644
index 000000000..0849f4f69
--- /dev/null
+++ b/fop-sandbox/src/main/java/org/apache/fop/render/mif/RefElement.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.mif;
+
+/**
+ * Reference MIF Element.
+ * This element is a lookup reference set that contains
+ * a list of resources used in the MIF Document.
+ * When a lookup is performed it will either create a new
+ * element or return an existing element that is valid.
+ * THe key depends on the type of reference, it should be able
+ * to uniquely identify the element.
+ */
+public class RefElement extends MIFElement {
+
+ /**
+ * @param name a name
+ * @see org.apache.fop.render.mif.MIFElement#MIFElement(String)
+ */
+ public RefElement(String name) {
+ super(name);
+ }
+
+ /**
+ * @param key a key
+ * @return an mif element
+ */
+ public MIFElement lookupElement(Object key) {
+ return null;
+ }
+}
+
diff --git a/fop-sandbox/src/main/java/org/apache/fop/render/mif/RulingElement.java b/fop-sandbox/src/main/java/org/apache/fop/render/mif/RulingElement.java
new file mode 100644
index 000000000..c811a01a4
--- /dev/null
+++ b/fop-sandbox/src/main/java/org/apache/fop/render/mif/RulingElement.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.mif;
+
+/** a ruling element */
+public class RulingElement extends RefElement {
+
+ /** default constructor */
+ public RulingElement() {
+ super("RulingCatalog");
+ }
+
+ /** {@inheritDoc} */
+ public MIFElement lookupElement(Object key) {
+ if (key == null) {
+ MIFElement rul = new MIFElement("Ruling");
+ MIFElement prop = new MIFElement("RulingTag");
+ prop.setValue("`Default'");
+ rul.addElement(prop);
+ prop = new MIFElement("RulingPenWidth");
+ prop.setValue("1");
+ rul.addElement(prop);
+ prop = new MIFElement("RulingPen");
+ prop.setValue("0");
+ rul.addElement(prop);
+ prop = new MIFElement("RulingLines");
+ prop.setValue("1");
+ rul.addElement(prop);
+
+ addElement(rul);
+ rul.finish(true);
+ return rul;
+ }
+ return null;
+ }
+}
+
diff --git a/fop-sandbox/src/main/java/org/apache/fop/render/mif/package.html b/fop-sandbox/src/main/java/org/apache/fop/render/mif/package.html
new file mode 100644
index 000000000..6a8e3054d
--- /dev/null
+++ b/fop-sandbox/src/main/java/org/apache/fop/render/mif/package.html
@@ -0,0 +1,23 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!-- $Id$ -->
+<HTML>
+<TITLE>org.apache.fop.render.mif Package</TITLE>
+<BODY>
+<P>MIF Output Support</P>
+</BODY>
+</HTML> \ No newline at end of file
diff --git a/fop-sandbox/src/main/java/org/apache/fop/render/svg/AbstractSVGDocumentHandler.java b/fop-sandbox/src/main/java/org/apache/fop/render/svg/AbstractSVGDocumentHandler.java
new file mode 100644
index 000000000..091d904e5
--- /dev/null
+++ b/fop-sandbox/src/main/java/org/apache/fop/render/svg/AbstractSVGDocumentHandler.java
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.svg;
+
+import org.xml.sax.SAXException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.xmlgraphics.xmp.Metadata;
+
+import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.render.intermediate.AbstractXMLWritingIFDocumentHandler;
+import org.apache.fop.render.intermediate.IFContext;
+import org.apache.fop.render.intermediate.IFDocumentHandlerConfigurator;
+import org.apache.fop.render.intermediate.IFException;
+import org.apache.fop.render.intermediate.IFState;
+import org.apache.fop.render.java2d.Java2DUtil;
+
+/**
+ * Abstract base class for SVG Painter implementations.
+ */
+public abstract class AbstractSVGDocumentHandler extends AbstractXMLWritingIFDocumentHandler
+ implements SVGConstants {
+
+ /** logging instance */
+ private static Log log = LogFactory.getLog(AbstractSVGDocumentHandler.class);
+
+ /** Font configuration */
+ protected FontInfo fontInfo;
+
+ /** Holds the intermediate format state */
+ protected IFState state;
+
+ private static final int MODE_NORMAL = 0;
+ private static final int MODE_TEXT = 1;
+
+ private int mode = MODE_NORMAL;
+
+ public AbstractSVGDocumentHandler(IFContext context) {
+ super(context);
+ }
+
+ /** {@inheritDoc} */
+ protected String getMainNamespace() {
+ return NAMESPACE;
+ }
+
+ /** {@inheritDoc} */
+ public FontInfo getFontInfo() {
+ return this.fontInfo;
+ }
+
+ /** {@inheritDoc} */
+ public void setFontInfo(FontInfo fontInfo) {
+ this.fontInfo = fontInfo;
+ }
+
+ /** {@inheritDoc} */
+ public void setDefaultFontInfo(FontInfo fontInfo) {
+ FontInfo fi = Java2DUtil.buildDefaultJava2DBasedFontInfo(fontInfo, getUserAgent());
+ setFontInfo(fi);
+ }
+
+ /** {@inheritDoc} */
+ public IFDocumentHandlerConfigurator getConfigurator() {
+ return null; //No configurator, yet.
+ }
+
+ /** {@inheritDoc} */
+ public void startDocumentHeader() throws IFException {
+ try {
+ handler.startElement("defs");
+ } catch (SAXException e) {
+ throw new IFException("SAX error in startDocumentHeader()", e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void endDocumentHeader() throws IFException {
+ try {
+ handler.endElement("defs");
+ } catch (SAXException e) {
+ throw new IFException("SAX error in startDocumentHeader()", e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void handleExtensionObject(Object extension) throws IFException {
+ if (extension instanceof Metadata) {
+ Metadata meta = (Metadata)extension;
+ try {
+ handler.startElement("metadata");
+ meta.toSAX(this.handler);
+ handler.endElement("metadata");
+ } catch (SAXException e) {
+ throw new IFException("SAX error while handling extension object", e);
+ }
+ } else {
+ log.debug("Don't know how to handle extension object. Ignoring: "
+ + extension + " (" + extension.getClass().getName() + ")");
+ }
+ }
+}
diff --git a/fop-sandbox/src/main/java/org/apache/fop/render/svg/EmbeddedSVGImageHandler.java b/fop-sandbox/src/main/java/org/apache/fop/render/svg/EmbeddedSVGImageHandler.java
new file mode 100644
index 000000000..371f5a768
--- /dev/null
+++ b/fop-sandbox/src/main/java/org/apache/fop/render/svg/EmbeddedSVGImageHandler.java
@@ -0,0 +1,159 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.svg;
+
+import java.awt.Rectangle;
+import java.io.IOException;
+
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.sax.SAXResult;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.xmlgraphics.image.loader.Image;
+import org.apache.xmlgraphics.image.loader.ImageFlavor;
+import org.apache.xmlgraphics.image.loader.impl.ImageRawStream;
+import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM;
+import org.apache.xmlgraphics.util.QName;
+
+import org.apache.fop.image.loader.batik.BatikImageFlavors;
+import org.apache.fop.render.ImageHandler;
+import org.apache.fop.render.RenderingContext;
+import org.apache.fop.render.intermediate.DelegatingFragmentContentHandler;
+
+/**
+ * Image handler implementation that embeds SVG images in the target SVG file.
+ */
+public class EmbeddedSVGImageHandler implements ImageHandler, SVGConstants {
+
+ /** logging instance */
+ private static Log log = LogFactory.getLog(EmbeddedSVGImageHandler.class);
+
+ /** Constant for the "CDATA" attribute type. */
+ private static final String CDATA = "CDATA";
+
+ /** {@inheritDoc} */
+ public int getPriority() {
+ return 500;
+ }
+
+ /** {@inheritDoc} */
+ public Class getSupportedImageClass() {
+ return ImageRawStream.class;
+ }
+
+ /** {@inheritDoc} */
+ public ImageFlavor[] getSupportedImageFlavors() {
+ return new ImageFlavor[] {
+ BatikImageFlavors.SVG_DOM
+ };
+ }
+
+ private void addAttribute(AttributesImpl atts, QName attribute, String value) {
+ atts.addAttribute(attribute.getNamespaceURI(),
+ attribute.getLocalName(), attribute.getQName(), CDATA, value);
+ }
+
+ /** {@inheritDoc} */
+ public void handleImage(RenderingContext context, Image image, final Rectangle pos)
+ throws IOException {
+ SVGRenderingContext svgContext = (SVGRenderingContext)context;
+ ImageXMLDOM svg = (ImageXMLDOM)image;
+ ContentHandler handler = svgContext.getContentHandler();
+ AttributesImpl atts = new AttributesImpl();
+ atts.addAttribute("", "x", "x", CDATA, SVGUtil.formatMptToPt(pos.x));
+ atts.addAttribute("", "y", "y", CDATA, SVGUtil.formatMptToPt(pos.y));
+ atts.addAttribute("", "width", "width", CDATA, SVGUtil.formatMptToPt(pos.width));
+ atts.addAttribute("", "height", "height", CDATA, SVGUtil.formatMptToPt(pos.height));
+ try {
+
+ Document doc = (Document)svg.getDocument();
+ Element svgEl = (Element)doc.getDocumentElement();
+ if (svgEl.getAttribute("viewBox").length() == 0) {
+ log.warn("SVG doesn't have a viewBox. The result might not be scaled correctly!");
+ }
+
+ TransformerFactory tFactory = TransformerFactory.newInstance();
+ Transformer transformer = tFactory.newTransformer();
+ DOMSource src = new DOMSource(svg.getDocument());
+ SAXResult res = new SAXResult(new DelegatingFragmentContentHandler(handler) {
+
+ private boolean topLevelSVGFound;
+
+ private void setAttribute(AttributesImpl atts, String localName, String value) {
+ int index;
+ index = atts.getIndex("", localName);
+ if (index < 0) {
+ atts.addAttribute("", localName, localName, CDATA, value);
+ } else {
+ atts.setAttribute(index, "", localName, localName, CDATA, value);
+ }
+ }
+
+ public void startElement(String uri, String localName, String name, Attributes atts)
+ throws SAXException {
+ if (!topLevelSVGFound
+ && SVG_ELEMENT.getNamespaceURI().equals(uri)
+ && SVG_ELEMENT.getLocalName().equals(localName)) {
+ topLevelSVGFound = true;
+ AttributesImpl modAtts = new AttributesImpl(atts);
+ setAttribute(modAtts, "x", SVGUtil.formatMptToPt(pos.x));
+ setAttribute(modAtts, "y", SVGUtil.formatMptToPt(pos.y));
+ setAttribute(modAtts, "width", SVGUtil.formatMptToPt(pos.width));
+ setAttribute(modAtts, "height", SVGUtil.formatMptToPt(pos.height));
+ super.startElement(uri, localName, name, modAtts);
+ } else {
+ super.startElement(uri, localName, name, atts);
+ }
+ }
+
+ });
+ transformer.transform(src, res);
+ } catch (TransformerException te) {
+ throw new IOException(te.getMessage());
+ }
+ }
+
+ /** {@inheritDoc} */
+ public boolean isCompatible(RenderingContext targetContext, Image image) {
+ if (targetContext instanceof SVGRenderingContext) {
+ if (image == null) {
+ return true;
+ }
+ if (image instanceof ImageXMLDOM) {
+ ImageXMLDOM svg = (ImageXMLDOM)image;
+ return NAMESPACE.equals(svg.getRootNamespace());
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGConstants.java b/fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGConstants.java
new file mode 100644
index 000000000..46e0b8da8
--- /dev/null
+++ b/fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGConstants.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.svg;
+
+import org.apache.xmlgraphics.util.QName;
+
+import org.apache.fop.apps.MimeConstants;
+import org.apache.fop.util.XMLConstants;
+
+/**
+ * Constants for the intermediate format.
+ */
+public interface SVGConstants extends XMLConstants {
+
+ /** MIME type for SVG. */
+ String MIME_TYPE = MimeConstants.MIME_SVG;
+
+ /** MIME type for SVG Print. */
+ String MIME_SVG_PRINT = MimeConstants.MIME_SVG + ";profile=print";
+
+ /** File extension for SVG. */
+ String FILE_EXTENSION_SVG = "svg";
+
+ /** XML namespace for SVG. */
+ String NAMESPACE = "http://www.w3.org/2000/svg";
+
+ /** the SVG element */
+ QName SVG_ELEMENT = new QName(NAMESPACE, null, "svg");
+
+}
diff --git a/fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGDataUrlImageHandler.java b/fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGDataUrlImageHandler.java
new file mode 100644
index 000000000..fbe29e8d5
--- /dev/null
+++ b/fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGDataUrlImageHandler.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.svg;
+
+import java.awt.Rectangle;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+import org.apache.commons.io.IOUtils;
+
+import org.apache.xmlgraphics.image.loader.Image;
+import org.apache.xmlgraphics.image.loader.ImageFlavor;
+import org.apache.xmlgraphics.image.loader.impl.ImageRawStream;
+import org.apache.xmlgraphics.util.QName;
+import org.apache.xmlgraphics.util.uri.DataURLUtil;
+
+import org.apache.fop.render.ImageHandler;
+import org.apache.fop.render.RenderingContext;
+import org.apache.fop.render.intermediate.IFConstants;
+
+/**
+ * Image handler implementation that embeds JPEG bitmaps as RFC 2397 data URLs in the target SVG
+ * file.
+ */
+public class SVGDataUrlImageHandler implements ImageHandler, SVGConstants {
+
+ /** Constant for the "CDATA" attribute type. */
+ private static final String CDATA = "CDATA";
+
+ /** {@inheritDoc} */
+ public int getPriority() {
+ return 500;
+ }
+
+ /** {@inheritDoc} */
+ public Class getSupportedImageClass() {
+ return ImageRawStream.class;
+ }
+
+ /** {@inheritDoc} */
+ public ImageFlavor[] getSupportedImageFlavors() {
+ return new ImageFlavor[] {
+ ImageFlavor.RAW_PNG,
+ ImageFlavor.RAW_JPEG,
+ };
+ }
+
+ private void addAttribute(AttributesImpl atts, QName attribute, String value) {
+ atts.addAttribute(attribute.getNamespaceURI(),
+ attribute.getLocalName(), attribute.getQName(), CDATA, value);
+ }
+
+ /** {@inheritDoc} */
+ public void handleImage(RenderingContext context, Image image, Rectangle pos)
+ throws IOException {
+ SVGRenderingContext svgContext = (SVGRenderingContext)context;
+ ImageRawStream raw = (ImageRawStream)image;
+ InputStream in = raw.createInputStream();
+ try {
+ ContentHandler handler = svgContext.getContentHandler();
+ String url = DataURLUtil.createDataURL(in, raw.getMimeType());
+ AttributesImpl atts = new AttributesImpl();
+ addAttribute(atts, IFConstants.XLINK_HREF, url);
+ atts.addAttribute("", "x", "x", CDATA, Integer.toString(pos.x));
+ atts.addAttribute("", "y", "y", CDATA, Integer.toString(pos.y));
+ atts.addAttribute("", "width", "width", CDATA, Integer.toString(pos.width));
+ atts.addAttribute("", "height", "height", CDATA, Integer.toString(pos.height));
+ try {
+ handler.startElement(NAMESPACE, "image", "image", atts);
+ handler.endElement(NAMESPACE, "image", "image");
+ } catch (SAXException e) {
+ throw new IOException(e.getMessage());
+ }
+ } finally {
+ IOUtils.closeQuietly(in);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public boolean isCompatible(RenderingContext targetContext, Image image) {
+ return (image == null || image instanceof ImageRawStream)
+ && targetContext instanceof SVGRenderingContext;
+ }
+
+}
diff --git a/fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGDocumentHandler.java b/fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGDocumentHandler.java
new file mode 100644
index 000000000..f7bfbb38e
--- /dev/null
+++ b/fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGDocumentHandler.java
@@ -0,0 +1,275 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.svg;
+
+import java.awt.Dimension;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.sax.SAXResult;
+import javax.xml.transform.sax.TransformerHandler;
+import javax.xml.transform.stream.StreamResult;
+
+import org.w3c.dom.Document;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+import org.apache.commons.io.IOUtils;
+
+import org.apache.fop.render.bitmap.BitmapRendererEventProducer;
+import org.apache.fop.render.bitmap.MultiFileRenderingUtil;
+import org.apache.fop.render.intermediate.DelegatingFragmentContentHandler;
+import org.apache.fop.render.intermediate.IFContext;
+import org.apache.fop.render.intermediate.IFException;
+import org.apache.fop.render.intermediate.IFPainter;
+import org.apache.fop.util.GenerationHelperContentHandler;
+import org.apache.fop.util.XMLUtil;
+
+/**
+ * {@link org.apache.fop.render.intermediate.IFDocumentHandler} implementation
+ * that writes SVG 1.1.
+ */
+public class SVGDocumentHandler extends AbstractSVGDocumentHandler {
+
+ /** Helper class for generating multiple files */
+ private MultiFileRenderingUtil multiFileUtil;
+
+ private StreamResult firstStream;
+ private StreamResult currentStream;
+
+ /** Used for single-page documents rendered to a DOM or SAX. */
+ private Result simpleResult;
+
+ private Document reusedParts;
+
+ /**
+ * Default constructor.
+ */
+ public SVGDocumentHandler(IFContext context) {
+ super(context);
+ }
+
+ /** {@inheritDoc} */
+ public boolean supportsPagesOutOfOrder() {
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ public String getMimeType() {
+ return MIME_TYPE;
+ }
+
+ /** {@inheritDoc} */
+ public void setResult(Result result) throws IFException {
+ if (result instanceof StreamResult) {
+ multiFileUtil = new MultiFileRenderingUtil(FILE_EXTENSION_SVG,
+ getUserAgent().getOutputFile());
+ this.firstStream = (StreamResult)result;
+ } else {
+ this.simpleResult = result;
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void startDocument() throws IFException {
+ super.startDocument();
+ DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
+ builderFactory.setNamespaceAware(true);
+ builderFactory.setValidating(false);
+ try {
+ DocumentBuilder builder = builderFactory.newDocumentBuilder();
+ this.reusedParts = builder.newDocument();
+ } catch (ParserConfigurationException e) {
+ throw new IFException("Error while setting up a DOM for SVG generation", e);
+ }
+
+ try {
+ TransformerHandler toDOMHandler = tFactory.newTransformerHandler();
+ toDOMHandler.setResult(new DOMResult(this.reusedParts));
+ this.handler = decorate(toDOMHandler);
+ this.handler.startDocument();
+ } catch (SAXException se) {
+ throw new IFException("SAX error in startDocument()", se);
+ } catch (TransformerConfigurationException e) {
+ throw new IFException(
+ "Error while setting up a TransformerHandler for SVG generation", e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void endDocument() throws IFException {
+ //nop
+ }
+
+ /** {@inheritDoc} */
+ public void endDocumentHeader() throws IFException {
+ super.endDocumentHeader();
+ try {
+ //Stop recording parts reused for each page
+ this.handler.endDocument();
+ this.handler = null;
+ } catch (SAXException e) {
+ throw new IFException("SAX error in endDocumentHeader()", e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void startPageSequence(String id) throws IFException {
+ //nop
+ }
+
+ /** {@inheritDoc} */
+ public void endPageSequence() throws IFException {
+ //nop
+ }
+
+ /** {@inheritDoc} */
+ public void startPage(int index, String name, String pageMasterName, Dimension size)
+ throws IFException {
+ if (this.multiFileUtil != null) {
+ prepareHandlerWithOutputStream(index);
+ } else {
+ if (this.simpleResult == null) {
+ //Only one page is supported with this approach at the moment
+ throw new IFException(
+ "Only one page is supported for output with the given Result instance!",
+ null);
+ }
+ super.setResult(this.simpleResult);
+ this.simpleResult = null;
+ }
+
+ try {
+ handler.startDocument();
+ handler.startPrefixMapping("", NAMESPACE);
+ handler.startPrefixMapping(XLINK_PREFIX, XLINK_NAMESPACE);
+ AttributesImpl atts = new AttributesImpl();
+ XMLUtil.addAttribute(atts, "version", "1.1"); //SVG 1.1
+ /*
+ XMLUtil.addAttribute(atts, "index", Integer.toString(index));
+ XMLUtil.addAttribute(atts, "name", name);
+ */
+ XMLUtil.addAttribute(atts, "width", SVGUtil.formatMptToPt(size.width) + "pt");
+ XMLUtil.addAttribute(atts, "height", SVGUtil.formatMptToPt(size.height) + "pt");
+ XMLUtil.addAttribute(atts, "viewBox",
+ "0 0 " + SVGUtil.formatMptToPt(size.width)
+ + " " + SVGUtil.formatMptToPt(size.height));
+ handler.startElement("svg", atts);
+
+ try {
+ Transformer transformer = tFactory.newTransformer();
+ Source src = new DOMSource(this.reusedParts.getDocumentElement());
+ Result res = new SAXResult(new DelegatingFragmentContentHandler(this.handler));
+ transformer.transform(src, res);
+ } catch (TransformerConfigurationException tce) {
+ throw new IFException("Error setting up a Transformer", tce);
+ } catch (TransformerException te) {
+ if (te.getCause() instanceof SAXException) {
+ throw (SAXException)te.getCause();
+ } else {
+ throw new IFException("Error while serializing reused parts", te);
+ }
+ }
+ } catch (SAXException e) {
+ throw new IFException("SAX error in startPage()", e);
+ }
+ }
+
+ private void prepareHandlerWithOutputStream(int index) throws IFException {
+ OutputStream out;
+ try {
+ if (index == 0) {
+ out = null;
+ } else {
+ out = this.multiFileUtil.createOutputStream(index);
+ if (out == null) {
+ BitmapRendererEventProducer eventProducer
+ = BitmapRendererEventProducer.Provider.get(
+ getUserAgent().getEventBroadcaster());
+ eventProducer.stoppingAfterFirstPageNoFilename(this);
+ }
+ }
+ } catch (IOException ioe) {
+ throw new IFException("I/O exception while setting up output file", ioe);
+ }
+ if (out == null) {
+ this.handler = decorate(createContentHandler(this.firstStream));
+ } else {
+ this.currentStream = new StreamResult(out);
+ this.handler = decorate(createContentHandler(this.currentStream));
+ }
+ }
+
+ private GenerationHelperContentHandler decorate(ContentHandler contentHandler) {
+ return new GenerationHelperContentHandler(contentHandler, getMainNamespace(), getContext());
+ }
+
+ private void closeCurrentStream() {
+ if (this.currentStream != null) {
+ IOUtils.closeQuietly(currentStream.getOutputStream());
+ currentStream.setOutputStream(null);
+ IOUtils.closeQuietly(currentStream.getWriter());
+ currentStream.setWriter(null);
+ this.currentStream = null;
+ }
+ }
+
+ /** {@inheritDoc} */
+ public IFPainter startPageContent() throws IFException {
+ try {
+ handler.startElement("g");
+ } catch (SAXException e) {
+ throw new IFException("SAX error in startPageContent()", e);
+ }
+ return new SVGPainter(this, handler);
+ }
+
+ /** {@inheritDoc} */
+ public void endPageContent() throws IFException {
+ try {
+ handler.endElement("g");
+ } catch (SAXException e) {
+ throw new IFException("SAX error in endPageContent()", e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void endPage() throws IFException {
+ try {
+ handler.endElement("svg");
+ this.handler.endDocument();
+ } catch (SAXException e) {
+ throw new IFException("SAX error in endPage()", e);
+ }
+ closeCurrentStream();
+ }
+
+}
diff --git a/fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGDocumentHandlerMaker.java b/fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGDocumentHandlerMaker.java
new file mode 100644
index 000000000..75fc8b70e
--- /dev/null
+++ b/fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGDocumentHandlerMaker.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.svg;
+
+import org.apache.fop.render.intermediate.AbstractIFDocumentHandlerMaker;
+import org.apache.fop.render.intermediate.IFContext;
+import org.apache.fop.render.intermediate.IFDocumentHandler;
+
+/**
+ * Document handler factory for SVG output.
+ */
+public class SVGDocumentHandlerMaker extends AbstractIFDocumentHandlerMaker {
+
+ private static final String[] MIMES = new String[] {SVGConstants.MIME_TYPE};
+
+ /** {@inheritDoc} */
+ public IFDocumentHandler makeIFDocumentHandler(IFContext ifContext) {
+ return new SVGDocumentHandler(ifContext);
+ }
+
+ /** {@inheritDoc} */
+ public boolean needsOutputStream() {
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ public String[] getSupportedMimeTypes() {
+ return MIMES;
+ }
+
+}
diff --git a/fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGPainter.java b/fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGPainter.java
new file mode 100644
index 000000000..fb7ce2677
--- /dev/null
+++ b/fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGPainter.java
@@ -0,0 +1,418 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.svg;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Paint;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.geom.AffineTransform;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Map;
+
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+import org.apache.xmlgraphics.image.loader.ImageException;
+import org.apache.xmlgraphics.image.loader.ImageInfo;
+import org.apache.xmlgraphics.image.loader.ImageManager;
+import org.apache.xmlgraphics.image.loader.ImageSessionContext;
+import org.apache.xmlgraphics.xmp.Metadata;
+
+import org.apache.fop.ResourceEventProducer;
+import org.apache.fop.apps.MimeConstants;
+import org.apache.fop.render.ImageHandlerUtil;
+import org.apache.fop.render.RenderingContext;
+import org.apache.fop.render.intermediate.AbstractIFPainter;
+import org.apache.fop.render.intermediate.IFConstants;
+import org.apache.fop.render.intermediate.IFException;
+import org.apache.fop.render.intermediate.IFState;
+import org.apache.fop.render.intermediate.IFUtil;
+import org.apache.fop.traits.BorderProps;
+import org.apache.fop.traits.RuleStyle;
+import org.apache.fop.util.ColorUtil;
+import org.apache.fop.util.GenerationHelperContentHandler;
+import org.apache.fop.util.XMLConstants;
+import org.apache.fop.util.XMLUtil;
+
+/**
+ * IFPainter implementation that writes SVG.
+ */
+public class SVGPainter extends AbstractIFPainter<AbstractSVGDocumentHandler>
+ implements SVGConstants {
+
+ /** The SAX content handler that receives the generated XML events. */
+ private GenerationHelperContentHandler handler;
+
+ private static final int MODE_NORMAL = 0;
+ private static final int MODE_TEXT = 1;
+
+ private int mode = MODE_NORMAL;
+
+ /**
+ * Main constructor.
+ * @param parent the parent document handler
+ * @param contentHandler the target SAX content handler
+ */
+ public SVGPainter(AbstractSVGDocumentHandler parent,
+ GenerationHelperContentHandler contentHandler) {
+ super(parent);
+ this.handler = contentHandler;
+ this.state = IFState.create();
+ }
+
+ /** {@inheritDoc} */
+ public void startViewport(AffineTransform transform, Dimension size, Rectangle clipRect)
+ throws IFException {
+ startViewport(SVGUtil.formatAffineTransformMptToPt(transform), size, clipRect);
+ }
+
+ /** {@inheritDoc} */
+ public void startViewport(AffineTransform[] transforms, Dimension size, Rectangle clipRect)
+ throws IFException {
+ startViewport(SVGUtil.formatAffineTransformsMptToPt(transforms), size, clipRect);
+ }
+
+ private void startViewport(String transform, Dimension size, Rectangle clipRect)
+ throws IFException {
+ try {
+ establish(MODE_NORMAL);
+ AttributesImpl atts = new AttributesImpl();
+ if (transform != null && transform.length() > 0) {
+ XMLUtil.addAttribute(atts, "transform", transform);
+ }
+ handler.startElement("g", atts);
+
+ atts.clear();
+ XMLUtil.addAttribute(atts, "width", SVGUtil.formatMptToPt(size.width));
+ XMLUtil.addAttribute(atts, "height", SVGUtil.formatMptToPt(size.height));
+ if (clipRect != null) {
+ int[] v = new int[] {
+ clipRect.y,
+ -clipRect.x + size.width - clipRect.width,
+ -clipRect.y + size.height - clipRect.height,
+ clipRect.x};
+ int sum = 0;
+ for (int i = 0; i < 4; i++) {
+ sum += Math.abs(v[i]);
+ }
+ if (sum != 0) {
+ StringBuffer sb = new StringBuffer("rect(");
+ sb.append(SVGUtil.formatMptToPt(v[0])).append(',');
+ sb.append(SVGUtil.formatMptToPt(v[1])).append(',');
+ sb.append(SVGUtil.formatMptToPt(v[2])).append(',');
+ sb.append(SVGUtil.formatMptToPt(v[3])).append(')');
+ XMLUtil.addAttribute(atts, "clip", sb.toString());
+ }
+ XMLUtil.addAttribute(atts, "overflow", "hidden");
+ } else {
+ XMLUtil.addAttribute(atts, "overflow", "visible");
+ }
+ handler.startElement("svg", atts);
+ } catch (SAXException e) {
+ throw new IFException("SAX error in startBox()", e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void endViewport() throws IFException {
+ try {
+ establish(MODE_NORMAL);
+ handler.endElement("svg");
+ handler.endElement("g");
+ } catch (SAXException e) {
+ throw new IFException("SAX error in endBox()", e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void startGroup(AffineTransform[] transforms, String layer) throws IFException {
+ startGroup(SVGUtil.formatAffineTransformsMptToPt(transforms), layer);
+ }
+
+ /** {@inheritDoc} */
+ public void startGroup(AffineTransform transform, String layer) throws IFException {
+ startGroup(SVGUtil.formatAffineTransformMptToPt(transform), layer);
+ }
+
+ private void startGroup(String transform, String layer) throws IFException {
+ try {
+ AttributesImpl atts = new AttributesImpl();
+ if (transform != null && transform.length() > 0) {
+ XMLUtil.addAttribute(atts, "transform", transform);
+ }
+ handler.startElement("g", atts);
+ } catch (SAXException e) {
+ throw new IFException("SAX error in startGroup()", e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void endGroup() throws IFException {
+ try {
+ establish(MODE_NORMAL);
+ handler.endElement("g");
+ } catch (SAXException e) {
+ throw new IFException("SAX error in endGroup()", e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void drawImage(String uri, Rectangle rect) throws IFException {
+ try {
+ establish(MODE_NORMAL);
+
+ ImageManager manager = getUserAgent().getImageManager();
+ ImageInfo info = null;
+ try {
+ ImageSessionContext sessionContext = getUserAgent().getImageSessionContext();
+ info = manager.getImageInfo(uri, sessionContext);
+
+ String mime = info.getMimeType();
+ Map foreignAttributes = getContext().getForeignAttributes();
+ String conversionMode = (String)foreignAttributes.get(
+ ImageHandlerUtil.CONVERSION_MODE);
+ if ("reference".equals(conversionMode)
+ && (MimeConstants.MIME_GIF.equals(mime)
+ || MimeConstants.MIME_JPEG.equals(mime)
+ || MimeConstants.MIME_PNG.equals(mime)
+ || MimeConstants.MIME_SVG.equals(mime))) {
+ //Just reference the image
+ //TODO Some additional URI rewriting might be necessary
+ AttributesImpl atts = new AttributesImpl();
+ XMLUtil.addAttribute(atts, IFConstants.XLINK_HREF, uri);
+ XMLUtil.addAttribute(atts, "x", SVGUtil.formatMptToPt(rect.x));
+ XMLUtil.addAttribute(atts, "y", SVGUtil.formatMptToPt(rect.y));
+ XMLUtil.addAttribute(atts, "width", SVGUtil.formatMptToPt(rect.width));
+ XMLUtil.addAttribute(atts, "height", SVGUtil.formatMptToPt(rect.height));
+ handler.element("image", atts);
+ } else {
+ drawImageUsingImageHandler(info, rect);
+ }
+ } catch (ImageException ie) {
+ ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
+ getUserAgent().getEventBroadcaster());
+ eventProducer.imageError(this, (info != null ? info.toString() : uri), ie, null);
+ } catch (FileNotFoundException fe) {
+ ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
+ getUserAgent().getEventBroadcaster());
+ eventProducer.imageNotFound(this, (info != null ? info.toString() : uri), fe, null);
+ } catch (IOException ioe) {
+ ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
+ getUserAgent().getEventBroadcaster());
+ eventProducer.imageIOError(this, (info != null ? info.toString() : uri), ioe, null);
+ }
+ } catch (SAXException e) {
+ throw new IFException("SAX error in drawImage()", e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void drawImage(Document doc, Rectangle rect) throws IFException {
+ try {
+ establish(MODE_NORMAL);
+
+ drawImageUsingDocument(doc, rect);
+ } catch (SAXException e) {
+ throw new IFException("SAX error in drawImage()", e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ protected RenderingContext createRenderingContext() {
+ SVGRenderingContext svgContext = new SVGRenderingContext(
+ getUserAgent(), handler);
+ return svgContext;
+ }
+
+ private static String toString(Paint paint) {
+ //TODO Paint serialization: Fine-tune and extend!
+ if (paint instanceof Color) {
+ return ColorUtil.colorToString((Color)paint);
+ } else {
+ throw new UnsupportedOperationException("Paint not supported: " + paint);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void clipRect(Rectangle rect) throws IFException {
+ //TODO Implement me!!!
+ }
+
+ /** {@inheritDoc} */
+ public void clipBackground(Rectangle rect, BorderProps bpsBefore, BorderProps bpsAfter,
+ BorderProps bpsStart, BorderProps bpsEnd) throws IFException {
+ //TODO Implement me!!!
+
+ }
+
+ /** {@inheritDoc} */
+ public void fillRect(Rectangle rect, Paint fill) throws IFException {
+ if (fill == null) {
+ return;
+ }
+ try {
+ establish(MODE_NORMAL);
+ AttributesImpl atts = new AttributesImpl();
+ XMLUtil.addAttribute(atts, "x", SVGUtil.formatMptToPt(rect.x));
+ XMLUtil.addAttribute(atts, "y", SVGUtil.formatMptToPt(rect.y));
+ XMLUtil.addAttribute(atts, "width", SVGUtil.formatMptToPt(rect.width));
+ XMLUtil.addAttribute(atts, "height", SVGUtil.formatMptToPt(rect.height));
+ if (fill != null) {
+ XMLUtil.addAttribute(atts, "fill", toString(fill));
+ }
+ /* disabled
+ if (stroke != null) {
+ XMLUtil.addAttribute(atts, "stroke", toString(stroke));
+ }*/
+ handler.element("rect", atts);
+ } catch (SAXException e) {
+ throw new IFException("SAX error in fillRect()", e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void drawBorderRect(Rectangle rect, BorderProps before, BorderProps after,
+ BorderProps start, BorderProps end) throws IFException {
+ // TODO Auto-generated method stub
+ }
+
+ /** {@inheritDoc} */
+ public void drawLine(Point start, Point end, int width, Color color, RuleStyle style)
+ throws IFException {
+ try {
+ establish(MODE_NORMAL);
+ AttributesImpl atts = new AttributesImpl();
+ XMLUtil.addAttribute(atts, "x1", SVGUtil.formatMptToPt(start.x));
+ XMLUtil.addAttribute(atts, "y1", SVGUtil.formatMptToPt(start.y));
+ XMLUtil.addAttribute(atts, "x2", SVGUtil.formatMptToPt(end.x));
+ XMLUtil.addAttribute(atts, "y2", SVGUtil.formatMptToPt(end.y));
+ XMLUtil.addAttribute(atts, "stroke-width", toString(color));
+ XMLUtil.addAttribute(atts, "fill", toString(color));
+ //TODO Handle style parameter
+ handler.element("line", atts);
+ } catch (SAXException e) {
+ throw new IFException("SAX error in drawLine()", e);
+ }
+ }
+
+ /** {@inheritDoc} */
+
+ public void drawText(int x, int y, int letterSpacing, int wordSpacing, int[][] dp,
+ String text) throws IFException {
+ try {
+ establish(MODE_TEXT);
+ AttributesImpl atts = new AttributesImpl();
+ XMLUtil.addAttribute(atts, XMLConstants.XML_SPACE, "preserve");
+ XMLUtil.addAttribute(atts, "x", SVGUtil.formatMptToPt(x));
+ XMLUtil.addAttribute(atts, "y", SVGUtil.formatMptToPt(y));
+ if (letterSpacing != 0) {
+ XMLUtil.addAttribute(atts, "letter-spacing", SVGUtil.formatMptToPt(letterSpacing));
+ }
+ if (wordSpacing != 0) {
+ XMLUtil.addAttribute(atts, "word-spacing", SVGUtil.formatMptToPt(wordSpacing));
+ }
+ if (dp != null) {
+ int[] dx = IFUtil.convertDPToDX(dp);
+ XMLUtil.addAttribute(atts, "dx", SVGUtil.formatMptArrayToPt(dx));
+ }
+ handler.startElement("text", atts);
+ char[] chars = text.toCharArray();
+ handler.characters(chars, 0, chars.length);
+ handler.endElement("text");
+ } catch (SAXException e) {
+ throw new IFException("SAX error in setFont()", e);
+ }
+ }
+
+ private void leaveTextMode() throws SAXException {
+ assert this.mode == MODE_TEXT;
+ handler.endElement("g");
+ this.mode = MODE_NORMAL;
+ }
+
+ private void establish(int newMode) throws SAXException {
+ switch (newMode) {
+ case MODE_TEXT:
+ enterTextMode();
+ break;
+ default:
+ if (this.mode == MODE_TEXT) {
+ leaveTextMode();
+ }
+ }
+ }
+
+ private void enterTextMode() throws SAXException {
+ if (state.isFontChanged() && this.mode == MODE_TEXT) {
+ leaveTextMode();
+ }
+ if (this.mode != MODE_TEXT) {
+ startTextGroup();
+ this.mode = MODE_TEXT;
+ }
+ }
+
+ private void startTextGroup() throws SAXException {
+ AttributesImpl atts = new AttributesImpl();
+ XMLUtil.addAttribute(atts, "font-family", "'" + state.getFontFamily() + "'");
+ XMLUtil.addAttribute(atts, "font-style", state.getFontStyle());
+ XMLUtil.addAttribute(atts, "font-weight", Integer.toString(state.getFontWeight()));
+ XMLUtil.addAttribute(atts, "font-variant", state.getFontVariant());
+ XMLUtil.addAttribute(atts, "font-size", SVGUtil.formatMptToPt(state.getFontSize()));
+ XMLUtil.addAttribute(atts, "fill", toString(state.getTextColor()));
+ handler.startElement("g", atts);
+ state.resetFontChanged();
+ }
+
+ /**
+ * @param extension an extension object
+ * @throws IFException if not caught
+ */
+ public void handleExtensionObject(Object extension) throws IFException {
+ if (extension instanceof Metadata) {
+ Metadata meta = (Metadata)extension;
+ try {
+ establish(MODE_NORMAL);
+ handler.startElement("metadata");
+ meta.toSAX(this.handler);
+ handler.endElement("metadata");
+ } catch (SAXException e) {
+ throw new IFException("SAX error while handling extension object", e);
+ }
+ } else {
+ throw new UnsupportedOperationException(
+ "Don't know how to handle extension object: " + extension);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void fillBackground(Rectangle rect, Paint fill, BorderProps bpsBefore,
+ BorderProps bpsAfter, BorderProps bpsStart, BorderProps bpsEnd) throws IFException {
+ // Not supported in SVG
+
+ }
+
+
+
+}
diff --git a/fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGPrintDocumentHandler.java b/fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGPrintDocumentHandler.java
new file mode 100644
index 000000000..b97d3d261
--- /dev/null
+++ b/fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGPrintDocumentHandler.java
@@ -0,0 +1,170 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.svg;
+
+import java.awt.Dimension;
+
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+import org.apache.fop.render.intermediate.IFConstants;
+import org.apache.fop.render.intermediate.IFContext;
+import org.apache.fop.render.intermediate.IFException;
+import org.apache.fop.render.intermediate.IFPainter;
+import org.apache.fop.util.XMLUtil;
+
+/**
+ * {@link org.apache.fop.render.intermediate.IFDocumentHandler} implementation
+ * that writes SVG Print.
+ */
+public class SVGPrintDocumentHandler extends AbstractSVGDocumentHandler {
+
+ /**
+ * Default constructor.
+ */
+ public SVGPrintDocumentHandler(IFContext context) {
+ super(context);
+ }
+
+ /** {@inheritDoc} */
+ public boolean supportsPagesOutOfOrder() {
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ public String getMimeType() {
+ return MIME_SVG_PRINT;
+ }
+
+ /** {@inheritDoc} */
+ public void startDocument() throws IFException {
+ super.startDocument();
+ try {
+ handler.startDocument();
+ handler.startPrefixMapping("", NAMESPACE);
+ handler.startPrefixMapping(XLINK_PREFIX, XLINK_NAMESPACE);
+ handler.startPrefixMapping("if", IFConstants.NAMESPACE);
+ AttributesImpl atts = new AttributesImpl();
+ XMLUtil.addAttribute(atts, "version", "1.2"); //SVG Print is SVG 1.2
+ handler.startElement("svg", atts);
+ } catch (SAXException e) {
+ throw new IFException("SAX error in startDocument()", e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void endDocument() throws IFException {
+ try {
+ handler.endElement("svg");
+ handler.endDocument();
+ } catch (SAXException e) {
+ throw new IFException("SAX error in endDocument()", e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void startPageSequence(String id) throws IFException {
+ try {
+ AttributesImpl atts = new AttributesImpl();
+ if (id != null) {
+ atts.addAttribute(XML_NAMESPACE, "id", "xml:id", CDATA, id);
+ }
+ handler.startElement("pageSet", atts);
+ } catch (SAXException e) {
+ throw new IFException("SAX error in startPageSequence()", e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void endPageSequence() throws IFException {
+ try {
+ handler.endElement("pageSet");
+ } catch (SAXException e) {
+ throw new IFException("SAX error in endPageSequence()", e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void startPage(int index, String name, String pageMasterName, Dimension size)
+ throws IFException {
+ try {
+ AttributesImpl atts = new AttributesImpl();
+ /*
+ XMLUtil.addAttribute(atts, "index", Integer.toString(index));
+ XMLUtil.addAttribute(atts, "name", name);
+ */
+ //NOTE: SVG Print doesn't support individual page sizes for each page
+ atts.addAttribute(IFConstants.NAMESPACE, "width", "if:width",
+ CDATA, Integer.toString(size.width));
+ atts.addAttribute(IFConstants.NAMESPACE, "height", "if:height",
+ CDATA, Integer.toString(size.height));
+ atts.addAttribute(IFConstants.NAMESPACE, "viewBox", "if:viewBox", CDATA,
+ "0 0 " + Integer.toString(size.width) + " " + Integer.toString(size.height));
+ handler.startElement("page", atts);
+ } catch (SAXException e) {
+ throw new IFException("SAX error in startPage()", e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void startPageHeader() throws IFException {
+ }
+
+ /** {@inheritDoc} */
+ public void endPageHeader() throws IFException {
+ }
+
+ /** {@inheritDoc} */
+ public IFPainter startPageContent() throws IFException {
+ try {
+ handler.startElement("g");
+ } catch (SAXException e) {
+ throw new IFException("SAX error in startPageContent()", e);
+ }
+ return new SVGPainter(this, handler);
+ }
+
+ /** {@inheritDoc} */
+ public void endPageContent() throws IFException {
+ try {
+ handler.endElement("g");
+ } catch (SAXException e) {
+ throw new IFException("SAX error in endPageContent()", e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void startPageTrailer() throws IFException {
+ }
+
+ /** {@inheritDoc} */
+ public void endPageTrailer() throws IFException {
+ }
+
+ /** {@inheritDoc} */
+ public void endPage() throws IFException {
+ try {
+ handler.endElement("page");
+ } catch (SAXException e) {
+ throw new IFException("SAX error in endPage()", e);
+ }
+ }
+
+}
diff --git a/fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGPrintDocumentHandlerMaker.java b/fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGPrintDocumentHandlerMaker.java
new file mode 100644
index 000000000..0a0e599ff
--- /dev/null
+++ b/fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGPrintDocumentHandlerMaker.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.svg;
+
+import org.apache.fop.render.intermediate.AbstractIFDocumentHandlerMaker;
+import org.apache.fop.render.intermediate.IFContext;
+import org.apache.fop.render.intermediate.IFDocumentHandler;
+
+/**
+ * Document handler factory for SVG Print output.
+ */
+public class SVGPrintDocumentHandlerMaker extends AbstractIFDocumentHandlerMaker {
+
+ private static final String[] MIMES = new String[] {SVGConstants.MIME_SVG_PRINT};
+
+ /** {@inheritDoc} */
+ public IFDocumentHandler makeIFDocumentHandler(IFContext ifContext) {
+ return new SVGPrintDocumentHandler(ifContext);
+ }
+
+ /** {@inheritDoc} */
+ public boolean needsOutputStream() {
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ public String[] getSupportedMimeTypes() {
+ return MIMES;
+ }
+
+}
diff --git a/fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGRenderer.java b/fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGRenderer.java
new file mode 100644
index 000000000..9cbc1662d
--- /dev/null
+++ b/fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGRenderer.java
@@ -0,0 +1,177 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.svg;
+
+import java.awt.Dimension;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Writer;
+
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.batik.dom.GenericDOMImplementation;
+import org.apache.batik.svggen.SVGGeneratorContext;
+import org.apache.batik.svggen.SVGGraphics2D;
+
+import org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.apps.MimeConstants;
+import org.apache.fop.area.PageViewport;
+import org.apache.fop.render.bitmap.MultiFileRenderingUtil;
+import org.apache.fop.render.java2d.Java2DGraphicsState;
+import org.apache.fop.render.java2d.Java2DRenderer;
+
+/**
+ * <p>
+ * This renderer generates SVG (Scalable Vector Graphics) format.
+ * <p>
+ * This class actually does not render itself, instead it extends
+ * <code>org.apache.fop.render.java2D.Java2DRenderer</code> and uses
+ * Apache Batik's SVGGraphics2D for SVG generation.
+ */
+public class SVGRenderer extends Java2DRenderer {
+
+ /** logging instance */
+ private static Log log = LogFactory.getLog(SVGRenderer.class);
+
+ /** The MIME type for the SVG format */
+ public static final String MIME_TYPE = MimeConstants.MIME_SVG;
+
+ private static final String SVG_FILE_EXTENSION = "svg";
+
+ private OutputStream firstOutputStream;
+
+ private Document document;
+
+ private SVGGraphics2D svgGenerator;
+
+ /** Helper class for generating multiple files */
+ private MultiFileRenderingUtil multiFileUtil;
+
+ /**
+ * @param userAgent the user agent that contains configuration details. This cannot be null.
+ */
+ public SVGRenderer(FOUserAgent userAgent) {
+ super(userAgent);
+ }
+
+ /** {@inheritDoc} */
+ public String getMimeType() {
+ return MIME_TYPE;
+ }
+
+ /** {@inheritDoc} */
+ public void startRenderer(OutputStream outputStream) throws IOException {
+ this.firstOutputStream = outputStream;
+ this.multiFileUtil = new MultiFileRenderingUtil(SVG_FILE_EXTENSION,
+ getUserAgent().getOutputFile());
+ super.startRenderer(this.firstOutputStream);
+ }
+
+ /** {@inheritDoc} */
+ public void renderPage(PageViewport pageViewport) throws IOException {
+ log.debug("Rendering page: " + pageViewport.getPageNumberString());
+ // Get a DOMImplementation
+ DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation();
+
+ // Create an instance of org.w3c.dom.Document
+ this.document = domImpl.createDocument(null, "svg", null);
+
+ // Create an SVGGeneratorContext to customize SVG generation
+ SVGGeneratorContext ctx = SVGGeneratorContext.createDefault(this.document);
+ ctx.setComment("Generated by " + userAgent.getProducer() + " with Batik SVG Generator");
+ ctx.setEmbeddedFontsOn(true);
+
+ // Create an instance of the SVG Generator
+ this.svgGenerator = new SVGGraphics2D(ctx, true);
+ Rectangle2D viewArea = pageViewport.getViewArea();
+ Dimension dim = new Dimension();
+ dim.setSize(viewArea.getWidth() / 1000, viewArea.getHeight() / 1000);
+ this.svgGenerator.setSVGCanvasSize(dim);
+
+ AffineTransform at = this.svgGenerator.getTransform();
+ this.state = new Java2DGraphicsState(this.svgGenerator, this.fontInfo, at);
+ try {
+ //super.renderPage(pageViewport);
+ renderPageAreas(pageViewport.getPage());
+ } finally {
+ this.state = null;
+ }
+ writeSVGFile(pageViewport.getPageIndex());
+
+ this.svgGenerator = null;
+ this.document = null;
+
+ }
+
+ /** {@inheritDoc} */
+ public void stopRenderer() throws IOException {
+ super.stopRenderer();
+
+ // Cleaning
+ clearViewportList();
+ log.debug("SVG generation complete.");
+ }
+
+ private void writeSVGFile(int pageNumber) throws IOException {
+ log.debug("Writing out SVG file...");
+ // Finally, stream out SVG to the standard output using UTF-8
+ // character to byte encoding
+ boolean useCSS = true; // we want to use CSS style attribute
+ OutputStream out = getCurrentOutputStream(pageNumber);
+ if (out == null) {
+ log.warn("No filename information available."
+ + " Stopping early after the first page.");
+ return;
+ }
+ try {
+ Writer writer = new java.io.OutputStreamWriter(out, "UTF-8");
+ this.svgGenerator.stream(writer, useCSS);
+ } finally {
+ if (out != this.firstOutputStream) {
+ IOUtils.closeQuietly(out);
+ } else {
+ out.flush();
+ }
+ }
+ }
+
+ /**
+ * Returns the OutputStream corresponding to this page
+ * @param pageNumber 0-based page number
+ * @return the corresponding OutputStream
+ * @throws IOException In case of an I/O error
+ */
+ protected OutputStream getCurrentOutputStream(int pageNumber) throws IOException {
+ if (pageNumber == 0) {
+ return firstOutputStream;
+ } else {
+ return multiFileUtil.createOutputStream(pageNumber);
+ }
+
+ }
+
+}
diff --git a/fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGRendererContextConstants.java b/fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGRendererContextConstants.java
new file mode 100644
index 000000000..789db898e
--- /dev/null
+++ b/fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGRendererContextConstants.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.svg;
+
+import org.apache.fop.render.RendererContextConstants;
+
+/**
+ * Defines a number of standard constants (keys) for use by the RendererContext class.
+ */
+public interface SVGRendererContextConstants extends RendererContextConstants {
+
+ /** The SVG document that this image is being drawn into. */
+ String SVG_DOCUMENT = "svgDoc";
+
+ /** The current SVG page g element. */
+ String SVG_PAGE_G = "svgPageG";
+
+}
diff --git a/fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGRendererMaker.java b/fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGRendererMaker.java
new file mode 100644
index 000000000..95c4effbb
--- /dev/null
+++ b/fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGRendererMaker.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.svg;
+
+import org.apache.fop.apps.FOPException;
+import org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.apps.MimeConstants;
+import org.apache.fop.render.AbstractRendererMaker;
+import org.apache.fop.render.Renderer;
+
+/**
+ * RendererMaker for the SVG Renderer.
+ */
+public class SVGRendererMaker extends AbstractRendererMaker {
+
+ private static final String[] MIMES = new String[] {MimeConstants.MIME_SVG};
+
+ @Override
+ public Renderer makeRenderer(FOUserAgent ua) {
+ return new SVGRenderer(ua);
+ }
+
+ @Override
+ public boolean needsOutputStream() {
+ return true;
+ }
+
+ @Override
+ public String[] getSupportedMimeTypes() {
+ return MIMES;
+ }
+
+ @Override
+ public void configureRenderer(FOUserAgent userAgent, Renderer renderer) throws FOPException {
+ // No-Op
+ }
+}
diff --git a/fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGRenderingContext.java b/fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGRenderingContext.java
new file mode 100644
index 000000000..5e64af677
--- /dev/null
+++ b/fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGRenderingContext.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.svg;
+
+import org.xml.sax.ContentHandler;
+
+import org.apache.xmlgraphics.util.MimeConstants;
+
+import org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.render.AbstractRenderingContext;
+
+/**
+ * Rendering context for SVG production.
+ */
+public class SVGRenderingContext extends AbstractRenderingContext {
+
+ private ContentHandler handler;
+
+ /**
+ * Main constructor.
+ * @param userAgent the user agent
+ * @param handler the target content handler
+ */
+ public SVGRenderingContext(FOUserAgent userAgent, ContentHandler handler) {
+ super(userAgent);
+ this.handler = handler;
+ }
+
+ /** {@inheritDoc} */
+ public String getMimeType() {
+ return MimeConstants.MIME_SVG;
+ }
+
+ /**
+ * Returns the target content handler.
+ * @return the content handler
+ */
+ public ContentHandler getContentHandler() {
+ return this.handler;
+ }
+
+}
diff --git a/fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGSVGHandler.java b/fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGSVGHandler.java
new file mode 100644
index 000000000..9c571db97
--- /dev/null
+++ b/fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGSVGHandler.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.svg;
+
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.svg.SVGDocument;
+import org.w3c.dom.svg.SVGElement;
+import org.w3c.dom.svg.SVGSVGElement;
+
+import org.apache.batik.anim.dom.SVGDOMImplementation;
+import org.apache.batik.dom.util.DOMUtilities;
+import org.apache.batik.dom.util.XMLSupport;
+
+import org.apache.fop.render.Renderer;
+import org.apache.fop.render.RendererContext;
+import org.apache.fop.render.XMLHandler;
+
+/** The svg:svg element handler. */
+public class SVGSVGHandler implements XMLHandler, SVGRendererContextConstants {
+
+ /** {@inheritDoc} */
+ public void handleXML(RendererContext context,
+ org.w3c.dom.Document doc, String ns) throws Exception {
+ if (getNamespace().equals(ns)) {
+ if (!(doc instanceof SVGDocument)) {
+ DOMImplementation impl = SVGDOMImplementation.getDOMImplementation();
+ doc = DOMUtilities.deepCloneDocument(doc, impl);
+ }
+ SVGSVGElement svg = ((SVGDocument) doc).getRootElement();
+ SVGDocument targetDoc = (SVGDocument)context.getProperty(SVG_DOCUMENT);
+ SVGElement currentPageG = (SVGElement)context.getProperty(SVG_PAGE_G);
+ Element view = targetDoc.createElementNS(getNamespace(), "svg");
+ Node newsvg = targetDoc.importNode(svg, true);
+ //view.setAttributeNS(null, "viewBox", "0 0 ");
+ int xpos = ((Integer)context.getProperty(XPOS)).intValue();
+ int ypos = ((Integer)context.getProperty(YPOS)).intValue();
+ view.setAttributeNS(null, "x", "" + xpos / 1000f);
+ view.setAttributeNS(null, "y", "" + ypos / 1000f);
+
+ // this fixes a problem where the xmlns is repeated sometimes
+ Element ele = (Element) newsvg;
+ ele.setAttributeNS(XMLSupport.XMLNS_NAMESPACE_URI, "xmlns",
+ getNamespace());
+ if (ele.hasAttributeNS(null, "xmlns")) {
+ ele.removeAttributeNS(null, "xmlns");
+ }
+
+ view.appendChild(newsvg);
+ currentPageG.appendChild(view);
+ }
+ }
+
+
+ /** {@inheritDoc} */
+ public boolean supportsRenderer(Renderer renderer) {
+ return (renderer instanceof SVGRenderer);
+ }
+
+ /** {@inheritDoc} */
+ public String getNamespace() {
+ return SVGRenderer.MIME_TYPE;
+ }
+
+
+}
diff --git a/fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGUtil.java b/fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGUtil.java
new file mode 100644
index 000000000..186789dac
--- /dev/null
+++ b/fop-sandbox/src/main/java/org/apache/fop/render/svg/SVGUtil.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.svg;
+
+import java.awt.geom.AffineTransform;
+
+import org.apache.fop.render.intermediate.IFUtil;
+
+/**
+ * This class provides utility methods for generating SVG.
+ */
+public final class SVGUtil {
+
+ private SVGUtil() {
+ }
+
+ /**
+ * Formats a length in millipoints as a point value.
+ * @param mpt the length in millipoints
+ * @return the formatted value in points
+ */
+ public static String formatMptToPt(int mpt) {
+ return Float.toString(mpt / 1000f);
+ }
+
+ /**
+ * Formats an array of lengths in millipoints as point values.
+ * @param lengths the lengths in millipoints
+ * @return the formatted array in points
+ */
+ public static String formatMptArrayToPt(int[] lengths) {
+ return IFUtil.toString(lengths);
+ }
+
+ /**
+ * Formats a transformation matrix in millipoints with values as points.
+ * @param transform the transformation matrix in millipoints
+ * @return the formatted matrix in points
+ */
+ public static String formatAffineTransformMptToPt(AffineTransform transform) {
+ AffineTransform scaled = new AffineTransform(transform);
+ scaled.setToTranslation(
+ transform.getTranslateX() / 1000,
+ transform.getTranslateY() / 1000);
+ return IFUtil.toString(scaled);
+ }
+
+ /**
+ * Formats an array of transformation matrices in millipoints with values as points.
+ * @param transforms the transformation matrices in millipoints
+ * @return the formatted matrices in points
+ */
+ public static String formatAffineTransformsMptToPt(AffineTransform[] transforms) {
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0, c = transforms.length; i < c; i++) {
+ if (i > 0) {
+ sb.append(' ');
+ }
+ sb.append(formatAffineTransformMptToPt(transforms[i]));
+ }
+ return sb.toString();
+ }
+
+}
diff --git a/fop-sandbox/src/main/java/org/apache/fop/render/svg/package.html b/fop-sandbox/src/main/java/org/apache/fop/render/svg/package.html
new file mode 100644
index 000000000..977c7d183
--- /dev/null
+++ b/fop-sandbox/src/main/java/org/apache/fop/render/svg/package.html
@@ -0,0 +1,23 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!-- $Id$ -->
+<HTML>
+<TITLE>org.apache.fop.render.svg Package</TITLE>
+<BODY>
+<P>SVG (Structured Vector Graphics) Renderer</P>
+</BODY>
+</HTML> \ No newline at end of file
diff --git a/fop-sandbox/src/main/resources/META-INF/services/org.apache.fop.fo.ElementMapping b/fop-sandbox/src/main/resources/META-INF/services/org.apache.fop.fo.ElementMapping
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/fop-sandbox/src/main/resources/META-INF/services/org.apache.fop.fo.ElementMapping
diff --git a/fop-sandbox/src/main/resources/META-INF/services/org.apache.fop.fo.FOEventHandler b/fop-sandbox/src/main/resources/META-INF/services/org.apache.fop.fo.FOEventHandler
new file mode 100644
index 000000000..8fe7aac6e
--- /dev/null
+++ b/fop-sandbox/src/main/resources/META-INF/services/org.apache.fop.fo.FOEventHandler
@@ -0,0 +1 @@
+org.apache.fop.render.mif.MIFFOEventHandlerMaker \ No newline at end of file
diff --git a/fop-sandbox/src/main/resources/META-INF/services/org.apache.fop.render.ImageHandler b/fop-sandbox/src/main/resources/META-INF/services/org.apache.fop.render.ImageHandler
new file mode 100644
index 000000000..49af6340e
--- /dev/null
+++ b/fop-sandbox/src/main/resources/META-INF/services/org.apache.fop.render.ImageHandler
@@ -0,0 +1,2 @@
+org.apache.fop.render.svg.SVGDataUrlImageHandler
+org.apache.fop.render.svg.EmbeddedSVGImageHandler
diff --git a/fop-sandbox/src/main/resources/META-INF/services/org.apache.fop.render.XMLHandler b/fop-sandbox/src/main/resources/META-INF/services/org.apache.fop.render.XMLHandler
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/fop-sandbox/src/main/resources/META-INF/services/org.apache.fop.render.XMLHandler
diff --git a/fop-sandbox/src/main/resources/META-INF/services/org.apache.fop.render.intermediate.IFDocumentHandler b/fop-sandbox/src/main/resources/META-INF/services/org.apache.fop.render.intermediate.IFDocumentHandler
new file mode 100644
index 000000000..5ed153ac3
--- /dev/null
+++ b/fop-sandbox/src/main/resources/META-INF/services/org.apache.fop.render.intermediate.IFDocumentHandler
@@ -0,0 +1,2 @@
+org.apache.fop.render.svg.SVGDocumentHandlerMaker
+org.apache.fop.render.svg.SVGPrintDocumentHandlerMaker \ No newline at end of file