String uri,
TranscoderOutput output)
throws TranscoderException {
if (!(document instanceof SVGOMDocument)) {
throw new TranscoderException(
Messages.formatMessage("notsvg", null));
}
SVGDocument svgDoc = (SVGDocument)document;
// set the alternate stylesheet if any
if (hints.containsKey(KEY_ALTERNATE_STYLESHEET)) {
String stylesheetName = (String)hints.get(KEY_ALTERNATE_STYLESHEET);
((SVGOMDocument)svgDoc).enableAlternateStyleSheet(stylesheetName);
}
SVGSVGElement root = svgDoc.getRootElement();
// initialize the SVG document with the appropriate context
DefaultSVGContext svgCtx = new DefaultSVGContext();
svgCtx.setPixelToMM(userAgent.getPixelToMM());
((SVGOMDocument)document).setSVGContext(svgCtx);
// build the GVT tree
GVTBuilder builder = new GVTBuilder();
ImageRendererFactory rendFactory = new StaticRendererFactory();
BridgeContext ctx = new BridgeContext(userAgent);
GraphicsNode gvtRoot;
try {
gvtRoot = builder.build(ctx, svgDoc);
} catch (BridgeException ex) {
throw new TranscoderException(ex);
}
// get the 'width' and 'height' attributes of the SVG document
float docWidth = (float)ctx.getDocumentSize().getWidth();
float docHeight = (float)ctx.getDocumentSize().getHeight();
ctx = null;
builder = null;
// compute the image's width and height according the hints
float imgWidth = -1;
if (hints.containsKey(KEY_WIDTH)) {
imgWidth = ((Float)hints.get(KEY_WIDTH)).floatValue();
}
float imgHeight = -1;
if (hints.containsKey(KEY_HEIGHT)) {
imgHeight = ((Float)hints.get(KEY_HEIGHT)).floatValue();
}
float width, height;
if (imgWidth > 0 && imgHeight > 0) {
width = imgWidth;
height = imgHeight;
} else if (imgHeight > 0) {
width = (docWidth * imgHeight) / docHeight;
height = imgHeight;
} else if (imgWidth > 0) {
width = imgWidth;
height = (docHeight * imgWidth) / docWidth;
} else {
width = docWidth;
height = docHeight;
}
// compute the preserveAspectRatio matrix
AffineTransform Px;
String ref = null;
try {
ref = new URL(uri).getRef();
} catch (MalformedURLException ex) {
// nothing to do, catched previously
}
try {
Px = ViewBox.getViewTransform(ref, root, width, height);
} catch (BridgeException ex) {
throw new TranscoderException(ex);
}
if (Px.isIdentity() && (width != docWidth || height != docHeight)) {
// The document has no viewBox, we need to resize it by hand.
// we want to keep the document size ratio
float d = Math.max(docWidth, docHeight);
float dd = Math.max(width, height);
float scale = dd/d;
Px = AffineTransform.getScaleInstance(scale, scale);
}
// take the AOI into account if any
if (hints.containsKey(KEY_AOI)) {
Rectangle2D aoi = (Rectangle2D)hints.get(KEY_AOI);
// transform the AOI into the image's coordinate system
aoi = Px.createTransformedShape(aoi).getBounds2D();
AffineTransform Mx = new AffineTransform();
double sx = width / aoi.getWidth();
double sy = height / aoi.getHeight();
Mx.scale(sx, sy);
double tx = -aoi.getX();
double ty = -aoi.getY();
Mx.translate(tx, ty);
// take the AOI transformation matrix into account
// we apply first the preserveAspectRatio matrix
Px.preConcatenate(Mx);
}
// prepare the image to be painted
int w = (int)width;
int h = (int)height;
// paint the SVG document using the bridge package
// create the appropriate renderer
ImageRenderer renderer = rendFactory.createImageRenderer();
renderer.updateOffScreen(w, h);
renderer.setTransform(Px);
renderer.setTree(gvtRoot);
gvtRoot = null; // We're done with it...
try {
// now we are sure that the aoi is the image size
Shape raoi = new Rectangle2D.Float(0, 0, width, height);
// Warning: the renderer's AOI must be in user space
renderer.repaint(Px.createInverse().createTransformedShape(raoi));
BufferedImage rend = renderer.getOffScreen();
renderer = null; // We're done with it...
BufferedImage dest = createImage(w, h);
Graphics2D g2d = GraphicsUtil.createGraphics(dest);
if (hints.containsKey(KEY_BACKGROUND_COLOR)) {
Paint bgcolor = (Paint)hints.get(KEY_BACKGROUND_COLOR);
g2d.setComposite(AlphaComposite.SrcOver);
g2d.setPaint(bgcolor);
g2d.fillRect(0, 0, w, h);
g2d.dispose();
}
if (rend != null) { // might be null if the svg document is empty
g2d.drawRenderedImage(rend, new AffineTransform());
}
rend = null; // We're done with it...
writeImage(dest, output);
} catch (Exception ex) {
throw new TranscoderException(ex);
}
}