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;
/** {@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;
return null;
}
}
- if (info != null) {
+ if (info != null && ImageUtil.hasInputStream(src)) {
ImageUtil.closeQuietly(src); //Image is fully read
}
return info;
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);
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);
+ }
+ }
+
}
}
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;
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.
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";