From c4c82d789126875999df9031d44ca9c772a649c5 Mon Sep 17 00:00:00 2001 From: Adrian Cumiskey Date: Wed, 26 Nov 2008 13:45:04 +0000 Subject: [PATCH] Merged revisions 719616,719629,719646,719654 via svnmerge from https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ........ r719616 | jeremias | 2008-11-21 16:07:58 +0000 (Fri, 21 Nov 2008) | 1 line Added support for SVG 1.2 inside fo:instream-foreign-object. The code just used the basic SVGDOMImplementation for SVG 1.1. Now it delegates the DOM building to Batik code instead of to a normal DOM builder. ........ r719629 | jeremias | 2008-11-21 16:33:33 +0000 (Fri, 21 Nov 2008) | 2 lines Fix for unit test failure in transcoder tests (NullPointerException): Have to pass the root PSGraphics2D to NativeTextHandler instead of the PSGenerator as this one hasn't been initialized in PSGraphics2D when the NativeTextHandler is built in AbstractPSTranscoder. ........ r719646 | jeremias | 2008-11-21 17:24:32 +0000 (Fri, 21 Nov 2008) | 1 line Fixed possible ClassCastException that was caused by my earlier attempt to support SVG 1.2. Batik's SAXSVGDocumentFactory doesn't currently deal well with the case when namespaces are declared outside of its scope. Worked around that by doing the SVG version detection in FOP code. SVG12DOMImplementation is obtained by reflection in order to keep backwards compatilibility with earlier Batik versions that don't support SVG 1.2. ........ r719654 | jeremias | 2008-11-21 17:44:08 +0000 (Fri, 21 Nov 2008) | 1 line This actually fixes a bug. ........ git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@720850 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/fo/XMLObj.java | 1 + .../svg/SVGDOMContentHandlerFactory.java | 151 ++++++++++++++++++ .../fop/fo/extensions/svg/SVGElement.java | 66 +++----- .../fop/render/ps/AbstractPSTranscoder.java | 15 +- .../fop/render/ps/NativeTextHandler.java | 15 +- .../apache/fop/render/ps/PSSVGHandler.java | 12 +- .../fop/svg/FOPSAXSVGDocumentFactory.java | 11 ++ status.xml | 5 +- 8 files changed, 209 insertions(+), 67 deletions(-) create mode 100644 src/java/org/apache/fop/fo/extensions/svg/SVGDOMContentHandlerFactory.java diff --git a/src/java/org/apache/fop/fo/XMLObj.java b/src/java/org/apache/fop/fo/XMLObj.java index 3330f41a5..e1eb47b46 100644 --- a/src/java/org/apache/fop/fo/XMLObj.java +++ b/src/java/org/apache/fop/fo/XMLObj.java @@ -217,6 +217,7 @@ public abstract class XMLObj extends FONode implements ObjectBuiltListener { /** {@inheritDoc} */ public void notifyObjectBuilt(Object obj) { this.doc = (Document)obj; + this.element = this.doc.getDocumentElement(); } } diff --git a/src/java/org/apache/fop/fo/extensions/svg/SVGDOMContentHandlerFactory.java b/src/java/org/apache/fop/fo/extensions/svg/SVGDOMContentHandlerFactory.java new file mode 100644 index 000000000..6556c7251 --- /dev/null +++ b/src/java/org/apache/fop/fo/extensions/svg/SVGDOMContentHandlerFactory.java @@ -0,0 +1,151 @@ +/* + * 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.fo.extensions.svg; + +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.sax.SAXTransformerFactory; +import javax.xml.transform.sax.TransformerHandler; + +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.Document; + +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; + +import org.apache.batik.dom.svg.SVGDOMImplementation; + +import org.apache.fop.util.ContentHandlerFactory; +import org.apache.fop.util.DelegatingContentHandler; + +/** + * ContentHandlerFactory which constructs ContentHandlers that build SVG DOM + * Documents. + */ +public class SVGDOMContentHandlerFactory implements ContentHandlerFactory { + + private static SAXTransformerFactory tFactory + = (SAXTransformerFactory)SAXTransformerFactory.newInstance(); + + /** + * Default Constructor. + */ + public SVGDOMContentHandlerFactory() { + // nop + } + + /** {@inheritDoc} */ + public String[] getSupportedNamespaces() { + return new String[] {SVGDOMImplementation.SVG_NAMESPACE_URI}; + } + + /** {@inheritDoc} */ + public ContentHandler createContentHandler() throws SAXException { + return new Handler(); + } + + private static class Handler extends DelegatingContentHandler implements + ContentHandlerFactory.ObjectSource { + + private Document doc; + private ObjectBuiltListener obListener; + + public Handler() throws SAXException { + super(); + } + + public Document getDocument() { + return this.doc; + } + + /** {@inheritDoc} */ + public Object getObject() { + return getDocument(); + } + + /** {@inheritDoc} */ + public void setObjectBuiltListener(ObjectBuiltListener listener) { + this.obListener = listener; + } + + /** {@inheritDoc} */ + public void startDocument() throws SAXException { + // Suppress startDocument() call if doc has not been set, yet. It + // will be done later. + if (doc != null) { + super.startDocument(); + } + } + + private DOMImplementation getDOMImplementation(String ver) { + //TODO It would be great if Batik provided this method as static helper method. + if (ver == null || ver.length() == 0 + || ver.equals("1.0") || ver.equals("1.1")) { + return SVGDOMImplementation.getDOMImplementation(); + } else if (ver.equals("1.2")) { + try { + Class clazz = Class.forName( + "org.apache.batik.dom.svg12.SVG12DOMImplementation"); + return (DOMImplementation)clazz.getMethod( + "getDOMImplementation", null).invoke(null, null); + } catch (Exception e) { + return SVGDOMImplementation.getDOMImplementation(); + } + } + throw new RuntimeException("Unsupport SVG version '" + ver + "'"); + } + + /** {@inheritDoc} */ + public void startElement(String uri, String localName, String qName, Attributes atts) + throws SAXException { + if (doc == null) { + TransformerHandler handler; + try { + handler = tFactory.newTransformerHandler(); + } catch (TransformerConfigurationException e) { + throw new SAXException("Error creating a new TransformerHandler", e); + } + String version = atts.getValue("version"); + DOMImplementation domImplementation = getDOMImplementation(version); + doc = domImplementation.createDocument(uri, qName, null); + // It's easier to work with an empty document, so remove the + // root element + doc.removeChild(doc.getDocumentElement()); + handler.setResult(new DOMResult(doc)); + setDelegateContentHandler(handler); + setDelegateLexicalHandler(handler); + setDelegateDTDHandler(handler); + handler.startDocument(); + } + super.startElement(uri, localName, qName, atts); + } + + /** {@inheritDoc} */ + public void endDocument() throws SAXException { + super.endDocument(); + if (obListener != null) { + obListener.notifyObjectBuilt(getObject()); + } + } + + } + +} diff --git a/src/java/org/apache/fop/fo/extensions/svg/SVGElement.java b/src/java/org/apache/fop/fo/extensions/svg/SVGElement.java index a40b80190..72cf19bc7 100644 --- a/src/java/org/apache/fop/fo/extensions/svg/SVGElement.java +++ b/src/java/org/apache/fop/fo/extensions/svg/SVGElement.java @@ -20,35 +20,27 @@ package org.apache.fop.fo.extensions.svg; // FOP -import org.apache.fop.apps.FOPException; -import org.apache.fop.fo.FONode; -import org.apache.fop.fo.PropertyList; -import org.apache.fop.util.ContentHandlerFactory; -import org.apache.fop.util.DOMBuilderContentHandlerFactory; +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.net.URL; + +import org.w3c.dom.Element; +import org.apache.batik.bridge.UnitProcessor; +import org.apache.batik.dom.svg.SVGContext; +import org.apache.batik.dom.svg.SVGDOMImplementation; import org.apache.batik.dom.svg.SVGOMDocument; import org.apache.batik.dom.svg.SVGOMElement; -import org.apache.batik.dom.svg.SVGContext; import org.apache.batik.dom.util.XMLSupport; -import org.w3c.dom.Element; -import org.w3c.dom.svg.SVGDocument; -import org.xml.sax.Attributes; -import org.xml.sax.Locator; -import org.apache.batik.bridge.UnitProcessor; import org.apache.batik.util.SVGConstants; -import org.w3c.dom.DOMImplementation; - -import org.apache.batik.dom.svg.SVGDOMImplementation; - -import java.net.URL; -import java.awt.geom.AffineTransform; -import java.awt.geom.Point2D; -import java.awt.geom.Rectangle2D; +import org.apache.fop.fo.FONode; +import org.apache.fop.util.ContentHandlerFactory; /** - * class representing the SVG root element - * for constructing an svg document. + * Class representing the SVG root element + * for constructing an SVG document. */ public class SVGElement extends SVGObj { @@ -61,21 +53,9 @@ public class SVGElement extends SVGObj { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public ContentHandlerFactory getContentHandlerFactory() { - return new DOMBuilderContentHandlerFactory(getNamespaceURI(), - SVGDOMImplementation.getDOMImplementation()); - } - - /** - * {@inheritDoc} - */ - public void processNode(String elementName, Locator locator, - Attributes attlist, PropertyList propertyList) throws FOPException { - super.processNode(elementName, locator, attlist, propertyList); - init(); + return new SVGDOMContentHandlerFactory(); } /** @@ -104,7 +84,6 @@ public class SVGElement extends SVGObj { log.error("Could not set base URL for svg", e); } - Element e = ((SVGDocument)doc).getRootElement(); final float ptmm = getUserAgent().getSourcePixelUnitToMillimeter(); // temporary svg context SVGContext dc = new SVGContext() { @@ -157,7 +136,8 @@ public class SVGElement extends SVGObj { public void deselectAll() { } }; - ((SVGOMElement)e).setSVGContext(dc); + SVGOMElement e = (SVGOMElement)svgRoot; + e.setSVGContext(dc); //if (!e.hasAttributeNS(XMLSupport.XMLNS_NAMESPACE_URI, "xmlns")) { e.setAttributeNS(XMLSupport.XMLNS_NAMESPACE_URI, "xmlns", @@ -165,21 +145,11 @@ public class SVGElement extends SVGObj { //} int fontSize = 12; Point2D p2d = getSize(fontSize, svgRoot, getUserAgent().getSourcePixelUnitToMillimeter()); - ((SVGOMElement)e).setSVGContext(null); + e.setSVGContext(null); return p2d; } - private void init() { - DOMImplementation impl = SVGDOMImplementation.getDOMImplementation(); - String svgNS = SVGDOMImplementation.SVG_NAMESPACE_URI; - doc = impl.createDocument(svgNS, "svg", null); - - element = doc.getDocumentElement(); - - buildTopLevel(doc, element); - } - /** * Get the size of the SVG root element. * @param size the font size diff --git a/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java b/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java index 374b5a256..705515311 100644 --- a/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java +++ b/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java @@ -25,20 +25,23 @@ import java.io.BufferedOutputStream; import java.io.IOException; import java.io.OutputStream; +import org.w3c.dom.Document; +import org.w3c.dom.svg.SVGLength; + import org.apache.avalon.framework.configuration.Configuration; import org.apache.batik.bridge.BridgeContext; import org.apache.batik.bridge.UnitProcessor; import org.apache.batik.transcoder.TranscoderException; import org.apache.batik.transcoder.TranscoderOutput; import org.apache.batik.transcoder.image.ImageTranscoder; -import org.apache.fop.fonts.FontInfo; -import org.apache.fop.fonts.FontSetup; -import org.apache.fop.svg.AbstractFOPTranscoder; + import org.apache.xmlgraphics.java2d.TextHandler; import org.apache.xmlgraphics.java2d.ps.AbstractPSDocumentGraphics2D; import org.apache.xmlgraphics.ps.PSGenerator; -import org.w3c.dom.Document; -import org.w3c.dom.svg.SVGLength; + +import org.apache.fop.fonts.FontInfo; +import org.apache.fop.fonts.FontSetup; +import org.apache.fop.svg.AbstractFOPTranscoder; /** * This class enables to transcode an input to a PostScript document. @@ -99,7 +102,7 @@ public abstract class AbstractPSTranscoder extends AbstractFOPTranscoder { //TODO Do custom font configuration here somewhere/somehow FontSetup.setup(fontInfo); PSGenerator generator = graphics.getPSGenerator(); - graphics.setCustomTextHandler(new NativeTextHandler(generator, fontInfo)); + graphics.setCustomTextHandler(new NativeTextHandler(graphics, fontInfo)); } super.transcode(document, uri, output); diff --git a/src/java/org/apache/fop/render/ps/NativeTextHandler.java b/src/java/org/apache/fop/render/ps/NativeTextHandler.java index 98addd19e..7cf59d519 100644 --- a/src/java/org/apache/fop/render/ps/NativeTextHandler.java +++ b/src/java/org/apache/fop/render/ps/NativeTextHandler.java @@ -24,13 +24,14 @@ import java.awt.Shape; import java.awt.geom.AffineTransform; import java.io.IOException; +import org.apache.xmlgraphics.java2d.ps.PSGraphics2D; +import org.apache.xmlgraphics.java2d.ps.PSTextHandler; +import org.apache.xmlgraphics.ps.PSGenerator; + import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.FontSetup; import org.apache.fop.fonts.FontTriplet; -import org.apache.xmlgraphics.java2d.ps.PSGraphics2D; -import org.apache.xmlgraphics.java2d.ps.PSTextHandler; -import org.apache.xmlgraphics.ps.PSGenerator; /** * Specialized TextHandler implementation that the PSGraphics2D class delegates to to paint text @@ -38,7 +39,7 @@ import org.apache.xmlgraphics.ps.PSGenerator; */ public class NativeTextHandler implements PSTextHandler { - private final PSGenerator gen; + private PSGraphics2D rootG2D; /** FontInfo containing all available fonts */ protected FontInfo fontInfo; @@ -60,8 +61,8 @@ public class NativeTextHandler implements PSTextHandler { * @param g2d the PSGraphics2D instance this instances is used by * @param fontInfo the FontInfo object with all available fonts */ - public NativeTextHandler(PSGenerator gen, FontInfo fontInfo) { - this.gen = gen; + public NativeTextHandler(PSGraphics2D g2d, FontInfo fontInfo) { + this.rootG2D = g2d; if (fontInfo != null) { this.fontInfo = fontInfo; } else { @@ -84,7 +85,7 @@ public class NativeTextHandler implements PSTextHandler { } private PSGenerator getPSGenerator() { - return this.gen; + return this.rootG2D.getPSGenerator(); } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/render/ps/PSSVGHandler.java b/src/java/org/apache/fop/render/ps/PSSVGHandler.java index 2bc0f069b..1e65dfb98 100644 --- a/src/java/org/apache/fop/render/ps/PSSVGHandler.java +++ b/src/java/org/apache/fop/render/ps/PSSVGHandler.java @@ -24,12 +24,18 @@ import java.awt.geom.AffineTransform; import java.io.IOException; import java.util.Map; +import org.w3c.dom.Document; + import org.apache.avalon.framework.configuration.Configuration; import org.apache.batik.bridge.BridgeContext; import org.apache.batik.bridge.GVTBuilder; import org.apache.batik.gvt.GraphicsNode; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + +import org.apache.xmlgraphics.java2d.ps.PSGraphics2D; +import org.apache.xmlgraphics.ps.PSGenerator; + import org.apache.fop.fonts.FontInfo; import org.apache.fop.render.AbstractGenericSVGHandler; import org.apache.fop.render.Renderer; @@ -37,9 +43,6 @@ import org.apache.fop.render.RendererContext; import org.apache.fop.render.RendererContextConstants; import org.apache.fop.svg.SVGEventProducer; import org.apache.fop.svg.SVGUserAgent; -import org.apache.xmlgraphics.java2d.ps.PSGraphics2D; -import org.apache.xmlgraphics.ps.PSGenerator; -import org.w3c.dom.Document; /** * PostScript XML handler for SVG. Uses Apache Batik for SVG processing. @@ -259,9 +262,8 @@ public class PSSVGHandler extends AbstractGenericSVGHandler NativeTextHandler nativeTextHandler = null; BridgeContext ctx = new BridgeContext(ua); if (!strokeText) { - PSGenerator generator = graphics.getPSGenerator(); FontInfo fontInfo = psInfo.getFontInfo(); - nativeTextHandler = new NativeTextHandler(generator, fontInfo); + nativeTextHandler = new NativeTextHandler(graphics, fontInfo); graphics.setCustomTextHandler(nativeTextHandler); PSTextPainter textPainter = new PSTextPainter(nativeTextHandler); ctx.setTextPainter(textPainter); diff --git a/src/java/org/apache/fop/svg/FOPSAXSVGDocumentFactory.java b/src/java/org/apache/fop/svg/FOPSAXSVGDocumentFactory.java index 720795cb2..fce6ed2b6 100644 --- a/src/java/org/apache/fop/svg/FOPSAXSVGDocumentFactory.java +++ b/src/java/org/apache/fop/svg/FOPSAXSVGDocumentFactory.java @@ -21,6 +21,8 @@ package org.apache.fop.svg; import java.io.IOException; +import org.w3c.dom.Document; + import org.xml.sax.EntityResolver; import org.xml.sax.InputSource; import org.xml.sax.SAXException; @@ -71,4 +73,13 @@ public class FOPSAXSVGDocumentFactory extends SAXSVGDocumentFactory { return super.resolveEntity(publicId, systemId); } + /** + * Returns the document built up by handling the incoming SAX events. This method will not + * return any instance for the first SAX events have been received. + * @return the DOM document + */ + public Document getDocument() { + return this.document; + } + } diff --git a/status.xml b/status.xml index ce3bc60d5..0f139fba7 100644 --- a/status.xml +++ b/status.xml @@ -62,9 +62,12 @@ AFP Output: Native image embedding support (e.g. JPEG, GIF, TIFF) using ObjectContainer and a MOD:CA Registry implementation. - + More robust AFP font parsing, although it is still in need of some rework in the future. + + Added support for SVG 1.2 functionality inside fo:instream-foreign-object. + Fixed a bug when combining break-before with a span change. -- 2.39.5