From 8b281b7c15488402a4dd30d41c4d8e2359e92140 Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Fri, 25 Jan 2008 08:26:54 +0000 Subject: [PATCH] Added support for DOMSource to Preloader SVG so a URI Resolver can be written that provides the SVG as a W3C SVG DOM. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@615144 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/image/loader/batik/PreloaderSVG.java | 125 +++++++++++------- .../loader/batik/ImagePreloaderTestCase.java | 56 +++++++- 2 files changed, 129 insertions(+), 52 deletions(-) diff --git a/src/java/org/apache/fop/image/loader/batik/PreloaderSVG.java b/src/java/org/apache/fop/image/loader/batik/PreloaderSVG.java index e83a302da..db03cbbf2 100644 --- a/src/java/org/apache/fop/image/loader/batik/PreloaderSVG.java +++ b/src/java/org/apache/fop/image/loader/batik/PreloaderSVG.java @@ -25,6 +25,7 @@ import java.io.InputStream; import javax.xml.parsers.SAXParserFactory; import javax.xml.transform.Source; +import javax.xml.transform.dom.DOMSource; import org.w3c.dom.Element; import org.w3c.dom.svg.SVGDocument; @@ -61,14 +62,13 @@ public class PreloaderSVG extends AbstractImagePreloader { /** {@inheritDoc} */ public ImageInfo preloadImage(String uri, Source src, ImageContext context) throws IOException { - if (!ImageUtil.hasInputStream(src)) { - //TODO Remove this and support DOMSource and possibly SAXSource - return null; - } ImageInfo info = null; if (batikAvailable) { try { Loader loader = new Loader(); + if (!loader.isSupportedSource(src)) { + return null; + } info = loader.getImage(uri, src, context); } catch (NoClassDefFoundError e) { batikAvailable = false; @@ -76,7 +76,7 @@ public class PreloaderSVG extends AbstractImagePreloader { return null; } } - if (info != null) { + if (info != null && ImageUtil.hasInputStream(src)) { ImageUtil.closeQuietly(src); //Image is fully read } return info; @@ -106,57 +106,30 @@ public class PreloaderSVG extends AbstractImagePreloader { ImageContext context) { // parse document and get the size attributes of the svg element - InputStream in = new UnclosableInputStream(ImageUtil.needInputStream(src)); + InputStream in = null; try { - int length = in.available(); - in.mark(length + 1); - SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory( - getParserName()); - SVGDocument doc = (SVGDocument) factory.createSVGDocument(src.getSystemId(), in); - - Element e = doc.getRootElement(); - float pxUnitToMillimeter = 25.4f / context.getSourceResolution(); - SVGUserAgent userAg = new SVGUserAgent(pxUnitToMillimeter, - new AffineTransform()); - BridgeContext ctx = new BridgeContext(userAg); - UnitProcessor.Context uctx = UnitProcessor.createContext(ctx, e); - - String s; - // 'width' attribute - default is 100% - s = e.getAttributeNS(null, SVGOMDocument.SVG_WIDTH_ATTRIBUTE); - if (s.length() == 0) { - s = SVGOMDocument.SVG_SVG_WIDTH_DEFAULT_VALUE; - } - float width = UnitProcessor.svgHorizontalLengthToUserSpace( - s, SVGOMDocument.SVG_WIDTH_ATTRIBUTE, uctx); - - // 'height' attribute - default is 100% - s = e.getAttributeNS(null, SVGOMDocument.SVG_HEIGHT_ATTRIBUTE); - if (s.length() == 0) { - s = SVGOMDocument.SVG_SVG_HEIGHT_DEFAULT_VALUE; + SVGDocument doc; + if (src instanceof DOMSource) { + DOMSource domSrc = (DOMSource)src; + doc = (SVGDocument)domSrc.getNode(); + } else { + in = new UnclosableInputStream(ImageUtil.needInputStream(src)); + int length = in.available(); + in.mark(length + 1); + SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory( + getParserName()); + doc = (SVGDocument) factory.createSVGDocument(src.getSystemId(), in); } - float height = UnitProcessor.svgVerticalLengthToUserSpace( - s, SVGOMDocument.SVG_HEIGHT_ATTRIBUTE, uctx); - - ImageInfo info = new ImageInfo(uri, MimeConstants.MIME_SVG); - ImageSize size = new ImageSize(); - size.setSizeInMillipoints(Math.round(width * 1000), Math.round(height * 1000)); - //Set the resolution to that of the FOUserAgent - size.setResolution(context.getSourceResolution()); - size.calcPixelsFromSize(); - info.setSize(size); - - //The whole image had to be loaded for this, so keep it - ImageXMLDOM xmlImage = new ImageXMLDOM(info, - doc, SVGDOMImplementation.SVG_NAMESPACE_URI); - info.getCustomObjects().put(ImageInfo.ORIGINAL_IMAGE, xmlImage); + ImageInfo info = createImageInfo(uri, context, doc); return info; } catch (NoClassDefFoundError ncdfe) { - try { - in.reset(); - } catch (IOException ioe) { - // we're more interested in the original exception + if (in != null) { + try { + in.reset(); + } catch (IOException ioe) { + // we're more interested in the original exception + } } batikAvailable = false; log.warn("Batik not in class path", ncdfe); @@ -177,6 +150,56 @@ public class PreloaderSVG extends AbstractImagePreloader { return null; } } + + private ImageInfo createImageInfo(String uri, ImageContext context, SVGDocument doc) { + Element e = doc.getRootElement(); + float pxUnitToMillimeter = 25.4f / context.getSourceResolution(); + SVGUserAgent userAg = new SVGUserAgent(pxUnitToMillimeter, + new AffineTransform()); + BridgeContext ctx = new BridgeContext(userAg); + UnitProcessor.Context uctx = UnitProcessor.createContext(ctx, e); + + String s; + // 'width' attribute - default is 100% + s = e.getAttributeNS(null, SVGOMDocument.SVG_WIDTH_ATTRIBUTE); + if (s.length() == 0) { + s = SVGOMDocument.SVG_SVG_WIDTH_DEFAULT_VALUE; + } + float width = UnitProcessor.svgHorizontalLengthToUserSpace( + s, SVGOMDocument.SVG_WIDTH_ATTRIBUTE, uctx); + + // 'height' attribute - default is 100% + s = e.getAttributeNS(null, SVGOMDocument.SVG_HEIGHT_ATTRIBUTE); + if (s.length() == 0) { + s = SVGOMDocument.SVG_SVG_HEIGHT_DEFAULT_VALUE; + } + float height = UnitProcessor.svgVerticalLengthToUserSpace( + s, SVGOMDocument.SVG_HEIGHT_ATTRIBUTE, uctx); + + ImageInfo info = new ImageInfo(uri, MimeConstants.MIME_SVG); + ImageSize size = new ImageSize(); + size.setSizeInMillipoints(Math.round(width * 1000), Math.round(height * 1000)); + //Set the resolution to that of the FOUserAgent + size.setResolution(context.getSourceResolution()); + size.calcPixelsFromSize(); + info.setSize(size); + + //The whole image had to be loaded for this, so keep it + ImageXMLDOM xmlImage = new ImageXMLDOM(info, + doc, SVGDOMImplementation.SVG_NAMESPACE_URI); + info.getCustomObjects().put(ImageInfo.ORIGINAL_IMAGE, xmlImage); + return info; + } + + private boolean isSupportedSource(Source src) { + if (src instanceof DOMSource) { + DOMSource domSrc = (DOMSource)src; + return (domSrc.getNode() instanceof SVGDocument); + } else { + return ImageUtil.hasInputStream(src); + } + } + } } diff --git a/test/java/org/apache/fop/image/loader/batik/ImagePreloaderTestCase.java b/test/java/org/apache/fop/image/loader/batik/ImagePreloaderTestCase.java index b14dd1fb8..9406ed65c 100644 --- a/test/java/org/apache/fop/image/loader/batik/ImagePreloaderTestCase.java +++ b/test/java/org/apache/fop/image/loader/batik/ImagePreloaderTestCase.java @@ -21,8 +21,19 @@ package org.apache.fop.image.loader.batik; import java.io.IOException; +import javax.xml.transform.Source; +import javax.xml.transform.TransformerException; +import javax.xml.transform.URIResolver; +import javax.xml.transform.dom.DOMSource; + import junit.framework.TestCase; +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import org.apache.batik.dom.svg.SVGDOMImplementation; + import org.apache.xmlgraphics.image.loader.ImageException; import org.apache.xmlgraphics.image.loader.ImageInfo; import org.apache.xmlgraphics.image.loader.ImageManager; @@ -30,7 +41,6 @@ import org.apache.xmlgraphics.image.loader.ImageManager; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.FopFactory; import org.apache.fop.apps.MimeConstants; -import org.apache.fop.image.loader.batik.ImageWMF; /** * Tests for bundled image preloader implementations. @@ -89,6 +99,50 @@ public class ImagePreloaderTestCase extends TestCase { assertEquals(100000, info.getSize().getHeightMpt()); } + public void testSVGWithDOM() throws Exception { + String uri = "my:SVGImage"; + FOUserAgent userAgent = fopFactory.newFOUserAgent(); + + userAgent.setURIResolver(new URIResolver() { + + public Source resolve(String href, String base) throws TransformerException { + if (href.startsWith("my:")) { + DOMImplementation impl = SVGDOMImplementation.getDOMImplementation(); + String svgNS = SVGDOMImplementation.SVG_NAMESPACE_URI; + Document doc = impl.createDocument(svgNS, "svg", null); + Element element = doc.getDocumentElement(); + element.setAttribute("viewBox", "0 0 20 20"); + element.setAttribute("width", "20pt"); + element.setAttribute("height", "20pt"); + + Element rect = doc.createElementNS(svgNS, "rect"); + rect.setAttribute("x", "5"); + rect.setAttribute("y", "5"); + rect.setAttribute("width", "10"); + rect.setAttribute("height", "10"); + element.appendChild(rect); + + DOMSource src = new DOMSource(doc); + return src; + } else { + return null; + } + } + + }); + + ImageManager manager = fopFactory.getImageManager(); + ImageInfo info = manager.preloadImage(uri, userAgent.getImageSessionContext()); + assertNotNull("ImageInfo must not be null", info); + assertEquals(MimeConstants.MIME_SVG, info.getMimeType()); + assertEquals(uri, info.getOriginalURI()); + assertEquals(20, info.getSize().getWidthPx()); //100 = default viewport size + assertEquals(20, info.getSize().getHeightPx()); + assertEquals(userAgent.getSourceResolution(), info.getSize().getDpiHorizontal(), 0.1); + assertEquals(20000, info.getSize().getWidthMpt()); + assertEquals(20000, info.getSize().getHeightMpt()); + } + public void testWMF() throws Exception { String uri = "test/resources/images/testChart.wmf"; -- 2.39.5