tkormann 01/08/22 05:17:27 Modified: sources/org/apache/batik/bridge SVGImageElementBridge.java ViewBox.java Log: Bug fix for the <image> element. Now viewBox works as mentioned in the SVG spec. Basically, it's no need to specify a viewBox on the image element. An implicit viewBox is created for a raster image (set to the size of the bitmap) or for a SVG image (set to the viewBox specified on the outermost SVG element of the referenced SVG file). Revision Changes Path 1.24 +34 -19 xml-batik/sources/org/apache/batik/bridge/SVGImageElementBridge.java Index: SVGImageElementBridge.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/bridge/SVGImageElementBridge.java,v retrieving revision 1.23 retrieving revision 1.24 diff -u -r1.23 -r1.24 --- SVGImageElementBridge.java 2001/08/21 15:03:24 1.23 +++ SVGImageElementBridge.java 2001/08/22 12:17:26 1.24 @@ -45,7 +45,7 @@ * Bridge class for the <image> element. * * @author <a href="mailto:[EMAIL PROTECTED]">Thierry Kormann</a> - * @version $Id: SVGImageElementBridge.java,v 1.23 2001/08/21 15:03:24 tkormann Exp $ + * @version $Id: SVGImageElementBridge.java,v 1.24 2001/08/22 12:17:26 tkormann Exp $ */ public class SVGImageElementBridge extends AbstractGraphicsNodeBridge { @@ -171,10 +171,21 @@ return createSVGImageNode(ctx, e, errDoc); } node.setImage(img); - node.setImageBounds(img.getBounds2D()); + Rectangle2D imgBounds = img.getBounds2D(); + node.setImageBounds(imgBounds); Rectangle2D bounds = getImageBounds(ctx, e); - initializeViewport(ctx, e, node, bounds); + // create the implicit viewBox for the raster image. The viewBox for a + // raster image is the size of the image + float [] vb = new float[4]; + vb[0] = 0; // x + vb[1] = 0; // y + vb[2] = (float)imgBounds.getWidth(); // width + vb[3] = (float)imgBounds.getHeight(); // height + + // handles the 'preserveAspectRatio', 'overflow' and 'clip' and sets the + // appropriate AffineTransform to the image node + initializeViewport(ctx, e, node, vb, bounds); return node; } @@ -183,35 +194,37 @@ * Returns a GraphicsNode that represents a svg document as an image. * * @param ctx the bridge context - * @param element the image element + * @param e the image element * @param imgDocument the SVG document that represents the image */ protected static GraphicsNode createSVGImageNode(BridgeContext ctx, - Element element, + Element e, SVGDocument imgDocument) { - // viewport is automatically created by the svg element of the image - SVGSVGElement svgElement = imgDocument.getRootElement(); CompositeGraphicsNode result = new CompositeGraphicsNode(); - CSSStyleDeclaration decl = CSSUtilities.getComputedStyle(element); - UnitProcessor.Context uctx = UnitProcessor.createContext(ctx, element); + CSSStyleDeclaration decl = CSSUtilities.getComputedStyle(e); + UnitProcessor.Context uctx = UnitProcessor.createContext(ctx, e); Rectangle2D r - = CSSUtilities.convertEnableBackground(element, uctx); + = CSSUtilities.convertEnableBackground(e, uctx); if (r != null) { result.setBackgroundEnable(r); } - Rectangle2D bounds = getImageBounds(ctx, element); - svgElement.setAttributeNS(null, SVG_WIDTH_ATTRIBUTE, - String.valueOf(bounds.getWidth())); - svgElement.setAttributeNS(null, SVG_HEIGHT_ATTRIBUTE, - String.valueOf(bounds.getHeight())); - + SVGSVGElement svgElement = imgDocument.getRootElement(); GraphicsNode node = ctx.getGVTBuilder().build(ctx, svgElement); result.getChildren().add(node); - initializeViewport(ctx, element, result, bounds); + // create the implicit viewBox for the SVG image. The viewBox for a + // SVG image is the viewBox of the outermost SVG element of the SVG file + String viewBox = + svgElement.getAttributeNS(null, SVG_VIEW_BOX_ATTRIBUTE); + float [] vb = ViewBox.parseViewBoxAttribute(e, viewBox); + + // handles the 'preserveAspectRatio', 'overflow' and 'clip' and sets the + // appropriate AffineTransform to the image node + Rectangle2D bounds = getImageBounds(ctx, e); + initializeViewport(ctx, e, result, vb, bounds); return result; } @@ -225,20 +238,22 @@ * @param ctx the bridge context * @param e the image element that defines the properties * @param node the graphics node + * @param vb the implicit viewBox definition * @param bounds the bounds of the image element */ protected static void initializeViewport(BridgeContext ctx, Element e, GraphicsNode node, + float [] vb, Rectangle2D bounds) { - // 'viewBox' and 'preserveAspectRatio' float x = (float)bounds.getX(); float y = (float)bounds.getY(); float w = (float)bounds.getWidth(); float h = (float)bounds.getHeight(); + AffineTransform at - = ViewBox.getPreserveAspectRatioTransform(e, w, h); + = ViewBox.getPreserveAspectRatioTransform(e, vb, w, h); at.preConcatenate(AffineTransform.getTranslateInstance(x, y)); node.setTransform(at); 1.6 +43 -10 xml-batik/sources/org/apache/batik/bridge/ViewBox.java Index: ViewBox.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/bridge/ViewBox.java,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- ViewBox.java 2001/04/12 15:14:47 1.5 +++ ViewBox.java 2001/08/22 12:17:26 1.6 @@ -29,7 +29,7 @@ * This class provides convenient methods to handle viewport. * * @author <a href="mailto:[EMAIL PROTECTED]">Thierry Kormann</a> - * @version $Id: ViewBox.java,v 1.5 2001/04/12 15:14:47 tkormann Exp $ + * @version $Id: ViewBox.java,v 1.6 2001/08/22 12:17:26 tkormann Exp $ */ public abstract class ViewBox implements SVGConstants, ErrorConstants { @@ -143,13 +143,12 @@ } /** - * Returns the transformation matrix to apply to initalize a - * viewport or null if the specified viewBox disables the - * rendering of the element. + * Returns the transformation matrix to apply to initalize a viewport or + * null if the specified viewBox disables the rendering of the element. * * @param e the element with a viewbox * @param w the width of the effective viewport - * @param h The height of the effective viewport + * @param h The height of the effective viewport */ public static AffineTransform getPreserveAspectRatioTransform(Element e, float w, @@ -164,14 +163,13 @@ } /** - * Returns the transformation matrix to apply to initalize a - * viewport or null if the specified viewBox disables the - * rendering of the element. + * Returns the transformation matrix to apply to initalize a viewport or + * null if the specified viewBox disables the rendering of the element. * * @param e the element with a viewbox * @param viewBox the viewBox definition * @param w the width of the effective viewport - * @param h The height of the effective viewport + * @param h The height of the effective viewport */ public static AffineTransform getPreserveAspectRatioTransform(Element e, @@ -203,11 +201,46 @@ } /** + * Returns the transformation matrix to apply to initalize a viewport or + * null if the specified viewBox disables the rendering of the element. + * + * @param e the element with a viewbox + * @param vb the viewBox definition as float + * @param w the width of the effective viewport + * @param h The height of the effective viewport + */ + public static + AffineTransform getPreserveAspectRatioTransform(Element e, + float [] vb, + float w, + float h) { + + String aspectRatio + = e.getAttributeNS(null, SVG_PRESERVE_ASPECT_RATIO_ATTRIBUTE); + + // 'preserveAspectRatio' attribute + PreserveAspectRatioParser p = new PreserveAspectRatioParser(); + ViewHandler ph = new ViewHandler(); + p.setPreserveAspectRatioHandler(ph); + try { + p.parse(new StringReader(aspectRatio)); + } catch (ParseException ex) { + throw new BridgeException + (e, ERR_ATTRIBUTE_VALUE_MALFORMED, + new Object[] {SVG_PRESERVE_ASPECT_RATIO_ATTRIBUTE, + aspectRatio, ex}); + } + + return getPreserveAspectRatioTransform(vb, ph.align, ph.meet, w, h); + } + + /** * Parses a viewBox attribute. + * * @param value the viewBox * @return The 4 viewbox components or null. */ - private static float[] parseViewBoxAttribute(Element e, String value) { + public static float[] parseViewBoxAttribute(Element e, String value) { if (value.length() == 0) { return null; } --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]