deweese 2003/06/05 03:03:17 Modified: samples/extensions multi.svg sources/org/apache/batik/extension/svg BatikMultiImageElementBridge.java MultiResGraphicsNode.java Added: samples sydney.svg samples/extensions/opera opera-subImage.svg opera-subImageRef.svg samples/tests/resources/images operaBridge.jpg operaSteps.jpg operaWalk.jpg Removed: samples/extensions/opera opera.svg Log: 1) The 'multiImage' element now implements both subImage and subImageRef. So resolution selected content can be included inline (see samples/extensions/opera-subImage.svg for an example). 2) New sample file: 'samples/sydney.svg' - layout images interactively. Revision Changes Path 1.1 xml-batik/samples/sydney.svg Index: sydney.svg =================================================================== <?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> <svg width="655" height="600" viewBox="0 0 655 600" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" > <script type="text/ecmascript"> <![CDATA[ var svgns = "http://www.w3.org/2000/svg"; var xlinkns = "http://www.w3.org/1999/xlink"; var dragNode; var scaleNode; var scaleTgt; var dx; var dy; var imgGroup = document.getElementById("imgGroup") var filter = imgGroup.getAttribute("style"); var dragged=false; function dragOn(evt) { dragNode = evt.target; var currX = parseFloat(dragNode.getAttribute("x")); var currY = parseFloat(dragNode.getAttribute("y")); dx = evt.getClientX()-currX; dy = evt.getClientY()-currY; dragged=false; } function scaleOn(evt) { scaleNode = scaleTgt; var cW = parseFloat(scaleNode.getAttribute("width")); var cH = parseFloat(scaleNode.getAttribute("height")); dx = evt.getClientX()-cW; dy = evt.getClientY()-cH; dragged=false; } function dragScaleOff() { if (dragged) imgGroup.setAttribute("style",filter); if (dragNode != null) { if (dragNode != imgGroup.lastChild) { imgGroup.appendChild(dragNode); } dragNode = null; } if (scaleNode != null) { if (scaleNode != imgGroup.lastChild) { imgGroup.appendChild(scaleNode); } scaleNode = null; } } function dragScaleImgBg(evt) { if ((dragNode == null) && (scaleNode == null)) { hideOverlay(); return; } dragScaleImg(evt); } function dragScaleImg(evt) { if ((dragNode == null) && (scaleNode == null)) return; dragged = true; imgGroup.setAttribute("style",""); if (dragNode != null) { if (dragNode != imgGroup.lastChild) imgGroup.appendChild(dragNode); dragNode.setAttribute("x",""+(evt.getClientX()-dx)); dragNode.setAttribute("y",""+(evt.getClientY()-dy)); updateOverlay(dragNode); } if (scaleNode != null) { if (scaleNode != imgGroup.lastChild) imgGroup.appendChild(scaleNode); var cW = parseFloat(scaleNode.getAttribute("width")); var cH = parseFloat(scaleNode.getAttribute("height")); var ar = cW/cH; var nW = evt.getClientX()-dx; var nH = evt.getClientY()-dy; if (nW/nH < ar) { nW = ar*nH; } else { nH = nW/ar; } scaleNode.setAttribute("width", ""+nW); scaleNode.setAttribute("height",""+nH); updateOverlay(scaleNode); } } function updateOverlay(tgt) { var cX = parseFloat(tgt.getAttribute("x")); var cY = parseFloat(tgt.getAttribute("y")); var cW = parseFloat(tgt.getAttribute("width")); var cH = parseFloat(tgt.getAttribute("height")); var over = document.getElementById("overlay"); over.setAttribute("transform","translate("+(cX+cW-1)+","+(cY+cH-1)+")"); scaleTgt = tgt; } function showOverlay(evt) { if ((dragNode != null) || (scaleNode != null)) return; var tgt = evt.target; updateOverlay(tgt); var over = document.getElementById("overlay"); over.setAttribute("visibility","visible"); } function hideOverlay() { if ((dragNode != null) || (scaleNode != null)) return; var over = document.getElementById("overlay"); over.setAttribute("visibility","hidden"); } ]]></script> <filter id="merge" filterUnits="objectBoundingBox" > <feMorphology operator="dilate" radius="10" in="SourceAlpha" /> <feGaussianBlur stdDeviation="4" /> <feOffset dx="3" dy="3"/> <feComponentTransfer result="shadow"> <feFuncA type="linear" slope=".6" intercept="0" /> </feComponentTransfer> <feComposite operator="over" in="SourceGraphic" in2="shadow"/> </filter> <rect fill="#88A" x="0%" y="0%" width="100%" height="100%"/> <text x="302" y="47" font-size="24" fill="#448" >Click and drag to move images</text> <text x="300" y="45" font-size="24" fill="white" >Click and drag to move images</text> <rect fill="none" x="0%" y="0%" width="100%" height="100%" pointer-events="fill" onmousedown="dragScaleOff()" onmouseup="dragScaleOff()" onmousemove="dragScaleImgBg(evt)"/> <g id="imgGroup" style="filter:url(#merge)" onmousedown="dragOn(evt)" onmouseup="dragScaleOff()" onmousemove="dragScaleImg(evt)" onmouseover="showOverlay(evt)"> <image x="25" y="315" width="360" height="240" xlink:href="tests/resources/images/operaSteps.jpg"/> <image x="50" y="40" width="200" height="300" xlink:href="tests/resources/images/operaWalk.jpg"/> <image x="270" y="200" width="360" height="240" xlink:href="tests/resources/images/operaBridge.jpg"/> </g> <g id="overlay" visibility="hidden" onmousedown="scaleOn(evt)" onmouseup="dragScaleOff()" onmousemove="dragScaleImg(evt)"> <path fill="darkgrey" stroke="white" d="M0,0 h-20 l20,-20 z M-12,-3 l9-9 z M-6,-3 l3-3z"/> </g> </svg> 1.6 +13 -13 xml-batik/samples/extensions/multi.svg Index: multi.svg =================================================================== RCS file: /home/cvs/xml-batik/samples/extensions/multi.svg,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- multi.svg 28 May 2003 18:45:59 -0000 1.5 +++ multi.svg 5 Jun 2003 10:03:16 -0000 1.6 @@ -2,20 +2,20 @@ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> -<!-- ====================================================================== --> -<!-- Copyright (C) The Apache Software Foundation. All rights reserved. --> -<!-- --> -<!-- This software is published under the terms of the Apache Software --> -<!-- License version 1.1, a copy of which has been included with this --> -<!-- distribution in the LICENSE file. --> -<!-- ====================================================================== --> +<!-- =================================================================== --> +<!-- Copyright (C) The Apache Software Foundation. All rights reserved. --> +<!-- --> +<!-- This software is published under the terms of the Apache Software --> +<!-- License version 1.1, a copy of which has been included with this --> +<!-- distribution in the LICENSE file. --> +<!-- =================================================================== --> -<!-- ====================================================================== --> -<!-- Tests 'multiImage' element with just 'subImageRef' children. --> -<!-- --> -<!-- @author [EMAIL PROTECTED] --> +<!-- =================================================================== --> +<!-- Tests 'multiImage' element with just 'subImageRef' children. --> +<!-- --> +<!-- @author [EMAIL PROTECTED] --> <!-- @version $Id$ --> -<!-- ====================================================================== --> +<!-- =================================================================== --> <svg width="450" height="500" xml:space="preserve" viewBox="0 0 450 500" 1.1 xml-batik/samples/extensions/opera/opera-subImage.svg Index: opera-subImage.svg =================================================================== <?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> <!-- =================================================================== --> <!-- Copyright (C) The Apache Software Foundation. All rights reserved. --> <!-- --> <!-- This software is published under the terms of the Apache Software --> <!-- License version 1.1, a copy of which has been included with this --> <!-- distribution in the LICENSE file. --> <!-- =================================================================== --> <!-- =================================================================== --> <!-- Tests 'multiImage' element with a combination of 'subImage' and --> <!-- 'subImageRef' children. --> <!-- --> <!-- @author [EMAIL PROTECTED] --> <!-- @version $Id: opera-subImage.svg,v 1.1 2003/06/05 10:03:16 deweese Exp $ --> <!-- =================================================================== --> <svg width="640" height="480" viewBox="0 0 640 480" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <style type="text/css"><![CDATA[ .overlay { fill:none; stroke-width:4; } ]]></style> <symbol id="opera" viewBox="0 0 90 135"> <multiImage x="0" y="0" width="90" height="135" xmlns="http://xml.apache.org/batik/ext"> <subImageRef xlink:href="multires/opera-3-0-0.jpg" min-pixel-size="1"/> <subImage max-pixel-size="1"> <svg width="100%" height="100%" viewBox="0 0 180 270"> <multiImage x="0" y="0" width="180" height="180" xmlns="http://xml.apache.org/batik/ext"> <subImageRef xlink:href="multires/opera-2-0-0.jpg" min-pixel-size="1"/> <subImage max-pixel-size="1"> <svg width="100%" height="100%" viewBox="0 0 360 360"> <multiImage x="0" y="0" width="180" height="180" xmlns="http://xml.apache.org/batik/ext"> <subImageRef xlink:href="multires/opera-1-0-0.jpg" min-pixel-size="1"/> <subImage max-pixel-size="1"> <svg width="100%" height="100%" viewBox="0 0 360 360"> <image x="0" y="0" width="180" height="180" xlink:href="multires/opera-0-0-0.jpg"/> <image x="180" y="0" width="180" height="180" xlink:href="multires/opera-0-1-0.jpg"/> <image x="0" y="180" width="180" height="180" xlink:href="multires/opera-0-0-1.jpg"/> <image x="180" y="180" width="180" height="180" xlink:href="multires/opera-0-1-1.jpg"/> <rect class="overlay" stroke="#F00" x="0" y="0" width="180" height="180"/> <rect class="overlay" stroke="#F00" x="180" y="0" width="180" height="180"/> <rect class="overlay" stroke="#F00" x="0" y="180" width="180" height="180"/> <rect class="overlay" stroke="#F00" x="180" y="180" width="180" height="180"/> </svg> </subImage> </multiImage> <multiImage x="180" y="0" width="180" height="180" xmlns="http://xml.apache.org/batik/ext"> <subImageRef xlink:href="multires/opera-1-1-0.jpg" min-pixel-size="1"/> <subImage max-pixel-size="1"> <svg width="100%" height="100%" viewBox="0 0 360 360"> <image x="0" y="0" width="180" height="180" xlink:href="multires/opera-0-2-0.jpg"/> <image x="180" y="0" width="180" height="180" xlink:href="multires/opera-0-3-0.jpg"/> <image x="0" y="180" width="180" height="180" xlink:href="multires/opera-0-2-1.jpg"/> <image x="180" y="180" width="180" height="180" xlink:href="multires/opera-0-3-1.jpg"/> <rect class="overlay" stroke="#F00" x="0" y="0" width="180" height="180"/> <rect class="overlay" stroke="#F00" x="180" y="0" width="180" height="180"/> <rect class="overlay" stroke="#F00" x="0" y="180" width="180" height="180"/> <rect class="overlay" stroke="#F00" x="180" y="180" width="180" height="180"/> </svg> </subImage> </multiImage> <multiImage x="0" y="180" width="180" height="180" xmlns="http://xml.apache.org/batik/ext"> <subImageRef xlink:href="multires/opera-1-0-1.jpg" min-pixel-size="1"/> <subImage max-pixel-size="1"> <svg width="100%" height="100%" viewBox="0 0 360 360"> <image x="0" y="0" width="180" height="180" xlink:href="multires/opera-0-0-2.jpg"/> <image x="180" y="0" width="180" height="180" xlink:href="multires/opera-0-1-2.jpg"/> <image x="0" y="180" width="180" height="180" xlink:href="multires/opera-0-0-3.jpg"/> <image x="180" y="180" width="180" height="180" xlink:href="multires/opera-0-1-3.jpg"/> <rect class="overlay" stroke="#F00" x="0" y="0" width="180" height="180"/> <rect class="overlay" stroke="#F00" x="180" y="0" width="180" height="180"/> <rect class="overlay" stroke="#F00" x="0" y="180" width="180" height="180"/> <rect class="overlay" stroke="#F00" x="180" y="180" width="180" height="180"/> </svg> </subImage> </multiImage> <multiImage x="180" y="180" width="180" height="180" xmlns="http://xml.apache.org/batik/ext"> <subImageRef xlink:href="multires/opera-1-1-1.jpg" min-pixel-size="1"/> <subImage max-pixel-size="1"> <svg width="100%" height="100%" viewBox="0 0 360 360"> <image x="0" y="0" width="180" height="180" xlink:href="multires/opera-0-2-2.jpg"/> <image x="180" y="0" width="180" height="180" xlink:href="multires/opera-0-3-2.jpg"/> <image x="0" y="180" width="180" height="180" xlink:href="multires/opera-0-2-3.jpg"/> <image x="180" y="180" width="180" height="180" xlink:href="multires/opera-0-3-3.jpg"/> <rect class="overlay" stroke="#F00" x="0" y="0" width="180" height="180"/> <rect class="overlay" stroke="#F00" x="180" y="0" width="180" height="180"/> <rect class="overlay" stroke="#F00" x="0" y="180" width="180" height="180"/> <rect class="overlay" stroke="#F00" x="180" y="180" width="180" height="180"/> </svg> </subImage> </multiImage> <rect class="overlay" stroke="#FF0" x="0" y="0" width="180" height="180"/> <rect class="overlay" stroke="#FF0" x="180" y="0" width="180" height="180"/> <rect class="overlay" stroke="#FF0" x="0" y="180" width="180" height="180"/> <rect class="overlay" stroke="#FF0" x="180" y="180" width="180" height="180"/> </svg> </subImage> </multiImage> <multiImage x="0" y="180" width="180" height="90" xmlns="http://xml.apache.org/batik/ext"> <subImageRef xlink:href="multires/opera-2-0-1.jpg" min-pixel-size="1"/> <subImage max-pixel-size="1"> <svg width="100%" height="100%" viewBox="0 0 360 180"> <multiImage x="0" y="0" width="180" height="180" xmlns="http://xml.apache.org/batik/ext"> <subImageRef xlink:href="multires/opera-1-0-2.jpg" min-pixel-size="1"/> <subImage max-pixel-size="1"> <svg width="100%" height="100%" viewBox="0 0 360 360"> <image x="0" y="0" width="180" height="180" xlink:href="multires/opera-0-0-4.jpg"/> <image x="180" y="0" width="180" height="180" xlink:href="multires/opera-0-1-4.jpg"/> <image x="0" y="180" width="180" height="180" xlink:href="multires/opera-0-0-5.jpg"/> <image x="180" y="180" width="180" height="180" xlink:href="multires/opera-0-1-5.jpg"/> <rect class="overlay" stroke="#F00" x="0" y="0" width="180" height="180"/> <rect class="overlay" stroke="#F00" x="180" y="0" width="180" height="180"/> <rect class="overlay" stroke="#F00" x="0" y="180" width="180" height="180"/> <rect class="overlay" stroke="#F00" x="180" y="180" width="180" height="180"/> </svg> </subImage> </multiImage> <multiImage x="180" y="0" width="180" height="180" xmlns="http://xml.apache.org/batik/ext"> <subImageRef xlink:href="multires/opera-1-1-2.jpg" min-pixel-size="1"/> <subImage max-pixel-size="1"> <svg width="100%" height="100%" viewBox="0 0 360 360"> <image x="0" y="0" width="180" height="180" xlink:href="multires/opera-0-2-4.jpg"/> <image x="180" y="0" width="180" height="180" xlink:href="multires/opera-0-3-4.jpg"/> <image x="0" y="180" width="180" height="180" xlink:href="multires/opera-0-2-5.jpg"/> <image x="180" y="180" width="180" height="180" xlink:href="multires/opera-0-3-5.jpg"/> <rect class="overlay" stroke="#F00" x="0" y="0" width="180" height="180"/> <rect class="overlay" stroke="#F00" x="180" y="0" width="180" height="180"/> <rect class="overlay" stroke="#F00" x="0" y="180" width="180" height="180"/> <rect class="overlay" stroke="#F00" x="180" y="180" width="180" height="180"/> </svg> </subImage> </multiImage> <rect class="overlay" stroke="#FF0" x="0" y="0" width="180" height="180"/> <rect class="overlay" stroke="#FF0" x="180" y="0" width="180" height="180"/> </svg> </subImage> </multiImage> <rect class="overlay" stroke="#0F0" x="0" y="0" width="180" height="180"/> <rect class="overlay" stroke="#0F0" x="0" y="180" width="180" height="90"/> </svg> </subImage> </multiImage> <rect class="overlay" stroke="#00F" x="0" y="0" width="90" height="135"/> </symbol>> <use x="165" y="50" width="270" height="405" xlink:href="#opera"/> <use x="10" y="50" width="135" height="202.5" xlink:href="#opera"/> <use x="43.75" y="272.5" width="67.5" height="101.25" xlink:href="#opera"/> </svg> 1.1 xml-batik/samples/extensions/opera/opera-subImageRef.svg Index: opera-subImageRef.svg =================================================================== <?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> <!-- =================================================================== --> <!-- Copyright (C) The Apache Software Foundation. All rights reserved. --> <!-- --> <!-- This software is published under the terms of the Apache Software --> <!-- License version 1.1, a copy of which has been included with this --> <!-- distribution in the LICENSE file. --> <!-- =================================================================== --> <!-- =================================================================== --> <!-- Tests 'multiImage' element with 'subImageRef' children that --> <!-- reference external SVG files. --> <!-- --> <!-- @author [EMAIL PROTECTED] --> <!-- @version $Id: opera-subImageRef.svg,v 1.1 2003/06/05 10:03:16 deweese Exp $ --> <!-- =================================================================== --> <svg width="640" height="480" viewBox="0 0 640 480" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <image x="165" y="50" width="270" height="405" xlink:href="opera-3-0-0.svg" /> <image x="10" y="50" width="135" height="202.5" xlink:href="opera-3-0-0.svg" /> <image x="43.75" y="272.5" width="67.5" height="101.25" xlink:href="opera-3-0-0.svg" /> </svg> 1.1 xml-batik/samples/tests/resources/images/operaBridge.jpg <<Binary file>> 1.1 xml-batik/samples/tests/resources/images/operaSteps.jpg <<Binary file>> 1.1 xml-batik/samples/tests/resources/images/operaWalk.jpg <<Binary file>> 1.10 +158 -32 xml-batik/sources/org/apache/batik/extension/svg/BatikMultiImageElementBridge.java Index: BatikMultiImageElementBridge.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/extension/svg/BatikMultiImageElementBridge.java,v retrieving revision 1.9 retrieving revision 1.10 diff -u -r1.9 -r1.10 --- BatikMultiImageElementBridge.java 28 May 2003 14:40:57 -0000 1.9 +++ BatikMultiImageElementBridge.java 5 Jun 2003 10:03:16 -0000 1.10 @@ -9,25 +9,32 @@ package org.apache.batik.extension.svg; import java.awt.Dimension; +import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; import java.util.Collection; import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import org.apache.batik.ext.awt.image.renderable.ClipRable8Bit; +import org.apache.batik.ext.awt.image.renderable.Filter; import org.apache.batik.bridge.Bridge; import org.apache.batik.bridge.BridgeContext; import org.apache.batik.bridge.BridgeException; import org.apache.batik.bridge.CSSUtilities; import org.apache.batik.bridge.SVGImageElementBridge; import org.apache.batik.bridge.SVGUtilities; +import org.apache.batik.bridge.Viewport; import org.apache.batik.dom.svg.SVGOMElement; import org.apache.batik.dom.svg.XMLBaseSupport; import org.apache.batik.dom.util.XLinkSupport; import org.apache.batik.gvt.GraphicsNode; import org.apache.batik.gvt.ImageNode; import org.apache.batik.util.ParsedURL; +import org.w3c.dom.Attr; +import org.w3c.dom.Document; import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; /** @@ -99,7 +106,35 @@ Rectangle2D b = getImageBounds(ctx, e); - List uris = new LinkedList(); + // 'transform' + AffineTransform at = null; + String s = e.getAttribute(SVG_TRANSFORM_ATTRIBUTE); + if (s.length() != 0) + at = SVGUtilities.convertTransform(e, SVG_TRANSFORM_ATTRIBUTE, s); + else + at = new AffineTransform(); + + at.translate(b.getX(), b.getY()); + imgNode.setTransform(at); + + // 'visibility' + imgNode.setVisible(CSSUtilities.convertVisibility(e)); + + Rectangle2D clip; + clip = new Rectangle2D.Double(0,0,b.getWidth(), b.getHeight()); + Filter filter = imgNode.getGraphicsNodeRable(true); + imgNode.setClip(new ClipRable8Bit(filter, clip)); + + // 'enable-background' + Rectangle2D r = CSSUtilities.convertEnableBackground(e); + if (r != null) { + imgNode.setBackgroundEnable(r); + } + ctx.openViewport(e, new MultiImageElementViewport + ((float)b.getWidth(), (float)b.getHeight())); + + + List elems = new LinkedList(); List minDim = new LinkedList(); List maxDim = new LinkedList(); @@ -108,19 +143,22 @@ continue; Element se = (Element)n; - if (!(se.getNamespaceURI().equals(BATIK_EXT_NAMESPACE_URI)) || - !(se.getLocalName().equals(BATIK_EXT_SUB_IMAGE_REF_TAG))) + if (!se.getNamespaceURI().equals(BATIK_EXT_NAMESPACE_URI)) continue; - - addInfo(se, uris, minDim, maxDim, b); + if (se.getLocalName().equals(BATIK_EXT_SUB_IMAGE_TAG)) { + addInfo(se, elems, minDim, maxDim, b); + } + if (se.getLocalName().equals(BATIK_EXT_SUB_IMAGE_REF_TAG)) { + addRefInfo(se, elems, minDim, maxDim, b); + } } - Dimension [] mindary = new Dimension[uris.size()]; - Dimension [] maxdary = new Dimension[uris.size()]; - ParsedURL [] uary = new ParsedURL[uris.size()]; + Dimension [] mindary = new Dimension[elems.size()]; + Dimension [] maxdary = new Dimension[elems.size()]; + Element [] elemary = new Element [elems.size()]; Iterator mindi = minDim.iterator(); Iterator maxdi = maxDim.iterator(); - Iterator ui = uris.iterator(); + Iterator ei = elems.iterator(); int n=0; while (mindi.hasNext()) { Dimension minD = (Dimension)mindi.next(); @@ -135,33 +173,20 @@ } } for (int j=n; j>i; j--) { - uary[j] = uary[j-1]; + elemary[j] = elemary[j-1]; mindary[j] = mindary[j-1]; maxdary[j] = maxdary[j-1]; } - uary [i] = (ParsedURL)ui.next(); + elemary[i] = (Element)ei.next(); mindary[i] = minD; maxdary[i] = maxD; n++; } - // System.out.println("Bounds: " + bounds); - // System.out.println("ImgB: " + imgBounds); - - - GraphicsNode node = new MultiResGraphicsNode(e, b, uary, - mindary, maxdary); - - // 'transform' - String s = e.getAttributeNS(null, SVG_TRANSFORM_ATTRIBUTE); - if (s.length() != 0) { - node.setTransform - (SVGUtilities.convertTransform(e, SVG_TRANSFORM_ATTRIBUTE, s)); - } - // 'visibility' - imgNode.setVisible(CSSUtilities.convertVisibility(e)); - + GraphicsNode node = new MultiResGraphicsNode(e, clip, elemary, + mindary, maxdary, + ctx); imgNode.setImage(node); return imgNode; @@ -174,6 +199,18 @@ return false; } + public void buildGraphicsNode(BridgeContext ctx, + Element e, + GraphicsNode node) { + if (ctx.isDynamic()) { + initializeDynamicSupport(ctx, e, node); + } + // Handle children elements such as <title> + //SVGUtilities.bridgeChildren(ctx, e); + //super.buildGraphicsNode(ctx, e, node); + ctx.closeViewport(e); + } + /** * This method is invoked during the build phase if the document * is dynamic. The responsability of this method is to ensure that @@ -192,22 +229,78 @@ ((SVGOMElement)e).setSVGContext(this); } - protected void addInfo(Element e, Collection uris, + /** + * Disposes this BridgeUpdateHandler and releases all resources. + */ + public void dispose() { + ctx.removeViewport(e); + super.dispose(); + } + + protected void addInfo(Element e, Collection elems, Collection minDim, Collection maxDim, Rectangle2D bounds) { + Document doc = e.getOwnerDocument(); + Element gElem = doc.createElementNS(SVG_NAMESPACE_URI, + SVG_G_TAG); + NamedNodeMap attrs = e.getAttributes(); + int len = attrs.getLength(); + for (int i = 0; i < len; i++) { + Attr attr = (Attr)attrs.item(i); + gElem.setAttributeNS(attr.getNamespaceURI(), + attr.getName(), + attr.getValue()); + } + // move the children from <subImage> to the <g> element + for (Node n = e.getFirstChild(); + n != null; + n = e.getFirstChild()) { + gElem.appendChild(n); + } + e.appendChild(gElem); + elems.add(gElem); + minDim.add(getElementMinPixel(e, bounds)); + maxDim.add(getElementMaxPixel(e, bounds)); + } + + protected void addRefInfo(Element e, Collection elems, + Collection minDim, Collection maxDim, + Rectangle2D bounds) { String uriStr = XLinkSupport.getXLinkHref(e); if (uriStr.length() == 0) { throw new BridgeException(e, ERR_ATTRIBUTE_MISSING, new Object[] {"xlink:href"}); } - String baseURI = XMLBaseSupport.getCascadedXMLBase(e); ParsedURL purl; if (baseURI == null) purl = new ParsedURL(uriStr); else purl = new ParsedURL(baseURI, uriStr); - uris.add(purl); + Document doc = e.getOwnerDocument(); + Element imgElem = doc.createElementNS(SVG_NAMESPACE_URI, + SVG_IMAGE_TAG); + imgElem.setAttributeNS(XLinkSupport.XLINK_NAMESPACE_URI, + "href", purl.toString()); + // move the attributes from <subImageRef> to the <image> element + NamedNodeMap attrs = e.getAttributes(); + int len = attrs.getLength(); + for (int i = 0; i < len; i++) { + Attr attr = (Attr)attrs.item(i); + imgElem.setAttributeNS(attr.getNamespaceURI(), + attr.getName(), + attr.getValue()); + } + String s; + s = e.getAttribute("x"); + if (s.length() == 0) imgElem.setAttribute("x", "0"); + s = e.getAttribute("y"); + if (s.length() == 0) imgElem.setAttribute("y", "0"); + s = e.getAttribute("width"); + if (s.length() == 0) imgElem.setAttribute("width", "100%"); + s = e.getAttribute("height"); + if (s.length() == 0) imgElem.setAttribute("height", "100%"); + e.appendChild(imgElem); + elems.add(imgElem); - minDim.add(getElementMinPixel(e, bounds)); maxDim.add(getElementMaxPixel(e, bounds)); } @@ -240,5 +333,38 @@ return new Dimension((int)(bounds.getWidth()/xPixSz+0.5), (int)(bounds.getHeight()/yPixSz+0.5)); + } + + /** + * A viewport defined an <svg> element. + */ + public static class MultiImageElementViewport implements Viewport { + private float width; + private float height; + + /** + * Constructs a new viewport with the specified <tt>SVGSVGElement</tt>. + * @param e the SVGSVGElement that defines this viewport + * @param w the width of the viewport + * @param h the height of the viewport + */ + public MultiImageElementViewport(float w, float h) { + this.width = w; + this.height = h; + } + + /** + * Returns the width of this viewport. + */ + public float getWidth(){ + return width; + } + + /** + * Returns the height of this viewport. + */ + public float getHeight(){ + return height; + } } } 1.7 +59 -188 xml-batik/sources/org/apache/batik/extension/svg/MultiResGraphicsNode.java Index: MultiResGraphicsNode.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/extension/svg/MultiResGraphicsNode.java,v retrieving revision 1.6 retrieving revision 1.7 diff -u -r1.6 -r1.7 --- MultiResGraphicsNode.java 30 May 2003 01:07:15 -0000 1.6 +++ MultiResGraphicsNode.java 5 Jun 2003 10:03:16 -0000 1.7 @@ -47,46 +47,36 @@ extends AbstractGraphicsNode implements SVGConstants { SoftReference [] srcs; - ParsedURL [] srcURLs; + Element [] srcElems; Dimension [] minSz; Dimension [] maxSz; Rectangle2D bounds; - UserAgent userAgent; - DocumentLoader loader; BridgeContext ctx; Element multiImgElem; - /** - * The error code when a required attribute is missing. - * {0} = the name of the attribute - */ - public static final String ERR_ATTRIBUTE_MISSING - = "attribute.missing"; - - public MultiResGraphicsNode(Element multiImgElem, Rectangle2D bounds, - ParsedURL [] srcURLs, + Element [] srcElems, Dimension [] minSz, - Dimension [] maxSz) { + Dimension [] maxSz, + BridgeContext ctx) { + this.multiImgElem = multiImgElem; - this.srcURLs = new ParsedURL[srcURLs.length]; - this.minSz = new Dimension[srcURLs.length]; - this.maxSz = new Dimension[srcURLs.length]; - - for (int i=0; i<srcURLs.length; i++) { - this.srcURLs[i] = srcURLs[i]; - this.minSz[i] = minSz[i]; - this.maxSz[i] = maxSz[i]; + this.srcElems = new Element [srcElems.length]; + this.minSz = new Dimension[srcElems.length]; + this.maxSz = new Dimension[srcElems.length]; + this.ctx = ctx; + + for (int i=0; i<srcElems.length; i++) { + this.srcElems[i] = srcElems[i]; + this.minSz[i] = minSz[i]; + this.maxSz[i] = maxSz[i]; } - this.srcs = new SoftReference[srcURLs.length]; + this.srcs = new SoftReference[srcElems.length]; this.bounds = bounds; - userAgent = new UserAgentAdapter(); - loader = new DocumentLoader(userAgent); - ctx = new BridgeContext(userAgent, loader); } /** @@ -95,12 +85,13 @@ * @param g2d the Graphics2D to use */ public void primitivePaint(Graphics2D g2d) { - // System.err.println("PrimPaint: " + this); // get the current affine transform AffineTransform at = g2d.getTransform(); - double scx = Math.sqrt(at.getShearX()*at.getShearX()+ + double scx = Math.sqrt(at.getShearY()*at.getShearY()+ at.getScaleX()*at.getScaleX()); + double scy = Math.sqrt(at.getShearX()*at.getShearX()+ + at.getScaleY()*at.getScaleY()); GraphicsNode gn = null; int idx =-1; @@ -133,7 +124,43 @@ if (gn == null) return; - // Rectangle2D gnBounds = gn.getBounds(); + // This makes sure that the image 'pushes out' to it's pixel + // bounderies. + Rectangle2D gnBounds = gn.getBounds(); + double gnDevW = gnBounds.getWidth()*scx; + double gnDevH = gnBounds.getHeight()*scy; + double gnDevX = gnBounds.getX()*scx; + double gnDevY = gnBounds.getY()*scy; + double gnDevX0, gnDevX1, gnDevY0, gnDevY1; + if (gnDevW < 0) { + gnDevX0 = gnDevX+gnDevW; + gnDevX1 = gnDevX; + } else { + gnDevX0 = gnDevX; + gnDevX1 = gnDevX+gnDevW; + } + if (gnDevH < 0) { + gnDevY0 = gnDevY+gnDevH; + gnDevY1 = gnDevY; + } else { + gnDevY0 = gnDevY; + gnDevY1 = gnDevY+gnDevH; + } + // This calculate the width/height in pixels given 'worst + // case' assessment. + gnDevW = (int)(Math.ceil(gnDevX1)-Math.floor(gnDevX0)); + gnDevH = (int)(Math.ceil(gnDevY1)-Math.floor(gnDevY0)); + scx = (gnDevW/gnBounds.getWidth())/scx; + scy = (gnDevH/gnBounds.getHeight())/scy; + + // This scales things up slightly so our edges fall on device + // pixel boundries. + AffineTransform nat = g2d.getTransform(); + nat = new AffineTransform(nat.getScaleX()*scx, nat.getShearY()*scx, + nat.getShearX()*scy, nat.getScaleY()*scy, + nat.getTranslateX(), nat.getTranslateY()); + g2d.setTransform(nat); + // double sx = bounds.getWidth()/sizes[idx].getWidth(); // double sy = bounds.getHeight()/sizes[idx].getHeight(); // System.err.println("Scale: [" + sx + ", " + sy + "]"); @@ -199,170 +226,14 @@ } try { - SVGDocument svgDoc = (SVGDocument)loader.loadDocument - (srcURLs[idx].toString()); - - GraphicsNode gn; - gn = createSVGImageNode(ctx, multiImgElem, - bounds, svgDoc); - srcs[idx] = new SoftReference(gn); - return gn; - } catch (Exception ex) { /* ex.printStackTrace(); */ } - - try { + GVTBuilder builder = ctx.getGVTBuilder(); GraphicsNode gn; - gn = createRasterImageNode(ctx, multiImgElem, - bounds, srcURLs[idx]); + gn = builder.build(ctx, srcElems[idx]); srcs[idx] = new SoftReference(gn); return gn; - } catch (Exception ex) { /* ex.printStackTrace(); */ } + } catch (Exception ex) { ex.printStackTrace(); } return null; - } - - - /** - * Returns a GraphicsNode that represents an raster image in JPEG or PNG - * format. - * - * @param ctx the bridge context - * @param e the image element - * @param uriStr the uri of the image - */ - protected static GraphicsNode createRasterImageNode(BridgeContext ctx, - Element e, - Rectangle2D bounds, - ParsedURL purl) { - - RasterImageNode node = new RasterImageNode(); - - ImageTagRegistry reg = ImageTagRegistry.getRegistry(); - Filter img = reg.readURL(purl); - Object obj = img.getProperty - (SVGBrokenLinkProvider.SVG_BROKEN_LINK_DOCUMENT_PROPERTY); - if ((obj != null) && (obj instanceof SVGDocument)) { - // Ok so we are dealing with a broken link. - return createSVGImageNode(ctx, e, bounds, (SVGDocument)obj); - } - node.setImage(img); - Rectangle2D imgBounds = img.getBounds2D(); - - // 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 - - // System.err.println("Bounds: " + bounds); - // System.err.println("ImgB: " + imgBounds); - // handles the 'preserveAspectRatio', 'overflow' and 'clip' and - // sets the appropriate AffineTransform to the image node - initializeViewport(e, node, vb, bounds); - - return node; - } - - /** - * Returns a GraphicsNode that represents a svg document as an image. - * - * @param ctx the bridge context - * @param e the image element - * @param bounds the bounds for this graphicsNode - * @param imgDocument the SVG document that represents the image - */ - protected static GraphicsNode createSVGImageNode(BridgeContext ctx, - Element e, - Rectangle2D bounds, - SVGDocument imgDocument) { - - CompositeGraphicsNode result = new CompositeGraphicsNode(); - - Rectangle2D r = CSSUtilities.convertEnableBackground(e); - if (r != null) { - result.setBackgroundEnable(r); - } - - SVGSVGElement svgElement = imgDocument.getRootElement(); - GVTBuilder builder = new GVTBuilder(); - GraphicsNode node = builder.build(ctx, imgDocument); - // HACK: remove the clip set by the SVGSVGElement as the overflow - // and clip properties must be ignored. The clip will be set later - // using the overflow and clip of the <image> element. - node.setClip(null); - result.getChildren().add(node); - - // 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 - - // System.err.println("Bounds: " + bounds); - // System.err.println("ViewBox: " + viewBox); - initializeViewport(e, result, vb, bounds); - - return result; - } - - /** - * Initializes according to the specified element, the specified graphics - * node with the specified bounds. This method takes into account the - * 'viewBox', 'preserveAspectRatio', and 'clip' properties. According to - * those properties, a AffineTransform and a clip is set. - * - * @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(Element e, - GraphicsNode node, - float [] vb, - Rectangle2D bounds) { - - 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, vb, w, h); - // System.err.println("VP Affine: " + at); - at.preConcatenate(AffineTransform.getTranslateInstance(x, y)); - node.setTransform(at); - - // 'overflow' and 'clip' - Shape clip = null; - if (CSSUtilities.convertOverflow(e)) { // overflow:hidden - float [] offsets = CSSUtilities.convertClip(e); - if (offsets == null) { // clip:auto - clip = new Rectangle2D.Float(x, y, w, h); - } else { // clip:rect(<x> <y> <w> <h>) - // offsets[0] = top - // offsets[1] = right - // offsets[2] = bottom - // offsets[3] = left - clip = new Rectangle2D.Float(x+offsets[3], - y+offsets[0], - w-offsets[1]-offsets[3], - h-offsets[2]-offsets[0]); - } - } - - if (clip != null) { - try { - at = at.createInverse(); // clip in user space - Filter filter = node.getGraphicsNodeRable(true); - clip = at.createTransformedShape(clip); - node.setClip(new ClipRable8Bit(filter, clip)); - } catch (java.awt.geom.NoninvertibleTransformException ex) {} - } } }
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]