package org.apache.fop.image.loader.batik;
import java.awt.Dimension;
import java.awt.geom.AffineTransform;
import java.util.Map;
import org.w3c.dom.Document;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.batik.anim.dom.SVGDOMImplementation;
import org.apache.batik.bridge.BridgeContext;
import org.apache.batik.bridge.DefaultFontFamilyResolver;
import org.apache.batik.bridge.GVTBuilder;
import org.apache.batik.bridge.UserAgent;
import org.apache.batik.gvt.GraphicsNode;
import org.apache.xmlgraphics.image.GraphicsConstants;
import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.ImageException;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
import org.apache.xmlgraphics.image.loader.ImageInfo;
import org.apache.xmlgraphics.image.loader.ImageManager;
import org.apache.xmlgraphics.image.loader.ImageProcessingHints;
import org.apache.xmlgraphics.image.loader.ImageSessionContext;
import org.apache.xmlgraphics.image.loader.XMLNamespaceEnabledImageFlavor;
import org.apache.xmlgraphics.image.loader.impl.AbstractImageConverter;
import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D;
import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM;
import org.apache.xmlgraphics.java2d.Graphics2DImagePainter;
import org.apache.xmlgraphics.util.UnitConv;
import org.apache.fop.svg.SimpleSVGUserAgent;
public class ImageConverterSVG2G2D extends AbstractImageConverter {
private static Log log = LogFactory.getLog(ImageConverterSVG2G2D.class);
public Image convert(final Image src, Map hints) throws ImageException {
checkSourceFlavor(src);
final ImageXMLDOM svg = (ImageXMLDOM)src;
if (!SVGDOMImplementation.SVG_NAMESPACE_URI.equals(svg.getRootNamespace())) {
throw new IllegalArgumentException("XML DOM is not in the SVG namespace: "
+ svg.getRootNamespace());
}
float pxToMillimeter = UnitConv.IN2MM / GraphicsConstants.DEFAULT_DPI;
Number ptm = (Number)hints.get(ImageProcessingHints.SOURCE_RESOLUTION);
if (ptm != null) {
pxToMillimeter = (float)(UnitConv.IN2MM / ptm.doubleValue());
}
UserAgent ua = createBatikUserAgent(pxToMillimeter);
GVTBuilder builder = new GVTBuilder();
final ImageManager imageManager = (ImageManager)hints.get(
ImageProcessingHints.IMAGE_MANAGER);
final ImageSessionContext sessionContext = (ImageSessionContext)hints.get(
ImageProcessingHints.IMAGE_SESSION_CONTEXT);
boolean useEnhancedBridgeContext = (imageManager != null && sessionContext != null);
final BridgeContext ctx = (useEnhancedBridgeContext
? new GenericFOPBridgeContext(ua, null, imageManager, sessionContext)
: new BridgeContext(ua));
Document doc = svg.getDocument();
Document clonedDoc = BatikUtil.cloneSVGDocument(doc);
final GraphicsNode root;
try {
root = builder.build(ctx, clonedDoc);
} catch (Exception e) {
throw new ImageException("GVT tree could not be built for SVG graphic", e);
}
int width = svg.getSize().getWidthMpt();
int height = svg.getSize().getHeightMpt();
Dimension imageSize = new Dimension(width, height);
Graphics2DImagePainter painter = createPainter(ctx, root, imageSize);
ImageInfo imageInfo = src.getInfo();
ImageGraphics2D g2dImage = new ImageGraphics2D(imageInfo, painter);
return g2dImage;
}
protected SimpleSVGUserAgent createBatikUserAgent(float pxToMillimeter) {
return new SimpleSVGUserAgent(pxToMillimeter, new AffineTransform(),
DefaultFontFamilyResolver.SINGLETON) {
public void displayMessage(String message) {
log.info(message);
}
public void displayError(Exception e) {
log.error("Error converting SVG to a Java2D graphic", e);
}
public void displayError(String message) {
log.error(message);
}
};
}
protected Graphics2DImagePainter createPainter(
BridgeContext ctx, GraphicsNode root, Dimension imageSize) {
return new Graphics2DImagePainterImpl(root, ctx, imageSize);
}
public ImageFlavor getSourceFlavor() {
return XMLNamespaceEnabledImageFlavor.SVG_DOM;
}
public ImageFlavor getTargetFlavor() {
return ImageFlavor.GRAPHICS2D;
}
}